diff --git a/.gitignore b/.gitignore index 6ed8833731da9..c5c101a3e69cd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ .* *.o *.o.* -*.a *.s *.ko *.so @@ -46,7 +45,7 @@ Module.symvers /vmlinuz /System.map /Module.markers - +/si # # Debian directory (make deb-pkg) # diff --git a/Makefile b/Makefile index abe6133d204e8..60ed96ce061ca 100644 --- a/Makefile +++ b/Makefile @@ -807,6 +807,11 @@ KBUILD_CPPFLAGS += $(KCPPFLAGS) KBUILD_AFLAGS += $(KAFLAGS) KBUILD_CFLAGS += $(KCFLAGS) +# Add macro for factory version +ifeq ($(strip $(FACTORY_VERSION_MODE)), true) + KBUILD_CFLAGS += -DFACTORY_VERSION_ENABLE +endif + # Use --build-id when available. LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ $(call cc-ldoption, -Wl$(comma)--build-id,)) diff --git a/android_dm_verity_release.x509 b/android_dm_verity_release.x509 new file mode 100644 index 0000000000000..74ced635946f3 Binary files /dev/null and b/android_dm_verity_release.x509 differ diff --git a/android_dm_verity_test.x509 b/android_dm_verity_test.x509 new file mode 100644 index 0000000000000..3bbfded787335 Binary files /dev/null and b/android_dm_verity_test.x509 differ diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 20ece7118a60f..508c3f2ad9764 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -1,124 +1,3 @@ -dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-mtp.dtb \ - msm8996-v2-pmi8994-pmk8001-mtp.dtb \ - msm8996-v2-pmi8994-pm8004-mtp.dtb \ - msm8996-v2-pmi8994-pm8004-pmk8001-mtp.dtb \ - msm8996-v2-fluid.dtb \ - msm8996-v2-liquid.dtb \ - msm8996-v2-dtp.dtb \ - msm8996-v3-auto-cdp.dtb \ - msm8996-v3-auto-adp.dtb \ - msm8996-v3-pmi8994-cdp.dtb \ - msm8996-v3-pmi8994-mtp.dtb \ - msm8996-v3-pmi8994-pmk8001-cdp.dtb \ - msm8996-v3-pmi8994-pmk8001-mtp.dtb \ - msm8996-v3-pmi8994-pm8004-cdp.dtb \ - msm8996-v3-pmi8994-pm8004-mtp.dtb \ - msm8996-v3-pmi8994-pm8004-pmk8001-cdp.dtb \ - msm8996-v3-pmi8994-pm8004-pmk8001-mtp.dtb \ - msm8996-v3-pmi8996-cdp.dtb \ - msm8996-v3-pmi8996-mtp.dtb \ - msm8996-v3-pmi8996-pmk8001-cdp.dtb \ - msm8996-v3-pmi8996-pmk8001-mtp.dtb \ - msm8996-v3-fluid.dtb \ - msm8996-v3-liquid.dtb \ - msm8996-v3-dtp.dtb \ - msm8996-v3-pm8004-mmxf-adp.dtb \ - msm8996-v3-pm8004-agave-adp.dtb \ - msm8996-v3-pm8004-agave-adp-lite.dtb \ - msm8996pro-auto-adp.dtb \ - msm8996pro-auto-adp-lite.dtb \ - msm8996pro-auto-cdp.dtb \ - msm8996pro-pmi8994-cdp.dtb \ - msm8996pro-pmi8994-mtp.dtb \ - msm8996pro-pmi8994-pmk8001-cdp.dtb \ - msm8996pro-pmi8994-pmk8001-mtp.dtb \ - msm8996pro-pmi8994-pm8004-cdp.dtb \ - msm8996pro-pmi8994-pm8004-mtp.dtb \ - msm8996pro-pmi8994-pm8004-pmk8001-cdp.dtb \ - msm8996pro-pmi8994-pm8004-pmk8001-mtp.dtb \ - msm8996pro-pmi8996-cdp.dtb \ - msm8996pro-pmi8996-mtp.dtb \ - msm8996pro-pmi8996-pmk8001-cdp.dtb \ - msm8996pro-pmi8996-pmk8001-mtp.dtb \ - msm8996pro-v1.1-auto-cdp.dtb \ - msm8996pro-v1.1-pmi8994-cdp.dtb \ - msm8996pro-v1.1-pmi8994-mtp.dtb \ - msm8996pro-v1.1-pmi8994-pmk8001-cdp.dtb \ - msm8996pro-v1.1-pmi8994-pmk8001-mtp.dtb \ - msm8996pro-v1.1-pmi8994-pm8004-cdp.dtb \ - msm8996pro-v1.1-pmi8994-pm8004-mtp.dtb \ - msm8996pro-v1.1-pmi8994-pm8004-pmk8001-cdp.dtb \ - msm8996pro-v1.1-pmi8994-pm8004-pmk8001-mtp.dtb \ - msm8996pro-v1.1-pmi8996-cdp.dtb \ - msm8996pro-v1.1-pmi8996-mtp.dtb \ - msm8996pro-v1.1-pmi8996-pmk8001-cdp.dtb \ - msm8996pro-v1.1-pmi8996-pmk8001-mtp.dtb \ - apq8096pro-auto-cdp.dtb \ - apq8096pro-v1.1-auto-adp.dtb \ - apq8096pro-v1.1-auto-adp-lite.dtb \ - apq8096pro-liquid.dtb \ - apq8096pro-v1.1-auto-cdp.dtb \ - apq8096pro-v1.1-pmi8994-cdp.dtb \ - apq8096pro-v1.1-pmi8994-mtp.dtb \ - apq8096pro-v1.1-pmi8994-pmk8001-cdp.dtb \ - apq8096pro-v1.1-pmi8994-pmk8001-mtp.dtb \ - apq8096pro-v1.1-pmi8994-pm8004-cdp.dtb \ - apq8096pro-v1.1-pmi8994-pm8004-mtp.dtb \ - apq8096pro-v1.1-pmi8994-pm8004-pmk8001-cdp.dtb \ - apq8096pro-v1.1-pmi8994-pm8004-pmk8001-mtp.dtb \ - apq8096pro-v1.1-pmi8996-cdp.dtb \ - apq8096pro-v1.1-pmi8996-mtp.dtb \ - apq8096pro-v1.1-pmi8996-pmk8001-cdp.dtb \ - apq8096pro-v1.1-pmi8996-pmk8001-mtp.dtb \ - msm8996-v3.0-pmi8994-cdp.dtb \ - msm8996-v3.0-pmi8994-mtp.dtb \ - msm8996-v3.0-pmi8994-pm8004-cdp.dtb \ - msm8996-v3.0-pmi8994-pm8004-mtp.dtb \ - msm8996-v3.0-pmi8994-pm8004-pmk8001-cdp.dtb \ - msm8996-v3.0-pmi8994-pmk8001-cdp.dtb \ - msm8996-v3.0-pmi8996-cdp.dtb \ - msm8996-v3.0-pmi8996-mtp.dtb \ - msm8996-v3.0-fluid.dtb \ - msm8996-v3.0-liquid.dtb \ - msm8996-v3.0-dtp.dtb \ - apq8096-v2-pmi8994-mtp.dtb \ - apq8096-v2-liquid.dtb \ - apq8096-v2-dragonboard.dtb \ - apq8096-v2-auto-dragonboard.dtb \ - apq8096-v3-pmi8994-cdp.dtb \ - apq8096-v3-pmi8994-mtp.dtb \ - apq8096-v3-pmi8994-pmk8001-cdp.dtb \ - apq8096-v3-pmi8994-pm8004-cdp.dtb \ - apq8096-v3-pmi8994-pm8004-pmk8001-cdp.dtb \ - apq8096-v3-pmi8996-cdp.dtb \ - apq8096-v3-pmi8996-mtp.dtb \ - apq8096-v3-liquid.dtb \ - apq8096-v3-dragonboard.dtb \ - apq8096-v3-mediabox.dtb \ - apq8096-v3-sbc.dtb \ - apq8096-v3-auto-dragonboard.dtb \ - apq8096-v3-auto-adp.dtb \ - apq8096-v3-auto-cdp.dtb \ - apq8096-v3-drone.dtb \ - apq8096-v3.0-pmi8994-cdp.dtb \ - apq8096-v3.0-pmi8994-mtp.dtb \ - apq8096-v3.0-pmi8994-pm8004-cdp.dtb \ - apq8096-v3.0-pmi8994-pm8004-pmk8001-cdp.dtb \ - apq8096-v3.0-pmi8994-pmk8001-cdp.dtb \ - apq8096-v3.0-pmi8996-cdp.dtb \ - apq8096-v3.0-pmi8996-mtp.dtb \ - apq8096-v3.0-liquid.dtb \ - apq8096-v3.0-dragonboard.dtb \ - apq8096-v3-pmi8994-mdm9x55-i2s-cdp.dtb \ - apq8096-v3-pmi8994-pm8004-mdm9x55-i2s-cdp.dtb \ - apq8096-v3-pmi8994-pm8004-pmk8001-mdm9x55-i2s-cdp.dtb \ - apq8096-v3-pmi8994-pmk8001-mdm9x55-i2s-cdp.dtb \ - apq8096-v3-pmi8996-mdm9x55-i2s-cdp.dtb \ - apq8096-v3-pmi8994-mdm9x55-i2s-mtp.dtb \ - apq8096-v3-pmi8994-mdm9x55-slimbus-mtp.dtb \ - apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dtb \ - apq8096-v3-pmi8996-mdm9x55-slimbus-mtp.dtb \ - apq8096-v3-pmi8996-dragonboard.dtb dtb-$(CONFIG_MSM_GVM_QUIN) += vplatform-lfv-msm8996.dtb @@ -131,48 +10,6 @@ dtb-$(CONFIG_ARCH_MSMCOBALT) += msmcobalt-sim.dtb \ msmcobalt-v2-mtp.dtb \ msmcobalt-v2-cdp.dtb -dtb-$(CONFIG_ARCH_MDM9640) += mdm9640-sim.dtb \ - mdm9640-rumi.dtb \ - mdm9640-emmc-cdp.dtb \ - mdm9640-nand-cdp.dtb \ - mdm9640-mtp.dtb \ - mdm9640-v1-mtp.dtb \ - mdm9640-v1-pmk8001-mtp.dtb \ - mdm9640-v2-mtp.dtb \ - mdm9640-v2-pmk8001-mtp.dtb \ - - -dtb-$(CONFIG_ARCH_MDM9650) += mdm9650-ttp.dtb \ - mdm9650-pcie-ep-ttp.dtb \ - mdm9650-v1.1-emmc-cdp.dtb \ - mdm9650-v1.1-nand-cdp.dtb \ - mdm9650-v1.1-emmc-mtp.dtb \ - mdm9650-v1.1-nand-mtp.dtb \ - mdm9650-v1.1-nand-dualwifi-mtp.dtb \ - mdm9650-v1.1-nand-ccard-v2.dtb \ - mdm9650-v1.1-emmc-pcie-ep-mtp.dtb \ - mdm9650-v1.1-nand-pcie-ep-mtp.dtb \ - mdm9650-v1.1-nand-cv2x.dtb \ - mdm9650-v1.1-nand-rome-sdio-mtp.dtb - -dtb-$(CONFIG_ARCH_SDX20) += sdx20-emmc-cdp.dtb \ - sdx20-emmc-mtp.dtb \ - sdx20-nand-cdp.dtb \ - sdx20-nand-mtp.dtb \ - sdx20-nand-dualwifi-mtp.dtb \ - sdx20-nand-dualwifi-cdp.dtb \ - sdx20-v2-emmc-cdp.dtb \ - sdx20-v2-emmc-mtp.dtb \ - sdx20-v2-nand-cdp.dtb \ - sdx20-v2-nand-mtp.dtb \ - sdx20-v2-nand-dualwifi-mtp.dtb \ - sdx20-v2-nand-dualwifi-cdp.dtb \ - sdx20-v2-nand-singlewifi-dualwificonf-mtp.dtb \ - sdx20-emmc-pcie-ep-mtp.dtb \ - sdx20-nand-pcie-ep-mtp.dtb \ - sdx20-v2-emmc-pcie-ep-mtp.dtb \ - sdx20-v2-nand-pcie-ep-mtp.dtb - dtb-$(CONFIG_ARCH_MSM8937) += msm8937-rumi.dtb \ msm8937-pmi8950-cdp.dtb \ msm8937-pmi8937-cdp.dtb \ @@ -215,28 +52,6 @@ dtb-$(CONFIG_ARCH_MSM8917) += msm8917-rumi.dtb \ apq8017-pmi8950-cdp-wcd-rome.dtb \ apq8017-no-pmi-wcd-rome-cdp.dtb -dtb-$(CONFIG_ARCH_MSM8920) += msm8920-pmi8937-cdp.dtb \ - msm8920-pmi8937-mtp.dtb \ - msm8920-pmi8950-cdp.dtb \ - msm8920-pmi8950-mtp.dtb \ - msm8920-pmi8937-rcm.dtb \ - msm8920-pmi8950-rcm.dtb \ - msm8920-pmi8940-qrd-sku7.dtb \ - msm8920-pmi8950-ext-codec-cdp.dtb - -dtb-$(CONFIG_ARCH_MSM8940) += msm8940-pmi8937-cdp.dtb \ - msm8940-pmi8937-mtp.dtb \ - msm8940-pmi8950-cdp.dtb \ - msm8940-pmi8950-mtp.dtb \ - msm8940-pmi8937-rcm.dtb \ - msm8940-pmi8950-rcm.dtb \ - msm8940-pmi8950-qrd-sku6.dtb \ - msm8940-pmi8950-qrd-sku7.dtb \ - msm8940-pmi8950-ext-codec-cdp.dtb \ - msm8940-pmi8940-mtp.dtb \ - msm8940-pmi8940-cdp.dtb \ - msm8940-pmi8940-rcm.dtb \ - msm8940-pmi8940-qrd-sku7.dtb dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-rumi.dtb \ @@ -244,21 +59,13 @@ dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-mtp.dtb \ msm8953-ext-codec-mtp.dtb \ msm8953-qrd-sku3.dtb \ + msm8953-qrd-sku3-e7.dtb \ + msm8953-qrd-sku3-daisy.dtb \ msm8953-rcm.dtb \ - apq8053-rcm.dtb \ msm8953-ext-codec-rcm.dtb \ - apq8053-cdp.dtb \ - apq8053-ipc.dtb \ msm8953-ipc.dtb \ - apq8053-mtp.dtb \ - apq8053-ext-audio-mtp.dtb \ - apq8053-ext-codec-rcm.dtb \ - apq8053-lite-dragon-v1.0.dtb \ - apq8053-lite-dragon-v2.0.dtb \ - apq8053-lite-ext-codec-dragon-v2.0.dtb \ msm8953-cdp-1200p.dtb \ msm8953-iot-mtp.dtb \ - apq8053-iot-mtp.dtb \ msm8953-pmi8940-cdp.dtb \ msm8953-pmi8940-mtp.dtb \ msm8953-pmi8937-cdp.dtb \ @@ -266,79 +73,6 @@ dtb-$(CONFIG_ARCH_MSM8953) += msm8953-sim.dtb \ msm8953-pmi8940-ext-codec-mtp.dtb \ msm8953-pmi8937-ext-codec-mtp.dtb -dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \ - sdm450-cdp.dtb \ - sdm450-mtp.dtb \ - sdm450-qrd.dtb \ - sdm450-pmi8940-mtp.dtb \ - sdm450-pmi8937-mtp.dtb \ - sdm450-iot-mtp.dtb \ - sda450-cdp.dtb \ - sda450-mtp.dtb - -dtb-$(CONFIG_ARCH_MDM9607) += mdm9607-rumi.dtb \ - mdm9607-cdp.dtb \ - mdm9607-mtp.dtb \ - mdm9607-rcm.dtb \ - mdm9607-mtp-sdcard.dtb \ - mdm9607-ttp.dtb \ - mdm9206-mtp.dtb \ - mdm9206-cdp.dtb \ - mdm9206-mtp-sdcard.dtb \ - mdm9206-rcm.dtb - -dtb-$(CONFIG_ARCH_MSM8916) += msm8952-qrd-skum.dtb \ - msm8952-cdp.dtb \ - msm8952-ext-codec-cdp.dtb \ - msm8952-mtp.dtb - -dtb-$(CONFIG_ARCH_MSM8909) += msm8909-pm8916-mtp.dtb \ - msm8909-cdp.dtb \ - msm8909-1gb-qrd-skuc.dtb \ - msm8909-1gb-qrd-skue.dtb \ - msm8909-qrd-skue.dtb \ - sdw2100-msm8909w-wtp.dtb \ - sdw2100-apq8009w-wtp.dtb \ - apq8009w-cdp.dtb \ - sdw2100-msm8909w-swoctp.dtb \ - msm8909w-swoctp-circpanel.dtb \ - apq8009w-swoctp-circpanel.dtb \ - apq8009w-nowgr-swoctp.dtb \ - sdw2100-apq8009w-nowgr-swoctp-circpanel.dtb \ - msm8909-pm8916-cdp.dtb \ - msm8909w-cdp.dtb \ - sdw2100-msm8909w-1gb-swoctp-circpanel.dtb \ - sdw3100-msm8909w-wtp.dtb \ - sdw2500-msm8909w-wtp.dtb \ - sdw3100-apq8009w-wtp.dtb \ - sdw3100-apq8009w-alpha.dtb \ - sdw2500-apq8009w-wtp.dtb \ - apq8009-mtp-wcd9326.dtb \ - msm8909-mtp-wcd9326.dtb \ - msm8909-mtp-wcd9326-refboard.dtb \ - msm8909-512mb-mtp-wcd9326-refboard.dtb \ - msm8909-512mb-cdp-wcd9326-refboard.dtb \ - msm8909-512mb-rcm-wcd9326-refboard.dtb \ - msm8909-cdp-wcd9326-refboard.dtb \ - msm8909-rcm-wcd9326-refboard.dtb \ - apq8009-mtp-wcd9326-refboard.dtb \ - apq8009-512mb-mtp-wcd9326-refboard.dtb \ - apq8009-512mb-cdp-wcd9326-refboard.dtb \ - apq8009-512mb-rcm-wcd9326-refboard.dtb \ - apq8009-cdp-wcd9326-refboard.dtb \ - apq8009-rcm-wcd9326-refboard.dtb \ - apq8009-robot-refboard.dtb \ - apq8009-robot-som-refboard.dtb \ - apq8009-robot-rome.dtb \ - apq8009-mtp-drone.dtb \ - apq8009-mtp-wcd9326-excelpoint-refboard.dtb \ - msm8909-mtp.dtb \ - msm8909-1gb-mtp.dtb \ - msm8909-1gb-rcm.dtb \ - msm8909-pm8916-1gb-rcm.dtb \ - msm8909-1gb-cdp.dtb \ - apq8009-ext-codec-dragon.dtb \ - apq8009-dragon.dtb ifeq ($(CONFIG_ARM64),y) always := $(dtb-y) diff --git a/arch/arm/boot/dts/qcom/Sakura-Default-4000mah-41kohm.dtsi b/arch/arm/boot/dts/qcom/Sakura-Default-4000mah-41kohm.dtsi new file mode 100644 index 0000000000000..fff510cab3d21 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Sakura-Default-4000mah-41kohm.dtsi @@ -0,0 +1,50 @@ + +qcom,3299637_huaqin_bn47atl_4000mah_averaged_masterslave_7thMay2018 { + /* #3299637_Huaqin_BN47atl_4000mAh_averaged_MasterSlave_Feb9th2018*/ + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <200>; + qcom,battery-beta = <3380>; + qcom,battery-type = "Default"; + qcom,chg-rslow-comp-c1 = <3424410>; + qcom,chg-rslow-comp-c2 = <5067152>; + qcom,chg-rs-to-rslow = <892701>; + qcom,chg-rslow-comp-thr = <0xA9>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,checksum = <0x4D97>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + F8 83 55 7D + 40 81 2A 77 + 3E 83 7E 72 + 66 7E 82 7B + EB 81 EC 9B + 81 BF D8 D0 + 81 10 ED 83 + C7 7C FE 80 + 07 77 30 83 + 2D 7A 47 8C + B5 88 22 82 + 9F 9B 2A C4 + 4F D2 67 0E + 63 0F B8 59 + 14 70 EE FC + BD 44 7F 44 + FA 43 00 00 + 20 4C C8 38 + 3F 39 00 00 + 00 00 00 00 + 00 00 00 00 + 1A 70 1F 6A + 55 70 84 8B + 42 77 E0 70 + 7D 6D 92 78 + A5 6F 68 68 + 90 3E 05 A1 + 2C C8 62 91 + 64 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/Sakura-FMT-4v4-4000mah-41kohm.dtsi b/arch/arm/boot/dts/qcom/Sakura-FMT-4v4-4000mah-41kohm.dtsi new file mode 100644 index 0000000000000..400a2c9d79c22 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Sakura-FMT-4v4-4000mah-41kohm.dtsi @@ -0,0 +1,50 @@ + +qcom,3299637_huaqin_bn47atl_4000mah_averaged_masterslave_feb9th2018 { + /* #3299637_Huaqin_BN47atl_4000mAh_averaged_MasterSlave_Feb9th2018*/ + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <41>; + qcom,battery-beta = <3380>; + qcom,battery-type = "FMT-4000mah-41kohm"; + qcom,chg-rslow-comp-c1 = <3424410>; + qcom,chg-rslow-comp-c2 = <5067152>; + qcom,chg-rs-to-rslow = <892701>; + qcom,chg-rslow-comp-thr = <0xA9>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,checksum = <0x4D97>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + F8 83 55 7D + 40 81 2A 77 + 3E 83 7E 72 + 66 7E 82 7B + EB 81 EC 9B + 81 BF D8 D0 + 81 10 ED 83 + C7 7C FE 80 + 07 77 30 83 + 2D 7A 47 8C + B5 88 22 82 + 9F 9B 2A C4 + 4F D2 67 0E + 63 0F B8 59 + 14 70 EE FC + BD 44 7F 44 + FA 43 00 00 + 20 4C C8 38 + 3F 39 00 00 + 00 00 00 00 + 00 00 00 00 + 1A 70 1F 6A + 55 70 84 8B + 42 77 E0 70 + 7D 6D 92 78 + A5 6F 68 68 + 90 3E 05 A1 + 2C C8 62 91 + 64 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/Sakura-GY-4000mah-51kohm.dtsi b/arch/arm/boot/dts/qcom/Sakura-GY-4000mah-51kohm.dtsi new file mode 100644 index 0000000000000..13b2773390862 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Sakura-GY-4000mah-51kohm.dtsi @@ -0,0 +1,50 @@ + +qcom,3299735_huaqin_d1scos_4000mah_averaged_masterslave_feb20th2018 { + /* #3299735_Huaqin_D1Scos_4000mAh_averaged_MasterSlave_Feb20th2018*/ + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <51>; + qcom,battery-beta = <3380>; + qcom,battery-type = "GY-4000mah-51kohm"; + qcom,chg-rslow-comp-c1 = <3910349>; + qcom,chg-rslow-comp-c2 = <7207770>; + qcom,chg-rs-to-rslow = <881635>; + qcom,chg-rslow-comp-thr = <0xBA>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,checksum = <0xDA4C>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + D0 83 F4 77 + 3A 80 29 75 + 3C 83 4C 73 + 1E 84 CC 80 + F6 81 A3 9B + 36 BF A6 D0 + 75 10 FB 83 + 4C 7D 45 81 + 56 77 31 83 + 0F 7A 28 8C + 81 88 23 82 + 9A 9B 28 C4 + 4D D2 6B 0E + 8D 0F 80 59 + 14 70 EE FC + 4E 45 BA 3F + A6 43 00 00 + 41 4C C7 40 + FD 16 00 00 + 00 00 00 00 + 00 00 00 00 + 36 70 58 6A + 91 60 EF 89 + 13 7C 72 71 + F9 6D 86 78 + DC 74 0A 6A + A1 6C 3F A1 + 2D C7 60 F3 + 5E A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/Sakura-XWD-4000mah-78kohm.dtsi b/arch/arm/boot/dts/qcom/Sakura-XWD-4000mah-78kohm.dtsi new file mode 100644 index 0000000000000..50d6e2be570e6 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Sakura-XWD-4000mah-78kohm.dtsi @@ -0,0 +1,50 @@ + +qcom,3464413_huaqin_d1ssun_4000mah_averaged_masterslave_may31st2018 { + /* #3464413_Huaqin_D1Ssun_4000mAh_averaged_MasterSlave_May31st2018*/ + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <78>; + qcom,battery-beta = <3380>; + qcom,battery-type = "XWD-4000mah-78kohm"; + qcom,chg-rslow-comp-c1 = <4038035>; + qcom,chg-rslow-comp-c2 = <7085423>; + qcom,chg-rs-to-rslow = <940608>; + qcom,chg-rslow-comp-thr = <0xB7>; + qcom,fg-cc-cv-threshold-mv = <4390>; + qcom,checksum = <0xDC28>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + BC 83 91 76 + 7B 7B 4B 74 + 36 83 22 78 + 0C 85 DF 81 + ED 81 1D A0 + 21 C4 AA D1 + 6C 0F 18 88 + FA 7E 66 82 + A6 7C 38 83 + 34 79 6F 86 + B1 82 26 82 + B0 9B 3B C4 + 6B D2 79 0E + 99 0F BD 59 + 14 70 EE FC + 5C 22 99 45 + 27 38 00 00 + 82 46 F0 41 + C5 3E 00 00 + 00 00 00 00 + 00 00 00 00 + CF 70 80 6A + 0B 84 CD 88 + 58 7D 4C 73 + DA 74 2B 73 + 25 76 7F 6B + 65 4B B3 A2 + 35 76 61 4C + 5F A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/Vince-coslight-50Kohm-4000mah.dtsi b/arch/arm/boot/dts/qcom/Vince-coslight-50Kohm-4000mah.dtsi new file mode 100755 index 0000000000000..e86cc6204c7ae --- /dev/null +++ b/arch/arm/boot/dts/qcom/Vince-coslight-50Kohm-4000mah.dtsi @@ -0,0 +1,49 @@ + +qcom,3005023_huaqin_e7cos_4000mah_averaged_masterslave_jul10th2017 { + /* #3005023_Huaqin_E7cos_4000mAh_averaged_MasterSlave_Jul10th2017*/ + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <50>; + qcom,battery-beta = <3435>; + qcom,battery-type = "Vince_coslight_50Kohm_4000mah"; + qcom,chg-rslow-comp-c1 = <2912209>; + qcom,chg-rslow-comp-c2 = <3933866>; + qcom,chg-rs-to-rslow = <758663>; + qcom,chg-rslow-comp-thr = <0xA0>; + qcom,checksum = <0xBFCD>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + ED 83 4A 7D + 73 81 EF 77 + 57 83 7C 44 + E0 80 0E 8C + 21 82 F5 99 + D6 BC 4F C9 + 5A 0F FA 83 + 58 7D 65 81 + AF 77 57 83 + 88 61 4C 81 + D6 8D 76 82 + 15 98 FD B5 + EA C1 52 13 + AC 0F 4A 59 + 14 70 EE FC + BF 44 F4 3C + 56 3A 00 00 + D9 44 8F 39 + 55 3E 00 00 + 00 00 00 00 + 00 00 00 00 + A7 6A B9 69 + B4 6B 37 83 + C7 6E AB 62 + 1D 70 67 81 + F6 6C 71 60 + 16 7D 3E 92 + 1B 51 60 6E + 5D A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/Vince-desay-24Kohm-4000mAh.dtsi b/arch/arm/boot/dts/qcom/Vince-desay-24Kohm-4000mAh.dtsi new file mode 100644 index 0000000000000..b0107e410d892 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Vince-desay-24Kohm-4000mAh.dtsi @@ -0,0 +1,49 @@ + +qcom,3199087_huaqin_e7desay_4000mah_averaged_masterslave_dec4th2017 { + /* #3199087_Huaqin_E7desay_4000mAh_averaged_MasterSlave_Dec4th2017*/ + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <24>; + qcom,battery-beta = <3380>; + qcom,battery-type = "Vince_desay_24Kohm_4000mah"; + qcom,chg-rslow-comp-c1 = <4132413>; + qcom,chg-rslow-comp-c2 = <7193808>; + qcom,chg-rs-to-rslow = <1059831>; + qcom,chg-rslow-comp-thr = <0xB7>; + qcom,checksum = <0x4B4D>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + A5 83 51 74 + 6F 79 3B 6C + 37 83 D1 73 + 70 84 1A 81 + EA 81 49 A0 + 75 C4 52 D2 + 6C 0F D0 83 + B9 76 4E 7B + 10 74 2F 83 + 61 7A 78 8C + EC 88 20 82 + 47 A0 3F C5 + 75 D8 63 0C + DC 0F C6 59 + 14 70 EE FC + 0E 20 34 45 + 77 39 00 00 + 46 47 EA 3B + FD 2E 00 00 + 00 00 00 00 + 00 00 00 00 + 60 71 DC 6A + 29 7C 0B 83 + 51 7D DF 72 + 3B 67 A7 78 + D6 75 DE 6A + 04 74 5A A3 + 2D 6E 60 A6 + 5D A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/Vince-sunwoda-40Kohm-4000mah.dtsi b/arch/arm/boot/dts/qcom/Vince-sunwoda-40Kohm-4000mah.dtsi new file mode 100755 index 0000000000000..466f8c35a8c96 --- /dev/null +++ b/arch/arm/boot/dts/qcom/Vince-sunwoda-40Kohm-4000mah.dtsi @@ -0,0 +1,49 @@ + +qcom,3005040_huaqin_e7sun_4000mah_averaged_masterslave_jul17th2017 { + /* #3005040_Huaqin_E7sun_4000mAh_averaged_MasterSlave_Jul17th2017*/ + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <40>; + qcom,battery-beta = <3380>; + qcom,battery-type = "Vince_sunwoda_40Kohm_4000mah"; + qcom,chg-rslow-comp-c1 = <3028448>; + qcom,chg-rslow-comp-c2 = <3651765>; + qcom,chg-rs-to-rslow = <853285>; + qcom,chg-rslow-comp-thr = <0x99>; + qcom,checksum = <0x94A0>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + D9 83 86 7C + E6 80 F9 76 + 5F 83 33 6E + B4 88 E5 8F + 2A 82 1C 9A + 4F BD 48 CA + 56 0E 37 83 + 31 68 76 70 + 9C 54 3F 83 + 7A 78 BC 84 + 48 80 7F 82 + 53 93 E8 B4 + 47 C0 77 10 + 7A 0F DD 59 + 14 70 EE FC + AC 3D 3B 45 + 1E 42 00 00 + D2 4C 92 3A + FE 42 00 00 + 00 00 00 00 + 00 00 00 00 + 71 6B B5 69 + 72 63 21 8A + 2F 76 34 6B + 5C 6C B4 79 + 40 6F 01 63 + BA 60 05 A2 + 23 F7 62 09 + 65 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi index 3e8c253440e58..c1379787c03db 100644 --- a/arch/arm/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi @@ -75,8 +75,8 @@ pinctrl-0 = <&cam_sensor_mclk0_default &cam_sensor_rear_default1 &cam_sensor_rear_vana1>; - pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep1 - &cam_sensor_rear_vana_sleep1>; + //pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep1 + // &cam_sensor_rear_vana_sleep1>; gpios = <&tlmm 26 0>, <&tlmm 40 0>, <&tlmm 46 0>, diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi index 7e06fea7f9cd2..c2c7a5e11b6e1 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi @@ -439,14 +439,14 @@ }; }; }; - +/* &pm8953_typec { ss-mux-supply = <&pm8953_l13>; qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&typec_ssmux_config>; }; - +*/ /{ mtp_batterydata: qcom,battery-data { qcom,batt-id-range-pct = <15>; diff --git a/arch/arm/boot/dts/qcom/batterydata-qrd-coslight-3000mAh.dtsi b/arch/arm/boot/dts/qcom/batterydata-qrd-coslight-3000mAh.dtsi new file mode 100755 index 0000000000000..d9774ab14fe0a --- /dev/null +++ b/arch/arm/boot/dts/qcom/batterydata-qrd-coslight-3000mAh.dtsi @@ -0,0 +1,49 @@ + +qcom,2760942_huaqin_d2cos_3080mah_averaged_masterslave_jan16th2017 { + /* #2760942_Huaqin_D2cos_3080mAh_averaged_MasterSlave_Jan16th2017*/ + qcom,max-voltage-uv = <4380000>; + qcom,nom-batt-capacity-mah = <3080>; + qcom,batt-id-kohm = <50>; + qcom,battery-beta = <3380>; + qcom,battery-type = "battey_qrd_coslight_3080mah"; + qcom,chg-rslow-comp-c1 = <3969816>; + qcom,chg-rslow-comp-c2 = <7140145>; + qcom,chg-rs-to-rslow = <997019>; + qcom,chg-rslow-comp-thr = <0xB8>; + qcom,checksum = <0x5DAD>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + E2 83 DF 7C + 10 81 12 77 + 65 83 51 74 + 74 89 94 94 + 33 82 B0 99 + A5 BC 1D C9 + 55 10 02 88 + 9A 7D 74 81 + 8D 77 4E 83 + CD 70 15 61 + CD 7E 4F 82 + 9D 99 DF BC + B5 C9 59 0C + 24 0C 15 59 + 14 70 B2 FD + A4 3F 23 3D + 6E 33 00 00 + 35 46 01 38 + FE 12 00 00 + 00 00 00 00 + 00 00 00 00 + 97 6B B4 6A + EF 60 0B 81 + 92 6E 72 60 + 3E 59 C0 79 + 5B 6D 56 5B + 18 7F 64 9A + 18 E9 61 55 + 5F A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/batterydata-qrd-sunwoda-ATL-4v4-4000mah.dtsi b/arch/arm/boot/dts/qcom/batterydata-qrd-sunwoda-ATL-4v4-4000mah.dtsi new file mode 100755 index 0000000000000..ba7c27f693634 --- /dev/null +++ b/arch/arm/boot/dts/qcom/batterydata-qrd-sunwoda-ATL-4v4-4000mah.dtsi @@ -0,0 +1,49 @@ + +qcom,3005040_huaqin_e7sun_4000mah_averaged_masterslave_jul17th2017 { + /* #3005040_Huaqin_E7sun_4000mAh_averaged_MasterSlave_Jul17th2017*/ + qcom,max-voltage-uv = <4400000>; + qcom,nom-batt-capacity-mah = <4000>; + qcom,batt-id-kohm = <40>; + qcom,battery-beta = <3380>; + qcom,battery-type = "qrd_msm8953_sunwoda_atl_4000mah"; + qcom,chg-rslow-comp-c1 = <3028448>; + qcom,chg-rslow-comp-c2 = <3651765>; + qcom,chg-rs-to-rslow = <853285>; + qcom,chg-rslow-comp-thr = <0x99>; + qcom,checksum = <0x94A0>; + qcom,gui-version = "PMI8950GUI - 2.0.0.16"; + qcom,fg-profile-data = [ + D9 83 86 7C + E6 80 F9 76 + 5F 83 33 6E + B4 88 E5 8F + 2A 82 1C 9A + 4F BD 48 CA + 56 0E 37 83 + 31 68 76 70 + 9C 54 3F 83 + 7A 78 BC 84 + 48 80 7F 82 + 53 93 E8 B4 + 47 C0 77 10 + 7A 0F DD 59 + 14 70 EE FC + AC 3D 3B 45 + 1E 42 00 00 + D2 4C 92 3A + FE 42 00 00 + 00 00 00 00 + 00 00 00 00 + 71 6B B5 69 + 72 63 21 8A + 2F 76 34 6B + 5C 6C B4 79 + 40 6F 01 63 + BA 60 05 A2 + 23 F7 62 09 + 65 A0 71 0C + 28 00 FF 36 + F0 11 30 03 + 00 00 00 0C + ]; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-hx8399c-fhdplus-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-hx8399c-fhdplus-video.dtsi new file mode 100644 index 0000000000000..135bbfd0815b2 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-hx8399c-fhdplus-video.dtsi @@ -0,0 +1,114 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_hx8399c_fhdplus_vid: qcom,mdss_dsi_hx8399c_fhdplus_video { + qcom,mdss-dsi-panel-name = "hx8399c fhdplus video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2280>; + qcom,mdss-dsi-h-front-porch = <24>; + qcom,mdss-dsi-h-back-porch = <40>; + qcom,mdss-dsi-h-pulse-width = <40>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <3>; + qcom,mdss-dsi-v-front-porch = <9>; + qcom,mdss-dsi-v-pulse-width = <4>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-brightness-max-level = <4095>; + qcom,mdss-brightness-max-level-global = <255>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 50>; + qcom,mdss-dsi-lp11-init; + qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 09 + 06 01 00 01 05 00 01 d9 + ]; + qcom,mdss-dsi-panel-status-read-length = <3 3>; + qcom,mdss-dsi-panel-status-valid-params = <3 3>; + qcom,mdss-dsi-panel-status-command-mode = "dsi_hs_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-value = <0x80 0x73 0x04 0x80 0x01 0x82>; + + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-on-command = [39 01 00 00 00 00 04 b9 ff 83 99 + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00 + 39 01 00 00 01 00 03 51 0F FF + 39 01 00 00 01 00 0A C9 03 00 16 1E 31 1E 00 91 00 + 39 01 00 00 05 00 02 55 01 + 39 01 00 00 01 00 02 53 2C + 39 01 00 00 01 00 0A CA 24 23 23 21 23 21 20 20 20 + 39 01 00 00 00 00 02 35 00]; + qcom,mdss-dsi-off-command = [39 01 00 00 32 00 02 28 00 + 39 01 00 00 78 00 02 10 00]; + + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-panel-timings = [29 40 2c 01 76 7a + 30 44 34 03 04 00]; + qcom,mdss-dsi-panel-timings-phy-v2 = [25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1e 08 0a 06 03 04 a0]; + qcom,mdss-dsi-t-clk-post = <0x0e>; + qcom,mdss-dsi-t-clk-pre = <0x34>; + qcom,mdss-dsi-CE_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_on-command = [ + 15 01 00 00 00 00 02 E4 00 + 39 01 00 00 00 00 20 E5 00 00 09 06 04 00 20 20 20 10 00 04 0B 18 01 12 FB 06 20 02 0C 03 05 02 0F 06 06 0E 17 02 01 + 39 01 00 00 00 00 12 E6 00 08 00 05 05 09 03 04 20 20 20 0C 08 0F 20 20 20 + 39 01 00 00 00 00 03 E4 00 40]; + qcom,mdss-dsi-CE_off-command = [ + 39 01 00 00 00 00 03 E4 00 00]; + qcom,mdss-dsi-CABC_on-command = [ + 39 01 00 00 01 00 03 51 0F FF + 39 01 00 00 01 00 0A C9 03 00 16 1E 31 1E 00 91 00 + 39 01 00 00 05 00 02 55 01 + 39 01 00 00 01 00 02 53 2C + 39 01 00 00 01 00 0A CA 24 23 23 21 23 21 20 20 20]; + qcom,mdss-dsi-CABC_off-command = [ + 39 01 00 00 05 00 02 55 01 + 39 01 00 00 01 00 0A CA 20 20 20 20 20 20 20 20 20]; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-ili7807-fhdplus-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-ili7807-fhdplus-video.dtsi new file mode 100644 index 0000000000000..69f1f4d3525f5 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-ili7807-fhdplus-video.dtsi @@ -0,0 +1,186 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_ili7807_fhdplus_vid: qcom,mdss_dsi_ili7807_fhdplus_video { + qcom,mdss-dsi-panel-name = "ili7807 fhdplus video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2280>; + qcom,mdss-dsi-h-front-porch = <72>; + qcom,mdss-dsi-h-back-porch = <64>; + qcom,mdss-dsi-h-pulse-width = <8>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <10>; + qcom,mdss-dsi-v-front-porch = <10>; + qcom,mdss-dsi-v-pulse-width = <8>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-brightness-max-level = <4095>; + qcom,mdss-brightness-max-level-global = <255>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 2>, <0 2>, <1 10>; + qcom,mdss-dsi-lp11-init; + qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A + 06 01 00 01 05 00 01 0B + 06 01 00 01 05 00 01 0D]; + qcom,mdss-dsi-panel-status-read-length = <1 1 1>; + qcom,mdss-dsi-panel-status-valid-params = <1 1 1>; + qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-value = <0x9C 0x00 0x00>; + + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 00 00 04 ff 78 07 00 + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 00 00 04 ff 78 07 07 + 39 01 00 00 00 00 02 12 22 + 39 01 00 00 00 00 02 31 0F + 39 01 00 00 00 00 02 44 07 + 39 01 00 00 00 00 04 FF 78 07 05 + 39 01 00 00 00 00 02 00 25 + 39 01 00 00 00 00 02 03 40 + 39 01 00 00 00 00 02 04 00 + 39 01 00 00 00 00 04 ff 78 07 00 + 39 01 00 00 00 00 03 51 0F FC + 39 01 00 00 00 00 02 53 2C + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00]; + + qcom,mdss-dsi-off-command = [ + 39 01 00 00 00 00 04 ff 78 07 00 + 39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00]; + + qcom,mdss-dsi-panel-timings = [29 40 2c 01 76 7a + 30 44 34 03 04 00]; + qcom,mdss-dsi-panel-timings-phy-v2 = [25 20 09 0c 06 03 04 a0 + 25 20 09 0c 06 03 04 a0 + 25 20 09 0c 06 03 04 a0 + 25 20 09 0c 06 03 04 a0 + 25 1e 09 0a 06 03 04 a0]; + qcom,mdss-dsi-t-clk-post = <0x0e>; + qcom,mdss-dsi-t-clk-pre = <0x35>; + + qcom,mdss-dsi-CE_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_hs_mode"; + + qcom,mdss-dsi-CE_on-command = [ + 29 01 00 00 00 00 04 ff 78 07 07 + 29 01 00 00 00 00 02 31 1F + 29 01 00 00 00 00 04 FF 78 07 05 + 29 00 00 00 00 00 02 30 06 + 29 00 00 00 00 00 02 31 10 + 29 00 00 00 00 00 02 38 07 + 29 00 00 00 00 00 02 39 09 + 29 00 00 00 00 00 02 3A 0C + 29 00 00 00 00 00 02 40 02 + 29 00 00 00 00 00 02 41 02 + 29 00 00 00 00 00 02 42 02 + 29 00 00 00 00 00 02 43 02 + 29 00 00 00 00 00 02 44 02 + 29 00 00 00 00 00 02 45 02 + 29 00 00 00 00 00 02 46 02 + 29 00 00 00 00 00 02 47 02 + 29 00 00 00 00 00 02 48 02 + 29 00 00 00 00 00 02 49 02 + 29 00 00 00 00 00 02 4A 02 + 29 00 00 00 00 00 02 4B 02 + 29 00 00 00 00 00 02 4C 02 + 29 00 00 00 00 00 02 4D 02 + 29 00 00 00 00 00 02 4E 02 + 29 00 00 00 00 00 02 4F 02 + 29 00 00 00 00 00 02 50 02 + 29 00 00 00 00 00 02 51 02 + 29 00 00 00 00 00 02 52 02 + 29 00 00 00 00 00 02 53 02 + 29 00 00 00 00 00 02 54 02 + 29 00 00 00 00 00 02 55 02 + 29 00 00 00 00 00 02 56 02 + 29 00 00 00 00 00 02 57 02 + 29 01 00 00 00 00 04 ff 78 07 07 + 29 01 00 00 00 00 02 31 0F + 29 01 00 00 00 00 04 FF 78 07 00]; + + qcom,mdss-dsi-CE_off-command = [ + 29 00 00 00 00 00 04 FF 78 07 07 + 29 00 00 00 00 00 02 3D 30 + 29 00 00 00 00 00 04 FF 78 07 05 + 29 01 00 00 00 00 02 31 00 + 29 00 00 00 00 00 04 FF 78 07 07 + 29 01 00 00 00 00 02 3d 00 + 29 01 00 00 00 00 04 FF 78 07 00]; + + qcom,mdss-dsi-CABC_on-command = [ + 29 01 00 00 00 00 04 FF 78 07 05 + 29 00 00 00 00 00 02 00 25 + 29 00 00 00 00 00 02 01 14 + 29 00 00 00 00 00 02 02 16 + 29 00 00 00 00 00 02 03 40 + 29 00 00 00 00 00 02 04 00 + 29 00 00 00 00 00 02 07 90 + 29 00 00 00 00 00 02 08 08 + 29 00 00 00 00 00 02 28 16 + 29 00 00 00 00 00 02 29 15 + 29 00 00 00 00 00 02 2A 14 + 29 00 00 00 00 00 02 2B 0D + 29 01 00 00 00 00 04 FF 78 07 00 + 29 00 00 00 00 00 03 51 0F FC + 29 00 00 00 00 00 02 53 2C + 29 00 00 00 00 00 02 55 01 + 29 00 00 00 00 00 03 68 05 00 + 29 01 00 00 00 00 04 FF 78 07 00 + ]; + + qcom,mdss-dsi-CABC_off-command = [ + 29 01 00 00 00 00 04 FF 78 07 00 + 29 00 00 00 00 00 03 51 0F FC + 29 00 00 00 00 00 02 53 2C + 29 00 00 00 00 00 02 55 00 + 29 01 00 00 00 00 04 FF 78 07 05 + 29 00 00 00 00 00 02 2B 08 + 29 01 00 00 00 00 04 FF 78 07 00 + ]; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt36672-csot-fhdplus-video_e7.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt36672-csot-fhdplus-video_e7.dtsi new file mode 100755 index 0000000000000..44c5d704c9878 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt36672-csot-fhdplus-video_e7.dtsi @@ -0,0 +1,2684 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_nt36672_csot_fhdplus_e7_vid: qcom,mdss_dsi_nt36672_csot_fhdplus_video_e7 { + qcom,mdss-dsi-panel-name = "nt36672 csot e7 fhdplus video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <108>; + qcom,mdss-dsi-h-back-porch = <62>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <8>; + qcom,mdss-dsi-v-front-porch = <10>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-white-command-00 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B2 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B3 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B4 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B5 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B6 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B7 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B8 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B9 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 BA 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D BB 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B2 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B3 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B4 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B5 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B6 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B7 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B8 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B9 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 BA 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D BB 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 01 00 00 00 00 11 B1 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 01 00 00 00 00 11 B2 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 01 00 00 00 00 0D B3 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 11 B4 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 01 00 00 00 00 11 B5 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 01 00 00 00 00 11 B6 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 01 00 00 00 00 0D B7 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 11 B8 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 01 00 00 00 00 11 B9 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 01 00 00 00 00 11 BA 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 01 00 00 00 00 0D BB 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 01 00 00 00 00 11 B1 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 01 00 00 00 00 11 B2 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 01 00 00 00 00 0D B3 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 11 B4 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 01 00 00 00 00 11 B5 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 01 00 00 00 00 11 B6 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 01 00 00 00 00 0D B7 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 11 B8 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 01 00 00 00 00 11 B9 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 01 00 00 00 00 11 BA 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 01 00 00 00 00 0D BB 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-01 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 C0 00 C6 00 D3 00 DE 00 E9 00 F3 00 FD 01 07 + 39 00 00 00 00 00 11 B1 01 10 01 30 01 4D 01 7D 01 A5 01 E5 02 1B 02 1D + 39 00 00 00 00 00 11 B2 02 56 02 99 02 C5 02 FA 03 1E 03 4C 03 58 03 66 + 39 00 00 00 00 00 0D B3 03 75 03 87 03 9C 03 B6 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 64 00 78 00 8A 00 9B + 39 00 00 00 00 00 11 B5 00 AA 00 DF 01 0B 01 4B 01 7D 01 CB 02 06 02 08 + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EF 03 10 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 DF 00 E4 00 EF 00 F9 01 03 01 0C 01 15 01 1D + 39 00 00 00 00 00 11 B9 01 25 01 42 01 5D 01 88 01 AD 01 EA 02 1E 02 20 + 39 00 00 00 00 00 11 BA 02 59 02 9C 02 C9 03 00 03 2B 03 66 03 7A 03 89 + 39 00 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 C0 00 C6 00 D3 00 DE 00 E9 00 F3 00 FD 01 07 + 39 00 00 00 00 00 11 B1 01 10 01 30 01 4D 01 7D 01 A5 01 E5 02 1B 02 1D + 39 00 00 00 00 00 11 B2 02 56 02 99 02 C5 02 FA 03 1E 03 4C 03 58 03 66 + 39 00 00 00 00 00 0D B3 03 75 03 87 03 9C 03 B6 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 64 00 78 00 8A 00 9B + 39 00 00 00 00 00 11 B5 00 AA 00 DF 01 0B 01 4B 01 7D 01 CB 02 06 02 08 + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EF 03 10 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 DF 00 E4 00 EF 00 F9 01 03 01 0C 01 15 01 1D + 39 00 00 00 00 00 11 B9 01 25 01 42 01 5D 01 88 01 AD 01 EA 02 1E 02 20 + 39 00 00 00 00 00 11 BA 02 59 02 9C 02 C9 03 00 03 2B 03 66 03 7A 03 89 + 39 00 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-01 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 C0 00 C6 00 D3 00 DE 00 E9 00 F3 00 FD 01 07 + 39 01 00 00 00 00 11 B1 01 10 01 30 01 4D 01 7D 01 A5 01 E5 02 1B 02 1D + 39 01 00 00 00 00 11 B2 02 56 02 99 02 C5 02 FA 03 1E 03 4C 03 58 03 66 + 39 01 00 00 00 00 0D B3 03 75 03 87 03 9C 03 B6 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 64 00 78 00 8A 00 9B + 39 01 00 00 00 00 11 B5 00 AA 00 DF 01 0B 01 4B 01 7D 01 CB 02 06 02 08 + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EF 03 10 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 DF 00 E4 00 EF 00 F9 01 03 01 0C 01 15 01 1D + 39 01 00 00 00 00 11 B9 01 25 01 42 01 5D 01 88 01 AD 01 EA 02 1E 02 20 + 39 01 00 00 00 00 11 BA 02 59 02 9C 02 C9 03 00 03 2B 03 66 03 7A 03 89 + 39 01 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 C0 00 C6 00 D3 00 DE 00 E9 00 F3 00 FD 01 07 + 39 01 00 00 00 00 11 B1 01 10 01 30 01 4D 01 7D 01 A5 01 E5 02 1B 02 1D + 39 01 00 00 00 00 11 B2 02 56 02 99 02 C5 02 FA 03 1E 03 4C 03 58 03 66 + 39 01 00 00 00 00 0D B3 03 75 03 87 03 9C 03 B6 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 64 00 78 00 8A 00 9B + 39 01 00 00 00 00 11 B5 00 AA 00 DF 01 0B 01 4B 01 7D 01 CB 02 06 02 08 + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EF 03 10 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 DF 00 E4 00 EF 00 F9 01 03 01 0C 01 15 01 1D + 39 01 00 00 00 00 11 B9 01 25 01 42 01 5D 01 88 01 AD 01 EA 02 1E 02 20 + 39 01 00 00 00 00 11 BA 02 59 02 9C 02 C9 03 00 03 2B 03 66 03 7A 03 89 + 39 01 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-02 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 39 00 46 00 5D 00 72 00 86 00 97 00 A8 00 B7 + 39 00 00 00 00 00 11 B1 00 C6 00 F8 01 20 01 5E 01 8E 01 D8 02 14 02 15 + 39 00 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B3 03 72 03 84 03 9A 03 B4 03 D1 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 1A 00 35 00 50 00 66 00 7A 00 8B 00 9D + 39 00 00 00 00 00 11 B5 00 AF 00 E3 01 11 01 50 01 82 01 D1 02 0D 02 0E + 39 00 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F1 03 11 03 44 03 51 03 5F + 39 00 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 81 00 8B 00 9C 00 AE 00 BD 00 CB 00 D7 00 E4 + 39 00 00 00 00 00 11 B9 00 F1 01 18 01 3C 01 70 01 9B 01 E1 02 19 02 1A + 39 00 00 00 00 00 11 BA 02 54 02 97 02 C4 02 FC 03 26 03 61 03 75 03 81 + 39 00 00 00 00 00 0D BB 03 84 03 86 03 97 03 AB 03 CE 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 39 00 46 00 5D 00 72 00 86 00 97 00 A8 00 B7 + 39 00 00 00 00 00 11 B1 00 C6 00 F8 01 20 01 5E 01 8E 01 D8 02 14 02 15 + 39 00 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B3 03 72 03 84 03 9A 03 B4 03 D1 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 1A 00 35 00 50 00 66 00 7A 00 8B 00 9D + 39 00 00 00 00 00 11 B5 00 AF 00 E3 01 11 01 50 01 82 01 D1 02 0D 02 0E + 39 00 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F1 03 11 03 44 03 51 03 5F + 39 00 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 81 00 8B 00 9C 00 AE 00 BD 00 CB 00 D7 00 E4 + 39 00 00 00 00 00 11 B9 00 F1 01 18 01 3C 01 70 01 9B 01 E1 02 19 02 1A + 39 00 00 00 00 00 11 BA 02 54 02 97 02 C4 02 FC 03 26 03 61 03 75 03 81 + 39 00 00 00 00 00 0D BB 03 84 03 86 03 97 03 AB 03 CE 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-02 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 39 00 46 00 5D 00 72 00 86 00 97 00 A8 00 B7 + 39 01 00 00 00 00 11 B1 00 C6 00 F8 01 20 01 5E 01 8E 01 D8 02 14 02 15 + 39 01 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 46 03 54 03 62 + 39 01 00 00 00 00 0D B3 03 72 03 84 03 9A 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 1A 00 35 00 50 00 66 00 7A 00 8B 00 9D + 39 01 00 00 00 00 11 B5 00 AF 00 E3 01 11 01 50 01 82 01 D1 02 0D 02 0E + 39 01 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F1 03 11 03 44 03 51 03 5F + 39 01 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 81 00 8B 00 9C 00 AE 00 BD 00 CB 00 D7 00 E4 + 39 01 00 00 00 00 11 B9 00 F1 01 18 01 3C 01 70 01 9B 01 E1 02 19 02 1A + 39 01 00 00 00 00 11 BA 02 54 02 97 02 C4 02 FC 03 26 03 61 03 75 03 81 + 39 01 00 00 00 00 0D BB 03 84 03 86 03 97 03 AB 03 CE 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 39 00 46 00 5D 00 72 00 86 00 97 00 A8 00 B7 + 39 01 00 00 00 00 11 B1 00 C6 00 F8 01 20 01 5E 01 8E 01 D8 02 14 02 15 + 39 01 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 46 03 54 03 62 + 39 01 00 00 00 00 0D B3 03 72 03 84 03 9A 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 1A 00 35 00 50 00 66 00 7A 00 8B 00 9D + 39 01 00 00 00 00 11 B5 00 AF 00 E3 01 11 01 50 01 82 01 D1 02 0D 02 0E + 39 01 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F1 03 11 03 44 03 51 03 5F + 39 01 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 81 00 8B 00 9C 00 AE 00 BD 00 CB 00 D7 00 E4 + 39 01 00 00 00 00 11 B9 00 F1 01 18 01 3C 01 70 01 9B 01 E1 02 19 02 1A + 39 01 00 00 00 00 11 BA 02 54 02 97 02 C4 02 FC 03 26 03 61 03 75 03 81 + 39 01 00 00 00 00 0D BB 03 84 03 86 03 97 03 AB 03 CE 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-03 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 50 00 66 00 79 00 8C 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 51 01 83 01 D0 02 0B 02 0E + 39 00 00 00 00 00 11 B2 02 49 02 8E 02 BB 02 F0 03 11 03 41 03 4D 03 61 + 39 00 00 00 00 00 0D B3 03 71 03 84 03 9A 03 B5 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 75 00 7F 00 91 00 A1 00 B1 00 BF 00 CC 00 D9 + 39 00 00 00 00 00 11 B5 00 E5 01 0E 01 30 01 68 01 94 01 DA 02 12 02 14 + 39 00 00 00 00 00 11 B6 02 4E 02 92 02 BE 02 F3 03 15 03 46 03 53 03 62 + 39 00 00 00 00 00 0D B7 03 72 03 84 03 9B 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1B 00 39 00 54 00 6C 00 81 00 95 00 A6 + 39 00 00 00 00 00 11 B9 00 B6 00 EC 01 16 01 57 01 88 01 D3 02 0D 02 10 + 39 00 00 00 00 00 11 BA 02 4A 02 90 02 BD 02 F4 03 1B 03 53 03 66 03 86 + 39 00 00 00 00 00 0D BB 03 9B 03 9D 03 9F 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 50 00 66 00 79 00 8C 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 51 01 83 01 D0 02 0B 02 0E + 39 00 00 00 00 00 11 B2 02 49 02 8E 02 BB 02 F0 03 11 03 41 03 4D 03 61 + 39 00 00 00 00 00 0D B3 03 71 03 84 03 9A 03 B5 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 75 00 7F 00 91 00 A1 00 B1 00 BF 00 CC 00 D9 + 39 00 00 00 00 00 11 B5 00 E5 01 0E 01 30 01 68 01 94 01 DA 02 12 02 14 + 39 00 00 00 00 00 11 B6 02 4E 02 92 02 BE 02 F3 03 15 03 46 03 53 03 62 + 39 00 00 00 00 00 0D B7 03 72 03 84 03 9B 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1B 00 39 00 54 00 6C 00 81 00 95 00 A6 + 39 00 00 00 00 00 11 B9 00 B6 00 EC 01 16 01 57 01 88 01 D3 02 0D 02 10 + 39 00 00 00 00 00 11 BA 02 4A 02 90 02 BD 02 F4 03 1B 03 53 03 66 03 86 + 39 00 00 00 00 00 0D BB 03 9B 03 9D 03 9F 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-03 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 50 00 66 00 79 00 8C 00 9D + 39 01 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 51 01 83 01 D0 02 0B 02 0E + 39 01 00 00 00 00 11 B2 02 49 02 8E 02 BB 02 F0 03 11 03 41 03 4D 03 61 + 39 01 00 00 00 00 0D B3 03 71 03 84 03 9A 03 B5 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 75 00 7F 00 91 00 A1 00 B1 00 BF 00 CC 00 D9 + 39 01 00 00 00 00 11 B5 00 E5 01 0E 01 30 01 68 01 94 01 DA 02 12 02 14 + 39 01 00 00 00 00 11 B6 02 4E 02 92 02 BE 02 F3 03 15 03 46 03 53 03 62 + 39 01 00 00 00 00 0D B7 03 72 03 84 03 9B 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1B 00 39 00 54 00 6C 00 81 00 95 00 A6 + 39 01 00 00 00 00 11 B9 00 B6 00 EC 01 16 01 57 01 88 01 D3 02 0D 02 10 + 39 01 00 00 00 00 11 BA 02 4A 02 90 02 BD 02 F4 03 1B 03 53 03 66 03 86 + 39 01 00 00 00 00 0D BB 03 9B 03 9D 03 9F 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 50 00 66 00 79 00 8C 00 9D + 39 01 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 51 01 83 01 D0 02 0B 02 0E + 39 01 00 00 00 00 11 B2 02 49 02 8E 02 BB 02 F0 03 11 03 41 03 4D 03 61 + 39 01 00 00 00 00 0D B3 03 71 03 84 03 9A 03 B5 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 75 00 7F 00 91 00 A1 00 B1 00 BF 00 CC 00 D9 + 39 01 00 00 00 00 11 B5 00 E5 01 0E 01 30 01 68 01 94 01 DA 02 12 02 14 + 39 01 00 00 00 00 11 B6 02 4E 02 92 02 BE 02 F3 03 15 03 46 03 53 03 62 + 39 01 00 00 00 00 0D B7 03 72 03 84 03 9B 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1B 00 39 00 54 00 6C 00 81 00 95 00 A6 + 39 01 00 00 00 00 11 B9 00 B6 00 EC 01 16 01 57 01 88 01 D3 02 0D 02 10 + 39 01 00 00 00 00 11 BA 02 4A 02 90 02 BD 02 F4 03 1B 03 53 03 66 03 86 + 39 01 00 00 00 00 0D BB 03 9B 03 9D 03 9F 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-04 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 09 00 19 00 35 00 4E 00 65 00 79 00 8C 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E5 01 11 01 56 01 88 01 D5 02 11 02 12 + 39 00 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 17 03 42 03 4E 03 61 + 39 00 00 00 00 00 0D B3 03 72 03 87 03 9E 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 C6 00 CD 00 D9 00 E5 00 F0 00 FB 01 05 01 0E + 39 00 00 00 00 00 11 B5 01 17 01 38 01 54 01 84 01 AB 01 EA 02 20 02 21 + 39 00 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FD 03 21 03 4C 03 59 03 67 + 39 00 00 00 00 00 0D B7 03 76 03 88 03 9E 03 B8 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 11 00 23 00 41 00 5B 00 73 00 88 00 9B 00 AC + 39 00 00 00 00 00 11 B9 00 BC 00 F3 01 1D 01 5F 01 8F 01 D9 02 14 02 15 + 39 00 00 00 00 00 11 BA 02 51 02 95 02 C1 02 FA 03 23 03 59 03 6D 03 95 + 39 00 00 00 00 00 0D BB 03 B8 03 BA 03 BC 03 BE 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 09 00 19 00 35 00 4E 00 65 00 79 00 8C 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E5 01 11 01 56 01 88 01 D5 02 11 02 12 + 39 00 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 17 03 42 03 4E 03 61 + 39 00 00 00 00 00 0D B3 03 72 03 87 03 9E 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 C6 00 CD 00 D9 00 E5 00 F0 00 FB 01 05 01 0E + 39 00 00 00 00 00 11 B5 01 17 01 38 01 54 01 84 01 AB 01 EA 02 20 02 21 + 39 00 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FD 03 21 03 4C 03 59 03 67 + 39 00 00 00 00 00 0D B7 03 76 03 88 03 9E 03 B8 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 11 00 23 00 41 00 5B 00 73 00 88 00 9B 00 AC + 39 00 00 00 00 00 11 B9 00 BC 00 F3 01 1D 01 5F 01 8F 01 D9 02 14 02 15 + 39 00 00 00 00 00 11 BA 02 51 02 95 02 C1 02 FA 03 23 03 59 03 6D 03 95 + 39 00 00 00 00 00 0D BB 03 B8 03 BA 03 BC 03 BE 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-04 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 09 00 19 00 35 00 4E 00 65 00 79 00 8C 00 9D + 39 01 00 00 00 00 11 B1 00 AD 00 E5 01 11 01 56 01 88 01 D5 02 11 02 12 + 39 01 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 17 03 42 03 4E 03 61 + 39 01 00 00 00 00 0D B3 03 72 03 87 03 9E 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 C6 00 CD 00 D9 00 E5 00 F0 00 FB 01 05 01 0E + 39 01 00 00 00 00 11 B5 01 17 01 38 01 54 01 84 01 AB 01 EA 02 20 02 21 + 39 01 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FD 03 21 03 4C 03 59 03 67 + 39 01 00 00 00 00 0D B7 03 76 03 88 03 9E 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 11 00 23 00 41 00 5B 00 73 00 88 00 9B 00 AC + 39 01 00 00 00 00 11 B9 00 BC 00 F3 01 1D 01 5F 01 8F 01 D9 02 14 02 15 + 39 01 00 00 00 00 11 BA 02 51 02 95 02 C1 02 FA 03 23 03 59 03 6D 03 95 + 39 01 00 00 00 00 0D BB 03 B8 03 BA 03 BC 03 BE 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 09 00 19 00 35 00 4E 00 65 00 79 00 8C 00 9D + 39 01 00 00 00 00 11 B1 00 AD 00 E5 01 11 01 56 01 88 01 D5 02 11 02 12 + 39 01 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 17 03 42 03 4E 03 61 + 39 01 00 00 00 00 0D B3 03 72 03 87 03 9E 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 C6 00 CD 00 D9 00 E5 00 F0 00 FB 01 05 01 0E + 39 01 00 00 00 00 11 B5 01 17 01 38 01 54 01 84 01 AB 01 EA 02 20 02 21 + 39 01 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FD 03 21 03 4C 03 59 03 67 + 39 01 00 00 00 00 0D B7 03 76 03 88 03 9E 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 11 00 23 00 41 00 5B 00 73 00 88 00 9B 00 AC + 39 01 00 00 00 00 11 B9 00 BC 00 F3 01 1D 01 5F 01 8F 01 D9 02 14 02 15 + 39 01 00 00 00 00 11 BA 02 51 02 95 02 C1 02 FA 03 23 03 59 03 6D 03 95 + 39 01 00 00 00 00 0D BB 03 B8 03 BA 03 BC 03 BE 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-05 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0A 00 1A 00 37 00 4E 00 66 00 79 00 8B 00 9D + 39 00 00 00 00 00 11 B1 00 AC 00 E2 01 0D 01 4E 01 82 01 CD 02 0A 02 0C + 39 00 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3D 03 4E 03 5D + 39 00 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 01 07 01 0B 01 14 01 1C 01 24 01 2B 01 32 01 39 + 39 00 00 00 00 00 11 B5 01 40 01 59 01 6F 01 96 01 B8 01 F1 02 24 02 26 + 39 00 00 00 00 00 11 B6 02 5C 02 9E 02 C9 02 FD 03 22 03 4D 03 5A 03 68 + 39 00 00 00 00 00 0D B7 03 78 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 01 0F 01 13 01 1C 01 23 01 2B 01 32 01 39 01 40 + 39 00 00 00 00 00 11 B9 01 46 01 5F 01 75 01 9B 01 BD 01 F3 02 27 02 29 + 39 00 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2C 03 64 03 80 03 92 + 39 00 00 00 00 00 0D BB 03 96 03 98 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0A 00 1A 00 37 00 4E 00 66 00 79 00 8B 00 9D + 39 00 00 00 00 00 11 B1 00 AC 00 E2 01 0D 01 4E 01 82 01 CD 02 0A 02 0C + 39 00 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3D 03 4E 03 5D + 39 00 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 01 07 01 0B 01 14 01 1C 01 24 01 2B 01 32 01 39 + 39 00 00 00 00 00 11 B5 01 40 01 59 01 6F 01 96 01 B8 01 F1 02 24 02 26 + 39 00 00 00 00 00 11 B6 02 5C 02 9E 02 C9 02 FD 03 22 03 4D 03 5A 03 68 + 39 00 00 00 00 00 0D B7 03 78 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 01 0F 01 13 01 1C 01 23 01 2B 01 32 01 39 01 40 + 39 00 00 00 00 00 11 B9 01 46 01 5F 01 75 01 9B 01 BD 01 F3 02 27 02 29 + 39 00 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2C 03 64 03 80 03 92 + 39 00 00 00 00 00 0D BB 03 96 03 98 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-05 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0A 00 1A 00 37 00 4E 00 66 00 79 00 8B 00 9D + 39 01 00 00 00 00 11 B1 00 AC 00 E2 01 0D 01 4E 01 82 01 CD 02 0A 02 0C + 39 01 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3D 03 4E 03 5D + 39 01 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 01 07 01 0B 01 14 01 1C 01 24 01 2B 01 32 01 39 + 39 01 00 00 00 00 11 B5 01 40 01 59 01 6F 01 96 01 B8 01 F1 02 24 02 26 + 39 01 00 00 00 00 11 B6 02 5C 02 9E 02 C9 02 FD 03 22 03 4D 03 5A 03 68 + 39 01 00 00 00 00 0D B7 03 78 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 01 0F 01 13 01 1C 01 23 01 2B 01 32 01 39 01 40 + 39 01 00 00 00 00 11 B9 01 46 01 5F 01 75 01 9B 01 BD 01 F3 02 27 02 29 + 39 01 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2C 03 64 03 80 03 92 + 39 01 00 00 00 00 0D BB 03 96 03 98 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0A 00 1A 00 37 00 4E 00 66 00 79 00 8B 00 9D + 39 01 00 00 00 00 11 B1 00 AC 00 E2 01 0D 01 4E 01 82 01 CD 02 0A 02 0C + 39 01 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3D 03 4E 03 5D + 39 01 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 01 07 01 0B 01 14 01 1C 01 24 01 2B 01 32 01 39 + 39 01 00 00 00 00 11 B5 01 40 01 59 01 6F 01 96 01 B8 01 F1 02 24 02 26 + 39 01 00 00 00 00 11 B6 02 5C 02 9E 02 C9 02 FD 03 22 03 4D 03 5A 03 68 + 39 01 00 00 00 00 0D B7 03 78 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 01 0F 01 13 01 1C 01 23 01 2B 01 32 01 39 01 40 + 39 01 00 00 00 00 11 B9 01 46 01 5F 01 75 01 9B 01 BD 01 F3 02 27 02 29 + 39 01 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2C 03 64 03 80 03 92 + 39 01 00 00 00 00 0D BB 03 96 03 98 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-06 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 39 00 53 00 6A 00 7E 00 91 00 A3 + 39 00 00 00 00 00 11 B1 00 B2 00 E9 01 15 01 57 01 89 01 D6 02 14 02 15 + 39 00 00 00 00 00 11 B2 02 51 02 94 02 C0 02 F5 03 15 03 43 03 53 03 62 + 39 00 00 00 00 00 0D B3 03 73 03 88 03 9F 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 CF 00 D5 00 E1 00 ED 00 F7 01 02 01 0B 01 15 + 39 00 00 00 00 00 11 B5 01 1D 01 3D 01 59 01 88 01 AE 01 ED 02 23 02 25 + 39 00 00 00 00 00 11 B6 02 5D 02 9F 02 CA 02 FE 03 22 03 4E 03 5A 03 68 + 39 00 00 00 00 00 0D B7 03 77 03 88 03 9C 03 B6 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 E2 00 E8 00 F3 00 FE 01 08 01 11 01 1A 01 23 + 39 00 00 00 00 00 11 B9 01 2B 01 49 01 64 01 90 01 B5 01 F2 02 28 02 29 + 39 00 00 00 00 00 11 BA 02 61 02 A3 02 CF 03 04 03 2D 03 64 03 7C 03 8C + 39 00 00 00 00 00 0D BB 03 8E 03 94 03 A0 03 C2 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 39 00 53 00 6A 00 7E 00 91 00 A3 + 39 00 00 00 00 00 11 B1 00 B2 00 E9 01 15 01 57 01 89 01 D6 02 14 02 15 + 39 00 00 00 00 00 11 B2 02 51 02 94 02 C0 02 F5 03 15 03 43 03 53 03 62 + 39 00 00 00 00 00 0D B3 03 73 03 88 03 9F 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 CF 00 D5 00 E1 00 ED 00 F7 01 02 01 0B 01 15 + 39 00 00 00 00 00 11 B5 01 1D 01 3D 01 59 01 88 01 AE 01 ED 02 23 02 25 + 39 00 00 00 00 00 11 B6 02 5D 02 9F 02 CA 02 FE 03 22 03 4E 03 5A 03 68 + 39 00 00 00 00 00 0D B7 03 77 03 88 03 9C 03 B6 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 E2 00 E8 00 F3 00 FE 01 08 01 11 01 1A 01 23 + 39 00 00 00 00 00 11 B9 01 2B 01 49 01 64 01 90 01 B5 01 F2 02 28 02 29 + 39 00 00 00 00 00 11 BA 02 61 02 A3 02 CF 03 04 03 2D 03 64 03 7C 03 8C + 39 00 00 00 00 00 0D BB 03 8E 03 94 03 A0 03 C2 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-06 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 39 00 53 00 6A 00 7E 00 91 00 A3 + 39 01 00 00 00 00 11 B1 00 B2 00 E9 01 15 01 57 01 89 01 D6 02 14 02 15 + 39 01 00 00 00 00 11 B2 02 51 02 94 02 C0 02 F5 03 15 03 43 03 53 03 62 + 39 01 00 00 00 00 0D B3 03 73 03 88 03 9F 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 CF 00 D5 00 E1 00 ED 00 F7 01 02 01 0B 01 15 + 39 01 00 00 00 00 11 B5 01 1D 01 3D 01 59 01 88 01 AE 01 ED 02 23 02 25 + 39 01 00 00 00 00 11 B6 02 5D 02 9F 02 CA 02 FE 03 22 03 4E 03 5A 03 68 + 39 01 00 00 00 00 0D B7 03 77 03 88 03 9C 03 B6 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 E2 00 E8 00 F3 00 FE 01 08 01 11 01 1A 01 23 + 39 01 00 00 00 00 11 B9 01 2B 01 49 01 64 01 90 01 B5 01 F2 02 28 02 29 + 39 01 00 00 00 00 11 BA 02 61 02 A3 02 CF 03 04 03 2D 03 64 03 7C 03 8C + 39 01 00 00 00 00 0D BB 03 8E 03 94 03 A0 03 C2 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 39 00 53 00 6A 00 7E 00 91 00 A3 + 39 01 00 00 00 00 11 B1 00 B2 00 E9 01 15 01 57 01 89 01 D6 02 14 02 15 + 39 01 00 00 00 00 11 B2 02 51 02 94 02 C0 02 F5 03 15 03 43 03 53 03 62 + 39 01 00 00 00 00 0D B3 03 73 03 88 03 9F 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 CF 00 D5 00 E1 00 ED 00 F7 01 02 01 0B 01 15 + 39 01 00 00 00 00 11 B5 01 1D 01 3D 01 59 01 88 01 AE 01 ED 02 23 02 25 + 39 01 00 00 00 00 11 B6 02 5D 02 9F 02 CA 02 FE 03 22 03 4E 03 5A 03 68 + 39 01 00 00 00 00 0D B7 03 77 03 88 03 9C 03 B6 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 E2 00 E8 00 F3 00 FE 01 08 01 11 01 1A 01 23 + 39 01 00 00 00 00 11 B9 01 2B 01 49 01 64 01 90 01 B5 01 F2 02 28 02 29 + 39 01 00 00 00 00 11 BA 02 61 02 A3 02 CF 03 04 03 2D 03 64 03 7C 03 8C + 39 01 00 00 00 00 0D BB 03 8E 03 94 03 A0 03 C2 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-07 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 00 00 00 00 00 11 B1 00 F4 01 1A 01 3B 01 6F 01 9A 01 DE 02 16 02 18 + 39 00 00 00 00 00 11 B2 02 51 02 95 02 C1 02 F7 03 1A 03 48 03 55 03 64 + 39 00 00 00 00 00 0D B3 03 74 03 87 03 9D 03 B9 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4E 00 65 00 79 00 8B 00 9B + 39 00 00 00 00 00 11 B5 00 AA 00 DF 01 09 01 4B 01 7E 01 CB 02 07 02 09 + 39 00 00 00 00 00 11 B6 02 46 02 8A 02 B7 02 EE 03 11 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 09 00 1A 00 37 00 51 00 68 00 7D 00 90 00 A1 + 39 00 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0B 02 0D + 39 00 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F4 03 1B 03 53 03 66 03 7D + 39 00 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 00 00 00 00 00 11 B1 00 F4 01 1A 01 3B 01 6F 01 9A 01 DE 02 16 02 18 + 39 00 00 00 00 00 11 B2 02 51 02 95 02 C1 02 F7 03 1A 03 48 03 55 03 64 + 39 00 00 00 00 00 0D B3 03 74 03 87 03 9D 03 B9 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4E 00 65 00 79 00 8B 00 9B + 39 00 00 00 00 00 11 B5 00 AA 00 DF 01 09 01 4B 01 7E 01 CB 02 07 02 09 + 39 00 00 00 00 00 11 B6 02 46 02 8A 02 B7 02 EE 03 11 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 09 00 1A 00 37 00 51 00 68 00 7D 00 90 00 A1 + 39 00 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0B 02 0D + 39 00 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F4 03 1B 03 53 03 66 03 7D + 39 00 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-07 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 01 00 00 00 00 11 B1 00 F4 01 1A 01 3B 01 6F 01 9A 01 DE 02 16 02 18 + 39 01 00 00 00 00 11 B2 02 51 02 95 02 C1 02 F7 03 1A 03 48 03 55 03 64 + 39 01 00 00 00 00 0D B3 03 74 03 87 03 9D 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4E 00 65 00 79 00 8B 00 9B + 39 01 00 00 00 00 11 B5 00 AA 00 DF 01 09 01 4B 01 7E 01 CB 02 07 02 09 + 39 01 00 00 00 00 11 B6 02 46 02 8A 02 B7 02 EE 03 11 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1A 00 37 00 51 00 68 00 7D 00 90 00 A1 + 39 01 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0B 02 0D + 39 01 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F4 03 1B 03 53 03 66 03 7D + 39 01 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 01 00 00 00 00 11 B1 00 F4 01 1A 01 3B 01 6F 01 9A 01 DE 02 16 02 18 + 39 01 00 00 00 00 11 B2 02 51 02 95 02 C1 02 F7 03 1A 03 48 03 55 03 64 + 39 01 00 00 00 00 0D B3 03 74 03 87 03 9D 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4E 00 65 00 79 00 8B 00 9B + 39 01 00 00 00 00 11 B5 00 AA 00 DF 01 09 01 4B 01 7E 01 CB 02 07 02 09 + 39 01 00 00 00 00 11 B6 02 46 02 8A 02 B7 02 EE 03 11 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1A 00 37 00 51 00 68 00 7D 00 90 00 A1 + 39 01 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0B 02 0D + 39 01 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F4 03 1B 03 53 03 66 03 7D + 39 01 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-08 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 01 03 01 08 01 10 01 19 01 21 01 28 01 30 01 37 + 39 00 00 00 00 00 11 B1 01 3E 01 58 01 6E 01 96 01 B9 01 F2 02 26 02 28 + 39 00 00 00 00 00 11 B2 02 5E 02 A0 02 CB 02 FF 03 25 03 50 03 5D 03 6A + 39 00 00 00 00 00 0D B3 03 7A 03 8C 03 A2 03 BC 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4B 00 61 00 74 00 87 00 97 + 39 00 00 00 00 00 11 B5 00 A7 00 DD 01 07 01 4A 01 7D 01 CB 02 08 02 0A + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 ED 03 10 03 41 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 09 00 1A 00 38 00 51 00 68 00 7D 00 90 00 A1 + 39 00 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0C 02 0E + 39 00 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F3 03 1A 03 52 03 66 03 7D + 39 00 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 01 03 01 08 01 10 01 19 01 21 01 28 01 30 01 37 + 39 00 00 00 00 00 11 B1 01 3E 01 58 01 6E 01 96 01 B9 01 F2 02 26 02 28 + 39 00 00 00 00 00 11 B2 02 5E 02 A0 02 CB 02 FF 03 25 03 50 03 5D 03 6A + 39 00 00 00 00 00 0D B3 03 7A 03 8C 03 A2 03 BC 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4B 00 61 00 74 00 87 00 97 + 39 00 00 00 00 00 11 B5 00 A7 00 DD 01 07 01 4A 01 7D 01 CB 02 08 02 0A + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 ED 03 10 03 41 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 09 00 1A 00 38 00 51 00 68 00 7D 00 90 00 A1 + 39 00 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0C 02 0E + 39 00 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F3 03 1A 03 52 03 66 03 7D + 39 00 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-08 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 01 03 01 08 01 10 01 19 01 21 01 28 01 30 01 37 + 39 01 00 00 00 00 11 B1 01 3E 01 58 01 6E 01 96 01 B9 01 F2 02 26 02 28 + 39 01 00 00 00 00 11 B2 02 5E 02 A0 02 CB 02 FF 03 25 03 50 03 5D 03 6A + 39 01 00 00 00 00 0D B3 03 7A 03 8C 03 A2 03 BC 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4B 00 61 00 74 00 87 00 97 + 39 01 00 00 00 00 11 B5 00 A7 00 DD 01 07 01 4A 01 7D 01 CB 02 08 02 0A + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 ED 03 10 03 41 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1A 00 38 00 51 00 68 00 7D 00 90 00 A1 + 39 01 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0C 02 0E + 39 01 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F3 03 1A 03 52 03 66 03 7D + 39 01 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 01 03 01 08 01 10 01 19 01 21 01 28 01 30 01 37 + 39 01 00 00 00 00 11 B1 01 3E 01 58 01 6E 01 96 01 B9 01 F2 02 26 02 28 + 39 01 00 00 00 00 11 B2 02 5E 02 A0 02 CB 02 FF 03 25 03 50 03 5D 03 6A + 39 01 00 00 00 00 0D B3 03 7A 03 8C 03 A2 03 BC 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4B 00 61 00 74 00 87 00 97 + 39 01 00 00 00 00 11 B5 00 A7 00 DD 01 07 01 4A 01 7D 01 CB 02 08 02 0A + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 ED 03 10 03 41 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1A 00 38 00 51 00 68 00 7D 00 90 00 A1 + 39 01 00 00 00 00 11 B9 00 B1 00 E7 01 11 01 52 01 84 01 D0 02 0C 02 0E + 39 01 00 00 00 00 11 BA 02 49 02 8E 02 BB 02 F3 03 1A 03 52 03 66 03 7D + 39 01 00 00 00 00 0D BB 03 8F 03 97 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-09 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0A 00 1B 00 37 00 50 00 66 00 7A 00 8C 00 9E + 39 00 00 00 00 00 11 B1 00 AE 00 E3 01 0E 01 4E 01 82 01 CE 02 0A 02 0C + 39 00 00 00 00 00 11 B2 02 48 02 8C 02 B9 02 EE 03 11 03 3F 03 51 03 5F + 39 00 00 00 00 00 0D B3 03 70 03 82 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 00 00 00 00 00 11 B5 00 F4 01 1A 01 39 01 6E 01 98 01 DC 02 14 02 15 + 39 00 00 00 00 00 11 B6 02 4F 02 92 02 BE 02 F4 03 16 03 46 03 53 03 62 + 39 00 00 00 00 00 0D B7 03 72 03 85 03 9C 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 01 12 01 16 01 1E 01 26 01 2D 01 35 01 3B 01 42 + 39 00 00 00 00 00 11 B9 01 49 01 61 01 77 01 9C 01 BE 01 F4 02 28 02 29 + 39 00 00 00 00 00 11 BA 02 60 02 A1 02 CE 03 03 03 2F 03 69 03 89 03 98 + 39 00 00 00 00 00 0D BB 03 9A 03 9C 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0A 00 1B 00 37 00 50 00 66 00 7A 00 8C 00 9E + 39 00 00 00 00 00 11 B1 00 AE 00 E3 01 0E 01 4E 01 82 01 CE 02 0A 02 0C + 39 00 00 00 00 00 11 B2 02 48 02 8C 02 B9 02 EE 03 11 03 3F 03 51 03 5F + 39 00 00 00 00 00 0D B3 03 70 03 82 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 00 00 00 00 00 11 B5 00 F4 01 1A 01 39 01 6E 01 98 01 DC 02 14 02 15 + 39 00 00 00 00 00 11 B6 02 4F 02 92 02 BE 02 F4 03 16 03 46 03 53 03 62 + 39 00 00 00 00 00 0D B7 03 72 03 85 03 9C 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 01 12 01 16 01 1E 01 26 01 2D 01 35 01 3B 01 42 + 39 00 00 00 00 00 11 B9 01 49 01 61 01 77 01 9C 01 BE 01 F4 02 28 02 29 + 39 00 00 00 00 00 11 BA 02 60 02 A1 02 CE 03 03 03 2F 03 69 03 89 03 98 + 39 00 00 00 00 00 0D BB 03 9A 03 9C 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-09 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0A 00 1B 00 37 00 50 00 66 00 7A 00 8C 00 9E + 39 01 00 00 00 00 11 B1 00 AE 00 E3 01 0E 01 4E 01 82 01 CE 02 0A 02 0C + 39 01 00 00 00 00 11 B2 02 48 02 8C 02 B9 02 EE 03 11 03 3F 03 51 03 5F + 39 01 00 00 00 00 0D B3 03 70 03 82 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 01 00 00 00 00 11 B5 00 F4 01 1A 01 39 01 6E 01 98 01 DC 02 14 02 15 + 39 01 00 00 00 00 11 B6 02 4F 02 92 02 BE 02 F4 03 16 03 46 03 53 03 62 + 39 01 00 00 00 00 0D B7 03 72 03 85 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 01 12 01 16 01 1E 01 26 01 2D 01 35 01 3B 01 42 + 39 01 00 00 00 00 11 B9 01 49 01 61 01 77 01 9C 01 BE 01 F4 02 28 02 29 + 39 01 00 00 00 00 11 BA 02 60 02 A1 02 CE 03 03 03 2F 03 69 03 89 03 98 + 39 01 00 00 00 00 0D BB 03 9A 03 9C 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0A 00 1B 00 37 00 50 00 66 00 7A 00 8C 00 9E + 39 01 00 00 00 00 11 B1 00 AE 00 E3 01 0E 01 4E 01 82 01 CE 02 0A 02 0C + 39 01 00 00 00 00 11 B2 02 48 02 8C 02 B9 02 EE 03 11 03 3F 03 51 03 5F + 39 01 00 00 00 00 0D B3 03 70 03 82 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 91 00 99 00 A9 00 B7 00 C5 00 D2 00 DE 00 E9 + 39 01 00 00 00 00 11 B5 00 F4 01 1A 01 39 01 6E 01 98 01 DC 02 14 02 15 + 39 01 00 00 00 00 11 B6 02 4F 02 92 02 BE 02 F4 03 16 03 46 03 53 03 62 + 39 01 00 00 00 00 0D B7 03 72 03 85 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 01 12 01 16 01 1E 01 26 01 2D 01 35 01 3B 01 42 + 39 01 00 00 00 00 11 B9 01 49 01 61 01 77 01 9C 01 BE 01 F4 02 28 02 29 + 39 01 00 00 00 00 11 BA 02 60 02 A1 02 CE 03 03 03 2F 03 69 03 89 03 98 + 39 01 00 00 00 00 0D BB 03 9A 03 9C 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-10 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0A 00 1A 00 35 00 4E 00 66 00 79 00 8C 00 9D + 39 00 00 00 00 00 11 B1 00 AC 00 E3 01 0C 01 4F 01 80 01 CE 02 0A 02 0C + 39 00 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3F 03 50 03 5E + 39 00 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 D5 00 DB 00 E6 00 F0 00 FA 01 04 01 0D 01 15 + 39 00 00 00 00 00 11 B5 01 1E 01 3C 01 56 01 83 01 A9 01 E7 02 1C 02 1E + 39 00 00 00 00 00 11 B6 02 55 02 98 02 C3 02 F8 03 1B 03 4A 03 57 03 65 + 39 00 00 00 00 00 0D B7 03 75 03 88 03 9E 03 B9 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 01 10 01 14 01 1C 01 24 01 2C 01 33 01 3A 01 41 + 39 00 00 00 00 00 11 B9 01 47 01 60 01 75 01 9C 01 BC 01 F4 02 27 02 29 + 39 00 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2D 03 68 03 86 03 95 + 39 00 00 00 00 00 0D BB 03 97 03 99 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0A 00 1A 00 35 00 4E 00 66 00 79 00 8C 00 9D + 39 00 00 00 00 00 11 B1 00 AC 00 E3 01 0C 01 4F 01 80 01 CE 02 0A 02 0C + 39 00 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3F 03 50 03 5E + 39 00 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 D5 00 DB 00 E6 00 F0 00 FA 01 04 01 0D 01 15 + 39 00 00 00 00 00 11 B5 01 1E 01 3C 01 56 01 83 01 A9 01 E7 02 1C 02 1E + 39 00 00 00 00 00 11 B6 02 55 02 98 02 C3 02 F8 03 1B 03 4A 03 57 03 65 + 39 00 00 00 00 00 0D B7 03 75 03 88 03 9E 03 B9 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 01 10 01 14 01 1C 01 24 01 2C 01 33 01 3A 01 41 + 39 00 00 00 00 00 11 B9 01 47 01 60 01 75 01 9C 01 BC 01 F4 02 27 02 29 + 39 00 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2D 03 68 03 86 03 95 + 39 00 00 00 00 00 0D BB 03 97 03 99 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-10 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0A 00 1A 00 35 00 4E 00 66 00 79 00 8C 00 9D + 39 01 00 00 00 00 11 B1 00 AC 00 E3 01 0C 01 4F 01 80 01 CE 02 0A 02 0C + 39 01 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3F 03 50 03 5E + 39 01 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 D5 00 DB 00 E6 00 F0 00 FA 01 04 01 0D 01 15 + 39 01 00 00 00 00 11 B5 01 1E 01 3C 01 56 01 83 01 A9 01 E7 02 1C 02 1E + 39 01 00 00 00 00 11 B6 02 55 02 98 02 C3 02 F8 03 1B 03 4A 03 57 03 65 + 39 01 00 00 00 00 0D B7 03 75 03 88 03 9E 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 01 10 01 14 01 1C 01 24 01 2C 01 33 01 3A 01 41 + 39 01 00 00 00 00 11 B9 01 47 01 60 01 75 01 9C 01 BC 01 F4 02 27 02 29 + 39 01 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2D 03 68 03 86 03 95 + 39 01 00 00 00 00 0D BB 03 97 03 99 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0A 00 1A 00 35 00 4E 00 66 00 79 00 8C 00 9D + 39 01 00 00 00 00 11 B1 00 AC 00 E3 01 0C 01 4F 01 80 01 CE 02 0A 02 0C + 39 01 00 00 00 00 11 B2 02 47 02 8C 02 B8 02 EF 03 0F 03 3F 03 50 03 5E + 39 01 00 00 00 00 0D B3 03 6F 03 82 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 D5 00 DB 00 E6 00 F0 00 FA 01 04 01 0D 01 15 + 39 01 00 00 00 00 11 B5 01 1E 01 3C 01 56 01 83 01 A9 01 E7 02 1C 02 1E + 39 01 00 00 00 00 11 B6 02 55 02 98 02 C3 02 F8 03 1B 03 4A 03 57 03 65 + 39 01 00 00 00 00 0D B7 03 75 03 88 03 9E 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 01 10 01 14 01 1C 01 24 01 2C 01 33 01 3A 01 41 + 39 01 00 00 00 00 11 B9 01 47 01 60 01 75 01 9C 01 BC 01 F4 02 27 02 29 + 39 01 00 00 00 00 11 BA 02 5F 02 A1 02 CD 03 03 03 2D 03 68 03 86 03 95 + 39 01 00 00 00 00 0D BB 03 97 03 99 03 A4 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-11 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 51 00 67 00 7B 00 8E 00 A0 + 39 00 00 00 00 00 11 B1 00 B0 00 E5 01 12 01 52 01 84 01 D0 02 0C 02 0E + 39 00 00 00 00 00 11 B2 02 49 02 8D 02 B8 02 EF 03 0E 03 3D 03 49 03 59 + 39 00 00 00 00 00 0D B3 03 67 03 7C 03 9A 03 B6 03 D1 03 D7 + 39 00 00 00 00 00 11 B4 01 35 01 38 01 3F 01 45 01 4B 01 51 01 57 01 5D + 39 00 00 00 00 00 11 B5 01 62 01 77 01 8B 01 AC 01 CA 01 FD 02 2F 02 30 + 39 00 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 02 03 29 03 53 03 5F 03 6D + 39 00 00 00 00 00 0D B7 03 7C 03 8E 03 A3 03 BD 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 01 1A 01 1E 01 26 01 2D 01 34 01 3B 01 42 01 49 + 39 00 00 00 00 00 11 B9 01 4F 01 66 01 7C 01 A1 01 C1 01 F7 02 2A 02 2B + 39 00 00 00 00 00 11 BA 02 61 02 A3 02 CE 03 04 03 2E 03 65 03 7B 03 A9 + 39 00 00 00 00 00 0D BB 03 C8 03 CB 03 CD 03 CF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 51 00 67 00 7B 00 8E 00 A0 + 39 00 00 00 00 00 11 B1 00 B0 00 E5 01 12 01 52 01 84 01 D0 02 0C 02 0E + 39 00 00 00 00 00 11 B2 02 49 02 8D 02 B8 02 EF 03 0E 03 3D 03 49 03 59 + 39 00 00 00 00 00 0D B3 03 67 03 7C 03 9A 03 B6 03 D1 03 D7 + 39 00 00 00 00 00 11 B4 01 35 01 38 01 3F 01 45 01 4B 01 51 01 57 01 5D + 39 00 00 00 00 00 11 B5 01 62 01 77 01 8B 01 AC 01 CA 01 FD 02 2F 02 30 + 39 00 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 02 03 29 03 53 03 5F 03 6D + 39 00 00 00 00 00 0D B7 03 7C 03 8E 03 A3 03 BD 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 01 1A 01 1E 01 26 01 2D 01 34 01 3B 01 42 01 49 + 39 00 00 00 00 00 11 B9 01 4F 01 66 01 7C 01 A1 01 C1 01 F7 02 2A 02 2B + 39 00 00 00 00 00 11 BA 02 61 02 A3 02 CE 03 04 03 2E 03 65 03 7B 03 A9 + 39 00 00 00 00 00 0D BB 03 C8 03 CB 03 CD 03 CF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-11 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 51 00 67 00 7B 00 8E 00 A0 + 39 01 00 00 00 00 11 B1 00 B0 00 E5 01 12 01 52 01 84 01 D0 02 0C 02 0E + 39 01 00 00 00 00 11 B2 02 49 02 8D 02 B8 02 EF 03 0E 03 3D 03 49 03 59 + 39 01 00 00 00 00 0D B3 03 67 03 7C 03 9A 03 B6 03 D1 03 D7 + 39 01 00 00 00 00 11 B4 01 35 01 38 01 3F 01 45 01 4B 01 51 01 57 01 5D + 39 01 00 00 00 00 11 B5 01 62 01 77 01 8B 01 AC 01 CA 01 FD 02 2F 02 30 + 39 01 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 02 03 29 03 53 03 5F 03 6D + 39 01 00 00 00 00 0D B7 03 7C 03 8E 03 A3 03 BD 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 01 1A 01 1E 01 26 01 2D 01 34 01 3B 01 42 01 49 + 39 01 00 00 00 00 11 B9 01 4F 01 66 01 7C 01 A1 01 C1 01 F7 02 2A 02 2B + 39 01 00 00 00 00 11 BA 02 61 02 A3 02 CE 03 04 03 2E 03 65 03 7B 03 A9 + 39 01 00 00 00 00 0D BB 03 C8 03 CB 03 CD 03 CF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 38 00 51 00 67 00 7B 00 8E 00 A0 + 39 01 00 00 00 00 11 B1 00 B0 00 E5 01 12 01 52 01 84 01 D0 02 0C 02 0E + 39 01 00 00 00 00 11 B2 02 49 02 8D 02 B8 02 EF 03 0E 03 3D 03 49 03 59 + 39 01 00 00 00 00 0D B3 03 67 03 7C 03 9A 03 B6 03 D1 03 D7 + 39 01 00 00 00 00 11 B4 01 35 01 38 01 3F 01 45 01 4B 01 51 01 57 01 5D + 39 01 00 00 00 00 11 B5 01 62 01 77 01 8B 01 AC 01 CA 01 FD 02 2F 02 30 + 39 01 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 02 03 29 03 53 03 5F 03 6D + 39 01 00 00 00 00 0D B7 03 7C 03 8E 03 A3 03 BD 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 01 1A 01 1E 01 26 01 2D 01 34 01 3B 01 42 01 49 + 39 01 00 00 00 00 11 B9 01 4F 01 66 01 7C 01 A1 01 C1 01 F7 02 2A 02 2B + 39 01 00 00 00 00 11 BA 02 61 02 A3 02 CE 03 04 03 2E 03 65 03 7B 03 A9 + 39 01 00 00 00 00 0D BB 03 C8 03 CB 03 CD 03 CF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-12 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 6A 00 7F 00 91 00 A3 + 39 00 00 00 00 00 11 B1 00 B3 00 E9 01 14 01 56 01 89 01 D6 02 11 02 13 + 39 00 00 00 00 00 11 B2 02 4F 02 91 02 BD 02 F4 03 15 03 3D 03 4D 03 5D + 39 00 00 00 00 00 0D B3 03 71 03 87 03 9E 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 01 59 01 5C 01 61 01 67 01 6C 01 71 01 76 01 7B + 39 00 00 00 00 00 11 B5 01 80 01 92 01 A3 01 C1 01 DD 02 0C 02 3C 02 3D + 39 00 00 00 00 00 11 B6 02 71 02 B0 02 D9 03 0D 03 30 03 58 03 64 03 72 + 39 00 00 00 00 00 0D B7 03 80 03 91 03 A6 03 BE 03 D4 03 D7 + 39 00 00 00 00 00 11 B8 01 23 01 27 01 2E 01 36 01 3D 01 44 01 4A 01 51 + 39 00 00 00 00 00 11 B9 01 57 01 6E 01 83 01 A8 01 C8 01 FE 02 30 02 32 + 39 00 00 00 00 00 11 BA 02 68 02 A8 02 D3 03 0B 03 34 03 6B 03 8A 03 A3 + 39 00 00 00 00 00 0D BB 03 A7 03 A9 03 AB 03 B7 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 6A 00 7F 00 91 00 A3 + 39 00 00 00 00 00 11 B1 00 B3 00 E9 01 14 01 56 01 89 01 D6 02 11 02 13 + 39 00 00 00 00 00 11 B2 02 4F 02 91 02 BD 02 F4 03 15 03 3D 03 4D 03 5D + 39 00 00 00 00 00 0D B3 03 71 03 87 03 9E 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 01 59 01 5C 01 61 01 67 01 6C 01 71 01 76 01 7B + 39 00 00 00 00 00 11 B5 01 80 01 92 01 A3 01 C1 01 DD 02 0C 02 3C 02 3D + 39 00 00 00 00 00 11 B6 02 71 02 B0 02 D9 03 0D 03 30 03 58 03 64 03 72 + 39 00 00 00 00 00 0D B7 03 80 03 91 03 A6 03 BE 03 D4 03 D7 + 39 00 00 00 00 00 11 B8 01 23 01 27 01 2E 01 36 01 3D 01 44 01 4A 01 51 + 39 00 00 00 00 00 11 B9 01 57 01 6E 01 83 01 A8 01 C8 01 FE 02 30 02 32 + 39 00 00 00 00 00 11 BA 02 68 02 A8 02 D3 03 0B 03 34 03 6B 03 8A 03 A3 + 39 00 00 00 00 00 0D BB 03 A7 03 A9 03 AB 03 B7 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-12 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 6A 00 7F 00 91 00 A3 + 39 01 00 00 00 00 11 B1 00 B3 00 E9 01 14 01 56 01 89 01 D6 02 11 02 13 + 39 01 00 00 00 00 11 B2 02 4F 02 91 02 BD 02 F4 03 15 03 3D 03 4D 03 5D + 39 01 00 00 00 00 0D B3 03 71 03 87 03 9E 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 01 59 01 5C 01 61 01 67 01 6C 01 71 01 76 01 7B + 39 01 00 00 00 00 11 B5 01 80 01 92 01 A3 01 C1 01 DD 02 0C 02 3C 02 3D + 39 01 00 00 00 00 11 B6 02 71 02 B0 02 D9 03 0D 03 30 03 58 03 64 03 72 + 39 01 00 00 00 00 0D B7 03 80 03 91 03 A6 03 BE 03 D4 03 D7 + 39 01 00 00 00 00 11 B8 01 23 01 27 01 2E 01 36 01 3D 01 44 01 4A 01 51 + 39 01 00 00 00 00 11 B9 01 57 01 6E 01 83 01 A8 01 C8 01 FE 02 30 02 32 + 39 01 00 00 00 00 11 BA 02 68 02 A8 02 D3 03 0B 03 34 03 6B 03 8A 03 A3 + 39 01 00 00 00 00 0D BB 03 A7 03 A9 03 AB 03 B7 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 6A 00 7F 00 91 00 A3 + 39 01 00 00 00 00 11 B1 00 B3 00 E9 01 14 01 56 01 89 01 D6 02 11 02 13 + 39 01 00 00 00 00 11 B2 02 4F 02 91 02 BD 02 F4 03 15 03 3D 03 4D 03 5D + 39 01 00 00 00 00 0D B3 03 71 03 87 03 9E 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 01 59 01 5C 01 61 01 67 01 6C 01 71 01 76 01 7B + 39 01 00 00 00 00 11 B5 01 80 01 92 01 A3 01 C1 01 DD 02 0C 02 3C 02 3D + 39 01 00 00 00 00 11 B6 02 71 02 B0 02 D9 03 0D 03 30 03 58 03 64 03 72 + 39 01 00 00 00 00 0D B7 03 80 03 91 03 A6 03 BE 03 D4 03 D7 + 39 01 00 00 00 00 11 B8 01 23 01 27 01 2E 01 36 01 3D 01 44 01 4A 01 51 + 39 01 00 00 00 00 11 B9 01 57 01 6E 01 83 01 A8 01 C8 01 FE 02 30 02 32 + 39 01 00 00 00 00 11 BA 02 68 02 A8 02 D3 03 0B 03 34 03 6B 03 8A 03 A3 + 39 01 00 00 00 00 0D BB 03 A7 03 A9 03 AB 03 B7 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-13 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0C 00 1D 00 3A 00 54 00 6B 00 80 00 93 00 A5 + 39 00 00 00 00 00 11 B1 00 B5 00 EC 01 17 01 5A 01 8C 01 D8 02 13 02 15 + 39 00 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 45 03 52 03 61 + 39 00 00 00 00 00 0D B3 03 6D 03 84 03 9B 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 0C 00 1C 00 39 00 54 00 6A 00 80 00 92 00 A5 + 39 00 00 00 00 00 11 B5 00 B4 00 EA 01 16 01 57 01 89 01 D4 02 10 02 12 + 39 00 00 00 00 00 11 B6 02 4D 02 90 02 BC 02 F3 03 14 03 45 03 52 03 60 + 39 00 00 00 00 00 0D B7 03 6B 03 80 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 D7 00 DD 00 E9 00 F5 00 FF 01 0A 01 13 01 1D + 39 00 00 00 00 00 11 B9 01 25 01 44 01 60 01 8D 01 B3 01 F0 02 25 02 27 + 39 00 00 00 00 00 11 BA 02 5E 02 A0 02 CC 03 03 03 2D 03 6A 03 87 03 C9 + 39 00 00 00 00 00 0D BB 03 CB 03 CD 03 CF 03 D1 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0C 00 1D 00 3A 00 54 00 6B 00 80 00 93 00 A5 + 39 00 00 00 00 00 11 B1 00 B5 00 EC 01 17 01 5A 01 8C 01 D8 02 13 02 15 + 39 00 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 45 03 52 03 61 + 39 00 00 00 00 00 0D B3 03 6D 03 84 03 9B 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 0C 00 1C 00 39 00 54 00 6A 00 80 00 92 00 A5 + 39 00 00 00 00 00 11 B5 00 B4 00 EA 01 16 01 57 01 89 01 D4 02 10 02 12 + 39 00 00 00 00 00 11 B6 02 4D 02 90 02 BC 02 F3 03 14 03 45 03 52 03 60 + 39 00 00 00 00 00 0D B7 03 6B 03 80 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 D7 00 DD 00 E9 00 F5 00 FF 01 0A 01 13 01 1D + 39 00 00 00 00 00 11 B9 01 25 01 44 01 60 01 8D 01 B3 01 F0 02 25 02 27 + 39 00 00 00 00 00 11 BA 02 5E 02 A0 02 CC 03 03 03 2D 03 6A 03 87 03 C9 + 39 00 00 00 00 00 0D BB 03 CB 03 CD 03 CF 03 D1 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-13 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0C 00 1D 00 3A 00 54 00 6B 00 80 00 93 00 A5 + 39 01 00 00 00 00 11 B1 00 B5 00 EC 01 17 01 5A 01 8C 01 D8 02 13 02 15 + 39 01 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 45 03 52 03 61 + 39 01 00 00 00 00 0D B3 03 6D 03 84 03 9B 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 0C 00 1C 00 39 00 54 00 6A 00 80 00 92 00 A5 + 39 01 00 00 00 00 11 B5 00 B4 00 EA 01 16 01 57 01 89 01 D4 02 10 02 12 + 39 01 00 00 00 00 11 B6 02 4D 02 90 02 BC 02 F3 03 14 03 45 03 52 03 60 + 39 01 00 00 00 00 0D B7 03 6B 03 80 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 D7 00 DD 00 E9 00 F5 00 FF 01 0A 01 13 01 1D + 39 01 00 00 00 00 11 B9 01 25 01 44 01 60 01 8D 01 B3 01 F0 02 25 02 27 + 39 01 00 00 00 00 11 BA 02 5E 02 A0 02 CC 03 03 03 2D 03 6A 03 87 03 C9 + 39 01 00 00 00 00 0D BB 03 CB 03 CD 03 CF 03 D1 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0C 00 1D 00 3A 00 54 00 6B 00 80 00 93 00 A5 + 39 01 00 00 00 00 11 B1 00 B5 00 EC 01 17 01 5A 01 8C 01 D8 02 13 02 15 + 39 01 00 00 00 00 11 B2 02 50 02 93 02 BF 02 F5 03 16 03 45 03 52 03 61 + 39 01 00 00 00 00 0D B3 03 6D 03 84 03 9B 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 0C 00 1C 00 39 00 54 00 6A 00 80 00 92 00 A5 + 39 01 00 00 00 00 11 B5 00 B4 00 EA 01 16 01 57 01 89 01 D4 02 10 02 12 + 39 01 00 00 00 00 11 B6 02 4D 02 90 02 BC 02 F3 03 14 03 45 03 52 03 60 + 39 01 00 00 00 00 0D B7 03 6B 03 80 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 D7 00 DD 00 E9 00 F5 00 FF 01 0A 01 13 01 1D + 39 01 00 00 00 00 11 B9 01 25 01 44 01 60 01 8D 01 B3 01 F0 02 25 02 27 + 39 01 00 00 00 00 11 BA 02 5E 02 A0 02 CC 03 03 03 2D 03 6A 03 87 03 C9 + 39 01 00 00 00 00 0D BB 03 CB 03 CD 03 CF 03 D1 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-14 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0C 00 1D 00 3B 00 54 00 6B 00 7E 00 93 00 A3 + 39 00 00 00 00 00 11 B1 00 B5 00 EB 01 16 01 5A 01 8D 01 DA 02 15 02 16 + 39 00 00 00 00 00 11 B2 02 51 02 94 02 BF 02 F6 03 16 03 44 03 51 03 60 + 39 00 00 00 00 00 0D B3 03 71 03 86 03 9C 03 BC 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 66 00 71 00 85 00 98 00 A9 00 B9 00 C8 00 D5 + 39 00 00 00 00 00 11 B5 00 E2 01 0E 01 32 01 6C 01 99 01 E0 02 19 02 1A + 39 00 00 00 00 00 11 B6 02 53 02 96 02 C1 02 F8 03 19 03 48 03 55 03 64 + 39 00 00 00 00 00 0D B7 03 74 03 89 03 9D 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 CC 00 D3 00 E0 00 EC 00 F7 01 01 01 0C 01 15 + 39 00 00 00 00 00 11 B9 01 1F 01 3F 01 5B 01 8B 01 B2 01 F1 02 26 02 27 + 39 00 00 00 00 00 11 BA 02 5E 02 A0 02 CB 03 04 03 2C 03 67 03 80 03 93 + 39 00 00 00 00 00 0D BB 03 97 03 9A 03 9C 03 B2 03 D0 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0C 00 1D 00 3B 00 54 00 6B 00 7E 00 93 00 A3 + 39 00 00 00 00 00 11 B1 00 B5 00 EB 01 16 01 5A 01 8D 01 DA 02 15 02 16 + 39 00 00 00 00 00 11 B2 02 51 02 94 02 BF 02 F6 03 16 03 44 03 51 03 60 + 39 00 00 00 00 00 0D B3 03 71 03 86 03 9C 03 BC 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 66 00 71 00 85 00 98 00 A9 00 B9 00 C8 00 D5 + 39 00 00 00 00 00 11 B5 00 E2 01 0E 01 32 01 6C 01 99 01 E0 02 19 02 1A + 39 00 00 00 00 00 11 B6 02 53 02 96 02 C1 02 F8 03 19 03 48 03 55 03 64 + 39 00 00 00 00 00 0D B7 03 74 03 89 03 9D 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 CC 00 D3 00 E0 00 EC 00 F7 01 01 01 0C 01 15 + 39 00 00 00 00 00 11 B9 01 1F 01 3F 01 5B 01 8B 01 B2 01 F1 02 26 02 27 + 39 00 00 00 00 00 11 BA 02 5E 02 A0 02 CB 03 04 03 2C 03 67 03 80 03 93 + 39 00 00 00 00 00 0D BB 03 97 03 9A 03 9C 03 B2 03 D0 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-14 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0C 00 1D 00 3B 00 54 00 6B 00 7E 00 93 00 A3 + 39 01 00 00 00 00 11 B1 00 B5 00 EB 01 16 01 5A 01 8D 01 DA 02 15 02 16 + 39 01 00 00 00 00 11 B2 02 51 02 94 02 BF 02 F6 03 16 03 44 03 51 03 60 + 39 01 00 00 00 00 0D B3 03 71 03 86 03 9C 03 BC 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 66 00 71 00 85 00 98 00 A9 00 B9 00 C8 00 D5 + 39 01 00 00 00 00 11 B5 00 E2 01 0E 01 32 01 6C 01 99 01 E0 02 19 02 1A + 39 01 00 00 00 00 11 B6 02 53 02 96 02 C1 02 F8 03 19 03 48 03 55 03 64 + 39 01 00 00 00 00 0D B7 03 74 03 89 03 9D 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 CC 00 D3 00 E0 00 EC 00 F7 01 01 01 0C 01 15 + 39 01 00 00 00 00 11 B9 01 1F 01 3F 01 5B 01 8B 01 B2 01 F1 02 26 02 27 + 39 01 00 00 00 00 11 BA 02 5E 02 A0 02 CB 03 04 03 2C 03 67 03 80 03 93 + 39 01 00 00 00 00 0D BB 03 97 03 9A 03 9C 03 B2 03 D0 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0C 00 1D 00 3B 00 54 00 6B 00 7E 00 93 00 A3 + 39 01 00 00 00 00 11 B1 00 B5 00 EB 01 16 01 5A 01 8D 01 DA 02 15 02 16 + 39 01 00 00 00 00 11 B2 02 51 02 94 02 BF 02 F6 03 16 03 44 03 51 03 60 + 39 01 00 00 00 00 0D B3 03 71 03 86 03 9C 03 BC 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 66 00 71 00 85 00 98 00 A9 00 B9 00 C8 00 D5 + 39 01 00 00 00 00 11 B5 00 E2 01 0E 01 32 01 6C 01 99 01 E0 02 19 02 1A + 39 01 00 00 00 00 11 B6 02 53 02 96 02 C1 02 F8 03 19 03 48 03 55 03 64 + 39 01 00 00 00 00 0D B7 03 74 03 89 03 9D 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 CC 00 D3 00 E0 00 EC 00 F7 01 01 01 0C 01 15 + 39 01 00 00 00 00 11 B9 01 1F 01 3F 01 5B 01 8B 01 B2 01 F1 02 26 02 27 + 39 01 00 00 00 00 11 BA 02 5E 02 A0 02 CB 03 04 03 2C 03 67 03 80 03 93 + 39 01 00 00 00 00 0D BB 03 97 03 9A 03 9C 03 B2 03 D0 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-15 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 36 00 4F 00 66 00 79 00 8C 00 9E + 39 00 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 52 01 83 01 D0 02 0B 02 0D + 39 00 00 00 00 00 11 B2 02 49 02 8E 02 BA 02 EF 03 0F 03 3F 03 4C 03 5E + 39 00 00 00 00 00 0D B3 03 6C 03 81 03 9A 03 B5 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 F0 00 F5 00 FF 01 08 01 11 01 19 01 21 01 29 + 39 00 00 00 00 00 11 B5 01 31 01 4C 01 65 01 8F 01 B2 01 EE 02 21 02 23 + 39 00 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FB 03 21 03 4D 03 5A 03 68 + 39 00 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 00 C6 00 CD 00 D9 00 E5 00 F0 00 FA 01 04 01 0E + 39 00 00 00 00 00 11 B9 01 16 01 36 01 52 01 82 01 A8 01 E7 02 1C 02 1E + 39 00 00 00 00 00 11 BA 02 56 02 9A 02 C6 02 FC 03 26 03 5C 03 72 03 99 + 39 00 00 00 00 00 0D BB 03 AD 03 B3 03 B5 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 0B 00 1C 00 36 00 4F 00 66 00 79 00 8C 00 9E + 39 00 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 52 01 83 01 D0 02 0B 02 0D + 39 00 00 00 00 00 11 B2 02 49 02 8E 02 BA 02 EF 03 0F 03 3F 03 4C 03 5E + 39 00 00 00 00 00 0D B3 03 6C 03 81 03 9A 03 B5 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 F0 00 F5 00 FF 01 08 01 11 01 19 01 21 01 29 + 39 00 00 00 00 00 11 B5 01 31 01 4C 01 65 01 8F 01 B2 01 EE 02 21 02 23 + 39 00 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FB 03 21 03 4D 03 5A 03 68 + 39 00 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 00 C6 00 CD 00 D9 00 E5 00 F0 00 FA 01 04 01 0E + 39 00 00 00 00 00 11 B9 01 16 01 36 01 52 01 82 01 A8 01 E7 02 1C 02 1E + 39 00 00 00 00 00 11 BA 02 56 02 9A 02 C6 02 FC 03 26 03 5C 03 72 03 99 + 39 00 00 00 00 00 0D BB 03 AD 03 B3 03 B5 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-15 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 36 00 4F 00 66 00 79 00 8C 00 9E + 39 01 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 52 01 83 01 D0 02 0B 02 0D + 39 01 00 00 00 00 11 B2 02 49 02 8E 02 BA 02 EF 03 0F 03 3F 03 4C 03 5E + 39 01 00 00 00 00 0D B3 03 6C 03 81 03 9A 03 B5 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 F0 00 F5 00 FF 01 08 01 11 01 19 01 21 01 29 + 39 01 00 00 00 00 11 B5 01 31 01 4C 01 65 01 8F 01 B2 01 EE 02 21 02 23 + 39 01 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FB 03 21 03 4D 03 5A 03 68 + 39 01 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 00 C6 00 CD 00 D9 00 E5 00 F0 00 FA 01 04 01 0E + 39 01 00 00 00 00 11 B9 01 16 01 36 01 52 01 82 01 A8 01 E7 02 1C 02 1E + 39 01 00 00 00 00 11 BA 02 56 02 9A 02 C6 02 FC 03 26 03 5C 03 72 03 99 + 39 01 00 00 00 00 0D BB 03 AD 03 B3 03 B5 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 0B 00 1C 00 36 00 4F 00 66 00 79 00 8C 00 9E + 39 01 00 00 00 00 11 B1 00 AD 00 E3 01 0E 01 52 01 83 01 D0 02 0B 02 0D + 39 01 00 00 00 00 11 B2 02 49 02 8E 02 BA 02 EF 03 0F 03 3F 03 4C 03 5E + 39 01 00 00 00 00 0D B3 03 6C 03 81 03 9A 03 B5 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 F0 00 F5 00 FF 01 08 01 11 01 19 01 21 01 29 + 39 01 00 00 00 00 11 B5 01 31 01 4C 01 65 01 8F 01 B2 01 EE 02 21 02 23 + 39 01 00 00 00 00 11 B6 02 5A 02 9C 02 C7 02 FB 03 21 03 4D 03 5A 03 68 + 39 01 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 00 C6 00 CD 00 D9 00 E5 00 F0 00 FA 01 04 01 0E + 39 01 00 00 00 00 11 B9 01 16 01 36 01 52 01 82 01 A8 01 E7 02 1C 02 1E + 39 01 00 00 00 00 11 BA 02 56 02 9A 02 C6 02 FC 03 26 03 5C 03 72 03 99 + 39 01 00 00 00 00 0D BB 03 AD 03 B3 03 B5 03 BF 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-16 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 68 00 7D 00 90 00 A1 + 39 00 00 00 00 00 11 B1 00 B3 00 E9 01 15 01 55 01 88 01 D5 02 10 02 13 + 39 00 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 15 03 40 03 50 03 60 + 39 00 00 00 00 00 0D B3 03 73 03 87 03 9E 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 01 1B 01 1F 01 27 01 2F 01 36 01 3D 01 44 01 4A + 39 00 00 00 00 00 11 B5 01 51 01 69 01 7E 01 A4 01 C4 01 FA 02 2D 02 2F + 39 00 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 05 03 28 03 52 03 5E 03 6C + 39 00 00 00 00 00 0D B7 03 7B 03 8D 03 A1 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 00 C5 00 CC 00 D9 00 E5 00 F0 00 FB 01 05 01 0F + 39 00 00 00 00 00 11 B9 01 19 01 3A 01 57 01 85 01 AC 01 EC 02 21 02 23 + 39 00 00 00 00 00 11 BA 02 5C 02 9F 02 CA 03 03 03 2A 03 61 03 7A 03 8D + 39 00 00 00 00 00 0D BB 03 91 03 93 03 9B 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 68 00 7D 00 90 00 A1 + 39 00 00 00 00 00 11 B1 00 B3 00 E9 01 15 01 55 01 88 01 D5 02 10 02 13 + 39 00 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 15 03 40 03 50 03 60 + 39 00 00 00 00 00 0D B3 03 73 03 87 03 9E 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 01 1B 01 1F 01 27 01 2F 01 36 01 3D 01 44 01 4A + 39 00 00 00 00 00 11 B5 01 51 01 69 01 7E 01 A4 01 C4 01 FA 02 2D 02 2F + 39 00 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 05 03 28 03 52 03 5E 03 6C + 39 00 00 00 00 00 0D B7 03 7B 03 8D 03 A1 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 00 C5 00 CC 00 D9 00 E5 00 F0 00 FB 01 05 01 0F + 39 00 00 00 00 00 11 B9 01 19 01 3A 01 57 01 85 01 AC 01 EC 02 21 02 23 + 39 00 00 00 00 00 11 BA 02 5C 02 9F 02 CA 03 03 03 2A 03 61 03 7A 03 8D + 39 00 00 00 00 00 0D BB 03 91 03 93 03 9B 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-16 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 68 00 7D 00 90 00 A1 + 39 01 00 00 00 00 11 B1 00 B3 00 E9 01 15 01 55 01 88 01 D5 02 10 02 13 + 39 01 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 15 03 40 03 50 03 60 + 39 01 00 00 00 00 0D B3 03 73 03 87 03 9E 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 01 1B 01 1F 01 27 01 2F 01 36 01 3D 01 44 01 4A + 39 01 00 00 00 00 11 B5 01 51 01 69 01 7E 01 A4 01 C4 01 FA 02 2D 02 2F + 39 01 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 05 03 28 03 52 03 5E 03 6C + 39 01 00 00 00 00 0D B7 03 7B 03 8D 03 A1 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 00 C5 00 CC 00 D9 00 E5 00 F0 00 FB 01 05 01 0F + 39 01 00 00 00 00 11 B9 01 19 01 3A 01 57 01 85 01 AC 01 EC 02 21 02 23 + 39 01 00 00 00 00 11 BA 02 5C 02 9F 02 CA 03 03 03 2A 03 61 03 7A 03 8D + 39 01 00 00 00 00 0D BB 03 91 03 93 03 9B 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 09 00 1B 00 39 00 53 00 68 00 7D 00 90 00 A1 + 39 01 00 00 00 00 11 B1 00 B3 00 E9 01 15 01 55 01 88 01 D5 02 10 02 13 + 39 01 00 00 00 00 11 B2 02 4F 02 93 02 BE 02 F5 03 15 03 40 03 50 03 60 + 39 01 00 00 00 00 0D B3 03 73 03 87 03 9E 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 01 1B 01 1F 01 27 01 2F 01 36 01 3D 01 44 01 4A + 39 01 00 00 00 00 11 B5 01 51 01 69 01 7E 01 A4 01 C4 01 FA 02 2D 02 2F + 39 01 00 00 00 00 11 B6 02 65 02 A6 02 D0 03 05 03 28 03 52 03 5E 03 6C + 39 01 00 00 00 00 0D B7 03 7B 03 8D 03 A1 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 00 C5 00 CC 00 D9 00 E5 00 F0 00 FB 01 05 01 0F + 39 01 00 00 00 00 11 B9 01 19 01 3A 01 57 01 85 01 AC 01 EC 02 21 02 23 + 39 01 00 00 00 00 11 BA 02 5C 02 9F 02 CA 03 03 03 2A 03 61 03 7A 03 8D + 39 01 00 00 00 00 0D BB 03 91 03 93 03 9B 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-17 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 01 14 01 18 01 20 01 27 01 2F 01 36 01 3D 01 43 + 39 00 00 00 00 00 11 B1 01 4A 01 62 01 78 01 9E 01 BF 01 F5 02 29 02 2B + 39 00 00 00 00 00 11 B2 02 61 02 A3 02 CE 03 01 03 27 03 54 03 5E 03 6B + 39 00 00 00 00 00 0D B3 03 7A 03 8B 03 A0 03 B9 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 63 00 77 00 89 00 99 + 39 00 00 00 00 00 11 B5 00 AB 00 E0 01 09 01 4A 01 7C 01 CA 02 06 02 08 + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B6 02 EE 03 10 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 DB 00 E1 00 EC 00 F6 01 00 01 09 01 12 01 1A + 39 00 00 00 00 00 11 B9 01 23 01 41 01 5A 01 86 01 AB 01 E9 02 1E 02 20 + 39 00 00 00 00 00 11 BA 02 58 02 9C 02 C8 02 FF 03 2A 03 65 03 79 03 89 + 39 00 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 01 14 01 18 01 20 01 27 01 2F 01 36 01 3D 01 43 + 39 00 00 00 00 00 11 B1 01 4A 01 62 01 78 01 9E 01 BF 01 F5 02 29 02 2B + 39 00 00 00 00 00 11 B2 02 61 02 A3 02 CE 03 01 03 27 03 54 03 5E 03 6B + 39 00 00 00 00 00 0D B3 03 7A 03 8B 03 A0 03 B9 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 63 00 77 00 89 00 99 + 39 00 00 00 00 00 11 B5 00 AB 00 E0 01 09 01 4A 01 7C 01 CA 02 06 02 08 + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B6 02 EE 03 10 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 DB 00 E1 00 EC 00 F6 01 00 01 09 01 12 01 1A + 39 00 00 00 00 00 11 B9 01 23 01 41 01 5A 01 86 01 AB 01 E9 02 1E 02 20 + 39 00 00 00 00 00 11 BA 02 58 02 9C 02 C8 02 FF 03 2A 03 65 03 79 03 89 + 39 00 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-17 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 01 14 01 18 01 20 01 27 01 2F 01 36 01 3D 01 43 + 39 01 00 00 00 00 11 B1 01 4A 01 62 01 78 01 9E 01 BF 01 F5 02 29 02 2B + 39 01 00 00 00 00 11 B2 02 61 02 A3 02 CE 03 01 03 27 03 54 03 5E 03 6B + 39 01 00 00 00 00 0D B3 03 7A 03 8B 03 A0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 63 00 77 00 89 00 99 + 39 01 00 00 00 00 11 B5 00 AB 00 E0 01 09 01 4A 01 7C 01 CA 02 06 02 08 + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B6 02 EE 03 10 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 DB 00 E1 00 EC 00 F6 01 00 01 09 01 12 01 1A + 39 01 00 00 00 00 11 B9 01 23 01 41 01 5A 01 86 01 AB 01 E9 02 1E 02 20 + 39 01 00 00 00 00 11 BA 02 58 02 9C 02 C8 02 FF 03 2A 03 65 03 79 03 89 + 39 01 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 01 14 01 18 01 20 01 27 01 2F 01 36 01 3D 01 43 + 39 01 00 00 00 00 11 B1 01 4A 01 62 01 78 01 9E 01 BF 01 F5 02 29 02 2B + 39 01 00 00 00 00 11 B2 02 61 02 A3 02 CE 03 01 03 27 03 54 03 5E 03 6B + 39 01 00 00 00 00 0D B3 03 7A 03 8B 03 A0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 35 00 4D 00 63 00 77 00 89 00 99 + 39 01 00 00 00 00 11 B5 00 AB 00 E0 01 09 01 4A 01 7C 01 CA 02 06 02 08 + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B6 02 EE 03 10 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 97 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 DB 00 E1 00 EC 00 F6 01 00 01 09 01 12 01 1A + 39 01 00 00 00 00 11 B9 01 23 01 41 01 5A 01 86 01 AB 01 E9 02 1E 02 20 + 39 01 00 00 00 00 11 BA 02 58 02 9C 02 C8 02 FF 03 2A 03 65 03 79 03 89 + 39 01 00 00 00 00 0D BB 03 8B 03 8F 03 A4 03 BC 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-18 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 DC 00 E2 00 EC 00 F7 01 00 01 0A 01 12 01 1B + 39 00 00 00 00 00 11 B1 01 23 01 41 01 5B 01 87 01 AD 01 EA 02 20 02 22 + 39 00 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 21 03 4D 03 59 03 67 + 39 00 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 18 00 35 00 4C 00 61 00 77 00 8A 00 9B + 39 00 00 00 00 00 11 B5 00 A9 00 E1 01 09 01 4B 01 80 01 CA 02 07 02 0A + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EE 03 10 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 84 00 8D 00 9F 00 AE 00 BC 00 CB 00 D8 00 E4 + 39 00 00 00 00 00 11 B9 00 EE 01 17 01 36 01 6C 01 99 01 DB 02 14 02 17 + 39 00 00 00 00 00 11 BA 02 50 02 94 02 C1 02 F9 03 22 03 5A 03 6E 03 89 + 39 00 00 00 00 00 0D BB 03 A6 03 AE 03 B0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 DC 00 E2 00 EC 00 F7 01 00 01 0A 01 12 01 1B + 39 00 00 00 00 00 11 B1 01 23 01 41 01 5B 01 87 01 AD 01 EA 02 20 02 22 + 39 00 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 21 03 4D 03 59 03 67 + 39 00 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 18 00 35 00 4C 00 61 00 77 00 8A 00 9B + 39 00 00 00 00 00 11 B5 00 A9 00 E1 01 09 01 4B 01 80 01 CA 02 07 02 0A + 39 00 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EE 03 10 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 84 00 8D 00 9F 00 AE 00 BC 00 CB 00 D8 00 E4 + 39 00 00 00 00 00 11 B9 00 EE 01 17 01 36 01 6C 01 99 01 DB 02 14 02 17 + 39 00 00 00 00 00 11 BA 02 50 02 94 02 C1 02 F9 03 22 03 5A 03 6E 03 89 + 39 00 00 00 00 00 0D BB 03 A6 03 AE 03 B0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-18 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 DC 00 E2 00 EC 00 F7 01 00 01 0A 01 12 01 1B + 39 01 00 00 00 00 11 B1 01 23 01 41 01 5B 01 87 01 AD 01 EA 02 20 02 22 + 39 01 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 21 03 4D 03 59 03 67 + 39 01 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 18 00 35 00 4C 00 61 00 77 00 8A 00 9B + 39 01 00 00 00 00 11 B5 00 A9 00 E1 01 09 01 4B 01 80 01 CA 02 07 02 0A + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EE 03 10 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 84 00 8D 00 9F 00 AE 00 BC 00 CB 00 D8 00 E4 + 39 01 00 00 00 00 11 B9 00 EE 01 17 01 36 01 6C 01 99 01 DB 02 14 02 17 + 39 01 00 00 00 00 11 BA 02 50 02 94 02 C1 02 F9 03 22 03 5A 03 6E 03 89 + 39 01 00 00 00 00 0D BB 03 A6 03 AE 03 B0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 DC 00 E2 00 EC 00 F7 01 00 01 0A 01 12 01 1B + 39 01 00 00 00 00 11 B1 01 23 01 41 01 5B 01 87 01 AD 01 EA 02 20 02 22 + 39 01 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 21 03 4D 03 59 03 67 + 39 01 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 18 00 35 00 4C 00 61 00 77 00 8A 00 9B + 39 01 00 00 00 00 11 B5 00 A9 00 E1 01 09 01 4B 01 80 01 CA 02 07 02 0A + 39 01 00 00 00 00 11 B6 02 45 02 8A 02 B7 02 EE 03 10 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6E 03 81 03 98 03 B4 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 84 00 8D 00 9F 00 AE 00 BC 00 CB 00 D8 00 E4 + 39 01 00 00 00 00 11 B9 00 EE 01 17 01 36 01 6C 01 99 01 DB 02 14 02 17 + 39 01 00 00 00 00 11 BA 02 50 02 94 02 C1 02 F9 03 22 03 5A 03 6E 03 89 + 39 01 00 00 00 00 0D BB 03 A6 03 AE 03 B0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-19 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 55 00 60 00 74 00 87 00 99 00 A9 00 B8 00 C7 + 39 00 00 00 00 00 11 B1 00 D4 01 03 01 29 01 64 01 93 01 DC 02 16 02 18 + 39 00 00 00 00 00 11 B2 02 53 02 96 02 C2 02 F8 03 1A 03 49 03 54 03 65 + 39 00 00 00 00 00 0D B3 03 74 03 85 03 9A 03 B4 03 D1 03 D7 + 39 00 00 00 00 00 11 B4 00 67 00 71 00 84 00 96 00 A7 00 B6 00 C4 00 D2 + 39 00 00 00 00 00 11 B5 00 DE 01 0A 01 2E 01 67 01 94 01 DB 02 15 02 17 + 39 00 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 49 03 55 03 64 + 39 00 00 00 00 00 0D B7 03 73 03 85 03 9B 03 B5 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 00 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 58 01 8A 01 D6 02 12 02 14 + 39 00 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 5B 03 6D 03 8D + 39 00 00 00 00 00 0D BB 03 A1 03 A3 03 A5 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 55 00 60 00 74 00 87 00 99 00 A9 00 B8 00 C7 + 39 00 00 00 00 00 11 B1 00 D4 01 03 01 29 01 64 01 93 01 DC 02 16 02 18 + 39 00 00 00 00 00 11 B2 02 53 02 96 02 C2 02 F8 03 1A 03 49 03 54 03 65 + 39 00 00 00 00 00 0D B3 03 74 03 85 03 9A 03 B4 03 D1 03 D7 + 39 00 00 00 00 00 11 B4 00 67 00 71 00 84 00 96 00 A7 00 B6 00 C4 00 D2 + 39 00 00 00 00 00 11 B5 00 DE 01 0A 01 2E 01 67 01 94 01 DB 02 15 02 17 + 39 00 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 49 03 55 03 64 + 39 00 00 00 00 00 0D B7 03 73 03 85 03 9B 03 B5 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 00 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 58 01 8A 01 D6 02 12 02 14 + 39 00 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 5B 03 6D 03 8D + 39 00 00 00 00 00 0D BB 03 A1 03 A3 03 A5 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-19 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 55 00 60 00 74 00 87 00 99 00 A9 00 B8 00 C7 + 39 01 00 00 00 00 11 B1 00 D4 01 03 01 29 01 64 01 93 01 DC 02 16 02 18 + 39 01 00 00 00 00 11 B2 02 53 02 96 02 C2 02 F8 03 1A 03 49 03 54 03 65 + 39 01 00 00 00 00 0D B3 03 74 03 85 03 9A 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B4 00 67 00 71 00 84 00 96 00 A7 00 B6 00 C4 00 D2 + 39 01 00 00 00 00 11 B5 00 DE 01 0A 01 2E 01 67 01 94 01 DB 02 15 02 17 + 39 01 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 49 03 55 03 64 + 39 01 00 00 00 00 0D B7 03 73 03 85 03 9B 03 B5 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 01 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 58 01 8A 01 D6 02 12 02 14 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 5B 03 6D 03 8D + 39 01 00 00 00 00 0D BB 03 A1 03 A3 03 A5 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 55 00 60 00 74 00 87 00 99 00 A9 00 B8 00 C7 + 39 01 00 00 00 00 11 B1 00 D4 01 03 01 29 01 64 01 93 01 DC 02 16 02 18 + 39 01 00 00 00 00 11 B2 02 53 02 96 02 C2 02 F8 03 1A 03 49 03 54 03 65 + 39 01 00 00 00 00 0D B3 03 74 03 85 03 9A 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B4 00 67 00 71 00 84 00 96 00 A7 00 B6 00 C4 00 D2 + 39 01 00 00 00 00 11 B5 00 DE 01 0A 01 2E 01 67 01 94 01 DB 02 15 02 17 + 39 01 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 49 03 55 03 64 + 39 01 00 00 00 00 0D B7 03 73 03 85 03 9B 03 B5 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 01 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 58 01 8A 01 D6 02 12 02 14 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 5B 03 6D 03 8D + 39 01 00 00 00 00 0D BB 03 A1 03 A3 03 A5 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-20 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 A9 00 B1 00 BF 00 CC 00 D9 00 E5 00 F0 00 FB + 39 00 00 00 00 00 11 B1 01 05 01 29 01 48 01 7B 01 A5 01 E8 02 1F 02 20 + 39 00 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 20 03 4B 03 57 03 68 + 39 00 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 B1 00 B8 00 C6 00 D3 00 DF 00 EA 00 F5 00 FF + 39 00 00 00 00 00 11 B5 01 09 01 2B 01 4A 01 7B 01 A5 01 E6 02 1C 02 1E + 39 00 00 00 00 00 11 B6 02 56 02 99 02 C4 02 FA 03 1D 03 4B 03 58 03 66 + 39 00 00 00 00 00 0D B7 03 75 03 87 03 9D 03 B8 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 09 00 1A 00 39 00 53 00 6B 00 81 00 94 00 A6 + 39 00 00 00 00 00 11 B9 00 B6 00 EC 01 17 01 58 01 8C 01 D8 02 12 02 14 + 39 00 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 F9 03 21 03 58 03 6B 03 88 + 39 00 00 00 00 00 0D BB 03 9B 03 A4 03 AA 03 B8 03 D1 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 A9 00 B1 00 BF 00 CC 00 D9 00 E5 00 F0 00 FB + 39 00 00 00 00 00 11 B1 01 05 01 29 01 48 01 7B 01 A5 01 E8 02 1F 02 20 + 39 00 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 20 03 4B 03 57 03 68 + 39 00 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 B1 00 B8 00 C6 00 D3 00 DF 00 EA 00 F5 00 FF + 39 00 00 00 00 00 11 B5 01 09 01 2B 01 4A 01 7B 01 A5 01 E6 02 1C 02 1E + 39 00 00 00 00 00 11 B6 02 56 02 99 02 C4 02 FA 03 1D 03 4B 03 58 03 66 + 39 00 00 00 00 00 0D B7 03 75 03 87 03 9D 03 B8 03 D2 03 D7 + 39 00 00 00 00 00 11 B8 00 09 00 1A 00 39 00 53 00 6B 00 81 00 94 00 A6 + 39 00 00 00 00 00 11 B9 00 B6 00 EC 01 17 01 58 01 8C 01 D8 02 12 02 14 + 39 00 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 F9 03 21 03 58 03 6B 03 88 + 39 00 00 00 00 00 0D BB 03 9B 03 A4 03 AA 03 B8 03 D1 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-20 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 A9 00 B1 00 BF 00 CC 00 D9 00 E5 00 F0 00 FB + 39 01 00 00 00 00 11 B1 01 05 01 29 01 48 01 7B 01 A5 01 E8 02 1F 02 20 + 39 01 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 20 03 4B 03 57 03 68 + 39 01 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 B1 00 B8 00 C6 00 D3 00 DF 00 EA 00 F5 00 FF + 39 01 00 00 00 00 11 B5 01 09 01 2B 01 4A 01 7B 01 A5 01 E6 02 1C 02 1E + 39 01 00 00 00 00 11 B6 02 56 02 99 02 C4 02 FA 03 1D 03 4B 03 58 03 66 + 39 01 00 00 00 00 0D B7 03 75 03 87 03 9D 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1A 00 39 00 53 00 6B 00 81 00 94 00 A6 + 39 01 00 00 00 00 11 B9 00 B6 00 EC 01 17 01 58 01 8C 01 D8 02 12 02 14 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 F9 03 21 03 58 03 6B 03 88 + 39 01 00 00 00 00 0D BB 03 9B 03 A4 03 AA 03 B8 03 D1 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 A9 00 B1 00 BF 00 CC 00 D9 00 E5 00 F0 00 FB + 39 01 00 00 00 00 11 B1 01 05 01 29 01 48 01 7B 01 A5 01 E8 02 1F 02 20 + 39 01 00 00 00 00 11 B2 02 59 02 9B 02 C7 02 FC 03 20 03 4B 03 57 03 68 + 39 01 00 00 00 00 0D B3 03 77 03 8A 03 A0 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 B1 00 B8 00 C6 00 D3 00 DF 00 EA 00 F5 00 FF + 39 01 00 00 00 00 11 B5 01 09 01 2B 01 4A 01 7B 01 A5 01 E6 02 1C 02 1E + 39 01 00 00 00 00 11 B6 02 56 02 99 02 C4 02 FA 03 1D 03 4B 03 58 03 66 + 39 01 00 00 00 00 0D B7 03 75 03 87 03 9D 03 B8 03 D2 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1A 00 39 00 53 00 6B 00 81 00 94 00 A6 + 39 01 00 00 00 00 11 B9 00 B6 00 EC 01 17 01 58 01 8C 01 D8 02 12 02 14 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 F9 03 21 03 58 03 6B 03 88 + 39 01 00 00 00 00 0D BB 03 9B 03 A4 03 AA 03 B8 03 D1 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-21 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 01 57 01 5A 01 5F 01 64 01 6A 01 6F 01 74 01 78 + 39 00 00 00 00 00 11 B1 01 7D 01 8F 01 A0 01 BE 01 D9 02 09 02 39 02 3A + 39 00 00 00 00 00 11 B2 02 6E 02 AF 02 D9 03 0A 03 2F 03 5E 03 6B 03 74 + 39 00 00 00 00 00 0D B3 03 80 03 90 03 A4 03 BC 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 33 00 4C 00 63 00 77 00 8A 00 9A + 39 00 00 00 00 00 11 B5 00 AA 00 DF 01 0A 01 4A 01 7D 01 CA 02 07 02 08 + 39 00 00 00 00 00 11 B6 02 44 02 8A 02 B7 02 EE 03 0E 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6B 03 7F 03 97 03 B2 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 E0 00 E6 00 F0 00 FA 01 04 01 0D 01 16 01 1E + 39 00 00 00 00 00 11 B9 01 26 01 43 01 5D 01 88 01 AD 01 EA 02 1F 02 20 + 39 00 00 00 00 00 11 BA 02 58 02 9C 02 C9 02 FF 03 28 03 66 03 7E 03 AC + 39 00 00 00 00 00 0D BB 03 C7 03 CA 03 CC 03 CE 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 01 57 01 5A 01 5F 01 64 01 6A 01 6F 01 74 01 78 + 39 00 00 00 00 00 11 B1 01 7D 01 8F 01 A0 01 BE 01 D9 02 09 02 39 02 3A + 39 00 00 00 00 00 11 B2 02 6E 02 AF 02 D9 03 0A 03 2F 03 5E 03 6B 03 74 + 39 00 00 00 00 00 0D B3 03 80 03 90 03 A4 03 BC 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 33 00 4C 00 63 00 77 00 8A 00 9A + 39 00 00 00 00 00 11 B5 00 AA 00 DF 01 0A 01 4A 01 7D 01 CA 02 07 02 08 + 39 00 00 00 00 00 11 B6 02 44 02 8A 02 B7 02 EE 03 0E 03 42 03 4F 03 5E + 39 00 00 00 00 00 0D B7 03 6B 03 7F 03 97 03 B2 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 E0 00 E6 00 F0 00 FA 01 04 01 0D 01 16 01 1E + 39 00 00 00 00 00 11 B9 01 26 01 43 01 5D 01 88 01 AD 01 EA 02 1F 02 20 + 39 00 00 00 00 00 11 BA 02 58 02 9C 02 C9 02 FF 03 28 03 66 03 7E 03 AC + 39 00 00 00 00 00 0D BB 03 C7 03 CA 03 CC 03 CE 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-21 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 01 57 01 5A 01 5F 01 64 01 6A 01 6F 01 74 01 78 + 39 01 00 00 00 00 11 B1 01 7D 01 8F 01 A0 01 BE 01 D9 02 09 02 39 02 3A + 39 01 00 00 00 00 11 B2 02 6E 02 AF 02 D9 03 0A 03 2F 03 5E 03 6B 03 74 + 39 01 00 00 00 00 0D B3 03 80 03 90 03 A4 03 BC 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 33 00 4C 00 63 00 77 00 8A 00 9A + 39 01 00 00 00 00 11 B5 00 AA 00 DF 01 0A 01 4A 01 7D 01 CA 02 07 02 08 + 39 01 00 00 00 00 11 B6 02 44 02 8A 02 B7 02 EE 03 0E 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6B 03 7F 03 97 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 E0 00 E6 00 F0 00 FA 01 04 01 0D 01 16 01 1E + 39 01 00 00 00 00 11 B9 01 26 01 43 01 5D 01 88 01 AD 01 EA 02 1F 02 20 + 39 01 00 00 00 00 11 BA 02 58 02 9C 02 C9 02 FF 03 28 03 66 03 7E 03 AC + 39 01 00 00 00 00 0D BB 03 C7 03 CA 03 CC 03 CE 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 01 57 01 5A 01 5F 01 64 01 6A 01 6F 01 74 01 78 + 39 01 00 00 00 00 11 B1 01 7D 01 8F 01 A0 01 BE 01 D9 02 09 02 39 02 3A + 39 01 00 00 00 00 11 B2 02 6E 02 AF 02 D9 03 0A 03 2F 03 5E 03 6B 03 74 + 39 01 00 00 00 00 0D B3 03 80 03 90 03 A4 03 BC 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 33 00 4C 00 63 00 77 00 8A 00 9A + 39 01 00 00 00 00 11 B5 00 AA 00 DF 01 0A 01 4A 01 7D 01 CA 02 07 02 08 + 39 01 00 00 00 00 11 B6 02 44 02 8A 02 B7 02 EE 03 0E 03 42 03 4F 03 5E + 39 01 00 00 00 00 0D B7 03 6B 03 7F 03 97 03 B2 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 E0 00 E6 00 F0 00 FA 01 04 01 0D 01 16 01 1E + 39 01 00 00 00 00 11 B9 01 26 01 43 01 5D 01 88 01 AD 01 EA 02 1F 02 20 + 39 01 00 00 00 00 11 BA 02 58 02 9C 02 C9 02 FF 03 28 03 66 03 7E 03 AC + 39 01 00 00 00 00 0D BB 03 C7 03 CA 03 CC 03 CE 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-22 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 01 3E 01 41 01 48 01 4E 01 54 01 5A 01 60 01 66 + 39 00 00 00 00 00 11 B1 01 6B 01 80 01 93 01 B4 01 D2 02 05 02 36 02 38 + 39 00 00 00 00 00 11 B2 02 6C 02 AC 02 D6 03 06 03 2C 03 58 03 65 03 6F + 39 00 00 00 00 00 0D B3 03 7E 03 8F 03 A3 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 37 00 4F 00 65 00 7A 00 8C 00 9F + 39 00 00 00 00 00 11 B5 00 AF 00 E5 01 0F 01 51 01 84 01 D0 02 0C 02 10 + 39 00 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F0 03 10 03 43 03 51 03 5F + 39 00 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 8F 00 97 00 A9 00 B8 00 C6 00 D4 00 E0 00 ED + 39 00 00 00 00 00 11 B9 00 F8 01 1F 01 3F 01 74 01 9F 01 E2 02 1A 02 1D + 39 00 00 00 00 00 11 BA 02 55 02 98 02 C5 02 FB 03 25 03 60 03 79 03 9D + 39 00 00 00 00 00 0D BB 03 CC 03 CE 03 D0 03 D2 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 01 3E 01 41 01 48 01 4E 01 54 01 5A 01 60 01 66 + 39 00 00 00 00 00 11 B1 01 6B 01 80 01 93 01 B4 01 D2 02 05 02 36 02 38 + 39 00 00 00 00 00 11 B2 02 6C 02 AC 02 D6 03 06 03 2C 03 58 03 65 03 6F + 39 00 00 00 00 00 0D B3 03 7E 03 8F 03 A3 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 09 00 19 00 37 00 4F 00 65 00 7A 00 8C 00 9F + 39 00 00 00 00 00 11 B5 00 AF 00 E5 01 0F 01 51 01 84 01 D0 02 0C 02 10 + 39 00 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F0 03 10 03 43 03 51 03 5F + 39 00 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 8F 00 97 00 A9 00 B8 00 C6 00 D4 00 E0 00 ED + 39 00 00 00 00 00 11 B9 00 F8 01 1F 01 3F 01 74 01 9F 01 E2 02 1A 02 1D + 39 00 00 00 00 00 11 BA 02 55 02 98 02 C5 02 FB 03 25 03 60 03 79 03 9D + 39 00 00 00 00 00 0D BB 03 CC 03 CE 03 D0 03 D2 03 D4 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-22 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 01 3E 01 41 01 48 01 4E 01 54 01 5A 01 60 01 66 + 39 01 00 00 00 00 11 B1 01 6B 01 80 01 93 01 B4 01 D2 02 05 02 36 02 38 + 39 01 00 00 00 00 11 B2 02 6C 02 AC 02 D6 03 06 03 2C 03 58 03 65 03 6F + 39 01 00 00 00 00 0D B3 03 7E 03 8F 03 A3 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 37 00 4F 00 65 00 7A 00 8C 00 9F + 39 01 00 00 00 00 11 B5 00 AF 00 E5 01 0F 01 51 01 84 01 D0 02 0C 02 10 + 39 01 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F0 03 10 03 43 03 51 03 5F + 39 01 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 8F 00 97 00 A9 00 B8 00 C6 00 D4 00 E0 00 ED + 39 01 00 00 00 00 11 B9 00 F8 01 1F 01 3F 01 74 01 9F 01 E2 02 1A 02 1D + 39 01 00 00 00 00 11 BA 02 55 02 98 02 C5 02 FB 03 25 03 60 03 79 03 9D + 39 01 00 00 00 00 0D BB 03 CC 03 CE 03 D0 03 D2 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 01 3E 01 41 01 48 01 4E 01 54 01 5A 01 60 01 66 + 39 01 00 00 00 00 11 B1 01 6B 01 80 01 93 01 B4 01 D2 02 05 02 36 02 38 + 39 01 00 00 00 00 11 B2 02 6C 02 AC 02 D6 03 06 03 2C 03 58 03 65 03 6F + 39 01 00 00 00 00 0D B3 03 7E 03 8F 03 A3 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 09 00 19 00 37 00 4F 00 65 00 7A 00 8C 00 9F + 39 01 00 00 00 00 11 B5 00 AF 00 E5 01 0F 01 51 01 84 01 D0 02 0C 02 10 + 39 01 00 00 00 00 11 B6 02 4A 02 8D 02 BA 02 F0 03 10 03 43 03 51 03 5F + 39 01 00 00 00 00 0D B7 03 6F 03 82 03 98 03 B3 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 8F 00 97 00 A9 00 B8 00 C6 00 D4 00 E0 00 ED + 39 01 00 00 00 00 11 B9 00 F8 01 1F 01 3F 01 74 01 9F 01 E2 02 1A 02 1D + 39 01 00 00 00 00 11 BA 02 55 02 98 02 C5 02 FB 03 25 03 60 03 79 03 9D + 39 01 00 00 00 00 0D BB 03 CC 03 CE 03 D0 03 D2 03 D4 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-23 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 FD 01 02 01 0B 01 14 01 1D 01 25 01 2D 01 35 + 39 00 00 00 00 00 11 B1 01 3C 01 57 01 6F 01 98 01 BB 01 F5 02 2A 02 2C + 39 00 00 00 00 00 11 B2 02 63 02 A4 02 CF 03 03 03 27 03 52 03 5E 03 6C + 39 00 00 00 00 00 0D B3 03 7B 03 8B 03 9F 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 65 00 6F 00 83 00 95 00 A5 00 B5 00 C3 00 D0 + 39 00 00 00 00 00 11 B5 00 DD 01 09 01 2D 01 67 01 94 01 DB 02 15 02 17 + 39 00 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 48 03 55 03 63 + 39 00 00 00 00 00 0D B7 03 73 03 85 03 9A 03 B5 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 00 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 59 01 8A 01 D6 02 12 02 14 + 39 00 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 59 03 6D 03 84 + 39 00 00 00 00 00 0D BB 03 99 03 9E 03 A0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 FD 01 02 01 0B 01 14 01 1D 01 25 01 2D 01 35 + 39 00 00 00 00 00 11 B1 01 3C 01 57 01 6F 01 98 01 BB 01 F5 02 2A 02 2C + 39 00 00 00 00 00 11 B2 02 63 02 A4 02 CF 03 03 03 27 03 52 03 5E 03 6C + 39 00 00 00 00 00 0D B3 03 7B 03 8B 03 9F 03 B7 03 D2 03 D7 + 39 00 00 00 00 00 11 B4 00 65 00 6F 00 83 00 95 00 A5 00 B5 00 C3 00 D0 + 39 00 00 00 00 00 11 B5 00 DD 01 09 01 2D 01 67 01 94 01 DB 02 15 02 17 + 39 00 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 48 03 55 03 63 + 39 00 00 00 00 00 0D B7 03 73 03 85 03 9A 03 B5 03 D1 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 00 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 59 01 8A 01 D6 02 12 02 14 + 39 00 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 59 03 6D 03 84 + 39 00 00 00 00 00 0D BB 03 99 03 9E 03 A0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-23 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 00 FD 01 02 01 0B 01 14 01 1D 01 25 01 2D 01 35 + 39 01 00 00 00 00 11 B1 01 3C 01 57 01 6F 01 98 01 BB 01 F5 02 2A 02 2C + 39 01 00 00 00 00 11 B2 02 63 02 A4 02 CF 03 03 03 27 03 52 03 5E 03 6C + 39 01 00 00 00 00 0D B3 03 7B 03 8B 03 9F 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 65 00 6F 00 83 00 95 00 A5 00 B5 00 C3 00 D0 + 39 01 00 00 00 00 11 B5 00 DD 01 09 01 2D 01 67 01 94 01 DB 02 15 02 17 + 39 01 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 48 03 55 03 63 + 39 01 00 00 00 00 0D B7 03 73 03 85 03 9A 03 B5 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 01 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 59 01 8A 01 D6 02 12 02 14 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 59 03 6D 03 84 + 39 01 00 00 00 00 0D BB 03 99 03 9E 03 A0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 FD 01 02 01 0B 01 14 01 1D 01 25 01 2D 01 35 + 39 01 00 00 00 00 11 B1 01 3C 01 57 01 6F 01 98 01 BB 01 F5 02 2A 02 2C + 39 01 00 00 00 00 11 B2 02 63 02 A4 02 CF 03 03 03 27 03 52 03 5E 03 6C + 39 01 00 00 00 00 0D B3 03 7B 03 8B 03 9F 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 65 00 6F 00 83 00 95 00 A5 00 B5 00 C3 00 D0 + 39 01 00 00 00 00 11 B5 00 DD 01 09 01 2D 01 67 01 94 01 DB 02 15 02 17 + 39 01 00 00 00 00 11 B6 02 51 02 94 02 C0 02 F7 03 19 03 48 03 55 03 63 + 39 01 00 00 00 00 0D B7 03 73 03 85 03 9A 03 B5 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1E 00 3C 00 55 00 6B 00 80 00 93 00 A4 + 39 01 00 00 00 00 11 B9 00 B4 00 EB 01 16 01 59 01 8A 01 D6 02 12 02 14 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 C0 02 FA 03 21 03 59 03 6D 03 84 + 39 01 00 00 00 00 0D BB 03 99 03 9E 03 A0 03 B9 03 D3 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-24 = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 01 06 01 0B 01 14 01 1C 01 25 01 2D 01 34 01 3C + 39 00 00 00 00 00 11 B1 01 43 01 5D 01 74 01 9C 01 BE 01 F8 02 2C 02 2E + 39 00 00 00 00 00 11 B2 02 64 02 A5 02 CF 03 02 03 28 03 51 03 5E 03 6C + 39 00 00 00 00 00 0D B3 03 7B 03 8D 03 A2 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 C2 00 C9 00 D6 00 E2 00 ED 00 F8 01 02 01 0C + 39 00 00 00 00 00 11 B5 01 15 01 36 01 53 01 82 01 A8 01 E9 02 20 02 21 + 39 00 00 00 00 00 11 B6 02 59 02 9B 02 C6 02 FA 03 21 03 4C 03 59 03 67 + 39 00 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1D 00 3C 00 55 00 6C 00 81 00 94 00 A6 + 39 00 00 00 00 00 11 B9 00 B7 00 EE 01 1A 01 5B 01 8B 01 D7 02 14 02 15 + 39 00 00 00 00 00 11 BA 02 50 02 94 02 C0 02 F8 03 22 03 58 03 6C 03 84 + 39 00 00 00 00 00 0D BB 03 98 03 9E 03 A0 03 B7 03 D1 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 01 06 01 0B 01 14 01 1C 01 25 01 2D 01 34 01 3C + 39 00 00 00 00 00 11 B1 01 43 01 5D 01 74 01 9C 01 BE 01 F8 02 2C 02 2E + 39 00 00 00 00 00 11 B2 02 64 02 A5 02 CF 03 02 03 28 03 51 03 5E 03 6C + 39 00 00 00 00 00 0D B3 03 7B 03 8D 03 A2 03 BB 03 D3 03 D7 + 39 00 00 00 00 00 11 B4 00 C2 00 C9 00 D6 00 E2 00 ED 00 F8 01 02 01 0C + 39 00 00 00 00 00 11 B5 01 15 01 36 01 53 01 82 01 A8 01 E9 02 20 02 21 + 39 00 00 00 00 00 11 B6 02 59 02 9B 02 C6 02 FA 03 21 03 4C 03 59 03 67 + 39 00 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 00 00 00 00 00 11 B8 00 0B 00 1D 00 3C 00 55 00 6C 00 81 00 94 00 A6 + 39 00 00 00 00 00 11 B9 00 B7 00 EE 01 1A 01 5B 01 8B 01 D7 02 14 02 15 + 39 00 00 00 00 00 11 BA 02 50 02 94 02 C0 02 F8 03 22 03 58 03 6C 03 84 + 39 00 00 00 00 00 0D BB 03 98 03 9E 03 A0 03 B7 03 D1 03 D7 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-24 = + [ + 39 01 00 00 00 00 02 FF 25 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 8D 04 + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 30 10 + 39 01 00 00 00 00 02 31 50 + 39 01 00 00 00 00 02 32 2F + 39 01 00 00 00 00 02 94 00 + 39 01 00 00 00 00 02 95 E1 + 39 01 00 00 00 00 02 96 E1 + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 01 00 00 00 00 11 B0 01 06 01 0B 01 14 01 1C 01 25 01 2D 01 34 01 3C + 39 01 00 00 00 00 11 B1 01 43 01 5D 01 74 01 9C 01 BE 01 F8 02 2C 02 2E + 39 01 00 00 00 00 11 B2 02 64 02 A5 02 CF 03 02 03 28 03 51 03 5E 03 6C + 39 01 00 00 00 00 0D B3 03 7B 03 8D 03 A2 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 C2 00 C9 00 D6 00 E2 00 ED 00 F8 01 02 01 0C + 39 01 00 00 00 00 11 B5 01 15 01 36 01 53 01 82 01 A8 01 E9 02 20 02 21 + 39 01 00 00 00 00 11 B6 02 59 02 9B 02 C6 02 FA 03 21 03 4C 03 59 03 67 + 39 01 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1D 00 3C 00 55 00 6C 00 81 00 94 00 A6 + 39 01 00 00 00 00 11 B9 00 B7 00 EE 01 1A 01 5B 01 8B 01 D7 02 14 02 15 + 39 01 00 00 00 00 11 BA 02 50 02 94 02 C0 02 F8 03 22 03 58 03 6C 03 84 + 39 01 00 00 00 00 0D BB 03 98 03 9E 03 A0 03 B7 03 D1 03 D7 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 01 06 01 0B 01 14 01 1C 01 25 01 2D 01 34 01 3C + 39 01 00 00 00 00 11 B1 01 43 01 5D 01 74 01 9C 01 BE 01 F8 02 2C 02 2E + 39 01 00 00 00 00 11 B2 02 64 02 A5 02 CF 03 02 03 28 03 51 03 5E 03 6C + 39 01 00 00 00 00 0D B3 03 7B 03 8D 03 A2 03 BB 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 C2 00 C9 00 D6 00 E2 00 ED 00 F8 01 02 01 0C + 39 01 00 00 00 00 11 B5 01 15 01 36 01 53 01 82 01 A8 01 E9 02 20 02 21 + 39 01 00 00 00 00 11 B6 02 59 02 9B 02 C6 02 FA 03 21 03 4C 03 59 03 67 + 39 01 00 00 00 00 0D B7 03 77 03 89 03 9F 03 BA 03 D3 03 D7 + 39 01 00 00 00 00 11 B8 00 0B 00 1D 00 3C 00 55 00 6C 00 81 00 94 00 A6 + 39 01 00 00 00 00 11 B9 00 B7 00 EE 01 1A 01 5B 01 8B 01 D7 02 14 02 15 + 39 01 00 00 00 00 11 BA 02 50 02 94 02 C0 02 F8 03 22 03 58 03 6C 03 84 + 39 01 00 00 00 00 0D BB 03 98 03 9E 03 A0 03 B7 03 D1 03 D7 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 51 FF + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 FF F0 + 39 01 00 00 00 00 02 5A 02 + 39 01 00 00 00 00 02 FF 10 + 39 01 00 00 00 00 02 36 00 + 39 01 00 00 00 00 02 35 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-dsi-off-command = + [ + 39 01 00 00 00 00 02 FF 10 + 05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-CABC_on-command = [ + 23 01 00 00 00 00 02 FF 23 + 23 00 00 00 00 00 02 07 20 + 23 00 00 00 00 00 02 08 05 + 23 00 00 00 00 00 02 09 00 + 23 00 00 00 00 00 02 10 95 + 23 00 00 00 00 00 02 30 FF + 23 00 00 00 00 00 02 31 FF + 23 00 00 00 00 00 02 32 FF + 23 00 00 00 00 00 02 33 FF + 23 00 00 00 00 00 02 34 FF + 23 00 00 00 00 00 02 35 FF + 23 00 00 00 00 00 02 36 FF + 23 00 00 00 00 00 02 37 FF + 23 00 00 00 00 00 02 38 FF + 23 00 00 00 00 00 02 39 FF + 23 00 00 00 00 00 02 3A FF + 23 00 00 00 00 00 02 3B F9 + 23 00 00 00 00 00 02 3D D9 + 23 00 00 00 00 00 02 3F B9 + 23 00 00 00 00 00 02 40 AB + 23 00 00 00 00 00 02 41 98 + 23 01 00 00 00 00 02 FB 01 + 23 01 00 00 00 00 02 FF 10 + 23 00 00 00 00 00 02 55 81 + 23 00 00 00 00 00 02 53 2C + 23 01 00 00 00 00 02 FB 01 + + ]; + qcom,mdss-dsi-CABC_off-command = [ + 23 01 00 00 00 00 02 FF 10 + 23 00 00 00 00 00 02 53 24 + 23 00 00 00 00 00 02 55 80 + 23 01 00 00 00 00 02 FB 01 + ]; + qcom,mdss-dsi-CE_on-command = [ + + 23 01 00 00 00 00 02 FF 22 + 23 00 00 00 00 00 02 00 54 + 23 00 00 00 00 00 02 01 54 + 23 00 00 00 00 00 02 02 54 + 23 00 00 00 00 00 02 03 54 + 23 00 00 00 00 00 02 04 54 + 23 00 00 00 00 00 02 05 54 + 23 00 00 00 00 00 02 06 54 + 23 00 00 00 00 00 02 07 54 + 23 00 00 00 00 00 02 08 54 + 23 00 00 00 00 00 02 09 54 + 23 00 00 00 00 00 02 0A 54 + 23 00 00 00 00 00 02 0B 54 + 23 00 00 00 00 00 02 0C 54 + 23 00 00 00 00 00 02 0D 54 + 23 00 00 00 00 00 02 0E 54 + 23 00 00 00 00 00 02 0F 54 + 23 00 00 00 00 00 02 10 54 + 23 00 00 00 00 00 02 11 50 + 23 00 00 00 00 00 02 12 60 + 23 00 00 00 00 00 02 13 70 + 23 00 00 00 00 00 02 14 58 + 23 00 00 00 00 00 02 15 68 + 23 00 00 00 00 00 02 16 78 + 23 00 00 00 00 00 02 17 00 + 23 00 00 00 00 00 02 18 40 + 23 00 00 00 00 00 02 19 40 + 23 00 00 00 00 00 02 1A 40 + 23 00 00 00 00 00 02 1B 40 + 23 00 00 00 00 00 02 1C 40 + 23 00 00 00 00 00 02 1D 40 + 23 00 00 00 00 00 02 1E 40 + 23 00 00 00 00 00 02 1F 40 + 23 00 00 00 00 00 02 20 40 + 23 00 00 00 00 00 02 21 3D + 23 00 00 00 00 00 02 22 39 + 23 00 00 00 00 00 02 23 36 + 23 00 00 00 00 00 02 24 32 + 23 00 00 00 00 00 02 25 32 + 23 00 00 00 00 00 02 26 31 + 23 00 00 00 00 00 02 27 2F + 23 00 00 00 00 00 02 28 2D + 23 00 00 00 00 00 02 2D 00 + 23 00 00 00 00 00 02 2F 40 + 23 00 00 00 00 00 02 30 40 + 23 00 00 00 00 00 02 31 40 + 23 00 00 00 00 00 02 32 40 + 23 00 00 00 00 00 02 33 40 + 23 00 00 00 00 00 02 34 40 + 23 00 00 00 00 00 02 35 40 + 23 00 00 00 00 00 02 36 40 + 23 00 00 00 00 00 02 37 40 + 23 00 00 00 00 00 02 38 3E + 23 00 00 00 00 00 02 39 3B + 23 00 00 00 00 00 02 3A 39 + 23 00 00 00 00 00 02 3B 36 + 23 00 00 00 00 00 02 3D 36 + 23 00 00 00 00 00 02 3F 36 + 23 00 00 00 00 00 02 40 36 + 23 00 00 00 00 00 02 41 36 + 23 00 00 00 00 00 02 42 40 + 23 00 00 00 00 00 02 43 40 + 23 00 00 00 00 00 02 44 40 + 23 00 00 00 00 00 02 45 40 + 23 00 00 00 00 00 02 46 40 + 23 00 00 00 00 00 02 47 46 + 23 00 00 00 00 00 02 48 4C + 23 00 00 00 00 00 02 49 50 + 23 00 00 00 00 00 02 4A 52 + 23 00 00 00 00 00 02 4B 52 + 23 00 00 00 00 00 02 4C 50 + 23 00 00 00 00 00 02 4D 4E + 23 00 00 00 00 00 02 4E 4A + 23 00 00 00 00 00 02 4F 46 + 23 00 00 00 00 00 02 50 42 + 23 00 00 00 00 00 02 51 41 + 23 00 00 00 00 00 02 52 40 + 23 00 00 00 00 00 02 53 01 + 23 00 00 00 00 00 02 54 01 + 23 00 00 00 00 00 02 55 89 + 23 00 00 00 00 00 02 56 7F + 23 00 00 00 00 00 02 58 40 + 23 00 00 00 00 00 02 59 40 + 23 00 00 00 00 00 02 5A C2 + 23 00 00 00 00 00 02 5B 44 + 23 00 00 00 00 00 02 5C 43 + 23 00 00 00 00 00 02 5D 43 + 23 00 00 00 00 00 02 5E 42 + 23 00 00 00 00 00 02 5F 44 + 23 00 00 00 00 00 02 60 44 + 23 00 00 00 00 00 02 61 44 + 23 00 00 00 00 00 02 62 42 + 23 00 00 00 00 00 02 63 42 + 23 00 00 00 00 00 02 64 41 + 23 00 00 00 00 00 02 65 40 + 23 00 00 00 00 00 02 66 3F + 23 00 00 00 00 00 02 67 BD + 23 00 00 00 00 00 02 68 BC + 23 00 00 00 00 00 02 69 BD + 23 00 00 00 00 00 02 6A 3F + 23 00 00 00 00 00 02 6B 40 + 23 00 00 00 00 00 02 6C 40 + 23 00 00 00 00 00 02 6D 3F + 23 00 00 00 00 00 02 6E 3E + 23 00 00 00 00 00 02 6F BC + 23 00 00 00 00 00 02 70 8C + 23 00 00 00 00 00 02 71 0E + 23 00 00 00 00 00 02 72 00 + 23 00 00 00 00 00 02 73 16 + 23 00 00 00 00 00 02 74 06 + 23 00 00 00 00 00 02 75 0C + 23 00 00 00 00 00 02 76 03 + 23 00 00 00 00 00 02 77 09 + 23 00 00 00 00 00 02 78 0F + 23 00 00 00 00 00 02 79 68 + 23 00 00 00 00 00 02 7A 88 + 23 00 00 00 00 00 02 83 01 + 23 00 00 00 00 00 02 84 68 + //23 00 00 00 00 00 02 85 40 + 23 00 00 00 00 00 02 86 40 + //23 00 00 00 00 00 02 87 40 + //23 00 00 00 00 00 02 88 40 + 23 00 00 00 00 00 02 89 CF + 23 00 00 00 00 00 02 A2 20 + 23 00 00 00 00 00 02 B3 00 + 23 00 00 00 00 00 02 B7 00 + 23 00 00 00 00 00 02 B8 00 + 23 01 00 00 00 00 02 FB 01 + 23 01 00 00 00 00 02 FF 10 + 23 00 00 00 00 00 02 9D 00 + 23 00 00 00 00 00 02 89 00 + 23 00 00 00 00 00 02 55 80 + 23 01 00 00 00 00 02 FB 01 + + + ]; + qcom,mdss-dsi-CE_off-command = [ + 23 01 00 00 00 00 02 FF 10 + 23 00 00 00 00 00 02 55 01 + 23 01 00 00 00 00 02 FB 01 + + ]; + qcom,mdss-dsi-sRGB_on-command = [ + 23 01 00 00 00 00 02 FF 10 + 23 00 00 00 00 00 02 55 80 + 23 00 00 00 00 00 02 97 00 + 23 00 00 00 00 00 02 98 00 + 23 00 00 00 00 00 02 99 00 + 23 00 00 00 00 00 02 8E C0 + 23 00 00 00 00 00 02 8F 0C + 23 00 00 00 00 00 02 90 C0 + 23 00 00 00 00 00 02 91 30 + 23 00 00 00 00 00 02 92 83 + 23 00 00 00 00 00 02 93 00 + 23 00 00 00 00 00 02 94 0F + 23 00 00 00 00 00 02 95 00 + 23 00 00 00 00 00 02 96 01 + 23 00 00 00 00 00 02 9A 00 + 23 00 00 00 00 00 02 9B 00 + 23 00 00 00 00 00 02 9C 00 + 23 00 00 00 00 00 02 9D 24 + 23 00 00 00 00 00 02 89 00 + 23 01 00 00 00 00 02 FB 01 + 23 01 00 00 00 00 02 FF 22 + 23 00 00 00 00 00 02 00 40 + 23 00 00 00 00 00 02 01 54 + 23 00 00 00 00 00 02 02 5A + 23 00 00 00 00 00 02 03 60 + 23 00 00 00 00 00 02 04 66 + 23 00 00 00 00 00 02 05 6A + 23 00 00 00 00 00 02 06 6C + 23 00 00 00 00 00 02 07 6C + 23 00 00 00 00 00 02 08 68 + 23 00 00 00 00 00 02 09 62 + 23 00 00 00 00 00 02 0A 5B + 23 00 00 00 00 00 02 0B 53 + 23 00 00 00 00 00 02 0C 4D + 23 00 00 00 00 00 02 0D 48 + 23 00 00 00 00 00 02 0E 44 + 23 00 00 00 00 00 02 0F 41 + 23 00 00 00 00 00 02 10 40 + 23 00 00 00 00 00 02 11 50 + 23 00 00 00 00 00 02 12 60 + 23 00 00 00 00 00 02 13 70 + 23 00 00 00 00 00 02 14 58 + 23 00 00 00 00 00 02 15 68 + 23 00 00 00 00 00 02 16 78 + 23 00 00 00 00 00 02 17 00 + 23 00 00 00 00 00 02 18 40 + 23 00 00 00 00 00 02 19 40 + 23 00 00 00 00 00 02 1A 40 + 23 00 00 00 00 00 02 1B 40 + 23 00 00 00 00 00 02 1C 40 + 23 00 00 00 00 00 02 1D 40 + 23 00 00 00 00 00 02 1E 40 + 23 00 00 00 00 00 02 1F 40 + 23 00 00 00 00 00 02 20 40 + 23 00 00 00 00 00 02 21 45 + 23 00 00 00 00 00 02 22 49 + 23 00 00 00 00 00 02 23 4C + 23 00 00 00 00 00 02 24 4B + 23 00 00 00 00 00 02 25 48 + 23 00 00 00 00 00 02 26 44 + 23 00 00 00 00 00 02 27 41 + 23 00 00 00 00 00 02 28 40 + 23 00 00 00 00 00 02 2D 00 + 23 00 00 00 00 00 02 2F 40 + 23 00 00 00 00 00 02 30 40 + 23 00 00 00 00 00 02 31 40 + 23 00 00 00 00 00 02 32 40 + 23 00 00 00 00 00 02 33 40 + 23 00 00 00 00 00 02 34 40 + 23 00 00 00 00 00 02 35 40 + 23 00 00 00 00 00 02 36 40 + 23 00 00 00 00 00 02 37 40 + 23 00 00 00 00 00 02 38 40 + 23 00 00 00 00 00 02 39 40 + 23 00 00 00 00 00 02 3A 40 + 23 00 00 00 00 00 02 3B 40 + 23 00 00 00 00 00 02 3D 40 + 23 00 00 00 00 00 02 3F 40 + 23 00 00 00 00 00 02 40 40 + 23 00 00 00 00 00 02 41 40 + 23 00 00 00 00 00 02 42 40 + 23 00 00 00 00 00 02 43 40 + 23 00 00 00 00 00 02 44 40 + 23 00 00 00 00 00 02 45 40 + 23 00 00 00 00 00 02 46 40 + 23 00 00 00 00 00 02 47 40 + 23 00 00 00 00 00 02 48 40 + 23 00 00 00 00 00 02 49 40 + 23 00 00 00 00 00 02 4A 40 + 23 00 00 00 00 00 02 4B 40 + 23 00 00 00 00 00 02 4C 40 + 23 00 00 00 00 00 02 4D 40 + 23 00 00 00 00 00 02 4E 40 + 23 00 00 00 00 00 02 4F 40 + 23 00 00 00 00 00 02 50 40 + 23 00 00 00 00 00 02 51 40 + 23 00 00 00 00 00 02 52 40 + 23 00 00 00 00 00 02 53 01 + 23 00 00 00 00 00 02 54 00 + 23 00 00 00 00 00 02 55 88 + 23 00 00 00 00 00 02 56 77 + 23 00 00 00 00 00 02 58 32 + 23 00 00 00 00 00 02 59 30 + 23 00 00 00 00 00 02 5A 2D + 23 00 00 00 00 00 02 5B 2B + 23 00 00 00 00 00 02 5C 29 + 23 00 00 00 00 00 02 5D 27 + 23 00 00 00 00 00 02 5E 24 + 23 00 00 00 00 00 02 5F 26 + 23 00 00 00 00 00 02 60 2A + 23 00 00 00 00 00 02 61 2B + 23 00 00 00 00 00 02 62 2D + 23 00 00 00 00 00 02 63 30 + 23 00 00 00 00 00 02 64 30 + 23 00 00 00 00 00 02 65 33 + 23 00 00 00 00 00 02 66 34 + 23 00 00 00 00 00 02 67 34 + 23 00 00 00 00 00 02 68 34 + 23 00 00 00 00 00 02 69 34 + 23 00 00 00 00 00 02 6A 33 + 23 00 00 00 00 00 02 6B 32 + 23 00 00 00 00 00 02 6C 32 + 23 00 00 00 00 00 02 6D 32 + 23 00 00 00 00 00 02 6E 32 + 23 00 00 00 00 00 02 6F 32 + 23 00 00 00 00 00 02 70 00 + 23 00 00 00 00 00 02 71 00 + 23 00 00 00 00 00 02 72 00 + 23 00 00 00 00 00 02 73 05 + 23 00 00 00 00 00 02 74 06 + 23 00 00 00 00 00 02 75 0C + 23 00 00 00 00 00 02 76 03 + 23 00 00 00 00 00 02 77 09 + 23 00 00 00 00 00 02 78 0F + 23 00 00 00 00 00 02 79 68 + 23 00 00 00 00 00 02 7A 88 + 23 00 00 00 00 00 02 83 77 + 23 00 00 00 00 00 02 84 3B + 23 00 00 00 00 00 02 86 20 + 23 00 00 00 00 00 02 89 40 + 23 00 00 00 00 00 02 A2 20 + 23 00 00 00 00 00 02 B3 00 + 23 00 00 00 00 00 02 B7 00 + 23 00 00 00 00 00 02 B8 00 + 23 01 00 00 00 00 02 FB 01 + 23 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-sRGB_off-command = [ + 23 01 00 00 00 00 02 FF 10 + 23 00 00 00 00 00 02 9D 00 + 23 00 00 00 00 00 02 55 01 + 23 00 00 00 00 00 02 89 00 + 23 01 00 00 00 00 02 FB 01 + ]; + qcom,mdss-dsi-cold_gamma-command = [ + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 77 00 81 00 93 00 A4 00 B3 00 C2 00 D0 00 DC + 39 01 00 00 00 00 11 B1 00 E9 01 13 01 36 01 6E 01 9A 01 E0 02 19 02 1A + 39 01 00 00 00 00 11 B2 02 54 02 97 02 C2 02 F9 03 1C 03 49 03 57 03 65 + 39 01 00 00 00 00 0D B3 03 75 03 87 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 20 00 2F 00 49 00 60 00 76 00 89 00 9B 00 AA + 39 01 00 00 00 00 11 B5 00 B9 00 EB 01 15 01 54 01 86 01 D3 02 0E 02 0F + 39 01 00 00 00 00 11 B6 02 4B 02 8F 02 BA 02 F2 03 15 03 44 03 52 03 60 + 39 01 00 00 00 00 0D B7 03 70 03 83 03 99 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1B 00 39 00 54 00 6B 00 81 00 95 00 A6 + 39 01 00 00 00 00 11 B9 00 B7 00 ED 01 18 01 59 01 8B 01 D7 02 12 02 13 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 BF 02 F9 03 23 03 5E 03 78 03 9A + 39 01 00 00 00 00 0D BB 03 C0 03 C2 03 C4 03 C6 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 77 00 81 00 93 00 A4 00 B3 00 C2 00 D0 00 D3 + 39 01 00 00 00 00 11 B1 00 E9 01 13 01 36 01 6E 01 9A 01 E0 02 19 02 1A + 39 01 00 00 00 00 11 B2 02 54 02 97 02 C2 02 F9 03 1C 03 49 03 57 03 65 + 39 01 00 00 00 00 0D B3 03 75 03 87 03 9C 03 B7 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 20 00 2F 00 49 00 60 00 76 00 89 00 9B 00 AA + 39 01 00 00 00 00 11 B5 00 B9 00 EB 01 15 01 54 01 86 01 D3 02 0E 02 0F + 39 01 00 00 00 00 11 B6 02 4B 02 8F 02 BA 02 F2 03 15 03 44 03 52 03 60 + 39 01 00 00 00 00 0D B7 03 70 03 83 03 99 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 09 00 1B 00 39 00 54 00 6B 00 81 00 95 00 A6 + 39 01 00 00 00 00 11 B9 00 B7 00 ED 01 18 01 59 01 8B 01 D7 02 12 02 13 + 39 01 00 00 00 00 11 BA 02 4F 02 93 02 BF 02 F9 03 23 03 5E 03 78 03 9A + 39 01 00 00 00 00 0D BB 03 C0 03 C2 03 C4 03 C6 03 D2 03 D7 + ]; + qcom,mdss-dsi-warm_gamma-command = [ + 39 01 00 00 00 00 02 FF 20 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 09 00 19 00 37 00 4F 00 67 00 7A 00 8E 00 9E + 39 01 00 00 00 00 11 B1 00 B0 00 E6 01 12 01 53 01 86 01 D4 02 0F 02 11 + 39 01 00 00 00 00 11 B2 02 4C 02 92 02 BC 02 F3 03 16 03 43 03 53 03 62 + 39 01 00 00 00 00 0D B3 03 72 03 87 03 9A 03 B5 03 D2 03 D7 + 39 01 00 00 00 00 11 B4 00 0E 00 1E 00 3B 00 54 00 6B 00 7F 00 92 00 A3 + 39 01 00 00 00 00 11 B5 00 B4 00 E9 01 14 01 55 01 86 01 D2 02 0D 02 0F + 39 01 00 00 00 00 11 B6 02 4A 02 8F 02 BA 02 F2 03 15 03 44 03 51 03 60 + 39 01 00 00 00 00 0D B7 03 70 03 84 03 9B 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 DA 00 E0 00 EC 00 F6 01 01 01 0A 01 14 01 1C + 39 01 00 00 00 00 11 B9 01 25 01 43 01 5E 01 8A 01 B0 01 EE 02 22 02 24 + 39 01 00 00 00 00 11 BA 02 5C 02 A0 02 CB 03 04 03 2F 03 6E 03 8F 03 A3 + 39 01 00 00 00 00 0D BB 03 A5 03 A7 03 A9 03 BA 03 D2 03 D7 + 39 01 00 00 00 00 02 FF 21 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 11 B0 00 09 00 19 00 37 00 4F 00 67 00 7A 00 8E 00 9E + 39 01 00 00 00 00 11 B1 00 B0 00 E6 01 12 01 53 01 86 01 D4 02 0F 02 11 + 39 01 00 00 00 00 11 B2 02 4C 02 92 02 BC 02 F3 03 16 03 43 03 53 03 62 + 39 01 00 00 00 00 0D B3 03 72 03 87 03 9A 03 B5 03 D3 03 D7 + 39 01 00 00 00 00 11 B4 00 0E 00 1E 00 3B 00 54 00 6B 00 7F 00 92 00 A3 + 39 01 00 00 00 00 11 B5 00 B4 00 E9 01 14 01 55 01 86 01 D2 02 0D 02 0F + 39 01 00 00 00 00 11 B6 02 4A 02 8F 02 BA 02 F2 03 15 03 44 03 51 03 60 + 39 01 00 00 00 00 0D B7 03 70 03 84 03 9B 03 B4 03 D1 03 D7 + 39 01 00 00 00 00 11 B8 00 DA 00 E0 00 EC 00 F6 01 01 01 0A 01 14 01 1C + 39 01 00 00 00 00 11 B9 01 25 01 43 01 5E 01 8A 01 B0 01 EE 02 22 02 24 + 39 01 00 00 00 00 11 BA 02 5C 02 A0 02 CB 03 04 03 2F 03 6E 03 8F 03 A3 + 39 01 00 00 00 00 0D BB 03 A5 03 A7 03 A9 03 BA 03 D2 03 D7 + ]; + qcom,mdss-dsi-default_gamma-command = [ + 39 01 00 00 00 00 02 FF 20 //Enter CMD2_P0 + 39 00 00 00 00 00 02 AF 00 //R G B Gamma independent + 39 00 00 00 00 00 11 B0 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B2 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B3 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B4 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B5 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B6 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B7 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B8 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B9 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 BA 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D BB 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 21 //Enter CMD2_P1 + 39 00 00 00 00 00 11 B0 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B1 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B2 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B3 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B4 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B5 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 B6 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D B7 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 00 00 00 00 00 11 B8 00 00 00 11 00 30 00 4A 00 62 00 77 00 8B 00 9D + 39 00 00 00 00 00 11 B9 00 AD 00 E4 01 10 01 52 01 85 01 D2 02 10 02 12 + 39 00 00 00 00 00 11 BA 02 4D 02 91 02 BD 02 F4 03 18 03 46 03 54 03 62 + 39 00 00 00 00 00 0D BB 03 73 03 84 03 99 03 C1 03 D5 03 D9 + 39 01 00 00 00 00 02 FB 01 + 39 01 00 00 00 00 02 FF 10 + ]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-cold_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-warm_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-default_gamma-command-state = "dsi_hs_mode"; + qcom,mdss-white-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-sRGB_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-sRGB_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-t-clk-post = <0x0E>; + qcom,mdss-dsi-t-clk-pre = <0x34>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-lp11-init; + //qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "reg_read"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt36672-tianma-fhdplus-video_e7.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt36672-tianma-fhdplus-video_e7.dtsi new file mode 100755 index 0000000000000..dc967b9a54802 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt36672-tianma-fhdplus-video_e7.dtsi @@ -0,0 +1,79 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_nt36672_tianma_fhdplus_e7_vid: qcom,mdss_dsi_nt36672_tianma_fhdplus_video_e7 { + qcom,mdss-dsi-panel-name = "nt36672 tianma e7 fhdplus video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <16>; + qcom,mdss-dsi-h-back-porch = <64>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <4>; + qcom,mdss-dsi-v-front-porch = <4>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [29 01 00 00 01 00 02 ff 10 + 29 01 00 00 00 00 02 35 00 + 29 01 00 00 00 00 02 51 ff + 29 01 00 00 00 00 02 53 2c + 29 01 00 00 00 00 02 55 00 + 29 01 00 00 00 00 02 ff 10 + 29 01 00 00 78 00 02 11 00 + 29 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-dsi-off-command = [29 01 00 00 00 00 02 FF 00 + 05 01 00 00 14 00 02 28 00 + 05 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-t-clk-post = <0x0E>; + qcom,mdss-dsi-t-clk-pre = <0x31>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + qcom,mdss-dsi-tx-eot-append; + //qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-otm1911-fhd-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-otm1911-fhd-video.dtsi new file mode 100644 index 0000000000000..aaf37f52abcf5 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-otm1911-fhd-video.dtsi @@ -0,0 +1,76 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_otm1911_fhd_vid: qcom,mdss_dsi_otm1911_fhd_video { + qcom,mdss-dsi-panel-name = "otm1911 fhd video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <1920>; + qcom,mdss-dsi-h-front-porch = <24>; + qcom,mdss-dsi-h-back-porch = <24>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <6>; + qcom,mdss-dsi-v-front-porch = <14>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 78 00 02 00 00 + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00]; + + qcom,mdss-dsi-off-command = [39 01 00 00 32 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0d>; + qcom,mdss-dsi-t-clk-pre = <0x2d>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>; + //qcom,mdss-dsi-tx-eot-append; + //qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-otm1911-fhdplus-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-otm1911-fhdplus-video.dtsi new file mode 100644 index 0000000000000..5ba39e9daf808 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-otm1911-fhdplus-video.dtsi @@ -0,0 +1,138 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_otm1911_fhdplus_vid: qcom,mdss_dsi_otm1911_fhdplus_video { + qcom,mdss-dsi-panel-name = "otm1911 fhdplus video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2280>; + qcom,mdss-dsi-h-front-porch = <24>; + qcom,mdss-dsi-h-back-porch = <24>; + qcom,mdss-dsi-h-pulse-width = <20>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <38>; + qcom,mdss-dsi-v-front-porch = <47>; + qcom,mdss-dsi-v-pulse-width = <2>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 04 ff 19 11 01 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 03 ff 19 11 + 39 01 00 00 00 00 02 00 b0 + 39 01 00 00 00 00 05 b3 04 38 08 e8 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 02 C9 8E + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 0D CA F0 D9 C8 BA AF A6 9E 98 92 8D 88 84 + 39 01 00 00 00 00 02 00 90 + 39 01 00 00 00 00 0A CA FD FF 98 FB FF 33 F6 FF 66 + 39 01 00 00 00 00 02 00 A0 + 39 01 00 00 00 00 0D D6 0a 0b 0b 0b 0b 0c 0f 13 0f 13 11 0e + 39 01 00 00 00 00 02 00 B0 + 39 01 00 00 00 00 0D D6 9a 8d 82 83 83 83 80 6b 80 85 88 8a + 39 01 00 00 00 00 02 00 C0 + 39 01 00 00 00 00 0D D6 8d 86 91 90 89 81 80 83 80 8a 86 84 + 39 01 00 00 00 00 02 00 D0 + 39 01 00 00 00 00 0D D6 88 84 80 80 80 80 80 80 80 80 80 80 + 39 01 00 00 00 00 02 00 B0 + 39 01 00 00 00 00 02 CA 00 + 39 01 00 00 00 00 02 00 B2 + 39 01 00 00 00 00 02 CA 0A + 39 01 00 00 00 00 03 51 ff 0C + 39 01 00 00 00 00 02 53 2C + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 78 00 02 11 00 + 39 01 00 00 14 00 02 29 00]; + + qcom,mdss-dsi-off-command = [ + 39 01 00 00 00 00 04 ff 19 11 01 + 39 01 00 00 00 00 02 00 80 + 39 01 00 00 00 00 03 ff 19 11 + 39 01 00 00 00 00 02 00 90 + 39 01 00 00 00 00 02 b3 34 + 39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00]; + + qcom,mdss-dsi-CABC_on-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 55 01]; + + qcom,mdss-dsi-CABC_off-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 55 00]; + + qcom,mdss-dsi-CE_on-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 91 80]; + + qcom,mdss-dsi-CE_off-command = [ + 39 01 00 00 00 00 02 00 00 + 39 01 00 00 00 00 02 91 00]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_hs_mode"; + + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [f7 3c 28 00 6e 70 + 22 40 31 03 04 00]; + qcom,mdss-dsi-panel-timings-phy-v2 = [25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1e 08 0a 06 03 04 a0]; + qcom,mdss-dsi-t-clk-post = <0x0E>; + qcom,mdss-dsi-t-clk-pre = <0x34>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-brightness-max-level = <4095>; + qcom,mdss-brightness-max-level-global = <255>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 10>, <0 2>, <1 15>; + qcom,mdss-dsi-lp11-init; + //qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-td4310-ebbg-fhdplus-video_e7.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-td4310-ebbg-fhdplus-video_e7.dtsi new file mode 100644 index 0000000000000..596274884d72c --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-td4310-ebbg-fhdplus-video_e7.dtsi @@ -0,0 +1,572 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_td4310_ebbg_fhdplus_e7_vid: qcom,mdss_dsi_td4310_ebbg_fhdplus_video_e7 { + qcom,mdss-dsi-panel-name = "td4310 ebbg fhdplus e7 video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <130>; + qcom,mdss-dsi-h-back-porch = <26>; + qcom,mdss-dsi-h-pulse-width = <2>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <54>; + qcom,mdss-dsi-v-front-porch = <4>; + qcom,mdss-dsi-v-pulse-width = <10>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + + + qcom,mdss-white-command-00 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 10 1C 2C 3A 45 5D 6F 7D 8A 3E 4B 5B 71 7B 88 98 A5 B1 00 10 1C 2C 3A 45 5D 6F 7D 8A 3E 4B 5B 71 7B 88 98 A5 B1 + 29 01 00 00 00 00 15 C8 01 00 03 01 03 FC 00 00 03 FE FE FC 00 00 01 FE FB FC 00 00 + ]; + qcom,mdss-dsi-on-command = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 10 1C 2C 3A 45 5D 6F 7D 8A 3E 4B 5B 71 7B 88 98 A5 B1 00 10 1C 2C 3A 45 5D 6F 7D 8A 3E 4B 5B 71 7B 88 98 A5 B1 + 29 01 00 00 00 00 15 C8 01 00 03 01 03 FC 00 00 03 FE FE FC 00 00 01 FE FB FC 00 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-01 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 BB 00 00 01 05 03 FC 00 00 FC 03 FF B1 00 00 FA 02 01 BD 00 00 01 05 03 FC 00 00 FC 04 FE E3 00 00 FA 02 FF FB 00 00 01 05 03 FC 00 00 FC 03 FE 9F 00 + ]; + qcom,mdss-dsi-on-command-01 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 BB 00 00 01 05 03 FC 00 00 FC 03 FF B1 00 00 FA 02 01 BD 00 00 01 05 03 FC 00 00 FC 04 FE E3 00 00 FA 02 FF FB 00 00 01 05 03 FC 00 00 FC 03 FE 9F 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-02 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 FA 02 01 DD 00 00 01 05 03 FC 00 00 FB 04 FD D5 00 00 F9 02 FF D4 00 00 FE 05 03 EE 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 04 02 DD 00 00 FC 03 FE A4 00 + ]; + qcom,mdss-dsi-on-command-02 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 FA 02 01 DD 00 00 01 05 03 FC 00 00 FB 04 FD D5 00 00 F9 02 FF D4 00 00 FE 05 03 EE 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 04 02 DD 00 00 FC 03 FE A4 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-03 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FE 04 01 D4 00 00 FD 03 FE F7 00 00 FA 02 FF D3 00 00 FE 04 01 A5 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 03 02 9A 00 00 FC 03 01 AA 00 + ]; + qcom,mdss-dsi-on-command-03 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FE 04 01 D4 00 00 FD 03 FE F7 00 00 FA 02 FF D3 00 00 FE 04 01 A5 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 03 02 9A 00 00 FC 03 01 AA 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-04 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FF 04 02 AE 00 00 FD 03 FD F9 00 00 FA 02 FF D3 00 00 FF 03 02 80 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 03 01 79 00 00 FC 03 FF AE 00 + ]; + qcom,mdss-dsi-on-command-04 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FF 04 02 AE 00 00 FD 03 FD F9 00 00 FA 02 FF D3 00 00 FF 03 02 80 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 03 01 79 00 00 FC 03 FF AE 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-05 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 03 01 87 00 00 FD 03 01 83 00 00 F9 02 FF FC 00 00 FF 03 02 7C 00 00 FD 03 01 AD 00 00 F9 02 FF FC 00 00 FF 03 02 59 00 00 FD 02 02 46 00 + ]; + qcom,mdss-dsi-on-command-05 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 03 01 87 00 00 FD 03 01 83 00 00 F9 02 FF FC 00 00 FF 03 02 7C 00 00 FD 03 01 AD 00 00 F9 02 FF FC 00 00 FF 03 02 59 00 00 FD 02 02 46 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-06 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 04 02 BB 00 00 FC 03 FF B9 00 00 F9 02 FF FC 00 00 FE 04 01 B3 00 00 FC 04 FE E4 00 00 F9 02 FF FC 00 00 01 03 01 88 00 00 FC 03 01 73 00 + ]; + qcom,mdss-dsi-on-command-06 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 04 02 BB 00 00 FC 03 FF B9 00 00 F9 02 FF FC 00 00 FE 04 01 B3 00 00 FC 04 FE E4 00 00 F9 02 FF FC 00 00 01 03 01 88 00 00 FC 03 01 73 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-07 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF BF 00 00 01 05 03 FC 00 00 FD 03 FF FA 00 00 F9 02 01 91 00 00 FE 04 01 CE 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 05 04 F4 00 00 FC 04 FE E0 00 + ]; + qcom,mdss-dsi-on-command-07 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF BF 00 00 01 05 03 FC 00 00 FD 03 FF FA 00 00 F9 02 01 91 00 00 FE 04 01 CE 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 05 04 F4 00 00 FC 04 FE E0 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-08 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 78 00 00 01 05 03 FC 00 00 FD 03 FE F9 00 00 FA 01 03 4E 00 00 FF 04 01 D0 00 00 FC 03 FE FC 00 00 F9 02 FF C2 00 00 01 05 03 FC 00 00 FC 04 FE E7 00 + ]; + qcom,mdss-dsi-on-command-08 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 78 00 00 01 05 03 FC 00 00 FD 03 FE F9 00 00 FA 01 03 4E 00 00 FF 04 01 D0 00 00 FC 03 FE FC 00 00 F9 02 FF C2 00 00 01 05 03 FC 00 00 FC 04 FE E7 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-09 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 04 01 C7 00 00 FC 03 01 7A 00 00 F9 02 FF FC 00 00 FF 04 01 BF 00 00 FC 03 FE A7 00 00 F9 02 FF FC 00 00 FF 03 01 96 00 00 FD 02 02 3A 00 + ]; + qcom,mdss-dsi-on-command-09 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 04 01 C7 00 00 FC 03 01 7A 00 00 F9 02 FF FC 00 00 FF 04 01 BF 00 00 FC 03 FE A7 00 00 F9 02 FF FC 00 00 FF 03 01 96 00 00 FD 02 02 3A 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-10 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 03 02 A7 00 00 FC 03 01 7F 00 00 F9 02 FF FC 00 00 01 03 02 9E 00 00 FC 03 FF AA 00 00 F9 02 FF FC 00 00 01 03 02 77 00 00 FD 02 03 40 00 + ]; + qcom,mdss-dsi-on-command-10 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 03 02 A7 00 00 FC 03 01 7F 00 00 F9 02 FF FC 00 00 01 03 02 9E 00 00 FC 03 FF AA 00 00 F9 02 FF FC 00 00 01 03 02 77 00 00 FD 02 03 40 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-11 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FF 03 01 67 00 00 FD 03 01 87 00 00 F9 02 FF FC 00 00 FE 03 01 5B 00 00 FC 03 FE B1 00 00 F9 02 FF FC 00 00 01 02 02 3B 00 00 FC 03 01 4B 00 + ]; + qcom,mdss-dsi-on-command-11 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FF 03 01 67 00 00 FD 03 01 87 00 00 F9 02 FF FC 00 00 FE 03 01 5B 00 00 FC 03 FE B1 00 00 F9 02 FF FC 00 00 01 02 02 3B 00 00 FC 03 01 4B 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-12 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 02 03 46 00 00 FD 03 02 8B 00 00 F9 02 FF FC 00 00 01 02 02 39 00 00 FC 03 FE B5 00 00 F9 02 FF FC 00 00 FF 02 01 1E 00 00 FC 03 02 50 00 + ]; + qcom,mdss-dsi-on-command-12 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 02 03 46 00 00 FD 03 02 8B 00 00 F9 02 FF FC 00 00 01 02 02 39 00 00 FC 03 FE B5 00 00 F9 02 FF FC 00 00 FF 02 01 1E 00 00 FC 03 02 50 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-13 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 FA 00 00 01 05 03 FC 00 00 FC 03 FE B1 00 00 F9 02 FF FC 00 00 01 05 03 F8 00 00 FC 04 FE E0 00 00 F9 02 FF FC 00 00 FF 04 01 C7 00 00 FC 03 02 68 00 + ]; + qcom,mdss-dsi-on-command-13 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 FA 00 00 01 05 03 FC 00 00 FC 03 FE B1 00 00 F9 02 FF FC 00 00 01 05 03 F8 00 00 FC 04 FE E0 00 00 F9 02 FF FC 00 00 FF 04 01 C7 00 00 FC 03 02 68 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-14 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FE 05 01 DD 00 00 FC 03 FE B6 00 00 F9 02 FF FC 00 00 01 04 01 D7 00 00 FC 04 FE E2 00 00 F9 02 FF FC 00 00 FF 04 01 A7 00 00 FC 03 02 6D 00 + ]; + qcom,mdss-dsi-on-command-14 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FE 05 01 DD 00 00 FC 03 FE B6 00 00 F9 02 FF FC 00 00 01 04 01 D7 00 00 FC 04 FE E2 00 00 F9 02 FF FC 00 00 FF 04 01 A7 00 00 FC 03 02 6D 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-15 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 03 02 9A 00 00 FC 03 FF BC 00 00 F9 02 FF FC 00 00 FF 03 01 90 00 00 FC 04 FD E7 00 00 F9 02 FF FC 00 00 FF 03 02 68 00 00 FC 03 01 77 00 + ]; + qcom,mdss-dsi-on-command-15 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 01 03 02 9A 00 00 FC 03 FF BC 00 00 F9 02 FF FC 00 00 FF 03 01 90 00 00 FC 04 FD E7 00 00 F9 02 FF FC 00 00 FF 03 02 68 00 00 FC 03 01 77 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-16 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FF 03 01 78 00 00 FC 03 FE C0 00 00 F9 02 FF FC 00 00 01 03 02 6B 00 00 FC 04 FE E9 00 00 F9 02 FF FC 00 00 01 02 03 48 00 00 FD 03 02 7B 00 + ]; + qcom,mdss-dsi-on-command-16 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 FF FC 00 00 FF 03 01 78 00 00 FC 03 FE C0 00 00 F9 02 FF FC 00 00 01 03 02 6B 00 00 FC 04 FE E9 00 00 F9 02 FF FC 00 00 01 02 03 48 00 00 FD 03 02 7B 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-17 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 79 00 00 01 05 03 FC 00 00 FC 03 FF B2 00 00 F9 02 02 78 00 00 01 05 03 FC 00 00 FC 04 FE E2 00 00 FA 02 01 BD 00 00 01 05 03 FC 00 00 FC 03 FD A1 00 + ]; + qcom,mdss-dsi-on-command-17 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 79 00 00 01 05 03 FC 00 00 FC 03 FF B2 00 00 F9 02 02 78 00 00 01 05 03 FC 00 00 FC 04 FE E2 00 00 FA 02 01 BD 00 00 01 05 03 FC 00 00 FC 03 FD A1 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-18 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 9C 00 00 01 05 03 FC 00 00 FB 04 FD D5 00 00 FA 02 02 8F 00 00 FE 05 03 F0 00 00 FC 03 FE FC 00 00 F9 02 01 DF 00 00 01 05 03 FC 00 00 FC 03 FE C4 00 + ]; + qcom,mdss-dsi-on-command-18 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 9C 00 00 01 05 03 FC 00 00 FB 04 FD D5 00 00 FA 02 02 8F 00 00 FE 05 03 F0 00 00 FC 03 FE FC 00 00 F9 02 01 DF 00 00 01 05 03 FC 00 00 FC 03 FE C4 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-19 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 C0 00 00 01 04 02 DA 00 00 FC 03 FE FC 00 00 F9 02 02 92 00 00 FE 04 02 A8 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 04 01 D3 00 00 FC 04 FF E2 00 + ]; + qcom,mdss-dsi-on-command-19 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 C0 00 00 01 04 02 DA 00 00 FC 03 FE FC 00 00 F9 02 02 92 00 00 FE 04 02 A8 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 01 04 01 D3 00 00 FC 04 FF E2 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-20 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 C0 00 00 FF 04 01 B5 00 00 FB 03 FE FC 00 00 F9 02 01 94 00 00 01 03 01 85 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 FF 04 02 AF 00 00 FB 04 FD E5 00 + ]; + qcom,mdss-dsi-on-command-20 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 01 C0 00 00 FF 04 01 B5 00 00 FB 03 FE FC 00 00 F9 02 01 94 00 00 01 03 01 85 00 00 FC 03 FE FC 00 00 F9 02 FF FC 00 00 FF 04 02 AF 00 00 FB 04 FD E5 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-21 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 FA 01 02 37 00 00 01 05 03 FC 00 00 FC 03 FE B3 00 00 F9 01 01 34 00 00 01 05 03 FC 00 00 FD 03 FF E2 00 00 F9 02 02 7C 00 00 01 05 03 FC 00 00 FC 03 FE A2 00 + ]; + qcom,mdss-dsi-on-command-21 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 FA 01 02 37 00 00 01 05 03 FC 00 00 FC 03 FE B3 00 00 F9 01 01 34 00 00 01 05 03 FC 00 00 FD 03 FF E2 00 00 F9 02 02 7C 00 00 01 05 03 FC 00 00 FC 03 FE A2 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-22 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 FA 01 02 57 00 00 01 05 03 FC 00 00 FC 03 FE D5 00 00 FA 01 03 4A 00 00 01 05 03 F1 00 00 FC 03 FE FC 00 00 FA 01 01 A0 00 00 01 05 03 FC 00 00 FC 03 FE C4 00 + ]; + qcom,mdss-dsi-on-command-22 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 FA 01 02 57 00 00 01 05 03 FC 00 00 FC 03 FE D5 00 00 FA 01 03 4A 00 00 01 05 03 F1 00 00 FC 03 FE FC 00 00 FA 01 01 A0 00 00 01 05 03 FC 00 00 FC 03 FE C4 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-23 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 7C 00 00 01 04 02 DC 00 00 FC 03 FE FC 00 00 FA 01 03 51 00 00 FF 04 02 AB 00 00 FC 03 FE FC 00 00 F9 02 FF D4 00 00 01 04 02 EC 00 00 FC 03 FE FC 00 + ]; + qcom,mdss-dsi-on-command-23 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 7C 00 00 01 04 02 DC 00 00 FC 03 FE FC 00 00 FA 01 03 51 00 00 FF 04 02 AB 00 00 FC 03 FE FC 00 00 F9 02 FF D4 00 00 01 04 02 EC 00 00 FC 03 FE FC 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-white-command-24 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 7E 00 00 01 04 02 B7 00 00 FC 03 FE FC 00 00 FA 01 02 55 00 00 01 03 01 89 00 00 FD 03 FE FC 00 00 FA 02 01 D3 00 00 FF 04 01 C7 00 00 FC 03 FE FC 00 + ]; + qcom,mdss-dsi-on-command-24 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 00 11 1D 2D 3B 46 5E 6F 7D 8A 3D 4A 5A 70 7B 88 98 A4 B1 + 29 01 00 00 00 00 38 C8 01 00 F9 02 02 7E 00 00 01 04 02 B7 00 00 FC 03 FE FC 00 00 FA 01 02 55 00 00 01 03 01 89 00 00 FD 03 FE FC 00 00 FA 02 01 D3 00 00 FF 04 01 C7 00 00 FC 03 FE FC 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + qcom,mdss-dsi-off-command = [ + 39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-CABC_on-command = [ + 15 01 00 00 00 00 02 55 01 + 29 00 00 00 00 00 02 b0 04 + 29 01 00 00 00 00 08 B8 89 51 15 00 02 00 00 + 29 01 00 00 00 00 1A CE dd 05 0F 10 24 45 66 85 9C AC C4 C6 eE F0 f2 fb ff 02 00 04 04 24 04 69 5a + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00 + ]; + qcom,mdss-dsi-CABC_off-command = [ + 15 01 00 00 00 00 02 55 00 + ]; + qcom,mdss-dsi-CE_on-command = [ + //29 01 00 00 00 00 2C CA 1D FC E4 B8 03 FF 05 F5 EF FB E1 F8 05 0C 16 11 FD F7 FD FA FD 00 FF 00 00 FF 00 00 FF 00 FF 00 07 FF 05 FF 00 00 FF 2A 00 FF FF + 29 01 00 00 00 00 2C CA 1D FC FC FC 0D F0 03 18 00 18 12 0F 07 15 00 FB 0A 0B 0C 03 00 FD FF 00 00 FC 02 01 80 9F 6C 50 97 62 4C 00 B9 87 72 BF 89 70 00 + ]; + qcom,mdss-dsi-CE_off-command = [ + 29 01 00 00 00 00 2C CA 1C FC FC FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + qcom,mdss-dsi-cold_gamma-command = [ + 39 01 00 00 00 00 02 84 7F + ]; + qcom,mdss-dsi-warm_gamma-command = [ + 39 01 00 00 00 00 02 84 80 + ]; + qcom,mdss-dsi-default_gamma-command = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 c7 00 10 1C 2C 3A 45 5D 6F 7D 8A 3E 4B 5B 71 7B 88 98 A5 B1 00 10 1C 2C 3A 45 5D 6F 7D 8A 3E 4B 5B 71 7B 88 98 A5 B1 + 29 01 00 00 00 00 15 C8 01 00 03 01 03 FC 00 00 03 FE FE FC 00 00 01 FE FB FC 00 00 + ]; + + qcom,mdss-dsi-sRGB_on-command = [ + 15 01 00 00 00 00 02 B0 00 + 29 01 00 00 00 00 2C CA 1D FC D8 80 1B EB F1 CA E7 D5 F5 DC EE 25 FD E9 1F 2B FF 08 F7 27 FF 00 00 F6 25 1E FF 00 FF 00 55 FA 3C FF 00 00 FF 01 35 E6 FF + ]; + qcom,mdss-dsi-sRGB_off-command = [ + 29 01 00 00 00 00 2C CA 1C FC FC FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-cold_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-warm_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-default_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-sRGB_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-sRGB_off-command-state = "dsi_lp_mode"; + qcom,mdss-white-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0E>; + qcom,mdss-dsi-t-clk-pre = <0x34>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 5>, <0 5>, <1 30>; + //qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-td4310-fhdplus-video_e7.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-td4310-fhdplus-video_e7.dtsi new file mode 100644 index 0000000000000..38cc3744112a9 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-td4310-fhdplus-video_e7.dtsi @@ -0,0 +1,624 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_td4310_fhdplus_e7_vid: qcom,mdss_dsi_td4310_fhdplus_video_e7 { + qcom,mdss-dsi-panel-name = "td4310 fhdplus e7 video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <108>; + qcom,mdss-dsi-h-back-porch = <60>; + qcom,mdss-dsi-h-pulse-width = <12>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <33>; + qcom,mdss-dsi-v-front-porch = <6>; + qcom,mdss-dsi-v-pulse-width = <4>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + + qcom,mdss-dsi-on-command = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 03 00 01 01 02 FE 00 00 FE FF 02 F3 00 00 01 FD 01 EE 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-01 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 CC 00 00 02 FE 01 FC 00 00 01 FF FF B7 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-02 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 F3 00 00 02 FE 01 FC 00 00 01 FE FE E0 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-03 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 03 00 01 FD 01 FE 00 00 02 FE FF F0 00 00 01 FE FD FE 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-04 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE 01 B6 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-05 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF 96 00 00 FE 01 02 8E 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD C0 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-06 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE FF D9 00 00 01 FF 01 CB 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-07 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 CC 00 00 02 FE 01 FC 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-08 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 84 00 00 02 FE 01 FC 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-09 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE FE E7 00 00 01 FE 01 8F 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-10 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF BA 00 00 FE 01 02 8C 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-11 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FF FF 02 70 00 00 FE 01 02 8F 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-12 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 01 4C 00 00 FE 01 02 90 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-13 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE 01 FC 00 00 01 FF FF B8 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-14 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE 01 FC 00 00 01 FF 01 CB 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-15 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FF 01 AE 00 00 01 FF 01 CB 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-16 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 FD 87 00 00 FD 01 01 CA 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-17 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 85 00 00 02 FE 01 FC 00 00 01 FF 01 B6 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-18 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 AB 00 00 02 FE 01 FC 00 00 01 FE FE DD 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-19 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 CE 00 00 02 FE FE E3 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-20 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FC CF 00 00 FD 01 FC BB 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-21 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 3D 00 00 02 FE 01 FC 00 00 01 FF FF B5 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-22 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE FF 63 00 00 02 FE 01 FC 00 00 01 FE 01 DA 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-23 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 86 00 00 02 FE 01 E6 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-24 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FF 85 00 00 FC 01 FA C1 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-off-command = [ + 39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-CABC_on-command = [ + 15 01 00 00 00 00 02 55 01 + 29 01 00 00 00 00 08 B8 89 51 0d 00 02 00 00 + 29 01 00 00 00 00 1A CE 55 40 4d 6a 75 97 a7 b6 c9 d0 d4 e7 f8 f9 fa fb ff 04 00 00 04 46 04 69 5a //default old rsp + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00 + ]; + qcom,mdss-dsi-CABC_off-command = [ + 15 01 00 00 00 00 02 55 00 + ]; + qcom,mdss-dsi-CE_on-command = [ + 29 01 00 00 00 00 2C CA 1D FC FC FC 00 EC F8 3D 00 13 0E 13 00 1F 08 00 19 11 00 00 00 00 D5 A1 89 d8 9e 87 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + qcom,mdss-dsi-CE_off-command = [ + 29 01 00 00 00 00 2C CA 1C FC FC FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + qcom,mdss-dsi-cold_gamma-command = [ + 39 01 00 00 00 00 02 84 7F + ]; + qcom,mdss-dsi-warm_gamma-command = [ + 39 01 00 00 00 00 02 84 80 + ]; + qcom,mdss-dsi-default_gamma-command = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 03 00 01 01 02 FE 00 00 FE FF 02 F3 00 00 01 FD 01 EE 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; /*Add by HQ-sxf follow gamma0*/ + + + /*Add by HQ-sxf follow white gamma start*/ + qcom,mdss-white-command-00 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 03 00 01 01 02 FE 00 00 FE FF 02 F3 00 00 01 FD 01 EE 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-01 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 CC 00 00 02 FE 01 FC 00 00 01 FF FF B7 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-02 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 F3 00 00 02 FE 01 FC 00 00 01 FE FE E0 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-03 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 03 00 01 FD 01 FE 00 00 02 FE FF F0 00 00 01 FE FD FE 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-04 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE 01 B6 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-05 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF 96 00 00 FE 01 02 8E 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD C0 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-06 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE FF D9 00 00 01 FF 01 CB 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-07 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 CC 00 00 02 FE 01 FC 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-08 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 84 00 00 02 FE 01 FC 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-09 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE FE E7 00 00 01 FE 01 8F 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-10 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF BA 00 00 FE 01 02 8C 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-11 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FF FF 02 70 00 00 FE 01 02 8F 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-12 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 01 4C 00 00 FE 01 02 90 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-13 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE 01 FC 00 00 01 FF FF B8 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-14 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FE 01 FC 00 00 01 FF 01 CB 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-15 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 FC 00 00 02 FF 01 AE 00 00 01 FF 01 CB 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-16 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 FD 87 00 00 FD 01 01 CA 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-17 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 85 00 00 02 FE 01 FC 00 00 01 FF 01 B6 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-18 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 AB 00 00 02 FE 01 FC 00 00 01 FE FE DD 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-19 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FD 01 CE 00 00 02 FE FE E3 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-20 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FC CF 00 00 FD 01 FC BB 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-21 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 3D 00 00 02 FE 01 FC 00 00 01 FF FF B5 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-22 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE FF 63 00 00 02 FE 01 FC 00 00 01 FE 01 DA 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-23 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 01 FE 01 86 00 00 02 FE 01 E6 00 00 01 FE FD FC 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + ]; + + qcom,mdss-white-command-24 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FF 85 00 00 FC 01 FA C1 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + /*white gamma end*/ + + /*Add by HQ-zmc follow sRGB[Date: 2017-11-25 13:35:40]*/ + qcom,mdss-dsi-sRGB_on-command = [ + 15 01 00 00 00 00 02 84 00 + 29 01 00 00 00 00 2C CA 1D FC DC 9C 17 EA F4 EF 30 EF DB 0C F6 67 4C 2C 38 2A 19 06 06 25 FF 00 00 F7 2E 19 FF 00 FF 00 4B FD 3D FF 00 00 FF 42 01 FC FF + ]; + qcom,mdss-dsi-sRGB_off-command = [ + 29 01 00 00 00 00 2C CA 1C FC FC FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-cold_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-warm_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-default_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-white-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-sRGB_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-sRGB_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0E>; + qcom,mdss-dsi-t-clk-pre = <0x35>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 5>, <0 5>, <1 30>; + //qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-td4310-fhdplus-video_e7_g55.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-td4310-fhdplus-video_e7_g55.dtsi new file mode 100644 index 0000000000000..54bd1959d0224 --- /dev/null +++ b/arch/arm/boot/dts/qcom/dsi-panel-td4310-fhdplus-video_e7_g55.dtsi @@ -0,0 +1,627 @@ +/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&mdss_mdp { + dsi_td4310_fhdplus_e7_g55_vid: qcom,mdss_dsi_td4310_fhdplus_video_e7_g55 { + qcom,mdss-dsi-panel-name = "td4310 fhdplus e7 g55 video mode dsi panel"; + qcom,mdss-dsi-panel-type = "dsi_video_mode"; + qcom,mdss-dsi-panel-framerate = <60>; + qcom,mdss-dsi-virtual-channel-id = <0>; + qcom,mdss-dsi-stream = <0>; + qcom,mdss-dsi-panel-width = <1080>; + qcom,mdss-dsi-panel-height = <2160>; + qcom,mdss-dsi-h-front-porch = <108>; + qcom,mdss-dsi-h-back-porch = <60>; + qcom,mdss-dsi-h-pulse-width = <12>; + qcom,mdss-dsi-h-sync-skew = <0>; + qcom,mdss-dsi-v-back-porch = <33>; + qcom,mdss-dsi-v-front-porch = <6>; + qcom,mdss-dsi-v-pulse-width = <4>; + qcom,mdss-dsi-h-left-border = <0>; + qcom,mdss-dsi-h-right-border = <0>; + qcom,mdss-dsi-v-top-border = <0>; + qcom,mdss-dsi-v-bottom-border = <0>; + qcom,mdss-dsi-bpp = <24>; + qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-border-color = <0>; + + qcom,mdss-dsi-on-command = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + //29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + //29 01 00 00 00 00 38 C8 03 00 01 01 02 FE 00 00 FE FF 02 F3 00 00 01 FD 01 EE 00 00 FF 01 01 F6 00 00 01 FE 03 EC 00 00 01 FC FE FE 00 00 01 01 02 FE 00 00 FF FF 02 E9 00 00 01 FE 01 CD 00 + 29 01 00 00 00 00 27 C7 00 19 28 3B 4A 55 6D 7D 8A 96 48 54 62 76 7F 8B 99 A4 B2 00 19 28 3B 4A 55 6D 7D 8A 96 48 54 62 76 7F 8B 99 A4 B2 + 29 01 00 00 00 00 38 C8 03 00 01 03 FF FE 00 00 FE 01 FD F7 00 00 01 FF FB F2 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-01 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FA B1 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-02 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FD D7 00 00 FF FB FF FC 00 00 FD FB FD D4 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-03 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FE FB FB D6 00 00 FD FB FD FC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-04 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FF FB FB AE 00 00 FD FB FE FB 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-05 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF 96 00 00 FE 01 02 8E 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD C0 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-06 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 01 FB FD B9 00 00 FE FB FA BB 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-07 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FC B4 00 00 FF FB FF FC 00 00 FD FB FE F9 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-08 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FB 66 00 00 FF FB FF FC 00 00 FD FB FD F8 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-09 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FF FB FD C5 00 00 FF FB FD 7A 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-10 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF BA 00 00 FE 01 02 8C 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-11 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FF FF 02 70 00 00 FE 01 02 8F 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-12 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 01 4C 00 00 FE 01 02 90 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-13 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FC FB FF F4 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-14 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FE FB FD E0 00 00 FE FB FB B9 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-15 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 01 FB FD 94 00 00 FD FB FC BC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-16 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 FD 87 00 00 FD 01 01 CA 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-17 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FC 68 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-18 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FB 8D 00 00 FF FB FF FC 00 00 FE FB FC D3 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-19 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FD B8 00 00 FF FB FD D9 00 00 FD FB FD FC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-20 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FC CF 00 00 FD 01 FC BB 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-21 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FC F8 20 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-22 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FB FB 42 00 00 FF FB FF FC 00 00 FD FB FC D2 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-23 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FA 6F 00 00 FE FB FC DC 00 00 FD FB FD FC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-on-command-24 = [ + 39 01 00 00 78 00 02 11 00 + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FF 85 00 00 FC 01 FA C1 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + 39 01 00 00 00 00 02 51 ff + 39 01 00 00 00 00 02 53 24 + 39 01 00 00 00 00 02 55 00 + 39 01 00 00 00 00 02 35 00 + 39 01 00 00 14 00 02 29 00 + ]; + + qcom,mdss-dsi-off-command = [ + 39 01 00 00 14 00 02 28 00 + 39 01 00 00 78 00 02 10 00 + ]; + qcom,mdss-dsi-CABC_on-command = [ + 15 01 00 00 00 00 02 55 01 + 29 01 00 00 00 00 08 B8 89 51 0d 00 02 00 00 + 29 01 00 00 00 00 1A CE 55 40 4d 6a 75 97 a7 b6 c9 d0 d4 e7 f8 f9 fa fb ff 04 00 00 04 46 04 69 5a //default old rsp + 29 01 00 00 00 00 0A F9 64 FF E0 BE 00 8D BF 80 00 + ]; + qcom,mdss-dsi-CABC_off-command = [ + 15 01 00 00 00 00 02 55 00 + ]; + qcom,mdss-dsi-CE_on-command = [ + 29 01 00 00 00 00 2C CA 1D FC FC FC 00 EC F8 3D 00 13 0E 13 00 1F 08 00 19 11 00 00 00 00 D5 A1 89 d8 9e 87 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + qcom,mdss-dsi-CE_off-command = [ + 29 01 00 00 00 00 2C CA 1C FC FC FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + qcom,mdss-dsi-cold_gamma-command = [ + 39 01 00 00 00 00 02 84 7F + ]; + qcom,mdss-dsi-warm_gamma-command = [ + 39 01 00 00 00 00 02 84 80 + ]; + qcom,mdss-dsi-default_gamma-command = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 19 28 3B 4A 55 6D 7D 8A 96 48 54 62 76 7F 8B 99 A4 B2 00 19 28 3B 4A 55 6D 7D 8A 96 48 54 62 76 7F 8B 99 A4 B2 + 29 01 00 00 00 00 38 C8 03 00 01 03 FF FE 00 00 FE 01 FD F7 00 00 01 FF FB F2 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; /*Add by sxf fllow gamma0*/ + + + /*Add by HQ sxf fllow white gamma start*/ + qcom,mdss-white-command-00 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 19 28 3B 4A 55 6D 7D 8A 96 48 54 62 76 7F 8B 99 A4 B2 00 19 28 3B 4A 55 6D 7D 8A 96 48 54 62 76 7F 8B 99 A4 B2 + 29 01 00 00 00 00 38 C8 03 00 01 03 FF FE 00 00 FE 01 FD F7 00 00 01 FF FB F2 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-01 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FA B1 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-02 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FD D7 00 00 FF FB FF FC 00 00 FD FB FD D4 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-03 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FE FB FB D6 00 00 FD FB FD FC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-04 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FF FB FB AE 00 00 FD FB FE FB 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-05 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF 96 00 00 FE 01 02 8E 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD C0 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-06 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 01 FB FD B9 00 00 FE FB FA BB 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-07 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FC B4 00 00 FF FB FF FC 00 00 FD FB FE F9 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-08 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FB 66 00 00 FF FB FF FC 00 00 FD FB FD F8 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-09 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FF FB FD C5 00 00 FF FB FD 7A 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-10 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FE FF FF BA 00 00 FE 01 02 8C 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-11 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FF FF 02 70 00 00 FE 01 02 8F 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-12 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 01 4C 00 00 FE 01 02 90 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-13 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FC FB FF F4 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-14 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 FE FB FD E0 00 00 FE FB FB B9 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-15 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FF FC 00 00 01 FB FD 94 00 00 FD FB FC BC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-16 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FE FC 00 00 FD 01 FD 87 00 00 FD 01 01 CA 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-17 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FC 68 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-18 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FB 8D 00 00 FF FB FF FC 00 00 FE FB FC D3 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-19 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FA FD B8 00 00 FF FB FD D9 00 00 FD FB FD FC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-20 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FC CF 00 00 FD 01 FC BB 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + qcom,mdss-white-command-21 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FC F8 20 00 00 FF FB FF FC 00 00 FE FB FC AF 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-22 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FB FB 42 00 00 FF FB FF FC 00 00 FD FB FC D2 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-23 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FD FB FA 6F 00 00 FE FB FC DC 00 00 FD FB FD FC 00 00 01 03 01 EC 00 00 FE 01 FD F5 00 00 01 FE FA FE 00 00 01 03 FF FE 00 00 FE 01 FD EC 00 00 FE 01 FB D3 00 + ]; + + qcom,mdss-white-command-24 = [ + 29 01 00 00 00 00 02 B0 04 + 29 01 00 00 00 00 02 D6 01 + 29 01 00 00 00 00 27 C7 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 00 1A 29 3C 4B 57 6F 7F 8C 97 49 55 63 77 80 8C 9B A6 B2 + 29 01 00 00 00 00 38 C8 01 00 FE FF FF 85 00 00 FC 01 FA C1 00 00 FD 01 FD FC 00 00 04 01 FD 97 00 00 03 FF FD B9 00 00 04 FC F8 FC 00 00 04 01 FE FC 00 00 03 FF FD CC 00 00 04 FF FE 53 00 + ]; + + /*white gamma end*/ + + + /*Add by HQ-zmc follow sRGB[Date: 2017-11-25 13:35:40]*/ + qcom,mdss-dsi-sRGB_on-command = [ + 15 01 00 00 00 00 02 84 00 + 29 01 00 00 00 00 2C CA 1D FC E8 90 0E E7 F1 E1 1F E7 DB 0B EF 6F 4A 27 35 2A 19 FD 00 22 FF 00 00 F7 2F 1A FF 00 FF 00 54 FD 3B FF 00 00 FF 45 01 FE FF + ]; + qcom,mdss-dsi-sRGB_off-command = [ + 29 01 00 00 00 00 2C CA 1C FC FC FC 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ]; + + qcom,mdss-dsi-on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-off-command-state = "dsi_hs_mode"; + qcom,mdss-dsi-CABC_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CABC_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-CE_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-cold_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-warm_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-default_gamma-command-state = "dsi_lp_mode"; + qcom,mdss-white-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-sRGB_on-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-sRGB_off-command-state = "dsi_lp_mode"; + qcom,mdss-dsi-h-sync-pulse = <1>; + qcom,mdss-dsi-traffic-mode = "burst_mode"; + qcom,mdss-dsi-bllp-eof-power-mode; + qcom,mdss-dsi-bllp-power-mode; + qcom,mdss-dsi-lane-0-state; + qcom,mdss-dsi-lane-1-state; + qcom,mdss-dsi-lane-2-state; + qcom,mdss-dsi-lane-3-state; + qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33 + 22 27 1e 03 04 00]; + qcom,mdss-dsi-t-clk-post = <0x0E>; + qcom,mdss-dsi-t-clk-pre = <0x35>; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,mdss-dsi-dma-trigger = "trigger_sw"; + qcom,mdss-dsi-mdp-trigger = "none"; + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-reset-sequence = <1 5>, <0 5>, <1 30>; + //qcom,mdss-dsi-tx-eot-append; + qcom,esd-check-enabled; + qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 0A]; + qcom,mdss-dsi-panel-status-command-mode = "dsi_lp_mode"; + qcom,mdss-dsi-panel-status-check-mode = "TE_check_NT35596"; + qcom,mdss-dsi-panel-status-read-length = <1>; + qcom,mdss-dsi-panel-status-value = <0x9C>; + qcom,mdss-dsi-panel-max-error-count = <3>; + qcom,mdss-pan-physical-width-dimension = <69>; + qcom,mdss-pan-physical-height-dimension = <122>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-audio-e7.dtsi b/arch/arm/boot/dts/qcom/msm-audio-e7.dtsi new file mode 100644 index 0000000000000..363b58f1ecb5f --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-audio-e7.dtsi @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + + pcm0: qcom,msm-pcm { + compatible = "qcom,msm-pcm-dsp"; + qcom,msm-pcm-dsp-id = <0>; + }; + + routing: qcom,msm-pcm-routing { + compatible = "qcom,msm-pcm-routing"; + }; + + pcm2: qcom,msm-ultra-low-latency { + compatible = "qcom,msm-pcm-dsp"; + qcom,msm-pcm-dsp-id = <2>; + qcom,msm-pcm-low-latency; + qcom,latency-level = "ultra"; + }; + + pcm1: qcom,msm-pcm-low-latency { + compatible = "qcom,msm-pcm-dsp"; + qcom,msm-pcm-dsp-id = <1>; + qcom,msm-pcm-low-latency; + qcom,latency-level = "regular"; + }; + + pcm2: qcom,msm-ultra-low-latency { + compatible = "qcom,msm-pcm-dsp"; + qcom,msm-pcm-dsp-id = <2>; + qcom,msm-pcm-low-latency; + qcom,latency-level = "ultra"; + }; + + cpe: qcom,msm-cpe-lsm { + compatible = "qcom,msm-cpe-lsm"; + }; + + lpa: qcom,msm-pcm-lpa { + compatible = "qcom,msm-pcm-lpa"; + }; + + compress: qcom,msm-compress-dsp { + compatible = "qcom,msm-compress-dsp"; + }; + + voip: qcom,msm-voip-dsp { + compatible = "qcom,msm-voip-dsp"; + }; + + voice: qcom,msm-pcm-voice { + compatible = "qcom,msm-pcm-voice"; + qcom,destroy-cvd; + }; + + stub_codec: qcom,msm-stub-codec { + compatible = "qcom,msm-stub-codec"; + }; + + qcom,msm-dai-fe { + compatible = "qcom,msm-dai-fe"; + }; + + afe: qcom,msm-pcm-afe { + compatible = "qcom,msm-pcm-afe"; + }; + + loopback: qcom,msm-pcm-loopback { + compatible = "qcom,msm-pcm-loopback"; + }; + + qcom,msm-dai-mi2s { + compatible = "qcom,msm-dai-mi2s"; + dai_mi2s0: qcom,msm-dai-q6-mi2s-prim { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <0>; + qcom,msm-mi2s-rx-lines = <3>; + qcom,msm-mi2s-tx-lines = <0>; + }; + + dai_mi2s1: qcom,msm-dai-q6-mi2s-sec { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <1>; + qcom,msm-mi2s-rx-lines = <1>; + qcom,msm-mi2s-tx-lines = <0>; + }; + + dai_mi2s3: qcom,msm-dai-q6-mi2s-quat { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <3>; + qcom,msm-mi2s-rx-lines = <1>; + qcom,msm-mi2s-tx-lines = <2>; + }; + + dai_mi2s2: qcom,msm-dai-q6-mi2s-tert { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <2>; + qcom,msm-mi2s-rx-lines = <0>; + qcom,msm-mi2s-tx-lines = <3>; + }; + + dai_mi2s5: qcom,msm-dai-q6-mi2s-quin { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <5>; + qcom,msm-mi2s-rx-lines = <1>; + qcom,msm-mi2s-tx-lines = <2>; + }; + + dai_mi2s6: qcom,msm-dai-q6-mi2s-senary { + compatible = "qcom,msm-dai-q6-mi2s"; + qcom,msm-dai-q6-mi2s-dev-id = <6>; + qcom,msm-mi2s-rx-lines = <0>; + qcom,msm-mi2s-tx-lines = <3>; + }; + }; + + lsm: qcom,msm-lsm-client { + compatible = "qcom,msm-lsm-client"; + }; + + qcom,msm-dai-q6 { + compatible = "qcom,msm-dai-q6"; + sb_0_rx: qcom,msm-dai-q6-sb-0-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16384>; + }; + + sb_0_tx: qcom,msm-dai-q6-sb-0-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16385>; + }; + + sb_1_rx: qcom,msm-dai-q6-sb-1-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16386>; + }; + + sb_1_tx: qcom,msm-dai-q6-sb-1-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16387>; + }; + + sb_2_rx: qcom,msm-dai-q6-sb-2-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16388>; + }; + + sb_2_tx: qcom,msm-dai-q6-sb-2-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16389>; + }; + + + sb_3_rx: qcom,msm-dai-q6-sb-3-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16390>; + }; + + sb_3_tx: qcom,msm-dai-q6-sb-3-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16391>; + }; + + sb_4_rx: qcom,msm-dai-q6-sb-4-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16392>; + }; + + sb_4_tx: qcom,msm-dai-q6-sb-4-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16393>; + }; + + sb_5_tx: qcom,msm-dai-q6-sb-5-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16395>; + }; + + sb_5_rx: qcom,msm-dai-q6-sb-5-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16394>; + }; + + bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <12288>; + }; + + bt_sco_tx: qcom,msm-dai-q6-bt-sco-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <12289>; + }; + + int_fm_rx: qcom,msm-dai-q6-int-fm-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <12292>; + }; + + int_fm_tx: qcom,msm-dai-q6-int-fm-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <12293>; + }; + + afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <224>; + }; + + afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <225>; + }; + + afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <241>; + }; + + afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <240>; + }; + + afe_loopback_tx: qcom,msm-dai-q6-afe-loopback-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <24577>; + }; + + incall_record_rx: qcom,msm-dai-q6-incall-record-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <32771>; + }; + + incall_record_tx: qcom,msm-dai-q6-incall-record-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <32772>; + }; + + incall_music_rx: qcom,msm-dai-q6-incall-music-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <32773>; + }; + + incall_music_2_rx: qcom,msm-dai-q6-incall-music-2-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <32770>; + }; + + sb_6_rx: qcom,msm-dai-q6-sb-6-rx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <16396>; + }; + }; + + hostless: qcom,msm-pcm-hostless { + compatible = "qcom,msm-pcm-hostless"; + }; + + dai_pri_auxpcm: qcom,msm-pri-auxpcm { + compatible = "qcom,msm-auxpcm-dev"; + qcom,msm-cpudai-auxpcm-mode = <0>, <0>; + qcom,msm-cpudai-auxpcm-sync = <1>, <1>; + qcom,msm-cpudai-auxpcm-frame = <5>, <4>; + qcom,msm-cpudai-auxpcm-quant = <2>, <2>; + qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>; + qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>; + qcom,msm-cpudai-auxpcm-data = <0>, <0>; + qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>; + qcom,msm-auxpcm-interface = "primary"; + }; + + hdmi_dba: qcom,msm-hdmi-dba-codec-rx { + compatible = "qcom,msm-hdmi-dba-codec-rx"; + qcom,dba-bridge-chip = "adv7533"; + }; + + qcom,msm-audio-ion { + compatible = "qcom,msm-audio-ion"; + qcom,smmu-version = <1>; + qcom,smmu-enabled; + iommus = <&adsp_io 1>; + }; + + qcom,msm-adsp-loader { + compatible = "qcom,adsp-loader"; + qcom,adsp-state = <0>; + }; + + qcom,avtimer@c0a300c { + compatible = "qcom,avtimer"; + reg = <0x0c0a300c 0x4>, + <0x0c0a3010 0x4>; + reg-names = "avtimer_lsb_addr", "avtimer_msb_addr"; + qcom,clk-div = <27>; + }; + + int_codec: sound { + status = "ok"; + compatible = "qcom,msm8952-audio-codec"; + qcom,model = "msm8952-snd-card-mtp"; + reg = <0xc051000 0x4>, + <0xc051004 0x4>, + <0xc055000 0x4>, + <0xc052000 0x4>; + reg-names = "csr_gp_io_mux_mic_ctl", + "csr_gp_io_mux_spkr_ctl", + "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel", + "csr_gp_io_mux_quin_ctl"; + + qcom,msm-ext-pa = "primary"; + qcom,msm-mclk-freq = <9600000>; + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; + qcom,msm-hs-micbias-type = "internal"; + qcom,msm-micbias1-ext-cap; + qcom,audio-routing = + "RX_BIAS", "MCLK", + "SPK_RX_BIAS", "MCLK", + "INT_LDO_H", "MCLK", + "MIC BIAS External", "Handset Mic", + "MIC BIAS Internal2", "Headset Mic", + "MIC BIAS External", "Secondary Mic", + "AMIC1", "MIC BIAS External", + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External"; + + + qcom,msm-gpios = + "pri_i2s", + "us_eu_gpio", + "quin_i2s"; + qcom,pinctrl-names = + "all_off", + "pri_i2s_act", + "us_eu_gpio_act", + "pri_i2s_us_eu_gpio_act", + "quin_act", + "quin_pri_i2s_act", + "quin_us_eu_gpio_act", + "quin_us_eu_gpio_pri_i2s_act"; + pinctrl-names = + "all_off", + "pri_i2s_act", + "us_eu_gpio_act", + "pri_i2s_us_eu_gpio_act", + "quin_act", + "quin_pri_i2s_act", + "quin_us_eu_gpio_act", + "quin_us_eu_gpio_pri_i2s_act"; + pinctrl-0 = <&cdc_pdm_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-1 = <&cdc_pdm_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-2 = <&cdc_pdm_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_act + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-3 = <&cdc_pdm_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_act + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-4 = <&cdc_pdm_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-5 = <&cdc_pdm_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_sus + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-6 = <&cdc_pdm_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_act + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-7 = <&cdc_pdm_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_act + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&lpa>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", "msm-voip-dsp", + "msm-pcm-voice", "msm-pcm-loopback", + "msm-compress-dsp", "msm-pcm-hostless", + "msm-pcm-afe", "msm-lsm-client", + "msm-pcm-routing", "msm-pcm-lpa"; + asoc-cpu = <&dai_pri_auxpcm>, + <&dai_mi2s0>, <&dai_mi2s1>, + <&dai_mi2s2>, <&dai_mi2s3>, + <&dai_mi2s5>, <&dai_mi2s6>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>, + <&bt_sco_rx>, <&bt_sco_tx>, + <&int_fm_rx>, <&int_fm_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, + <&afe_proxy_rx>, <&afe_proxy_tx>, + <&incall_record_rx>, <&incall_record_tx>, + <&incall_music_rx>, <&incall_music_2_rx>; + asoc-cpu-names = "msm-dai-q6-auxpcm.1", + "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", + "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", + "msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289", + "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293", + "msm-dai-q6-dev.224", "msm-dai-q6-dev.225", + "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", + "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", + "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770"; + }; + + ext_codec: sound-9335 { + status = "disabled"; + compatible = "qcom,msm8952-audio-slim-codec"; + qcom,model = "msm8952-tasha-snd-card"; + reg = <0xc051000 0x4>, + <0xc051004 0x4>, + <0xc055000 0x4>, + <0xc052000 0x4>; + + reg-names = "csr_gp_io_mux_mic_ctl", + "csr_gp_io_mux_spkr_ctl", + "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel", + "csr_gp_io_mux_quin_ctl"; + + qcom,audio-routing = + "AIF4 VI", "MCLK", + "AIF4 VI", "MICBIAS_REGULATOR", + "RX_BIAS", "MCLK", + "MADINPUT", "MCLK", + "AIF4 MAD", "MICBIAS_REGULATOR", + "AMIC2", "MIC BIAS2", + "MIC BIAS2", "Headset Mic", + "AMIC3", "MIC BIAS2", + "MIC BIAS2", "ANCRight Headset Mic", + "AMIC4", "MIC BIAS2", + "MIC BIAS2", "ANCLeft Headset Mic", + "AMIC5", "MIC BIAS3", + "MIC BIAS3", "Handset Mic", + "AMIC6", "MIC BIAS4", + "MIC BIAS4", "Analog Mic6", + "DMIC0", "MIC BIAS1", + "MIC BIAS1", "Digital Mic0", + "DMIC1", "MIC BIAS1", + "MIC BIAS1", "Digital Mic1", + "DMIC2", "MIC BIAS3", + "MIC BIAS3", "Digital Mic2", + "DMIC3", "MIC BIAS3", + "MIC BIAS3", "Digital Mic3", + "DMIC4", "MIC BIAS4", + "MIC BIAS4", "Digital Mic4", + "DMIC5", "MIC BIAS4", + "MIC BIAS4", "Digital Mic5", + "MIC BIAS1", "MICBIAS_REGULATOR", + "MIC BIAS2", "MICBIAS_REGULATOR", + "MIC BIAS3", "MICBIAS_REGULATOR", + "MIC BIAS4", "MICBIAS_REGULATOR", + "SpkrLeft IN", "SPK1 OUT", + "SpkrRight IN", "SPK2 OUT"; + + qcom,hdmi-dba-codec-rx; + + qcom,msm-gpios = + "quin_i2s", + "us_eu_gpio"; + qcom,pinctrl-names = + "all_off", + "quin_act", + "us_eu_gpio_act", + "quin_us_eu_gpio_act"; + pinctrl-names = + "all_off", + "quin_act", + "us_eu_gpio_act", + "quin_us_eu_gpio_act"; + pinctrl-0 = <&pri_tlmm_lines_sus &pri_tlmm_ws_sus + &cross_conn_det_sus>; + pinctrl-1 = <&pri_tlmm_lines_act &pri_tlmm_ws_act + &cross_conn_det_sus>; + pinctrl-2 = <&pri_tlmm_lines_sus &pri_tlmm_ws_sus + &cross_conn_det_act>; + pinctrl-3 = <&pri_tlmm_lines_act &pri_tlmm_ws_act + &cross_conn_det_act>; + + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; + qcom,tasha-mclk-clk-freq = <9600000>; + asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>, + <&loopback>, <&compress>, <&hostless>, + <&afe>, <&lsm>, <&routing>, <&cpe>, <&lpa>; + asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1", + "msm-pcm-dsp.2", "msm-voip-dsp", + "msm-pcm-voice", "msm-pcm-loopback", + "msm-compress-dsp", "msm-pcm-hostless", + "msm-pcm-afe", "msm-lsm-client", + "msm-pcm-routing", "msm-cpe-lsm", + "msm-pcm-lpa"; + asoc-cpu = <&dai_pri_auxpcm>, + <&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s5>, + <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, + <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, + <&afe_pcm_rx>, <&afe_pcm_tx>, + <&afe_proxy_rx>, <&afe_proxy_tx>, + <&incall_record_rx>, <&incall_record_tx>, + <&incall_music_rx>, <&incall_music_2_rx>, + <&sb_5_rx>, <&bt_sco_rx>, + <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>, + <&sb_6_rx>; + asoc-cpu-names = "msm-dai-q6-auxpcm.1", + "msm-dai-q6-mi2s.2", + "msm-dai-q6-mi2s.3", "msm-dai-q6-mi2s.5", + "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385", + "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387", + "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", + "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", + "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", + "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224", + "msm-dai-q6-dev.225", "msm-dai-q6-dev.241", + "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", + "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", + "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394", + "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289", + "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293", + "msm-dai-q6-dev.16396"; + asoc-codec = <&stub_codec>, <&hdmi_dba>; + asoc-codec-names = "msm-stub-codec.1", "msm-hdmi-dba-codec-rx"; + }; + + i2c@78b6000 { + status = "okay"; + tas2557@4c { + compatible = "ti,tas2557"; + reg = <0x4c>; + ti,cdc-reset-gpio = <&tlmm 86 0>; + ti,irq-gpio = <&tlmm 87 0x0>; + ti,i2s-bits = <16>; /* support 16, 24, 32 */ + ti,bypass-tmax = <0>; /* 0, not bypass; 1, bypass */ + status = "ok"; + pinctrl-names = "smartpa_irq_active"; + pinctrl-0 = <&smartpa_irq_active>; + }; + wsa881x_i2c_e: wsa881x-i2c-codec@e { + status = "disabled"; + compatible = "qcom,wsa881x-i2c-codec"; + reg = <0x0e>; + qcom,msm-gpios = "wsa_clk", + "wsa_reset", + "wsa_vi"; + qcom,pinctrl-names = "all_off", + "wsa_clk", + "wsa_active", + "wsa_clk_active", + "wsa_vi", + "wsa_clk_vi", + "wsa_active_vi", + "wsa_all"; + pinctrl-names = "all_off", + "wsa_clk", + "wsa_active", + "wsa_clk_active", + "wsa_vi", + "wsa_clk_vi", + "wsa_active_vi", + "wsa_all"; + pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>; + pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>; + pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>; + pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>; + pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>; + pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>; + pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>; + pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>; + }; + wsa881x_i2c_44: wsa881x-i2c-codec@44 { + status = "disabled"; + + compatible = "qcom,wsa881x-i2c-codec"; + reg = <0x44>; + }; + wsa881x_i2c_f: wsa881x-i2c-codec@f { + status = "disabled"; + + compatible = "qcom,wsa881x-i2c-codec"; + reg = <0x0f>; + qcom,msm-gpios = "wsa_clk", + "wsa_reset", + "wsa_vi"; + qcom,pinctrl-names = "all_off", + "wsa_clk", + "wsa_active", + "wsa_clk_active", + "wsa_vi", + "wsa_clk_vi", + "wsa_active_vi", + "wsa_all"; + pinctrl-names = "all_off", + "wsa_clk", + "wsa_active", + "wsa_clk_active", + "wsa_vi", + "wsa_clk_vi", + "wsa_active_vi", + "wsa_all"; + pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>; + pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>; + pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>; + pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>; + pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>; + pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>; + pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>; + pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>; + }; + wsa881x_i2c_45: wsa881x-i2c-codec@45 { + status = "disabled"; + compatible = "qcom,wsa881x-i2c-codec"; + reg = <0x45>; + }; + }; + + wcd9xxx_intc: wcd9xxx-irq { + status = "disabled"; + compatible = "qcom,wcd9xxx-irq"; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-names = "cdc-int"; + pinctrl-names = "default"; + pinctrl-0 = <&wcd_intr_default>; + }; + + wcd_rst_gpio: wcd_gpio_ctrl { + status = "disabled"; + compatible = "qcom,wcd-gpio-ctrl"; + pinctrl-names = "aud_active", "aud_sleep"; + pinctrl-0 = <&cdc_reset_active>; + pinctrl-1 = <&cdc_reset_sleep>; + }; + + clock_audio: audio_ext_clk { + status = "disabled"; + compatible = "qcom,audio-ref-clk"; + clock-names = "osr_clk"; + qcom,node_has_rpm_clock; + #clock-cells = <1>; + }; +}; + +&adsp_io { + qcom,virtual-addr-pool = <0x10000000 0x0fffffff>; + #iommu-cells = <1>; +}; + +&slim_msm { + status = "disabled"; + dai_slim: msm_dai_slim { + status = "disabled"; + compatible = "qcom,msm-dai-slim"; + elemental-addr = [ff ff ff fe 17 02]; + }; + + wcd9335: tasha_codec { + status = "disabled"; + compatible = "qcom,tasha-slim-pgd"; + elemental-addr = [00 01 A0 01 17 02]; + + interrupt-parent = <&wcd9xxx_intc>; + interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 25 26 27 28 29 + 30>; + + qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>; + + clock-names = "wcd_clk"; + clocks = <&clock_audio clk_audio_pmi_clk>; + + qcom,cdc-static-supplies = + "cdc-vdd-buck", + "cdc-buck-sido", + "cdc-vdd-tx-h", + "cdc-vdd-rx-h", + "cdc-vdd-px"; + + qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias"; + + qcom,cdc-micbias1-mv = <1800>; + qcom,cdc-micbias2-mv = <1800>; + qcom,cdc-micbias3-mv = <1800>; + qcom,cdc-micbias4-mv = <1800>; + + qcom,cdc-mclk-clk-rate = <9600000>; + qcom,cdc-slim-ifd = "tasha-slim-ifd"; + qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 01 17 02]; + qcom,cdc-dmic-sample-rate = <2400000>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-audio.dtsi b/arch/arm/boot/dts/qcom/msm-audio.dtsi index 777fcdf1d27b6..9b05ae5a7c5d6 100644 --- a/arch/arm/boot/dts/qcom/msm-audio.dtsi +++ b/arch/arm/boot/dts/qcom/msm-audio.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -306,7 +307,7 @@ }; int_codec: sound { - status = "disabled"; + status = "ok"; compatible = "qcom,msm8952-audio-codec"; qcom,model = "msm8952-snd-card-mtp"; reg = <0xc051000 0x4>, @@ -322,22 +323,19 @@ qcom,msm-mclk-freq = <9600000>; qcom,msm-mbhc-hphl-swh = <0>; qcom,msm-mbhc-gnd-swh = <0>; - qcom,msm-hs-micbias-type = "external"; + qcom,msm-hs-micbias-type = "internal"; qcom,msm-micbias1-ext-cap; qcom,audio-routing = "RX_BIAS", "MCLK", "SPK_RX_BIAS", "MCLK", "INT_LDO_H", "MCLK", "MIC BIAS External", "Handset Mic", - "MIC BIAS External2", "Headset Mic", + "MIC BIAS Internal2", "Headset Mic", "MIC BIAS External", "Secondary Mic", "AMIC1", "MIC BIAS External", - "AMIC2", "MIC BIAS External2", - "AMIC3", "MIC BIAS External", - "WSA_SPK OUT", "VDD_WSA_SWITCH", - "SpkrMono WSA_IN", "WSA_SPK OUT"; + "AMIC2", "MIC BIAS Internal2", + "AMIC3", "MIC BIAS External"; - qcom,hdmi-dba-codec-rx; qcom,msm-gpios = "pri_i2s", @@ -542,6 +540,19 @@ }; i2c@78b6000 { + status = "okay"; + spkamp@3a {/* max98927 smartpa device*/ + compatible = "maxim,max98927L"; + status = "okay"; + reg = <0x3a>; + mono_stereo_mode = <0>; + interleave_mode = <0>; + vmon-l-slot = <1>; + imon-l-slot = <1>; + vmon-r-slot = <1>; + imon-r-slot = <1>; + maxim,98927-reset-gpio = <&tlmm 89 0>; + }; wsa881x_i2c_e: wsa881x-i2c-codec@e { status = "disabled"; compatible = "qcom,wsa881x-i2c-codec"; diff --git a/arch/arm/boot/dts/qcom/msm-pm8953-e7.dtsi b/arch/arm/boot/dts/qcom/msm-pm8953-e7.dtsi new file mode 100644 index 0000000000000..dee55c017ed78 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-pm8953-e7.dtsi @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&spmi_bus { + + qcom,pm8953@0 { + spmi-slave-container; + reg = <0x0>; + #address-cells = <1>; + #size-cells = <1>; + + pm8953_revid: qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + + qcom,power-on@800 { + compatible = "qcom,qpnp-power-on"; + reg = <0x800 0x100>; + interrupts = <0x0 0x8 0x0>, + <0x0 0x8 0x1>, + <0x0 0x8 0x4>, + <0x0 0x8 0x5>; + interrupt-names = "kpdpwr", "resin", + "resin-bark", "kpdpwr-resin-bark"; + qcom,pon-dbc-delay = <15625>; + qcom,system-reset; + qcom,store-hard-reset-reason; + + qcom,pon_1 { + qcom,pon-type = <0>; + qcom,pull-up = <1>; + qcom,support-reset = <1>; + qcom,s1-timer = <6720>; + qcom,s2-timer = <0>; + qcom,s2-type = <7>; + linux,code = <116>; + }; + + qcom,pon_2 { + qcom,pon-type = <1>; + qcom,pull-up = <1>; + linux,code = <114>; + }; + qcom,pon_3 { + qcom,pon-type = <3>; + qcom,support-reset = <1>; + qcom,pull-up = <1>; + qcom,s1-timer = <3072>; + qcom,s2-timer = <2000>; + qcom,s2-type = <7>; + qcom,use-bark; + }; + }; + + pm8953_temp_alarm: qcom,temp-alarm@2400 { + compatible = "qcom,qpnp-temp-alarm"; + reg = <0x2400 0x100>; + interrupts = <0x0 0x24 0x0>; + label = "pm8953_tz"; + qcom,channel-num = <8>; + qcom,threshold-set = <0>; + qcom,temp_alarm-vadc = <&pm8953_vadc>; + }; + + pm8953_coincell: qcom,coincell@2800 { + compatible = "qcom,qpnp-coincell"; + reg = <0x2800 0x100>; + }; + + pm8953_mpps: mpps { + compatible = "qcom,qpnp-pin"; + spmi-dev-container; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + label = "pm8953-mpp"; + + mpp@a000 { + reg = <0xa000 0x100>; + qcom,pin-num = <1>; + status = "disabled"; + }; + + mpp@a100 { + reg = <0xa100 0x100>; + qcom,pin-num = <2>; + }; + + mpp@a200 { + reg = <0xa200 0x100>; + qcom,pin-num = <3>; + status = "disabled"; + }; + + mpp@a300 { + reg = <0xa300 0x100>; + qcom,pin-num = <4>; + }; + }; + + pm8953_gpios: gpios { + spmi-dev-container; + compatible = "qcom,qpnp-pin"; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + label = "pm8953-gpio"; + + gpio@c000 { + reg = <0xc000 0x100>; + qcom,pin-num = <1>; + status = "disabled"; + }; + + gpio@c100 { + reg = <0xc100 0x100>; + qcom,pin-num = <2>; + status = "disabled"; + }; + + gpio@c200 { + reg = <0xc200 0x100>; + qcom,pin-num = <3>; + status = "disabled"; + }; + + gpio@c300 { + reg = <0xc300 0x100>; + qcom,pin-num = <4>; + status = "disabled"; + }; + + gpio@c400 { + reg = <0xc400 0x100>; + qcom,pin-num = <5>; + status = "disabled"; + }; + + gpio@c500 { + reg = <0xc500 0x100>; + qcom,pin-num = <6>; + status = "disabled"; + }; + + gpio@c600 { + reg = <0xc600 0x100>; + qcom,pin-num = <7>; + status = "disabled"; + }; + + gpio@c700 { + reg = <0xc700 0x100>; + qcom,pin-num = <8>; + /* + status = "disabled"; + */ + qcom,master-en = <0>;/* disable this gpio */ + }; + }; + + pm8953_vadc: vadc@3100 { + compatible = "qcom,qpnp-vadc"; + reg = <0x3100 0x100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x31 0x0>; + interrupt-names = "eoc-int-en-set"; + qcom,adc-bit-resolution = <15>; + qcom,adc-vdd-reference = <1800>; + qcom,vadc-poll-eoc; + + chan@8 { + label = "die_temp"; + reg = <8>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <3>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@9 { + label = "ref_625mv"; + reg = <9>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@a { + label = "ref_1250v"; + reg = <0xa>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@c { + label = "ref_buf_625mv"; + reg = <0xc>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + }; + + pm8953_adc_tm: vadc@3400 { + compatible = "qcom,qpnp-adc-tm"; + reg = <0x3400 0x100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x0 0x34 0x0>, + <0x0 0x34 0x3>, + <0x0 0x34 0x4>; + interrupt-names = "eoc-int-en-set", + "high-thr-en-set", + "low-thr-en-set"; + qcom,adc-bit-resolution = <15>; + qcom,adc-vdd-reference = <1800>; + qcom,adc_tm-vadc = <&pm8953_vadc>; + + }; + + pm8953_rtc: qcom,pm8953_rtc { + spmi-dev-container; + compatible = "qcom,qpnp-rtc"; + #address-cells = <1>; + #size-cells = <1>; + qcom,qpnp-rtc-write = <0>; + qcom,qpnp-rtc-alarm-pwrup = <0>; + + qcom,pm8953_rtc_rw@6000 { + reg = <0x6000 0x100>; + }; + + qcom,pm8953_rtc_alarm@6100 { + reg = <0x6100 0x100>; + interrupts = <0x0 0x61 0x1>; + }; + }; +/* + pm8953_typec: qcom,pm8953_typec@bf00 { + compatible = "qcom,qpnp-typec"; + reg = <0xbf00 0x100>; + interrupts = <0x0 0xbf 0x0>, + <0x0 0xbf 0x1>, + <0x0 0xbf 0x2>, + <0x0 0xbf 0x3>, + <0x0 0xbf 0x4>, + <0x0 0xbf 0x6>, + <0x0 0xbf 0x7>; + + interrupt-names = "vrd-change", + "ufp-detect", + "ufp-detach", + "dfp-detect", + "dfp-detach", + "vbus-err", + "vconn-oc"; + }; +*/ + }; + + pm8953_1: qcom,pm8953@1 { + spmi-slave-container; + reg = <0x1>; + #address-cells = <1>; + #size-cells = <1>; + + pm8953_pwm: pwm@bc00 { + status = "disabled"; + compatible = "qcom,qpnp-pwm"; + reg = <0xbc00 0x100>; + reg-names = "qpnp-lpg-channel-base"; + qcom,channel-id = <0>; + qcom,supported-sizes = <6>, <9>; + #pwm-cells = <2>; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-pm8953.dtsi b/arch/arm/boot/dts/qcom/msm-pm8953.dtsi index 4517a24d0c266..7ebbfd96410da 100644 --- a/arch/arm/boot/dts/qcom/msm-pm8953.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm8953.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -34,12 +35,18 @@ interrupt-names = "kpdpwr", "resin", "resin-bark", "kpdpwr-resin-bark"; qcom,pon-dbc-delay = <15625>; + qcom,s3-debounce = <32>; + qcom,s3-src = "kpdpwr-and-resin"; qcom,system-reset; qcom,store-hard-reset-reason; qcom,pon_1 { qcom,pon-type = <0>; qcom,pull-up = <1>; + qcom,support-reset = <1>; + qcom,s1-timer = <6720>; + qcom,s2-timer = <0>; + qcom,s2-type = <7>; linux,code = <116>; }; @@ -48,6 +55,15 @@ qcom,pull-up = <1>; linux,code = <114>; }; + qcom,pon_3 { + qcom,pon-type = <3>; + qcom,support-reset = <1>; + qcom,pull-up = <1>; + qcom,s1-timer = <3072>; + qcom,s2-timer = <2000>; + qcom,s2-type = <1>; + qcom,use-bark; + }; }; pm8953_temp_alarm: qcom,temp-alarm@2400 { @@ -151,7 +167,10 @@ gpio@c700 { reg = <0xc700 0x100>; qcom,pin-num = <8>; + /* status = "disabled"; + */ + qcom,master-en = <0>;/* disable this gpio */ }; }; @@ -245,7 +264,7 @@ interrupts = <0x0 0x61 0x1>; }; }; - +/* pm8953_typec: qcom,pm8953_typec@bf00 { compatible = "qcom,qpnp-typec"; reg = <0xbf00 0x100>; @@ -265,6 +284,7 @@ "vbus-err", "vconn-oc"; }; +*/ }; pm8953_1: qcom,pm8953@1 { diff --git a/arch/arm/boot/dts/qcom/msm-pmi8940.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8940.dtsi index 59001baad55fe..23b4b350c88cb 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8940.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8940.dtsi @@ -494,6 +494,7 @@ qcom,fs-curr-ua = <20000>; qcom,en-phase-stag; qcom,led-strings-list = [00 01]; + qcom,en-cabc; qcom,en-ext-pfet-sc-pro; qcom,cons-sync-write-delay-us = <1000>; }; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8950-e7.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8950-e7.dtsi new file mode 100644 index 0000000000000..7881789ecfce7 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-pmi8950-e7.dtsi @@ -0,0 +1,662 @@ +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +&spmi_bus { + + qcom,pmi8950@2 { + spmi-slave-container; + reg = <0x2>; + #address-cells = <1>; + #size-cells = <1>; + + pmi8950_revid: qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + + qcom,power-on@800 { + compatible = "qcom,qpnp-power-on"; + reg = <0x800 0x100>; + qcom,secondary-pon-reset; + qcom,hard-reset-poweroff-type = + ; + + pon_perph_reg: qcom,pon_perph_reg { + regulator-name = "pon_spare_reg"; + qcom,pon-spare-reg-addr = <0x8c>; + qcom,pon-spare-reg-bit = <1>; + }; + }; + + pmi8950_vadc: vadc@3100 { + compatible = "qcom,qpnp-vadc"; + reg = <0x3100 0x100>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <0x2 0x31 0x0>; + interrupt-names = "eoc-int-en-set"; + qcom,adc-bit-resolution = <15>; + qcom,adc-vdd-reference = <1800>; + qcom,vadc-poll-eoc; + + chan@0 { + label = "usbin"; + reg = <0>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <4>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@1 { + label = "dcin"; + reg = <1>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <4>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@3 { + label = "vchg_sns"; + reg = <3>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@9 { + label = "ref_625mv"; + reg = <9>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@a { + label = "ref_1250v"; + reg = <0xa>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@d { + label = "chg_temp"; + reg = <0xd>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <16>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@43 { + label = "usb_dp"; + reg = <0x43>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@44 { + label = "usb_dm"; + reg = <0x44>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + chan@10 { + label = "pcba_vadc"; + reg = <0x10>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; //1:1 + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <1>; + qcom,fast-avg-setup = <2>; + }; + }; + + pmi8950_gpios: gpios { + spmi-dev-container; + compatible = "qcom,qpnp-pin"; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + label = "pmi8950-gpio"; + + gpio@c000 { + reg = <0xc000 0x100>; + qcom,pin-num = <1>; + status = "disabled"; + }; + + gpio@c100 { + reg = <0xc100 0x100>; + qcom,pin-num = <2>; + status = "disabled"; + }; + }; + + pmi8950_mpps: mpps { + spmi-dev-container; + compatible = "qcom,qpnp-pin"; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + label = "pmi8950-mpp"; + + mpp@a000 { + reg = <0xa000 0x100>; + qcom,pin-num = <1>; + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + com,ain-route = <0>; /* AMUX 5 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + status = "okay"; + }; + + mpp@a100 { + reg = <0xa100 0x100>; + qcom,pin-num = <2>; + status = "disabled"; + }; + + mpp@a200 { + reg = <0xa200 0x100>; + qcom,pin-num = <3>; + status = "disabled"; + }; + + mpp@a300 { + reg = <0xa300 0x100>; + qcom,pin-num = <4>; + status = "disabled"; + }; + }; + + pmi8950_charger: qcom,qpnp-smbcharger { + spmi-dev-container; + compatible = "qcom,qpnp-smbcharger"; + #address-cells = <1>; + #size-cells = <1>; + + qcom,iterm-ma = <200>; + qcom,float-voltage-mv = <4380>; + qcom,resume-delta-mv = <50>; + qcom,chg-inhibit-fg; + qcom,rparasitics-uohm = <100000>; + qcom,bms-psy-name = "bms"; + qcom,charge-unknown-battery; + qcom,thermal-mitigation = <1500 700 600 0>; + //qcom,parallel-usb-min-current-ma = <1400>; + //qcom,parallel-usb-9v-min-current-ma = <900>; + //qcom,parallel-allowed-lowering-ma = <500>; + qcom,pmic-revid = <&pmi8950_revid>; + qcom,force-aicl-rerun; + qcom,aicl-rerun-period-s = <180>; + qcom,override-usb-current; + qcom,fastchg-current-comp = <1200>; + qcom,float-voltage-comp = <15>; + qcom,chgr@1000 { + reg = <0x1000 0x100>; + interrupts = <0x2 0x10 0x0>, + <0x2 0x10 0x1>, + <0x2 0x10 0x2>, + <0x2 0x10 0x3>, + <0x2 0x10 0x4>, + <0x2 0x10 0x5>, + <0x2 0x10 0x6>, + <0x2 0x10 0x7>; + + interrupt-names = "chg-error", + "chg-inhibit", + "chg-prechg-sft", + "chg-complete-chg-sft", + "chg-p2f-thr", + "chg-rechg-thr", + "chg-taper-thr", + "chg-tcc-thr"; + }; + + qcom,otg@1100 { + reg = <0x1100 0x100>; + interrupts = <0x2 0x11 0x0>, + <0x2 0x11 0x1>, + <0x2 0x11 0x3>; + interrupt-names = "otg-fail", + "otg-oc", + "usbid-change"; + }; + + qcom,bat-if@1200 { + reg = <0x1200 0x100>; + interrupts = <0x2 0x12 0x0>, + <0x2 0x12 0x1>, + <0x2 0x12 0x2>, + <0x2 0x12 0x3>, + <0x2 0x12 0x4>, + <0x2 0x12 0x5>, + <0x2 0x12 0x6>, + <0x2 0x12 0x7>; + + interrupt-names = "batt-hot", + "batt-warm", + "batt-cold", + "batt-cool", + "batt-ov", + "batt-low", + "batt-missing", + "batt-term-missing"; + }; + + qcom,usb-chgpth@1300 { + reg = <0x1300 0x100>; + interrupts = <0x2 0x13 0x0>, + <0x2 0x13 0x1>, + <0x2 0x13 0x2>, + <0x2 0x13 0x5>; + + interrupt-names = "usbin-uv", + "usbin-ov", + "usbin-src-det", + "aicl-done"; + }; + + qcom,dc-chgpth@1400 { + reg = <0x1400 0x100>; + interrupts = <0x2 0x14 0x0>, + <0x2 0x14 0x1>; + interrupt-names = "dcin-uv", + "dcin-ov"; + }; + + qcom,chgr-misc@1600 { + reg = <0x1600 0x100>; + interrupts = <0x2 0x16 0x0>, + <0x2 0x16 0x1>, + <0x2 0x16 0x2>, + <0x2 0x16 0x3>, + <0x2 0x16 0x4>, + <0x2 0x16 0x5>; + + interrupt-names = "power-ok", + "temp-shutdown", + "wdog-timeout", + "flash-fail", + "otst2", + "otst3"; + }; + + smbcharger_charger_otg: qcom,smbcharger-boost-otg { + regulator-name = "smbcharger_charger_otg"; + }; + }; + + pmi8950_fg: qcom,fg { + spmi-dev-container; + compatible = "qcom,qpnp-fg"; + #address-cells = <1>; + #size-cells = <1>; + qcom,resume-soc-raw = <254>; + status = "okay"; + qcom,bcl-lm-threshold-ma = <127>; + qcom,bcl-mh-threshold-ma = <405>; + qcom,fg-iterm-ma = <300>; + qcom,fg-chg-iterm-ma = <200>; + qcom,pmic-revid = <&pmi8950_revid>; + qcom,fg-cutoff-voltage-mv = <3400>; + qcom,cycle-counter-en; + qcom,hold-soc-while-full; + qcom,capacity-learning-on; + qcom,fg-cc-cv-threshold-mv =<4370>; + qcom,vbat-estimate-diff-mv = <200>; + qcom,fg-soc@4000 { + status = "okay"; + reg = <0x4000 0x100>; + interrupts = <0x2 0x40 0x0>, + <0x2 0x40 0x1>, + <0x2 0x40 0x2>, + <0x2 0x40 0x3>, + <0x2 0x40 0x4>, + <0x2 0x40 0x5>, + <0x2 0x40 0x6>; + + interrupt-names = "high-soc", + "low-soc", + "full-soc", + "empty-soc", + "delta-soc", + "first-est-done", + "update-soc"; + }; + + qcom,fg-batt@4100 { + reg = <0x4100 0x100>; + interrupts = <0x2 0x41 0x0>, + <0x2 0x41 0x1>, + <0x2 0x41 0x2>, + <0x2 0x41 0x3>, + <0x2 0x41 0x4>, + <0x2 0x41 0x5>, + <0x2 0x41 0x6>, + <0x2 0x41 0x7>; + + interrupt-names = "soft-cold", + "soft-hot", + "vbatt-low", + "batt-ided", + "batt-id-req", + "batt-unknown", + "batt-missing", + "batt-match"; + }; + + qcom,revid-tp-rev@1f1 { + reg = <0x1f1 0x1>; + }; + + qcom,fg-memif@4400 { + status = "okay"; + reg = <0x4400 0x100>; + interrupts = <0x2 0x44 0x0>, + <0x2 0x44 0x2>; + + interrupt-names = "mem-avail", + "data-rcvry-sug"; + }; + }; + + bcl@4200 { + compatible = "qcom,msm-bcl"; + reg = <0x4200 0xFF 0x88E 0x2>; + reg-names = "fg_user_adc", "pon_spare"; + interrupts = <0x2 0x42 0x0>, + <0x2 0x42 0x1>; + interrupt-names = "bcl-high-ibat-int", + "bcl-low-vbat-int"; + qcom,vbat-scaling-factor = <39000>; + qcom,vbat-gain-numerator = <1>; + qcom,vbat-gain-denominator = <128>; + qcom,vbat-polling-delay-ms = <100>; + qcom,ibat-scaling-factor = <39000>; + qcom,ibat-gain-numerator = <1>; + qcom,ibat-gain-denominator = <128>; + qcom,ibat-offset-numerator = <1200>; + qcom,ibat-offset-denominator = <1>; + qcom,ibat-polling-delay-ms = <100>; + qcom,inhibit-derating-ua = <550000>; + }; + + qcom,leds@a100 { + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + }; + }; + + qcom,pmi8950@3 { + spmi-slave-container; + reg = <0x3>; + #address-cells = <1>; + #size-cells = <1>; + + pmi8950_pwm: pwm@b000 { + status = "disabled"; + compatible = "qcom,qpnp-pwm"; + reg = <0xb000 0x100>; + reg-names = "qpnp-lpg-channel-base"; + qcom,channel-id = <0>; + qcom,supported-sizes = <6>, <9>; + #pwm-cells = <2>; + }; + + labibb: qpnp-labibb-regulator { + status = "okay"; + spmi-dev-container; + compatible = "qcom,qpnp-labibb-regulator"; + #address-cells = <1>; + #size-cells = <1>; + qcom,pmic-revid = <&pmi8950_revid>; + + ibb_regulator: qcom,ibb@dc00 { + reg = <0xdc00 0x100>; + reg-names = "ibb_reg"; + regulator-name = "ibb_reg"; + + regulator-min-microvolt = <4600000>; + regulator-max-microvolt = <6000000>; + + qcom,qpnp-ibb-min-voltage = <1400000>; + qcom,qpnp-ibb-step-size = <100000>; + qcom,qpnp-ibb-slew-rate = <2000000>; + qcom,qpnp-ibb-use-default-voltage; + qcom,qpnp-ibb-init-voltage = <5500000>; + qcom,qpnp-ibb-init-amoled-voltage = <4000000>; + qcom,qpnp-ibb-init-lcd-voltage = <5500000>; + + qcom,qpnp-ibb-soft-start = <1000>; + + qcom,qpnp-ibb-discharge-resistor = <32>; + qcom,qpnp-ibb-lab-pwrup-delay = <8000>; + qcom,qpnp-ibb-lab-pwrdn-delay = <8000>; + qcom,qpnp-ibb-en-discharge; + + qcom,qpnp-ibb-full-pull-down; + qcom,qpnp-ibb-pull-down-enable; + qcom,qpnp-ibb-switching-clock-frequency = <1480>; + qcom,qpnp-ibb-limit-maximum-current = <200>; + qcom,qpnp-ibb-debounce-cycle = <16>; + qcom,qpnp-ibb-limit-max-current-enable; + qcom,qpnp-ibb-ps-enable; + }; + + lab_regulator: qcom,lab@de00 { + reg = <0xde00 0x100>; + reg-names = "lab"; + regulator-name = "lab_reg"; + + regulator-min-microvolt = <4600000>; + regulator-max-microvolt = <6000000>; + + qcom,qpnp-lab-min-voltage = <4600000>; + qcom,qpnp-lab-step-size = <100000>; + qcom,qpnp-lab-slew-rate = <5000>; + qcom,qpnp-lab-use-default-voltage; + qcom,qpnp-lab-init-voltage = <5500000>; + qcom,qpnp-lab-init-amoled-voltage = <4600000>; + qcom,qpnp-lab-init-lcd-voltage = <5500000>; + + qcom,qpnp-lab-soft-start = <800>; + + qcom,qpnp-lab-full-pull-down; + qcom,qpnp-lab-pull-down-enable; + qcom,qpnp-lab-switching-clock-frequency = + <1600>; + qcom,qpnp-lab-limit-maximum-current = <200>; + qcom,qpnp-lab-limit-max-current-enable; + qcom,qpnp-lab-ps-threshold = <40>; + qcom,qpnp-lab-ps-enable; + qcom,qpnp-lab-nfet-size = <100>; + qcom,qpnp-lab-pfet-size = <100>; + qcom,qpnp-lab-max-precharge-time = <500>; + }; + + }; + + wled: qcom,leds@d800 { + compatible = "qcom,qpnp-wled"; + reg = <0xd800 0x100>, + <0xd900 0x100>, + <0xdc00 0x100>, + <0xde00 0x100>; + reg-names = "qpnp-wled-ctrl-base", + "qpnp-wled-sink-base", + "qpnp-wled-ibb-base", + "qpnp-wled-lab-base"; + interrupts = <0x3 0xd8 0x2>; + interrupt-names = "sc-irq"; + status = "okay"; + linux,name = "wled"; + linux,default-trigger = "bkl-trigger"; + qcom,fdbk-output = "auto"; + qcom,vref-mv = <350>; + qcom,switch-freq-khz = <800>; + qcom,ovp-mv = <19400>; + qcom,ilim-ma = <980>; + qcom,boost-duty-ns = <26>; + qcom,mod-freq-khz = <9600>; + qcom,dim-mode = "hybrid"; + qcom,dim-method = "linear"; + qcom,hyb-thres = <625>; + qcom,sync-dly-us = <800>; + qcom,fs-curr-ua = <20000>; + qcom,led-strings-list = [00 01 02]; + qcom,en-cabc; + qcom,en-ext-pfet-sc-pro; + qcom,cons-sync-write-delay-us = <1000>; + }; + + flash_led: qcom,leds@d300 { + compatible = "qcom,qpnp-flash-led"; + status = "okay"; + reg = <0xd300 0x100>; + label = "flash"; + qcom,headroom = <500>; + qcom,startup-dly = <128>; + qcom,clamp-curr = <200>; + qcom,pmic-charger-support; + qcom,self-check-enabled; + qcom,thermal-derate-enabled; + qcom,thermal-derate-threshold = <100>; + qcom,thermal-derate-rate = "5_PERCENT"; + qcom,current-ramp-enabled; + qcom,ramp_up_step = "6P7_US"; + qcom,ramp_dn_step = "6P7_US"; + qcom,vph-pwr-droop-enabled; + qcom,vph-pwr-droop-threshold = <3000>; + qcom,vph-pwr-droop-debounce-time = <10>; + qcom,headroom-sense-ch0-enabled; + qcom,headroom-sense-ch1-enabled; + qcom,pmic-revid = <&pmi8950_revid>; + + pmi8950_flash0: qcom,flash_0 { + label = "flash"; + qcom,led-name = "led:flash_0"; + qcom,default-led-trigger = + "flash0_trigger"; + qcom,max-current = <1000>; + qcom,duration = <1280>; + qcom,id = <0>; + qcom,current = <1000>; + }; + + pmi8950_flash1: qcom,flash_1 { + label = "flash"; + qcom,led-name = "led:flash_1"; + qcom,default-led-trigger = + "flash1_trigger"; + qcom,max-current = <1000>; + qcom,duration = <1280>; + qcom,id = <1>; + qcom,current = <625>; + }; + + pmi8950_torch0: qcom,torch_0 { + label = "torch"; + qcom,led-name = "led:torch_0"; + qcom,default-led-trigger = + "torch0_trigger"; + qcom,max-current = <200>; + qcom,id = <0>; + qcom,current = <120>; + }; + + pmi8950_torch1: qcom,torch_1 { + label = "torch"; + qcom,led-name = "led:torch_1"; + qcom,default-led-trigger = + "torch1_trigger"; + qcom,max-current = <200>; + qcom,id = <1>; + qcom,current = <120>; + }; + + pmi8950_switch: qcom,switch { + label = "switch"; + qcom,led-name = "led:switch"; + qcom,default-led-trigger = + "switch_trigger"; + qcom,max-current = <1000>; + qcom,duration = <1280>; + qcom,id = <2>; + qcom,current = <625>; + reg0 { + regulator-name = "pon_spare_reg"; + }; + }; + }; + + pmi_haptic: qcom,haptic@c000 { + compatible = "qcom,qpnp-haptic"; + reg = <0xc000 0x100>; + interrupts = <0x3 0xc0 0x0>, + <0x3 0xc0 0x1>; + interrupt-names = "sc-irq", "play-irq"; + qcom,pmic-revid = <&pmi8950_revid>; + vcc_pon-supply = <&pon_perph_reg>; + qcom,play-mode = "direct"; + qcom,wave-play-rate-us = <5263>; + qcom,actuator-type = "erm"; + qcom,wave-shape = "square"; + qcom,vmax-mv = <3000>; + qcom,ilim-ma = <800>; + qcom,sc-deb-cycles = <8>; + qcom,int-pwm-freq-khz = <505>; + qcom,en-brake; + qcom,brake-pattern = [03 03 00 00]; + qcom,use-play-irq; + qcom,use-sc-irq; + qcom,wave-samples = [3e 3e 3e 3e 3e 3e 3e 3e]; + qcom,wave-rep-cnt = <1>; + qcom,wave-samp-rep-cnt = <1>; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi index a7146546f309d..9cfc2f65d6095 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8950.dtsi @@ -1,4 +1,5 @@ /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -138,6 +139,16 @@ qcom,hw-settle-time = <0>; qcom,fast-avg-setup = <0>; }; + chan@10 { + label = "pcba_vadc"; + reg = <0x10>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; //1:1 + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <1>; + qcom,fast-avg-setup = <2>; + }; }; pmi8950_gpios: gpios { @@ -174,7 +185,12 @@ mpp@a000 { reg = <0xa000 0x100>; qcom,pin-num = <1>; - status = "disabled"; + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + com,ain-route = <0>; /* AMUX 5 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + status = "okay"; }; mpp@a100 { @@ -202,21 +218,23 @@ #address-cells = <1>; #size-cells = <1>; - qcom,iterm-ma = <100>; - qcom,float-voltage-mv = <4200>; - qcom,resume-delta-mv = <200>; + qcom,iterm-ma = <200>; + qcom,float-voltage-mv = <4400>; + qcom,resume-delta-mv = <50>; qcom,chg-inhibit-fg; qcom,rparasitic-uohm = <100000>; qcom,bms-psy-name = "bms"; + qcom,charge-unknown-battery; qcom,thermal-mitigation = <1500 700 600 0>; - qcom,parallel-usb-min-current-ma = <1400>; - qcom,parallel-usb-9v-min-current-ma = <900>; - qcom,parallel-allowed-lowering-ma = <500>; + //qcom,parallel-usb-min-current-ma = <1400>; + //qcom,parallel-usb-9v-min-current-ma = <900>; + //qcom,parallel-allowed-lowering-ma = <500>; qcom,pmic-revid = <&pmi8950_revid>; qcom,force-aicl-rerun; qcom,aicl-rerun-period-s = <180>; - qcom,autoadjust-vfloat; - + qcom,override-usb-current; + qcom,fastchg-current-comp = <900>; + qcom,float-voltage-comp = <16>; qcom,chgr@1000 { reg = <0x1000 0x100>; interrupts = <0x2 0x10 0x0>, @@ -317,17 +335,20 @@ compatible = "qcom,qpnp-fg"; #address-cells = <1>; #size-cells = <1>; - qcom,resume-soc = <95>; + qcom,resume-soc-raw = <253>; status = "okay"; qcom,bcl-lm-threshold-ma = <127>; qcom,bcl-mh-threshold-ma = <405>; - qcom,fg-iterm-ma = <150>; - qcom,fg-chg-iterm-ma = <100>; + qcom,fg-iterm-ma = <300>; + qcom,fg-chg-iterm-ma = <200>; qcom,pmic-revid = <&pmi8950_revid>; - qcom,fg-cutoff-voltage-mv = <3500>; + qcom,fg-cutoff-voltage-mv = <3400>; qcom,cycle-counter-en; + qcom,hold-soc-while-full; qcom,capacity-learning-on; - + qcom,capacity-learning-feedback; + qcom,fg-cc-cv-threshold-mv =<4390>; + qcom,vbat-estimate-diff-mv = <250>; qcom,fg-soc@4000 { status = "okay"; reg = <0x4000 0x100>; @@ -519,7 +540,7 @@ qcom,fdbk-output = "auto"; qcom,vref-mv = <350>; qcom,switch-freq-khz = <800>; - qcom,ovp-mv = <29500>; + qcom,ovp-mv = <19400>; qcom,ilim-ma = <980>; qcom,boost-duty-ns = <26>; qcom,mod-freq-khz = <9600>; @@ -528,7 +549,8 @@ qcom,hyb-thres = <625>; qcom,sync-dly-us = <800>; qcom,fs-curr-ua = <20000>; - qcom,led-strings-list = [00 01]; + qcom,led-strings-list = [00 01 02]; + qcom,en-cabc; qcom,en-ext-pfet-sc-pro; qcom,cons-sync-write-delay-us = <1000>; }; @@ -564,7 +586,7 @@ qcom,max-current = <1000>; qcom,duration = <1280>; qcom,id = <0>; - qcom,current = <625>; + qcom,current = <1000>; }; pmi8950_flash1: qcom,flash_1 { @@ -578,6 +600,16 @@ qcom,current = <625>; }; + pmi8950_flashlight: qcom,flashlight { + label = "torch"; + qcom,led-name = "flashlight"; + qcom,default-led-trigger = + "torch0_trigger"; + qcom,max-current = <200>; + qcom,id = <0>; + qcom,current = <120>; + }; + pmi8950_torch0: qcom,torch_0 { label = "torch"; qcom,led-name = "led:torch_0"; @@ -625,7 +657,7 @@ qcom,wave-play-rate-us = <5263>; qcom,actuator-type = "erm"; qcom,wave-shape = "square"; - qcom,vmax-mv = <2000>; + qcom,vmax-mv = <3000>; qcom,ilim-ma = <800>; qcom,sc-deb-cycles = <8>; qcom,int-pwm-freq-khz = <505>; diff --git a/arch/arm/boot/dts/qcom/msm8953-audio-e7.dtsi b/arch/arm/boot/dts/qcom/msm8953-audio-e7.dtsi new file mode 100644 index 0000000000000..c986900f71de7 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-audio-e7.dtsi @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "msm8953-wsa881x.dtsi" + +&int_codec { + qcom,model = "msm8953-snd-card-mtp"; + + qcom,cdc-us-euro-gpios = <&tlmm 63 0>; + qcom,msm-mbhc-hphl-swh = <1>; + qcom,msm-mbhc-gnd-swh = <1>; + qcom,msm-hs-micbias-type = "internal"; + qcom,msm-micbias1-ext-cap; + + qcom,msm-gpios = + "pri_i2s", + "us_eu_gpio", + "quin_i2s", + "comp_gpio"; + qcom,pinctrl-names = + "all_off", + "pri_i2s_act", + "us_eu_gpio_act", + "pri_i2s_us_eu_gpio_act", + "quin_act", + "quin_pri_i2s_act", + "quin_us_eu_gpio_act", + "quin_us_eu_gpio_pri_i2s_act", + "comp_gpio_act", + "comp_gpio_pri_i2s_act", + "comp_gpio_us_eu_gpio_act", + "comp_gpio_pri_i2s_us_eu_gpio_act", + "comp_gpio_quin_act", + "comp_gpio_quin_pri_i2s_act", + "comp_gpio_quin_us_eu_gpio_act", + "comp_gpio_quin_us_eu_gpio_pri_i2s_act"; + + pinctrl-names = + "all_off", + "pri_i2s_act", + "us_eu_gpio_act", + "pri_i2s_us_eu_gpio_act", + "quin_act", + "quin_pri_i2s_act", + "quin_us_eu_gpio_act", + "quin_us_eu_gpio_pri_i2s_act", + "comp_gpio_act", + "comp_gpio_pri_i2s_act", + "comp_gpio_us_eu_gpio_act", + "comp_gpio_pri_i2s_us_eu_gpio_act", + "comp_gpio_quin_act", + "comp_gpio_quin_pri_i2s_act", + "comp_gpio_quin_us_eu_gpio_act", + "comp_gpio_quin_us_eu_gpio_pri_i2s_act"; + + pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_act + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &cross_conn_det_act + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-4 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-5 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &cross_conn_det_sus + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-6 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_sus &cross_conn_det_act + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-7 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus + &cdc_pdm_lines_2_act &cross_conn_det_act + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-8 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-9 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_sus + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-10 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &cross_conn_det_act + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-11 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_act + &pri_tlmm_lines_sus &pri_tlmm_ws_sus>; + pinctrl-12 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &cross_conn_det_sus + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-13 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_sus + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-14 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_sus &cross_conn_det_act + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + pinctrl-15 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act + &cdc_pdm_lines_2_act &cross_conn_det_act + &pri_tlmm_lines_act &pri_tlmm_ws_act>; + + asoc-codec = <&stub_codec>, <&pm8953_diangu_dig>, <&hdmi_dba>; + asoc-codec-names = "msm-stub-codec.1", "cajon_codec", + "msm-hdmi-dba-codec-rx"; + +}; + +&pm8953_gpios { + gpio@c000 { + status = "ok"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,master-en = <1>; + qcom,out-strength = <2>; + }; +}; + +&ext_codec { + qcom,model = "msm8953-tasha-snd-card"; + + qcom,cdc-us-euro-gpios = <&tlmm 63 0>; + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; + + qcom,wsa-max-devs = <2>; + qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>, + <&wsa881x_213>, <&wsa881x_214>; + qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight", + "SpkrLeft", "SpkrRight"; +}; + +&wcd9xxx_intc { + interrupt-parent = <&tlmm>; + interrupts = <73 0>; + qcom,gpio-connect = <&tlmm 73 0>; +}; + +&clock_audio { + qcom,audio-ref-clk-gpio = <&pm8953_gpios 1 0>; + qcom,lpass-mclk-id = "pri_mclk"; + clocks = <&clock_gcc clk_div_clk2>; + pinctrl-names = "sleep", "active"; + pinctrl-0 = <&cdc_mclk2_sleep>; + pinctrl-1 = <&cdc_mclk2_active>; +}; + +&pm8953_1 { + pm8953_diangu_dig: 8953_wcd_codec@f000 { + compatible = "qcom,msm8x16_wcd_codec"; + reg = <0xf000 0x100>; + interrupt-parent = <&spmi_bus>; + interrupts = <0x1 0xf0 0x0>, + <0x1 0xf0 0x1>, + <0x1 0xf0 0x2>, + <0x1 0xf0 0x3>, + <0x1 0xf0 0x4>, + <0x1 0xf0 0x5>, + <0x1 0xf0 0x6>, + <0x1 0xf0 0x7>; + interrupt-names = "spk_cnp_int", + "spk_clip_int", + "spk_ocp_int", + "ins_rem_det1", + "but_rel_det", + "but_press_det", + "ins_rem_det", + "mbhc_int"; + + cdc-vdda-cp-supply = <&pm8953_s4>; + qcom,cdc-vdda-cp-voltage = <1900000 2050000>; + qcom,cdc-vdda-cp-current = <500000>; + + cdc-vdd-io-supply = <&pm8953_l5>; + qcom,cdc-vdd-io-voltage = <1800000 1800000>; + qcom,cdc-vdd-io-current = <5000>; + + cdc-vdd-pa-supply = <&pm8953_s4>; + qcom,cdc-vdd-pa-voltage = <1900000 2050000>; + qcom,cdc-vdd-pa-current = <260000>; + + cdc-vdd-mic-bias-supply = <&pm8953_l13>; + qcom,cdc-vdd-mic-bias-voltage = <3125000 3125000>; + qcom,cdc-vdd-mic-bias-current = <5000>; + + qcom,cdc-mclk-clk-rate = <9600000>; + + qcom,cdc-static-supplies = "cdc-vdd-io", + "cdc-vdd-pa", + "cdc-vdda-cp"; + + qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias"; + qcom,dig-cdc-base-addr = <0xc0f0000>; + }; + + pm8953_diangu_analog: 8953_wcd_codec@f100 { + compatible = "qcom,msm8x16_wcd_codec"; + reg = <0xf100 0x100>; + interrupt-parent = <&spmi_bus>; + interrupts = <0x1 0xf1 0x0>, + <0x1 0xf1 0x1>, + <0x1 0xf1 0x2>, + <0x1 0xf1 0x3>, + <0x1 0xf1 0x4>, + <0x1 0xf1 0x5>; + interrupt-names = "ear_ocp_int", + "hphr_ocp_int", + "hphl_ocp_det", + "ear_cnp_int", + "hphr_cnp_int", + "hphl_cnp_int"; + qcom,dig-cdc-base-addr = <0xc0f0000>; + }; +}; + +&wcd_rst_gpio { + qcom,cdc-rst-n-gpio = <&tlmm 67 0>; +}; + +&wcd9335 { + clock-names = "wcd_clk", "wcd_native_clk"; + clocks = <&clock_audio clk_audio_pmi_clk>, + <&clock_audio clk_audio_ap_clk2>; + + qcom,cdc-reset-gpio = <&tlmm 67 0>; + + cdc-vdd-buck-supply = <&eldo2_8953>; + qcom,cdc-vdd-buck-voltage = <1800000 1800000>; + qcom,cdc-vdd-buck-current = <650000>; + + cdc-buck-sido-supply = <&eldo2_8953>; + qcom,cdc-buck-sido-voltage = <1800000 1800000>; + qcom,cdc-buck-sido-current = <150000>; + + cdc-vdd-tx-h-supply = <&eldo2_8953>; + qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>; + qcom,cdc-vdd-tx-h-current = <25000>; + + cdc-vdd-rx-h-supply = <&eldo2_8953>; + qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>; + qcom,cdc-vdd-rx-h-current = <25000>; + + cdc-vdd-px-supply = <&eldo2_8953>; + qcom,cdc-vdd-px-voltage = <1800000 1800000>; + qcom,cdc-vdd-px-current = <10000>; + + cdc-vdd-mic-bias-supply = <&pm8953_l13>; + qcom,cdc-vdd-mic-bias-voltage = <3125000 3125000>; + qcom,cdc-vdd-mic-bias-current = <15000>; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-audio.dtsi b/arch/arm/boot/dts/qcom/msm8953-audio.dtsi index 386bc5fc7b578..c986900f71de7 100644 --- a/arch/arm/boot/dts/qcom/msm8953-audio.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-audio.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,8 +18,8 @@ qcom,model = "msm8953-snd-card-mtp"; qcom,cdc-us-euro-gpios = <&tlmm 63 0>; - qcom,msm-mbhc-hphl-swh = <0>; - qcom,msm-mbhc-gnd-swh = <0>; + qcom,msm-mbhc-hphl-swh = <1>; + qcom,msm-mbhc-gnd-swh = <1>; qcom,msm-hs-micbias-type = "internal"; qcom,msm-micbias1-ext-cap; @@ -115,12 +116,7 @@ asoc-codec = <&stub_codec>, <&pm8953_diangu_dig>, <&hdmi_dba>; asoc-codec-names = "msm-stub-codec.1", "cajon_codec", "msm-hdmi-dba-codec-rx"; - asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f"; - asoc-wsa-codec-prefixes = "SpkrMono"; - msm-vdd-wsa-switch-supply = <&pm8953_l5>; - qcom,msm-vdd-wsa-switch-voltage = <1800000>; - qcom,msm-vdd-wsa-switch-current = <10000>; }; &pm8953_gpios { diff --git a/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd-e7.dtsi b/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd-e7.dtsi new file mode 100644 index 0000000000000..45cc24e936fa9 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd-e7.dtsi @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; + qcom,switch-source = <&pmi8950_switch>; + }; + + led_flash2: qcom,camera-frontflash { + cell-index = <2>; + compatible = "qcom,camera-frontflash"; + qcom,flash-type = <1>; + gpios = <&tlmm 36 0>; + qcom,gpio-req-tbl-num = <0>; + qcom,gpio-req-tbl-flags = <1>; + qcom,gpio-req-tbl-label = "FRONT_FLASH"; + }; +}; + +&cci { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + qcom,cci-master = <0>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vaf"; + qcom,cam-vreg-min-voltage = <2850000>; + qcom,cam-vreg-max-voltage = <2850000>; + qcom,cam-vreg-op-mode = <80000>; + }; + + eeprom0: qcom,eeprom@ { + cell-index = <0>; + qcom,eeprom-name = "vince_ov12a10_sunny"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xb0>; + qcom,cci-master = <0>; + reg = <0x0>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <5444 0x0 2 0x0 1 0>; + + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom1: qcom,eeprom@1 { + cell-index = <0>; + qcom,eeprom-name = "vince_imx486_ofilm"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xA0>; + qcom,cci-master = <0>; + reg = <0x0>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <5444 0x0 2 0x0 1 0>; + + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom3: qcom,eeprom@3 { + cell-index = <3>; + reg = <0x3>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "vince_ov5675_qtech"; + qcom,slave-addr = <0x6c>; + + qcom,num-blocks = <10>; + qcom,page0 = <1 0x0100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + + qcom,page1 = <1 0x5001 2 0x02 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + + qcom,page2 = <1 0x3d84 2 0xc0 1 1>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <0 0x0 2 0 1 0>; + + qcom,page3 = <1 0x3d88 2 0x70 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + + qcom,page4 = <1 0x3d89 2 0x10 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + + qcom,page5 = <1 0x3d8a 2 0x70 1 0>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <0 0x0 2 0 1 0>; + + qcom,page6 = <1 0x3d8b 2 0x29 1 10>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + + qcom,page7 = <1 0x3d81 2 0x01 1 10>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + + qcom,page8 = <0 0x0 2 0 1 0>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <148 0x7010 2 0 1 5>; + + qcom,page9 = <1 0x5001 2 0x03 1 5>; + qcom,pageen9 = <1 0x0100 2 0x00 1 5>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom4: qcom,eeprom@4 { + cell-index = <4>; + reg = <0x4>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "vince_ov5675_ofilm"; + qcom,slave-addr = <0x6c>; + + qcom,num-blocks = <10>; + qcom,page0 = <1 0x0100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + + qcom,page1 = <1 0x5001 2 0x02 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + + qcom,page2 = <1 0x3d84 2 0xc0 1 1>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <0 0x0 2 0 1 0>; + + qcom,page3 = <1 0x3d88 2 0x70 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + + qcom,page4 = <1 0x3d89 2 0x10 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + + qcom,page5 = <1 0x3d8a 2 0x70 1 0>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <0 0x0 2 0 1 0>; + + qcom,page6 = <1 0x3d8b 2 0x29 1 10>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + + qcom,page7 = <1 0x3d81 2 0x01 1 10>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + + qcom,page8 = <0 0x0 2 0 1 0>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <148 0x7010 2 0 1 5>; + + qcom,page9 = <1 0x5001 2 0x03 1 5>; + qcom,pageen9 = <1 0x0100 2 0x00 1 5>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x0>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,mount-angle = <90>; + qcom,led-flash-src = <&led_flash0>; + qcom,eeprom-src = <&eeprom0 &eeprom1 >; + qcom,actuator-src = <&actuator0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep + &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@2 { + cell-index = <2>; + compatible = "qcom,camera"; + reg = <0x02>; + qcom,csiphy-sd-index = <2>; + qcom,csid-sd-index = <1>; + qcom,mount-angle = <270>; + // qcom,led-flash-src = <&led_flash2>; + // qcom,eeprom-src = <&eeprom3 &eeprom4>; + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front1_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi index da00fb4624aaa..8e3e8c17c376c 100644 --- a/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -11,6 +12,17 @@ * GNU General Public License for more details. */ +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0>; + qcom,torch-source = <&pmi8950_torch0>; + qcom,switch-source = <&pmi8950_switch>; + }; +}; + &cci { actuator0: qcom,actuator@0 { cell-index = <0>; @@ -26,192 +38,713 @@ eeprom0: qcom,eeprom@0 { cell-index = <0>; - compatible = "qcom,eeprom"; - qcom,cci-master = <0>; - reg = <0x0>; - cam_vio-supply = <&pm8953_l6>; - cam_vdig-supply = <&pm8953_l2>; - cam_vaf-supply = <&pm8953_l17>; - qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf"; - qcom,cam-vreg-min-voltage = <0 1100000 2850000>; - qcom,cam-vreg-max-voltage = <0 1100000 2850000>; - qcom,cam-vreg-op-mode = <0 105000 100000>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_default - &cam_sensor_rear_default>; - pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>; - gpios = <&tlmm 26 0>, - <&tlmm 40 0>, - <&tlmm 39 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0", - "CAM_STANDBY0"; - status = "ok"; - clocks = <&clock_gcc clk_mclk0_clk_src>, - <&clock_gcc clk_gcc_camss_mclk0_clk>; - clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <19200000 0>; - }; + qcom,eeprom-name = "sakura_ov12a10_sunny"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xa8>; + qcom,cci-master = <0>; + reg = <0x0>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <7158 0x0 2 0x0 1 0>; + + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom1: qcom,eeprom@1 { + cell-index = <1>; + qcom,eeprom-name = "sakura_imx486_ofilm"; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0xA8>; + qcom,cci-master = <0>; + reg = <0x01>; + qcom,num-blocks = <1>; + qcom,page0 = <0 0x0 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0x0 1 0>; + qcom,mem0 = <7158 0x0 2 0x0 1 0>; + + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "sensor_gpio_standby", "cam_vana", + "cam_vdig", "cam_vio", "cam_vaf", "sensor_cam_mclk", "sensor_gpio_reset", "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <0 0 1 1 1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 0 0 0 0 10 1 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; eeprom2: qcom,eeprom@2 { - cell-index = <2>; - reg = <0x2>; - compatible = "qcom,eeprom"; - qcom,cci-master = <1>; - cam_vdig-supply = <&pm8953_l23>; - cam_vana-supply = <&pm8953_l22>; - cam_vio-supply = <&pm8953_l6>; - qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; - qcom,cam-vreg-min-voltage = <1200000 0 2800000>; - qcom,cam-vreg-max-voltage = <1200000 0 2800000>; - qcom,cam-vreg-op-mode = <105000 0 80000>; - qcom,gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_default - &cam_sensor_front1_default>; - pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>; - gpios = <&tlmm 27 0>, - <&tlmm 129 0>, - <&tlmm 130 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_STANDBY2"; - qcom,sensor-mode = <0>; - status = "ok"; - clocks = <&clock_gcc clk_mclk1_clk_src>, - <&clock_gcc clk_gcc_camss_mclk1_clk>; - clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <19200000 0>; - }; + cell-index = <2>; + reg = <0x2>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "sakura_s5k5e8_ofilm"; + qcom,slave-addr = <0x5A>; + qcom,num-blocks = <27>; + + //init 4 + qcom,page0 = <1 0x0A00 2 0x4 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + //set 4 page + qcom,page1 = <1 0x0A02 2 0x4 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + //read value + qcom,page2 = <1 0x0A00 2 0x1 1 5>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <16 0x0A34 2 0 1 0>; + //init 5 + qcom,page3 = <1 0x0A00 2 0x4 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + //set 5 page + qcom,page4 = <1 0x0A02 2 0x5 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + //read value + qcom,page5 = <1 0x0A00 2 0x1 1 5>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <64 0x0A04 2 0 1 0>; + //init 6 + qcom,page6 = <1 0x0A00 2 0x4 1 1>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + //set 6 page + qcom,page7 = <1 0x0A02 2 0x6 1 1>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + //read value + qcom,page8 = <1 0x0A00 2 0x1 1 5>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <64 0x0A04 2 0 1 0>; + //init 7 + qcom,page9 = <1 0x0A00 2 0x4 1 1>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + //set 7 page + qcom,page10 = <1 0x0A02 2 0x7 1 1>; + qcom,poll10 = <0 0x0 2 0 1 1>; + qcom,mem10 = <0 0x0 2 0 1 0>; + //read value + qcom,page11 = <1 0x0A00 2 0x1 1 5>; + qcom,poll11 = <0 0x0 2 0 1 1>; + qcom,mem11 = <64 0x0A04 2 0 1 0>; + //init 8 + qcom,page12 = <1 0x0A00 2 0x4 1 1>; + qcom,poll12 = <0 0x0 2 0 1 1>; + qcom,mem12 = <0 0x0 2 0 1 0>; + //set 8 page + qcom,page13 = <1 0x0A02 2 0x8 1 1>; + qcom,poll13 = <0 0x0 2 0 1 1>; + qcom,mem13 = <0 0x0 2 0 1 0>; + //read value + qcom,page14 = <1 0x0A00 2 0x1 1 5>; + qcom,poll14 = <0 0x0 2 0 1 1>; + qcom,mem14 = <64 0x0A04 2 0 1 0>; + //init 9 + qcom,page15 = <1 0x0A00 2 0x4 1 1>; + qcom,poll15 = <0 0x0 2 0 1 1>; + qcom,mem15 = <0 0x0 2 0 1 0>; + //set 9 page + qcom,page16 = <1 0x0A02 2 0x9 1 1>; + qcom,poll16 = <0 0x0 2 0 1 1>; + qcom,mem16 = <0 0x0 2 0 1 0>; + //read value + qcom,page17 = <1 0x0A00 2 0x1 1 5>; + qcom,poll17 = <0 0x0 2 0 1 1>; + qcom,mem17 = <64 0x0A04 2 0 1 0>; + //init 10 + qcom,page18 = <1 0x0A00 2 0x4 1 1>; + qcom,poll18 = <0 0x0 2 0 1 1>; + qcom,mem18 = <0 0x0 2 0 1 0>; + //set 10 page + qcom,page19 = <1 0x0A02 2 0x0A 1 1>; + qcom,poll19 = <0 0x0 2 0 1 1>; + qcom,mem19 = <0 0x0 2 0 1 0>; + //read value + qcom,page20 = <1 0x0A00 2 0x1 1 5>; + qcom,poll20 = <0 0x0 2 0 1 1>; + qcom,mem20 = <24 0x0A04 2 0 1 0>; + //init 14 + qcom,page21 = <1 0x0A00 2 0x4 1 1>; + qcom,poll21 = <0 0x0 2 0 1 1>; + qcom,mem21 = <0 0x0 2 0 1 0>; + //set 14 page + qcom,page22 = <1 0x0A02 2 0x0E 1 1>; + qcom,poll22 = <0 0x0 2 0 1 1>; + qcom,mem22 = <0 0x0 2 0 1 0>; + //read value + qcom,page23 = <1 0x0A00 2 0x1 1 5>; + qcom,poll23 = <0 0x0 2 0 1 1>; + qcom,mem23 = <64 0x0A04 2 0 1 0>; + //init 15 + qcom,page24 = <1 0x0A00 2 0x4 1 1>; + qcom,poll24 = <0 0x0 2 0 1 1>; + qcom,mem24 = <0 0x0 2 0 1 0>; + //set 15 page + qcom,page25 = <1 0x0A02 2 0x0F 1 1>; + qcom,poll25 = <0 0x0 2 0 1 1>; + qcom,mem25 = <0 0x0 2 0 1 0>; + //read value + qcom,page26 = <1 0x0A00 2 0x1 1 5>; + qcom,poll26 = <0 0x0 2 0 1 1>; + qcom,mem26 = <15 0x0A04 2 0 1 0>; - qcom,camera@0 { - cell-index = <0>; - compatible = "qcom,camera"; - reg = <0x0>; - qcom,csiphy-sd-index = <0>; - qcom,csid-sd-index = <0>; - qcom,mount-angle = <90>; - qcom,eeprom-src = <&eeprom0>; - qcom,actuator-src = <&actuator0>; - qcom,led-flash-src = <&led_flash0>; cam_vdig-supply = <&pm8953_l2>; - cam_vio-supply = <&pm8953_l6>; - cam_vana-supply = <&pm8953_l22>; - qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; - qcom,cam-vreg-min-voltage = <1200000 0 2800000>; - qcom,cam-vreg-max-voltage = <1200000 0 2800000>; - qcom,cam-vreg-op-mode = <200000 0 80000>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_default - &cam_sensor_rear_default>; - pinctrl-1 = <&cam_sensor_mclk0_sleep - &cam_sensor_rear_sleep>; - gpios = <&tlmm 26 0>, - <&tlmm 40 0>, - <&tlmm 39 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0", - "CAM_STANDBY0"; - qcom,sensor-position = <0>; - qcom,sensor-mode = <0>; - qcom,cci-master = <0>; - status = "ok"; - clocks = <&clock_gcc clk_mclk0_clk_src>, - <&clock_gcc clk_gcc_camss_mclk0_clk>; - clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <24000000 0>; - }; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 41 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom3: qcom,eeprom@3 { + cell-index = <3>; + reg = <0x3>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "sakura_s5k5e8_sunny"; + qcom,slave-addr = <0x5A>; + qcom,num-blocks = <27>; + + //init 4 + qcom,page0 = <1 0x0A00 2 0x4 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + //set 4 page + qcom,page1 = <1 0x0A02 2 0x4 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + //read value + qcom,page2 = <1 0x0A00 2 0x1 1 5>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <16 0x0A34 2 0 1 0>; + //init 5 + qcom,page3 = <1 0x0A00 2 0x4 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + //set 5 page + qcom,page4 = <1 0x0A02 2 0x5 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + //read value + qcom,page5 = <1 0x0A00 2 0x1 1 5>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <64 0x0A04 2 0 1 0>; + //init 6 + qcom,page6 = <1 0x0A00 2 0x4 1 1>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + //set 6 page + qcom,page7 = <1 0x0A02 2 0x6 1 1>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + //read value + qcom,page8 = <1 0x0A00 2 0x1 1 5>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <64 0x0A04 2 0 1 0>; + //init 7 + qcom,page9 = <1 0x0A00 2 0x4 1 1>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + //set 7 page + qcom,page10 = <1 0x0A02 2 0x7 1 1>; + qcom,poll10 = <0 0x0 2 0 1 1>; + qcom,mem10 = <0 0x0 2 0 1 0>; + //read value + qcom,page11 = <1 0x0A00 2 0x1 1 5>; + qcom,poll11 = <0 0x0 2 0 1 1>; + qcom,mem11 = <64 0x0A04 2 0 1 0>; + //init 8 + qcom,page12 = <1 0x0A00 2 0x4 1 1>; + qcom,poll12 = <0 0x0 2 0 1 1>; + qcom,mem12 = <0 0x0 2 0 1 0>; + //set 8 page + qcom,page13 = <1 0x0A02 2 0x8 1 1>; + qcom,poll13 = <0 0x0 2 0 1 1>; + qcom,mem13 = <0 0x0 2 0 1 0>; + //read value + qcom,page14 = <1 0x0A00 2 0x1 1 5>; + qcom,poll14 = <0 0x0 2 0 1 1>; + qcom,mem14 = <64 0x0A04 2 0 1 0>; + //init 9 + qcom,page15 = <1 0x0A00 2 0x4 1 1>; + qcom,poll15 = <0 0x0 2 0 1 1>; + qcom,mem15 = <0 0x0 2 0 1 0>; + //set 9 page + qcom,page16 = <1 0x0A02 2 0x9 1 1>; + qcom,poll16 = <0 0x0 2 0 1 1>; + qcom,mem16 = <0 0x0 2 0 1 0>; + //read value + qcom,page17 = <1 0x0A00 2 0x1 1 5>; + qcom,poll17 = <0 0x0 2 0 1 1>; + qcom,mem17 = <64 0x0A04 2 0 1 0>; + //init 10 + qcom,page18 = <1 0x0A00 2 0x4 1 1>; + qcom,poll18 = <0 0x0 2 0 1 1>; + qcom,mem18 = <0 0x0 2 0 1 0>; + //set 10 page + qcom,page19 = <1 0x0A02 2 0x0A 1 1>; + qcom,poll19 = <0 0x0 2 0 1 1>; + qcom,mem19 = <0 0x0 2 0 1 0>; + //read value + qcom,page20 = <1 0x0A00 2 0x1 1 5>; + qcom,poll20 = <0 0x0 2 0 1 1>; + qcom,mem20 = <24 0x0A04 2 0 1 0>; + //init 14 + qcom,page21 = <1 0x0A00 2 0x4 1 1>; + qcom,poll21 = <0 0x0 2 0 1 1>; + qcom,mem21 = <0 0x0 2 0 1 0>; + //set 14 page + qcom,page22 = <1 0x0A02 2 0x0E 1 1>; + qcom,poll22 = <0 0x0 2 0 1 1>; + qcom,mem22 = <0 0x0 2 0 1 0>; + //read value + qcom,page23 = <1 0x0A00 2 0x1 1 5>; + qcom,poll23 = <0 0x0 2 0 1 1>; + qcom,mem23 = <64 0x0A04 2 0 1 0>; + //init 15 + qcom,page24 = <1 0x0A00 2 0x4 1 1>; + qcom,poll24 = <0 0x0 2 0 1 1>; + qcom,mem24 = <0 0x0 2 0 1 0>; + //set 15 page + qcom,page25 = <1 0x0A02 2 0x0F 1 1>; + qcom,poll25 = <0 0x0 2 0 1 1>; + qcom,mem25 = <0 0x0 2 0 1 0>; + //read value + qcom,page26 = <1 0x0A00 2 0x1 1 5>; + qcom,poll26 = <0 0x0 2 0 1 1>; + qcom,mem26 = <15 0x0A04 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + cam_vaf-supply = <&pm8953_l17>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 41 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom4: qcom,eeprom@4 { + cell-index = <4>; + reg = <0x4>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "sakura_ov5675_ofilm"; + qcom,slave-addr = <0x6c>; + + qcom,num-blocks = <10>; + qcom,page0 = <1 0x0100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + + qcom,page1 = <1 0x5001 2 0x02 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + + qcom,page2 = <1 0x3d84 2 0xc0 1 1>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <0 0x0 2 0 1 0>; + + qcom,page3 = <1 0x3d88 2 0x70 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + + qcom,page4 = <1 0x3d89 2 0x10 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + + qcom,page5 = <1 0x3d8a 2 0x70 1 0>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <0 0x0 2 0 1 0>; + + qcom,page6 = <1 0x3d8b 2 0x29 1 10>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + + qcom,page7 = <1 0x3d81 2 0x01 1 10>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + + qcom,page8 = <0 0x0 2 0 1 0>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <148 0x7010 2 0 1 5>; + + qcom,page9 = <1 0x5001 2 0x03 1 5>; + qcom,pageen9 = <1 0x0100 2 0x00 1 5>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front1_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + eeprom5: qcom,eeprom@5 { + cell-index = <5>; + reg = <0x5>; + compatible = "qcom,eeprom"; + qcom,cci-master = <1>; + + qcom,eeprom-name = "sakura_ov5675_qtech"; + qcom,slave-addr = <0x20>; + + qcom,num-blocks = <10>; + qcom,page0 = <1 0x0100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + + qcom,page1 = <1 0x5001 2 0x02 1 1>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <0 0x0 2 0 1 0>; + + qcom,page2 = <1 0x3d84 2 0xc0 1 1>; + qcom,poll2 = <0 0x0 2 0 1 1>; + qcom,mem2 = <0 0x0 2 0 1 0>; + + qcom,page3 = <1 0x3d88 2 0x70 1 1>; + qcom,poll3 = <0 0x0 2 0 1 1>; + qcom,mem3 = <0 0x0 2 0 1 0>; + + qcom,page4 = <1 0x3d89 2 0x10 1 1>; + qcom,poll4 = <0 0x0 2 0 1 1>; + qcom,mem4 = <0 0x0 2 0 1 0>; + + qcom,page5 = <1 0x3d8a 2 0x70 1 0>; + qcom,poll5 = <0 0x0 2 0 1 1>; + qcom,mem5 = <0 0x0 2 0 1 0>; + + qcom,page6 = <1 0x3d8b 2 0x29 1 10>; + qcom,poll6 = <0 0x0 2 0 1 1>; + qcom,mem6 = <0 0x0 2 0 1 0>; + + qcom,page7 = <1 0x3d81 2 0x01 1 10>; + qcom,poll7 = <0 0x0 2 0 1 1>; + qcom,mem7 = <0 0x0 2 0 1 0>; + + qcom,page8 = <0 0x0 2 0 1 0>; + qcom,poll8 = <0 0x0 2 0 1 1>; + qcom,mem8 = <148 0x7010 2 0 1 5>; + + qcom,page9 = <1 0x5001 2 0x03 1 5>; + qcom,pageen9 = <1 0x0100 2 0x00 1 5>; + qcom,poll9 = <0 0x0 2 0 1 1>; + qcom,mem9 = <0 0x0 2 0 1 0>; + + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front1_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VANA"; + qcom,cam-power-seq-type = "sensor_gpio", "sensor_vreg", + "sensor_vreg", "sensor_vreg", "sensor_clk" , "sensor_gpio"; + qcom,cam-power-seq-val = "sensor_gpio_reset", "cam_vana", + "cam_vdig", "cam_vio", "sensor_cam_mclk", "sensor_gpio_reset"; + qcom,cam-power-seq-cfg-val = <0 1 1 1 24000000 1>; + qcom,cam-power-seq-delay = <1 0 0 0 10 1>; + + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + + qcom,camera@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x0>; + qcom,csiphy-sd-index = <0>; + qcom,csid-sd-index = <0>; + qcom,mount-angle = <90>; + qcom,led-flash-src = <&led_flash0>; + qcom,eeprom-src = <&eeprom0 &eeprom1>; + qcom,actuator-src = <&actuator0>; + cam_vio-supply = <&pm8953_l6>; + cam_vdig-supply = <&pm8953_l2>; + cam_vaf-supply = <&pm8953_l17>; + cam_vana-supply = <&pm8953_l22>; + qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf", + "cam_vana"; + qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>; + qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>; + qcom,cam-vreg-op-mode = <0 105000 100000 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_default + &cam_sensor_rear_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk0_sleep + &cam_sensor_rear_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 26 0>, + <&tlmm 33 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <0>; + status = "ok"; + clocks = <&clock_gcc clk_mclk0_clk_src>, + <&clock_gcc clk_gcc_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + qcom,camera@1 { - cell-index = <1>; - compatible = "qcom,camera"; - reg = <0x1>; - qcom,csiphy-sd-index = <1>; - qcom,csid-sd-index = <1>; - qcom,mount-angle = <90>; - cam_vdig-supply = <&pm8953_l23>; - cam_vana-supply = <&pm8953_l22>; - cam_vio-supply = <&pm8953_l6>; - cam_vaf-supply = <&pm8953_l17>; - qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana", - "cam_vaf"; - qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; - qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>; - qcom,cam-vreg-op-mode = <200000 0 80000 100000>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_default - &cam_sensor_front_default>; - pinctrl-1 = <&cam_sensor_mclk2_sleep - &cam_sensor_front_sleep>; - gpios = <&tlmm 28 0>, - <&tlmm 131 0>, - <&tlmm 132 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1", - "CAM_STANDBY1"; - qcom,sensor-position = <1>; - qcom,sensor-mode = <0>; - qcom,cci-master = <0>; - status = "disabled"; - clocks = <&clock_gcc clk_mclk2_clk_src>, - <&clock_gcc clk_gcc_camss_mclk2_clk>; - clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <24000000 0>; - }; + cell-index = <1>; + compatible = "qcom,camera"; + reg = <0x1>; + qcom,csiphy-sd-index = <1>; + qcom,csid-sd-index = <1>; + qcom,mount-angle = <90>; + qcom,led-flash-src = <&led_flash0>; + qcom,eeprom-src = <&eeprom2 &eeprom3>; + cam_vdig-supply = <&pm8953_l2>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk2_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk2_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 28 0>, + <&tlmm 41 0>; + qcom,gpio-reset = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <1 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_RESET1"; + qcom,sensor-position = <0>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk2_clk_src>, + <&clock_gcc clk_gcc_camss_mclk2_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; qcom,camera@2 { cell-index = <2>; - compatible = "qcom,camera"; - reg = <0x02>; - qcom,csiphy-sd-index = <2>; - qcom,csid-sd-index = <2>; - qcom,mount-angle = <270>; - qcom,eeprom-src = <&eeprom2>; - cam_vdig-supply = <&pm8953_l23>; - cam_vana-supply = <&pm8953_l22>; - cam_vio-supply = <&pm8953_l6>; - qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; - qcom,cam-vreg-min-voltage = <1200000 0 2800000>; - qcom,cam-vreg-max-voltage = <1200000 0 2800000>; - qcom,cam-vreg-op-mode = <105000 0 80000>; - qcom,gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_default - &cam_sensor_front1_default>; - pinctrl-1 = <&cam_sensor_mclk1_sleep - &cam_sensor_front1_sleep>; - gpios = <&tlmm 27 0>, - <&tlmm 129 0>, - <&tlmm 130 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_STANDBY2"; - qcom,sensor-position = <1>; - qcom,sensor-mode = <0>; - qcom,cci-master = <1>; - status = "ok"; - clocks = <&clock_gcc clk_mclk1_clk_src>, - <&clock_gcc clk_gcc_camss_mclk1_clk>; - clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <24000000 0>; - }; + compatible = "qcom,camera"; + reg = <0x02>; + qcom,csiphy-sd-index = <2>; + qcom,csid-sd-index = <2>; + qcom,mount-angle = <270>; + qcom,eeprom-src = <&eeprom4 &eeprom5>; + cam_vdig-supply = <&pm8953_l23>; + cam_vana-supply = <&pm8953_l22>; + cam_vio-supply = <&pm8953_l6>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 0 2800000>; + qcom,cam-vreg-max-voltage = <1200000 0 2800000>; + qcom,cam-vreg-op-mode = <105000 0 80000>; + qcom,gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front1_default + &cam_sensor_rear_vana>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front1_sleep + &cam_sensor_rear_vana_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 129 0>, + <&tlmm 62 0>; + qcom,gpio-reset = <1>; + qcom,gpio-vana = <2>; + qcom,gpio-req-tbl-num = <0 1 2>; + qcom,gpio-req-tbl-flags = <1 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK2", + "CAM_RESET2", + "CAM_VANA"; + qcom,sensor-position = <1>; + qcom,sensor-mode = <0>; + qcom,cci-master = <1>; + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; + clock-names = "cam_src_clk", "cam_clk"; + qcom,clock-rates = <24000000 0>; + }; + }; diff --git a/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi index 01d462da5a9ea..a2b8eced2e600 100644 --- a/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-cdp.dtsi @@ -288,12 +288,14 @@ status = "ok"; }; +/* &pm8953_typec { ss-mux-supply = <&pm8953_l13>; qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&typec_ssmux_config>; }; +*/ &pm8953_gpios { /* GPIO 2 (NFC_CLK_REQ) */ diff --git a/arch/arm/boot/dts/qcom/msm8953-daisy.dtsi b/arch/arm/boot/dts/qcom/msm8953-daisy.dtsi new file mode 100644 index 0000000000000..99328c3ac6f45 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-daisy.dtsi @@ -0,0 +1,2606 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "skeleton64.dtsi" +#include +#include +#include + +/ { + model = "Qualcomm Technologies, Inc. MSM 8953"; + compatible = "qcom,msm8953"; + qcom,msm-id = <293 0x0>; + interrupt-parent = <&intc>; + + chosen { + bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1"; + }; + + firmware: firmware { + android { + compatible = "android,firmware"; + fstab { + compatible = "android,fstab"; + vendor { + compatible = "android,vendor"; + dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor"; + type = "ext4"; + mnt_flags = "ro,barrier=1,discard"; + fsmgr_flags = "wait,verify,slotselect"; + status = "ok"; + }; + system { + compatible = "android,system"; + dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system"; + type = "ext4"; + mnt_flags = "ro,barrier=1,discard"; + fsmgr_flags = "wait,slotselect"; + status = "disable"; + }; + + }; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + other_ext_mem: other_ext_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x84A00000 0x0 0x1E00000>; + }; + + modem_mem: modem_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x86c00000 0x0 0x6a00000>; + }; + + adsp_fw_mem: adsp_fw_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x8d600000 0x0 0x1200000>; + }; + + wcnss_fw_mem: wcnss_fw_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x8e800000 0x0 0x700000>; + }; + + venus_mem: venus_region@0 { + compatible = "shared-dma-pool"; + reusable; + alloc-ranges = <0x0 0x80000000 0x0 0x10000000>; + alignment = <0 0x400000>; + size = <0 0x0800000>; + }; + + secure_mem: secure_region@0 { + compatible = "shared-dma-pool"; + reusable; + alignment = <0 0x400000>; + size = <0 0x09800000>; + }; + + qseecom_mem: qseecom_region@0 { + compatible = "shared-dma-pool"; + reusable; + alignment = <0 0x400000>; + size = <0 0x1000000>; + }; + + adsp_mem: adsp_region@0 { + compatible = "shared-dma-pool"; + reusable; + size = <0 0x400000>; + }; + + dfps_data_mem: dfps_data_mem@90000000 { + reg = <0 0x90000000 0 0x1000>; + label = "dfps_data_mem"; + }; + + cont_splash_mem: splash_region@0x90001000 { + reg = <0x0 0x90001000 0x0 0x13ff000>; + label = "cont_splash_mem"; + }; + + gpu_mem: gpu_region@0 { + compatible = "shared-dma-pool"; + reusable; + alloc-ranges = <0x0 0x80000000 0x0 0x10000000>; + alignment = <0 0x400000>; + size = <0 0x800000>; + }; + pstore_reserve_mem: pstore_reserve_mem_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x9ff00000 0x0 0x00100000>; + }; + }; + + aliases { + /* smdtty devices */ + smd1 = &smdtty_apps_fm; + smd2 = &smdtty_apps_riva_bt_acl; + smd3 = &smdtty_apps_riva_bt_cmd; + smd4 = &smdtty_mbalbridge; + smd5 = &smdtty_apps_riva_ant_cmd; + smd6 = &smdtty_apps_riva_ant_data; + smd7 = &smdtty_data1; + smd8 = &smdtty_data4; + smd11 = &smdtty_data11; + smd21 = &smdtty_data21; + smd36 = &smdtty_loopback; + sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ + sdhc2 = &sdhc_2; /* SDC2 for SD card */ + i2c2 = &i2c_2; + i2c3 = &i2c_3; + i2c5 = &i2c_5; + spi3 = &spi_3; + spi6 = &spi_6; + }; + + soc: soc { }; + +}; + +#include "msm8953-pinctrl.dtsi" +#include "msm8953-cpu.dtsi" +#include "msm8953-gpu.dtsi" +#include "msm8953-ion.dtsi" +#include "msm8953-smp2p.dtsi" +#include "msm-arm-smmu-8953.dtsi" +#include "msm8953-coresight.dtsi" +#include "msm8953-bus.dtsi" +#include "msm8953-iommu-domains.dtsi" +#include "msm8953-vidc.dtsi" +#include "msm8953-pm.dtsi" + +&soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + apc_apm: apm@b111000 { + compatible = "qcom,msm8953-apm"; + reg = <0xb111000 0x1000>; + reg-names = "pm-apcc-glb"; + qcom,apm-post-halt-delay = <0x2>; + qcom,apm-halt-clk-delay = <0x11>; + qcom,apm-resume-clk-delay = <0x10>; + qcom,apm-sel-switch-delay = <0x01>; + }; + + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x0b000000 0x1000>, + <0x0b002000 0x1000>; + }; + + arm64-cpu-erp { + compatible = "arm,arm64-cpu-erp"; + interrupts = <0 275 0>, + <0 276 0>, + <0 273 0>, + <0 274 0>; + interrupt-names = "pri-dbe-irq", + "sec-dbe-irq", + "pri-ext-irq", + "sec-ext-irq"; + poll-delay-ms = <5000>; + }; + + qcom,msm-gladiator@b1c0000 { + compatible = "qcom,msm-gladiator"; + reg = <0x0b1c0000 0x4000>; + reg-names = "gladiator_base"; + interrupts = <0 22 0>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 2 0xff08>, + <1 3 0xff08>, + <1 4 0xff08>, + <1 1 0xff08>; + clock-frequency = <19200000>; + }; + + timer@b120000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0xb120000 0x1000>; + clock-frequency = <19200000>; + + frame@b121000 { + frame-number = <0>; + interrupts = <0 8 0x4>, + <0 7 0x4>; + reg = <0xb121000 0x1000>, + <0xb122000 0x1000>; + }; + + frame@b123000 { + frame-number = <1>; + interrupts = <0 9 0x4>; + reg = <0xb123000 0x1000>; + status = "disabled"; + }; + + frame@b124000 { + frame-number = <2>; + interrupts = <0 10 0x4>; + reg = <0xb124000 0x1000>; + status = "disabled"; + }; + + frame@b125000 { + frame-number = <3>; + interrupts = <0 11 0x4>; + reg = <0xb125000 0x1000>; + status = "disabled"; + }; + + frame@b126000 { + frame-number = <4>; + interrupts = <0 12 0x4>; + reg = <0xb126000 0x1000>; + status = "disabled"; + }; + + frame@b127000 { + frame-number = <5>; + interrupts = <0 13 0x4>; + reg = <0xb127000 0x1000>; + status = "disabled"; + }; + + frame@b128000 { + frame-number = <6>; + interrupts = <0 14 0x4>; + reg = <0xb128000 0x1000>; + status = "disabled"; + }; + }; + qcom,rmtfs_sharedmem@00000000 { + compatible = "qcom,sharedmem-uio"; + reg = <0x00000000 0x00180000>; + reg-names = "rmtfs"; + qcom,client-id = <0x00000001>; + }; + + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x4ab000 0x4>, + <0x193d100 0x4>; + reg-names = "pshold-base", "tcsr-boot-misc-detect"; + }; + + qcom,mpm2-sleep-counter@4a3000 { + compatible = "qcom,mpm2-sleep-counter"; + reg = <0x4a3000 0x1000>; + clock-frequency = <32768>; + }; + + cpu-pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <1 7 0xff00>; + }; + + qcom,sps { + compatible = "qcom,msm_sps_4k"; + qcom,pipe-attr-ee; + }; + + tsens: tsens@4a8000 { + compatible = "qcom,msm8953-tsens"; + reg = <0x4a8000 0x2000>, + <0xa4000 0x1000>; + reg-names = "tsens_physical", "tsens_eeprom_physical"; + interrupts = <0 184 0>, <0 314 0>; + interrupt-names = "tsens-upper-lower", "tsens-critical"; + qcom,client-id = <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + qcom,sensor-id = <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + qcom,sensors = <15>; + qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200 + 3200 3200 3200 3200 3200 3200 3200>; + qcom,valid-status-check; + }; + + qcom,sensor-information { + compatible = "qcom,sensor-information"; + sensor_information0: qcom,sensor-information-0 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor0"; + qcom,scaling-factor = <10>; + }; + + sensor_information1: qcom,sensor-information-1 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor1"; + qcom,scaling-factor = <10>; + }; + + sensor_information2: qcom,sensor-information-2 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor2"; + qcom,alias-name = "pop_mem"; + qcom,scaling-factor = <10>; + }; + + sensor_information3: qcom,sensor-information-3 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor3"; + qcom,scaling-factor = <10>; + }; + + sensor_information4: qcom,sensor-information-4 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor4"; + qcom,scaling-factor = <10>; + }; + + sensor_information5: qcom,sensor-information-5 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor5"; + qcom,scaling-factor = <10>; + }; + + sensor_information6: qcom,sensor-information-6 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor6"; + qcom,scaling-factor = <10>; + }; + + sensor_information7: qcom,sensor-information-7 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor7"; + qcom,scaling-factor = <10>; + }; + + sensor_information8: qcom,sensor-information-8 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor8"; + qcom,scaling-factor = <10>; + qcom,alias-name = "L2_cache_1"; + }; + + sensor_information9: qcom,sensor-information-9 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor9"; + qcom,scaling-factor = <10>; + }; + + sensor_information10: qcom,sensor-information-10 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor10"; + qcom,scaling-factor = <10>; + }; + + sensor_information11: qcom,sensor-information-11 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor11"; + qcom,scaling-factor = <10>; + }; + + sensor_information12: qcom,sensor-information-12 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor12"; + qcom,scaling-factor = <10>; + }; + + sensor_information13: qcom,sensor-information-13 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor13"; + qcom,scaling-factor = <10>; + qcom,alias-name = "L2_cache_0"; + }; + + sensor_information14: qcom,sensor-information-14 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor14"; + qcom,scaling-factor = <10>; + }; + + sensor_information15: qcom,sensor-information-15 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor15"; + qcom,alias-name = "gpu"; + qcom,scaling-factor = <10>; + }; + + sensor_information16: qcom,sensor-information-16 { + qcom,sensor-type = "alarm"; + qcom,sensor-name = "pm8953_tz"; + qcom,scaling-factor = <1000>; + }; + + sensor_information17: qcom,sensor-information-17 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "pa_therm0"; + }; + + sensor_information18: qcom,sensor-information-18 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "pa_therm1"; + }; + + sensor_information19: qcom,sensor-information-19 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "xo_therm"; + }; + + sensor_information20: qcom,sensor-information-20 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "xo_therm_buf"; + }; + + sensor_information21: qcom,sensor-information-21 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "case_therm"; + }; + }; + + mitigation_profile0: qcom,limit_info-0 { + qcom,temperature-sensor = <&sensor_information9>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile1: qcom,limit_info-1 { + qcom,temperature-sensor = <&sensor_information10>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile2: qcom,limit_info-2 { + qcom,temperature-sensor = <&sensor_information11>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile3: qcom,limit_info-3 { + qcom,temperature-sensor = <&sensor_information12>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile4: qcom,limit_info-4 { + qcom,temperature-sensor = <&sensor_information4>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile5: qcom,limit_info-5 { + qcom,temperature-sensor = <&sensor_information5>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile6: qcom,limit_info-6 { + qcom,temperature-sensor = <&sensor_information6>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile7: qcom,limit_info-7 { + qcom,temperature-sensor = <&sensor_information7>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + qcom,msm-thermal { + compatible = "qcom,msm-thermal"; + qcom,sensor-id = <9>; + qcom,poll-ms = <250>; + qcom,limit-temp = <60>; + qcom,temp-hysteresis = <10>; + qcom,freq-step = <2>; + qcom,core-limit-temp = <80>; + qcom,core-temp-hysteresis = <10>; + qcom,hotplug-temp = <105>; + qcom,hotplug-temp-hysteresis = <15>; + qcom,freq-mitigation-temp = <105>; + qcom,freq-mitigation-temp-hysteresis = <15>; + qcom,freq-mitigation-value = <1036800>; + qcom,therm-reset-temp = <115>; + qcom,online-hotplug-core; + qcom,synchronous-cluster-id = <0 1>; + qcom,synchronous-cluster-map = <0 4 &CPU0 &CPU1 &CPU2 &CPU3>, + <1 4 &CPU4 &CPU5 &CPU6 &CPU7>; + qcom,disable-cx-phase-ctrl; + qcom,disable-gfx-phase-ctrl; + qcom,disable-vdd-mx; + qcom,disable-psm; + qcom,disable-ocr; + qcom,vdd-restriction-temp = <5>; + qcom,vdd-restriction-temp-hysteresis = <10>; + vdd-dig-supply = <&pm8953_s2_floor_level>; + vdd-gfx-supply = <&gfx_vreg_corner>; + + qcom,vdd-dig-rstr { + qcom,vdd-rstr-reg = "vdd-dig"; + qcom,levels = ; + qcom,min-level = ; + }; + + qcom,vdd-gfx-rstr { + qcom,vdd-rstr-reg = "vdd-gfx"; + qcom,levels = <5 7 7>; /* Nominal, Turbo, Turbo */ + qcom,min-level = <1>; /* No Request */ + }; + + msm_thermal_freq: qcom,vdd-apps-rstr { + qcom,vdd-rstr-reg = "vdd-apps"; + qcom,levels = <1689600>; + qcom,freq-req; + }; + }; + + qcom,bcl { + compatible = "qcom,bcl"; + qcom,bcl-enable; + qcom,bcl-framework-interface; + qcom,bcl-freq-control-list = <&CPU0 &CPU1 &CPU2 &CPU3 + &CPU4 &CPU5 &CPU6 &CPU7>; + qcom,bcl-hotplug-list = <&CPU6 &CPU7>; + qcom,bcl-soc-hotplug-list = <&CPU4 &CPU5 &CPU6 &CPU7>; + qcom,ibat-monitor { + qcom,low-threshold-uamp = <3400000>; + qcom,high-threshold-uamp = <4200000>; + qcom,mitigation-freq-khz = <1689600>; + qcom,vph-high-threshold-uv = <3500000>; + qcom,vph-low-threshold-uv = <3200000>; + qcom,soc-low-threshold = <10>; + qcom,thermal-handle = <&msm_thermal_freq>; + }; + }; + + qcom,msm-core@a0000 { + compatible = "qcom,apss-core-ea"; + reg = <0xa0000 0x1000>; + qcom,low-hyst-temp = <100>; + qcom,high-hyst-temp = <100>; + + ea0: ea0 { + sensor = <&sensor_information9>; + }; + + ea1: ea1 { + sensor = <&sensor_information10>; + }; + + ea2: ea2 { + sensor = <&sensor_information11>; + }; + + ea3: ea3 { + sensor = <&sensor_information12>; + }; + + ea4: ea4 { + sensor = <&sensor_information4>; + }; + + ea5: ea5 { + sensor = <&sensor_information5>; + }; + + ea6: ea6 { + sensor = <&sensor_information6>; + }; + + ea7: ea7 { + sensor = <&sensor_information7>; + }; + }; + + blsp1_uart0: serial@78af000 { + compatible = "qcom,msm-lsuart-v14"; + reg = <0x78af000 0x200>; + interrupts = <0 107 0>; + status = "disabled"; + clocks = <&clock_gcc clk_gcc_blsp1_uart1_apps_clk>, + <&clock_gcc clk_gcc_blsp1_ahb_clk>; + clock-names = "core_clk", "iface_clk"; + }; + + blsp1_uart1: uart@78b0000 { + compatible = "qcom,msm-hsuart-v14"; + reg = <0x78b0000 0x200>, + <0x7884000 0x1f000>; + reg-names = "core_mem", "bam_mem"; + + interrupt-names = "core_irq", "bam_irq", "wakeup_irq"; + #address-cells = <0>; + interrupt-parent = <&blsp1_uart1>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 108 0 + 1 &intc 0 238 0 + 2 &tlmm 13 0>; + + qcom,inject-rx-on-wakeup; + qcom,rx-char-to-inject = <0xFD>; + qcom,master-id = <86>; + clock-names = "core_clk", "iface_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>, + <&clock_gcc clk_gcc_blsp1_ahb_clk>; + pinctrl-names = "sleep", "default"; + pinctrl-0 = <&hsuart_sleep>; + pinctrl-1 = <&hsuart_active>; + qcom,bam-tx-ep-pipe-index = <2>; + qcom,bam-rx-ep-pipe-index = <3>; + qcom,msm-bus,name = "blsp1_uart1"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <86 512 0 0>, + <86 512 500 800>; + status = "disabled"; + }; + + blsp2_uart0: uart@7aef000 { + compatible = "qcom,msm-hsuart-v14"; + reg = <0x7aef000 0x200>, + <0x7ac4000 0x1f000>; + reg-names = "core_mem", "bam_mem"; + + interrupt-names = "core_irq", "bam_irq", "wakeup_irq"; + #address-cells = <0>; + interrupt-parent = <&blsp2_uart0>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 306 0 + 1 &intc 0 239 0 + 2 &tlmm 17 0>; + + qcom,inject-rx-on-wakeup; + qcom,rx-char-to-inject = <0xFD>; + qcom,master-id = <84>; + clock-names = "core_clk", "iface_clk"; + clocks = <&clock_gcc clk_gcc_blsp2_uart1_apps_clk>, + <&clock_gcc clk_gcc_blsp2_ahb_clk>; + pinctrl-names = "sleep", "default"; + pinctrl-0 = <&blsp2_uart0_sleep>; + pinctrl-1 = <&blsp2_uart0_active>; + qcom,bam-tx-ep-pipe-index = <0>; + qcom,bam-rx-ep-pipe-index = <1>; + qcom,msm-bus,name = "blsp2_uart0"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <84 512 0 0>, + <84 512 500 800>; + status = "disabled"; + }; + + dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */ + #dma-cells = <4>; + compatible = "qcom,sps-dma"; + reg = <0x7884000 0x1f000>; + interrupts = <0 238 0>; + qcom,summing-threshold = <10>; + }; + + dma_blsp2: qcom,sps-dma@7ac4000 { /* BLSP2 */ + #dma-cells = <4>; + compatible = "qcom,sps-dma"; + reg = <0x7ac4000 0x1f000>; + interrupts = <0 239 0>; + qcom,summing-threshold = <10>; + }; + + spi_3: spi@78b7000 { /* BLSP1 QUP3 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x78b7000 0x600>, + <0x7884000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 97 0>, <0 238 0>; + spi-max-frequency = <19200000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi3_default &spi3_cs0_active>; + pinctrl-1 = <&spi3_sleep &spi3_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup3_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <8>; + qcom,bam-producer-pipe-index = <9>; + qcom,master-id = <86>; + }; + + spi_6: spi@7af6000 { /* BLSP2 QUP2 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x7af6000 0x600>, + <0x7ac4000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 300 0>, <0 239 0>; + spi-max-frequency = <50000000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi6_default &spi6_cs0_active>; + pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <6>; + qcom,bam-producer-pipe-index = <7>; + qcom,master-id = <84>; + }; + + i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */ + compatible = "qcom,i2c-msm-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0x78b6000 0x600>; + interrupt-names = "qup_irq"; + interrupts = <0 96 0>; + qcom,clk-freq-out = <400000>; + qcom,clk-freq-in = <19200000>; + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>; + + pinctrl-names = "i2c_active", "i2c_sleep"; + pinctrl-0 = <&i2c_2_active>; + pinctrl-1 = <&i2c_2_sleep>; + qcom,noise-rjct-scl = <0>; + qcom,noise-rjct-sda = <0>; + qcom,master-id = <86>; + dmas = <&dma_blsp1 6 64 0x20000020 0x20>, + <&dma_blsp1 7 32 0x20000020 0x20>; + dma-names = "tx", "rx"; + + /* DSI_TO_HDMI I2C configuration */ + adv7533@39 { + compatible = "adv7533"; + reg = <0x39>; + instance_id = <0>; + adi,video-mode = <3>; /* 3 = 1080p */ + adi,main-addr = <0x39>; + adi,cec-dsi-addr = <0x3C>; + adi,enable-audio; + pinctrl-names = "pmx_adv7533_active", + "pmx_adv7533_suspend"; + pinctrl-0 = <&adv7533_int_active>; + pinctrl-1 = <&adv7533_int_suspend>; + adi,irq-gpio = <&tlmm 90 0x2002>; + hpd-5v-en-supply = <&adv_vreg>; + qcom,supply-names = "hpd-5v-en"; + qcom,min-voltage-level = <0>; + qcom,max-voltage-level = <0>; + qcom,enable-load = <0>; + qcom,disable-load = <0>; + }; + }; + + i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */ + compatible = "qcom,i2c-msm-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0x78b7000 0x600>; + interrupt-names = "qup_irq"; + interrupts = <0 97 0>; + qcom,clk-freq-out = <400000>; + qcom,clk-freq-in = <19200000>; + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>; + + pinctrl-names = "i2c_active", "i2c_sleep"; + pinctrl-0 = <&i2c_3_active>; + pinctrl-1 = <&i2c_3_sleep>; + qcom,noise-rjct-scl = <0>; + qcom,noise-rjct-sda = <0>; + qcom,master-id = <86>; + dmas = <&dma_blsp1 8 64 0x20000020 0x20>, + <&dma_blsp1 9 32 0x20000020 0x20>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2c_5: i2c@7af5000 { /* BLSP2 QUP1 */ + compatible = "qcom,i2c-msm-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0x7af5000 0x600>; + interrupt-names = "qup_irq"; + interrupts = <0 299 0>; + qcom,clk-freq-out = <400000>; + qcom,clk-freq-in = <19200000>; + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup1_i2c_apps_clk>; + + pinctrl-names = "i2c_active", "i2c_sleep"; + pinctrl-0 = <&i2c_5_active>; + pinctrl-1 = <&i2c_5_sleep>; + qcom,noise-rjct-scl = <0>; + qcom,noise-rjct-sda = <0>; + qcom,master-id = <84>; + dmas = <&dma_blsp2 4 64 0x20000020 0x20>, + <&dma_blsp2 5 32 0x20000020 0x20>; + dma-names = "tx", "rx"; + }; + + slim_msm: slim@c140000{ + cell-index = <1>; + compatible = "qcom,slim-ngd"; + reg = <0xc140000 0x2c000>, + <0xc104000 0x2a000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 163 0>, <0 180 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x600000>; + qcom,ea-pc = <0x200>; + status = "disabled"; + }; + + dcc: dcc@b3000 { + compatible = "qcom,dcc"; + reg = <0xb3000 0x1000>, + <0xb4000 0x800>; + reg-names = "dcc-base", "dcc-ram-base"; + + clocks = <&clock_gcc clk_gcc_dcc_clk>; + clock-names = "dcc_clk"; + + qcom,save-reg; + }; + + clock_gcc: qcom,gcc@1800000 { + compatible = "qcom,gcc-8953"; + reg = <0x1800000 0x80000>, + <0x00a4124 0x08>; + reg-names = "cc_base", "efuse"; + vdd_dig-supply = <&pm8953_s2_level>; + #clock-cells = <1>; + }; + + clock_gcc_mdss: qcom,gcc-mdss@1800000 { + compatible = "qcom,gcc-mdss-8953"; + reg = <0x1800000 0x80000>; + reg-names = "cc_base"; + clock-names = "pclk0_src", "pclk1_src", + "byte0_src", "byte1_src"; + clocks = <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>, + <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_mux>, + <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>, + <&mdss_dsi1_pll clk_dsi1pll_byte_clk_mux>; + #clock-cells = <1>; + }; + + clock_debug: qcom,cc-debug@1874000 { + compatible = "qcom,cc-debug-8953"; + reg = <0x1874000 0x4>; + reg-names = "cc_base"; + clocks = <&clock_cpu clk_cpu_debug_pri_mux>; + clock-names = "debug_cpu_clk"; + #clock-cells = <1>; + }; + + clock_gcc_gfx: qcom,gcc-gfx@1800000 { + compatible = "qcom,gcc-gfx-8953"; + reg = <0x1800000 0x80000>; + reg-names = "cc_base"; + vdd_gfx-supply = <&gfx_vreg_corner>; + qcom,gfxfreq-corner = + < 0 0 >, + < 133330000 1 >, /* Min SVS */ + < 216000000 2 >, /* Low SVS */ + < 320000000 3 >, /* SVS */ + < 400000000 4 >, /* SVS Plus */ + < 510000000 5 >, /* NOM */ + < 560000000 6 >, /* Nom Plus */ + < 650000000 7 >; /* Turbo */ + #clock-cells = <1>; + }; + + clock_cpu: qcom,cpu-clock-8953@b116000 { + compatible = "qcom,cpu-clock-8953"; + reg = <0xb114000 0x68>, + <0xb014000 0x68>, + <0xb116000 0x400>, + <0xb111050 0x08>, + <0xb011050 0x08>, + <0xb1d1050 0x08>, + <0x00a4124 0x08>; + reg-names = "rcgwr-c0-base", "rcgwr-c1-base", + "c0-pll", "c0-mux", "c1-mux", + "cci-mux", "efuse"; + vdd-mx-supply = <&pm8953_s7_level_ao>; + vdd-cl-supply = <&apc_vreg>; + clocks = <&clock_gcc clk_xo_a_clk_src>; + clock-names = "xo_a"; + qcom,num-clusters = <2>; + qcom,speed0-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>, + < 1958400000 6>, + < 2016000000 7>; + qcom,speed0-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>, + < 783360000 6>, + < 806400000 7>; + qcom,speed2-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>, + < 1958400000 6>, + < 2016000000 7>; + qcom,speed2-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>, + < 783360000 6>, + < 806400000 7>; + qcom,speed7-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>, + < 1958400000 6>, + < 2016000000 7>, + < 2150400000 8>, + < 2208000000 9>; + qcom,speed7-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>, + < 783360000 6>, + < 806400000 7>, + < 860160000 8>, + < 883200000 9>; + qcom,speed6-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>; + qcom,speed6-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>; + #clock-cells = <1>; + }; + + msm_cpufreq: qcom,msm-cpufreq { + compatible = "qcom,msm-cpufreq"; + clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk", + "cpu3_clk", "cpu4_clk", "cpu5_clk", + "cpu6_clk", "cpu7_clk"; + clocks = <&clock_cpu clk_cci_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>; + + qcom,cpufreq-table = + < 652800 >, + < 1036800 >, + < 1401600 >, + < 1689600 >, + < 1804800 >, + < 1958400 >, + < 2016000 >, + < 2150400 >, + < 2208000 >; + }; + + cpubw: qcom,cpubw { + compatible = "qcom,devbw"; + governor = "cpufreq"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + qcom,bw-tbl = + < 769 /* 100.8 MHz */ >, + < 1611 /* 211.2 MHz */ >, /*Low SVS*/ + < 2124 /* 278.4 MHz */ >, + < 2929 /* 384 MHz */ >, + < 3221 /* 422.4 MHz */ >, /* SVS */ + < 4248 /* 556.8 MHz */ >, + < 5126 /* 672 MHz */ >, + < 5859 /* 768 MHz */ >, /* SVS+ */ + < 6152 /* 806.4 MHz */ >, + < 6445 /* 844.8 MHz */ >, /* NOM */ + < 7104 /* 931.2 MHz */ >; /* TURBO */ + }; + + mincpubw: qcom,mincpubw { + compatible = "qcom,devbw"; + governor = "cpufreq"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + qcom,bw-tbl = + < 769 /* 100.8 MHz */ >, + < 1611 /* 211.2 MHz */ >, /*Low SVS*/ + < 2124 /* 278.4 MHz */ >, + < 2929 /* 384 MHz */ >, + < 3221 /* 422.4 MHz */ >, /* SVS */ + < 4248 /* 556.8 MHz */ >, + < 5126 /* 672 MHz */ >, + < 5859 /* 768 MHz */ >, /* SVS+ */ + < 6152 /* 806.4 MHz */ >, + < 6445 /* 844.8 MHz */ >, /* NOM */ + < 7104 /* 931.2 MHz */ >; /* TURBO */ + }; + + qcom,cpu-bwmon { + compatible = "qcom,bimc-bwmon2"; + reg = <0x408000 0x300>, <0x401000 0x200>; + reg-names = "base", "global_base"; + interrupts = <0 183 4>; + qcom,mport = <0>; + qcom,target-dev = <&cpubw>; + }; + + devfreq-cpufreq { + cpubw-cpufreq { + target-dev = <&cpubw>; + cpu-to-dev-map = + < 652800 1611>, + < 1036800 3221>, + < 1401600 5859>, + < 1689600 6445>, + < 1804800 7104>, + < 1958400 7104>, + < 2208000 7104>; + }; + + mincpubw-cpufreq { + target-dev = <&mincpubw>; + cpu-to-dev-map = + < 652800 1611 >, + < 1401600 3221 >, + < 2208000 5859 >; + }; + }; + + rpm_bus: qcom,rpm-smd { + compatible = "qcom,rpm-smd"; + rpm-channel-name = "rpm_requests"; + rpm-channel-type = <15>; /* SMD_APPS_RPM */ + }; + + qcom,ipc-spinlock@1905000 { + compatible = "qcom,ipc-spinlock-sfpb"; + reg = <0x1905000 0x8000>; + qcom,num-locks = <8>; + }; + + qcom,smem@86300000 { + compatible = "qcom,smem"; + reg = <0x86300000 0x100000>, + <0x0b011008 0x4>, + <0x60000 0x8000>, + <0x193d000 0x8>; + reg-names = "smem", "irq-reg-base", + "aux-mem1", "smem_targ_info_reg"; + qcom,mpu-enabled; + + qcom,smd-modem { + compatible = "qcom,smd"; + qcom,smd-edge = <0>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x1000>; + interrupts = <0 25 1>; + label = "modem"; + qcom,not-loadable; + }; + + qcom,smsm-modem { + compatible = "qcom,smsm"; + qcom,smsm-edge = <0>; + qcom,smsm-irq-offset = <0x0>; + qcom,smsm-irq-bitmask = <0x2000>; + interrupts = <0 26 1>; + }; + + qcom,smd-wcnss { + compatible = "qcom,smd"; + qcom,smd-edge = <6>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x20000>; + interrupts = <0 142 1>; + label = "wcnss"; + }; + + qcom,smsm-wcnss { + compatible = "qcom,smsm"; + qcom,smsm-edge = <6>; + qcom,smsm-irq-offset = <0x0>; + qcom,smsm-irq-bitmask = <0x80000>; + interrupts = <0 144 1>; + }; + + qcom,smd-adsp { + compatible = "qcom,smd"; + qcom,smd-edge = <1>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x100>; + interrupts = <0 289 1>; + label = "adsp"; + }; + + qcom,smsm-adsp { + compatible = "qcom,smsm"; + qcom,smsm-edge = <1>; + qcom,smsm-irq-offset = <0x0>; + qcom,smsm-irq-bitmask = <0x200>; + interrupts = <0 290 1>; + }; + + qcom,smd-rpm { + compatible = "qcom,smd"; + qcom,smd-edge = <15>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x1>; + interrupts = <0 168 1>; + label = "rpm"; + qcom,irq-no-suspend; + qcom,not-loadable; + }; + }; + + qcom,wdt@b017000 { + compatible = "qcom,msm-watchdog"; + reg = <0xb017000 0x1000>; + reg-names = "wdt-base"; + interrupts = <0 3 0>, <0 4 0>; + qcom,bark-time = <11000>; + qcom,pet-time = <10000>; + qcom,ipi-ping; + qcom,wakeup-enable; + }; + + qcom,chd { + compatible = "qcom,core-hang-detect"; + qcom,threshold-arr = <0xb1880b0 0xb1980b0 0xb1a80b0 + 0xb1b80b0 0xb0880b0 0xb0980b0 0xb0a80b0 0xb0b80b0>; + qcom,config-arr = <0xb1880b8 0xb1980b8 0xb1a80b8 + 0xb1b80b8 0xb0880b8 0xb0980b8 0xb0a80b8 0xb0b80b8>; + }; + + qcom,msm-rtb { + compatible = "qcom,msm-rtb"; + qcom,rtb-size = <0x100000>; + }; + + qcom,msm-imem@8600000 { + compatible = "qcom,msm-imem"; + reg = <0x08600000 0x1000>; + ranges = <0x0 0x08600000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + mem_dump_table@10 { + compatible = "qcom,msm-imem-mem_dump_table"; + reg = <0x10 8>; + }; + + dload_type@18 { + compatible = "qcom,msm-imem-dload-type"; + reg = <0x18 4>; + }; + + restart_reason@65c { + compatible = "qcom,msm-imem-restart_reason"; + reg = <0x65c 4>; + }; + + boot_stats@6b0 { + compatible = "qcom,msm-imem-boot_stats"; + reg = <0x6b0 32>; + }; + + pil@94c { + compatible = "qcom,msm-imem-pil"; + reg = <0x94c 200>; + + }; + }; + + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + + jtag_fuse: jtagfuse@a601c { + compatible = "qcom,jtag-fuse-v2"; + reg = <0xa601c 0x8>; + reg-names = "fuse-base"; + }; + + sn_fuse: snfuse@0xa4128 { + compatible = "qcom,sn-fuse"; + reg = <0xa4128 0x4>; + reg-names = "sn-base"; + }; + + jtag_mm0: jtagmm@619c000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619c000 0x1000>, + <0x6190000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU0>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm1: jtagmm@619d000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619d000 0x1000>, + <0x6192000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU1>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm2: jtagmm@619e000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619e000 0x1000>, + <0x6194000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU2>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm3: jtagmm@619f000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619f000 0x1000>, + <0x6196000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU3>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm4: jtagmm@61bc000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61bc000 0x1000>, + <0x61b0000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU4>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm5: jtagmm@61bd000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61bd000 0x1000>, + <0x61b2000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU5>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm6: jtagmm@61be000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61be000 0x1000>, + <0x61b4000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU6>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm7: jtagmm@61bf000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61bf000 0x1000>, + <0x61b6000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU7>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + ipa_hw: qcom,ipa@07900000 { + compatible = "qcom,ipa"; + reg = <0x07900000 0x4effc>, <0x07904000 0x26934>; + reg-names = "ipa-base", "bam-base"; + interrupts = <0 228 0>, + <0 230 0>; + interrupt-names = "ipa-irq", "bam-irq"; + qcom,ipa-hw-ver = <6>; /* IPA core version = IPAv2.6L */ + qcom,ipa-hw-mode = <0>; /* IPA hw type = Normal */ + qcom,wan-rx-ring-size = <192>; /* IPA WAN-rx-ring-size*/ + qcom,lan-rx-ring-size = <192>; /* IPA LAN-rx-ring-size*/ + clock-names = "core_clk"; + clocks = <&clock_gcc clk_ipa_clk>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,modem-cfg-emb-pipe-flt; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <90 512 0 0>, /* No BIMC vote (ab=0 Mbps, ib=0 Mbps ~ 0MHZ) */ + <90 512 100000 800000>, /* SVS (ab=100, ib=800 ~ 50MHz) */ + <90 512 100000 1200000>; /* PERF (ab=100, ib=1200 ~ 75MHz) */ + qcom,bus-vector-names = "MIN", "SVS", "PERF"; + }; + + qcom,rmnet-ipa { + compatible = "qcom,rmnet-ipa"; + qcom,rmnet-ipa-ssr; + qcom,ipa-loaduC; + qcom,ipa-advertise-sg-support; + }; + + qcom,smdtty { + compatible = "qcom,smdtty"; + + smdtty_apps_fm: qcom,smdtty-apps-fm { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_FM"; + }; + + smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_BT_ACL"; + }; + + smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_BT_CMD"; + }; + + smdtty_mbalbridge: qcom,smdtty-mbalbridge { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "MBALBRIDGE"; + }; + + smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD"; + }; + + smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA"; + }; + + smdtty_data1: qcom,smdtty-data1 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA1"; + }; + + smdtty_data4: qcom,smdtty-data4 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA4"; + }; + + smdtty_data11: qcom,smdtty-data11 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA11"; + }; + + smdtty_data21: qcom,smdtty-data21 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA21"; + }; + + smdtty_loopback: smdtty-loopback { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "LOOPBACK"; + qcom,smdtty-dev-name = "LOOPBACK_TTY"; + }; + }; + + qcom,smdpkt { + compatible = "qcom,smdpkt"; + + qcom,smdpkt-data5-cntl { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "DATA5_CNTL"; + qcom,smdpkt-dev-name = "smdcntl0"; + }; + + qcom,smdpkt-data22 { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "DATA22"; + qcom,smdpkt-dev-name = "smd22"; + }; + + qcom,smdpkt-data40-cntl { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "DATA40_CNTL"; + qcom,smdpkt-dev-name = "smdcntl8"; + }; + + qcom,smdpkt-apr-apps2 { + qcom,smdpkt-remote = "adsp"; + qcom,smdpkt-port-name = "apr_apps2"; + qcom,smdpkt-dev-name = "apr_apps2"; + }; + + qcom,smdpkt-loopback { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "LOOPBACK"; + qcom,smdpkt-dev-name = "smd_pkt_loopback"; + }; + }; + + qcom,iris-fm { + compatible = "qcom,iris_fm"; + }; + + qcom,wcnss-wlan@0a000000 { + compatible = "qcom,wcnss_wlan"; + reg = <0x0a000000 0x280000>, + <0x0b011008 0x04>, + <0x0a21b000 0x3000>, + <0x03204000 0x00000100>, + <0x03200800 0x00000200>, + <0x0a100400 0x00000200>, + <0x0a205050 0x00000200>, + <0x0a219000 0x00000020>, + <0x0a080488 0x00000008>, + <0x0a080fb0 0x00000008>, + <0x0a08040c 0x00000008>, + <0x0a0120a8 0x00000008>, + <0x0a012448 0x00000008>, + <0x0a080c00 0x00000001>; + + reg-names = "wcnss_mmio", "wcnss_fiq", + "pronto_phy_base", "riva_phy_base", + "riva_ccu_base", "pronto_a2xb_base", + "pronto_ccpu_base", "pronto_saw2_base", + "wlan_tx_phy_aborts","wlan_brdg_err_source", + "wlan_tx_status", "alarms_txctl", + "alarms_tactl", "pronto_mcu_base"; + + interrupts = <0 145 0 0 146 0>; + interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq"; + + qcom,pronto-vddmx-supply = <&pm8953_s7_level_ao>; + qcom,pronto-vddcx-supply = <&pm8953_s2_level>; + qcom,pronto-vddpx-supply = <&pm8953_l5>; + qcom,iris-vddxo-supply = <&pm8953_l7>; + qcom,iris-vddrfa-supply = <&pm8953_l19>; + qcom,iris-vddpa-supply = <&pm8953_l9>; + qcom,iris-vdddig-supply = <&pm8953_l5>; + + qcom,iris-vddxo-voltage-level = <1800000 0 1800000>; + qcom,iris-vddrfa-voltage-level = <1380000 0 1380000>; + qcom,iris-vddpa-voltage-level = <3300000 0 3300000>; + qcom,iris-vdddig-voltage-level = <1800000 0 1800000>; + + qcom,vddmx-voltage-level = ; + qcom,vddcx-voltage-level = ; + qcom,vddpx-voltage-level = <1800000 0 1800000>; + + qcom,iris-vddxo-current = <10000>; + qcom,iris-vddrfa-current = <100000>; + qcom,iris-vddpa-current = <515000>; + qcom,iris-vdddig-current = <10000>; + + qcom,pronto-vddmx-current = <0>; + qcom,pronto-vddcx-current = <0>; + qcom,pronto-vddpx-current = <0>; + + pinctrl-names = "wcnss_default", "wcnss_sleep", + "wcnss_gpio_default"; + pinctrl-0 = <&wcnss_default>; + pinctrl-1 = <&wcnss_sleep>; + pinctrl-2 = <&wcnss_gpio_default>; + + gpios = <&tlmm 76 0>, <&tlmm 77 0>, <&tlmm 78 0>, + <&tlmm 79 0>, <&tlmm 80 0>; + + clocks = <&clock_gcc clk_xo_wlan_clk>, + <&clock_gcc clk_rf_clk2>, + <&clock_debug clk_gcc_debug_mux>, + <&clock_gcc clk_wcnss_m_clk>; + + clock-names = "xo", "rf_clk", "measure", "wcnss_debug"; + + qcom,has-autodetect-xo; + qcom,is-pronto-v3; + qcom,has-pronto-hw; + qcom,has-vsys-adc-channel; + qcom,has-a2xb-split-reg; + qcom,wcnss-adc_tm = <&pm8953_adc_tm>; + }; + + qcom_rng: qrng@e3000 { + compatible = "qcom,msm-rng"; + reg = <0xe3000 0x1000>; + qcom,msm-rng-iface-clk; + qcom,no-qrng-config; + qcom,msm-bus,name = "msm-rng-noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 618 0 0>, /* No vote */ + <1 618 0 800>; /* 100 MB/s */ + clocks = <&clock_gcc clk_gcc_prng_ahb_clk>; + clock-names = "iface_clk"; + }; + + qcom_tzlog: tz-log@08600720 { + compatible = "qcom,tz-log"; + reg = <0x08600720 0x2000>; + }; + + qcom_crypto: qcrypto@720000 { + compatible = "qcom,qcrypto"; + reg = <0x720000 0x20000>, + <0x704000 0x20000>; + reg-names = "crypto-base","crypto-bam-base"; + interrupts = <0 207 0>; + qcom,bam-pipe-pair = <2>; + qcom,ce-hw-instance = <0>; + qcom,ce-device = <0>; + qcom,ce-hw-shared; + qcom,clk-mgmt-sus-res; + qcom,msm-bus,name = "qcrypto-noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 393600 393600>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,use-sw-aes-cbc-ecb-ctr-algo; + qcom,use-sw-aes-xts-algo; + qcom,use-sw-aes-ccm-algo; + qcom,use-sw-ahash-algo; + qcom,use-sw-hmac-algo; + qcom,use-sw-aead-algo; + qcom,ce-opp-freq = <100000000>; + }; + + qcom_cedev: qcedev@720000 { + compatible = "qcom,qcedev"; + reg = <0x720000 0x20000>, + <0x704000 0x20000>; + reg-names = "crypto-base","crypto-bam-base"; + interrupts = <0 207 0>; + qcom,bam-pipe-pair = <1>; + qcom,ce-hw-instance = <0>; + qcom,ce-device = <0>; + qcom,ce-hw-shared; + qcom,msm-bus,name = "qcedev-noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 393600 393600>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,ce-opp-freq = <100000000>; + }; + + qcom_seecom: qseecom@84A00000 { + compatible = "qcom,qseecom"; + reg = <0x84A00000 0x1900000>; + reg-names = "secapp-region"; + qcom,hlos-num-ce-hw-instances = <1>; + qcom,hlos-ce-hw-instance = <0>; + qcom,qsee-ce-hw-instance = <0>; + qcom,disk-encrypt-pipe-pair = <2>; + qcom,support-fde; + qcom,msm-bus,name = "qseecom-noc"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,support-bus-scaling; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 0 0>, + <55 512 120000 1200000>, + <55 512 393600 3936000>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,ce-opp-freq = <100000000>; + }; + + qcom,ipc_router { + compatible = "qcom,ipc_router"; + qcom,node-id = <1>; + }; + + qcom,ipc_router_modem_xprt { + compatible = "qcom,ipc_router_smd_xprt"; + qcom,ch-name = "IPCRTR"; + qcom,xprt-remote = "modem"; + qcom,xprt-linkid = <1>; + qcom,xprt-version = <1>; + qcom,fragmented-data; + qcom,disable-pil-loading; + }; + + qcom,ipc_router_q6_xprt { + compatible = "qcom,ipc_router_smd_xprt"; + qcom,ch-name = "IPCRTR"; + qcom,xprt-remote = "adsp"; + qcom,xprt-linkid = <1>; + qcom,xprt-version = <1>; + qcom,fragmented-data; + }; + + qcom,ipc_router_wcnss_xprt { + compatible = "qcom,ipc_router_smd_xprt"; + qcom,ch-name = "IPCRTR"; + qcom,xprt-remote = "wcnss"; + qcom,xprt-linkid = <1>; + qcom,xprt-version = <1>; + qcom,fragmented-data; + }; + + qcom,adsprpc-mem { + compatible = "qcom,msm-adsprpc-mem-region"; + memory-region = <&adsp_mem>; + }; + + qcom,adsprpc_domains { + compatible = "qcom,msm-fastrpc-legacy-compute-cb"; + qcom,msm_fastrpc_compute_cb { + qcom,adsp-shared-phandle = <&adsp_shared>; + qcom,adsp-shared-sids = + <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>; + qcom,virtual-addr-pool = <0x80000000 0x7FFFFFFF>; + }; + }; + + sdcc1_ice: sdcc1ice@7803000 { + compatible = "qcom,ice"; + reg = <0x7803000 0x8000>; + interrupt-names = "sdcc_ice_nonsec_level_irq", + "sdcc_ice_sec_level_irq"; + interrupts = <0 312 0>, <0 313 0>; + qcom,enable-ice-clk; + clock-names = "ice_core_clk_src", "ice_core_clk", + "bus_clk", "iface_clk"; + clocks = <&clock_gcc clk_sdcc1_ice_core_clk_src>, + <&clock_gcc clk_gcc_sdcc1_ice_core_clk>, + <&clock_gcc clk_gcc_sdcc1_apps_clk>, + <&clock_gcc clk_gcc_sdcc1_ahb_clk>; + qcom,op-freq-hz = <270000000>, <0>, <0>, <0>; + qcom,msm-bus,name = "sdcc_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <78 512 0 0>, /* No vote */ + <78 512 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", "MAX"; + qcom,instance-type = "sdcc"; + }; + + sdhc_1: sdhci@7824900 { + compatible = "qcom,sdhci-msm"; + reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>; + reg-names = "hc_mem", "core_mem", "cmdq_mem"; + + interrupts = <0 123 0>, <0 138 0>; + interrupt-names = "hc_irq", "pwr_irq"; + + sdhc-msm-crypto = <&sdcc1_ice>; + qcom,bus-width = <8>; + + qcom,devfreq,freq-table = <50000000 200000000>; + + qcom,pm-qos-irq-type = "affine_irq"; + qcom,pm-qos-irq-latency = <2 213>; + + qcom,pm-qos-cpu-groups = <0x0f 0xf0>; + qcom,pm-qos-cmdq-latency-us = <2 213>, <2 213>; + + qcom,pm-qos-legacy-latency-us = <2 213>, <2 213>; + + qcom,msm-bus,name = "sdhc1"; + qcom,msm-bus,num-cases = <9>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */ + <78 512 1046 3200>, /* 400 KB/s*/ + <78 512 52286 160000>, /* 20 MB/s */ + <78 512 65360 200000>, /* 25 MB/s */ + <78 512 130718 400000>, /* 50 MB/s */ + <78 512 130718 400000>, /* 100 MB/s */ + <78 512 261438 800000>, /* 200 MB/s */ + <78 512 261438 800000>, /* 400 MB/s */ + <78 512 1338562 4096000>; /* Max. bandwidth */ + qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 + 100000000 200000000 400000000 4294967295>; + + clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>, + <&clock_gcc clk_gcc_sdcc1_apps_clk>, + <&clock_gcc clk_gcc_sdcc1_ice_core_clk>; + clock-names = "iface_clk", "core_clk", "ice_core_clk"; + qcom,ice-clk-rates = <270000000 160000000>; + qcom,large-address-bus; + + status = "disabled"; + }; + + sdhc_2: sdhci@7864900 { + compatible = "qcom,sdhci-msm"; + reg = <0x7864900 0x500>, <0x7864000 0x800>; + reg-names = "hc_mem", "core_mem"; + + interrupts = <0 125 0>, <0 221 0>; + interrupt-names = "hc_irq", "pwr_irq"; + + qcom,bus-width = <4>; + + qcom,pm-qos-irq-type = "affine_irq"; + qcom,pm-qos-irq-latency = <2 213>; + + qcom,pm-qos-cpu-groups = <0x0f 0xf0>; + qcom,pm-qos-legacy-latency-us = <2 213>, <2 213>; + + qcom,devfreq,freq-table = <50000000 200000000>; + + qcom,msm-bus,name = "sdhc2"; + qcom,msm-bus,num-cases = <8>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */ + <81 512 1046 3200>, /* 400 KB/s*/ + <81 512 52286 160000>, /* 20 MB/s */ + <81 512 65360 200000>, /* 25 MB/s */ + <81 512 130718 400000>, /* 50 MB/s */ + <81 512 261438 800000>, /* 100 MB/s */ + <81 512 261438 800000>, /* 200 MB/s */ + <81 512 1338562 4096000>; /* Max. bandwidth */ + qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 + 100000000 200000000 4294967295>; + + clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>, + <&clock_gcc clk_gcc_sdcc2_apps_clk>; + clock-names = "iface_clk", "core_clk"; + + qcom,large-address-bus; + status = "disabled"; + }; + + spmi_bus: qcom,spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x200f000 0x1000>, + <0x2400000 0x800000>, + <0x2c00000 0x800000>, + <0x3800000 0x200000>, + <0x200a000 0x2100>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupts = <0 190 0>; + qcom,pmic-arb-channel = <0>; + qcom,pmic-arb-max-peripherals = <256>; + qcom,pmic-arb-max-periph-interrupts = <256>; + qcom,pmic-arb-ee = <0>; + #interrupt-cells = <3>; + interrupt-controller; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + }; + + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + + qcom,mss@4080000 { + compatible = "qcom,pil-q6v55-mss"; + reg = <0x04080000 0x100>, + <0x0194f000 0x010>, + <0x01950000 0x008>, + <0x01951000 0x008>, + <0x04020000 0x040>, + <0x01871000 0x004>; + reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc", + "rmb_base", "restart_reg"; + + interrupts = <0 24 1>; + vdd_mss-supply = <&pm8953_s1>; + vdd_cx-supply = <&pm8953_s2_level>; + vdd_cx-voltage = ; + vdd_mx-supply = <&pm8953_s7_level_ao>; + vdd_mx-uV = ; + vdd_pll-supply = <&pm8953_l7>; + qcom,vdd_pll = <1800000>; + + clocks = <&clock_gcc clk_xo_pil_mss_clk>, + <&clock_gcc clk_gcc_mss_cfg_ahb_clk>, + <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>, + <&clock_gcc clk_gcc_boot_rom_ahb_clk>; + clock-names = "xo", "iface_clk", "bus_clk", "mem_clk"; + qcom,proxy-clock-names = "xo"; + qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk"; + + qcom,pas-id = <5>; + qcom,pil-mss-memsetup; + qcom,firmware-name = "modem"; + qcom,pil-self-auth; + qcom,sysmon-id = <0>; + qcom,ssctl-instance-id = <0x12>; + qcom,qdsp6v56-1-10; + + /* GPIO inputs from mss */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>; + qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>; + + /* GPIO output to mss */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; + memory-region = <&modem_mem>; + }; + + qcom,lpass@c200000 { + compatible = "qcom,pil-tz-generic"; + reg = <0xc200000 0x00100>; + interrupts = <0 293 1>; + + vdd_cx-supply = <&pm8953_s2_level>; + qcom,proxy-reg-names = "vdd_cx"; + qcom,vdd_cx-uV-uA = ; + + clocks = <&clock_gcc clk_xo_pil_lpass_clk>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>, + <&clock_gcc clk_crypto_clk_src>; + clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,scm_core_clk_src-freq = <80000000>; + + qcom,pas-id = <1>; + qcom,complete-ramdump; + qcom,proxy-timeout-ms = <10000>; + qcom,smem-id = <423>; + qcom,sysmon-id = <1>; + qcom,ssctl-instance-id = <0x14>; + qcom,firmware-name = "adsp"; + + /* GPIO inputs from lpass */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>; + + /* GPIO output to lpass */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>; + + memory-region = <&adsp_fw_mem>; + }; + + qcom,venus@1de0000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x1de0000 0x4000>; + + vdd-supply = <&gdsc_venus>; + qcom,proxy-reg-names = "vdd"; + + clocks = <&clock_gcc clk_gcc_venus0_vcodec0_clk>, + <&clock_gcc clk_gcc_venus0_ahb_clk>, + <&clock_gcc clk_gcc_venus0_axi_clk>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>, + <&clock_gcc clk_crypto_clk_src>; + + clock-names = "core_clk", "iface_clk", "bus_clk", + "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + + qcom,proxy-clock-names = "core_clk", "iface_clk", + "bus_clk", "scm_core_clk", + "scm_iface_clk", "scm_bus_clk", + "scm_core_clk_src"; + qcom,scm_core_clk_src-freq = <80000000>; + + qcom,msm-bus,name = "pil-venus"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <63 512 0 0>, + <63 512 0 304000>; + + qcom,pas-id = <9>; + qcom,proxy-timeout-ms = <100>; + qcom,firmware-name = "venus"; + memory-region = <&venus_mem>; + }; + + qcom,msm-ssc-sensors { + compatible = "qcom,msm-ssc-sensors"; + }; + + qcom,pronto@a21b000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x0a21b000 0x3000>; + interrupts = <0 149 1>; + + vdd_pronto_pll-supply = <&pm8953_l7>; + proxy-reg-names = "vdd_pronto_pll"; + vdd_pronto_pll-uV-uA = <1800000 18000>; + clocks = <&clock_gcc clk_xo_pil_pronto_clk>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>, + <&clock_gcc clk_crypto_clk_src>; + + clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,scm_core_clk_src = <80000000>; + + qcom,pas-id = <6>; + qcom,proxy-timeout-ms = <10000>; + qcom,smem-id = <422>; + qcom,sysmon-id = <6>; + qcom,ssctl-instance-id = <0x13>; + qcom,firmware-name = "wcnss"; + + /* GPIO inputs from wcnss */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_4_in 3 0>; + + /* GPIO output to wcnss */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>; + memory-region = <&wcnss_fw_mem>; + }; + + usb3: ssusb@7000000{ + compatible = "qcom,dwc-usb3-msm"; + reg = <0x07000000 0xfc000>, + <0x0007e000 0x400>; + reg-names = "core_base", + "ahb2phy_base"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + interrupts = <0 136 0>, <0 220 0>, <0 134 0>; + interrupt-names = "hs_phy_irq", "ss_phy_irq", "pwr_event_irq"; + + USB3_GDSC-supply = <&gdsc_usb30>; + qcom,usb-dbm = <&dbm_1p5>; + qcom,msm-bus,name = "usb3"; + qcom,usbin-vadc = <&pmi8950_vadc>; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <1>; + qcom,detect-dpdm-floating; + qcom,msm-bus,vectors-KBps = + <61 512 0 0>, + <61 512 240000 800000>, + <61 512 240000 800000>; + + qcom,dwc-usb3-msm-tx-fifo-size = <21288>; + + clocks = <&clock_gcc clk_gcc_usb30_master_clk>, + <&clock_gcc clk_gcc_pcnoc_usb3_axi_clk>, + <&clock_gcc clk_gcc_usb30_mock_utmi_clk>, + <&clock_gcc clk_gcc_usb30_sleep_clk>, + <&clock_gcc clk_xo_dwc3_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb_clk>; + + clock-names = "core_clk", "iface_clk", "utmi_clk", + "sleep_clk", "xo", "cfg_ahb_clk"; + + dwc3@7000000 { + compatible = "snps,dwc3"; + reg = <0x07000000 0xc8d0>; + interrupt-parent = <&intc>; + interrupts = <0 140 0>; + usb-phy = <&qusb_phy>, <&ssphy>; + tx-fifo-resize; + snps,usb3-u1u2-disable; + snps,nominal-elastic-buffer; + snps,is-utmi-l1-suspend; + snps,hird-threshold = /bits/ 8 <0x0>; + }; + + qcom,usbbam@7104000 { + compatible = "qcom,usb-bam-msm"; + reg = <0x07104000 0x1a934>; + interrupt-parent = <&intc>; + interrupts = <0 135 0>; + + qcom,bam-type = <0>; + qcom,usb-bam-fifo-baseaddr = <0x08605000>; + qcom,usb-bam-num-pipes = <8>; + qcom,ignore-core-reset-ack; + qcom,disable-clk-gating; + qcom,usb-bam-override-threshold = <0x4001>; + qcom,usb-bam-max-mbps-highspeed = <400>; + qcom,usb-bam-max-mbps-superspeed = <3600>; + qcom,reset-bam-on-connect; + + qcom,pipe0 { + label = "ssusb-ipa-out-0"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <0>; + qcom,pipe-num = <0>; + qcom,peer-bam = <1>; + qcom,src-bam-pipe-index = <1>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + + qcom,pipe1 { + label = "ssusb-ipa-in-0"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <1>; + qcom,pipe-num = <0>; + qcom,peer-bam = <1>; + qcom,dst-bam-pipe-index = <0>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + + qcom,pipe2 { + label = "ssusb-qdss-in-0"; + qcom,usb-bam-mem-type = <2>; + qcom,dir = <1>; + qcom,pipe-num = <0>; + qcom,peer-bam = <0>; + qcom,peer-bam-physical-address = <0x06044000>; + qcom,src-bam-pipe-index = <0>; + qcom,dst-bam-pipe-index = <2>; + qcom,data-fifo-offset = <0x0>; + qcom,data-fifo-size = <0xe00>; + qcom,descriptor-fifo-offset = <0xe00>; + qcom,descriptor-fifo-size = <0x200>; + }; + + qcom,pipe3 { + label = "ssusb-dpl-ipa-in-1"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <1>; + qcom,pipe-num = <1>; + qcom,peer-bam = <1>; + qcom,dst-bam-pipe-index = <2>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + }; + }; + + qusb_phy: qusb@79000 { + compatible = "qcom,qusb2phy"; + reg = <0x079000 0x180>, + <0x01841030 0x4>, + <0x0193f044 0x4>, + <0x0193f020 0x4>; + reg-names = "qusb_phy_base", + "ref_clk_addr", + "tcsr_phy_clk_scheme_sel", + "tcsr_phy_level_shift_keeper"; + + USB3_GDSC-supply = <&gdsc_usb30>; + vdd-supply = <&pm8953_l3>; + vdda18-supply = <&pm8953_l7>; + vdda33-supply = <&pm8953_l13>; + qcom,vdd-voltage-level = <0 925000 925000>; + + qcom,qusb-phy-init-seq = <0xF8 0x80 + 0x93 0x84 + 0x83 0x88 + 0xC7 0x8C + 0x14 0x9C + 0x30 0x08 + 0x79 0x0C + 0x21 0x10 + 0x00 0x90 + 0x9F 0x1C + 0x00 0x18>; + phy_type= "utmi"; + + clocks = <&clock_gcc clk_bb_clk1>, + <&clock_gcc clk_gcc_qusb_ref_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb_clk>, + <&clock_gcc clk_gcc_qusb2_phy_reset>, + <&clock_gcc clk_gcc_pcnoc_usb3_axi_clk>, + <&clock_gcc clk_gcc_usb30_master_clk>; + + clock-names = "ref_clk_src", "ref_clk", "cfg_ahb_clk", + "phy_reset", "iface_clk", "core_clk"; + + }; + + usb_nop_phy: usb_nop_phy { + status = "disabled"; + compatible = "usb-nop-xceiv"; + }; + + + ssphy: ssphy@78000 { + compatible = "qcom,usb-ssphy-qmp"; + reg = <0x78000 0x9f8>, + <0x0193f244 0x4>, + <0x0193f044 0x4>; + reg-names = "qmp_phy_base", + "vls_clamp_reg", + "tcsr_phy_clk_scheme_sel"; + qcom,qmp-phy-init-seq = <0xac 0x14 0x1a 0x00 + 0x34 0x08 0x08 0x00 + 0x174 0x30 0x30 0x00 + 0x3c 0x06 0x06 0x00 + 0xb4 0x00 0x00 0x00 + 0xb8 0x08 0x08 0x00 + 0x194 0x06 0x06 0x3e8 + 0x19c 0x01 0x01 0x00 + 0x178 0x00 0x00 0x00 + 0xd0 0x82 0x82 0x00 + 0xdc 0x55 0x55 0x00 + 0xe0 0x55 0x55 0x00 + 0xe4 0x03 0x03 0x00 + 0x78 0x0b 0x0b 0x00 + 0x84 0x16 0x16 0x00 + 0x90 0x28 0x28 0x00 + 0x108 0x80 0x80 0x00 + 0x10c 0x00 0x00 0x00 + 0x184 0x0a 0x0a 0x00 + 0x4c 0x15 0x15 0x00 + 0x50 0x34 0x34 0x00 + 0x54 0x00 0x00 0x00 + 0xc8 0x00 0x00 0x00 + 0x18c 0x00 0x00 0x00 + 0xcc 0x00 0x00 0x00 + 0x128 0x00 0x00 0x00 + 0x0c 0x0a 0x0a 0x00 + 0x10 0x01 0x01 0x00 + 0x1c 0x31 0x31 0x00 + 0x20 0x01 0x01 0x00 + 0x14 0x00 0x00 0x00 + 0x18 0x00 0x00 0x00 + 0x24 0xde 0xde 0x00 + 0x28 0x07 0x07 0x00 + 0x48 0x0f 0x0f 0x00 + 0x70 0x0f 0x0f 0x00 + 0x100 0x80 0x80 0x00 + 0x440 0x0b 0x0b 0x00 + 0x4d8 0x02 0x02 0x00 + 0x4dc 0x6c 0x6c 0x00 + 0x4e0 0xbb 0xbb 0x00 + 0x508 0x77 0x77 0x00 + 0x50c 0x80 0x80 0x00 + 0x514 0x03 0x03 0x00 + 0x51c 0x16 0x16 0x00 + 0x448 0x75 0x75 0x00 + 0x454 0x00 0x00 0x00 + 0x40c 0x0a 0x0a 0x00 + 0x41c 0x06 0x06 0x00 + 0x510 0x00 0x00 0x00 + 0x268 0x45 0x45 0x00 + 0x2ac 0x12 0x12 0x00 + 0x294 0x06 0x06 0x00 + 0x254 0x00 0x00 0x00 + 0x8c8 0x83 0x83 0x00 + 0x8c4 0x02 0x02 0x00 + 0x8cc 0x09 0x09 0x00 + 0x8d0 0xa2 0xa2 0x00 + 0x8d4 0x85 0x85 0x00 + 0x880 0xd1 0xd1 0x00 + 0x884 0x1f 0x1f 0x00 + 0x888 0x47 0x47 0x00 + 0x80c 0x9f 0x9f 0x00 + 0x824 0x17 0x17 0x00 + 0x828 0x0f 0x0f 0x00 + 0x8b8 0x75 0x75 0x00 + 0x8bc 0x13 0x13 0x00 + 0x8b0 0x86 0x86 0x00 + 0x8a0 0x04 0x04 0x00 + 0x88c 0x44 0x44 0x00 + 0x870 0xe7 0xe7 0x00 + 0x874 0x03 0x03 0x00 + 0x878 0x40 0x40 0x00 + 0x87c 0x00 0x00 0x00 + 0x9d8 0x88 0x88 0x00 + 0xffffffff 0xffffffff 0x00 0x00>; + qcom,qmp-phy-reg-offset = <0x988 0x98c 0x990 0x994 + 0x974 0x8d8 0x8dc 0x804 0x800 + 0x808>; + vdd-supply = <&pm8953_l3>; + core-supply = <&pm8953_l7>; + qcom,vdd-voltage-level = <0 925000 925000>; + qcom,vbus-valid-override; + + clocks = <&clock_gcc clk_gcc_usb3_aux_clk>, + <&clock_gcc clk_gcc_usb3_pipe_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb_clk>, + <&clock_gcc clk_gcc_usb3_phy_reset>, + <&clock_gcc clk_gcc_usb3phy_phy_reset>, + <&clock_gcc clk_bb_clk1>, + <&clock_gcc clk_gcc_usb_ss_ref_clk>; + + clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk", "phy_reset", + "phy_phy_reset", "ref_clk_src", "ref_clk"; + + }; + + dbm_1p5: dbm@70f8000 { + compatible = "qcom,usb-dbm-1p5"; + reg = <0x070f8000 0x300>; + qcom,reset-ep-after-lpm-resume; + }; + + android_usb@86000c8 { + compatible = "qcom,android-usb"; + reg = <0x086000c8 0xc8>; + qcom,pm-qos-latency = <2 213 11028>; + }; +}; + +#include "msm-pm8953-rpm-regulator.dtsi" +#include "msm-pm8953.dtsi" +#include "msm8953-regulator.dtsi" +#include "msm-audio.dtsi" +#include "msm8953-audio.dtsi" +#include "msm-gdsc-8916.dtsi" +#include "msm8953-camera.dtsi" +#include "msm8953-mdss.dtsi" +#include "msm8953-mdss-pll.dtsi" + +&gdsc_venus { + clock-names = "bus_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_venus0_axi_clk>, + <&clock_gcc clk_gcc_venus0_vcodec0_clk>; + status = "okay"; +}; + +&gdsc_venus_core0 { + qcom,support-hw-trigger; + clock-names ="core0_clk"; + clocks = <&clock_gcc clk_gcc_venus0_core0_vcodec0_clk>; + status = "okay"; +}; + +&gdsc_mdss { + clock-names = "core_clk", "bus_clk"; + clocks = <&clock_gcc clk_gcc_mdss_mdp_clk>, + <&clock_gcc clk_gcc_mdss_axi_clk>; + proxy-supply = <&gdsc_mdss>; + qcom,proxy-consumer-enable; + status = "okay"; +}; + +&gdsc_oxili_gx { + clock-names = "core_root_clk"; + clocks =<&clock_gcc_gfx clk_gfx3d_clk_src>; + qcom,force-enable-root-clk; + parent-supply = <&gfx_vreg_corner>; + status = "okay"; +}; + +&gdsc_jpeg { + clock-names = "core_clk", "bus_clk"; + clocks = <&clock_gcc clk_gcc_camss_jpeg0_clk>, + <&clock_gcc clk_gcc_camss_jpeg_axi_clk>; + status = "okay"; +}; + +&gdsc_vfe { + clock-names = "core_clk", "bus_clk", "micro_clk", + "csi_clk"; + clocks = <&clock_gcc clk_gcc_camss_vfe0_clk>, + <&clock_gcc clk_gcc_camss_vfe_axi_clk>, + <&clock_gcc clk_gcc_camss_micro_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi_vfe0_clk>; + status = "okay"; +}; + +&gdsc_vfe1 { + clock-names = "core_clk", "bus_clk", "micro_clk", + "csi_clk"; + clocks = <&clock_gcc clk_gcc_camss_vfe1_clk>, + <&clock_gcc clk_gcc_camss_vfe1_axi_clk>, + <&clock_gcc clk_gcc_camss_micro_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi_vfe1_clk>; + status = "okay"; +}; + +&gdsc_cpp { + clock-names = "core_clk", "bus_clk"; + clocks = <&clock_gcc clk_gcc_camss_cpp_clk>, + <&clock_gcc clk_gcc_camss_cpp_axi_clk>; + status = "okay"; +}; + +&gdsc_oxili_cx { + clock-names = "core_clk"; + clocks = <&clock_gcc_gfx clk_gcc_oxili_gfx3d_clk>; + status = "okay"; +}; + +&gdsc_usb30 { + status = "okay"; +}; + +&pm8953_mpps { + mpp@a100 { + /* MPP2 - PA_THERM config */ + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + qcom,ain-route = <1>; /* AMUX 6 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + }; + + mpp@a300 { + /* MPP4 - CASE_THERM config */ + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + qcom,ain-route = <3>; /* AMUX 8 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + }; +}; + +&pm8953_vadc { + chan@5 { + label = "vcoin"; + reg = <5>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@7 { + label = "vph_pwr"; + reg = <7>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@36 { + label = "pa_therm0"; + reg = <0x36>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + }; + + chan@11 { + label = "pa_therm1"; + reg = <0x11>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@32 { + label = "xo_therm"; + reg = <0x32>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <4>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@3c { + label = "xo_therm_buf"; + reg = <0x3c>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <4>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@13 { + label = "case_therm"; + reg = <0x13>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; +}; + +&pm8953_adc_tm { + chan@36 { + label = "pa_therm0"; + reg = <0x36>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,btm-channel-number = <0x48>; + qcom,thermal-node; + }; + + chan@7 { + label = "vph_pwr"; + reg = <0x7>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + qcom,btm-channel-number = <0x68>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-e7.dtsi b/arch/arm/boot/dts/qcom/msm8953-e7.dtsi new file mode 100644 index 0000000000000..c0f60a86028d8 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-e7.dtsi @@ -0,0 +1,2605 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "skeleton64.dtsi" +#include +#include +#include + +/ { + model = "Qualcomm Technologies, Inc. MSM 8953"; + compatible = "qcom,msm8953"; + qcom,msm-id = <293 0x0>; + interrupt-parent = <&intc>; + + chosen { + bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1"; + }; + + firmware: firmware { + android { + compatible = "android,firmware"; + fstab { + compatible = "android,fstab"; + vendor { + compatible = "android,vendor"; + dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor"; + type = "ext4"; + mnt_flags = "ro,barrier=1,discard"; + fsmgr_flags = "wait,verify"; + status = "disable"; + }; + system { + compatible = "android,system"; + dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system"; + type = "ext4"; + mnt_flags = "ro,barrier=1,discard"; + fsmgr_flags = "wait,verify"; + status = "ok"; + }; + + }; + }; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + other_ext_mem: other_ext_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x84A00000 0x0 0x1E00000>; + }; + + modem_mem: modem_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x86c00000 0x0 0x6a00000>; + }; + + adsp_fw_mem: adsp_fw_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x8d600000 0x0 0x1200000>; + }; + + wcnss_fw_mem: wcnss_fw_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x8e800000 0x0 0x700000>; + }; + + venus_mem: venus_region@0 { + compatible = "shared-dma-pool"; + reusable; + alloc-ranges = <0x0 0x80000000 0x0 0x10000000>; + alignment = <0 0x400000>; + size = <0 0x0800000>; + }; + + secure_mem: secure_region@0 { + compatible = "shared-dma-pool"; + reusable; + alignment = <0 0x400000>; + size = <0 0x09800000>; + }; + + qseecom_mem: qseecom_region@0 { + compatible = "shared-dma-pool"; + reusable; + alignment = <0 0x400000>; + size = <0 0x1000000>; + }; + + adsp_mem: adsp_region@0 { + compatible = "shared-dma-pool"; + reusable; + size = <0 0x400000>; + }; + + dfps_data_mem: dfps_data_mem@90000000 { + reg = <0 0x90000000 0 0x1000>; + label = "dfps_data_mem"; + }; + + cont_splash_mem: splash_region@0x90001000 { + reg = <0x0 0x90001000 0x0 0x13ff000>; + label = "cont_splash_mem"; + }; + + gpu_mem: gpu_region@0 { + compatible = "shared-dma-pool"; + reusable; + alloc-ranges = <0x0 0x80000000 0x0 0x10000000>; + alignment = <0 0x400000>; + size = <0 0x800000>; + }; + pstore_reserve_mem: pstore_reserve_mem_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x9ff00000 0x0 0x00100000>; + }; + }; + + aliases { + /* smdtty devices */ + smd1 = &smdtty_apps_fm; + smd2 = &smdtty_apps_riva_bt_acl; + smd3 = &smdtty_apps_riva_bt_cmd; + smd4 = &smdtty_mbalbridge; + smd5 = &smdtty_apps_riva_ant_cmd; + smd6 = &smdtty_apps_riva_ant_data; + smd7 = &smdtty_data1; + smd8 = &smdtty_data4; + smd11 = &smdtty_data11; + smd21 = &smdtty_data21; + smd36 = &smdtty_loopback; + sdhc1 = &sdhc_1; /* SDC1 eMMC slot */ + sdhc2 = &sdhc_2; /* SDC2 for SD card */ + i2c2 = &i2c_2; + i2c3 = &i2c_3; + i2c5 = &i2c_5; + spi3 = &spi_3; + spi6 = &spi_6; + }; + + soc: soc { }; + +}; + +#include "msm8953-pinctrl-e7.dtsi" +#include "msm8953-cpu.dtsi" +#include "msm8953-gpu.dtsi" +#include "msm8953-ion.dtsi" +#include "msm8953-smp2p.dtsi" +#include "msm-arm-smmu-8953.dtsi" +#include "msm8953-coresight.dtsi" +#include "msm8953-bus.dtsi" +#include "msm8953-iommu-domains.dtsi" +#include "msm8953-vidc.dtsi" +#include "msm8953-pm.dtsi" + +&soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + apc_apm: apm@b111000 { + compatible = "qcom,msm8953-apm"; + reg = <0xb111000 0x1000>; + reg-names = "pm-apcc-glb"; + qcom,apm-post-halt-delay = <0x2>; + qcom,apm-halt-clk-delay = <0x11>; + qcom,apm-resume-clk-delay = <0x10>; + qcom,apm-sel-switch-delay = <0x01>; + }; + + intc: interrupt-controller@b000000 { + compatible = "qcom,msm-qgic2"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x0b000000 0x1000>, + <0x0b002000 0x1000>; + }; + + arm64-cpu-erp { + compatible = "arm,arm64-cpu-erp"; + interrupts = <0 275 0>, + <0 276 0>, + <0 273 0>, + <0 274 0>; + interrupt-names = "pri-dbe-irq", + "sec-dbe-irq", + "pri-ext-irq", + "sec-ext-irq"; + poll-delay-ms = <5000>; + }; + + qcom,msm-gladiator@b1c0000 { + compatible = "qcom,msm-gladiator"; + reg = <0x0b1c0000 0x4000>; + reg-names = "gladiator_base"; + interrupts = <0 22 0>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 2 0xff08>, + <1 3 0xff08>, + <1 4 0xff08>, + <1 1 0xff08>; + clock-frequency = <19200000>; + }; + + timer@b120000 { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "arm,armv7-timer-mem"; + reg = <0xb120000 0x1000>; + clock-frequency = <19200000>; + + frame@b121000 { + frame-number = <0>; + interrupts = <0 8 0x4>, + <0 7 0x4>; + reg = <0xb121000 0x1000>, + <0xb122000 0x1000>; + }; + + frame@b123000 { + frame-number = <1>; + interrupts = <0 9 0x4>; + reg = <0xb123000 0x1000>; + status = "disabled"; + }; + + frame@b124000 { + frame-number = <2>; + interrupts = <0 10 0x4>; + reg = <0xb124000 0x1000>; + status = "disabled"; + }; + + frame@b125000 { + frame-number = <3>; + interrupts = <0 11 0x4>; + reg = <0xb125000 0x1000>; + status = "disabled"; + }; + + frame@b126000 { + frame-number = <4>; + interrupts = <0 12 0x4>; + reg = <0xb126000 0x1000>; + status = "disabled"; + }; + + frame@b127000 { + frame-number = <5>; + interrupts = <0 13 0x4>; + reg = <0xb127000 0x1000>; + status = "disabled"; + }; + + frame@b128000 { + frame-number = <6>; + interrupts = <0 14 0x4>; + reg = <0xb128000 0x1000>; + status = "disabled"; + }; + }; + qcom,rmtfs_sharedmem@00000000 { + compatible = "qcom,sharedmem-uio"; + reg = <0x00000000 0x00180000>; + reg-names = "rmtfs"; + qcom,client-id = <0x00000001>; + }; + + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x4ab000 0x4>, + <0x193d100 0x4>; + reg-names = "pshold-base", "tcsr-boot-misc-detect"; + }; + + qcom,mpm2-sleep-counter@4a3000 { + compatible = "qcom,mpm2-sleep-counter"; + reg = <0x4a3000 0x1000>; + clock-frequency = <32768>; + }; + + cpu-pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <1 7 0xff00>; + }; + + qcom,sps { + compatible = "qcom,msm_sps_4k"; + qcom,pipe-attr-ee; + }; + + tsens: tsens@4a8000 { + compatible = "qcom,msm8953-tsens"; + reg = <0x4a8000 0x2000>, + <0xa4000 0x1000>; + reg-names = "tsens_physical", "tsens_eeprom_physical"; + interrupts = <0 184 0>, <0 314 0>; + interrupt-names = "tsens-upper-lower", "tsens-critical"; + qcom,client-id = <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + qcom,sensor-id = <1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + qcom,sensors = <15>; + qcom,slope = <3200 3200 3200 3200 3200 3200 3200 3200 + 3200 3200 3200 3200 3200 3200 3200>; + qcom,valid-status-check; + }; + + qcom,sensor-information { + compatible = "qcom,sensor-information"; + sensor_information0: qcom,sensor-information-0 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor0"; + qcom,scaling-factor = <10>; + }; + + sensor_information1: qcom,sensor-information-1 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor1"; + qcom,scaling-factor = <10>; + }; + + sensor_information2: qcom,sensor-information-2 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor2"; + qcom,alias-name = "pop_mem"; + qcom,scaling-factor = <10>; + }; + + sensor_information3: qcom,sensor-information-3 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor3"; + qcom,scaling-factor = <10>; + }; + + sensor_information4: qcom,sensor-information-4 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor4"; + qcom,scaling-factor = <10>; + }; + + sensor_information5: qcom,sensor-information-5 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor5"; + qcom,scaling-factor = <10>; + }; + + sensor_information6: qcom,sensor-information-6 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor6"; + qcom,scaling-factor = <10>; + }; + + sensor_information7: qcom,sensor-information-7 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor7"; + qcom,scaling-factor = <10>; + }; + + sensor_information8: qcom,sensor-information-8 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor8"; + qcom,scaling-factor = <10>; + qcom,alias-name = "L2_cache_1"; + }; + + sensor_information9: qcom,sensor-information-9 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor9"; + qcom,scaling-factor = <10>; + }; + + sensor_information10: qcom,sensor-information-10 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor10"; + qcom,scaling-factor = <10>; + }; + + sensor_information11: qcom,sensor-information-11 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor11"; + qcom,scaling-factor = <10>; + }; + + sensor_information12: qcom,sensor-information-12 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor12"; + qcom,scaling-factor = <10>; + }; + + sensor_information13: qcom,sensor-information-13 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor13"; + qcom,scaling-factor = <10>; + qcom,alias-name = "L2_cache_0"; + }; + + sensor_information14: qcom,sensor-information-14 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor14"; + qcom,scaling-factor = <10>; + }; + + sensor_information15: qcom,sensor-information-15 { + qcom,sensor-type = "tsens"; + qcom,sensor-name = "tsens_tz_sensor15"; + qcom,alias-name = "gpu"; + qcom,scaling-factor = <10>; + }; + + sensor_information16: qcom,sensor-information-16 { + qcom,sensor-type = "alarm"; + qcom,sensor-name = "pm8953_tz"; + qcom,scaling-factor = <1000>; + }; + + sensor_information17: qcom,sensor-information-17 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "pa_therm0"; + }; + + sensor_information18: qcom,sensor-information-18 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "pa_therm1"; + }; + + sensor_information19: qcom,sensor-information-19 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "xo_therm"; + }; + + sensor_information20: qcom,sensor-information-20 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "xo_therm_buf"; + }; + + sensor_information21: qcom,sensor-information-21 { + qcom,sensor-type = "adc"; + qcom,sensor-name = "case_therm"; + }; + }; + + mitigation_profile0: qcom,limit_info-0 { + qcom,temperature-sensor = <&sensor_information9>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile1: qcom,limit_info-1 { + qcom,temperature-sensor = <&sensor_information10>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile2: qcom,limit_info-2 { + qcom,temperature-sensor = <&sensor_information11>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile3: qcom,limit_info-3 { + qcom,temperature-sensor = <&sensor_information12>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile4: qcom,limit_info-4 { + qcom,temperature-sensor = <&sensor_information4>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile5: qcom,limit_info-5 { + qcom,temperature-sensor = <&sensor_information5>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile6: qcom,limit_info-6 { + qcom,temperature-sensor = <&sensor_information6>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + mitigation_profile7: qcom,limit_info-7 { + qcom,temperature-sensor = <&sensor_information7>; + qcom,boot-frequency-mitigate; + qcom,hotplug-mitigation-enable; + qcom,emergency-frequency-mitigate; + }; + + qcom,msm-thermal { + compatible = "qcom,msm-thermal"; + qcom,sensor-id = <9>; + qcom,poll-ms = <250>; + qcom,limit-temp = <60>; + qcom,temp-hysteresis = <10>; + qcom,freq-step = <2>; + qcom,core-limit-temp = <80>; + qcom,core-temp-hysteresis = <10>; + qcom,hotplug-temp = <105>; + qcom,hotplug-temp-hysteresis = <15>; + qcom,freq-mitigation-temp = <105>; + qcom,freq-mitigation-temp-hysteresis = <15>; + qcom,freq-mitigation-value = <1036800>; + qcom,therm-reset-temp = <115>; + qcom,online-hotplug-core; + qcom,synchronous-cluster-id = <0 1>; + qcom,synchronous-cluster-map = <0 4 &CPU0 &CPU1 &CPU2 &CPU3>, + <1 4 &CPU4 &CPU5 &CPU6 &CPU7>; + qcom,disable-cx-phase-ctrl; + qcom,disable-gfx-phase-ctrl; + qcom,disable-vdd-mx; + qcom,disable-psm; + qcom,disable-ocr; + qcom,vdd-restriction-temp = <5>; + qcom,vdd-restriction-temp-hysteresis = <10>; + vdd-dig-supply = <&pm8953_s2_floor_level>; + vdd-gfx-supply = <&gfx_vreg_corner>; + + qcom,vdd-dig-rstr { + qcom,vdd-rstr-reg = "vdd-dig"; + qcom,levels = ; + qcom,min-level = ; + }; + + qcom,vdd-gfx-rstr { + qcom,vdd-rstr-reg = "vdd-gfx"; + qcom,levels = <5 7 7>; /* Nominal, Turbo, Turbo */ + qcom,min-level = <1>; /* No Request */ + }; + + msm_thermal_freq: qcom,vdd-apps-rstr { + qcom,vdd-rstr-reg = "vdd-apps"; + qcom,levels = <1689600>; + qcom,freq-req; + }; + }; + + qcom,bcl { + compatible = "qcom,bcl"; + qcom,bcl-enable; + qcom,bcl-framework-interface; + qcom,bcl-freq-control-list = <&CPU0 &CPU1 &CPU2 &CPU3 + &CPU4 &CPU5 &CPU6 &CPU7>; + qcom,bcl-hotplug-list = <&CPU6 &CPU7>; + qcom,bcl-soc-hotplug-list = <&CPU4 &CPU5 &CPU6 &CPU7>; + qcom,ibat-monitor { + qcom,low-threshold-uamp = <3400000>; + qcom,high-threshold-uamp = <4200000>; + qcom,mitigation-freq-khz = <1689600>; + qcom,vph-high-threshold-uv = <3500000>; + qcom,vph-low-threshold-uv = <3200000>; + qcom,soc-low-threshold = <10>; + qcom,thermal-handle = <&msm_thermal_freq>; + }; + }; + + qcom,msm-core@a0000 { + compatible = "qcom,apss-core-ea"; + reg = <0xa0000 0x1000>; + qcom,low-hyst-temp = <100>; + qcom,high-hyst-temp = <100>; + + ea0: ea0 { + sensor = <&sensor_information9>; + }; + + ea1: ea1 { + sensor = <&sensor_information10>; + }; + + ea2: ea2 { + sensor = <&sensor_information11>; + }; + + ea3: ea3 { + sensor = <&sensor_information12>; + }; + + ea4: ea4 { + sensor = <&sensor_information4>; + }; + + ea5: ea5 { + sensor = <&sensor_information5>; + }; + + ea6: ea6 { + sensor = <&sensor_information6>; + }; + + ea7: ea7 { + sensor = <&sensor_information7>; + }; + }; + + blsp1_uart0: serial@78af000 { + compatible = "qcom,msm-lsuart-v14"; + reg = <0x78af000 0x200>; + interrupts = <0 107 0>; + status = "disabled"; + clocks = <&clock_gcc clk_gcc_blsp1_uart1_apps_clk>, + <&clock_gcc clk_gcc_blsp1_ahb_clk>; + clock-names = "core_clk", "iface_clk"; + }; + + blsp1_uart1: uart@78b0000 { + compatible = "qcom,msm-hsuart-v14"; + reg = <0x78b0000 0x200>, + <0x7884000 0x1f000>; + reg-names = "core_mem", "bam_mem"; + + interrupt-names = "core_irq", "bam_irq", "wakeup_irq"; + #address-cells = <0>; + interrupt-parent = <&blsp1_uart1>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 108 0 + 1 &intc 0 238 0 + 2 &tlmm 13 0>; + + qcom,inject-rx-on-wakeup; + qcom,rx-char-to-inject = <0xFD>; + qcom,master-id = <86>; + clock-names = "core_clk", "iface_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>, + <&clock_gcc clk_gcc_blsp1_ahb_clk>; + pinctrl-names = "sleep", "default"; + pinctrl-0 = <&hsuart_sleep>; + pinctrl-1 = <&hsuart_active>; + qcom,bam-tx-ep-pipe-index = <2>; + qcom,bam-rx-ep-pipe-index = <3>; + qcom,msm-bus,name = "blsp1_uart1"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <86 512 0 0>, + <86 512 500 800>; + status = "disabled"; + }; + + blsp2_uart0: uart@7aef000 { + compatible = "qcom,msm-hsuart-v14"; + reg = <0x7aef000 0x200>, + <0x7ac4000 0x1f000>; + reg-names = "core_mem", "bam_mem"; + + interrupt-names = "core_irq", "bam_irq", "wakeup_irq"; + #address-cells = <0>; + interrupt-parent = <&blsp2_uart0>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 306 0 + 1 &intc 0 239 0 + 2 &tlmm 17 0>; + + qcom,inject-rx-on-wakeup; + qcom,rx-char-to-inject = <0xFD>; + qcom,master-id = <84>; + clock-names = "core_clk", "iface_clk"; + clocks = <&clock_gcc clk_gcc_blsp2_uart1_apps_clk>, + <&clock_gcc clk_gcc_blsp2_ahb_clk>; + pinctrl-names = "sleep", "default"; + pinctrl-0 = <&blsp2_uart0_sleep>; + pinctrl-1 = <&blsp2_uart0_active>; + qcom,bam-tx-ep-pipe-index = <0>; + qcom,bam-rx-ep-pipe-index = <1>; + qcom,msm-bus,name = "blsp2_uart0"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <84 512 0 0>, + <84 512 500 800>; + status = "disabled"; + }; + + dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */ + #dma-cells = <4>; + compatible = "qcom,sps-dma"; + reg = <0x7884000 0x1f000>; + interrupts = <0 238 0>; + qcom,summing-threshold = <10>; + }; + + dma_blsp2: qcom,sps-dma@7ac4000 { /* BLSP2 */ + #dma-cells = <4>; + compatible = "qcom,sps-dma"; + reg = <0x7ac4000 0x1f000>; + interrupts = <0 239 0>; + qcom,summing-threshold = <10>; + }; + + spi_3: spi@78b7000 { /* BLSP1 QUP3 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x78b7000 0x600>, + <0x7884000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 97 0>, <0 238 0>; + spi-max-frequency = <19200000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi3_default &spi3_cs0_active>; + pinctrl-1 = <&spi3_sleep &spi3_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup3_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <8>; + qcom,bam-producer-pipe-index = <9>; + qcom,master-id = <86>; + }; + + spi_6: spi@7af6000 { /* BLSP2 QUP2 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x7af6000 0x600>, + <0x7ac4000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 300 0>, <0 239 0>; + spi-max-frequency = <50000000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi6_default &spi6_cs0_active>; + pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <6>; + qcom,bam-producer-pipe-index = <7>; + qcom,master-id = <84>; + }; + + i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */ + compatible = "qcom,i2c-msm-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0x78b6000 0x600>; + interrupt-names = "qup_irq"; + interrupts = <0 96 0>; + qcom,clk-freq-out = <400000>; + qcom,clk-freq-in = <19200000>; + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>; + + pinctrl-names = "i2c_active", "i2c_sleep"; + pinctrl-0 = <&i2c_2_active>; + pinctrl-1 = <&i2c_2_sleep>; + qcom,noise-rjct-scl = <0>; + qcom,noise-rjct-sda = <0>; + qcom,master-id = <86>; + dmas = <&dma_blsp1 6 64 0x20000020 0x20>, + <&dma_blsp1 7 32 0x20000020 0x20>; + dma-names = "tx", "rx"; + + /* DSI_TO_HDMI I2C configuration */ + adv7533@39 { + compatible = "adv7533"; + reg = <0x39>; + instance_id = <0>; + adi,video-mode = <3>; /* 3 = 1080p */ + adi,main-addr = <0x39>; + adi,cec-dsi-addr = <0x3C>; + adi,enable-audio; + pinctrl-names = "pmx_adv7533_active", + "pmx_adv7533_suspend"; + pinctrl-0 = <&adv7533_int_active>; + pinctrl-1 = <&adv7533_int_suspend>; + adi,irq-gpio = <&tlmm 90 0x2002>; + hpd-5v-en-supply = <&adv_vreg>; + qcom,supply-names = "hpd-5v-en"; + qcom,min-voltage-level = <0>; + qcom,max-voltage-level = <0>; + qcom,enable-load = <0>; + qcom,disable-load = <0>; + }; + }; + + i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */ + compatible = "qcom,i2c-msm-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0x78b7000 0x600>; + interrupt-names = "qup_irq"; + interrupts = <0 97 0>; + qcom,clk-freq-out = <400000>; + qcom,clk-freq-in = <19200000>; + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>; + + pinctrl-names = "i2c_active", "i2c_sleep"; + pinctrl-0 = <&i2c_3_active>; + pinctrl-1 = <&i2c_3_sleep>; + qcom,noise-rjct-scl = <0>; + qcom,noise-rjct-sda = <0>; + qcom,master-id = <86>; + dmas = <&dma_blsp1 8 64 0x20000020 0x20>, + <&dma_blsp1 9 32 0x20000020 0x20>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + + i2c_5: i2c@7af5000 { /* BLSP2 QUP1 */ + compatible = "qcom,i2c-msm-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0x7af5000 0x600>; + interrupt-names = "qup_irq"; + interrupts = <0 299 0>; + qcom,clk-freq-out = <400000>; + qcom,clk-freq-in = <19200000>; + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup1_i2c_apps_clk>; + + pinctrl-names = "i2c_active", "i2c_sleep"; + pinctrl-0 = <&i2c_5_active>; + pinctrl-1 = <&i2c_5_sleep>; + qcom,noise-rjct-scl = <0>; + qcom,noise-rjct-sda = <0>; + qcom,master-id = <84>; + dmas = <&dma_blsp2 4 64 0x20000020 0x20>, + <&dma_blsp2 5 32 0x20000020 0x20>; + dma-names = "tx", "rx"; + }; + + slim_msm: slim@c140000{ + cell-index = <1>; + compatible = "qcom,slim-ngd"; + reg = <0xc140000 0x2c000>, + <0xc104000 0x2a000>; + reg-names = "slimbus_physical", "slimbus_bam_physical"; + interrupts = <0 163 0>, <0 180 0>; + interrupt-names = "slimbus_irq", "slimbus_bam_irq"; + qcom,apps-ch-pipes = <0x600000>; + qcom,ea-pc = <0x200>; + status = "disabled"; + }; + + dcc: dcc@b3000 { + compatible = "qcom,dcc"; + reg = <0xb3000 0x1000>, + <0xb4000 0x800>; + reg-names = "dcc-base", "dcc-ram-base"; + + clocks = <&clock_gcc clk_gcc_dcc_clk>; + clock-names = "dcc_clk"; + + qcom,save-reg; + }; + + clock_gcc: qcom,gcc@1800000 { + compatible = "qcom,gcc-8953"; + reg = <0x1800000 0x80000>, + <0x00a4124 0x08>; + reg-names = "cc_base", "efuse"; + vdd_dig-supply = <&pm8953_s2_level>; + #clock-cells = <1>; + }; + + clock_gcc_mdss: qcom,gcc-mdss@1800000 { + compatible = "qcom,gcc-mdss-8953"; + reg = <0x1800000 0x80000>; + reg-names = "cc_base"; + clock-names = "pclk0_src", "pclk1_src", + "byte0_src", "byte1_src"; + clocks = <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>, + <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_mux>, + <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>, + <&mdss_dsi1_pll clk_dsi1pll_byte_clk_mux>; + #clock-cells = <1>; + }; + + clock_debug: qcom,cc-debug@1874000 { + compatible = "qcom,cc-debug-8953"; + reg = <0x1874000 0x4>; + reg-names = "cc_base"; + clocks = <&clock_cpu clk_cpu_debug_pri_mux>; + clock-names = "debug_cpu_clk"; + #clock-cells = <1>; + }; + + clock_gcc_gfx: qcom,gcc-gfx@1800000 { + compatible = "qcom,gcc-gfx-8953"; + reg = <0x1800000 0x80000>; + reg-names = "cc_base"; + vdd_gfx-supply = <&gfx_vreg_corner>; + qcom,gfxfreq-corner = + < 0 0 >, + < 133330000 1 >, /* Min SVS */ + < 216000000 2 >, /* Low SVS */ + < 320000000 3 >, /* SVS */ + < 400000000 4 >, /* SVS Plus */ + < 510000000 5 >, /* NOM */ + < 560000000 6 >, /* Nom Plus */ + < 650000000 7 >; /* Turbo */ + #clock-cells = <1>; + }; + + clock_cpu: qcom,cpu-clock-8953@b116000 { + compatible = "qcom,cpu-clock-8953"; + reg = <0xb114000 0x68>, + <0xb014000 0x68>, + <0xb116000 0x400>, + <0xb111050 0x08>, + <0xb011050 0x08>, + <0xb1d1050 0x08>, + <0x00a4124 0x08>; + reg-names = "rcgwr-c0-base", "rcgwr-c1-base", + "c0-pll", "c0-mux", "c1-mux", + "cci-mux", "efuse"; + vdd-mx-supply = <&pm8953_s7_level_ao>; + vdd-cl-supply = <&apc_vreg>; + clocks = <&clock_gcc clk_xo_a_clk_src>; + clock-names = "xo_a"; + qcom,num-clusters = <2>; + qcom,speed0-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>, + < 1958400000 6>, + < 2016000000 7>; + qcom,speed0-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>, + < 783360000 6>, + < 806400000 7>; + qcom,speed2-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>, + < 1958400000 6>, + < 2016000000 7>; + qcom,speed2-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>, + < 783360000 6>, + < 806400000 7>; + qcom,speed7-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>, + < 1958400000 6>, + < 2016000000 7>, + < 2150400000 8>, + < 2208000000 9>; + qcom,speed7-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>, + < 783360000 6>, + < 806400000 7>, + < 860160000 8>, + < 883200000 9>; + qcom,speed6-bin-v0-cl = + < 0 0>, + < 652800000 1>, + < 1036800000 2>, + < 1401600000 3>, + < 1689600000 4>, + < 1804800000 5>; + qcom,speed6-bin-v0-cci = + < 0 0>, + < 261120000 1>, + < 414720000 2>, + < 560640000 3>, + < 675840000 4>, + < 721920000 5>; + #clock-cells = <1>; + }; + + msm_cpufreq: qcom,msm-cpufreq { + compatible = "qcom,msm-cpufreq"; + clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk", + "cpu3_clk", "cpu4_clk", "cpu5_clk", + "cpu6_clk", "cpu7_clk"; + clocks = <&clock_cpu clk_cci_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>, + <&clock_cpu clk_a53_pwr_clk>; + + qcom,cpufreq-table = + < 652800 >, + < 1036800 >, + < 1401600 >, + < 1689600 >, + < 1804800 >, + < 1958400 >, + < 2016000 >, + < 2150400 >, + < 2208000 >; + }; + + cpubw: qcom,cpubw { + compatible = "qcom,devbw"; + governor = "cpufreq"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + qcom,bw-tbl = + < 769 /* 100.8 MHz */ >, + < 1611 /* 211.2 MHz */ >, /*Low SVS*/ + < 2124 /* 278.4 MHz */ >, + < 2929 /* 384 MHz */ >, + < 3221 /* 422.4 MHz */ >, /* SVS */ + < 4248 /* 556.8 MHz */ >, + < 5126 /* 672 MHz */ >, + < 5859 /* 768 MHz */ >, /* SVS+ */ + < 6152 /* 806.4 MHz */ >, + < 6445 /* 844.8 MHz */ >, /* NOM */ + < 7104 /* 931.2 MHz */ >; /* TURBO */ + }; + + mincpubw: qcom,mincpubw { + compatible = "qcom,devbw"; + governor = "cpufreq"; + qcom,src-dst-ports = <1 512>; + qcom,active-only; + qcom,bw-tbl = + < 769 /* 100.8 MHz */ >, + < 1611 /* 211.2 MHz */ >, /*Low SVS*/ + < 2124 /* 278.4 MHz */ >, + < 2929 /* 384 MHz */ >, + < 3221 /* 422.4 MHz */ >, /* SVS */ + < 4248 /* 556.8 MHz */ >, + < 5126 /* 672 MHz */ >, + < 5859 /* 768 MHz */ >, /* SVS+ */ + < 6152 /* 806.4 MHz */ >, + < 6445 /* 844.8 MHz */ >, /* NOM */ + < 7104 /* 931.2 MHz */ >; /* TURBO */ + }; + + qcom,cpu-bwmon { + compatible = "qcom,bimc-bwmon2"; + reg = <0x408000 0x300>, <0x401000 0x200>; + reg-names = "base", "global_base"; + interrupts = <0 183 4>; + qcom,mport = <0>; + qcom,target-dev = <&cpubw>; + }; + + devfreq-cpufreq { + cpubw-cpufreq { + target-dev = <&cpubw>; + cpu-to-dev-map = + < 652800 1611>, + < 1036800 3221>, + < 1401600 5859>, + < 1689600 6445>, + < 1804800 7104>, + < 1958400 7104>, + < 2208000 7104>; + }; + + mincpubw-cpufreq { + target-dev = <&mincpubw>; + cpu-to-dev-map = + < 652800 1611 >, + < 1401600 3221 >, + < 2208000 5859 >; + }; + }; + + rpm_bus: qcom,rpm-smd { + compatible = "qcom,rpm-smd"; + rpm-channel-name = "rpm_requests"; + rpm-channel-type = <15>; /* SMD_APPS_RPM */ + }; + + qcom,ipc-spinlock@1905000 { + compatible = "qcom,ipc-spinlock-sfpb"; + reg = <0x1905000 0x8000>; + qcom,num-locks = <8>; + }; + + qcom,smem@86300000 { + compatible = "qcom,smem"; + reg = <0x86300000 0x100000>, + <0x0b011008 0x4>, + <0x60000 0x8000>, + <0x193d000 0x8>; + reg-names = "smem", "irq-reg-base", + "aux-mem1", "smem_targ_info_reg"; + qcom,mpu-enabled; + + qcom,smd-modem { + compatible = "qcom,smd"; + qcom,smd-edge = <0>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x1000>; + interrupts = <0 25 1>; + label = "modem"; + qcom,not-loadable; + }; + + qcom,smsm-modem { + compatible = "qcom,smsm"; + qcom,smsm-edge = <0>; + qcom,smsm-irq-offset = <0x0>; + qcom,smsm-irq-bitmask = <0x2000>; + interrupts = <0 26 1>; + }; + + qcom,smd-wcnss { + compatible = "qcom,smd"; + qcom,smd-edge = <6>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x20000>; + interrupts = <0 142 1>; + label = "wcnss"; + }; + + qcom,smsm-wcnss { + compatible = "qcom,smsm"; + qcom,smsm-edge = <6>; + qcom,smsm-irq-offset = <0x0>; + qcom,smsm-irq-bitmask = <0x80000>; + interrupts = <0 144 1>; + }; + + qcom,smd-adsp { + compatible = "qcom,smd"; + qcom,smd-edge = <1>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x100>; + interrupts = <0 289 1>; + label = "adsp"; + }; + + qcom,smsm-adsp { + compatible = "qcom,smsm"; + qcom,smsm-edge = <1>; + qcom,smsm-irq-offset = <0x0>; + qcom,smsm-irq-bitmask = <0x200>; + interrupts = <0 290 1>; + }; + + qcom,smd-rpm { + compatible = "qcom,smd"; + qcom,smd-edge = <15>; + qcom,smd-irq-offset = <0x0>; + qcom,smd-irq-bitmask = <0x1>; + interrupts = <0 168 1>; + label = "rpm"; + qcom,irq-no-suspend; + qcom,not-loadable; + }; + }; + + qcom,wdt@b017000 { + compatible = "qcom,msm-watchdog"; + reg = <0xb017000 0x1000>; + reg-names = "wdt-base"; + interrupts = <0 3 0>, <0 4 0>; + qcom,bark-time = <11000>; + qcom,pet-time = <10000>; + qcom,ipi-ping; + qcom,wakeup-enable; + }; + + qcom,chd { + compatible = "qcom,core-hang-detect"; + qcom,threshold-arr = <0xb1880b0 0xb1980b0 0xb1a80b0 + 0xb1b80b0 0xb0880b0 0xb0980b0 0xb0a80b0 0xb0b80b0>; + qcom,config-arr = <0xb1880b8 0xb1980b8 0xb1a80b8 + 0xb1b80b8 0xb0880b8 0xb0980b8 0xb0a80b8 0xb0b80b8>; + }; + + qcom,msm-rtb { + compatible = "qcom,msm-rtb"; + qcom,rtb-size = <0x100000>; + }; + + qcom,msm-imem@8600000 { + compatible = "qcom,msm-imem"; + reg = <0x08600000 0x1000>; + ranges = <0x0 0x08600000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + mem_dump_table@10 { + compatible = "qcom,msm-imem-mem_dump_table"; + reg = <0x10 8>; + }; + + dload_type@18 { + compatible = "qcom,msm-imem-dload-type"; + reg = <0x18 4>; + }; + + restart_reason@65c { + compatible = "qcom,msm-imem-restart_reason"; + reg = <0x65c 4>; + }; + + boot_stats@6b0 { + compatible = "qcom,msm-imem-boot_stats"; + reg = <0x6b0 32>; + }; + + pil@94c { + compatible = "qcom,msm-imem-pil"; + reg = <0x94c 200>; + + }; + }; + + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + mem_client_3_size: qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + + jtag_fuse: jtagfuse@a601c { + compatible = "qcom,jtag-fuse-v2"; + reg = <0xa601c 0x8>; + reg-names = "fuse-base"; + }; + + sn_fuse: snfuse@0xa4128 { + compatible = "qcom,sn-fuse"; + reg = <0xa4128 0x4>; + reg-names = "sn-base"; + }; + + jtag_mm0: jtagmm@619c000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619c000 0x1000>, + <0x6190000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU0>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm1: jtagmm@619d000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619d000 0x1000>, + <0x6192000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU1>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm2: jtagmm@619e000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619e000 0x1000>, + <0x6194000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU2>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm3: jtagmm@619f000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x619f000 0x1000>, + <0x6196000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU3>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm4: jtagmm@61bc000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61bc000 0x1000>, + <0x61b0000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU4>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm5: jtagmm@61bd000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61bd000 0x1000>, + <0x61b2000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU5>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm6: jtagmm@61be000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61be000 0x1000>, + <0x61b4000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU6>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + jtag_mm7: jtagmm@61bf000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x61bf000 0x1000>, + <0x61b6000 0x1000>; + reg-names = "etm-base", "debug-base"; + + qcom,coresight-jtagmm-cpu = <&CPU7>; + + clocks = <&clock_gcc clk_qdss_clk>, + <&clock_gcc clk_qdss_a_clk>; + clock-names = "core_clk", "core_a_clk"; + }; + + ipa_hw: qcom,ipa@07900000 { + compatible = "qcom,ipa"; + reg = <0x07900000 0x4effc>, <0x07904000 0x26934>; + reg-names = "ipa-base", "bam-base"; + interrupts = <0 228 0>, + <0 230 0>; + interrupt-names = "ipa-irq", "bam-irq"; + qcom,ipa-hw-ver = <6>; /* IPA core version = IPAv2.6L */ + qcom,ipa-hw-mode = <0>; /* IPA hw type = Normal */ + qcom,wan-rx-ring-size = <192>; /* IPA WAN-rx-ring-size*/ + qcom,lan-rx-ring-size = <192>; /* IPA LAN-rx-ring-size*/ + clock-names = "core_clk"; + clocks = <&clock_gcc clk_ipa_clk>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,modem-cfg-emb-pipe-flt; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <90 512 0 0>, /* No BIMC vote (ab=0 Mbps, ib=0 Mbps ~ 0MHZ) */ + <90 512 100000 800000>, /* SVS (ab=100, ib=800 ~ 50MHz) */ + <90 512 100000 1200000>; /* PERF (ab=100, ib=1200 ~ 75MHz) */ + qcom,bus-vector-names = "MIN", "SVS", "PERF"; + }; + + qcom,rmnet-ipa { + compatible = "qcom,rmnet-ipa"; + qcom,rmnet-ipa-ssr; + qcom,ipa-loaduC; + qcom,ipa-advertise-sg-support; + }; + + qcom,smdtty { + compatible = "qcom,smdtty"; + + smdtty_apps_fm: qcom,smdtty-apps-fm { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_FM"; + }; + + smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_BT_ACL"; + }; + + smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_BT_CMD"; + }; + + smdtty_mbalbridge: qcom,smdtty-mbalbridge { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "MBALBRIDGE"; + }; + + smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD"; + }; + + smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data { + qcom,smdtty-remote = "wcnss"; + qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA"; + }; + + smdtty_data1: qcom,smdtty-data1 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA1"; + }; + + smdtty_data4: qcom,smdtty-data4 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA4"; + }; + + smdtty_data11: qcom,smdtty-data11 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA11"; + }; + + smdtty_data21: qcom,smdtty-data21 { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "DATA21"; + }; + + smdtty_loopback: smdtty-loopback { + qcom,smdtty-remote = "modem"; + qcom,smdtty-port-name = "LOOPBACK"; + qcom,smdtty-dev-name = "LOOPBACK_TTY"; + }; + }; + + qcom,smdpkt { + compatible = "qcom,smdpkt"; + + qcom,smdpkt-data5-cntl { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "DATA5_CNTL"; + qcom,smdpkt-dev-name = "smdcntl0"; + }; + + qcom,smdpkt-data22 { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "DATA22"; + qcom,smdpkt-dev-name = "smd22"; + }; + + qcom,smdpkt-data40-cntl { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "DATA40_CNTL"; + qcom,smdpkt-dev-name = "smdcntl8"; + }; + + qcom,smdpkt-apr-apps2 { + qcom,smdpkt-remote = "adsp"; + qcom,smdpkt-port-name = "apr_apps2"; + qcom,smdpkt-dev-name = "apr_apps2"; + }; + + qcom,smdpkt-loopback { + qcom,smdpkt-remote = "modem"; + qcom,smdpkt-port-name = "LOOPBACK"; + qcom,smdpkt-dev-name = "smd_pkt_loopback"; + }; + }; + + qcom,iris-fm { + compatible = "qcom,iris_fm"; + }; + + qcom,wcnss-wlan@0a000000 { + compatible = "qcom,wcnss_wlan"; + reg = <0x0a000000 0x280000>, + <0x0b011008 0x04>, + <0x0a21b000 0x3000>, + <0x03204000 0x00000100>, + <0x03200800 0x00000200>, + <0x0a100400 0x00000200>, + <0x0a205050 0x00000200>, + <0x0a219000 0x00000020>, + <0x0a080488 0x00000008>, + <0x0a080fb0 0x00000008>, + <0x0a08040c 0x00000008>, + <0x0a0120a8 0x00000008>, + <0x0a012448 0x00000008>, + <0x0a080c00 0x00000001>; + + reg-names = "wcnss_mmio", "wcnss_fiq", + "pronto_phy_base", "riva_phy_base", + "riva_ccu_base", "pronto_a2xb_base", + "pronto_ccpu_base", "pronto_saw2_base", + "wlan_tx_phy_aborts","wlan_brdg_err_source", + "wlan_tx_status", "alarms_txctl", + "alarms_tactl", "pronto_mcu_base"; + + interrupts = <0 145 0 0 146 0>; + interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq"; + + qcom,pronto-vddmx-supply = <&pm8953_s7_level_ao>; + qcom,pronto-vddcx-supply = <&pm8953_s2_level>; + qcom,pronto-vddpx-supply = <&pm8953_l5>; + qcom,iris-vddxo-supply = <&pm8953_l7>; + qcom,iris-vddrfa-supply = <&pm8953_l19>; + qcom,iris-vddpa-supply = <&pm8953_l9>; + qcom,iris-vdddig-supply = <&pm8953_l5>; + + qcom,iris-vddxo-voltage-level = <1800000 0 1800000>; + qcom,iris-vddrfa-voltage-level = <1380000 0 1380000>; + qcom,iris-vddpa-voltage-level = <3300000 0 3300000>; + qcom,iris-vdddig-voltage-level = <1800000 0 1800000>; + + qcom,vddmx-voltage-level = ; + qcom,vddcx-voltage-level = ; + qcom,vddpx-voltage-level = <1800000 0 1800000>; + + qcom,iris-vddxo-current = <10000>; + qcom,iris-vddrfa-current = <100000>; + qcom,iris-vddpa-current = <515000>; + qcom,iris-vdddig-current = <10000>; + + qcom,pronto-vddmx-current = <0>; + qcom,pronto-vddcx-current = <0>; + qcom,pronto-vddpx-current = <0>; + + pinctrl-names = "wcnss_default", "wcnss_sleep", + "wcnss_gpio_default"; + pinctrl-0 = <&wcnss_default>; + pinctrl-1 = <&wcnss_sleep>; + pinctrl-2 = <&wcnss_gpio_default>; + + gpios = <&tlmm 76 0>, <&tlmm 77 0>, <&tlmm 78 0>, + <&tlmm 79 0>, <&tlmm 80 0>; + + clocks = <&clock_gcc clk_xo_wlan_clk>, + <&clock_gcc clk_rf_clk2>, + <&clock_debug clk_gcc_debug_mux>, + <&clock_gcc clk_wcnss_m_clk>; + + clock-names = "xo", "rf_clk", "measure", "wcnss_debug"; + + qcom,has-autodetect-xo; + qcom,is-pronto-v3; + qcom,has-pronto-hw; + qcom,has-vsys-adc-channel; + qcom,has-a2xb-split-reg; + qcom,wcnss-adc_tm = <&pm8953_adc_tm>; + }; + + qcom_rng: qrng@e3000 { + compatible = "qcom,msm-rng"; + reg = <0xe3000 0x1000>; + qcom,msm-rng-iface-clk; + qcom,no-qrng-config; + qcom,msm-bus,name = "msm-rng-noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 618 0 0>, /* No vote */ + <1 618 0 800>; /* 100 MB/s */ + clocks = <&clock_gcc clk_gcc_prng_ahb_clk>; + clock-names = "iface_clk"; + }; + + qcom_tzlog: tz-log@08600720 { + compatible = "qcom,tz-log"; + reg = <0x08600720 0x2000>; + }; + + qcom_crypto: qcrypto@720000 { + compatible = "qcom,qcrypto"; + reg = <0x720000 0x20000>, + <0x704000 0x20000>; + reg-names = "crypto-base","crypto-bam-base"; + interrupts = <0 207 0>; + qcom,bam-pipe-pair = <2>; + qcom,ce-hw-instance = <0>; + qcom,ce-device = <0>; + qcom,ce-hw-shared; + qcom,clk-mgmt-sus-res; + qcom,msm-bus,name = "qcrypto-noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 393600 393600>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,use-sw-aes-cbc-ecb-ctr-algo; + qcom,use-sw-aes-xts-algo; + qcom,use-sw-aes-ccm-algo; + qcom,use-sw-ahash-algo; + qcom,use-sw-hmac-algo; + qcom,use-sw-aead-algo; + qcom,ce-opp-freq = <100000000>; + }; + + qcom_cedev: qcedev@720000 { + compatible = "qcom,qcedev"; + reg = <0x720000 0x20000>, + <0x704000 0x20000>; + reg-names = "crypto-base","crypto-bam-base"; + interrupts = <0 207 0>; + qcom,bam-pipe-pair = <1>; + qcom,ce-hw-instance = <0>; + qcom,ce-device = <0>; + qcom,ce-hw-shared; + qcom,msm-bus,name = "qcedev-noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 393600 393600>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,ce-opp-freq = <100000000>; + }; + + qcom_seecom: qseecom@84A00000 { + compatible = "qcom,qseecom"; + reg = <0x84A00000 0x1900000>; + reg-names = "secapp-region"; + qcom,hlos-num-ce-hw-instances = <1>; + qcom,hlos-ce-hw-instance = <0>; + qcom,qsee-ce-hw-instance = <0>; + qcom,disk-encrypt-pipe-pair = <2>; + qcom,support-fde; + qcom,msm-bus,name = "qseecom-noc"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,support-bus-scaling; + qcom,msm-bus,vectors-KBps = + <55 512 0 0>, + <55 512 0 0>, + <55 512 120000 1200000>, + <55 512 393600 3936000>; + clocks = <&clock_gcc clk_crypto_clk_src>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>; + clock-names = "core_clk_src", "core_clk", + "iface_clk", "bus_clk"; + qcom,ce-opp-freq = <100000000>; + }; + + qcom,ipc_router { + compatible = "qcom,ipc_router"; + qcom,node-id = <1>; + }; + + qcom,ipc_router_modem_xprt { + compatible = "qcom,ipc_router_smd_xprt"; + qcom,ch-name = "IPCRTR"; + qcom,xprt-remote = "modem"; + qcom,xprt-linkid = <1>; + qcom,xprt-version = <1>; + qcom,fragmented-data; + qcom,disable-pil-loading; + }; + + qcom,ipc_router_q6_xprt { + compatible = "qcom,ipc_router_smd_xprt"; + qcom,ch-name = "IPCRTR"; + qcom,xprt-remote = "adsp"; + qcom,xprt-linkid = <1>; + qcom,xprt-version = <1>; + qcom,fragmented-data; + }; + + qcom,ipc_router_wcnss_xprt { + compatible = "qcom,ipc_router_smd_xprt"; + qcom,ch-name = "IPCRTR"; + qcom,xprt-remote = "wcnss"; + qcom,xprt-linkid = <1>; + qcom,xprt-version = <1>; + qcom,fragmented-data; + }; + + qcom,adsprpc-mem { + compatible = "qcom,msm-adsprpc-mem-region"; + memory-region = <&adsp_mem>; + }; + + qcom,adsprpc_domains { + compatible = "qcom,msm-fastrpc-legacy-compute-cb"; + qcom,msm_fastrpc_compute_cb { + qcom,adsp-shared-phandle = <&adsp_shared>; + qcom,adsp-shared-sids = + <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>; + qcom,virtual-addr-pool = <0x80000000 0x7FFFFFFF>; + }; + }; + + sdcc1_ice: sdcc1ice@7803000 { + compatible = "qcom,ice"; + reg = <0x7803000 0x8000>; + interrupt-names = "sdcc_ice_nonsec_level_irq", + "sdcc_ice_sec_level_irq"; + interrupts = <0 312 0>, <0 313 0>; + qcom,enable-ice-clk; + clock-names = "ice_core_clk_src", "ice_core_clk", + "bus_clk", "iface_clk"; + clocks = <&clock_gcc clk_sdcc1_ice_core_clk_src>, + <&clock_gcc clk_gcc_sdcc1_ice_core_clk>, + <&clock_gcc clk_gcc_sdcc1_apps_clk>, + <&clock_gcc clk_gcc_sdcc1_ahb_clk>; + qcom,op-freq-hz = <270000000>, <0>, <0>, <0>; + qcom,msm-bus,name = "sdcc_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <78 512 0 0>, /* No vote */ + <78 512 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", "MAX"; + qcom,instance-type = "sdcc"; + }; + + sdhc_1: sdhci@7824900 { + compatible = "qcom,sdhci-msm"; + reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>; + reg-names = "hc_mem", "core_mem", "cmdq_mem"; + + interrupts = <0 123 0>, <0 138 0>; + interrupt-names = "hc_irq", "pwr_irq"; + + sdhc-msm-crypto = <&sdcc1_ice>; + qcom,bus-width = <8>; + + qcom,devfreq,freq-table = <50000000 200000000>; + + qcom,pm-qos-irq-type = "affine_irq"; + qcom,pm-qos-irq-latency = <2 213>; + + qcom,pm-qos-cpu-groups = <0x0f 0xf0>; + qcom,pm-qos-cmdq-latency-us = <2 213>, <2 213>; + + qcom,pm-qos-legacy-latency-us = <2 213>, <2 213>; + + qcom,msm-bus,name = "sdhc1"; + qcom,msm-bus,num-cases = <9>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */ + <78 512 1046 3200>, /* 400 KB/s*/ + <78 512 52286 160000>, /* 20 MB/s */ + <78 512 65360 200000>, /* 25 MB/s */ + <78 512 130718 400000>, /* 50 MB/s */ + <78 512 130718 400000>, /* 100 MB/s */ + <78 512 261438 800000>, /* 200 MB/s */ + <78 512 261438 800000>, /* 400 MB/s */ + <78 512 1338562 4096000>; /* Max. bandwidth */ + qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 + 100000000 200000000 400000000 4294967295>; + + clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>, + <&clock_gcc clk_gcc_sdcc1_apps_clk>, + <&clock_gcc clk_gcc_sdcc1_ice_core_clk>; + clock-names = "iface_clk", "core_clk", "ice_core_clk"; + qcom,ice-clk-rates = <270000000 160000000>; + qcom,large-address-bus; + + status = "disabled"; + }; + + sdhc_2: sdhci@7864900 { + compatible = "qcom,sdhci-msm"; + reg = <0x7864900 0x500>, <0x7864000 0x800>; + reg-names = "hc_mem", "core_mem"; + + interrupts = <0 125 0>, <0 221 0>; + interrupt-names = "hc_irq", "pwr_irq"; + + qcom,bus-width = <4>; + + qcom,pm-qos-irq-type = "affine_irq"; + qcom,pm-qos-irq-latency = <2 213>; + + qcom,pm-qos-cpu-groups = <0x0f 0xf0>; + qcom,pm-qos-legacy-latency-us = <2 213>, <2 213>; + + qcom,devfreq,freq-table = <50000000 200000000>; + + qcom,msm-bus,name = "sdhc2"; + qcom,msm-bus,num-cases = <8>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */ + <81 512 1046 3200>, /* 400 KB/s*/ + <81 512 52286 160000>, /* 20 MB/s */ + <81 512 65360 200000>, /* 25 MB/s */ + <81 512 130718 400000>, /* 50 MB/s */ + <81 512 261438 800000>, /* 100 MB/s */ + <81 512 261438 800000>, /* 200 MB/s */ + <81 512 1338562 4096000>; /* Max. bandwidth */ + qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 + 100000000 200000000 4294967295>; + + clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>, + <&clock_gcc clk_gcc_sdcc2_apps_clk>; + clock-names = "iface_clk", "core_clk"; + + qcom,large-address-bus; + status = "disabled"; + }; + + spmi_bus: qcom,spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x200f000 0x1000>, + <0x2400000 0x800000>, + <0x2c00000 0x800000>, + <0x3800000 0x200000>, + <0x200a000 0x2100>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupts = <0 190 0>; + qcom,pmic-arb-channel = <0>; + qcom,pmic-arb-max-peripherals = <256>; + qcom,pmic-arb-max-periph-interrupts = <256>; + qcom,pmic-arb-ee = <0>; + #interrupt-cells = <3>; + interrupt-controller; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + }; + + qcom,memshare { + compatible = "qcom,memshare"; + + qcom,client_1 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x200000>; + qcom,client-id = <0>; + qcom,allocate-boot-time; + label = "modem"; + }; + + qcom,client_2 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x300000>; + qcom,client-id = <2>; + label = "modem"; + }; + + qcom,client_3 { + compatible = "qcom,memshare-peripheral"; + qcom,peripheral-size = <0x0>; + qcom,client-id = <1>; + label = "modem"; + }; + }; + + qcom,mss@4080000 { + compatible = "qcom,pil-q6v55-mss"; + reg = <0x04080000 0x100>, + <0x0194f000 0x010>, + <0x01950000 0x008>, + <0x01951000 0x008>, + <0x04020000 0x040>, + <0x01871000 0x004>; + reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc", + "rmb_base", "restart_reg"; + + interrupts = <0 24 1>; + vdd_mss-supply = <&pm8953_s1>; + vdd_cx-supply = <&pm8953_s2_level>; + vdd_cx-voltage = ; + vdd_mx-supply = <&pm8953_s7_level_ao>; + vdd_mx-uV = ; + vdd_pll-supply = <&pm8953_l7>; + qcom,vdd_pll = <1800000>; + + clocks = <&clock_gcc clk_xo_pil_mss_clk>, + <&clock_gcc clk_gcc_mss_cfg_ahb_clk>, + <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>, + <&clock_gcc clk_gcc_boot_rom_ahb_clk>; + clock-names = "xo", "iface_clk", "bus_clk", "mem_clk"; + qcom,proxy-clock-names = "xo"; + qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk"; + + qcom,pas-id = <5>; + qcom,pil-mss-memsetup; + qcom,firmware-name = "modem"; + qcom,pil-self-auth; + qcom,sysmon-id = <0>; + qcom,ssctl-instance-id = <0x12>; + qcom,qdsp6v56-1-10; + + /* GPIO inputs from mss */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>; + qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>; + + /* GPIO output to mss */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; + memory-region = <&modem_mem>; + }; + + qcom,lpass@c200000 { + compatible = "qcom,pil-tz-generic"; + reg = <0xc200000 0x00100>; + interrupts = <0 293 1>; + + vdd_cx-supply = <&pm8953_s2_level>; + qcom,proxy-reg-names = "vdd_cx"; + qcom,vdd_cx-uV-uA = ; + + clocks = <&clock_gcc clk_xo_pil_lpass_clk>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>, + <&clock_gcc clk_crypto_clk_src>; + clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,scm_core_clk_src-freq = <80000000>; + + qcom,pas-id = <1>; + qcom,complete-ramdump; + qcom,proxy-timeout-ms = <10000>; + qcom,smem-id = <423>; + qcom,sysmon-id = <1>; + qcom,ssctl-instance-id = <0x14>; + qcom,firmware-name = "adsp"; + + /* GPIO inputs from lpass */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>; + + /* GPIO output to lpass */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>; + + memory-region = <&adsp_fw_mem>; + }; + + qcom,venus@1de0000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x1de0000 0x4000>; + + vdd-supply = <&gdsc_venus>; + qcom,proxy-reg-names = "vdd"; + + clocks = <&clock_gcc clk_gcc_venus0_vcodec0_clk>, + <&clock_gcc clk_gcc_venus0_ahb_clk>, + <&clock_gcc clk_gcc_venus0_axi_clk>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>, + <&clock_gcc clk_crypto_clk_src>; + + clock-names = "core_clk", "iface_clk", "bus_clk", + "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + + qcom,proxy-clock-names = "core_clk", "iface_clk", + "bus_clk", "scm_core_clk", + "scm_iface_clk", "scm_bus_clk", + "scm_core_clk_src"; + qcom,scm_core_clk_src-freq = <80000000>; + + qcom,msm-bus,name = "pil-venus"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <63 512 0 0>, + <63 512 0 304000>; + + qcom,pas-id = <9>; + qcom,proxy-timeout-ms = <100>; + qcom,firmware-name = "venus"; + memory-region = <&venus_mem>; + }; + + qcom,msm-ssc-sensors { + compatible = "qcom,msm-ssc-sensors"; + }; + + qcom,pronto@a21b000 { + compatible = "qcom,pil-tz-generic"; + reg = <0x0a21b000 0x3000>; + interrupts = <0 149 1>; + + vdd_pronto_pll-supply = <&pm8953_l7>; + proxy-reg-names = "vdd_pronto_pll"; + vdd_pronto_pll-uV-uA = <1800000 18000>; + clocks = <&clock_gcc clk_xo_pil_pronto_clk>, + <&clock_gcc clk_gcc_crypto_clk>, + <&clock_gcc clk_gcc_crypto_ahb_clk>, + <&clock_gcc clk_gcc_crypto_axi_clk>, + <&clock_gcc clk_crypto_clk_src>; + + clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk", + "scm_bus_clk", "scm_core_clk_src"; + qcom,scm_core_clk_src = <80000000>; + + qcom,pas-id = <6>; + qcom,proxy-timeout-ms = <10000>; + qcom,smem-id = <422>; + qcom,sysmon-id = <6>; + qcom,ssctl-instance-id = <0x13>; + qcom,firmware-name = "wcnss"; + + /* GPIO inputs from wcnss */ + qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>; + qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>; + qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>; + qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_4_in 3 0>; + + /* GPIO output to wcnss */ + qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>; + memory-region = <&wcnss_fw_mem>; + }; + + usb3: ssusb@7000000{ + compatible = "qcom,dwc-usb3-msm"; + reg = <0x07000000 0xfc000>, + <0x0007e000 0x400>; + reg-names = "core_base", + "ahb2phy_base"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + interrupts = <0 136 0>, <0 220 0>, <0 134 0>; + interrupt-names = "hs_phy_irq", "ss_phy_irq", "pwr_event_irq"; + + USB3_GDSC-supply = <&gdsc_usb30>; + qcom,usb-dbm = <&dbm_1p5>; + qcom,msm-bus,name = "usb3"; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <1>; + qcom,detect-dpdm-floating; + qcom,msm-bus,vectors-KBps = + <61 512 0 0>, + <61 512 240000 800000>, + <61 512 240000 800000>; + + qcom,dwc-usb3-msm-tx-fifo-size = <21288>; + + clocks = <&clock_gcc clk_gcc_usb30_master_clk>, + <&clock_gcc clk_gcc_pcnoc_usb3_axi_clk>, + <&clock_gcc clk_gcc_usb30_mock_utmi_clk>, + <&clock_gcc clk_gcc_usb30_sleep_clk>, + <&clock_gcc clk_xo_dwc3_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb_clk>; + + clock-names = "core_clk", "iface_clk", "utmi_clk", + "sleep_clk", "xo", "cfg_ahb_clk"; + + dwc3@7000000 { + compatible = "snps,dwc3"; + reg = <0x07000000 0xc8d0>; + interrupt-parent = <&intc>; + interrupts = <0 140 0>; + usb-phy = <&qusb_phy>, <&ssphy>; + tx-fifo-resize; + snps,usb3-u1u2-disable; + snps,nominal-elastic-buffer; + snps,is-utmi-l1-suspend; + snps,hird-threshold = /bits/ 8 <0x0>; + }; + + qcom,usbbam@7104000 { + compatible = "qcom,usb-bam-msm"; + reg = <0x07104000 0x1a934>; + interrupt-parent = <&intc>; + interrupts = <0 135 0>; + + qcom,bam-type = <0>; + qcom,usb-bam-fifo-baseaddr = <0x08605000>; + qcom,usb-bam-num-pipes = <8>; + qcom,ignore-core-reset-ack; + qcom,disable-clk-gating; + qcom,usb-bam-override-threshold = <0x4001>; + qcom,usb-bam-max-mbps-highspeed = <400>; + qcom,usb-bam-max-mbps-superspeed = <3600>; + qcom,reset-bam-on-connect; + + qcom,pipe0 { + label = "ssusb-ipa-out-0"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <0>; + qcom,pipe-num = <0>; + qcom,peer-bam = <1>; + qcom,src-bam-pipe-index = <1>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + + qcom,pipe1 { + label = "ssusb-ipa-in-0"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <1>; + qcom,pipe-num = <0>; + qcom,peer-bam = <1>; + qcom,dst-bam-pipe-index = <0>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + + qcom,pipe2 { + label = "ssusb-qdss-in-0"; + qcom,usb-bam-mem-type = <2>; + qcom,dir = <1>; + qcom,pipe-num = <0>; + qcom,peer-bam = <0>; + qcom,peer-bam-physical-address = <0x06044000>; + qcom,src-bam-pipe-index = <0>; + qcom,dst-bam-pipe-index = <2>; + qcom,data-fifo-offset = <0x0>; + qcom,data-fifo-size = <0xe00>; + qcom,descriptor-fifo-offset = <0xe00>; + qcom,descriptor-fifo-size = <0x200>; + }; + + qcom,pipe3 { + label = "ssusb-dpl-ipa-in-1"; + qcom,usb-bam-mem-type = <1>; + qcom,dir = <1>; + qcom,pipe-num = <1>; + qcom,peer-bam = <1>; + qcom,dst-bam-pipe-index = <2>; + qcom,data-fifo-size = <0x8000>; + qcom,descriptor-fifo-size = <0x2000>; + }; + }; + }; + + qusb_phy: qusb@79000 { + compatible = "qcom,qusb2phy"; + reg = <0x079000 0x180>, + <0x01841030 0x4>, + <0x0193f044 0x4>, + <0x0193f020 0x4>; + reg-names = "qusb_phy_base", + "ref_clk_addr", + "tcsr_phy_clk_scheme_sel", + "tcsr_phy_level_shift_keeper"; + + USB3_GDSC-supply = <&gdsc_usb30>; + vdd-supply = <&pm8953_l3>; + vdda18-supply = <&pm8953_l7>; + vdda33-supply = <&pm8953_l13>; + qcom,vdd-voltage-level = <0 925000 925000>; + + qcom,qusb-phy-init-seq = <0xF8 0x80 + 0x53 0x84 + 0x93 0x88 + 0xCf 0x8C + 0x14 0x9C + 0x30 0x08 + 0x79 0x0C + 0x21 0x10 + 0x00 0x90 + 0x9F 0x1C + 0x00 0x18>; + phy_type= "utmi"; + + clocks = <&clock_gcc clk_bb_clk1>, + <&clock_gcc clk_gcc_qusb_ref_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb_clk>, + <&clock_gcc clk_gcc_qusb2_phy_reset>, + <&clock_gcc clk_gcc_pcnoc_usb3_axi_clk>, + <&clock_gcc clk_gcc_usb30_master_clk>; + + clock-names = "ref_clk_src", "ref_clk", "cfg_ahb_clk", + "phy_reset", "iface_clk", "core_clk"; + + }; + + usb_nop_phy: usb_nop_phy { + status = "disabled"; + compatible = "usb-nop-xceiv"; + }; + + + ssphy: ssphy@78000 { + compatible = "qcom,usb-ssphy-qmp"; + reg = <0x78000 0x9f8>, + <0x0193f244 0x4>, + <0x0193f044 0x4>; + reg-names = "qmp_phy_base", + "vls_clamp_reg", + "tcsr_phy_clk_scheme_sel"; + qcom,qmp-phy-init-seq = <0xac 0x14 0x1a 0x00 + 0x34 0x08 0x08 0x00 + 0x174 0x30 0x30 0x00 + 0x3c 0x06 0x06 0x00 + 0xb4 0x00 0x00 0x00 + 0xb8 0x08 0x08 0x00 + 0x194 0x06 0x06 0x3e8 + 0x19c 0x01 0x01 0x00 + 0x178 0x00 0x00 0x00 + 0xd0 0x82 0x82 0x00 + 0xdc 0x55 0x55 0x00 + 0xe0 0x55 0x55 0x00 + 0xe4 0x03 0x03 0x00 + 0x78 0x0b 0x0b 0x00 + 0x84 0x16 0x16 0x00 + 0x90 0x28 0x28 0x00 + 0x108 0x80 0x80 0x00 + 0x10c 0x00 0x00 0x00 + 0x184 0x0a 0x0a 0x00 + 0x4c 0x15 0x15 0x00 + 0x50 0x34 0x34 0x00 + 0x54 0x00 0x00 0x00 + 0xc8 0x00 0x00 0x00 + 0x18c 0x00 0x00 0x00 + 0xcc 0x00 0x00 0x00 + 0x128 0x00 0x00 0x00 + 0x0c 0x0a 0x0a 0x00 + 0x10 0x01 0x01 0x00 + 0x1c 0x31 0x31 0x00 + 0x20 0x01 0x01 0x00 + 0x14 0x00 0x00 0x00 + 0x18 0x00 0x00 0x00 + 0x24 0xde 0xde 0x00 + 0x28 0x07 0x07 0x00 + 0x48 0x0f 0x0f 0x00 + 0x70 0x0f 0x0f 0x00 + 0x100 0x80 0x80 0x00 + 0x440 0x0b 0x0b 0x00 + 0x4d8 0x02 0x02 0x00 + 0x4dc 0x6c 0x6c 0x00 + 0x4e0 0xbb 0xbb 0x00 + 0x508 0x77 0x77 0x00 + 0x50c 0x80 0x80 0x00 + 0x514 0x03 0x03 0x00 + 0x51c 0x16 0x16 0x00 + 0x448 0x75 0x75 0x00 + 0x454 0x00 0x00 0x00 + 0x40c 0x0a 0x0a 0x00 + 0x41c 0x06 0x06 0x00 + 0x510 0x00 0x00 0x00 + 0x268 0x45 0x45 0x00 + 0x2ac 0x12 0x12 0x00 + 0x294 0x06 0x06 0x00 + 0x254 0x00 0x00 0x00 + 0x8c8 0x83 0x83 0x00 + 0x8c4 0x02 0x02 0x00 + 0x8cc 0x09 0x09 0x00 + 0x8d0 0xa2 0xa2 0x00 + 0x8d4 0x85 0x85 0x00 + 0x880 0xd1 0xd1 0x00 + 0x884 0x1f 0x1f 0x00 + 0x888 0x47 0x47 0x00 + 0x80c 0x9f 0x9f 0x00 + 0x824 0x17 0x17 0x00 + 0x828 0x0f 0x0f 0x00 + 0x8b8 0x75 0x75 0x00 + 0x8bc 0x13 0x13 0x00 + 0x8b0 0x86 0x86 0x00 + 0x8a0 0x04 0x04 0x00 + 0x88c 0x44 0x44 0x00 + 0x870 0xe7 0xe7 0x00 + 0x874 0x03 0x03 0x00 + 0x878 0x40 0x40 0x00 + 0x87c 0x00 0x00 0x00 + 0x9d8 0x88 0x88 0x00 + 0xffffffff 0xffffffff 0x00 0x00>; + qcom,qmp-phy-reg-offset = <0x988 0x98c 0x990 0x994 + 0x974 0x8d8 0x8dc 0x804 0x800 + 0x808>; + vdd-supply = <&pm8953_l3>; + core-supply = <&pm8953_l7>; + qcom,vdd-voltage-level = <0 925000 925000>; + qcom,vbus-valid-override; + + clocks = <&clock_gcc clk_gcc_usb3_aux_clk>, + <&clock_gcc clk_gcc_usb3_pipe_clk>, + <&clock_gcc clk_gcc_usb_phy_cfg_ahb_clk>, + <&clock_gcc clk_gcc_usb3_phy_reset>, + <&clock_gcc clk_gcc_usb3phy_phy_reset>, + <&clock_gcc clk_bb_clk1>, + <&clock_gcc clk_gcc_usb_ss_ref_clk>; + + clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk", "phy_reset", + "phy_phy_reset", "ref_clk_src", "ref_clk"; + + }; + + dbm_1p5: dbm@70f8000 { + compatible = "qcom,usb-dbm-1p5"; + reg = <0x070f8000 0x300>; + qcom,reset-ep-after-lpm-resume; + }; + + android_usb@86000c8 { + compatible = "qcom,android-usb"; + reg = <0x086000c8 0xc8>; + qcom,pm-qos-latency = <2 213 11028>; + }; +}; + +#include "msm-pm8953-rpm-regulator.dtsi" +#include "msm-pm8953-e7.dtsi" +#include "msm8953-regulator.dtsi" +#include "msm-audio-e7.dtsi" +#include "msm8953-audio-e7.dtsi" +#include "msm-gdsc-8916.dtsi" +#include "msm8953-camera.dtsi" +#include "msm8953-mdss.dtsi" +#include "msm8953-mdss-pll.dtsi" + +&gdsc_venus { + clock-names = "bus_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_venus0_axi_clk>, + <&clock_gcc clk_gcc_venus0_vcodec0_clk>; + status = "okay"; +}; + +&gdsc_venus_core0 { + qcom,support-hw-trigger; + clock-names ="core0_clk"; + clocks = <&clock_gcc clk_gcc_venus0_core0_vcodec0_clk>; + status = "okay"; +}; + +&gdsc_mdss { + clock-names = "core_clk", "bus_clk"; + clocks = <&clock_gcc clk_gcc_mdss_mdp_clk>, + <&clock_gcc clk_gcc_mdss_axi_clk>; + proxy-supply = <&gdsc_mdss>; + qcom,proxy-consumer-enable; + status = "okay"; +}; + +&gdsc_oxili_gx { + clock-names = "core_root_clk"; + clocks =<&clock_gcc_gfx clk_gfx3d_clk_src>; + qcom,force-enable-root-clk; + parent-supply = <&gfx_vreg_corner>; + status = "okay"; +}; + +&gdsc_jpeg { + clock-names = "core_clk", "bus_clk"; + clocks = <&clock_gcc clk_gcc_camss_jpeg0_clk>, + <&clock_gcc clk_gcc_camss_jpeg_axi_clk>; + status = "okay"; +}; + +&gdsc_vfe { + clock-names = "core_clk", "bus_clk", "micro_clk", + "csi_clk"; + clocks = <&clock_gcc clk_gcc_camss_vfe0_clk>, + <&clock_gcc clk_gcc_camss_vfe_axi_clk>, + <&clock_gcc clk_gcc_camss_micro_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi_vfe0_clk>; + status = "okay"; +}; + +&gdsc_vfe1 { + clock-names = "core_clk", "bus_clk", "micro_clk", + "csi_clk"; + clocks = <&clock_gcc clk_gcc_camss_vfe1_clk>, + <&clock_gcc clk_gcc_camss_vfe1_axi_clk>, + <&clock_gcc clk_gcc_camss_micro_ahb_clk>, + <&clock_gcc clk_gcc_camss_csi_vfe1_clk>; + status = "okay"; +}; + +&gdsc_cpp { + clock-names = "core_clk", "bus_clk"; + clocks = <&clock_gcc clk_gcc_camss_cpp_clk>, + <&clock_gcc clk_gcc_camss_cpp_axi_clk>; + status = "okay"; +}; + +&gdsc_oxili_cx { + clock-names = "core_clk"; + clocks = <&clock_gcc_gfx clk_gcc_oxili_gfx3d_clk>; + status = "okay"; +}; + +&gdsc_usb30 { + status = "okay"; +}; + +&pm8953_mpps { + mpp@a100 { + /* MPP2 - PA_THERM config */ + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + qcom,ain-route = <1>; /* AMUX 6 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + }; + + mpp@a300 { + /* MPP4 - CASE_THERM config */ + qcom,mode = <4>; /* AIN input */ + qcom,invert = <1>; /* Enable MPP */ + qcom,ain-route = <3>; /* AMUX 8 */ + qcom,master-en = <1>; + qcom,src-sel = <0>; /* Function constant */ + }; +}; + +&pm8953_vadc { + chan@5 { + label = "vcoin"; + reg = <5>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@7 { + label = "vph_pwr"; + reg = <7>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + }; + + chan@36 { + label = "pa_therm0"; + reg = <0x36>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + }; + + chan@11 { + label = "pa_therm1"; + reg = <0x11>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@32 { + label = "xo_therm"; + reg = <0x32>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <4>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@3c { + label = "xo_therm_buf"; + reg = <0x3c>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <4>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; + + chan@13 { + label = "case_therm"; + reg = <0x13>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,vadc-thermal-node; + }; +}; + +&pm8953_adc_tm { + chan@36 { + label = "pa_therm0"; + reg = <0x36>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + qcom,btm-channel-number = <0x48>; + qcom,thermal-node; + }; + + chan@7 { + label = "vph_pwr"; + reg = <0x7>; + qcom,decimation = <0>; + qcom,pre-div-channel-scaling = <1>; + qcom,calibration-type = "absolute"; + qcom,scale-function = <0>; + qcom,hw-settle-time = <0>; + qcom,fast-avg-setup = <0>; + qcom,btm-channel-number = <0x68>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi index a481b684ce5da..7639c90744a07 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mdss-panels.dtsi @@ -1,4 +1,5 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -24,8 +25,17 @@ #include "dsi-panel-lt8912-480p-video.dtsi" #include "dsi-panel-lt8912-1080p-video.dtsi" #include "dsi-panel-lgd-incell-sw49106-fhd-video.dtsi" -#include "dsi-panel-hx83100a-800p-video.dtsi" - +#include "dsi-panel-otm1911-fhd-video.dtsi" +#include "dsi-panel-otm1911-fhdplus-video.dtsi" +#include "dsi-panel-ili7807-fhdplus-video.dtsi" +#include "dsi-panel-hx8399c-fhdplus-video.dtsi" +/*add begin for E7 display*/ +#include "dsi-panel-td4310-fhdplus-video_e7.dtsi" +#include "dsi-panel-td4310-fhdplus-video_e7_g55.dtsi" +#include "dsi-panel-td4310-ebbg-fhdplus-video_e7.dtsi" +#include "dsi-panel-nt36672-tianma-fhdplus-video_e7.dtsi" +#include "dsi-panel-nt36672-csot-fhdplus-video_e7.dtsi" +/*add end for E7 display*/ &soc { dsi_panel_pwr_supply: dsi_panel_pwr_supply { #address-cells = <1>; @@ -37,6 +47,7 @@ qcom,supply-min-voltage = <2850000>; qcom,supply-max-voltage = <2850000>; qcom,supply-enable-load = <100000>; + qcom,supply-post-on-sleep= <2>; qcom,supply-disable-load = <100>; }; @@ -46,11 +57,62 @@ qcom,supply-min-voltage = <1800000>; qcom,supply-max-voltage = <1800000>; qcom,supply-enable-load = <100000>; + qcom,supply-post-on-sleep= <2>; qcom,supply-disable-load = <100>; }; }; }; +/*add begin for E7 display*/ +&dsi_td4310_fhdplus_e7_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 08 0a 06 03 04 a0]; +}; + +&dsi_td4310_fhdplus_e7_g55_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 08 0a 06 03 04 a0]; +}; + +&dsi_td4310_ebbg_fhdplus_e7_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [19 1F 09 0A 06 03 04 a0 + 19 1F 09 0A 06 03 04 a0 + 19 1F 09 0A 06 03 04 a0 + 19 1F 09 0A 06 03 04 a0 + 19 1E 08 0A 06 03 04 a0]; +}; + +&dsi_nt36672_tianma_fhdplus_e7_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1F 08 09 05 03 04 a0 + 24 1C 08 09 05 03 04 a0]; +}; + +&dsi_nt36672_csot_fhdplus_e7_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1f 09 0a 06 03 04 a0 + 25 1e 08 0a 06 03 04 a0]; +}; +/*add end for E7 display*/ + +&dsi_otm1911_fhd_vid { + qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 1e 07 08 05 03 04 a0 + 23 18 07 08 05 03 04 a0]; +}; + &dsi_truly_1080_vid { qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 08 09 05 03 04 a0 23 1e 08 09 05 03 04 a0 @@ -116,11 +178,3 @@ qcom,mdss-dsi-t-clk-post = <0x0d>; qcom,mdss-dsi-t-clk-pre = <0x30>; }; - -&dsi_boyi_hx83100a_800p_video { - qcom,mdss-dsi-panel-timings-phy-v2 = [1f 1c 05 06 03 03 04 a0 - 1f 1c 05 06 03 03 04 a0 - 1f 1c 05 06 03 03 04 a0 - 1f 1c 05 06 03 03 04 a0 - 1f 10 05 06 03 03 04 a0]; -}; diff --git a/arch/arm/boot/dts/qcom/msm8953-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/msm8953-mdss-pll.dtsi index a279453a1c74f..55f0a4802ad48 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mdss-pll.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mdss-pll.dtsi @@ -1,4 +1,5 @@ /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,8 +29,7 @@ clock-names = "iface_clk"; clock-rate = <0>; - qcom,dsi-pll-ssc-en; - qcom,dsi-pll-ssc-mode = "down-spread"; + /* Memory region for passing dynamic refresh pll codes */ memory-region = <&dfps_data_mem>; @@ -61,8 +61,7 @@ gdsc-supply = <&gdsc_mdss>; - qcom,dsi-pll-ssc-en; - qcom,dsi-pll-ssc-mode = "down-spread"; + clocks = <&clock_gcc clk_gcc_mdss_ahb_clk>; clock-names = "iface_clk"; clock-rate = <0>; diff --git a/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi index 2131dc35bc3f2..9aca82b4417d2 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mdss.dtsi @@ -31,7 +31,7 @@ /* Fudge factors */ qcom,mdss-ab-factor = <1 1>; /* 1 time */ qcom,mdss-ib-factor = <1 1>; /* 1 time */ - qcom,mdss-clk-factor = <105 100>; /* 1.05 times */ + qcom,mdss-clk-factor = <110 100>; /* 1.10 times */ qcom,max-mixer-width = <2048>; qcom,max-pipe-width = <2048>; diff --git a/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi index d805dd67b87db..d3a8a8627ad90 100644 --- a/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-mtp.dtsi @@ -249,12 +249,14 @@ status = "ok"; }; +/* &pm8953_typec { ss-mux-supply = <&pm8953_l13>; qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&typec_ssmux_config>; }; +*/ &pm8953_gpios { /* GPIO 2 (NFC_CLK_REQ) */ diff --git a/arch/arm/boot/dts/qcom/msm8953-pinctrl-e7.dtsi b/arch/arm/boot/dts/qcom/msm8953-pinctrl-e7.dtsi new file mode 100644 index 0000000000000..9e789dddc6b3e --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-pinctrl-e7.dtsi @@ -0,0 +1,1848 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +&soc { + tlmm: pinctrl@1000000 { + compatible = "qcom,msm8953-pinctrl"; + reg = <0x1000000 0x300000>; + interrupts = <0 208 0>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + + pmx-uartconsole { + uart_console_active: uart_console_active { + mux { + pins = "gpio4", "gpio5"; + function = "blsp_uart2"; + }; + + config { + pins = "gpio4", "gpio5"; + drive-strength = <2>; + bias-disable; + }; + }; + + uart_console_sleep: uart_console_sleep { + mux { + pins = "gpio4", "gpio5"; + function = "blsp_uart2"; + }; + + config { + pins = "gpio4", "gpio5"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + }; + cci { + cci0_active: cci0_active { + /* cci0 active state */ + mux { + /* CLK, DATA */ + pins = "gpio29", "gpio30"; + function = "cci_i2c"; + }; + + config { + pins = "gpio29", "gpio30"; + drive-strength = <2>; /* 2 MA */ + bias-disable; /* No PULL */ + }; + }; + + cci0_suspend: cci0_suspend { + /* cci0 suspended state */ + mux { + /* CLK, DATA */ + pins = "gpio29", "gpio30"; + function = "cci_i2c"; + }; + + config { + pins = "gpio29", "gpio30"; + drive-strength = <2>; /* 2 MA */ + bias-disable; /* No PULL */ + }; + }; + + cci1_active: cci1_active { + /* cci1 active state */ + mux { + /* CLK, DATA */ + pins = "gpio31", "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio31", "gpio32"; + drive-strength = <2>; /* 2 MA */ + bias-disable; /* No PULL */ + }; + }; + + cci1_suspend: cci1_suspend { + /* cci1 suspended state */ + mux { + /* CLK, DATA */ + pins = "gpio31", "gpio32"; + function = "cci_i2c"; + }; + + config { + pins = "gpio31", "gpio32"; + drive-strength = <2>; /* 2 MA */ + bias-disable; /* No PULL */ + }; + }; + }; + + /*sensors */ + cam_sensor_mclk0_default: cam_sensor_mclk0_default { + /* MCLK0 */ + mux { + /* CLK, DATA */ + pins = "gpio26"; + function = "cam_mclk"; + }; + + config { + pins = "gpio26"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk0_sleep: cam_sensor_mclk0_sleep { + /* MCLK0 */ + mux { + /* CLK, DATA */ + pins = "gpio26"; + function = "cam_mclk"; + }; + + config { + pins = "gpio26"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_default: cam_sensor_rear_default { + /* RESET, STANDBY */ + mux { + pins = "gpio33", "gpio39"; + function = "gpio"; + }; + + config { + pins = "gpio33", "gpio39"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_sleep: cam_sensor_rear_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio33", "gpio39"; + function = "gpio"; + }; + + config { + pins = "gpio33", "gpio39"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_ir_cut_default: cam_sensor_ir_cut_default { + /* RESET, STANDBY */ + mux { + pins = "gpio38", "gpio39"; + function = "gpio"; + }; + + config { + pins = "gpio38","gpio39"; + bias-pull-up; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_ir_cut_sleep: cam_sensor_ir_cut_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio38","gpio39"; + function = "gpio"; + }; + + config { + pins = "gpio38","gpio39"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_default1: cam_sensor_rear_default1 { + /* RESET*/ + mux { + pins = "gpio40"; + function = "gpio"; + }; + + config { + pins = "gpio40"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_sleep1: cam_sensor_rear_sleep1 { + /* RESET*/ + mux { + pins = "gpio40"; + function = "gpio"; + }; + + config { + pins = "gpio40"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_vana: cam_sensor_rear_vdig { + /* VDIG */ + mux { + pins = "gpio62"; + function = "gpio"; + }; + + config { + pins = "gpio62"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_rear_vana_sleep: cam_sensor_rear_vdig_sleep { + /* VDIG */ + mux { + pins = "gpio62"; + function = "gpio"; + }; + + config { + pins = "gpio62"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_default: cam_sensor_mclk1_default { + /* MCLK1 */ + mux { + /* CLK, DATA */ + pins = "gpio27"; + function = "cam_mclk"; + }; + + config { + pins = "gpio27"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk1_sleep: cam_sensor_mclk1_sleep { + /* MCLK1 */ + mux { + /* CLK, DATA */ + pins = "gpio27"; + function = "cam_mclk"; + }; + + config { + pins = "gpio27"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_front_default: cam_sensor_front_default { + /* RESET, STANDBY */ + mux { + pins = "gpio41","gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio41","gpio132"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_front_sleep: cam_sensor_front_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio41","gpio132"; + function = "gpio"; + }; + + config { + pins = "gpio41","gpio132"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_default: cam_sensor_mclk2_default { + /* MCLK2 */ + mux { + /* CLK, DATA */ + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_mclk2_sleep: cam_sensor_mclk2_sleep { + /* MCLK2 */ + mux { + /* CLK, DATA */ + pins = "gpio28"; + function = "cam_mclk"; + }; + + config { + pins = "gpio28"; + bias-pull-down; /* PULL DOWN */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_front1_default: cam_sensor_front1_default { + /* RESET, STANDBY */ + mux { + pins = "gpio129"; + function = "gpio"; + }; + + config { + pins = "gpio129"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + cam_sensor_front1_sleep: cam_sensor_front1_sleep { + /* RESET, STANDBY */ + mux { + pins = "gpio129"; + function = "gpio"; + }; + + config { + pins = "gpio129"; + bias-disable; /* No PULL */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + pmx_adv7533_int: pmx_adv7533_int { + adv7533_int_active: adv7533_int_active { + mux { + pins = "gpio90"; + function = "gpio"; + }; + + config { + pins = "gpio90"; + drive-strength = <16>; + bias-disable; + }; + }; + + adv7533_int_suspend: adv7533_int_suspend { + mux { + pins = "gpio90"; + function = "gpio"; + }; + + config { + pins = "gpio90"; + drive-strength = <16>; + bias-disable; + }; + }; + + }; + + pmx_mdss: pmx_mdss { + mdss_dsi_active: mdss_dsi_active { + mux { + pins = "gpio61", "gpio59"; + function = "gpio"; + }; + + config { + pins = "gpio61", "gpio59"; + drive-strength = <8>; /* 8 mA */ + bias-disable = <0>; /* no pull */ + output-high; + }; + }; + + mdss_dsi_suspend: mdss_dsi_suspend { + mux { + pins = "gpio61", "gpio59"; + function = "gpio"; + }; + + config { + pins = "gpio61", "gpio59"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + }; + }; + }; + + pmx_mdss_te { + mdss_te_active: mdss_te_active { + mux { + pins = "gpio24"; + function = "mdp_vsync"; + }; + config { + pins = "gpio24"; + drive-strength = <2>; /* 8 mA */ + bias-pull-down; /* pull down*/ + }; + }; + + mdss_te_suspend: mdss_te_suspend { + mux { + pins = "gpio24"; + function = "mdp_vsync"; + }; + config { + pins = "gpio24"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + }; + }; + }; + + hsuart_active: default { + mux { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + function = "blsp_uart4"; + }; + + config { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + drive-strength = <16>; + bias-disable; + }; + }; + + hsuart_sleep: sleep { + mux { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + function = "gpio"; + }; + + config { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + drive-strength = <2>; + bias-disable; + }; + }; + + blsp2_uart0_active: blsp2_uart0_active { + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_uart5"; + }; + + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <16>; + bias-disable; + }; + }; + + blsp2_uart0_sleep: blsp2_uart0_sleep { + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "gpio"; + }; + + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + }; + + /* SDC pin type */ + sdc1_clk_on: sdc1_clk_on { + config { + pins = "sdc1_clk"; + bias-disable; /* NO pull */ + drive-strength = <16>; /* 16 MA */ + }; + }; + + sdc1_clk_off: sdc1_clk_off { + config { + pins = "sdc1_clk"; + bias-disable; /* NO pull */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + sdc1_cmd_on: sdc1_cmd_on { + config { + pins = "sdc1_cmd"; + bias-pull-up; /* pull up */ + drive-strength = <10>; /* 10 MA */ + }; + }; + + sdc1_cmd_off: sdc1_cmd_off { + config { + pins = "sdc1_cmd"; + num-grp-pins = <1>; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + sdc1_data_on: sdc1_data_on { + config { + pins = "sdc1_data"; + bias-pull-up; /* pull up */ + drive-strength = <10>; /* 10 MA */ + }; + }; + + sdc1_data_off: sdc1_data_off { + config { + pins = "sdc1_data"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + sdc1_rclk_on: sdc1_rclk_on { + config { + pins = "sdc1_rclk"; + bias-pull-down; /* pull down */ + }; + }; + + sdc1_rclk_off: sdc1_rclk_off { + config { + pins = "sdc1_rclk"; + bias-pull-down; /* pull down */ + }; + }; + + sdc2_clk_on: sdc2_clk_on { + config { + pins = "sdc2_clk"; + drive-strength = <16>; /* 16 MA */ + bias-disable; /* NO pull */ + }; + }; + + sdc2_clk_off: sdc2_clk_off { + config { + pins = "sdc2_clk"; + bias-disable; /* NO pull */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + sdc2_cmd_on: sdc2_cmd_on { + config { + pins = "sdc2_cmd"; + bias-pull-up; /* pull up */ + drive-strength = <10>; /* 10 MA */ + }; + }; + + sdc2_cmd_off: sdc2_cmd_off { + config { + pins = "sdc2_cmd"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + sdc2_data_on: sdc2_data_on { + config { + pins = "sdc2_data"; + bias-pull-up; /* pull up */ + drive-strength = <10>; /* 10 MA */ + }; + }; + + sdc2_data_off: sdc2_data_off { + config { + pins = "sdc2_data"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + + sdc2_cd_on: cd_on { + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + sdc2_cd_off: cd_off { + mux { + pins = "gpio133"; + function = "gpio"; + }; + + config { + pins = "gpio133"; + drive-strength = <2>; + bias-disable; + }; + }; + + i2c_2 { + i2c_2_active: i2c_2_active { + /* active state */ + mux { + pins = "gpio6", "gpio7"; + function = "blsp_i2c2"; + }; + + config { + pins = "gpio6", "gpio7"; + drive-strength = <2>; + bias-disable; + }; + }; + + i2c_2_sleep: i2c_2_sleep { + /* suspended state */ + mux { + pins = "gpio6", "gpio7"; + function = "gpio"; + }; + + config { + pins = "gpio6", "gpio7"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + i2c_3 { + i2c_3_active: i2c_3_active { + /* active state */ + mux { + pins = "gpio10", "gpio11"; + function = "blsp_i2c3"; + }; + + config { + pins = "gpio10", "gpio11"; + drive-strength = <2>; + bias-disable; + }; + }; + + i2c_3_sleep: i2c_3_sleep { + /* suspended state */ + mux { + pins = "gpio10", "gpio11"; + function = "gpio"; + }; + + config { + pins = "gpio10", "gpio11"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + i2c_5 { + i2c_5_active: i2c_5_active { + /* active state */ + mux { + pins = "gpio18", "gpio19"; + function = "blsp_i2c5"; + }; + + config { + pins = "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + }; + + i2c_5_sleep: i2c_5_sleep { + /* suspended state */ + mux { + pins = "gpio18", "gpio19"; + function = "gpio"; + }; + + config { + pins = "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + /*fp gpio of gooid & fpc */ + goodix_spi_active: goodix_spi_active{ + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_spi5"; + }; + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + goodix_reset_reset: goodix_reset_reset{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-low; + }; + }; + goodix_reset_active: goodix_reset_active{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-high; + }; + }; + goodix_irq_active: goodix_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable = <0>; + input-enable; + }; + }; + + /* fingerprint pin function */ + fpc_spi_active: fpc_spi_active { + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_spi7"; + }; + + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + }; + fpc_reset_reset: fpc_reset_reset { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + fpc_reset_active: fpc_reset_active { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + fpc_irq_active: fpc_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable; + input-enable; + }; + }; + + smartpa_irq_active: smartpa_irq_active { + mux { + pins = "gpio87"; + function = "gpio"; + }; + config { + pins = "gpio87"; + drive-strength = <2>; + bias-pull-down; + input-enable; + }; + }; + + pmx_rd_nfc_int { + /*qcom,pins = <&gp 17>;*/ + pins = "gpio17"; + qcom,pin-func = <0>; + qcom,num-grp-pins = <1>; + label = "pmx_nfc_int"; + + nfc_int_active: active { + drive-strength = <6>; + bias-pull-up; + }; + + nfc_int_suspend: suspend { + drive-strength = <6>; + bias-pull-up; + }; + }; + + pmx_nfc_reset { + /*qcom,pins = <&gp 16>;*/ + pins = "gpio16"; + qcom,pin-func = <0>; + qcom,num-grp-pins = <1>; + label = "pmx_nfc_disable"; + + nfc_disable_active: active { + drive-strength = <6>; + bias-pull-up; + }; + + nfc_disable_suspend: suspend { + drive-strength = <6>; + bias-disable; + }; + }; + + wcnss_pmux_5wire { + /* Active configuration of bus pins */ + wcnss_default: wcnss_default { + wcss_wlan2 { + pins = "gpio76"; + function = "wcss_wlan2"; + }; + wcss_wlan1 { + pins = "gpio77"; + function = "wcss_wlan1"; + }; + wcss_wlan0 { + pins = "gpio78"; + function = "wcss_wlan0"; + }; + wcss_wlan { + pins = "gpio79", "gpio80"; + function = "wcss_wlan"; + }; + + config { + pins = "gpio76", "gpio77", + "gpio78", "gpio79", + "gpio80"; + drive-strength = <6>; /* 6 MA */ + bias-pull-up; /* PULL UP */ + }; + }; + + wcnss_sleep: wcnss_sleep { + wcss_wlan2 { + pins = "gpio76"; + function = "wcss_wlan2"; + }; + wcss_wlan1 { + pins = "gpio77"; + function = "wcss_wlan1"; + }; + wcss_wlan0 { + pins = "gpio78"; + function = "wcss_wlan0"; + }; + wcss_wlan { + pins = "gpio79", "gpio80"; + function = "wcss_wlan"; + }; + + config { + pins = "gpio76", "gpio77", + "gpio78", "gpio79", + "gpio80"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; /* PULL Down */ + }; + }; + }; + + wcnss_pmux_gpio: wcnss_pmux_gpio { + wcnss_gpio_default: wcnss_gpio_default { + /* Active configuration of bus pins */ + mux { + /* Uses general purpose pins */ + pins = "gpio76", "gpio77", + "gpio78", "gpio79", + "gpio80"; + function = "gpio"; + }; + + config { + pins = "gpio76", "gpio77", + "gpio78", "gpio79", + "gpio80"; + drive-strength = <6>; /* 6 MA */ + bias-pull-up; /* PULL UP */ + }; + }; + }; + + wcd9xxx_intr { + wcd_intr_default: wcd_intr_default{ + mux { + pins = "gpio73"; + function = "gpio"; + }; + + config { + pins = "gpio73"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + input-enable; + }; + }; + }; + + cdc_reset_ctrl { + cdc_reset_sleep: cdc_reset_sleep { + mux { + pins = "gpio67"; + function = "gpio"; + }; + config { + pins = "gpio67"; + drive-strength = <16>; + bias-disable; + output-low; + }; + }; + cdc_reset_active:cdc_reset_active { + mux { + pins = "gpio67"; + function = "gpio"; + }; + config { + pins = "gpio67"; + drive-strength = <16>; + bias-pull-down; + output-high; + }; + }; + }; + + cdc_mclk2_pin { + cdc_mclk2_sleep: cdc_mclk2_sleep { + mux { + pins = "gpio66"; + function = "pri_mi2s"; + }; + config { + pins = "gpio66"; + drive-strength = <2>; /* 2 mA */ + bias-pull-down; /* PULL DOWN */ + }; + }; + cdc_mclk2_active: cdc_mclk2_active { + mux { + pins = "gpio66"; + function = "pri_mi2s"; + }; + config { + pins = "gpio66"; + drive-strength = <8>; /* 8 mA */ + bias-disable; /* NO PULL */ + }; + }; + }; + + cdc-pdm-2-lines { + cdc_pdm_lines_2_act: pdm_lines_2_on { + mux { + pins = "gpio70", "gpio71", "gpio72"; + function = "cdc_pdm0"; + }; + + config { + pins = "gpio70", "gpio71", "gpio72"; + drive-strength = <8>; + }; + }; + + cdc_pdm_lines_2_sus: pdm_lines_2_off { + mux { + pins = "gpio70", "gpio71", "gpio72"; + function = "cdc_pdm0"; + }; + + config { + pins = "gpio70", "gpio71", "gpio72"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + cdc-pdm-lines { + cdc_pdm_lines_act: pdm_lines_on { + mux { + pins = "gpio69", "gpio73", "gpio74"; + function = "cdc_pdm0"; + }; + + config { + pins = "gpio69", "gpio73", "gpio74"; + drive-strength = <8>; + }; + }; + cdc_pdm_lines_sus: pdm_lines_off { + mux { + pins = "gpio69", "gpio73", "gpio74"; + function = "cdc_pdm0"; + }; + + config { + pins = "gpio69", "gpio73", "gpio74"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + cdc-pdm-comp-lines { + cdc_pdm_comp_lines_act: pdm_comp_lines_on { + mux { + pins = "gpio67", "gpio68"; + function = "cdc_pdm0"; + }; + + config { + pins = "gpio67", "gpio68"; + drive-strength = <8>; + }; + }; + + cdc_pdm_comp_lines_sus: pdm_comp_lines_off { + mux { + pins = "gpio67", "gpio68"; + function = "cdc_pdm0"; + }; + + config { + pins = "gpio67", "gpio68"; + drive-strength = <2>; + bias-disable; + }; + }; + }; + + cross-conn-det { + cross_conn_det_act: lines_on { + mux { + pins = "gpio63"; + function = "gpio"; + }; + + config { + pins = "gpio63"; + drive-strength = <8>; + output-low; + bias-pull-down; + }; + }; + + cross_conn_det_sus: lines_off { + mux { + pins = "gpio63"; + function = "gpio"; + }; + + config { + pins = "gpio63"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + /* WSA VI sense */ + wsa-vi { + wsa_vi_on: wsa_vi_on { + mux { + pins = "gpio94", "gpio95"; + function = "wsa_io"; + }; + + config { + pins = "gpio94", "gpio95"; + drive-strength = <8>; /* 8 MA */ + bias-disable; /* NO pull */ + }; + }; + + wsa_vi_off: wsa_vi_off { + mux { + pins = "gpio94", "gpio95"; + function = "wsa_io"; + }; + + config { + pins = "gpio94", "gpio95"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; + }; + }; + }; + + /* WSA Reset */ + wsa_reset { + wsa_reset_on: wsa_reset_on { + mux { + pins = "gpio96"; + function = "gpio"; + }; + + config { + pins = "gpio96"; + drive-strength = <2>; /* 2 MA */ + output-high; + }; + }; + + wsa_reset_off: wsa_reset_off { + mux { + pins = "gpio96"; + function = "gpio"; + }; + + config { + pins = "gpio96"; + drive-strength = <2>; /* 2 MA */ + output-low; + }; + }; + }; + + /* WSA CLK */ + wsa_clk { + wsa_clk_on: wsa_clk_on { + mux { + pins = "gpio25"; + function = "pri_mi2s_mclk_a"; + }; + + config { + pins = "gpio25"; + drive-strength = <8>; /* 8 MA */ + output-high; + }; + }; + + wsa_clk_off: wsa_clk_off { + mux { + pins = "gpio25"; + function = "pri_mi2s_mclk_a"; + }; + + config { + pins = "gpio25"; + drive-strength = <2>; /* 2 MA */ + output-low; + bias-pull-down; + }; + }; + }; + + pri-tlmm-lines { + pri_tlmm_lines_act: pri_tlmm_lines_act { + mux { + pins = "gpio88", "gpio91", "gpio93"; + function = "pri_mi2s"; + }; + + config { + pins = "gpio88", "gpio91", "gpio93"; + drive-strength = <8>; + }; + }; + + pri_tlmm_lines_sus: pri_tlmm_lines_sus { + mux { + pins = "gpio88", "gpio91", "gpio93"; + function = "pri_mi2s"; + }; + + config { + pins = "gpio88", "gpio91", "gpio93"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + pri-tlmm-ws-lines { + pri_tlmm_ws_act: pri_tlmm_ws_act { + mux { + pins = "gpio92"; + function = "pri_mi2s_ws"; + }; + + config { + pins = "gpio92"; + drive-strength = <8>; + }; + }; + + pri_tlmm_ws_sus: pri_tlmm_ws_sus { + mux { + pins = "gpio92"; + function = "pri_mi2s_ws"; + }; + + config { + pins = "gpio92"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + spi6 { + spi6_default: spi6_default { + /* active state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <12>; /* 12 MA */ + bias-disable = <0>; /* No PULL */ + }; + }; + + spi6_sleep: spi6_sleep { + /* suspended state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "gpio"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; /* PULL Down */ + }; + }; + + spi6_cs0_active: cs0_active { + /* CS */ + mux { + pins = "gpio22"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + + spi6_cs0_sleep: cs0_sleep { + /* CS */ + mux { + pins = "gpio22"; + function = "gpio"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + }; + + spi3 { + spi3_default: spi3_default { + /* active state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio8", "gpio9", "gpio11"; + function = "blsp_spi3"; + }; + + config { + pins = "gpio8", "gpio9", "gpio11"; + drive-strength = <12>; /* 12 MA */ + bias-disable = <0>; /* No PULL */ + }; + }; + + spi3_sleep: spi3_sleep { + /* suspended state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio8", "gpio9", "gpio11"; + function = "gpio"; + }; + + config { + pins = "gpio8", "gpio9", "gpio11"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; /* PULL Down */ + }; + }; + + spi3_cs0_active: cs0_active { + /* CS */ + mux { + pins = "gpio10"; + function = "blsp_spi3"; + }; + + config { + pins = "gpio10"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + + spi3_cs0_sleep: cs0_sleep { + /* CS */ + mux { + pins = "gpio10"; + function = "gpio"; + }; + + config { + pins = "gpio10"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + }; + + /* add pingrp for touchscreen */ + pmx_ts_int_active { + ts_int_active: ts_int_active { + mux { + pins = "gpio65"; + function = "gpio"; + }; + + config { + pins = "gpio65"; + drive-strength = <8>; + bias-pull-up; + }; + }; + }; + + pmx_ts_int_suspend { + ts_int_suspend: ts_int_suspend { + mux { + pins = "gpio65"; + function = "gpio"; + }; + + config { + pins = "gpio65"; + drive-strength = <2>; + bias-pull-down; + }; + }; + synaptic_int_suspend: synaptic_int_suspend { + mux { + pins = "gpio65"; + function = "gpio"; + }; + + config { + pins = "gpio65"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + /* add pingrp for goodix gt917d touchscreen */ + ts_int_default: ts_int_defalut { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + drive-strength = <16>; + /*bias-pull-up;*/ + input-enable; + bias-disable; + }; + }; + + ts_int_output_high: ts_int_output_high { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + output-high; + }; + }; + + ts_int_output_low: ts_int_output_low { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + output-low; + }; + }; + + ts_int_input: ts_int_input { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + input-enable; + bias-disable; + }; + }; + + pmx_ts_reset_active { + ts_reset_active: ts_reset_active { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + drive-strength = <8>; + bias-pull-up; + }; + }; + }; + + pmx_ts_reset_suspend { + ts_reset_suspend: ts_reset_suspend { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + drive-strength = <2>; + bias-pull-down; + }; + }; + synaptic_reset_suspend: synaptic_reset_suspend { + mux { + pins = "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio64"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + + pmx_ts_release { + ts_release: ts_release { + mux { + pins = "gpio65", "gpio64"; + function = "gpio"; + }; + + config { + pins = "gpio65", "gpio64"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + tlmm_gpio_key { + gpio_key_active: gpio_key_active { + mux { + pins = "gpio85", "gpio86", "gpio87"; + function = "gpio"; + }; + + config { + pins = "gpio85", "gpio86", "gpio87"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + gpio_key_suspend: gpio_key_suspend { + mux { + pins = "gpio85", "gpio86", "gpio87"; + function = "gpio"; + }; + + config { + pins = "gpio85", "gpio86", "gpio87"; + drive-strength = <2>; + bias-pull-up; + }; + }; + }; + pmx_qdsd_clk { + qdsd_clk_sdcard: clk_sdcard { + config { + pins = "qdsd_clk"; + bias-disable;/* NO pull */ + drive-strength = <16>; /* 16 MA */ + }; + }; + qdsd_clk_trace: clk_trace { + config { + pins = "qdsd_clk"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_clk_swdtrc: clk_swdtrc { + config { + pins = "qdsd_clk"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_clk_spmi: clk_spmi { + config { + pins = "qdsd_clk"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + }; + + pmx_qdsd_cmd { + qdsd_cmd_sdcard: cmd_sdcard { + config { + pins = "qdsd_cmd"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_cmd_trace: cmd_trace { + config { + pins = "qdsd_cmd"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_cmd_swduart: cmd_uart { + config { + pins = "qdsd_cmd"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_cmd_swdtrc: cmd_swdtrc { + config { + pins = "qdsd_cmd"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_cmd_jtag: cmd_jtag { + config { + pins = "qdsd_cmd"; + bias-disable; /* NO pull */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_cmd_spmi: cmd_spmi { + config { + pins = "qdsd_cmd"; + bias-pull-down; /* pull down */ + drive-strength = <10>; /* 10 MA */ + }; + }; + }; + + pmx_qdsd_data0 { + qdsd_data0_sdcard: data0_sdcard { + config { + pins = "qdsd_data0"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data0_trace: data0_trace { + config { + pins = "qdsd_data0"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data0_swduart: data0_uart { + config { + pins = "qdsd_data0"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data0_swdtrc: data0_swdtrc { + config { + pins = "qdsd_data0"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data0_jtag: data0_jtag { + config { + pins = "qdsd_data0"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data0_spmi: data0_spmi { + config { + pins = "qdsd_data0"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + }; + + pmx_qdsd_data1 { + qdsd_data1_sdcard: data1_sdcard { + config { + pins = "qdsd_data1"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data1_trace: data1_trace { + config { + pins = "qdsd_data1"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data1_swduart: data1_uart { + config { + pins = "qdsd_data1"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data1_swdtrc: data1_swdtrc { + config { + pins = "qdsd_data1"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data1_jtag: data1_jtag { + config { + pins = "qdsd_data1"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + }; + + pmx_qdsd_data2 { + qdsd_data2_sdcard: data2_sdcard { + config { + pins = "qdsd_data2"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data2_trace: data2_trace { + config { + pins = "qdsd_data2"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data2_swduart: data2_uart { + config { + pins = "qdsd_data2"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data2_swdtrc: data2_swdtrc { + config { + pins = "qdsd_data2"; + bias-pull-down; /* pull down */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data2_jtag: data2_jtag { + config { + pins = "qdsd_data2"; + bias-pull-up; /* pull up */ + drive-strength = <8>; /* 8 MA */ + }; + }; + }; + + pmx_qdsd_data3 { + qdsd_data3_sdcard: data3_sdcard { + config { + pins = "qdsd_data3"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data3_trace: data3_trace { + config { + pins = "qdsd_data3"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + qdsd_data3_swduart: data3_uart { + config { + pins = "qdsd_data3"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data3_swdtrc: data3_swdtrc { + config { + pins = "qdsd_data3"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data3_jtag: data3_jtag { + config { + pins = "qdsd_data3"; + bias-pull-up; /* pull up */ + drive-strength = <2>; /* 2 MA */ + }; + }; + qdsd_data3_spmi: data3_spmi { + config { + pins = "qdsd_data3"; + bias-pull-down; /* pull down */ + drive-strength = <8>; /* 8 MA */ + }; + }; + }; + + typec_ssmux_config: typec_ssmux_config { + mux { + pins = "gpio139"; + function = "gpio"; + }; + + config { + pins = "gpio139"; + drive-strength = <2>; + bias-disable; + }; + }; + + ssusb_mode_sel: ssusb_mode_sel { + mux { + pins = "gpio12"; + function = "gpio"; + }; + + config { + pins = "gpio12"; + drive-strength = <2>; + bias-disable; + input-enable; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi index 4f4324d746079..5a3945a2fc186 100644 --- a/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-pinctrl.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -145,12 +146,12 @@ cam_sensor_rear_default: cam_sensor_rear_default { /* RESET, STANDBY */ mux { - pins = "gpio40", "gpio39"; + pins = "gpio33", "gpio39"; function = "gpio"; }; config { - pins = "gpio40", "gpio39"; + pins = "gpio33", "gpio39"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -159,12 +160,12 @@ cam_sensor_rear_sleep: cam_sensor_rear_sleep { /* RESET, STANDBY */ mux { - pins = "gpio40", "gpio39"; + pins = "gpio33", "gpio39"; function = "gpio"; }; config { - pins = "gpio40", "gpio39"; + pins = "gpio33", "gpio39"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -229,12 +230,12 @@ cam_sensor_rear_vana: cam_sensor_rear_vdig { /* VDIG */ mux { - pins = "gpio134"; + pins = "gpio62"; function = "gpio"; }; config { - pins = "gpio134"; + pins = "gpio62"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -243,40 +244,12 @@ cam_sensor_rear_vana_sleep: cam_sensor_rear_vdig_sleep { /* VDIG */ mux { - pins = "gpio134"; + pins = "gpio62"; function = "gpio"; }; config { - pins = "gpio134"; - bias-disable; /* No PULL */ - drive-strength = <2>; /* 2 MA */ - }; - }; - - cam_sensor_rear_vana1: cam_sensor_rear_vdig1 { - /* VDIG */ - mux { - pins = "gpio46"; - function = "gpio"; - }; - - config { - pins = "gpio46"; - bias-disable; /* No PULL */ - drive-strength = <2>; /* 2 MA */ - }; - }; - - cam_sensor_rear_vana_sleep1: cam_sensor_rear_vdig_sleep1 { - /* VDIG */ - mux { - pins = "gpio46"; - function = "gpio"; - }; - - config { - pins = "gpio46"; + pins = "gpio62"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -315,12 +288,12 @@ cam_sensor_front_default: cam_sensor_front_default { /* RESET, STANDBY */ mux { - pins = "gpio131","gpio132"; + pins = "gpio41","gpio132"; function = "gpio"; }; config { - pins = "gpio131","gpio132"; + pins = "gpio41","gpio132"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -329,12 +302,12 @@ cam_sensor_front_sleep: cam_sensor_front_sleep { /* RESET, STANDBY */ mux { - pins = "gpio131","gpio132"; + pins = "gpio41","gpio132"; function = "gpio"; }; config { - pins = "gpio131","gpio132"; + pins = "gpio41","gpio132"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -373,12 +346,12 @@ cam_sensor_front1_default: cam_sensor_front1_default { /* RESET, STANDBY */ mux { - pins = "gpio129", "gpio130"; + pins = "gpio129"; function = "gpio"; }; config { - pins = "gpio129", "gpio130"; + pins = "gpio129"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -387,12 +360,12 @@ cam_sensor_front1_sleep: cam_sensor_front1_sleep { /* RESET, STANDBY */ mux { - pins = "gpio129", "gpio130"; + pins = "gpio129"; function = "gpio"; }; config { - pins = "gpio129", "gpio130"; + pins = "gpio129"; bias-disable; /* No PULL */ drive-strength = <2>; /* 2 MA */ }; @@ -777,6 +750,105 @@ }; }; + /*fp gpio of gooid & fpc */ + goodix_spi_active: goodix_spi_active{ + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_spi5"; + }; + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + goodix_reset_reset: goodix_reset_reset{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-low; + }; + }; + goodix_reset_active: goodix_reset_active{ + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable = <0>; + output-high; + }; + }; + goodix_irq_active: goodix_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable = <0>; + input-enable; + }; + }; + + /* fingerprint pin function */ + fpc_spi_active: fpc_spi_active { + mux { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + function = "blsp_spi7"; + }; + + config { + pins = "gpio16", "gpio17", "gpio18", "gpio19"; + drive-strength = <2>; + bias-disable; + }; + }; + fpc_reset_reset: fpc_reset_reset { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-low; + }; + }; + fpc_reset_active: fpc_reset_active { + mux { + pins = "gpio140"; + function = "gpio"; + }; + config { + pins = "gpio140"; + drive-strength = <2>; + bias-disable; + output-high; + }; + }; + fpc_irq_active: fpc_irq_active { + mux { + pins = "gpio48"; + function = "gpio"; + }; + config { + pins = "gpio48"; + drive-strength = <2>; + bias-disable; + input-enable; + }; + }; + pmx_rd_nfc_int { /*qcom,pins = <&gp 17>;*/ pins = "gpio17"; @@ -1159,24 +1231,24 @@ pri-tlmm-lines { pri_tlmm_lines_act: pri_tlmm_lines_act { mux { - pins = "gpio91", "gpio93"; + pins = "gpio88", "gpio91", "gpio93"; function = "pri_mi2s"; }; config { - pins = "gpio91", "gpio93"; + pins = "gpio88", "gpio91", "gpio93"; drive-strength = <8>; }; }; pri_tlmm_lines_sus: pri_tlmm_lines_sus { mux { - pins = "gpio91", "gpio93"; + pins = "gpio88", "gpio91", "gpio93"; function = "pri_mi2s"; }; config { - pins = "gpio91", "gpio93"; + pins = "gpio88", "gpio91", "gpio93"; drive-strength = <2>; bias-pull-down; }; @@ -1210,6 +1282,66 @@ }; }; + spi6 { + spi6_default: spi6_default { + /* active state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <12>; /* 12 MA */ + bias-disable = <0>; /* No PULL */ + }; + }; + + spi6_sleep: spi6_sleep { + /* suspended state */ + mux { + /* MOSI, MISO, CLK */ + pins = "gpio20", "gpio21", "gpio23"; + function = "gpio"; + }; + + config { + pins = "gpio20", "gpio21", "gpio23"; + drive-strength = <2>; /* 2 MA */ + bias-pull-down; /* PULL Down */ + }; + }; + + spi6_cs0_active: cs0_active { + /* CS */ + mux { + pins = "gpio22"; + function = "blsp_spi6"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + + spi6_cs0_sleep: cs0_sleep { + /* CS */ + mux { + pins = "gpio22"; + function = "gpio"; + }; + + config { + pins = "gpio22"; + drive-strength = <2>; + bias-disable = <0>; + }; + }; + }; + spi3 { spi3_default: spi3_default { /* active state */ @@ -1301,6 +1433,55 @@ }; }; + /* add pingrp for goodix gt917d touchscreen */ + ts_int_default: ts_int_defalut { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + drive-strength = <16>; + /*bias-pull-up;*/ + input-enable; + bias-disable; + }; + }; + + ts_int_output_high: ts_int_output_high { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + output-high; + }; + }; + + ts_int_output_low: ts_int_output_low { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + output-low; + }; + }; + + ts_int_input: ts_int_input { + mux { + pins = "gpio65"; + function = "gpio"; + }; + config { + pins = "gpio65"; + input-enable; + bias-disable; + }; + }; + pmx_ts_reset_active { ts_reset_active: ts_reset_active { mux { @@ -1349,12 +1530,12 @@ tlmm_gpio_key { gpio_key_active: gpio_key_active { mux { - pins = "gpio85", "gpio86", "gpio87"; + pins = "gpio85"; function = "gpio"; }; config { - pins = "gpio85", "gpio86", "gpio87"; + pins = "gpio85"; drive-strength = <2>; bias-pull-up; }; @@ -1362,12 +1543,12 @@ gpio_key_suspend: gpio_key_suspend { mux { - pins = "gpio85", "gpio86", "gpio87"; + pins = "gpio85"; function = "gpio"; }; config { - pins = "gpio85", "gpio86", "gpio87"; + pins = "gpio85"; drive-strength = <2>; bias-pull-up; }; diff --git a/arch/arm/boot/dts/qcom/msm8953-pm.dtsi b/arch/arm/boot/dts/qcom/msm8953-pm.dtsi index d30fe282fb356..71c5dc8b15ec7 100644 --- a/arch/arm/boot/dts/qcom/msm8953-pm.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-pm.dtsi @@ -402,6 +402,7 @@ <0xff 264>, /* arm-smmu context fault */ <0xff 269>, /* rpm_wdog_expired_irq */ <0xff 270>, /* blsp1_bam_irq[0] */ + <0xff 271>, /* blsp1_bam_irq[0] */ <0xff 273>, /* smmu_bus_intr[18] */ <0xff 274>, /* smmu_bus_intr[19] */ <0xff 275>, /* rpm_ipc(30) */ @@ -475,6 +476,7 @@ <72 139>, <73 140>, <74 141>, + <0xff 24>, <0xff 88>; }; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-e7.dtsi b/arch/arm/boot/dts/qcom/msm8953-qrd-e7.dtsi new file mode 100644 index 0000000000000..2542be41ae4f3 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-e7.dtsi @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "msm8953-pinctrl-e7.dtsi" +#include "msm8953-camera-sensor-qrd-e7.dtsi" + +&soc { + gpio_keys { + compatible = "gpio-keys"; + input-name = "gpio-keys"; + pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; + pinctrl-0 = <&gpio_key_active>; + pinctrl-1 = <&gpio_key_suspend>; + + vol_up { + label = "volume_up"; + gpios = <&tlmm 85 0x1>; + linux,input-type = <1>; + linux,code = <115>; + debounce-interval = <15>; + }; + }; + + goodix_fp { + compatible = "goodix,fingerprint"; + spi-max-frequency = <1000000>; + input-device-name = "gf3208"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + + goodix,gpio_reset = <&tlmm 140 0>; + goodix,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "goodixfp_spi_active", + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active"; + + pinctrl-0 = <&goodix_spi_active>; + pinctrl-1 = <&goodix_reset_reset>; + pinctrl-2 = <&goodix_reset_active>; + pinctrl-3 = <&goodix_irq_active>; + }; + + fpc1020 { + compatible = "fpc,fpc1020"; + spi-max-frequency = <1000000>; + input-device-name = "fpc1020"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + fpc,gpio_rst = <&tlmm 140 0>; + fpc,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "fpc1020_spi_active", + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active"; + + pinctrl-0 = <&fpc_spi_active>; + pinctrl-1 = <&fpc_reset_reset>; + pinctrl-2 = <&fpc_reset_active>; + pinctrl-3 = <&fpc_irq_active>; + }; + + i2c@78b7000 { /* BLSP1 QUP3 */ + status = "okay"; + vituralsar@33{ + compatible = "virtualsar,sar"; + reg = <0x33>; + interrupt-parent = <&tlmm>; + interrupts = <130 0x02>; + vituralsar,irq-gpio = <&tlmm 130 0x2008>; + }; + synaptics_dsx@20 { + compatible = "synaptics,dsx-i2c"; + reg = <0x20>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + avdd-supply = <&pm8953_l6>; + pinctrl-names = "pmx_ts_active", "pmx_ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&synaptic_int_suspend &synaptic_reset_suspend>; + synaptics,pwr-reg-name = "avdd"; + synaptics,bus-reg-name = "vdd"; + synaptics,ub-i2c-addr = <0x2c>; + synaptics,irq-gpio = <&tlmm 65 0x2008>; /* IRQF_ONESHOT | IRQF_TRIGGER_LOW */ + synaptics,rst-gpio = <&tlmm 64 0x0>; + synaptics,irq-on-state = <0>; + synaptics,power-delay-ms = <200>; + synaptics,reset-delay-ms = <200>; + synaptics,reset-on-state = <0>; + synaptics,reset-active-ms = <20>; + /* uncomment and update line below as appropriate if there are 0D buttons */ + /* synaptics,cap-button-codes = <102 158>; */ + synaptics,cap-button-codes = <139 172 158>; + /* uncomment and update lines below as appropriate if there are virtual buttons */ + /* synaptics,vir-button-codes = <102 100 900 100 60 158 300 900 100 60>; */ + /* synaptics,max-y-for-2d = <800>; */ + }; + /* Novatek device tree node */ + novatek@62 { + compatible = "novatek,NVT-ts"; + reg = <0x62>; + status = "ok"; + + vdd-supply = <&pm8953_l10>; + avdd-supply = <&pm8953_l6>; + nvt,pwr-reg-name = "avdd"; + nvt,bus-reg-name = "vdd"; + + novatek,reset-gpio = <&tlmm 64 0x0>; + novatek,irq-gpio = <&tlmm 65 0x2001>; + + /* MP */ + novatek,mp-support-dt; + + novatek-mp-criteria-5902@0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "novatek-mp-criteria-5902"; + + /* MP Config*/ + IC_X_CFG_SIZE = <18>; + IC_Y_CFG_SIZE = <32>; + IC_KEY_CFG_SIZE = <4>; + X_Channel = <18>; + Y_Channel = <32>; + AIN_X = <17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0>; + AIN_Y = <31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 + 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0>; + AIN_KEY = <0 1 2 0xFF>; + + /* MP Criteria */ + PS_Config_Lmt_Short_Rawdata_P = <13500>; + PS_Config_Lmt_Short_Rawdata_N = <11500>; + PS_Config_Lmt_Key_Short_Rawdata_P = <20000>; + PS_Config_Lmt_Key_Short_Rawdata_N = <11550>; + PS_Config_Lmt_Short_Diff_P = <6300>; + PS_Config_Lmt_Short_Diff_N = <0>; + PS_Config_Lmt_Key_Short_Diff_P = <6300>; + PS_Config_Lmt_Key_Short_Diff_N = <0>; + PS_Config_Lmt_Short_Base_P = <2000>; + PS_Config_Lmt_Short_Base_N = <(-2000)>; + PS_Config_Lmt_Key_Short_Base_P = <2000>; + PS_Config_Lmt_Key_Short_Base_N = <(-2000)>; + + PS_Config_Lmt_Open_Rawdata_P = < + 10288 10571 10538 10516 10489 10469 10460 10489 10509 10474 10495 10470 10454 10454 10458 10461 10475 10402 + 10203 10356 10326 10308 10287 10276 10272 10295 10305 10273 10287 10268 10256 10250 10251 10249 10260 10258 + 10262 10393 10367 10350 10333 10337 10322 10344 10348 10307 10320 10298 10289 10277 10279 10275 10283 10281 + 10178 10320 10290 10273 10261 10258 10253 10275 10276 10252 10264 10245 10234 10230 10219 10215 10226 10208 + 10199 10348 10307 10291 10285 10278 10277 10299 10299 10279 10290 10270 10260 10248 10245 10242 10263 10234 + 10137 10276 10233 10217 10215 10216 10210 10233 10231 10199 10208 10189 10178 10165 10164 10160 10182 10153 + 10151 10284 10241 10226 10228 10225 10224 10247 10246 10235 10245 10225 10215 10214 10202 10196 10218 10190 + 10067 10186 10153 10139 10143 10140 10140 10164 10162 10140 10149 10127 10118 10109 10106 10100 10114 10093 + 10095 10205 10188 10167 10171 10167 10168 10191 10189 10152 10162 10139 10130 10120 10119 10126 10124 10106 + 9997 10101 10083 10065 10068 10065 10068 10092 10090 10072 10080 10057 10048 10049 10038 10045 10043 10026 + 10000 10100 10082 10068 10068 10068 10072 10097 10094 10069 10076 10053 10044 10037 10035 10041 10041 10021 + 9917 10011 9988 9983 9993 9983 9987 10012 10009 9977 9984 9959 9951 9942 9943 9948 9949 9930 + 9910 9999 9969 9983 9977 9974 9980 10005 10001 9986 9994 9969 9960 9965 9961 9949 9962 9938 + 9811 9892 9867 9884 9870 9871 9878 9903 9899 9881 9888 9862 9853 9850 9861 9844 9861 9832 + 9823 9900 9880 9898 9896 9884 9893 9917 9911 9876 9881 9856 9847 9843 9857 9839 9862 9826 + 9708 9779 9763 9780 9769 9769 9777 9800 9794 9784 9790 9764 9755 9765 9768 9752 9777 9735 + 9690 9758 9747 9750 9750 9752 9760 9784 9780 9758 9763 9739 9732 9734 9732 9728 9759 9711 + 9597 9661 9652 9658 9666 9668 9662 9685 9681 9652 9657 9632 9640 9629 9631 9631 9665 9610 + 9572 9636 9628 9634 9632 9632 9640 9661 9656 9641 9646 9623 9620 9631 9623 9624 9659 9598 + 9458 9521 9513 9518 9514 9519 9537 9547 9542 9529 9533 9522 9510 9511 9512 9518 9554 9485 + 9449 9511 9504 9509 9517 9512 9529 9538 9533 9494 9498 9485 9477 9474 9478 9489 9523 9448 + 9316 9380 9371 9376 9376 9381 9399 9406 9401 9394 9398 9389 9380 9387 9380 9396 9430 9347 + 9282 9348 9339 9343 9341 9350 9359 9374 9368 9349 9353 9335 9336 9338 9338 9357 9391 9301 + 9179 9245 9237 9242 9252 9249 9255 9285 9265 9236 9250 9218 9225 9226 9229 9248 9283 9186 + 9131 9198 9190 9196 9198 9205 9210 9239 9219 9208 9224 9192 9199 9201 9207 9228 9261 9158 + 9015 9084 9077 9082 9082 9093 9098 9126 9105 9094 9110 9078 9086 9088 9099 9120 9152 9042 + 8984 9054 9046 9052 9063 9062 9067 9088 9072 9046 9060 9032 9041 9043 9057 9078 9111 8989 + 8806 8877 8871 8877 8878 8882 8889 8903 8902 8903 8892 8872 8881 8883 8903 8923 8955 8828 + 8763 8836 8830 8836 8835 8838 8845 8859 8861 8858 8837 8818 8826 8832 8853 8874 8906 8769 + 8673 8746 8741 8746 8751 8743 8749 8764 8765 8751 8726 8705 8711 8724 8747 8767 8797 8650 + 8633 8707 8701 8706 8696 8697 8706 8719 8716 8725 8697 8677 8694 8703 8726 8747 8779 8621 + 10520 10245 10233 10231 10209 10213 10224 10243 10220 10229 10211 10185 10199 10226 10252 10278 10309 9059 + 13000 13000 13000>; + + PS_Config_Lmt_Open_Rawdata_N = < + 8578 8744 8725 8712 8696 8684 8679 8696 8708 8687 8699 8685 8675 8675 8678 8679 8688 8645 + 8528 8617 8600 8590 8577 8571 8568 8582 8588 8569 8577 8566 8559 8556 8556 8555 8561 8560 + 8562 8640 8624 8614 8604 8607 8598 8611 8613 8589 8597 8584 8578 8571 8572 8570 8575 8574 + 8513 8597 8579 8569 8562 8560 8557 8570 8571 8556 8564 8553 8546 8544 8537 8535 8541 8531 + 8525 8613 8589 8579 8576 8572 8571 8584 8584 8572 8579 8567 8561 8554 8553 8551 8563 8546 + 8489 8571 8546 8536 8535 8536 8532 8546 8544 8525 8531 8519 8513 8506 8505 8502 8515 8499 + 8497 8576 8550 8541 8543 8541 8540 8554 8553 8547 8553 8541 8535 8534 8527 8524 8537 8520 + 8448 8518 8499 8490 8493 8491 8491 8505 8504 8491 8496 8483 8478 8472 8471 8467 8476 8463 + 8464 8529 8519 8507 8509 8507 8507 8521 8520 8498 8504 8491 8485 8479 8478 8483 8482 8471 + 8407 8468 8458 8447 8449 8447 8448 8463 8461 8451 8456 8442 8437 8438 8431 8435 8434 8424 + 8409 8467 8457 8449 8448 8449 8451 8466 8464 8449 8454 8440 8435 8430 8429 8433 8433 8421 + 8360 8415 8402 8399 8405 8399 8401 8416 8414 8395 8399 8384 8380 8375 8375 8378 8379 8368 + 8356 8408 8390 8398 8395 8393 8397 8411 8409 8401 8405 8390 8385 8388 8386 8379 8386 8372 + 8297 8345 8330 8340 8332 8333 8337 8352 8349 8339 8343 8328 8322 8321 8327 8317 8327 8310 + 8304 8350 8338 8349 8347 8340 8346 8360 8357 8336 8339 8324 8319 8316 8325 8314 8328 8306 + 8237 8279 8269 8279 8273 8273 8277 8291 8288 8282 8285 8270 8265 8270 8272 8263 8278 8253 + 8227 8266 8260 8262 8262 8263 8268 8282 8280 8266 8270 8255 8251 8252 8251 8249 8267 8239 + 8172 8209 8204 8208 8212 8214 8210 8224 8221 8204 8207 8193 8197 8191 8192 8192 8212 8180 + 8157 8195 8190 8193 8192 8193 8197 8210 8207 8198 8201 8187 8186 8192 8187 8188 8208 8172 + 8090 8127 8123 8126 8123 8126 8137 8143 8140 8132 8134 8128 8121 8121 8122 8126 8147 8106 + 8085 8122 8117 8120 8125 8122 8132 8137 8135 8111 8114 8106 8101 8100 8102 8109 8129 8085 + 8007 8044 8039 8042 8042 8045 8056 8060 8057 8053 8055 8050 8044 8048 8044 8054 8074 8025 + 7987 8025 8020 8023 8022 8027 8032 8041 8038 8027 8028 8018 8019 8020 8020 8031 8051 7998 + 7926 7966 7961 7964 7970 7968 7971 7989 7977 7960 7968 7950 7954 7954 7956 7967 7988 7931 + 7898 7938 7933 7936 7937 7942 7945 7962 7950 7944 7953 7934 7938 7939 7943 7955 7975 7914 + 7830 7871 7867 7870 7869 7876 7879 7895 7883 7877 7886 7867 7872 7873 7880 7892 7911 7846 + 7812 7853 7849 7852 7858 7858 7861 7873 7864 7848 7857 7840 7846 7847 7855 7867 7886 7815 + 7708 7749 7746 7749 7750 7752 7756 7765 7764 7765 7758 7746 7751 7752 7764 7776 7795 7720 + 7682 7725 7722 7725 7724 7726 7730 7738 7740 7738 7726 7714 7719 7723 7735 7747 7766 7685 + 7629 7672 7669 7672 7675 7670 7674 7683 7683 7675 7660 7648 7652 7659 7673 7684 7702 7616 + 7606 7649 7646 7648 7643 7643 7649 7656 7655 7660 7643 7632 7642 7647 7660 7673 7692 7599 + 8714 8553 8545 8545 8531 8534 8540 8551 8538 8543 8533 8518 8525 8542 8556 8572 8590 7856 + 6500 6500 6500>; + + PS_Config_Lmt_FW_Rawdata_P = < + 1126 1131 1127 1122 1126 1127 1128 1123 1125 1130 1119 1128 1127 1117 1119 1130 1120 1127 + 1125 1129 1126 1118 1133 1125 1125 1123 1127 1122 1126 1127 1124 1126 1122 1119 1123 1124 + 1123 1123 1125 1125 1124 1123 1123 1122 1126 1128 1120 1123 1120 1125 1120 1123 1122 1121 + 1123 1121 1128 1123 1122 1128 1123 1124 1123 1121 1125 1122 1120 1124 1121 1124 1127 1124 + 1130 1126 1129 1127 1124 1122 1124 1128 1121 1126 1120 1129 1118 1119 1120 1137 1121 1122 + 1126 1124 1131 1117 1129 1122 1127 1120 1119 1125 1120 1123 1122 1121 1118 1126 1125 1127 + 1125 1122 1131 1125 1123 1126 1124 1118 1118 1126 1122 1124 1124 1129 1121 1124 1123 1120 + 1128 1128 1122 1129 1121 1128 1129 1119 1120 1118 1118 1123 1125 1122 1126 1121 1129 1126 + 1125 1126 1123 1118 1123 1117 1119 1118 1125 1122 1125 1127 1122 1126 1120 1123 1123 1123 + 1126 1129 1124 1128 1119 1127 1119 1126 1118 1125 1123 1121 1121 1122 1121 1127 1122 1130 + 1126 1123 1125 1127 1121 1121 1124 1128 1120 1119 1124 1118 1126 1121 1123 1123 1126 1119 + 1130 1129 1124 1132 1123 1123 1121 1127 1118 1125 1126 1122 1131 1120 1127 1127 1121 1128 + 1125 1128 1130 1128 1124 1129 1122 1123 1125 1124 1128 1122 1123 1120 1124 1123 1123 1122 + 1124 1129 1125 1129 1129 1127 1123 1123 1129 1124 1123 1121 1125 1121 1126 1123 1124 1125 + 1127 1128 1126 1122 1129 1123 1128 1130 1130 1123 1132 1125 1130 1128 1130 1119 1128 1123 + 1127 1127 1128 1127 1126 1126 1126 1128 1129 1125 1129 1128 1129 1126 1130 1122 1125 1120 + 1125 1126 1126 1129 1129 1127 1126 1126 1127 1131 1127 1132 1126 1125 1121 1131 1122 1121 + 1127 1129 1131 1121 1124 1130 1123 1131 1135 1122 1126 1133 1135 1133 1129 1130 1125 1124 + 1118 1122 1131 1120 1126 1125 1133 1134 1136 1133 1130 1128 1127 1128 1128 1132 1127 1126 + 1127 1126 1128 1132 1125 1129 1126 1128 1124 1127 1128 1131 1126 1129 1122 1128 1128 1126 + 1120 1125 1123 1126 1125 1124 1128 1128 1133 1129 1127 1127 1124 1129 1118 1128 1128 1121 + 1124 1126 1125 1127 1124 1128 1130 1125 1130 1127 1125 1127 1126 1123 1128 1123 1128 1130 + 1130 1125 1124 1122 1122 1126 1127 1129 1123 1127 1126 1132 1123 1126 1122 1128 1122 1120 + 1120 1124 1125 1125 1126 1127 1117 1127 1126 1126 1123 1127 1124 1125 1127 1123 1119 1119 + 1125 1132 1127 1135 1124 1128 1125 1116 1131 1126 1128 1122 1129 1121 1127 1127 1121 1125 + 1131 1128 1125 1127 1123 1128 1124 1118 1126 1126 1124 1128 1128 1129 1120 1124 1123 1126 + 1127 1122 1126 1123 1129 1123 1127 1129 1123 1122 1125 1119 1124 1128 1116 1128 1121 1121 + 1132 1127 1123 1126 1125 1129 1119 1120 1119 1125 1120 1128 1126 1125 1125 1129 1124 1126 + 1129 1125 1129 1132 1125 1126 1123 1122 1123 1127 1122 1126 1125 1130 1120 1130 1118 1128 + 1126 1133 1126 1130 1125 1128 1123 1123 1125 1128 1129 1122 1130 1128 1123 1125 1121 1123 + 1122 1124 1125 1126 1128 1126 1126 1126 1126 1124 1121 1124 1124 1124 1124 1121 1124 1120 + 1126 1119 1125 1128 1123 1128 1124 1128 1125 1128 1117 1125 1129 1127 1121 1126 1125 1126 + 2000 2000 2000>; + + PS_Config_Lmt_FW_Rawdata_N = < + 676 678 676 673 676 676 677 674 675 678 671 677 676 670 671 678 672 676 + 675 677 676 671 680 675 675 674 676 673 675 676 674 676 673 672 674 675 + 674 674 675 675 675 674 674 673 675 677 672 674 672 675 672 674 673 673 + 674 673 677 674 673 677 674 675 674 672 675 673 672 674 673 675 676 674 + 678 676 677 676 675 673 674 677 673 676 672 678 671 671 672 682 673 673 + 676 674 679 670 678 673 676 672 671 675 672 674 673 673 671 676 675 676 + 675 673 679 675 674 675 674 671 671 676 673 674 674 677 672 675 674 672 + 677 677 673 677 673 677 677 671 672 671 671 674 675 673 676 673 677 676 + 675 676 674 671 674 670 671 671 675 673 675 676 673 675 672 674 674 674 + 676 677 675 677 672 676 672 676 671 675 674 673 672 673 673 676 673 678 + 675 674 675 676 673 673 674 677 672 671 675 671 675 672 674 674 675 672 + 678 677 674 679 674 674 673 676 671 675 676 673 678 672 676 676 672 677 + 675 677 678 677 674 677 673 674 675 675 677 673 674 672 675 674 674 673 + 675 678 675 677 677 676 674 674 677 674 674 672 675 673 676 674 675 675 + 676 677 675 673 678 674 677 678 678 674 679 675 678 677 678 672 677 674 + 676 676 677 676 676 676 675 677 678 675 677 677 677 675 678 673 675 672 + 675 675 675 677 677 676 675 676 676 679 676 679 676 675 673 678 673 673 + 676 678 679 673 674 678 674 679 681 673 676 680 681 680 678 678 675 675 + 671 673 679 672 675 675 680 681 682 680 678 677 676 677 677 679 676 675 + 676 676 677 679 675 677 675 677 674 676 677 679 676 677 673 677 677 676 + 672 675 674 676 675 675 677 677 680 677 676 676 674 677 671 677 677 673 + 674 676 675 676 674 677 678 675 678 676 675 676 676 674 677 674 677 678 + 678 675 675 673 673 676 676 677 674 676 676 679 674 676 673 677 673 672 + 672 674 675 675 675 676 670 676 675 675 674 676 674 675 676 674 671 672 + 675 679 676 681 674 677 675 670 679 675 677 673 677 673 676 676 672 675 + 678 677 675 676 674 677 674 671 676 675 674 677 677 677 672 674 674 676 + 676 673 676 674 678 674 676 678 674 673 675 672 674 677 669 677 673 673 + 679 676 674 676 675 677 672 672 671 675 672 677 676 675 675 677 674 675 + 677 675 678 679 675 676 674 673 674 676 673 676 675 678 672 678 671 677 + 675 680 676 678 675 677 674 674 675 677 678 673 678 677 674 675 672 674 + 673 674 675 676 677 676 675 675 676 674 673 674 675 675 674 672 674 672 + 675 671 675 677 674 677 674 677 675 677 670 675 678 676 673 676 675 676 + 400 400 400>; + + PS_Config_Lmt_FW_CC_P = <112>; + PS_Config_Lmt_FW_CC_N = <72>; + PS_Config_Lmt_Key_FW_CC_P = <38>; + PS_Config_Lmt_Key_FW_CC_N = <9>; + + PS_Config_Lmt_FW_CC_I_P = <25>; + PS_Config_Lmt_FW_CC_I_N = <0>; + PS_Config_Lmt_FW_CC_Q_P = <25>; + PS_Config_Lmt_FW_CC_Q_N = <0>; + PS_Config_Lmt_Key_FW_CC_I_P = <25>; + PS_Config_Lmt_Key_FW_CC_I_N = <0>; + PS_Config_Lmt_Key_FW_CC_Q_P = <25>; + PS_Config_Lmt_Key_FW_CC_Q_N = <0>; + + PS_Config_Lmt_FW_Diff_P = <35>; + PS_Config_Lmt_FW_Diff_N = <(-35)>; + PS_Config_Lmt_Key_FW_Diff_P = <35>; + PS_Config_Lmt_Key_FW_Diff_N = <(-35)>; + + PS_Config_Diff_Test_Frame = <50>; + }; + }; + synaptics_dsx@70 { + compatible = "synaptics_lansi,dsx-i2c"; + reg = <0x70>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + avdd-supply = <&pm8953_l6>; + pinctrl-names = "pmx_ts_active", "pmx_ts_suspend"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&synaptic_int_suspend &synaptic_reset_suspend>; + synaptics,pwr-reg-name = "avdd"; + synaptics,bus-reg-name = "vdd"; + synaptics,ub-i2c-addr = <0x2c>; + synaptics,irq-gpio = <&tlmm 65 0x2008>; /* IRQF_ONESHOT | IRQF_TRIGGER_LOW */ + synaptics,rst-gpio = <&tlmm 64 0x0>; + synaptics,irq-on-state = <0>; + synaptics,power-delay-ms = <200>; + synaptics,reset-delay-ms = <200>; + synaptics,reset-on-state = <0>; + synaptics,reset-active-ms = <20>; + /* uncomment and update line below as appropriate if there are 0D buttons */ + /* synaptics,cap-button-codes = <102 158>; */ + synaptics,cap-button-codes = <139 172 158>; + /* uncomment and update lines below as appropriate if there are virtual buttons */ + /* synaptics,vir-button-codes = <102 100 900 100 60 158 300 900 100 60>; */ + /* synaptics,max-y-for-2d = <800>; */ + }; + }; + + i2c@78b6000 { /* BLSP1 QUP3 */ + aw2013@45 { + compatible = "awinic,aw2013_led"; + reg = <0x45>; + vdd-supply = <&pm8953_l10>; + vcc-supply = <&pm8953_l5>; + + aw2013,red { + aw2013,name = "red"; + aw2013,id = <0>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + + }; + + aw2023@46 { + compatible = "awinic,aw2023_led"; + reg = <0x46>; + vcc-supply = <&pm8953_l5>; + vdd-supply = <&pm8953_l10>; + + aw2023,red { + aw2023,name = "red"; + aw2023,id = <0>; + aw2023,imax = <2>; + aw2023,led-current = <3>; + aw2023,max-brightness = <255>; + aw2023,rise-time-ms = <6>; + aw2023,hold-time-ms = <0>; + aw2023,fall-time-ms = <6>; + aw2023,off-time-ms = <4>; + }; + }; + }; + + vdd_vreg: vdd_vreg { + compatible = "regulator-fixed"; + status = "ok"; + regulator-name = "vdd_vreg"; + }; +}; + +&wled { + qcom,cons-sync-write-delay-us = <1000>; +}; + +&spi_6 { + status = "ok"; + peel_ir@0 { + compatible = "peel_ir"; + reg = <0x0>; + spi-max-frequency = <19200000>; + vdd-supply = <&pm8953_l8>; //vdd + peel_ir,reg-id = "vdd"; + peel_ir,lr-gpio = <73>; + peel_ir,lr-gpio-valid = <0>; + peel_ir,spi-bpw = <32>; + peel_ir,spi-clk-speed = <960000>; + peel_ir,spi-mode = <0>; + peel_ir,peel-field = <2345>; + status = "ok"; + }; +}; + +&spmi_bus { + qcom,pm8953@0 { + qcom,leds@a100 { + status = "okay"; + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; + qcom,led_mpp_2 { + label = "mpp"; + linux,name = "button-backlight"; + linux,default-trigger = "none"; + qcom,default-state = "off"; + qcom,max-current = <10>; + qcom,current-setting = <5>; + qcom,id = <6>; + qcom,mode = "manual"; + qcom,source-sel = <1>; + qcom,mode-ctrl = <0x61>; + }; + }; + }; +}; + +/ { + qrd_batterydata: qcom,battery-data { + qcom,batt-id-range-pct = <5>; + #include "Vince-sunwoda-40Kohm-4000mah.dtsi" + #include "Vince-desay-24Kohm-4000mAh.dtsi" + #include "Vince-coslight-50Kohm-4000mah.dtsi" + }; +}; + +/* +&pm8953_typec { + ss-mux-supply = <&pm8953_l6>; + qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&typec_ssmux_config>; +}; +*/ + +&pmi8950_charger { + qcom,battery-data = <&qrd_batterydata>; + qcom,float-voltage-mv = <4400>; +// qcom,external-typec; +// qcom,typec-psy-name = "typec"; + qcom,thermal-mitigation = <3000 2500 2500 2500 1000 1000 0>; + status = "okay"; +}; + +&pmi8950_fg { + qcom,battery-data = <&qrd_batterydata>; + qcom,thermal-coefficients = [c8 86 c1 50 d3 37]; + qcom,cold-bat-decidegc = <0>; + qcom,cool-bat-decidegc = <150>; + qcom,warm-bat-decidegc = <450>; + qcom,hot-bat-decidegc = <550>; + qcom,bad-battery-detection-enable; + qcom,hold-soc-while-full; +}; + +&blsp1_uart0 { + status = "ok"; + pinctrl-names = "default"; + pinctrl-0 = <&uart_console_active>; +}; + +&sdhc_1 { + /* device core power supply */ + vdd-supply = <&pm8953_l8>; + qcom,vdd-voltage-level = <2900000 2900000>; + qcom,vdd-current-level = <200 570000>; + + /* device communication power supply */ + vdd-io-supply = <&pm8953_l5>; + qcom,vdd-io-always-on; + qcom,vdd-io-lpm-sup; + qcom,vdd-io-voltage-level = <1800000 1800000>; + qcom,vdd-io-current-level = <200 325000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>; + + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000 + 384000000>; + qcom,nonremovable; + qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v"; + + status = "ok"; +}; + +&sdhc_2 { + /* device core power supply */ + vdd-supply = <&pm8953_l11>; + qcom,vdd-voltage-level = <2950000 2950000>; + qcom,vdd-current-level = <15000 800000>; + + /* device communication power supply */ + vdd-io-supply = <&pm8953_l12>; + qcom,vdd-io-voltage-level = <1800000 2950000>; + qcom,vdd-io-current-level = <200 22000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + + #address-cells = <0>; + interrupt-parent = <&sdhc_2>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 125 0 + 1 &intc 0 221 0 + 2 &tlmm 133 0>; + interrupt-names = "hc_irq", "pwr_irq", "status_irq"; + cd-gpios = <&tlmm 133 0x0>; + + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 + 200000000>; + qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; + + status = "ok"; +}; + +&i2c_5 { /* BLSP2 QUP1 (NFC) */ + nq@28 { + compatible = "qcom,nq-nci"; + reg = <0x28>; + qcom,nq-irq = <&tlmm 17 0x00>; + qcom,nq-ven = <&tlmm 16 0x00>; + qcom,nq-firm = <&tlmm 62 0x00>; + qcom,nq-clkreq = <&pm8953_gpios 2 0x00>; + interrupt-parent = <&tlmm>; + qcom,clk-src = "BBCLK2"; + interrupts = <17 0>; + interrupt-names = "nfc_irq"; + pinctrl-names = "nfc_active", "nfc_suspend"; + pinctrl-0 = <&nfc_int_active &nfc_disable_active>; + pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>; + clocks = <&clock_gcc clk_bb_clk2_pin>; + clock-names = "ref_clk"; + }; +}; + +&pm8953_gpios { + /* GPIO 2 (NFC_CLK_REQ) */ + gpio@c100 { + qcom,mode = <0>; + qcom,output-type = <0>; + qcom,pull = <0>; + qcom,vin-sel = <2>; + qcom,out-strength = <3>; + qcom,src-sel = <0>; + qcom,master-en = <1>; + status = "okay"; + }; +}; + +&i2c_3 { + status = "ok"; +}; + + +&led_flash0{ + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; +}; + +&pm8953_vadc { + /delete-node/ chan@11; +}; + +&sdc2_cmd_on { + config { + drive-strength=<12>; + }; +}; + +&sdc2_data_on { + config { + drive-strength=<12>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-daisy.dts b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-daisy.dts new file mode 100644 index 0000000000000..809cc15cca852 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-daisy.dts @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "msm8953-daisy.dtsi" +#include "msm-pmi8950.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 daisy QRD SKU3"; + compatible = "qcom,msm8953-qrd-sku3", + "qcom,msm8953-qrd", "qcom,msm8953", "qcom,qrd"; + qcom,board-id= <0x1000b 0x09>; +}; + +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; + qcom,switch-source = <&pmi8950_switch>; + }; +}; + +#include "msm8953-qrd-sku3.dtsi" + +&usb3 { + vbus_dwc3-supply = <&smbcharger_charger_otg>; +}; + +&mdss_dsi1 { + lab-supply = <&lab_regulator>; + ibb-supply = <&ibb_regulator>; +}; + +&dsi_panel_pwr_supply { + qcom,panel-supply-entry@2 { + reg = <2>; + qcom,supply-name = "lab"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <10>; + qcom,supply-post-off-sleep = <2>; + }; + + qcom,panel-supply-entry@3 { + reg = <3>; + qcom,supply-name = "ibb"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + /*qcom,supply-post-on-sleep = <10>;*/ + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-e7.dts b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-e7.dts new file mode 100644 index 0000000000000..3e0acf20ea7bc --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-e7.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "msm8953-e7.dtsi" +#include "msm-pmi8950-e7.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. E7 QRD SKU3"; + compatible = "qcom,msm8953-qrd-sku3", + "qcom,msm8953-qrd", "qcom,msm8953", "qcom,qrd"; + qcom,board-id= <0x1000b 0x08>; +}; + +&soc { + led_flash0: qcom,camera-flash { + cell-index = <0>; + compatible = "qcom,camera-flash"; + qcom,flash-type = <1>; + qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>; + qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>; + qcom,switch-source = <&pmi8950_switch>; + }; +}; + +#include "msm8953-qrd-sku3-e7.dtsi" + +&usb3 { + vbus_dwc3-supply = <&smbcharger_charger_otg>; +}; + +&mdss_dsi1 { + lab-supply = <&lab_regulator>; + ibb-supply = <&ibb_regulator>; +}; + +&wled { + qcom,fs-curr-ua = <20000>; + qcom,led-strings-list = [00 01]; + qcom,ovp-mv = <29500>; +}; + +&dsi_panel_pwr_supply { + qcom,panel-supply-entry@2 { + reg = <2>; + qcom,supply-name = "lab"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <10>; + qcom,supply-post-off-sleep = <2>; + }; + + qcom,panel-supply-entry@3 { + reg = <3>; + qcom,supply-name = "ibb"; + qcom,supply-min-voltage = <4600000>; + qcom,supply-max-voltage = <6000000>; + qcom,supply-enable-load = <100000>; + qcom,supply-disable-load = <100>; + /*qcom,supply-post-on-sleep = <10>;*/ + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-e7.dtsi b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-e7.dtsi new file mode 100644 index 0000000000000..71da2b903fc6e --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3-e7.dtsi @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "msm8953-qrd-e7.dtsi" + +&spmi_bus { + qcom,pmi8950@3 { + labibb: qpnp-labibb-regulator { + ibb_regulator: qcom,ibb@dc00 { + /delete-property/ + qcom,qpnp-ibb-use-default-voltage; + qcom,qpnp-ibb-init-lcd-voltage = <5700000>; + }; + + lab_regulator: qcom,lab@de00 { + /delete-property/ + qcom,qpnp-ibb-use-default-voltage; + qcom,qpnp-ibb-init-lcd-voltage = <5700000>; + }; + }; + }; +}; + +#include "msm8953-mdss-panels.dtsi" + +&tlmm { + pmx_mdss { + mdss_dsi_active: mdss_dsi_active { + mux { + pins = "gpio61"; + }; + config { + pins = "gpio61"; + }; + }; + mdss_dsi_suspend: mdss_dsi_suspend { + mux { + pins = "gpio61"; + }; + config { + pins = "gpio61"; + }; + }; + }; +}; + +&dsi_r69006_1080p_cmd { + qcom,esd-check-enabled; +}; + +&mdss_mdp { + qcom,mdss-pref-prim-intf = "dsi"; +}; + +&mdss_dsi { + hw-config = "single_dsi"; +}; + +&mdss_dsi0 { + lab-supply = <&lab_regulator>; + ibb-supply = <&ibb_regulator>; + /delete-property/ vdd-supply; + + //qcom,dsi-pref-prim-pan = <&dsi_r69006_1080p_cmd>; + qcom,dsi-pref-prim-pan = <&dsi_td4310_fhdplus_e7_vid>; + pinctrl-names = "mdss_default", "mdss_sleep"; + pinctrl-0 = <&mdss_dsi_active &mdss_te_active>; + pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>; + qcom,platform-te-gpio = <&tlmm 24 0>; + qcom,platform-reset-gpio = <&tlmm 61 0>; +}; + +&mdss_dsi1 { + status = "disabled"; +}; + +&labibb { + status = "ok"; + qpnp,qpnp-labibb-mode = "lcd"; +}; + +&dsi_otm1911_fhd_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; + +}; + +&dsi_ili7807_fhdplus_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; + +}; + +/*add begin for E7 display*/ +&dsi_td4310_fhdplus_e7_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_td4310_fhdplus_e7_g55_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + + +&dsi_td4310_ebbg_fhdplus_e7_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_nt36672_tianma_fhdplus_e7_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_nt36672_csot_fhdplus_e7_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; +/*add end for E7 display*/ + +&dsi_otm1911_fhdplus_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; + +}; + +&dsi_r69006_1080p_cmd { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_r69006_1080p_video { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&int_codec { + status = "ok"; +}; + +&pm8953_diangu_dig { + status = "ok"; +}; + +&pm8953_diangu_analog { + status = "ok"; +}; + +&ext_codec { + status = "disabled"; + qcom,model = "msm8953-sku3-tasha-snd-card"; + + qcom,audio-routing = + "AIF4 VI", "MCLK", + "RX_BIAS", "MCLK", + "DMIC0", "MIC BIAS1", + "MIC BIAS1", "Digital Mic0", + "AMIC2", "MIC BIAS2", + "MIC BIAS2", "Headset Mic", + "DMIC2", "MIC BIAS3", + "MIC BIAS3", "Digital Mic2", + "MIC BIAS1", "MICBIAS_REGULATOR", + "MIC BIAS2", "MICBIAS_REGULATOR", + "MIC BIAS3", "MICBIAS_REGULATOR", + "SpkrLeft IN", "SPK1 OUT"; + + qcom,cdc-us-euro-gpios; + + qcom,msm-mbhc-hphl-swh = <1>; + + qcom,wsa-max-devs = <1>; + qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_213>; + qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft"; +}; + +&slim_msm { + status = "disabled"; +}; + +&dai_slim { + status = "disabled"; +}; + +&wcd9xxx_intc { + status = "disabled"; +}; + +&clock_audio { + status = "disabled"; +}; + +&wcd9335 { + status = "disabled"; +}; + +&wcd_rst_gpio { + status = "disabled"; +}; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dts b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dts index b6acd5abbae7f..52676d51188ff 100644 --- a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dts +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,7 +21,7 @@ model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 QRD SKU3"; compatible = "qcom,msm8953-qrd-sku3", "qcom,msm8953-qrd", "qcom,msm8953", "qcom,qrd"; - qcom,board-id= <0x2000b 0>; + qcom,board-id= <0x1000b 0>; }; &soc { @@ -53,6 +54,8 @@ qcom,supply-max-voltage = <6000000>; qcom,supply-enable-load = <100000>; qcom,supply-disable-load = <100>; + qcom,supply-post-on-sleep = <10>; + qcom,supply-post-off-sleep = <2>; }; qcom,panel-supply-entry@3 { @@ -62,6 +65,6 @@ qcom,supply-max-voltage = <6000000>; qcom,supply-enable-load = <100000>; qcom,supply-disable-load = <100>; - qcom,supply-post-on-sleep = <10>; + /*qcom,supply-post-on-sleep = <10>;*/ }; }; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dtsi b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dtsi index 871e7f2867034..dec9afa178b80 100644 --- a/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-qrd-sku3.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -71,7 +72,8 @@ ibb-supply = <&ibb_regulator>; /delete-property/ vdd-supply; - qcom,dsi-pref-prim-pan = <&dsi_r69006_1080p_cmd>; + //qcom,dsi-pref-prim-pan = <&dsi_r69006_1080p_cmd>; + qcom,dsi-pref-prim-pan = <&dsi_otm1911_fhd_vid>; pinctrl-names = "mdss_default", "mdss_sleep"; pinctrl-0 = <&mdss_dsi_active &mdss_te_active>; pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>; @@ -88,6 +90,30 @@ qpnp,qpnp-labibb-mode = "lcd"; }; + +&dsi_otm1911_fhd_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; + +}; + +&dsi_ili7807_fhdplus_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; + +}; + +&dsi_otm1911_fhdplus_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; + +}; + +&dsi_hx8399c_fhdplus_vid { + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; + //qcom,esd-check-enabled; +}; + &dsi_r69006_1080p_cmd { qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; @@ -97,19 +123,19 @@ }; &int_codec { - status = "disabled"; + status = "ok"; }; &pm8953_diangu_dig { - status = "disabled"; + status = "ok"; }; &pm8953_diangu_analog { - status = "disabled"; + status = "ok"; }; &ext_codec { - status = "ok"; + status = "disabled"; qcom,model = "msm8953-sku3-tasha-snd-card"; qcom,audio-routing = @@ -136,25 +162,25 @@ }; &slim_msm { - status = "ok"; + status = "disabled"; }; &dai_slim { - status = "ok"; + status = "disabled"; }; &wcd9xxx_intc { - status = "ok"; + status = "disabled"; }; &clock_audio { - status = "ok"; + status = "disabled"; }; &wcd9335 { - status = "ok"; + status = "disabled"; }; &wcd_rst_gpio { - status = "ok"; + status = "disabled"; }; diff --git a/arch/arm/boot/dts/qcom/msm8953-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8953-qrd.dtsi index c081a1c30822d..ee2e188947d26 100644 --- a/arch/arm/boot/dts/qcom/msm8953-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-qrd.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -31,6 +32,55 @@ }; }; + goodix_fp { + compatible = "goodix,fingerprint"; + spi-max-frequency = <1000000>; + input-device-name = "gf3208"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + + fp-gpio-reset = <&tlmm 140 0>; + fp-gpio-irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "goodixfp_spi_active", + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active"; + + pinctrl-0 = <&goodix_spi_active>; + pinctrl-1 = <&goodix_reset_reset>; + pinctrl-2 = <&goodix_reset_active>; + pinctrl-3 = <&goodix_irq_active>; + }; + + fpc1020 { + compatible = "fpc,fpc1020"; + spi-max-frequency = <1000000>; + input-device-name = "fpc1020"; + interrupt-parent = <&tlmm>; + interrupts = <9 0x0>; + fpc,gpio_rst = <&tlmm 140 0>; + fpc,gpio_irq = <&tlmm 48 0>; + + clock-names = "iface_clk", "core_clk"; + clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, + <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>; + + pinctrl-names = "fpc1020_spi_active", + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active"; + + pinctrl-0 = <&fpc_spi_active>; + pinctrl-1 = <&fpc_reset_reset>; + pinctrl-2 = <&fpc_reset_active>; + pinctrl-3 = <&fpc_irq_active>; + }; + i2c@78b7000 { /* BLSP1 QUP3 */ status = "okay"; synaptics@4b { @@ -58,6 +108,131 @@ clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, <&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>; }; + gt9xx@5d { + compatible = "goodix,gt9xx"; + reg = <0x5d>; + status = "okay"; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + pinctrl-names = "default", "int-output-low","int-output-high", "int-input"; + pinctrl-0 = <&ts_int_default>; + pinctrl-1 = <&ts_int_output_low>; + pinctrl-2 = <&ts_int_output_high>; + pinctrl-3 = <&ts_int_input>; + + reset-gpios = <&tlmm 64 0x0>; + irq-gpios = <&tlmm 65 0x2008>; + irq-flags = <1>; + + vdd_ana-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + + touchscreen-max-id = <11>; + touchscreen-size-x = <1080>; + touchscreen-size-y = <2280>; + touchscreen-max-w = <512>; + touchscreen-max-p = <512>; + + goodix,slide-wakeup = <1>; + goodix,type-a-report = <0>; + goodix,driver-send-cfg = <1>; + goodix,resume-in-workqueue = <0>; + goodix,int-sync = <1>; + goodix,swap-x2y = <0>; + goodix,esd-protect = <1>; + goodix,auto-update-cfg = <1>; + goodix,auto-update = <1>; + goodix,power-off-sleep = <0>; + goodix,pen-suppress-finger = <0>; + goodix,charger-cmd = <1>; + goodix,cfg-group0 = [55 38 04 E8 08 0A 7C 10 21 2A 32 0D 5A 32 1E 55 00 00 60 22 22 22 04 30 00 00 2E 87 27 EE 46 48 F1 08 F1 08 00 C2 33 91 0A 00 00 00 00 A3 50 0C 0F 5A 02 2D 50 84 E0 A7 19 28 23 04 B2 2F 00 9F 35 00 95 3C 00 8C 42 00 84 4A 00 82 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 04 60 28 00 00 00 00 00 01 46 00 00 00 00 32 16 17 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 18 19 1A 1B 00 01 02 03 04 05 06 07 08 09 FF FF 08 06 05 04 0A 0C 0E 1E 1F 20 22 24 29 2A FF FF FF 00 00 00 00 00 00 00 00 00 2D 28 37 0A 1E 32 F0 00 00 44 66 32 0A 4A 84 5B 00 00 00 00 00 00 2A 5A 00 00 00 00 00 32 0C 28 00 55 00 1E 88 20 8C 47 33 36 0A 6F 66 1C 00 14 14 0C 02 44 44 58 9A 4C 83 85 BC 01]; + }; + focaltech@38 { + compatible = "focaltech,5446"; + reg = <0x38>; + interrupt-parent = <&tlmm>; + interrupts = <65 0x2>; + vdd-supply = <&pm8953_l10>; + vcc_i2c-supply = <&pm8953_l6>; + /* pins used by touchscreen */ + pinctrl-names = "pmx_ts_active","pmx_ts_suspend", + "pmx_ts_release"; + pinctrl-0 = <&ts_int_active &ts_reset_active>; + pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; + pinctrl-2 = <&ts_release>; + focaltech,name = "ft5435"; + focaltech,family-id = <0x54>; + focaltech,reset-gpio = <&tlmm 64 0x0>; + focaltech,irq-gpio = <&tlmm 65 0x2002>; + focaltech,display-coords = <0 0 1080 2280>; + focaltech,panel-coords = <0 0 1080 2280>; + focaltech,no-force-update; + focaltech,i2c-pull-up; + focaltech,group-id = <1>; + focaltech,hard-reset-delay-ms = <200>; + focaltech,soft-reset-delay-ms = <200>; + focaltech,num-max-touches = <10>; + focaltech,fw-delay-aa-ms = <2>; + focaltech,fw-delay-55-ms = <2>; + focaltech,fw-upgrade-id1 = <0x54>; + focaltech,fw-upgrade-id2 = <0x2c>; + focaltech,fw-delay-readid-ms = <10>; + focaltech,fw-delay-era-flsh-ms = <2000>; + focaltech,fw-auto-cal; + focaltech,fw-vkey-support; + focaltech,resume-in-workqueue; + focaltech,num-virtual-key = <3>; + focal,virtual_key_1 = <172 500 2040>;/*home*/ + focal,virtual_key_2 = <139 200 2040>;/*menu*/ + focal,virtual_key_3 = <158 800 2040>;/*back*/ + }; + vituralsar@33{ + compatible = "virtualsar,sar"; + reg = <0x33>; + interrupt-parent = <&tlmm>; + interrupts = <130 0x02>; + vituralsar,irq-gpio = <&tlmm 130 0x2008>; + }; + }; + + i2c@78b6000 { /* BLSP1 QUP3 */ + aw2013@45 { + compatible = "awinic,aw2013_led"; + reg = <0x45>; + vdd-supply = <&pm8953_l10>; + vcc-supply = <&pm8953_l5>; + + aw2013,red { + aw2013,name = "red"; + aw2013,id = <0>; + aw2013,max-brightness = <150>; + aw2013,max-current = <1>; + aw2013,rise-time-ms = <3>; + aw2013,hold-time-ms = <1>; + aw2013,fall-time-ms = <3>; + aw2013,off-time-ms = <3>; + }; + + }; + + aw2023@46 { + compatible = "awinic,aw2023_led"; + reg = <0x46>; + vcc-supply = <&pm8953_l5>; + vdd-supply = <&pm8953_l10>; + + aw2023,red { + aw2023,name = "red"; + aw2023,id = <0>; + aw2023,imax = <2>; + aw2023,led-current = <15>; + aw2023,max-brightness = <150>; + aw2023,rise-time-ms = <6>; + aw2023,hold-time-ms = <0>; + aw2023,fall-time-ms = <6>; + aw2023,off-time-ms = <4>; + }; + }; }; vdd_vreg: vdd_vreg { @@ -71,21 +246,42 @@ qcom,cons-sync-write-delay-us = <1000>; }; +&spi_6 { + status = "ok"; + peel_ir@0 { + compatible = "peel_ir"; + reg = <0x0>; + spi-max-frequency = <19200000>; + vdd-supply = <&pm8953_l8>; //vdd + peel_ir,reg-id = "vdd"; + peel_ir,lr-gpio = <73>; + peel_ir,lr-gpio-valid = <0>; + peel_ir,spi-bpw = <32>; + peel_ir,spi-clk-speed = <960000>; + peel_ir,spi-mode = <0>; + peel_ir,peel-field = <2345>; + status = "ok"; + }; +}; + &spmi_bus { - qcom,pmi8950@2 { + qcom,pm8953@0 { qcom,leds@a100 { status = "okay"; + compatible = "qcom,leds-qpnp"; + reg = <0xa100 0x100>; + label = "mpp"; qcom,led_mpp_2 { label = "mpp"; - linux,name = "green"; + linux,name = "button-backlight"; linux,default-trigger = "none"; qcom,default-state = "off"; - qcom,max-current = <40>; + qcom,max-current = <10>; qcom,current-setting = <5>; qcom,id = <6>; qcom,mode = "manual"; qcom,source-sel = <1>; - qcom,mode-ctrl = <0x60>; + qcom,mode-ctrl = <0x61>; }; }; }; @@ -93,35 +289,39 @@ / { qrd_batterydata: qcom,battery-data { - qcom,batt-id-range-pct = <15>; - #include "batterydata-qrd-sku1-4v4-2800mah.dtsi" + qcom,batt-id-range-pct = <10>; + #include "Sakura-FMT-4v4-4000mah-41kohm.dtsi" + #include "Sakura-GY-4000mah-51kohm.dtsi" + #include "Sakura-XWD-4000mah-78kohm.dtsi" + #include "Sakura-Default-4000mah-41kohm.dtsi" }; }; +/* &pm8953_typec { ss-mux-supply = <&pm8953_l6>; qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&typec_ssmux_config>; }; +*/ &pmi8950_charger { qcom,battery-data = <&qrd_batterydata>; qcom,float-voltage-mv = <4400>; - qcom,chg-led-sw-controls; - qcom,chg-led-support; - qcom,external-typec; - qcom,typec-psy-name = "typec"; - qcom,thermal-mitigation = <3000 2500 2000 1500 1000 500 0>; +// qcom,external-typec; +// qcom,typec-psy-name = "typec"; + qcom,thermal-mitigation = <3000 2500 2000 2000 1000 1000 0>; status = "okay"; }; &pmi8950_fg { qcom,battery-data = <&qrd_batterydata>; - qcom,cold-bat-decidegc = <(-100)>; - qcom,cool-bat-decidegc = <0>; - qcom,warm-bat-decidegc = <550>; - qcom,hot-bat-decidegc = <550>; + qcom,thermal-coefficients = [c8 86 c1 50 d3 37]; + qcom,cold-bat-decidegc = <0>; + qcom,cool-bat-decidegc = <150>; + qcom,warm-bat-decidegc = <450>; + qcom,hot-bat-decidegc = <600>; qcom,bad-battery-detection-enable; qcom,hold-soc-while-full; }; @@ -181,7 +381,7 @@ 1 &intc 0 221 0 2 &tlmm 133 0>; interrupt-names = "hc_irq", "pwr_irq", "status_irq"; - cd-gpios = <&tlmm 133 0x1>; + cd-gpios = <&tlmm 133 0x0>; qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>; diff --git a/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi b/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi index d10d42bc5f43a..74215eb8e9ef5 100644 --- a/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953-regulator.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -138,9 +139,9 @@ rpm-regulator-ldoa2 { status = "okay"; pm8953_l2: regulator-l2 { - regulator-min-microvolt = <975000>; + regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1225000>; - qcom,init-voltage = <975000>; + qcom,init-voltage = <1200000>; status = "okay"; }; }; @@ -267,9 +268,9 @@ rpm-regulator-ldoa17 { status = "okay"; pm8953_l17: regulator-l17 { - regulator-min-microvolt = <2850000>; + regulator-min-microvolt = <2750000>; regulator-max-microvolt = <2850000>; - qcom,init-voltage = <2850000>; + qcom,init-voltage = <2750000>; status = "okay"; }; }; @@ -278,7 +279,7 @@ status = "okay"; pm8953_l19: regulator-l19 { regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1350000>; + regulator-max-microvolt = <1380000>; qcom,init-voltage = <1200000>; status = "okay"; }; @@ -288,7 +289,7 @@ status = "okay"; pm8953_l22: regulator-l22 { regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2850000>; + regulator-max-microvolt = <2800000>; qcom,init-voltage = <2800000>; status = "okay"; }; @@ -297,9 +298,9 @@ rpm-regulator-ldoa23 { status = "okay"; pm8953_l23: regulator-l23 { - regulator-min-microvolt = <975000>; + regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1225000>; - qcom,init-voltage = <975000>; + qcom,init-voltage = <1200000>; status = "okay"; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8953.dtsi b/arch/arm/boot/dts/qcom/msm8953.dtsi index 4aec5236ed057..30622ea0043b5 100644 --- a/arch/arm/boot/dts/qcom/msm8953.dtsi +++ b/arch/arm/boot/dts/qcom/msm8953.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -39,6 +40,14 @@ fsmgr_flags = "wait,verify"; status = "ok"; }; + system { + compatible = "android,system"; + dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system"; + type = "ext4"; + mnt_flags = "ro,barrier=1,discard"; + fsmgr_flags = "wait,verify"; + status = "ok"; + }; }; }; }; @@ -51,7 +60,7 @@ other_ext_mem: other_ext_region@0 { compatible = "removed-dma-pool"; no-map; - reg = <0x0 0x85b00000 0x0 0xd00000>; + reg = <0x0 0x84A00000 0x0 0x1E00000>; }; modem_mem: modem_region@0 { @@ -63,13 +72,13 @@ adsp_fw_mem: adsp_fw_region@0 { compatible = "removed-dma-pool"; no-map; - reg = <0x0 0x8d600000 0x0 0x1100000>; + reg = <0x0 0x8d600000 0x0 0x1200000>; }; wcnss_fw_mem: wcnss_fw_region@0 { compatible = "removed-dma-pool"; no-map; - reg = <0x0 0x8e700000 0x0 0x700000>; + reg = <0x0 0x8e800000 0x0 0x700000>; }; venus_mem: venus_region@0 { @@ -117,6 +126,11 @@ alignment = <0 0x400000>; size = <0 0x800000>; }; + pstore_reserve_mem: pstore_reserve_mem_region@0 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x9ff00000 0x0 0x00100000>; + }; }; aliases { @@ -138,6 +152,7 @@ i2c3 = &i2c_3; i2c5 = &i2c_5; spi3 = &spi_3; + spi6 = &spi_6; }; soc: soc { }; @@ -733,6 +748,31 @@ qcom,master-id = <86>; }; + spi_6: spi@7af6000 { /* BLSP2 QUP2 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "spi_physical", "spi_bam_physical"; + reg = <0x7af6000 0x600>, + <0x7ac4000 0x1f000>; + interrupt-names = "spi_irq", "spi_bam_irq"; + interrupts = <0 300 0>, <0 239 0>; + spi-max-frequency = <50000000>; + pinctrl-names = "spi_default", "spi_sleep"; + pinctrl-0 = <&spi6_default &spi6_cs0_active>; + pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>; + clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>, + <&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>; + clock-names = "iface_clk", "core_clk"; + qcom,infinite-mode = <0>; + qcom,use-bam; + qcom,use-pinctrl; + qcom,ver-reg-exists; + qcom,bam-consumer-pipe-index = <6>; + qcom,bam-producer-pipe-index = <7>; + qcom,master-id = <84>; + }; + i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */ compatible = "qcom,i2c-msm-v2"; #address-cells = <1>; @@ -1268,6 +1308,12 @@ reg-names = "fuse-base"; }; + sn_fuse: snfuse@0xa4128 { + compatible = "qcom,sn-fuse"; + reg = <0xa4128 0x4>; + reg-names = "sn-base"; + }; + jtag_mm0: jtagmm@619c000 { compatible = "qcom,jtagv8-mm"; reg = <0x619c000 0x1000>, @@ -1540,7 +1586,7 @@ qcom,iris-vdddig-supply = <&pm8953_l5>; qcom,iris-vddxo-voltage-level = <1800000 0 1800000>; - qcom,iris-vddrfa-voltage-level = <1300000 0 1300000>; + qcom,iris-vddrfa-voltage-level = <1380000 0 1380000>; qcom,iris-vddpa-voltage-level = <3300000 0 3300000>; qcom,iris-vdddig-voltage-level = <1800000 0 1800000>; @@ -1662,9 +1708,9 @@ qcom,ce-opp-freq = <100000000>; }; - qcom_seecom: qseecom@85b00000 { + qcom_seecom: qseecom@84A00000 { compatible = "qcom,qseecom"; - reg = <0x85b00000 0x800000>; + reg = <0x84A00000 0x1900000>; reg-names = "secapp-region"; qcom,hlos-num-ce-hw-instances = <1>; qcom,hlos-ce-hw-instance = <0>; @@ -2081,6 +2127,7 @@ qcom,msm-bus,name = "usb3"; qcom,msm-bus,num-cases = <3>; qcom,msm-bus,num-paths = <1>; + qcom,detect-dpdm-floating; qcom,msm-bus,vectors-KBps = <61 512 0 0>, <61 512 240000 800000>, @@ -2195,9 +2242,9 @@ qcom,vdd-voltage-level = <0 925000 925000>; qcom,qusb-phy-init-seq = <0xF8 0x80 - 0xB3 0x84 + 0x93 0x84 0x83 0x88 - 0xC0 0x8C + 0xC7 0x8C 0x14 0x9C 0x30 0x08 0x79 0x0C diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b82f23b239743..3a3d85552fdbf 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1140,4 +1140,11 @@ endif source "lib/Kconfig" +config BOOT_INFO + bool "Boot information from bootloader" + default y + help + On embedded linux device, we try to collect more information from + bootloader to kernel. eg. powerup reason. + source "arch/arm64/mm/Kconfig" diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 9ce661f6697d7..34fc22e066ea5 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -51,7 +51,7 @@ CONFIG_SCHED_MC=y CONFIG_PREEMPT=y CONFIG_CLEANCACHE=y CONFIG_CMA=y -CONFIG_CMA_DEBUGFS=y +#CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y CONFIG_ZCACHE=y CONFIG_PROCESS_RECLAIM=y @@ -69,7 +69,7 @@ CONFIG_PM_WAKELOCKS=y CONFIG_PM_WAKELOCKS_LIMIT=0 # CONFIG_PM_WAKELOCKS_GC is not set CONFIG_PM_RUNTIME=y -CONFIG_PM_DEBUG=y +#CONFIG_PM_DEBUG=y CONFIG_SUSPEND_TIME=y CONFIG_CPU_IDLE=y CONFIG_CPU_FREQ=y @@ -195,7 +195,7 @@ CONFIG_IP6_NF_RAW=y CONFIG_BRIDGE_NF_EBTABLES=y CONFIG_BRIDGE_EBT_BROUTE=y CONFIG_L2TP=y -CONFIG_L2TP_DEBUGFS=y +#CONFIG_L2TP_DEBUGFS=y CONFIG_L2TP_V3=y CONFIG_L2TP_IP=y CONFIG_L2TP_ETH=y @@ -216,7 +216,7 @@ CONFIG_NET_EMATCH_TEXT=y CONFIG_NET_CLS_ACT=y CONFIG_RMNET_DATA=y CONFIG_RMNET_DATA_FC=y -CONFIG_RMNET_DATA_DEBUG_PKT=y +#CONFIG_RMNET_DATA_DEBUG_PKT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_BT_RFCOMM=y @@ -235,7 +235,7 @@ CONFIG_IPC_ROUTER_SECURITY=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y CONFIG_DMA_CMA=y CONFIG_ZRAM=y -CONFIG_BLK_DEV_LOOP=y +#CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_UID_STAT=y @@ -315,7 +315,7 @@ CONFIG_INPUT_GPIO=y # CONFIG_LEGACY_PTYS is not set # CONFIG_DEVMEM is not set # CONFIG_DEVKMEM is not set -CONFIG_SERIAL_MSM_HS=y +#CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_SMD=y CONFIG_DIAG_CHAR=y CONFIG_HW_RANDOM=y @@ -427,7 +427,7 @@ CONFIG_MSM_DBA_ADV7533=y CONFIG_FB_MSM_MDSS=y CONFIG_FB_MSM_MDSS_WRITEBACK=y CONFIG_FB_MSM_MDSS_HDMI_PANEL=y -CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +#CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_SOUND=y CONFIG_SND=y @@ -467,7 +467,7 @@ CONFIG_NOP_USB_XCEIV=y CONFIG_USB_MSM_HSPHY=y CONFIG_USB_MSM_SSPHY_QMP=y CONFIG_MSM_QUSB_PHY=y -CONFIG_DUAL_ROLE_USB_INTF=y +# CONFIG_DUAL_ROLE_USB_INTF is not set CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_DEBUG_FS=y @@ -549,7 +549,7 @@ CONFIG_MSM_SCM_XPU=y CONFIG_MSM_MPM_OF=y CONFIG_MSM_SMEM=y CONFIG_MSM_SMD=y -CONFIG_MSM_SMD_DEBUG=y +#CONFIG_MSM_SMD_DEBUG=y CONFIG_MSM_GLINK=y CONFIG_MSM_GLINK_LOOPBACK_SERVER=y CONFIG_MSM_GLINK_SMD_XPRT=y @@ -581,12 +581,12 @@ CONFIG_PWM=y CONFIG_PWM_QPNP=y CONFIG_ARM_GIC_PANIC_HANDLER=y CONFIG_ARM_GIC_V3_ACL=y -CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_EVENT=y -CONFIG_CORESIGHT_TMC=y -CONFIG_CORESIGHT_FUNNEL=y -CONFIG_CORESIGHT_REPLICATOR=y -CONFIG_CORESIGHT_STM=y +#CONFIG_CORESIGHT=y +#CONFIG_CORESIGHT_EVENT=y +#CONFIG_CORESIGHT_TMC=y +#CONFIG_CORESIGHT_FUNNEL=y +#CONFIG_CORESIGHT_REPLICATOR=y +#CONFIG_CORESIGHT_STM=y CONFIG_SENSORS_SSC=y CONFIG_MSM_TZ_LOG=y CONFIG_EXT4_FS=y @@ -613,8 +613,8 @@ CONFIG_SCHED_STACK_END_CHECK=y CONFIG_TIMER_STATS=y CONFIG_IPC_LOGGING=y CONFIG_CPU_FREQ_SWITCH_PROFILER=y -CONFIG_DEBUG_SET_MODULE_RONX=y -CONFIG_DEBUG_RODATA=y +#CONFIG_DEBUG_SET_MODULE_RONX=y +#CONFIG_DEBUG_RODATA=y CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index e1b3bcf2b3f11..562d9fc805c49 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -476,7 +476,7 @@ CONFIG_NOP_USB_XCEIV=y CONFIG_USB_MSM_HSPHY=y CONFIG_USB_MSM_SSPHY_QMP=y CONFIG_MSM_QUSB_PHY=y -CONFIG_DUAL_ROLE_USB_INTF=y +# CONFIG_DUAL_ROLE_USB_INTF is not set CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_DEBUG_FS=y diff --git a/arch/arm64/configs/sakura-india-perf_defconfig b/arch/arm64/configs/sakura-india-perf_defconfig new file mode 100644 index 0000000000000..324dbd6ecc5c5 --- /dev/null +++ b/arch/arm64/configs/sakura-india-perf_defconfig @@ -0,0 +1,682 @@ +CONFIG_LOCALVERSION="-perf" +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_SCHED_HMP=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_ARCH_MSM=y +CONFIG_ARCH_MSM8916=y +CONFIG_ARCH_MSM8940=y +CONFIG_ARCH_MSM8953=y +CONFIG_ARCH_SDM450=y +CONFIG_ARCH_MSM8937=y +CONFIG_ARCH_MSMCOBALT=y +CONFIG_PCI_MSM=y +CONFIG_SCHED_MC=y +CONFIG_PREEMPT=y +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_ZCACHE=y +CONFIG_PROCESS_RECLAIM=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM_DEBUG=y +CONFIG_SUSPEND_TIME=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_FREQ=y +CONFIG_SCHED_FREQ_INPUT=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_SIT=y +CONFIG_NET_IPVTI=y +CONFIG_NET_UDP_TUNNEL=y +CONFIG_INET_UDP_DIAG=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NATTYPE_MODULE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_SOCKEV_NLMCAST=y +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_MSM_BT_POWER=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_IPC_ROUTER=y +CONFIG_IPC_ROUTER_SECURITY=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_DMA_CMA=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_UID_STAT=y +CONFIG_QSEECOM=y +CONFIG_HDCP_QSEECOM=y +CONFIG_UID_SYS_STATS=y +# CONFIG_USB_EXT_TYPE_C_PERICOM is not set +CONFIG_MSM_ULTRASOUND=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +CONFIG_RNDIS_IPA=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y +CONFIG_WCNSS_CORE=y +CONFIG_WCNSS_CORE_PRONTO=y +CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CNSS_CRYPTO=y +CONFIG_ATH_CARDS=y +CONFIG_WIL6210=m +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_KEYRESET=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y +#CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_TOUCHSCREEN_GEN_VKEYS=y +CONFIG_TOUCHSCREEN_FT5X06=y +CONFIG_TOUCHSCREEN_MAXIM_STI=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +CONFIG_INPUT_FINGERPRINT=y +CONFIG_FINGERPRINT_GOODIX_GF3208=y +CONFIG_FINGERPRINT_FPC1020=y +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_MSM_HS=y +CONFIG_SERIAL_MSM_SMD=y +CONFIG_DIAG_CHAR=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +# CONFIG_DEVPORT is not set +CONFIG_MSM_SMD_PKT=y +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SLIMBUS=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SOUNDWIRE=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=m +CONFIG_PINCTRL_MSM8952=y +CONFIG_PINCTRL_MSM8937=y +CONFIG_PINCTRL_MSMCOBALT=y +CONFIG_PINCTRL_MSM8940=y +CONFIG_PINCTRL_MSM8953=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_QPNP_PIN=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_SMB135X_CHARGER=y +CONFIG_QPNP_SMBCHARGER=y +CONFIG_QPNP_FG=y +CONFIG_BATTERY_BCL=y +# CONFIG_QPNP_TYPEC is not set +CONFIG_MSM_BCL_CTL=y +CONFIG_MSM_BCL_PERIPHERAL_CTL=y +CONFIG_POWER_RESET_MSM=y +CONFIG_MSM_DLOAD_MODE=y +CONFIG_MSM_PM=y +CONFIG_APSS_CORE_EA=y +CONFIG_MSM_APM=y +CONFIG_SENSORS_EPM_ADC=y +CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y +CONFIG_SENSORS_QPNP_ADC_CURRENT=y +CONFIG_THERMAL=y +CONFIG_THERMAL_TSENS8974=y +CONFIG_LIMITS_MONITOR=y +CONFIG_LIMITS_LITE_HW=y +CONFIG_THERMAL_MONITOR=y +CONFIG_THERMAL_QPNP=y +CONFIG_THERMAL_QPNP_ADC_TM=y +CONFIG_WCD9335_CODEC=y +CONFIG_SND_SOC_MSM8X16_WCD=y +CONFIG_SND_SOC_WCD_MBHC=y +CONFIG_MBHC_UART=n +CONFIG_SND_SOC_MAX98927=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_STUB=y +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_MSM_GFX_LDO=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_QPNP=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_CPR3_HMSS=y +CONFIG_REGULATOR_CPR3_MMSS=y +CONFIG_REGULATOR_CPR4_APSS=y +CONFIG_REGULATOR_CPRH_KBSS=y +CONFIG_REGULATOR_KRYO=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y +CONFIG_MSM_CAMERA=y +CONFIG_MSMB_CAMERA=y +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF=y +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_MSM_SDE_ROTATOR=y +CONFIG_RADIO_IRIS=y +CONFIG_RADIO_IRIS_TRANSPORT=y +CONFIG_RADIO_SILABS=y +CONFIG_MSM_KGSL=y +CONFIG_FB=y +CONFIG_FB_MSM=y +CONFIG_MSM_DBA=y +CONFIG_MSM_DBA_ADV7533=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_MSM8X16=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_EHCI_MSM_HSIC=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_DWC3=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MSM_HSPHY=y +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y +# CONFIG_DUAL_ROLE_USB_INTF is not set +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CI13XXX_MSM=y +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_CLKGATE=y +CONFIG_MMC_PARANOID_SD_INIT=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_TEST=m +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_ICE=y +CONFIG_MMC_CQ_HCI=y +CONFIG_LEDS_QPNP=y +CONFIG_LEDS_QPNP_FLASH=y +CONFIG_LEDS_QPNP_WLED=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_SWITCH=y +CONFIG_EDAC=y +CONFIG_EDAC_MM_EDAC=y +CONFIG_EDAC_CORTEX_ARM64=y +CONFIG_EDAC_CORTEX_ARM64_DBE_IRQ_ONLY=y +CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_UE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_QPNP=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_ION_MSM=y +CONFIG_MSM_AVTIMER=y +CONFIG_MSM_BUS_SCALING=y +CONFIG_BUS_TOPOLOGY_ADHOC=y +CONFIG_QPNP_POWER_ON=y +CONFIG_QPNP_REVID=y +CONFIG_QPNP_COINCELL=y +CONFIG_SPS=y +CONFIG_USB_BAM=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y +CONFIG_QPNP_HAPTIC=y +CONFIG_GPIO_USB_DETECT=y +CONFIG_MSM_SPMI=y +CONFIG_MSM_SPMI_PMIC_ARB=y +CONFIG_MSM_QPNP_INT=y +CONFIG_MSM_CLK_CONTROLLER_V2=y +CONFIG_MSM_MDSS_PLL=y +CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_IOMMU_V1=y +CONFIG_ARM_SMMU=y +CONFIG_MSM_ADSP_LOADER=y +CONFIG_MSM_MEMORY_DUMP_V2=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_MSM_CPUSS_DUMP=y +CONFIG_MSM_COMMON_LOG=y +CONFIG_MSM_DDR_HEALTH=y +CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_MSM_RPM_SMD=y +CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y +CONFIG_MSM_RPM_LOG=y +CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_MSM_RUN_QUEUE_STATS=y +CONFIG_MSM_SCM=y +CONFIG_MSM_SCM_XPU=y +CONFIG_MSM_MPM_OF=y +CONFIG_MSM_SMEM=y +CONFIG_MSM_SMD=y +CONFIG_MSM_SMD_DEBUG=y +CONFIG_MSM_GLINK=y +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y +CONFIG_MSM_GLINK_SMD_XPRT=y +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y +CONFIG_MSM_SMEM_LOGGING=y +CONFIG_MSM_SMP2P=y +CONFIG_MSM_SMP2P_TEST=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_QMI_INTERFACE=y +CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y +CONFIG_MSM_PIL=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +CONFIG_ICNSS=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_MSM_KERNEL_PROTECT=y +CONFIG_MSM_KERNEL_PROTECT_MPU=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_SPDM_SCM=y +CONFIG_DEVFREQ_SPDM=y +CONFIG_PWM=y +CONFIG_PWM_QPNP=y +CONFIG_ARM_GIC_PANIC_HANDLER=y +CONFIG_ARM_GIC_V3_ACL=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_EVENT=y +CONFIG_CORESIGHT_TMC=y +CONFIG_CORESIGHT_FUNNEL=y +CONFIG_CORESIGHT_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_SENSORS_SSC=y +CONFIG_MSM_TZ_LOG=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_SDCARD_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_RECURSIVE_FAULT=y +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_TIMER_STATS=y +CONFIG_IPC_LOGGING=y +CONFIG_CPU_FREQ_SWITCH_PROFILER=y +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HARDENED_USERCOPY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_OTA_CRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_QMI_ENCDEC=y +CONFIG_SERIAL_NUM=y +#CONFIG_TOUCHSCREEN_FT5435=y +CONFIG_LEDS_AW2013=y +CONFIG_LEDS_AW2023=y +CONFIG_HQ_SYSFS_SUPPORT=y +CONFIG_SPI_PEELIR=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_FTRACE=y +CONFIG_DEBUG_FS=y +CONFIG_FUNCTION_TRACER=y +CONFIG_PSTORE_PMSG=y +CONFIG_CPU_BOOST=y +CONFIG_TOUCHSCREEN_GT917d=y +CONFIG_TOUCHSCREEN_FT5446=y +CONFIG_VITURALSAR=y +CONFIG_MI_FS=y +CONFIG_BOOT_INFO=y +CONFIG_OF_FLATTREE=y +CONFIG_WPONIT_ADJUST_FUN=y +CONFIG_FLASHLIGHT_SAKURA=y +CONFIG_PROJECT_SAKURA=y +CONFIG_ENABLE_PM_TP_SUSPEND_RESUME=y diff --git a/arch/arm64/configs/sakura-perf_defconfig b/arch/arm64/configs/sakura-perf_defconfig new file mode 100644 index 0000000000000..f19de0ac52f6e --- /dev/null +++ b/arch/arm64/configs/sakura-perf_defconfig @@ -0,0 +1,683 @@ +CONFIG_LOCALVERSION="-perf" +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_BOOST=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_SCHED_HMP=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_KALLSYMS_ALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_PROFILING=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_ARCH_MSM=y +CONFIG_ARCH_MSM8916=y +CONFIG_ARCH_MSM8940=y +CONFIG_ARCH_MSM8953=y +CONFIG_ARCH_SDM450=y +CONFIG_ARCH_MSM8937=y +CONFIG_ARCH_MSMCOBALT=y +CONFIG_PCI_MSM=y +CONFIG_SCHED_MC=y +CONFIG_PREEMPT=y +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_ZSMALLOC_STAT=y +CONFIG_PROCESS_RECLAIM=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_RUNTIME=y +CONFIG_PM_DEBUG=y +CONFIG_SUSPEND_TIME=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_FREQ=y +CONFIG_SCHED_FREQ_INPUT=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_SIT=y +CONFIG_NET_IPVTI=y +CONFIG_NET_UDP_TUNNEL=y +CONFIG_INET_UDP_DIAG=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NATTYPE_MODULE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_RMNET_DATA=y +CONFIG_RMNET_DATA_FC=y +CONFIG_RMNET_DATA_DEBUG_PKT=y +CONFIG_SOCKEV_NLMCAST=y +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_MSM_BT_POWER=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_IPC_ROUTER=y +CONFIG_IPC_ROUTER_SECURITY=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_DMA_CMA=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_UID_STAT=y +CONFIG_QSEECOM=y +CONFIG_HDCP_QSEECOM=y +CONFIG_UID_SYS_STATS=y +# CONFIG_USB_EXT_TYPE_C_PERICOM is not set +CONFIG_MSM_ULTRASOUND=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +CONFIG_RNDIS_IPA=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_USBNET=y +CONFIG_WCNSS_CORE=y +CONFIG_WCNSS_CORE_PRONTO=y +CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CNSS_CRYPTO=y +CONFIG_ATH_CARDS=y +CONFIG_WIL6210=m +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_KEYRESET=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y +#CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y +#CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_TOUCHSCREEN_GEN_VKEYS=y +CONFIG_TOUCHSCREEN_FT5X06=y +CONFIG_TOUCHSCREEN_MAXIM_STI=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +CONFIG_INPUT_FINGERPRINT=y +CONFIG_FINGERPRINT_GOODIX_GF3208=y +CONFIG_FINGERPRINT_FPC1020=y +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_MSM_HS=y +CONFIG_SERIAL_MSM_SMD=y +CONFIG_DIAG_CHAR=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +# CONFIG_DEVPORT is not set +CONFIG_MSM_SMD_PKT=y +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SLIMBUS=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SOUNDWIRE=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=m +CONFIG_PINCTRL_MSM8952=y +CONFIG_PINCTRL_MSM8937=y +CONFIG_PINCTRL_MSMCOBALT=y +CONFIG_PINCTRL_MSM8940=y +CONFIG_PINCTRL_MSM8953=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_QPNP_PIN=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_SMB135X_CHARGER=y +CONFIG_QPNP_SMBCHARGER=y +CONFIG_QPNP_FG=y +CONFIG_BATTERY_BCL=y +# CONFIG_QPNP_TYPEC is not set +CONFIG_MSM_BCL_CTL=y +CONFIG_MSM_BCL_PERIPHERAL_CTL=y +CONFIG_POWER_RESET_MSM=y +CONFIG_MSM_DLOAD_MODE=y +CONFIG_MSM_PM=y +CONFIG_APSS_CORE_EA=y +CONFIG_MSM_APM=y +CONFIG_SENSORS_EPM_ADC=y +CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y +CONFIG_SENSORS_QPNP_ADC_CURRENT=y +CONFIG_THERMAL=y +CONFIG_THERMAL_TSENS8974=y +CONFIG_LIMITS_MONITOR=y +CONFIG_LIMITS_LITE_HW=y +CONFIG_THERMAL_MONITOR=y +CONFIG_THERMAL_QPNP=y +CONFIG_THERMAL_QPNP_ADC_TM=y +CONFIG_WCD9335_CODEC=y +CONFIG_SND_SOC_MSM8X16_WCD=y +CONFIG_SND_SOC_WCD_MBHC=y +CONFIG_MBHC_UART=n +CONFIG_SND_SOC_MAX98927=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_STUB=y +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_MSM_GFX_LDO=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_QPNP=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_CPR3_HMSS=y +CONFIG_REGULATOR_CPR3_MMSS=y +CONFIG_REGULATOR_CPR4_APSS=y +CONFIG_REGULATOR_CPRH_KBSS=y +CONFIG_REGULATOR_KRYO=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_MSM_VIDC_V4L2=y +CONFIG_MSM_VIDC_VMEM=y +CONFIG_MSM_VIDC_GOVERNORS=y +CONFIG_MSM_CAMERA=y +CONFIG_MSMB_CAMERA=y +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF=y +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_MSM_SDE_ROTATOR=y +CONFIG_RADIO_IRIS=y +CONFIG_RADIO_IRIS_TRANSPORT=y +CONFIG_RADIO_SILABS=y +CONFIG_MSM_KGSL=y +CONFIG_FB=y +CONFIG_FB_MSM=y +CONFIG_MSM_DBA=y +CONFIG_MSM_DBA_ADV7533=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_HDMI_PANEL=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_MSM8X16=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_EHCI_MSM_HSIC=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_DWC3=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MSM_HSPHY=y +CONFIG_USB_MSM_SSPHY_QMP=y +CONFIG_MSM_QUSB_PHY=y +# CONFIG_DUAL_ROLE_USB_INTF is not set +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CI13XXX_MSM=y +CONFIG_USB_G_ANDROID=y +CONFIG_MMC=y +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_CLKGATE=y +CONFIG_MMC_PARANOID_SD_INIT=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_TEST=m +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_SDHCI_MSM_ICE=y +CONFIG_MMC_CQ_HCI=y +CONFIG_LEDS_QPNP=y +CONFIG_LEDS_QPNP_FLASH=y +CONFIG_LEDS_QPNP_WLED=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_SWITCH=y +CONFIG_EDAC=y +CONFIG_EDAC_MM_EDAC=y +CONFIG_EDAC_CORTEX_ARM64=y +CONFIG_EDAC_CORTEX_ARM64_DBE_IRQ_ONLY=y +CONFIG_EDAC_CORTEX_ARM64_PANIC_ON_UE=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_QPNP=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_SW_SYNC_USER=y +CONFIG_ION=y +CONFIG_ION_MSM=y +CONFIG_MSM_AVTIMER=y +CONFIG_MSM_BUS_SCALING=y +CONFIG_BUS_TOPOLOGY_ADHOC=y +CONFIG_QPNP_POWER_ON=y +CONFIG_QPNP_REVID=y +CONFIG_QPNP_COINCELL=y +CONFIG_SPS=y +CONFIG_USB_BAM=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y +CONFIG_QPNP_HAPTIC=y +CONFIG_GPIO_USB_DETECT=y +CONFIG_MSM_SPMI=y +CONFIG_MSM_SPMI_PMIC_ARB=y +CONFIG_MSM_QPNP_INT=y +CONFIG_MSM_CLK_CONTROLLER_V2=y +CONFIG_MSM_MDSS_PLL=y +CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_IOMMU_V1=y +CONFIG_ARM_SMMU=y +CONFIG_MSM_ADSP_LOADER=y +CONFIG_MSM_MEMORY_DUMP_V2=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_MSM_CPUSS_DUMP=y +CONFIG_MSM_COMMON_LOG=y +CONFIG_MSM_DDR_HEALTH=y +CONFIG_MSM_WATCHDOG_V2=y +CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_MSM_RPM_SMD=y +CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y +CONFIG_MSM_RPM_LOG=y +CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_MSM_RUN_QUEUE_STATS=y +CONFIG_MSM_SCM=y +CONFIG_MSM_SCM_XPU=y +CONFIG_MSM_MPM_OF=y +CONFIG_MSM_SMEM=y +CONFIG_MSM_SMD=y +CONFIG_MSM_SMD_DEBUG=y +CONFIG_MSM_GLINK=y +CONFIG_MSM_GLINK_LOOPBACK_SERVER=y +CONFIG_MSM_GLINK_SMD_XPRT=y +CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y +CONFIG_MSM_SMEM_LOGGING=y +CONFIG_MSM_SMP2P=y +CONFIG_MSM_SMP2P_TEST=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_QMI_INTERFACE=y +CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y +CONFIG_MSM_PIL=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +CONFIG_ICNSS=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_MSM_KERNEL_PROTECT=y +CONFIG_MSM_KERNEL_PROTECT_MPU=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_SPDM_SCM=y +CONFIG_DEVFREQ_SPDM=y +CONFIG_PWM=y +CONFIG_PWM_QPNP=y +CONFIG_ARM_GIC_PANIC_HANDLER=y +CONFIG_ARM_GIC_V3_ACL=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_EVENT=y +CONFIG_CORESIGHT_TMC=y +CONFIG_CORESIGHT_FUNNEL=y +CONFIG_CORESIGHT_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +CONFIG_SENSORS_SSC=y +CONFIG_MSM_TZ_LOG=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_SDCARD_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_RECURSIVE_FAULT=y +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +CONFIG_TIMER_STATS=y +CONFIG_IPC_LOGGING=y +CONFIG_CPU_FREQ_SWITCH_PROFILER=y +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_DEBUG_RODATA=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HARDENED_USERCOPY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_OTA_CRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_QMI_ENCDEC=y +CONFIG_SERIAL_NUM=y +#CONFIG_TOUCHSCREEN_FT5435=y +CONFIG_LEDS_AW2013=y +CONFIG_LEDS_AW2023=y +CONFIG_HQ_SYSFS_SUPPORT=y +CONFIG_SPI_PEELIR=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y +CONFIG_PSTORE_FTRACE=y +CONFIG_DEBUG_FS=y +CONFIG_FUNCTION_TRACER=y +CONFIG_PSTORE_PMSG=y +CONFIG_CPU_BOOST=y +CONFIG_TOUCHSCREEN_GT917d=y +CONFIG_TOUCHSCREEN_FT5446=y +CONFIG_VITURALSAR=y +CONFIG_MI_FS=y +CONFIG_BOOT_INFO=y +CONFIG_OF_FLATTREE=y +CONFIG_WPONIT_ADJUST_FUN=y +CONFIG_FLASHLIGHT_SAKURA=y +CONFIG_PROJECT_SAKURA=y +CONFIG_PROJECT_SAKURA_CN=y +CONFIG_ENABLE_PM_TP_SUSPEND_RESUME=y diff --git a/arch/arm64/include/asm/bootinfo.h b/arch/arm64/include/asm/bootinfo.h new file mode 100644 index 0000000000000..e531544e2cac0 --- /dev/null +++ b/arch/arm64/include/asm/bootinfo.h @@ -0,0 +1,87 @@ +/* + * bootinfo.h + * + * 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 __ASMARM_BOOTINFO_H +#define __ASMARM_BOOTINFO_H + +typedef enum { + PU_REASON_EVENT_HWRST, + PU_REASON_EVENT_SMPL, + PU_REASON_EVENT_RTC, + PU_REASON_EVENT_DC_CHG, + PU_REASON_EVENT_USB_CHG, + PU_REASON_EVENT_PON1, + PU_REASON_EVENT_CABLE, + PU_REASON_EVENT_KPD, + PU_REASON_EVENT_WARMRST, + PU_REASON_EVENT_LPK, + PU_REASON_MAX +} powerup_reason_t; + +enum { + RS_REASON_EVENT_WDOG, + RS_REASON_EVENT_KPANIC, + RS_REASON_EVENT_NORMAL, + RS_REASON_EVENT_OTHER, + RS_REASON_MAX +}; + +typedef enum { + POFF_REASON_EVENT_SOFT, + POFF_REASON_EVENT_PS_HOLD, + POFF_REASON_EVENT_PMIC_WD, + POFF_REASON_EVENT_GP1_KPD1, + POFF_REASON_EVENT_GP2_KPD2, + POFF_REASON_EVENT_KPDPWR_AND_RESIN, + POFF_REASON_EVENT_RESIN_N, + POFF_REASON_EVENT_KPDPWR_N, + POFF_REASON_EVENT_RESEVER1, + POFF_REASON_EVENT_RESEVER2, + POFF_REASON_EVENT_RESEVER3, + POFF_REASON_EVENT_CHARGER, + POFF_REASON_EVENT_TFT, + POFF_REASON_EVENT_UVLO, + POFF_REASON_EVENT_OTST3, + POFF_REASON_EVENT_STAGE3, + POFF_REASON_EVENT_GP_FAULT0, + POFF_REASON_EVENT_GP_FAULT1, + POFF_REASON_EVENT_GP_FAULT2, + POFF_REASON_EVENT_GP_FAULT3, + POFF_REASON_EVENT_MBG_FAULT, + POFF_REASON_EVENT_OVLO, + POFF_REASON_EVENT_GEN2_UVLO, + POFF_REASON_EVENT_AVDD_RB, + POFF_REASON_EVENT_RESEVER4, + POFF_REASON_EVENT_RESEVER5, + POFF_REASON_EVENT_RESEVER6, + POFF_REASON_EVENT_FAULT_FAULT_N, + POFF_REASON_EVENT_FAULT_PBS_WATCHDOG_TO, + POFF_REASON_EVENT_FAULT_PBS_NACK, + POFF_REASON_EVENT_FAULT_RESTART_PON, + POFF_REASON_EVENT_GEN2_OTST3, + POFF_REASON_EVENT_RESEVER7, + POFF_REASON_EVENT_RESEVER8, + POFF_REASON_EVENT_RESEVER9, + POFF_REASON_EVENT_RESEVER10, + POFF_REASON_EVENT_S3_RESET_FAULT_N, + POFF_REASON_EVENT_S3_RESET_PBS_WATCHDOG_TO, + POFF_REASON_EVENT_S3_RESET_PBS_NACK, + POFF_REASON_EVENT_S3_RESET_KPDPWR_ANDOR_RESIN, + POFF_REASON_MAX +} poweroff_reason_t; + +#define RESTART_EVENT_WDOG 0x10000 +#define RESTART_EVENT_KPANIC 0x20000 +#define RESTART_EVENT_NORMAL 0x40000 +#define RESTART_EVENT_OTHER 0x80000 + +void set_poweroff_reason(int poweroff_reason); +unsigned int get_powerup_reason(void); +bool is_abnormal_powerup(void); +void set_powerup_reason(unsigned int powerup_reason); +#endif diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 7ca6f766dd04a..e7f6c96d0adac 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -36,6 +36,7 @@ arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_CPU_IDLE) += cpuidle.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_KGDB) += kgdb.o +arm64-obj-$(CONFIG_BOOT_INFO) += bootinfo.o arm64-obj-$(CONFIG_EFI) += efi.o efi-stub.o efi-entry.o arm64-obj-$(CONFIG_PCI) += pci.o arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o diff --git a/arch/arm64/kernel/bootinfo.c b/arch/arm64/kernel/bootinfo.c new file mode 100644 index 0000000000000..7b66bdc4fe816 --- /dev/null +++ b/arch/arm64/kernel/bootinfo.c @@ -0,0 +1,271 @@ +/* + * bootinfo.c + * + * Copyright (C) 2011 Xiaomi Ltd. + * Copyright (C) 2019 XiaoMi, Inc. + * + * 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 + +#define PMIC_NUM (16) +static int pmic_v[PMIC_NUM]; +static const char *poweroff_reasons[POFF_REASON_MAX] = { + [POFF_REASON_EVENT_SOFT] = "soft", + [POFF_REASON_EVENT_PS_HOLD] = "ps_hold", + [POFF_REASON_EVENT_PMIC_WD] = "pmic_wd", + [POFF_REASON_EVENT_GP1_KPD1] = "keypad_reset1", + [POFF_REASON_EVENT_GP2_KPD2] = "keypad_reset2", + [POFF_REASON_EVENT_KPDPWR_AND_RESIN] = "kpdpwr_resin", + [POFF_REASON_EVENT_RESIN_N] = "resin_n", + [POFF_REASON_EVENT_KPDPWR_N] = "kpdpwr_n", + [POFF_REASON_EVENT_RESEVER1] = "resever1", + [POFF_REASON_EVENT_RESEVER2] = "resever2", + [POFF_REASON_EVENT_RESEVER3] = "resever3", + [POFF_REASON_EVENT_CHARGER] = "charger", + [POFF_REASON_EVENT_TFT] = "tft", + [POFF_REASON_EVENT_UVLO] = "uvlo", + [POFF_REASON_EVENT_OTST3] = "otst3", + [POFF_REASON_EVENT_STAGE3] = "stage3", + [POFF_REASON_EVENT_GP_FAULT0] = "gp_fault0", + [POFF_REASON_EVENT_GP_FAULT1] = "gp_fault1", + [POFF_REASON_EVENT_GP_FAULT2] = "gp_fault2", + [POFF_REASON_EVENT_GP_FAULT3] = "gp_fault3", + [POFF_REASON_EVENT_MBG_FAULT] = "mbg_fault", + [POFF_REASON_EVENT_OVLO] = "ovlo", + [POFF_REASON_EVENT_GEN2_UVLO] = "gen2_uvlo", + [POFF_REASON_EVENT_AVDD_RB] = "avdd_rb", + [POFF_REASON_EVENT_RESEVER4] = "resever4", + [POFF_REASON_EVENT_RESEVER5] = "resever5", + [POFF_REASON_EVENT_RESEVER6] = "resever6", + [POFF_REASON_EVENT_FAULT_FAULT_N] = "fault_n", + [POFF_REASON_EVENT_FAULT_PBS_WATCHDOG_TO] = "fault_pbs_watchdog", + [POFF_REASON_EVENT_FAULT_PBS_NACK] = "fault_pbs_nack", + [POFF_REASON_EVENT_FAULT_RESTART_PON] = "fault_restart_pon", + [POFF_REASON_EVENT_GEN2_OTST3] = "otst3", + [POFF_REASON_EVENT_RESEVER7] = "resever7", + [POFF_REASON_EVENT_RESEVER8] = "resever8", + [POFF_REASON_EVENT_RESEVER9] = "resever9", + [POFF_REASON_EVENT_RESEVER10] = "resever10", + [POFF_REASON_EVENT_S3_RESET_FAULT_N] = "s3_reset_fault_n", + [POFF_REASON_EVENT_S3_RESET_PBS_WATCHDOG_TO] = "s3_reset_pbs_watchdog", + [POFF_REASON_EVENT_S3_RESET_PBS_NACK] = "s3_reset_pbs_nack", + [POFF_REASON_EVENT_S3_RESET_KPDPWR_ANDOR_RESIN] = "s3_reset_kpdpwr_andor_resin", +}; + + +static const char *powerup_reasons[PU_REASON_MAX] = { + [PU_REASON_EVENT_KPD] = "keypad", + [PU_REASON_EVENT_RTC] = "rtc", + [PU_REASON_EVENT_CABLE] = "cable", + [PU_REASON_EVENT_SMPL] = "smpl", + [PU_REASON_EVENT_PON1] = "pon1", + [PU_REASON_EVENT_USB_CHG] = "usb_chg", + [PU_REASON_EVENT_DC_CHG] = "dc_chg", + [PU_REASON_EVENT_HWRST] = "hw_reset", + [PU_REASON_EVENT_LPK] = "long_power_key", +}; + +static const char *reset_reasons[RS_REASON_MAX] = { + [RS_REASON_EVENT_WDOG] = "wdog", + [RS_REASON_EVENT_KPANIC] = "kpanic", + [RS_REASON_EVENT_NORMAL] = "reboot", + [RS_REASON_EVENT_OTHER] = "other", +}; + +static struct kobject *bootinfo_kobj; +static powerup_reason_t powerup_reason; + +#define bootinfo_attr(_name) \ +static struct kobj_attribute _name##_attr = { \ + .attr = { \ + .name = __stringify(_name), \ + .mode = 0644, \ + }, \ + .show = _name##_show, \ + .store = NULL, \ +} + +#define bootinfo_func_init(type, name, initval) \ + static type name = (initval); \ + type get_##name(void) \ + { \ + return name; \ + } \ + void set_##name(type __##name) \ + { \ + name = __##name; \ + } \ + EXPORT_SYMBOL(set_##name); \ + EXPORT_SYMBOL(get_##name); + +bool is_abnormal_powerup(void) +{ + u32 pu_reason = get_powerup_reason(); + return (((pu_reason & (RESTART_EVENT_KPANIC | RESTART_EVENT_WDOG)) | + (pu_reason & BIT(PU_REASON_EVENT_HWRST) & RESTART_EVENT_OTHER)) == 0 ? false : true); +} + +static ssize_t powerup_reason_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + char *s = buf; + u32 pu_reason; + int pu_reason_index = PU_REASON_MAX; + u32 reset_reason; + int reset_reason_index = RS_REASON_MAX; + + pu_reason = get_powerup_reason(); + if (((pu_reason & BIT(PU_REASON_EVENT_HWRST)) + && qpnp_pon_is_ps_hold_reset()) || + (pu_reason & BIT(PU_REASON_EVENT_WARMRST))) { + reset_reason = pu_reason >> 16; + reset_reason_index = find_first_bit((unsigned long *)&reset_reason, + sizeof(reset_reason)*BITS_PER_BYTE); + if (reset_reason_index < RS_REASON_MAX && reset_reason_index >= 0) { + s += snprintf(s, strlen(reset_reasons[reset_reason_index]) + 2, + "%s\n", reset_reasons[reset_reason_index]); + printk(KERN_DEBUG "%s: rs_reason [0x%x], first non-zero bit" + " %d\n", __func__, reset_reason, reset_reason_index); + goto out; + }; + } + if (qpnp_pon_is_lpk() && + (pu_reason & BIT(PU_REASON_EVENT_HWRST))) + pu_reason_index = PU_REASON_EVENT_LPK; + else if (pu_reason & BIT(PU_REASON_EVENT_HWRST)) + pu_reason_index = PU_REASON_EVENT_HWRST; + else if (pu_reason & BIT(PU_REASON_EVENT_SMPL)) + pu_reason_index = PU_REASON_EVENT_SMPL; + else if (pu_reason & BIT(PU_REASON_EVENT_RTC)) + pu_reason_index = PU_REASON_EVENT_RTC; + else if (pu_reason & BIT(PU_REASON_EVENT_USB_CHG)) + pu_reason_index = PU_REASON_EVENT_USB_CHG; + else if (pu_reason & BIT(PU_REASON_EVENT_DC_CHG)) + pu_reason_index = PU_REASON_EVENT_DC_CHG; + else if (pu_reason & BIT(PU_REASON_EVENT_KPD)) + pu_reason_index = PU_REASON_EVENT_KPD; + else if (pu_reason & BIT(PU_REASON_EVENT_PON1)) + pu_reason_index = PU_REASON_EVENT_PON1; + if (pu_reason_index < PU_REASON_MAX && pu_reason_index >=0) { + s += snprintf(s, strlen(powerup_reasons[pu_reason_index]) + 2, + "%s\n", powerup_reasons[pu_reason_index]); + printk(KERN_DEBUG "%s: pu_reason [0x%x] index %d\n", + __func__, pu_reason, pu_reason_index); + goto out; + } + s += snprintf(s, 15, "unknown reboot\n"); +out: + return (s - buf); +} + +static ssize_t powerup_reason_details_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + u32 pu_reason; + + pu_reason = get_powerup_reason(); + + return snprintf(buf, 11, "0x%x\n", pu_reason); +} + +void set_poweroff_reason(int pmicv) +{ + int i = 0; + + while (i < PMIC_NUM) { + if (pmic_v[i] != -1) + i++; + else { + pmic_v[i] = pmicv; + break; + } + } +} + +static ssize_t poweroff_reason_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int i = 0; + int l = 0; + int v = pmic_v[0]; + + if (v == -1) + return snprintf(buf, 10, " unknown \n"); + + while ((i < PMIC_NUM) && (pmic_v[i] != -1)) { + v = pmic_v[i]; + i++; + if (v >= 0 && v < POFF_REASON_MAX) + l += snprintf(buf + l, + (strlen(poweroff_reasons[v]) + 10), + " PNo.%d-%s ", i - 1, poweroff_reasons[v]); + else + l += snprintf(buf + l, 17, " PNo.%d-%s ", i - 1, "unknown"); + } + l += snprintf(buf + l, 2, "\n"); + + return l; +} + +bootinfo_attr(poweroff_reason); +bootinfo_attr(powerup_reason); +bootinfo_attr(powerup_reason_details); +bootinfo_func_init(u32, powerup_reason, 0); + +static struct attribute *g[] = { + &poweroff_reason_attr.attr, + &powerup_reason_attr.attr, + &powerup_reason_details_attr.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = g, +}; + +static int __init bootinfo_init(void) +{ + int ret = -ENOMEM; + + bootinfo_kobj = kobject_create_and_add("bootinfo", NULL); + if (bootinfo_kobj == NULL) { + printk("bootinfo_init: subsystem_register failed\n"); + goto fail; + } + memset(pmic_v, -1, sizeof(pmic_v)); + ret = sysfs_create_group(bootinfo_kobj, &attr_group); + if (ret) { + printk("bootinfo_init: subsystem_register failed\n"); + goto sys_fail; + } + + return ret; + +sys_fail: + kobject_del(bootinfo_kobj); +fail: + return ret; + +} + +static void __exit bootinfo_exit(void) +{ + if (bootinfo_kobj) { + sysfs_remove_group(bootinfo_kobj, &attr_group); + kobject_del(bootinfo_kobj); + } +} + +core_initcall(bootinfo_init); +module_exit(bootinfo_exit); + diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 0bfd0484edb6a..a92e9a805a45a 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -62,6 +62,15 @@ #include #include #include +#include + +#ifdef CONFIG_OF_FLATTREE +void __init early_init_dt_setup_pureason_arch(unsigned long pu_reason) +{ + set_powerup_reason(pu_reason); + pr_info("Powerup reason=0x%x\n", get_powerup_reason()); +} +#endif unsigned int boot_reason; EXPORT_SYMBOL(boot_reason); diff --git a/block/blk-mq.c b/block/blk-mq.c index 4b839c117c566..2f2e5259375a1 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -498,6 +498,7 @@ void blk_mq_kick_requeue_list(struct request_queue *q) } EXPORT_SYMBOL(blk_mq_kick_requeue_list); + struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag) { return tags->rqs[tag]; @@ -544,7 +545,7 @@ void blk_mq_rq_timed_out(struct request *req, bool reserved) break; } } - + static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx, struct request *rq, void *priv, bool reserved) { diff --git a/block/blk.h b/block/blk.h index a9cd7d987d54f..9ef3223e4d681 100644 --- a/block/blk.h +++ b/block/blk.h @@ -186,7 +186,7 @@ static inline int blk_should_fake_timeout(struct request_queue *q) int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *bio); -int ll_front_merge_fn(struct request_queue *q, struct request *req, +int ll_front_merge_fn(struct request_queue *q, struct request *req, struct bio *bio); int attempt_back_merge(struct request_queue *q, struct request *rq); int attempt_front_merge(struct request_queue *q, struct request *rq); diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index df04227d00cfa..b78013a17cf04 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -165,6 +165,11 @@ config FW_LOADER_USER_HELPER_FALLBACK If you are unsure about this, say N here. +config FW_CACHE + bool "Enable firmware caching during suspend" + depends on PM_SLEEP + default n + config WANT_DEV_COREDUMP bool help diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 2f23c4bf07c82..9ecc43a0242a9 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -2,6 +2,7 @@ * firmware_class.c - Multi purpose firmware loading support * * Copyright (c) 2003 Manuel Estrada Sainz + * Copyright (C) 2019 XiaoMi, Inc. * * Please see Documentation/firmware_class/ for more information. * @@ -1118,7 +1119,7 @@ static int fw_load_from_user_helper(struct firmware *firmware, return _request_firmware_load(fw_priv, desc->opt_flags, timeout); } -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE /* kill pending requests without uevent to avoid blocking suspend */ static void kill_requests_without_uevent(void) { @@ -1596,7 +1597,7 @@ request_firmware_nowait_into_buf( } EXPORT_SYMBOL_GPL(request_firmware_nowait_into_buf); -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); /** @@ -1936,7 +1937,7 @@ static void __init fw_cache_init(void) INIT_LIST_HEAD(&fw_cache.head); fw_cache.state = FW_LOADER_NO_CACHE; -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE spin_lock_init(&fw_cache.name_lock); INIT_LIST_HEAD(&fw_cache.fw_names); @@ -1963,7 +1964,7 @@ static int __init firmware_class_init(void) static void __exit firmware_class_exit(void) { -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_FW_CACHE unregister_syscore_ops(&fw_syscore_ops); unregister_pm_notifier(&fw_cache.pm_notify); #endif diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 15157a3eabb4b..7b6edc6bf394e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -4,6 +4,7 @@ * Written by Theodore Ts'o, 3/29/93 * * Copyright 1993 by Theodore Ts'o. Redistribution of this file is + * Copyright (C) 2019 XiaoMi, Inc. * permitted under the GNU General Public License. * * DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993 @@ -146,13 +147,13 @@ static int xor_init(struct loop_device *lo, const struct loop_info64 *info) static struct loop_func_table none_funcs = { .number = LO_CRYPT_NONE, .transfer = transfer_none, -}; +}; static struct loop_func_table xor_funcs = { .number = LO_CRYPT_XOR, .transfer = transfer_xor, .init = xor_init -}; +}; /* xfer_funcs[0] is special - its release function is never called */ static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { @@ -1142,7 +1143,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, info->lo_encrypt_key_size); lo->lo_key_owner = uid; - } + } return 0; } diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig index 6489c0fd0ea6e..386ba3d1a6ee8 100644 --- a/drivers/block/zram/Kconfig +++ b/drivers/block/zram/Kconfig @@ -23,12 +23,4 @@ config ZRAM_LZ4_COMPRESS default n help This option enables LZ4 compression algorithm support. Compression - algorithm can be changed using `comp_algorithm' device attribute. - -config ZRAM_DEBUG - bool "Compressed RAM block device debug support" - depends on ZRAM - default n - help - This option adds additional debugging code to the compressed - RAM block device driver. + algorithm can be changed using `comp_algorithm' device attribute. \ No newline at end of file diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index 6fbb10ca73b10..4fa72c82116ac 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Sergey Senozhatsky. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -13,6 +14,7 @@ #include #include #include +#include #include "zcomp.h" #include "zcomp_lzo.h" @@ -20,29 +22,6 @@ #include "zcomp_lz4.h" #endif -/* - * single zcomp_strm backend - */ -struct zcomp_strm_single { - struct mutex strm_lock; - struct zcomp_strm *zstrm; -}; - -/* - * multi zcomp_strm backend - */ -struct zcomp_strm_multi { - /* protect strm list */ - spinlock_t strm_lock; - /* max possible number of zstrm streams */ - int max_strm; - /* number of available zstrm streams */ - int avail_strm; - /* list of available strms */ - struct list_head idle_strm; - wait_queue_head_t strm_wait; -}; - static struct zcomp_backend *backends[] = { &zcomp_lzo, #ifdef CONFIG_ZRAM_LZ4_COMPRESS @@ -74,18 +53,18 @@ static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm) * allocate new zcomp_strm structure with ->private initialized by * backend, return NULL on error */ -static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) +static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp, gfp_t flags) { - struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_NOIO); + struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), flags); if (!zstrm) return NULL; - zstrm->private = comp->backend->create(); + zstrm->private = comp->backend->create(flags); /* * allocate 2 pages. 1 for compressed data, plus 1 extra for the * case when compressed size is larger than the original one */ - zstrm->buffer = (void *)__get_free_pages(GFP_NOIO | __GFP_ZERO, 1); + zstrm->buffer = (void *)__get_free_pages(flags | __GFP_ZERO, 1); if (!zstrm->private || !zstrm->buffer) { zcomp_strm_free(comp, zstrm); zstrm = NULL; @@ -93,180 +72,6 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) return zstrm; } -/* - * get idle zcomp_strm or wait until other process release - * (zcomp_strm_release()) one for us - */ -static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp) -{ - struct zcomp_strm_multi *zs = comp->stream; - struct zcomp_strm *zstrm; - - while (1) { - spin_lock(&zs->strm_lock); - if (!list_empty(&zs->idle_strm)) { - zstrm = list_entry(zs->idle_strm.next, - struct zcomp_strm, list); - list_del(&zstrm->list); - spin_unlock(&zs->strm_lock); - return zstrm; - } - /* zstrm streams limit reached, wait for idle stream */ - if (zs->avail_strm >= zs->max_strm) { - spin_unlock(&zs->strm_lock); - wait_event(zs->strm_wait, !list_empty(&zs->idle_strm)); - continue; - } - /* allocate new zstrm stream */ - zs->avail_strm++; - spin_unlock(&zs->strm_lock); - - zstrm = zcomp_strm_alloc(comp); - if (!zstrm) { - spin_lock(&zs->strm_lock); - zs->avail_strm--; - spin_unlock(&zs->strm_lock); - wait_event(zs->strm_wait, !list_empty(&zs->idle_strm)); - continue; - } - break; - } - return zstrm; -} - -/* add stream back to idle list and wake up waiter or free the stream */ -static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm) -{ - struct zcomp_strm_multi *zs = comp->stream; - - spin_lock(&zs->strm_lock); - if (zs->avail_strm <= zs->max_strm) { - list_add(&zstrm->list, &zs->idle_strm); - spin_unlock(&zs->strm_lock); - wake_up(&zs->strm_wait); - return; - } - - zs->avail_strm--; - spin_unlock(&zs->strm_lock); - zcomp_strm_free(comp, zstrm); -} - -/* change max_strm limit */ -static bool zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm) -{ - struct zcomp_strm_multi *zs = comp->stream; - struct zcomp_strm *zstrm; - - spin_lock(&zs->strm_lock); - zs->max_strm = num_strm; - /* - * if user has lowered the limit and there are idle streams, - * immediately free as much streams (and memory) as we can. - */ - while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) { - zstrm = list_entry(zs->idle_strm.next, - struct zcomp_strm, list); - list_del(&zstrm->list); - zcomp_strm_free(comp, zstrm); - zs->avail_strm--; - } - spin_unlock(&zs->strm_lock); - return true; -} - -static void zcomp_strm_multi_destroy(struct zcomp *comp) -{ - struct zcomp_strm_multi *zs = comp->stream; - struct zcomp_strm *zstrm; - - while (!list_empty(&zs->idle_strm)) { - zstrm = list_entry(zs->idle_strm.next, - struct zcomp_strm, list); - list_del(&zstrm->list); - zcomp_strm_free(comp, zstrm); - } - kfree(zs); -} - -static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm) -{ - struct zcomp_strm *zstrm; - struct zcomp_strm_multi *zs; - - comp->destroy = zcomp_strm_multi_destroy; - comp->strm_find = zcomp_strm_multi_find; - comp->strm_release = zcomp_strm_multi_release; - comp->set_max_streams = zcomp_strm_multi_set_max_streams; - zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL); - if (!zs) - return -ENOMEM; - - comp->stream = zs; - spin_lock_init(&zs->strm_lock); - INIT_LIST_HEAD(&zs->idle_strm); - init_waitqueue_head(&zs->strm_wait); - zs->max_strm = max_strm; - zs->avail_strm = 1; - - zstrm = zcomp_strm_alloc(comp); - if (!zstrm) { - kfree(zs); - return -ENOMEM; - } - list_add(&zstrm->list, &zs->idle_strm); - return 0; -} - -static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp) -{ - struct zcomp_strm_single *zs = comp->stream; - mutex_lock(&zs->strm_lock); - return zs->zstrm; -} - -static void zcomp_strm_single_release(struct zcomp *comp, - struct zcomp_strm *zstrm) -{ - struct zcomp_strm_single *zs = comp->stream; - mutex_unlock(&zs->strm_lock); -} - -static bool zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm) -{ - /* zcomp_strm_single support only max_comp_streams == 1 */ - return false; -} - -static void zcomp_strm_single_destroy(struct zcomp *comp) -{ - struct zcomp_strm_single *zs = comp->stream; - zcomp_strm_free(comp, zs->zstrm); - kfree(zs); -} - -static int zcomp_strm_single_create(struct zcomp *comp) -{ - struct zcomp_strm_single *zs; - - comp->destroy = zcomp_strm_single_destroy; - comp->strm_find = zcomp_strm_single_find; - comp->strm_release = zcomp_strm_single_release; - comp->set_max_streams = zcomp_strm_single_set_max_streams; - zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL); - if (!zs) - return -ENOMEM; - - comp->stream = zs; - mutex_init(&zs->strm_lock); - zs->zstrm = zcomp_strm_alloc(comp); - if (!zs->zstrm) { - kfree(zs); - return -ENOMEM; - } - return 0; -} - /* show available compressors */ ssize_t zcomp_available_show(const char *comp, char *buf) { @@ -274,7 +79,7 @@ ssize_t zcomp_available_show(const char *comp, char *buf) int i = 0; while (backends[i]) { - if (sysfs_streq(comp, backends[i]->name)) + if (!strcmp(comp, backends[i]->name)) sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2, "[%s] ", backends[i]->name); else @@ -286,19 +91,19 @@ ssize_t zcomp_available_show(const char *comp, char *buf) return sz; } -bool zcomp_set_max_streams(struct zcomp *comp, int num_strm) +bool zcomp_available_algorithm(const char *comp) { - return comp->set_max_streams(comp, num_strm); + return find_backend(comp) != NULL; } struct zcomp_strm *zcomp_strm_find(struct zcomp *comp) { - return comp->strm_find(comp); + return *get_cpu_ptr(comp->stream); } void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm) { - comp->strm_release(comp, zstrm); + put_cpu_ptr(comp->stream); } int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm, @@ -314,9 +119,83 @@ int zcomp_decompress(struct zcomp *comp, const unsigned char *src, return comp->backend->decompress(src, src_len, dst); } +static int __zcomp_cpu_notifier(struct zcomp *comp, + unsigned long action, unsigned long cpu) +{ + struct zcomp_strm *zstrm; + + switch (action) { + case CPU_UP_PREPARE: + if (WARN_ON(*per_cpu_ptr(comp->stream, cpu))) + break; + zstrm = zcomp_strm_alloc(comp, GFP_KERNEL); + if (IS_ERR_OR_NULL(zstrm)) { + pr_err("Can't allocate a compression stream\n"); + return NOTIFY_BAD; + } + *per_cpu_ptr(comp->stream, cpu) = zstrm; + break; + case CPU_DEAD: + case CPU_UP_CANCELED: + zstrm = *per_cpu_ptr(comp->stream, cpu); + if (!IS_ERR_OR_NULL(zstrm)) + zcomp_strm_free(comp, zstrm); + *per_cpu_ptr(comp->stream, cpu) = NULL; + break; + default: + break; + } + return NOTIFY_OK; +} + +static int zcomp_cpu_notifier(struct notifier_block *nb, + unsigned long action, void *pcpu) +{ + unsigned long cpu = (unsigned long)pcpu; + struct zcomp *comp = container_of(nb, typeof(*comp), notifier); + + return __zcomp_cpu_notifier(comp, action, cpu); +} + +static int zcomp_init(struct zcomp *comp) +{ + unsigned long cpu; + int ret; + + comp->notifier.notifier_call = zcomp_cpu_notifier; + + comp->stream = alloc_percpu(struct zcomp_strm *); + if (!comp->stream) + return -ENOMEM; + + cpu_notifier_register_begin(); + for_each_online_cpu(cpu) { + ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu); + if (ret == NOTIFY_BAD) + goto cleanup; + } + __register_cpu_notifier(&comp->notifier); + cpu_notifier_register_done(); + return 0; + +cleanup: + for_each_online_cpu(cpu) + __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu); + cpu_notifier_register_done(); + return -ENOMEM; +} + void zcomp_destroy(struct zcomp *comp) { - comp->destroy(comp); + unsigned long cpu; + + cpu_notifier_register_begin(); + for_each_online_cpu(cpu) + __zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu); + __unregister_cpu_notifier(&comp->notifier); + cpu_notifier_register_done(); + + free_percpu(comp->stream); kfree(comp); } @@ -326,9 +205,9 @@ void zcomp_destroy(struct zcomp *comp) * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL) * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in * case of allocation error, or any other error potentially - * returned by functions zcomp_strm_{multi,single}_create. + * returned by zcomp_init(). */ -struct zcomp *zcomp_create(const char *compress, int max_strm) +struct zcomp *zcomp_create(const char *compress) { struct zcomp *comp; struct zcomp_backend *backend; @@ -343,10 +222,7 @@ struct zcomp *zcomp_create(const char *compress, int max_strm) return ERR_PTR(-ENOMEM); comp->backend = backend; - if (max_strm > 1) - error = zcomp_strm_multi_create(comp, max_strm); - else - error = zcomp_strm_single_create(comp); + error = zcomp_init(comp); if (error) { kfree(comp); return ERR_PTR(error); diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index c59d1fca72c06..d799b412b42e1 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Sergey Senozhatsky. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -10,8 +11,6 @@ #ifndef _ZCOMP_H_ #define _ZCOMP_H_ -#include - struct zcomp_strm { /* compression/decompression buffer */ void *buffer; @@ -21,8 +20,6 @@ struct zcomp_strm { * working memory) */ void *private; - /* used in multi stream backend, protected by backend strm_lock */ - struct list_head list; }; /* static compression backend */ @@ -33,7 +30,7 @@ struct zcomp_backend { int (*decompress)(const unsigned char *src, size_t src_len, unsigned char *dst); - void *(*create)(void); + void *(*create)(gfp_t flags); void (*destroy)(void *private); const char *name; @@ -41,18 +38,15 @@ struct zcomp_backend { /* dynamic per-device compression frontend */ struct zcomp { - void *stream; + struct zcomp_strm * __percpu *stream; struct zcomp_backend *backend; - - struct zcomp_strm *(*strm_find)(struct zcomp *comp); - void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm); - bool (*set_max_streams)(struct zcomp *comp, int num_strm); - void (*destroy)(struct zcomp *comp); + struct notifier_block notifier; }; ssize_t zcomp_available_show(const char *comp, char *buf); +bool zcomp_available_algorithm(const char *comp); -struct zcomp *zcomp_create(const char *comp, int max_strm); +struct zcomp *zcomp_create(const char *comp); void zcomp_destroy(struct zcomp *comp); struct zcomp_strm *zcomp_strm_find(struct zcomp *comp); diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c index dd6083124276f..1d39fe3a252a2 100644 --- a/drivers/block/zram/zcomp_lz4.c +++ b/drivers/block/zram/zcomp_lz4.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Sergey Senozhatsky. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,24 +16,14 @@ #include "zcomp_lz4.h" -static void *zcomp_lz4_create(void) +static void *zcomp_lz4_create(gfp_t flags) { void *ret; - /* - * This function can be called in swapout/fs write path - * so we can't use GFP_FS|IO. And it assumes we already - * have at least one stream in zram initialization so we - * don't do best effort to allocate more stream in here. - * A default stream will work well without further multiple - * streams. That's why we use NORETRY | NOWARN. - */ - ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY | - __GFP_NOWARN); + ret = kmalloc(LZ4_MEM_COMPRESS, flags); if (!ret) ret = __vmalloc(LZ4_MEM_COMPRESS, - GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN | - __GFP_ZERO | __GFP_HIGHMEM, + flags | __GFP_HIGHMEM, PAGE_KERNEL); return ret; } diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c index edc549920fa06..47e391b6d366c 100644 --- a/drivers/block/zram/zcomp_lzo.c +++ b/drivers/block/zram/zcomp_lzo.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Sergey Senozhatsky. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,24 +16,14 @@ #include "zcomp_lzo.h" -static void *lzo_create(void) +static void *lzo_create(gfp_t flags) { void *ret; - /* - * This function can be called in swapout/fs write path - * so we can't use GFP_FS|IO. And it assumes we already - * have at least one stream in zram initialization so we - * don't do best effort to allocate more stream in here. - * A default stream will work well without further multiple - * streams. That's why we use NORETRY | NOWARN. - */ - ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY | - __GFP_NOWARN); + ret = kmalloc(LZO1X_MEM_COMPRESS, flags); if (!ret) ret = __vmalloc(LZO1X_MEM_COMPRESS, - GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN | - __GFP_ZERO | __GFP_HIGHMEM, + flags | __GFP_HIGHMEM, PAGE_KERNEL); return ret; } diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index ae3908e3a4d4d..033c40b908273 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2,6 +2,7 @@ * Compressed RAM block device * * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * Copyright (C) 2019 XiaoMi, Inc. * 2012, 2013 Minchan Kim * * This code is released using a dual license strategy: BSD/GPL @@ -15,10 +16,6 @@ #define KMSG_COMPONENT "zram" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt -#ifdef CONFIG_ZRAM_DEBUG -#define DEBUG -#endif - #include #include #include @@ -32,22 +29,18 @@ #include #include #include -#include -#include +#include +#include #include "zram_drv.h" -/* Globals */ +static DEFINE_IDR(zram_index_idr); +/* idr index must be protected */ +static DEFINE_MUTEX(zram_index_mutex); + static int zram_major; -static struct zram *zram_devices; static const char *default_compressor = "lzo"; -/* - * We don't need to see memory allocation errors more than once every 1 - * second to know that a problem is occurring. - */ -#define ALLOC_ERROR_LOG_RATE_MS 1000 - /* Module params (documentation at end) */ static unsigned int num_devices = 1; @@ -61,7 +54,7 @@ static inline void deprecated_attr_warn(const char *name) } #define ZRAM_ATTR_RO(name) \ -static ssize_t name##_show(struct device *d, \ +static ssize_t name##_show(struct device *d, \ struct device_attribute *attr, char *b) \ { \ struct zram *zram = dev_to_zram(d); \ @@ -77,81 +70,122 @@ static inline bool init_done(struct zram *zram) return zram->disksize; } -static int zram_show_mem_notifier(struct notifier_block *nb, - unsigned long action, - void *data) +static inline struct zram *dev_to_zram(struct device *dev) { - int i; + return (struct zram *)dev_to_disk(dev)->private_data; +} - if (!zram_devices) - return 0; +/* flag operations require table entry bit_spin_lock() being held */ +static int zram_test_flag(struct zram_meta *meta, u32 index, + enum zram_pageflags flag) +{ + return meta->table[index].value & BIT(flag); +} - for (i = 0; i < num_devices; i++) { - struct zram *zram = &zram_devices[i]; - struct zram_meta *meta = zram->meta; +static void zram_set_flag(struct zram_meta *meta, u32 index, + enum zram_pageflags flag) +{ + meta->table[index].value |= BIT(flag); +} - if (!down_read_trylock(&zram->init_lock)) - continue; +static void zram_clear_flag(struct zram_meta *meta, u32 index, + enum zram_pageflags flag) +{ + meta->table[index].value &= ~BIT(flag); +} - if (init_done(zram)) { - u64 val; - u64 data_size; - u64 orig_data_size; - - val = zs_get_total_pages(meta->mem_pool); - data_size = atomic64_read(&zram->stats.compr_data_size); - orig_data_size = atomic64_read( - &zram->stats.pages_stored); - pr_info("Zram[%d] mem_used_total = %llu\n", i, - val << PAGE_SHIFT); - pr_info("Zram[%d] compr_data_size = %llu\n", i, - (unsigned long long)data_size); - pr_info("Zram[%d] orig_data_size = %llu\n", i, - (unsigned long long)orig_data_size); - } +static size_t zram_get_obj_size(struct zram_meta *meta, u32 index) +{ + return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1); +} - up_read(&zram->init_lock); - } +static void zram_set_obj_size(struct zram_meta *meta, + u32 index, size_t size) +{ + unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT; - return 0; + meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size; } -static struct notifier_block zram_show_mem_notifier_block = { - .notifier_call = zram_show_mem_notifier -}; +static inline bool is_partial_io(struct bio_vec *bvec) +{ + return bvec->bv_len != PAGE_SIZE; +} -static inline struct zram *dev_to_zram(struct device *dev) +/* + * Check if request is within bounds and aligned on zram logical blocks. + */ +static inline bool valid_io_request(struct zram *zram, + sector_t start, unsigned int size) { - return (struct zram *)dev_to_disk(dev)->private_data; + u64 end, bound; + + /* unaligned request */ + if (unlikely(start & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1))) + return false; + if (unlikely(size & (ZRAM_LOGICAL_BLOCK_SIZE - 1))) + return false; + + end = start + (size >> SECTOR_SHIFT); + bound = zram->disksize >> SECTOR_SHIFT; + /* out of range range */ + if (unlikely(start >= bound || end > bound || start > end)) + return false; + + /* I/O request is valid */ + return true; } -static ssize_t compact_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +static void update_position(u32 *index, int *offset, struct bio_vec *bvec) { - unsigned long nr_migrated; - struct zram *zram = dev_to_zram(dev); - struct zram_meta *meta; + if (*offset + bvec->bv_len >= PAGE_SIZE) + (*index)++; + *offset = (*offset + bvec->bv_len) % PAGE_SIZE; +} - down_read(&zram->init_lock); - if (!init_done(zram)) { - up_read(&zram->init_lock); - return -EINVAL; - } +static inline void update_used_max(struct zram *zram, + const unsigned long pages) +{ + unsigned long old_max, cur_max; - meta = zram->meta; - nr_migrated = zs_compact(meta->mem_pool); - atomic64_add(nr_migrated, &zram->stats.num_migrated); - up_read(&zram->init_lock); + old_max = atomic_long_read(&zram->stats.max_used_pages); - return len; + do { + cur_max = old_max; + if (pages > cur_max) + old_max = atomic_long_cmpxchg( + &zram->stats.max_used_pages, cur_max, pages); + } while (old_max != cur_max); } -static ssize_t disksize_show(struct device *dev, - struct device_attribute *attr, char *buf) +static bool page_zero_filled(void *ptr) { - struct zram *zram = dev_to_zram(dev); + unsigned int pos; + unsigned long *page; - return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize); + page = (unsigned long *)ptr; + + for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { + if (page[pos]) + return false; + } + + return true; +} + +static void handle_zero_page(struct bio_vec *bvec) +{ + struct page *page = bvec->bv_page; + void *user_mem; + + user_mem = kmap_atomic(page); + if (is_partial_io(bvec)) + memset(user_mem + bvec->bv_offset, 0, bvec->bv_len); + else + clear_page(user_mem); + kunmap_atomic(user_mem); + + flush_dcache_page(page); } static ssize_t initstate_show(struct device *dev, @@ -167,6 +201,14 @@ static ssize_t initstate_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%u\n", val); } +static ssize_t disksize_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct zram *zram = dev_to_zram(dev); + + return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize); +} + static ssize_t orig_data_size_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -194,19 +236,6 @@ static ssize_t mem_used_total_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT); } -static ssize_t max_comp_streams_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int val; - struct zram *zram = dev_to_zram(dev); - - down_read(&zram->init_lock); - val = zram->max_comp_streams; - up_read(&zram->init_lock); - - return scnprintf(buf, PAGE_SIZE, "%d\n", val); -} - static ssize_t mem_limit_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -276,33 +305,25 @@ static ssize_t mem_used_max_store(struct device *dev, return len; } +/* + * We switched to per-cpu streams and this attr is not needed anymore. + * However, we will keep it around for some time, because: + * a) we may revert per-cpu streams in the future + * b) it's visible to user space and we need to follow our 2 years + * retirement rule; but we already have a number of 'soon to be + * altered' attrs, so max_comp_streams need to wait for the next + * layoff cycle. + */ +static ssize_t max_comp_streams_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", num_online_cpus()); +} + static ssize_t max_comp_streams_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - int num; - struct zram *zram = dev_to_zram(dev); - int ret; - - ret = kstrtoint(buf, 0, &num); - if (ret < 0) - return ret; - if (num < 1) - return -EINVAL; - - down_write(&zram->init_lock); - if (init_done(zram)) { - if (!zcomp_set_max_streams(zram->comp, num)) { - pr_info("Cannot change max compression streams\n"); - ret = -EINVAL; - goto out; - } - } - - zram->max_comp_streams = num; - ret = len; -out: - up_write(&zram->init_lock); - return ret; + return len; } static ssize_t comp_algorithm_show(struct device *dev, @@ -322,6 +343,11 @@ static ssize_t comp_algorithm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct zram *zram = dev_to_zram(dev); + size_t sz; + + if (!zcomp_available_algorithm(buf)) + return -EINVAL; + down_write(&zram->init_lock); if (init_done(zram)) { up_write(&zram->init_lock); @@ -329,78 +355,117 @@ static ssize_t comp_algorithm_store(struct device *dev, return -EBUSY; } strlcpy(zram->compressor, buf, sizeof(zram->compressor)); + + /* ignore trailing newline */ + sz = strlen(zram->compressor); + if (sz > 0 && zram->compressor[sz - 1] == '\n') + zram->compressor[sz - 1] = 0x00; + up_write(&zram->init_lock); return len; } -/* flag operations needs meta->tb_lock */ -static int zram_test_flag(struct zram_meta *meta, u32 index, - enum zram_pageflags flag) +static ssize_t compact_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { - return meta->table[index].value & BIT(flag); -} + struct zram *zram = dev_to_zram(dev); + struct zram_meta *meta; -static void zram_set_flag(struct zram_meta *meta, u32 index, - enum zram_pageflags flag) -{ - meta->table[index].value |= BIT(flag); -} + down_read(&zram->init_lock); + if (!init_done(zram)) { + up_read(&zram->init_lock); + return -EINVAL; + } -static void zram_clear_flag(struct zram_meta *meta, u32 index, - enum zram_pageflags flag) -{ - meta->table[index].value &= ~BIT(flag); -} + meta = zram->meta; + zs_compact(meta->mem_pool); + up_read(&zram->init_lock); -static size_t zram_get_obj_size(struct zram_meta *meta, u32 index) -{ - return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1); + return len; } -static void zram_set_obj_size(struct zram_meta *meta, - u32 index, size_t size) +static ssize_t io_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) { - unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT; + struct zram *zram = dev_to_zram(dev); + ssize_t ret; - meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size; -} + down_read(&zram->init_lock); + ret = scnprintf(buf, PAGE_SIZE, + "%8llu %8llu %8llu %8llu\n", + (u64)atomic64_read(&zram->stats.failed_reads), + (u64)atomic64_read(&zram->stats.failed_writes), + (u64)atomic64_read(&zram->stats.invalid_io), + (u64)atomic64_read(&zram->stats.notify_free)); + up_read(&zram->init_lock); -static inline int is_partial_io(struct bio_vec *bvec) -{ - return bvec->bv_len != PAGE_SIZE; + return ret; } -/* - * Check if request is within bounds and aligned on zram logical blocks. - */ -static inline int valid_io_request(struct zram *zram, - sector_t start, unsigned int size) +static ssize_t mm_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) { - u64 end, bound; + struct zram *zram = dev_to_zram(dev); + struct zs_pool_stats pool_stats; + u64 orig_size, mem_used = 0; + long max_used; + ssize_t ret; - /* unaligned request */ - if (unlikely(start & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1))) - return 0; - if (unlikely(size & (ZRAM_LOGICAL_BLOCK_SIZE - 1))) - return 0; + memset(&pool_stats, 0x00, sizeof(struct zs_pool_stats)); - end = start + (size >> SECTOR_SHIFT); - bound = zram->disksize >> SECTOR_SHIFT; - /* out of range range */ - if (unlikely(start >= bound || end > bound || start > end)) - return 0; + down_read(&zram->init_lock); + if (init_done(zram)) { + mem_used = zs_get_total_pages(zram->meta->mem_pool); + zs_pool_stats(zram->meta->mem_pool, &pool_stats); + } - /* I/O request is valid */ - return 1; -} + orig_size = atomic64_read(&zram->stats.pages_stored); + max_used = atomic_long_read(&zram->stats.max_used_pages); -static void zram_meta_free(struct zram_meta *meta, u64 disksize) -{ - size_t num_pages = disksize >> PAGE_SHIFT; - size_t index; + ret = scnprintf(buf, PAGE_SIZE, + "%8llu %8llu %8llu %8lu %8ld %8llu %8lu\n", + orig_size << PAGE_SHIFT, + (u64)atomic64_read(&zram->stats.compr_data_size), + mem_used << PAGE_SHIFT, + zram->limit_pages << PAGE_SHIFT, + max_used << PAGE_SHIFT, + (u64)atomic64_read(&zram->stats.zero_pages), + pool_stats.pages_compacted); + up_read(&zram->init_lock); - /* Free all pages that are still in this zram device */ - for (index = 0; index < num_pages; index++) { + return ret; +} + +static DEVICE_ATTR_RO(io_stat); +static DEVICE_ATTR_RO(mm_stat); +ZRAM_ATTR_RO(num_reads); +ZRAM_ATTR_RO(num_writes); +ZRAM_ATTR_RO(failed_reads); +ZRAM_ATTR_RO(failed_writes); +ZRAM_ATTR_RO(invalid_io); +ZRAM_ATTR_RO(notify_free); +ZRAM_ATTR_RO(zero_pages); +ZRAM_ATTR_RO(compr_data_size); + +static inline bool zram_meta_get(struct zram *zram) +{ + if (atomic_inc_not_zero(&zram->refcount)) + return true; + return false; +} + +static inline void zram_meta_put(struct zram *zram) +{ + atomic_dec(&zram->refcount); +} + +static void zram_meta_free(struct zram_meta *meta, u64 disksize) +{ + size_t num_pages = disksize >> PAGE_SHIFT; + size_t index; + + /* Free all pages that are still in this zram device */ + for (index = 0; index < num_pages; index++) { unsigned long handle = meta->table[index].handle; if (!handle) @@ -414,10 +479,9 @@ static void zram_meta_free(struct zram_meta *meta, u64 disksize) kfree(meta); } -static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize) +static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize) { size_t num_pages; - char pool_name[8]; struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL); if (!meta) @@ -430,8 +494,7 @@ static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize) goto out_error; } - snprintf(pool_name, sizeof(pool_name), "zram%d", device_id); - meta->mem_pool = zs_create_pool(pool_name, GFP_NOIO | __GFP_HIGHMEM); + meta->mem_pool = zs_create_pool(pool_name); if (!meta->mem_pool) { pr_err("Error creating memory pool\n"); goto out_error; @@ -445,56 +508,6 @@ static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize) return NULL; } -static inline bool zram_meta_get(struct zram *zram) -{ - if (atomic_inc_not_zero(&zram->refcount)) - return true; - return false; -} - -static inline void zram_meta_put(struct zram *zram) -{ - atomic_dec(&zram->refcount); -} - -static void update_position(u32 *index, int *offset, struct bio_vec *bvec) -{ - if (*offset + bvec->bv_len >= PAGE_SIZE) - (*index)++; - *offset = (*offset + bvec->bv_len) % PAGE_SIZE; -} - -static int page_zero_filled(void *ptr) -{ - unsigned int pos; - unsigned long *page; - - page = (unsigned long *)ptr; - - for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { - if (page[pos]) - return 0; - } - - return 1; -} - -static void handle_zero_page(struct bio_vec *bvec) -{ - struct page *page = bvec->bv_page; - void *user_mem; - - user_mem = kmap_atomic(page); - if (is_partial_io(bvec)) - memset(user_mem + bvec->bv_offset, 0, bvec->bv_len); - else - clear_page(user_mem); - kunmap_atomic(user_mem); - - flush_dcache_page(page); -} - - /* * To protect concurrent access to the same index entry, * caller should hold this table index entry's bit_spinlock to @@ -541,13 +554,13 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); - memset(mem, 0, PAGE_SIZE); + clear_page(mem); return 0; } cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); if (size == PAGE_SIZE) - memcpy(mem, cmem, PAGE_SIZE); + copy_page(mem, cmem); else ret = zcomp_decompress(zram->comp, cmem, size, mem); zs_unmap_object(meta->mem_pool, handle); @@ -589,7 +602,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, uncmem = user_mem; if (!uncmem) { - pr_info("Unable to allocate temp memory\n"); + pr_err("Unable to allocate temp memory\n"); ret = -ENOMEM; goto out_cleanup; } @@ -612,34 +625,17 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, return ret; } -static inline void update_used_max(struct zram *zram, - const unsigned long pages) -{ - unsigned long old_max, cur_max; - - old_max = atomic_long_read(&zram->stats.max_used_pages); - - do { - cur_max = old_max; - if (pages > cur_max) - old_max = atomic_long_cmpxchg( - &zram->stats.max_used_pages, cur_max, pages); - } while (old_max != cur_max); -} - static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, int offset) { int ret = 0; size_t clen; - unsigned long handle; + unsigned long handle = 0; struct page *page; unsigned char *user_mem, *cmem, *src, *uncmem = NULL; struct zram_meta *meta = zram->meta; - struct zcomp_strm *zstrm; - bool locked = false; + struct zcomp_strm *zstrm = NULL; unsigned long alloced_pages; - static unsigned long zram_rs_time; page = bvec->bv_page; if (is_partial_io(bvec)) { @@ -657,10 +653,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } - zstrm = zcomp_strm_find(zram->comp); - locked = true; +compress_again: user_mem = kmap_atomic(page); - if (is_partial_io(bvec)) { memcpy(uncmem + offset, user_mem + bvec->bv_offset, bvec->bv_len); @@ -684,6 +678,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } + zstrm = zcomp_strm_find(zram->comp); ret = zcomp_compress(zram->comp, zstrm, uncmem, &clen); if (!is_partial_io(bvec)) { kunmap_atomic(user_mem); @@ -695,6 +690,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, pr_err("Compression failed! err=%d\n", ret); goto out; } + src = zstrm->buffer; if (unlikely(clen > max_zpage_size)) { clen = PAGE_SIZE; @@ -702,38 +698,60 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, src = uncmem; } - handle = zs_malloc(meta->mem_pool, clen); + /* + * handle allocation has 2 paths: + * a) fast path is executed with preemption disabled (for + * per-cpu streams) and has __GFP_DIRECT_RECLAIM bit clear, + * since we can't sleep; + * b) slow path enables preemption and attempts to allocate + * the page with __GFP_DIRECT_RECLAIM bit set. we have to + * put per-cpu compression stream and, thus, to re-do + * the compression once handle is allocated. + * + * if we have a 'non-null' handle here then we are coming + * from the slow path and handle has already been allocated. + */ + if (!handle) + handle = zs_malloc(meta->mem_pool, clen, + + __GFP_NOWARN | + __GFP_HIGHMEM); if (!handle) { - if (printk_timed_ratelimit(&zram_rs_time, - ALLOC_ERROR_LOG_RATE_MS)) - pr_info("Error allocating memory for compressed page: %u, size=%zu\n", - index, clen); + zcomp_strm_release(zram->comp, zstrm); + zstrm = NULL; + handle = zs_malloc(meta->mem_pool, clen, + GFP_NOIO | __GFP_HIGHMEM); + if (handle) + goto compress_again; + + pr_err("Error allocating memory for compressed page: %u, size=%zu\n", + index, clen); ret = -ENOMEM; goto out; } alloced_pages = zs_get_total_pages(meta->mem_pool); + update_used_max(zram, alloced_pages); + if (zram->limit_pages && alloced_pages > zram->limit_pages) { zs_free(meta->mem_pool, handle); ret = -ENOMEM; goto out; } - update_used_max(zram, alloced_pages); - cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO); if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) { src = kmap_atomic(page); - memcpy(cmem, src, PAGE_SIZE); + copy_page(cmem, src); kunmap_atomic(src); } else { memcpy(cmem, src, clen); } zcomp_strm_release(zram->comp, zstrm); - locked = false; + zstrm = NULL; zs_unmap_object(meta->mem_pool, handle); /* @@ -751,36 +769,13 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, atomic64_add(clen, &zram->stats.compr_data_size); atomic64_inc(&zram->stats.pages_stored); out: - if (locked) + if (zstrm) zcomp_strm_release(zram->comp, zstrm); if (is_partial_io(bvec)) kfree(uncmem); return ret; } -static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, - int offset, int rw) -{ - int ret; - - if (rw == READ) { - atomic64_inc(&zram->stats.num_reads); - ret = zram_bvec_read(zram, bvec, index, offset); - } else { - atomic64_inc(&zram->stats.num_writes); - ret = zram_bvec_write(zram, bvec, index, offset); - } - - if (unlikely(ret)) { - if (rw == READ) - atomic64_inc(&zram->stats.failed_reads); - else - atomic64_inc(&zram->stats.failed_writes); - } - - return ret; -} - /* * zram_bio_discard - handler on discard request * @index: physical block index in PAGE_SIZE units @@ -820,217 +815,99 @@ static void zram_bio_discard(struct zram *zram, u32 index, } } -static void zram_reset_device(struct zram *zram) +static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, + int offset, int rw) { - struct zram_meta *meta; - struct zcomp *comp; - u64 disksize; - down_write(&zram->init_lock); + int ret; +/* + generic_start_io_acct(rw, bvec->bv_len >> SECTOR_SHIFT, + &zram->disk->part0); +*/ + if (rw == READ) { + atomic64_inc(&zram->stats.num_reads); + ret = zram_bvec_read(zram, bvec, index, offset); + } else { + atomic64_inc(&zram->stats.num_writes); + ret = zram_bvec_write(zram, bvec, index, offset); + } +/* + generic_end_io_acct(rw, &zram->disk->part0, start_time); +*/ + if (unlikely(ret)) { + if (rw == READ) + atomic64_inc(&zram->stats.failed_reads); + else + atomic64_inc(&zram->stats.failed_writes); + } - zram->limit_pages = 0; + return ret; +} - if (!init_done(zram)) { - up_write(&zram->init_lock); +static void __zram_make_request(struct zram *zram, struct bio *bio) +{ + int offset, rw; + u32 index; + struct bio_vec bvec; + struct bvec_iter iter; + + index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; + offset = (bio->bi_iter.bi_sector & + (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; + + if (unlikely(bio->bi_rw & REQ_DISCARD)) { + zram_bio_discard(zram, index, offset, bio); + bio_endio(bio, 0); return; } - meta = zram->meta; - comp = zram->comp; - disksize = zram->disksize; - /* - * Refcount will go down to 0 eventually and r/w handler - * cannot handle further I/O so it will bail out by - * check zram_meta_get. - */ - zram_meta_put(zram); - /* - * We want to free zram_meta in process context to avoid - * deadlock between reclaim path and any other locks. - */ - wait_event(zram->io_done, atomic_read(&zram->refcount) == 0); + rw = bio_data_dir(bio); + bio_for_each_segment(bvec, bio, iter) { + int max_transfer_size = PAGE_SIZE - offset; - /* Reset stats */ - memset(&zram->stats, 0, sizeof(zram->stats)); - zram->disksize = 0; - zram->max_comp_streams = 1; + if (bvec.bv_len > max_transfer_size) { + /* + * zram_bvec_rw() can only make operation on a single + * zram page. Split the bio vector. + */ + struct bio_vec bv; - set_capacity(zram->disk, 0); - part_stat_set_all(&zram->disk->part0, 0); + bv.bv_page = bvec.bv_page; + bv.bv_len = max_transfer_size; + bv.bv_offset = bvec.bv_offset; - up_write(&zram->init_lock); - /* I/O operation under all of CPU are done so let's free */ - zram_meta_free(meta, disksize); - zcomp_destroy(comp); + if (zram_bvec_rw(zram, &bv, index, offset, rw) < 0) + goto out; + + bv.bv_len = bvec.bv_len - max_transfer_size; + bv.bv_offset += max_transfer_size; + if (zram_bvec_rw(zram, &bv, index + 1, 0, rw) < 0) + goto out; + } else + if (zram_bvec_rw(zram, &bvec, index, offset, rw) < 0) + goto out; + + update_position(&index, &offset, &bvec); + } + + bio_endio(bio, 0); + return; + +out: + bio_io_error(bio); } -static ssize_t disksize_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +/* + * Handler function for all zram I/O requests. + */ +static void zram_make_request(struct request_queue *queue, struct bio *bio) { - u64 disksize; - struct zcomp *comp; - struct zram_meta *meta; - struct zram *zram = dev_to_zram(dev); - int err; + struct zram *zram = queue->queuedata; - disksize = memparse(buf, NULL); - if (!disksize) - return -EINVAL; + if (unlikely(!zram_meta_get(zram))) + goto error; - disksize = PAGE_ALIGN(disksize); - meta = zram_meta_alloc(zram->disk->first_minor, disksize); - if (!meta) - return -ENOMEM; - comp = zcomp_create(zram->compressor, zram->max_comp_streams); - if (IS_ERR(comp)) { - pr_info("Cannot initialise %s compressing backend\n", - zram->compressor); - err = PTR_ERR(comp); - goto out_free_meta; - } - - down_write(&zram->init_lock); - if (init_done(zram)) { - pr_info("Cannot change disksize for initialized device\n"); - err = -EBUSY; - goto out_destroy_comp; - } - - init_waitqueue_head(&zram->io_done); - atomic_set(&zram->refcount, 1); - zram->meta = meta; - zram->comp = comp; - zram->disksize = disksize; - set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); - up_write(&zram->init_lock); - - /* - * Revalidate disk out of the init_lock to avoid lockdep splat. - * It's okay because disk's capacity is protected by init_lock - * so that revalidate_disk always sees up-to-date capacity. - */ - revalidate_disk(zram->disk); - - return len; - -out_destroy_comp: - up_write(&zram->init_lock); - zcomp_destroy(comp); -out_free_meta: - zram_meta_free(meta, disksize); - return err; -} - -static ssize_t reset_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) -{ - int ret; - unsigned short do_reset; - struct zram *zram; - struct block_device *bdev; - - zram = dev_to_zram(dev); - bdev = bdget_disk(zram->disk, 0); - - if (!bdev) - return -ENOMEM; - - mutex_lock(&bdev->bd_mutex); - /* Do not reset an active device! */ - if (bdev->bd_openers) { - ret = -EBUSY; - goto out; - } - - ret = kstrtou16(buf, 10, &do_reset); - if (ret) - goto out; - - if (!do_reset) { - ret = -EINVAL; - goto out; - } - - /* Make sure all pending I/O is finished */ - fsync_bdev(bdev); - zram_reset_device(zram); - - mutex_unlock(&bdev->bd_mutex); - revalidate_disk(zram->disk); - bdput(bdev); - - return len; - -out: - mutex_unlock(&bdev->bd_mutex); - bdput(bdev); - return ret; -} - -static void __zram_make_request(struct zram *zram, struct bio *bio) -{ - int offset, rw; - u32 index; - struct bio_vec bvec; - struct bvec_iter iter; - - index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; - offset = (bio->bi_iter.bi_sector & - (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; - - if (unlikely(bio->bi_rw & REQ_DISCARD)) { - zram_bio_discard(zram, index, offset, bio); - bio_endio(bio, 0); - return; - } - - rw = bio_data_dir(bio); - bio_for_each_segment(bvec, bio, iter) { - int max_transfer_size = PAGE_SIZE - offset; - - if (bvec.bv_len > max_transfer_size) { - /* - * zram_bvec_rw() can only make operation on a single - * zram page. Split the bio vector. - */ - struct bio_vec bv; - - bv.bv_page = bvec.bv_page; - bv.bv_len = max_transfer_size; - bv.bv_offset = bvec.bv_offset; - - if (zram_bvec_rw(zram, &bv, index, offset, rw) < 0) - goto out; - - bv.bv_len = bvec.bv_len - max_transfer_size; - bv.bv_offset += max_transfer_size; - if (zram_bvec_rw(zram, &bv, index + 1, 0, rw) < 0) - goto out; - } else - if (zram_bvec_rw(zram, &bvec, index, offset, rw) < 0) - goto out; - - update_position(&index, &offset, &bvec); - } - - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio_endio(bio, 0); - return; - -out: - bio_io_error(bio); -} - -/* - * Handler function for all zram I/O requests. - */ -static void zram_make_request(struct request_queue *queue, struct bio *bio) -{ - struct zram *zram = queue->queuedata; - - if (unlikely(!zram_meta_get(zram))) - goto error; if (!valid_io_request(zram, bio->bi_iter.bi_sector, bio->bi_iter.bi_size)) { @@ -1045,6 +922,7 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio) zram_meta_put(zram); error: bio_io_error(bio); + return; } static void zram_slot_free_notify(struct block_device *bdev, @@ -1104,80 +982,184 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector, return err; } -static const struct block_device_operations zram_devops = { - .swap_slot_free_notify = zram_slot_free_notify, - .rw_page = zram_rw_page, - .owner = THIS_MODULE -}; +static void zram_reset_device(struct zram *zram) +{ + struct zram_meta *meta; + struct zcomp *comp; + u64 disksize; -static DEVICE_ATTR_WO(compact); -static DEVICE_ATTR_RW(disksize); -static DEVICE_ATTR_RO(initstate); -static DEVICE_ATTR_WO(reset); -static DEVICE_ATTR_RO(orig_data_size); -static DEVICE_ATTR_RO(mem_used_total); -static DEVICE_ATTR_RW(mem_limit); -static DEVICE_ATTR_RW(mem_used_max); -static DEVICE_ATTR_RW(max_comp_streams); -static DEVICE_ATTR_RW(comp_algorithm); + down_write(&zram->init_lock); -static ssize_t io_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) + zram->limit_pages = 0; + + if (!init_done(zram)) { + up_write(&zram->init_lock); + return; + } + + meta = zram->meta; + comp = zram->comp; + disksize = zram->disksize; + /* + * Refcount will go down to 0 eventually and r/w handler + * cannot handle further I/O so it will bail out by + * check zram_meta_get. + */ + zram_meta_put(zram); + /* + * We want to free zram_meta in process context to avoid + * deadlock between reclaim path and any other locks. + */ + wait_event(zram->io_done, atomic_read(&zram->refcount) == 0); + + /* Reset stats */ + memset(&zram->stats, 0, sizeof(zram->stats)); + zram->disksize = 0; + + set_capacity(zram->disk, 0); + part_stat_set_all(&zram->disk->part0, 0); + + up_write(&zram->init_lock); + /* I/O operation under all of CPU are done so let's free */ + zram_meta_free(meta, disksize); + zcomp_destroy(comp); +} + +static ssize_t disksize_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { + u64 disksize; + struct zcomp *comp; + struct zram_meta *meta; struct zram *zram = dev_to_zram(dev); - ssize_t ret; + int err; - down_read(&zram->init_lock); - ret = scnprintf(buf, PAGE_SIZE, - "%8llu %8llu %8llu %8llu\n", - (u64)atomic64_read(&zram->stats.failed_reads), - (u64)atomic64_read(&zram->stats.failed_writes), - (u64)atomic64_read(&zram->stats.invalid_io), - (u64)atomic64_read(&zram->stats.notify_free)); - up_read(&zram->init_lock); + disksize = memparse(buf, NULL); + if (!disksize) + return -EINVAL; - return ret; + disksize = PAGE_ALIGN(disksize); + meta = zram_meta_alloc(zram->disk->disk_name, disksize); + if (!meta) + return -ENOMEM; + + comp = zcomp_create(zram->compressor); + if (IS_ERR(comp)) { + pr_err("Cannot initialise %s compressing backend\n", + zram->compressor); + err = PTR_ERR(comp); + goto out_free_meta; + } + + down_write(&zram->init_lock); + if (init_done(zram)) { + pr_info("Cannot change disksize for initialized device\n"); + err = -EBUSY; + goto out_destroy_comp; + } + + init_waitqueue_head(&zram->io_done); + atomic_set(&zram->refcount, 1); + zram->meta = meta; + zram->comp = comp; + zram->disksize = disksize; + set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); + up_write(&zram->init_lock); + + /* + * Revalidate disk out of the init_lock to avoid lockdep splat. + * It's okay because disk's capacity is protected by init_lock + * so that revalidate_disk always sees up-to-date capacity. + */ + revalidate_disk(zram->disk); + + return len; + +out_destroy_comp: + up_write(&zram->init_lock); + zcomp_destroy(comp); +out_free_meta: + zram_meta_free(meta, disksize); + return err; } -static ssize_t mm_stat_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { - struct zram *zram = dev_to_zram(dev); - u64 orig_size, mem_used = 0; - long max_used; - ssize_t ret; + int ret; + unsigned short do_reset; + struct zram *zram; + struct block_device *bdev; - down_read(&zram->init_lock); - if (init_done(zram)) - mem_used = zs_get_total_pages(zram->meta->mem_pool); + ret = kstrtou16(buf, 10, &do_reset); + if (ret) + return ret; - orig_size = atomic64_read(&zram->stats.pages_stored); - max_used = atomic_long_read(&zram->stats.max_used_pages); + if (!do_reset) + return -EINVAL; - ret = scnprintf(buf, PAGE_SIZE, - "%8llu %8llu %8llu %8lu %8ld %8llu %8llu\n", - orig_size << PAGE_SHIFT, - (u64)atomic64_read(&zram->stats.compr_data_size), - mem_used << PAGE_SHIFT, - zram->limit_pages << PAGE_SHIFT, - max_used << PAGE_SHIFT, - (u64)atomic64_read(&zram->stats.zero_pages), - (u64)atomic64_read(&zram->stats.num_migrated)); - up_read(&zram->init_lock); + zram = dev_to_zram(dev); + bdev = bdget_disk(zram->disk, 0); + if (!bdev) + return -ENOMEM; + + mutex_lock(&bdev->bd_mutex); + /* Do not reset an active device or claimed device */ + if (bdev->bd_openers || zram->claim) { + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); + return -EBUSY; + } + + /* From now on, anyone can't open /dev/zram[0-9] */ + zram->claim = true; + mutex_unlock(&bdev->bd_mutex); + + /* Make sure all the pending I/O are finished */ + fsync_bdev(bdev); + zram_reset_device(zram); + revalidate_disk(zram->disk); + bdput(bdev); + + mutex_lock(&bdev->bd_mutex); + zram->claim = false; + mutex_unlock(&bdev->bd_mutex); + + return len; +} + +static int zram_open(struct block_device *bdev, fmode_t mode) +{ + int ret = 0; + struct zram *zram; + + WARN_ON(!mutex_is_locked(&bdev->bd_mutex)); + + zram = bdev->bd_disk->private_data; + /* zram was claimed to reset so open request fails */ + if (zram->claim) + ret = -EBUSY; return ret; } -static DEVICE_ATTR_RO(io_stat); -static DEVICE_ATTR_RO(mm_stat); -ZRAM_ATTR_RO(num_reads); -ZRAM_ATTR_RO(num_writes); -ZRAM_ATTR_RO(failed_reads); -ZRAM_ATTR_RO(failed_writes); -ZRAM_ATTR_RO(invalid_io); -ZRAM_ATTR_RO(notify_free); -ZRAM_ATTR_RO(zero_pages); -ZRAM_ATTR_RO(compr_data_size); +static const struct block_device_operations zram_devops = { + .open = zram_open, + .swap_slot_free_notify = zram_slot_free_notify, + .rw_page = zram_rw_page, + .owner = THIS_MODULE +}; + +static DEVICE_ATTR_WO(compact); +static DEVICE_ATTR_RW(disksize); +static DEVICE_ATTR_RO(initstate); +static DEVICE_ATTR_WO(reset); +static DEVICE_ATTR_RO(orig_data_size); +static DEVICE_ATTR_RO(mem_used_total); +static DEVICE_ATTR_RW(mem_limit); +static DEVICE_ATTR_RW(mem_used_max); +static DEVICE_ATTR_RW(max_comp_streams); +static DEVICE_ATTR_RW(comp_algorithm); static struct attribute *zram_disk_attrs[] = { &dev_attr_disksize.attr, @@ -1207,10 +1189,24 @@ static struct attribute_group zram_disk_attr_group = { .attrs = zram_disk_attrs, }; -static int create_device(struct zram *zram, int device_id) +/* + * Allocate and initialize new zram device. the function returns + * '>= 0' device_id upon success, and negative value otherwise. + */ +static int zram_add(void) { + struct zram *zram; struct request_queue *queue; - int ret = -ENOMEM; + int ret, device_id; + + zram = kzalloc(sizeof(struct zram), GFP_KERNEL); + if (!zram) + return -ENOMEM; + + ret = idr_alloc(&zram_index_idr, zram, 0, 0, GFP_KERNEL); + if (ret < 0) + goto out_free_dev; + device_id = ret; init_rwsem(&zram->init_lock); @@ -1218,15 +1214,16 @@ static int create_device(struct zram *zram, int device_id) if (!queue) { pr_err("Error allocating disk queue for device %d\n", device_id); - goto out; + ret = -ENOMEM; + goto out_free_idr; } blk_queue_make_request(queue, zram_make_request); - /* gendisk structure */ + /* gendisk structure */ zram->disk = alloc_disk(1); if (!zram->disk) { - pr_warn("Error allocating disk structure for device %d\n", + pr_err("Error allocating disk structure for device %d\n", device_id); ret = -ENOMEM; goto out_free_queue; @@ -1240,7 +1237,6 @@ static int create_device(struct zram *zram, int device_id) zram->disk->private_data = zram; snprintf(zram->disk->disk_name, 16, "zram%d", device_id); - __set_bit(QUEUE_FLAG_FAST, &queue->queue_flags); /* Actual capacity set using syfs (/sys/block/zram/disksize */ set_capacity(zram->disk, 0); /* zram devices sort of resembles non-rotational disks */ @@ -1256,7 +1252,7 @@ static int create_device(struct zram *zram, int device_id) blk_queue_io_min(zram->disk->queue, PAGE_SIZE); blk_queue_io_opt(zram->disk->queue, PAGE_SIZE); zram->disk->queue->limits.discard_granularity = PAGE_SIZE; - zram->disk->queue->limits.max_discard_sectors = UINT_MAX; + blk_queue_max_discard_sectors(zram->disk->queue, UINT_MAX); /* * zram_bio_discard() will clear all logical blocks if logical block * size is identical with physical block size(PAGE_SIZE). But if it is @@ -1276,98 +1272,184 @@ static int create_device(struct zram *zram, int device_id) ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj, &zram_disk_attr_group); if (ret < 0) { - pr_warn("Error creating sysfs group"); + pr_err("Error creating sysfs group for device %d\n", + device_id); goto out_free_disk; } strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); zram->meta = NULL; - zram->max_comp_streams = 1; - return 0; + + pr_info("Added device: %s\n", zram->disk->disk_name); + return device_id; out_free_disk: del_gendisk(zram->disk); put_disk(zram->disk); out_free_queue: blk_cleanup_queue(queue); -out: +out_free_idr: + idr_remove(&zram_index_idr, device_id); +out_free_dev: + kfree(zram); return ret; } -static void destroy_devices(unsigned int nr) +static int zram_remove(struct zram *zram) +{ + struct block_device *bdev; + + bdev = bdget_disk(zram->disk, 0); + if (!bdev) + return -ENOMEM; + + mutex_lock(&bdev->bd_mutex); + if (bdev->bd_openers || zram->claim) { + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); + return -EBUSY; + } + + zram->claim = true; + mutex_unlock(&bdev->bd_mutex); + + /* + * Remove sysfs first, so no one will perform a disksize + * store while we destroy the devices. This also helps during + * hot_remove -- zram_reset_device() is the last holder of + * ->init_lock, no later/concurrent disksize_store() or any + * other sysfs handlers are possible. + */ + sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, + &zram_disk_attr_group); + + /* Make sure all the pending I/O are finished */ + fsync_bdev(bdev); + zram_reset_device(zram); + bdput(bdev); + + pr_info("Removed device: %s\n", zram->disk->disk_name); + + blk_cleanup_queue(zram->disk->queue); + del_gendisk(zram->disk); + put_disk(zram->disk); + kfree(zram); + return 0; +} + +/* zram-control sysfs attributes */ +static ssize_t hot_add_show(struct class *class, + struct class_attribute *attr, + char *buf) +{ + int ret; + + mutex_lock(&zram_index_mutex); + ret = zram_add(); + mutex_unlock(&zram_index_mutex); + + if (ret < 0) + return ret; + return scnprintf(buf, PAGE_SIZE, "%d\n", ret); +} + +static ssize_t hot_remove_store(struct class *class, + struct class_attribute *attr, + const char *buf, + size_t count) { struct zram *zram; - unsigned int i; + int ret, dev_id; - for (i = 0; i < nr; i++) { - zram = &zram_devices[i]; - /* - * Remove sysfs first, so no one will perform a disksize - * store while we destroy the devices - */ - sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, - &zram_disk_attr_group); + /* dev_id is gendisk->first_minor, which is `int' */ + ret = kstrtoint(buf, 10, &dev_id); + if (ret) + return ret; + if (dev_id < 0) + return -EINVAL; - zram_reset_device(zram); + mutex_lock(&zram_index_mutex); - blk_cleanup_queue(zram->disk->queue); - del_gendisk(zram->disk); - put_disk(zram->disk); + zram = idr_find(&zram_index_idr, dev_id); + if (zram) { + ret = zram_remove(zram); + idr_remove(&zram_index_idr, dev_id); + } else { + ret = -ENODEV; } - kfree(zram_devices); + mutex_unlock(&zram_index_mutex); + return ret ? ret : count; +} + +static struct class_attribute zram_control_class_attrs[] = { + __ATTR_RO(hot_add), + __ATTR_WO(hot_remove), + __ATTR_NULL, +}; + +static struct class zram_control_class = { + .name = "zram-control", + .owner = THIS_MODULE, + .class_attrs = zram_control_class_attrs, +}; + +static int zram_remove_cb(int id, void *ptr, void *data) +{ + zram_remove(ptr); + return 0; +} + +static void destroy_devices(void) +{ + class_unregister(&zram_control_class); + idr_for_each(&zram_index_idr, &zram_remove_cb, NULL); + idr_destroy(&zram_index_idr); unregister_blkdev(zram_major, "zram"); - pr_info("Destroyed %u device(s)\n", nr); } static int __init zram_init(void) { - int ret, dev_id; + int ret; - if (num_devices > max_num_devices) { - pr_warn("Invalid value for num_devices: %u\n", - num_devices); - return -EINVAL; + ret = class_register(&zram_control_class); + if (ret) { + pr_err("Unable to register zram-control class\n"); + return ret; } zram_major = register_blkdev(0, "zram"); if (zram_major <= 0) { - pr_warn("Unable to get major number\n"); + pr_err("Unable to get major number\n"); + class_unregister(&zram_control_class); return -EBUSY; } - /* Allocate the device array and initialize each one */ - zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL); - if (!zram_devices) { - unregister_blkdev(zram_major, "zram"); - return -ENOMEM; - } - - for (dev_id = 0; dev_id < num_devices; dev_id++) { - ret = create_device(&zram_devices[dev_id], dev_id); - if (ret) + while (num_devices != 0) { + mutex_lock(&zram_index_mutex); + ret = zram_add(); + mutex_unlock(&zram_index_mutex); + if (ret < 0) goto out_error; + num_devices--; } - show_mem_notifier_register(&zram_show_mem_notifier_block); - pr_info("Created %u device(s) ...\n", num_devices); - return 0; out_error: - destroy_devices(dev_id); + destroy_devices(); return ret; } static void __exit zram_exit(void) { - destroy_devices(num_devices); + destroy_devices(); } module_init(zram_init); module_exit(zram_exit); module_param(num_devices, uint, 0); -MODULE_PARM_DESC(num_devices, "Number of zram devices"); +MODULE_PARM_DESC(num_devices, "Number of pre-created zram devices"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Nitin Gupta "); diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index 570c598f4ce9a..c50313bd5518b 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -2,6 +2,7 @@ * Compressed RAM block device * * Copyright (C) 2008, 2009, 2010 Nitin Gupta + * Copyright (C) 2019 XiaoMi, Inc. * 2012, 2013 Minchan Kim * * This code is released using a dual license strategy: BSD/GPL @@ -20,12 +21,6 @@ #include "zcomp.h" -/* - * Some arbitrary value. This is just to catch - * invalid value for num_devices module parameter. - */ -static const unsigned max_num_devices = 32; - /*-- Configurable parameters */ /* @@ -84,7 +79,6 @@ struct zram_stats { atomic64_t compr_data_size; /* compressed size of pages stored */ atomic64_t num_reads; /* failed + successful */ atomic64_t num_writes; /* --do-- */ - atomic64_t num_migrated; /* no. of migrated object */ atomic64_t failed_reads; /* can happen when memory is too low */ atomic64_t failed_writes; /* can happen when memory is too low */ atomic64_t invalid_io; /* non-page-aligned I/O requests */ @@ -109,7 +103,6 @@ struct zram { * the number of pages zram can consume for storing compressed data */ unsigned long limit_pages; - int max_comp_streams; struct zram_stats stats; atomic_t refcount; /* refcount for zram_meta */ @@ -121,5 +114,9 @@ struct zram { */ u64 disksize; /* bytes */ char compressor[10]; + /* + * zram is claimed so open request will be failed + */ + bool claim; /* Protected by bdev->bd_mutex */ }; #endif diff --git a/drivers/clk/msm/mdss/mdss-pll.c b/drivers/clk/msm/mdss/mdss-pll.c index a47a9d6848e95..b1e0f29208f8f 100644 --- a/drivers/clk/msm/mdss/mdss-pll.c +++ b/drivers/clk/msm/mdss/mdss-pll.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -211,9 +212,15 @@ static int mdss_pll_clock_register(struct platform_device *pdev, return rc; } +#if defined(CONFIG_PROJECT_SAKURA) || defined(CONFIG_PROJECT_DAISY) +extern char *saved_command_line; +#endif static int mdss_pll_probe(struct platform_device *pdev) { int rc = 0; +#if defined(CONFIG_PROJECT_SAKURA) || defined(CONFIG_PROJECT_DAISY) + int len = 0; +#endif const char *label; struct resource *pll_base_reg; struct resource *phy_base_reg; @@ -249,6 +256,29 @@ static int mdss_pll_probe(struct platform_device *pdev) pll_res->index = 0; } +#if defined(CONFIG_PROJECT_SAKURA) || defined(CONFIG_PROJECT_DAISY) + len = strlen(saved_command_line); + if (strnstr(saved_command_line, "ili7807_fhdplus_video", len)){ + + pll_res->ssc_en = 0; + printk("[sunbo] panel: CDY_ili7807.\n"); + + } else if (strnstr(saved_command_line, "hx8399c_fhdplus_video", len)){ + + pll_res->ssc_en = 1; + pll_res->ssc_freq = 30000; + pll_res->ssc_ppm = 5000; + pll_res->ssc_center = false; + printk("[sunbo] panel: CSOT_hx8399c.\n"); + } else if (strnstr(saved_command_line, "otm1911_fhdplus_video", len)){ + pll_res->ssc_en = 1; + pll_res->ssc_freq = 30000; + pll_res->ssc_ppm = 5000; + pll_res->ssc_center = false; + printk("[sunbo] panel: TIANMA_otm1911.\n"); + } + +#else pll_res->ssc_en = of_property_read_bool(pdev->dev.of_node, "qcom,dsi-pll-ssc-en"); @@ -269,6 +299,9 @@ static int mdss_pll_probe(struct platform_device *pdev) if (label && !strcmp(label, "center-spread")) pll_res->ssc_center = true; } +#endif + printk("[sunbo] SSC state: ssc_en = %d, frequency-hz = %u, ssc-ppm = %u, ssc_center = %d.\n", + pll_res->ssc_en, pll_res->ssc_freq, pll_res->ssc_ppm, pll_res->ssc_center); pll_base_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_base"); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 164ee9b4646b0..47220e0a40360 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -989,14 +989,6 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) struct gpio_chip *chip; int status = -EINVAL; - /* GPIOs used for IRQs shall not be set as output */ - if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) { - gpiod_err(desc, - "%s: tried to set a GPIO tied to an IRQ as output\n", - __func__); - return -EIO; - } - /* Open drain pin should not be driven to 1 */ if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) return gpiod_direction_input(desc); diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 78c1c99721b97..3ebe5e60191e2 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -208,6 +208,7 @@ source "drivers/input/touchscreen/Kconfig" source "drivers/input/misc/Kconfig" +source "drivers/input/fingerprint/Kconfig" source "drivers/input/sensors/smi130/Kconfig" endif diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 7d4786289ff7c..e26de1babc410 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_INPUT_MOUSE) += mouse/ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/ obj-$(CONFIG_INPUT_TABLET) += tablet/ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ +obj-$(CONFIG_INPUT_FINGERPRINT) += fingerprint/ obj-$(CONFIG_INPUT_MISC) += misc/ obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o diff --git a/drivers/input/fingerprint/Kconfig b/drivers/input/fingerprint/Kconfig new file mode 100644 index 0000000000000..80cce14f961a2 --- /dev/null +++ b/drivers/input/fingerprint/Kconfig @@ -0,0 +1,7 @@ +config INPUT_FINGERPRINT + tristate "Fingerprint driver support" + help + Say Y here to enable goodix fingerprint driver support! +source "drivers/input/fingerprint/goodix/Kconfig" +source "drivers/input/fingerprint/fpc/Kconfig" +source "drivers/input/fingerprint/goodix_e7/Kconfig" diff --git a/drivers/input/fingerprint/Makefile b/drivers/input/fingerprint/Makefile new file mode 100644 index 0000000000000..1b7c1ee0d8fbf --- /dev/null +++ b/drivers/input/fingerprint/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208) += goodix/ +obj-$(CONFIG_FINGERPRINT_FPC1020) += fpc/ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_E7) += goodix_e7/ diff --git a/drivers/input/fingerprint/fpc/Kconfig b/drivers/input/fingerprint/fpc/Kconfig new file mode 100644 index 0000000000000..749075beb7cae --- /dev/null +++ b/drivers/input/fingerprint/fpc/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_FPC1020 + tristate "FingerPrint Cards fingerprint drvier support" + depends on INPUT_FINGERPRINT + help + Say Y here to enable goodix fingerprint driver support! diff --git a/drivers/input/fingerprint/fpc/Makefile b/drivers/input/fingerprint/fpc/Makefile new file mode 100644 index 0000000000000..fc88d4c1e3043 --- /dev/null +++ b/drivers/input/fingerprint/fpc/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FINGERPRINT_FPC1020) += fpc1020_platform_tee.o diff --git a/drivers/input/fingerprint/fpc/fpc1020_platform_tee.c b/drivers/input/fingerprint/fpc/fpc1020_platform_tee.c new file mode 100644 index 0000000000000..96e66c475c6ff --- /dev/null +++ b/drivers/input/fingerprint/fpc/fpc1020_platform_tee.c @@ -0,0 +1,799 @@ +/* + * FPC1020 Fingerprint sensor device driver + * + * This driver will control the platform resources that the FPC fingerprint + * sensor needs to operate. The major things are probing the sensor to check + * that it is actually connected and let the Kernel know this and with that also + * enabling and disabling of regulators, controlling GPIOs such as sensor reset + * line, sensor IRQ line. + * + * The driver will expose most of its available functionality in sysfs which + * enables dynamic control of these features from eg. a user space process. + * + * The sensor's IRQ events will be pushed to Kernel's event handling system and + * are exposed in the drivers event node. + * + * This driver will NOT send any commands to the sensor it only controls the + * electrical parts. + * + * + * Copyright (c) 2015 Fingerprint Cards AB + * Copyright (C) 2019 XiaoMi, Inc. + * + * 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 +#include +#include + + + +#define FPC_TTW_HOLD_TIME 2000 +#define FP_UNLOCK_REJECTION_TIMEOUT (FPC_TTW_HOLD_TIME - 500) + + +#define RESET_LOW_SLEEP_MIN_US 5000 +#define RESET_LOW_SLEEP_MAX_US (RESET_LOW_SLEEP_MIN_US + 100) +#define RESET_HIGH_SLEEP1_MIN_US 100 +#define RESET_HIGH_SLEEP1_MAX_US (RESET_HIGH_SLEEP1_MIN_US + 100) +#define RESET_HIGH_SLEEP2_MIN_US 5000 +#define RESET_HIGH_SLEEP2_MAX_US (RESET_HIGH_SLEEP2_MIN_US + 100) +#define PWR_ON_SLEEP_MIN_US 100 +#define PWR_ON_SLEEP_MAX_US (PWR_ON_SLEEP_MIN_US + 900) + +#define NUM_PARAMS_REG_ENABLE_SET 2 + +static const char * const pctl_names[] = { + "fpc1020_reset_reset", + "fpc1020_reset_active", + "fpc1020_irq_active", +}; + +struct vreg_config { + char *name; + unsigned long vmin; + unsigned long vmax; + int ua_load; +}; + +static const struct vreg_config const vreg_conf[] = { + { "vdd_ana", 1800000UL, 1800000UL, 6000, }, + { "vcc_spi", 1800000UL, 1800000UL, 10, }, + { "vdd_io", 1800000UL, 1800000UL, 6000, }, +}; + +struct fpc1020_data { + struct device *dev; + + struct pinctrl *fingerprint_pinctrl; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; + struct regulator *vreg[ARRAY_SIZE(vreg_conf)]; + + struct wake_lock ttw_wl; + int irq_gpio; + int rst_gpio; + struct mutex lock; /* To set/get exported values in sysfs */ + bool prepared; + bool compatible_enabled; + atomic_t wakeup_enabled; /* Used both in ISR and non-ISR */ + + struct notifier_block fb_notifier; + bool fb_black; + bool wait_finger_down; + struct work_struct work; + +}; + +static irqreturn_t fpc1020_irq_handler(int irq, void *handle); +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, + const char *label, int *gpio); +static int hw_reset(struct fpc1020_data *fpc1020); + +static int vreg_setup(struct fpc1020_data *fpc1020, const char *name, + bool enable) +{ + size_t i; + int rc; + struct regulator *vreg; + struct device *dev = fpc1020->dev; + + for (i = 0; i < ARRAY_SIZE(fpc1020->vreg); i++) { + const char *n = vreg_conf[i].name; + + if (!strncmp(n, name, strlen(n))) + goto found; + } + + dev_err(dev, "Regulator %s not found\n", name); + + return -EINVAL; + +found: + vreg = fpc1020->vreg[i]; + if (enable) { + if (!vreg) { + vreg = regulator_get(dev, name); + if (IS_ERR(vreg)) { + dev_err(dev, "Unable to get %s\n", name); + return PTR_ERR(vreg); + } + } + + if (regulator_count_voltages(vreg) > 0) { + rc = regulator_set_voltage(vreg, vreg_conf[i].vmin, + vreg_conf[i].vmax); + if (rc) + dev_err(dev, + "Unable to set voltage on %s, %d\n", + name, rc); + } + + rc = regulator_set_optimum_mode(vreg, vreg_conf[i].ua_load); + if (rc < 0) + dev_err(dev, "Unable to set current on %s, %d\n", + name, rc); + + rc = regulator_enable(vreg); + if (rc) { + dev_err(dev, "error enabling %s: %d\n", name, rc); + regulator_put(vreg); + vreg = NULL; + } + fpc1020->vreg[i] = vreg; + } else { + if (vreg) { + if (regulator_is_enabled(vreg)) { + regulator_disable(vreg); + dev_dbg(dev, "disabled %s\n", name); + } + regulator_put(vreg); + fpc1020->vreg[i] = NULL; + } + rc = 0; + } + + return rc; +} + +/** + * sysfs node for controlling clocks. + * + * This is disabled in platform variant of this driver but kept for + * backwards compatibility. Only prints a debug print that it is + * disabled. + */ +static ssize_t clk_enable_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + dev_dbg(dev, + "clk_enable sysfs node not enabled in platform driver\n"); + + return count; +} +static DEVICE_ATTR(clk_enable, S_IWUSR, NULL, clk_enable_set); + +/** + * Will try to select the set of pins (GPIOS) defined in a pin control node of + * the device tree named @p name. + * + * The node can contain several eg. GPIOs that is controlled when selecting it. + * The node may activate or deactivate the pins it contains, the action is + * defined in the device tree node itself and not here. The states used + * internally is fetched at probe time. + * + * @see pctl_names + * @see fpc1020_probe + */ +static int select_pin_ctl(struct fpc1020_data *fpc1020, const char *name) +{ + size_t i; + int rc; + struct device *dev = fpc1020->dev; + + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) { + const char *n = pctl_names[i]; + + if (!strncmp(n, name, strlen(n))) { + rc = pinctrl_select_state(fpc1020->fingerprint_pinctrl, + fpc1020->pinctrl_state[i]); + if (rc) + dev_err(dev, "cannot select '%s'\n", name); + else + dev_dbg(dev, "Selected '%s'\n", name); + goto exit; + } + } + + rc = -EINVAL; + dev_err(dev, "%s:'%s' not found\n", __func__, name); + +exit: + return rc; +} + +static ssize_t pinctl_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + int rc; + + mutex_lock(&fpc1020->lock); + rc = select_pin_ctl(fpc1020, buf); + mutex_unlock(&fpc1020->lock); + + return rc ? rc : count; +} +static DEVICE_ATTR(pinctl_set, S_IWUSR, NULL, pinctl_set); + +static ssize_t regulator_enable_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + char op; + char name[16]; + int rc; + bool enable; + + if (NUM_PARAMS_REG_ENABLE_SET != sscanf(buf, "%15[^,],%c", name, &op)) + return -EINVAL; + if (op == 'e') + enable = true; + else if (op == 'd') + enable = false; + else + return -EINVAL; + + mutex_lock(&fpc1020->lock); + rc = vreg_setup(fpc1020, name, enable); + mutex_unlock(&fpc1020->lock); + + return rc ? rc : count; +} +static DEVICE_ATTR(regulator_enable, S_IWUSR, NULL, regulator_enable_set); + +static int hw_reset(struct fpc1020_data *fpc1020) +{ + int irq_gpio; + struct device *dev = fpc1020->dev; + int rc = select_pin_ctl(fpc1020, "fpc1020_reset_active"); + + if (rc) + goto exit; + usleep_range(RESET_HIGH_SLEEP1_MIN_US, RESET_HIGH_SLEEP1_MAX_US); + + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + if (rc) + goto exit; + usleep_range(RESET_LOW_SLEEP_MIN_US, RESET_LOW_SLEEP_MAX_US); + + rc = select_pin_ctl(fpc1020, "fpc1020_reset_active"); + if (rc) + goto exit; + usleep_range(RESET_HIGH_SLEEP2_MIN_US, RESET_HIGH_SLEEP2_MAX_US); + + irq_gpio = gpio_get_value(fpc1020->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); + +exit: + return rc; +} + +static ssize_t hw_reset_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "reset", strlen("reset"))) { + mutex_lock(&fpc1020->lock); + rc = hw_reset(fpc1020); + mutex_unlock(&fpc1020->lock); + } else { + return -EINVAL; + } + + return rc ? rc : count; +} +static DEVICE_ATTR(hw_reset, S_IWUSR, NULL, hw_reset_set); + +/** + * Will setup GPIOs, and regulators to correctly initialize the touch sensor to + * be ready for work. + * + * In the correct order according to the sensor spec this function will + * enable/disable regulators, and reset line, all to set the sensor in a + * correct power on or off state "electrical" wise. + * + * @see device_prepare_set + * @note This function will not send any commands to the sensor it will only + * control it "electrically". + */ +static int device_prepare(struct fpc1020_data *fpc1020, bool enable) +{ + int rc; + + mutex_lock(&fpc1020->lock); + if (enable && !fpc1020->prepared) { + fpc1020->prepared = true; + select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + + rc = vreg_setup(fpc1020, "vcc_spi", true); + if (rc) + goto exit; + + rc = vreg_setup(fpc1020, "vdd_io", true); + if (rc) + goto exit_1; + + rc = vreg_setup(fpc1020, "vdd_ana", true); + if (rc) + goto exit_2; + + usleep_range(PWR_ON_SLEEP_MIN_US, PWR_ON_SLEEP_MAX_US); + + /* As we can't control chip select here the other part of the + * sensor driver eg. the TEE driver needs to do a _SOFT_ reset + * on the sensor after power up to be sure that the sensor is + * in a good state after power up. Okeyed by ASIC. */ + + (void)select_pin_ctl(fpc1020, "fpc1020_reset_active"); + } else if (!enable && fpc1020->prepared) { + rc = 0; + (void)select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + + usleep_range(PWR_ON_SLEEP_MIN_US, PWR_ON_SLEEP_MAX_US); + + (void)vreg_setup(fpc1020, "vdd_ana", false); +exit_2: + (void)vreg_setup(fpc1020, "vdd_io", false); +exit_1: + (void)vreg_setup(fpc1020, "vcc_spi", false); +exit: + fpc1020->prepared = false; + } else { + rc = 0; + } + mutex_unlock(&fpc1020->lock); + + return rc; +} + +/** + * sysfs node to enable/disable (power up/power down) the touch sensor + * + * @see device_prepare + */ +static ssize_t device_prepare_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + if (!strncmp(buf, "enable", strlen("enable"))) + rc = device_prepare(fpc1020, true); + else if (!strncmp(buf, "disable", strlen("disable"))) + rc = device_prepare(fpc1020, false); + else + return -EINVAL; + + return rc ? rc : count; +} +static DEVICE_ATTR(device_prepare, S_IWUSR, NULL, device_prepare_set); + +/** + * sysfs node for controlling whether the driver is allowed + * to wake up the platform on interrupt. + */ +static ssize_t wakeup_enable_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + ssize_t ret = count; + + mutex_lock(&fpc1020->lock); + if (!strncmp(buf, "enable", strlen("enable"))) + atomic_set(&fpc1020->wakeup_enabled, 1); + else if (!strncmp(buf, "disable", strlen("disable"))) + atomic_set(&fpc1020->wakeup_enabled, 0); + else + ret = -EINVAL; + mutex_unlock(&fpc1020->lock); + + return ret; +} +static DEVICE_ATTR(wakeup_enable, S_IWUSR, NULL, wakeup_enable_set); + +/** + * sysf node to check the interrupt status of the sensor, the interrupt + * handler should perform sysf_notify to allow userland to poll the node. + */ +static ssize_t irq_get(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + int irq = gpio_get_value(fpc1020->irq_gpio); + + return scnprintf(buf, PAGE_SIZE, "%i\n", irq); +} + +/** + * writing to the irq node will just drop a printk message + * and return success, used for latency measurement. + */ +static ssize_t irq_ack(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + dev_dbg(fpc1020->dev, "%s\n", __func__); + + return count; +} +static DEVICE_ATTR(irq, S_IRUSR | S_IWUSR, irq_get, irq_ack); + + +static ssize_t fingerdown_wait_set(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + dev_err(fpc1020->dev, "%s\n", __func__); + if (!strncmp(buf, "enable", strlen("enable"))) + fpc1020->wait_finger_down = true; + else if (!strncmp(buf, "disable", strlen("disable"))) + fpc1020->wait_finger_down = false; + else + return -EINVAL; + + return count; +} +static DEVICE_ATTR(fingerdown_wait, S_IWUSR, NULL, fingerdown_wait_set); + + +static ssize_t compatible_all_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + int i; + int irqf; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + dev_err(dev, "compatible all enter %d\n", fpc1020->compatible_enabled); + if (!strncmp(buf, "enable", strlen("enable")) && fpc1020->compatible_enabled != 1){ + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_irq", + &fpc1020->irq_gpio); + if (rc) + goto exit; + + rc = fpc1020_request_named_gpio(fpc1020, "fpc,gpio_rst", + &fpc1020->rst_gpio); + dev_err(dev, "fpc request reset result = %d\n", rc); + if (rc) + goto exit; + fpc1020->fingerprint_pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(fpc1020->fingerprint_pinctrl)) { + if (PTR_ERR(fpc1020->fingerprint_pinctrl) == -EPROBE_DEFER) { + dev_info(dev, "pinctrl not ready\n"); + rc = -EPROBE_DEFER; + goto exit; + } + dev_err(dev, "Target does not use pinctrl\n"); + fpc1020->fingerprint_pinctrl = NULL; + rc = -EINVAL; + goto exit; + } + + for (i = 0; i < ARRAY_SIZE(fpc1020->pinctrl_state); i++) { + const char *n = pctl_names[i]; + struct pinctrl_state *state = + pinctrl_lookup_state(fpc1020->fingerprint_pinctrl, n); + if (IS_ERR(state)) { + dev_err(dev, "cannot find '%s'\n", n); + rc = -EINVAL; + goto exit; + } + dev_info(dev, "found pin control %s\n", n); + fpc1020->pinctrl_state[i] = state; + } + rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset"); + if (rc) + goto exit; + rc = select_pin_ctl(fpc1020, "fpc1020_irq_active"); + if (rc) + goto exit; + irqf = IRQF_TRIGGER_RISING | IRQF_ONESHOT; + if (of_property_read_bool(dev->of_node, "fpc,enable-wakeup")) { + irqf |= IRQF_NO_SUSPEND; + device_init_wakeup(dev, 1); + } + + + + rc = devm_request_threaded_irq(dev, gpio_to_irq(fpc1020->irq_gpio), + NULL, fpc1020_irq_handler, irqf, + dev_name(dev), fpc1020); + if (rc) { + dev_err(dev, "could not request irq %d\n", + gpio_to_irq(fpc1020->irq_gpio)); + goto exit; + } + dev_dbg(dev, "requested irq %d\n", gpio_to_irq(fpc1020->irq_gpio)); + + /* Request that the interrupt should be wakeable */ + enable_irq_wake(gpio_to_irq(fpc1020->irq_gpio)); + fpc1020->compatible_enabled = 1; + if (of_property_read_bool(dev->of_node, "fpc,enable-on-boot")) { + dev_info(dev, "Enabling hardware\n"); + (void)device_prepare(fpc1020, true); +#ifdef LINUX_CONTROL_SPI_CLK + (void)set_clks(fpc1020, false); +#endif + } + }else if (!strncmp(buf, "disable", strlen("disable")) && fpc1020->compatible_enabled != 0){ + if (gpio_is_valid(fpc1020->irq_gpio)) + { + devm_gpio_free(dev, fpc1020->irq_gpio); + pr_info("remove irq_gpio success\n"); + } + if (gpio_is_valid(fpc1020->rst_gpio)) + { + devm_gpio_free(dev, fpc1020->rst_gpio); + pr_info("remove rst_gpio success\n"); + } + devm_free_irq(dev, gpio_to_irq(fpc1020->irq_gpio), fpc1020); + fpc1020->compatible_enabled = 0; + } + hw_reset(fpc1020); + return count; +exit: + return -EINVAL; +} +static DEVICE_ATTR(compatible_all, S_IWUSR, NULL, compatible_all_set); + +static struct attribute *attributes[] = { + &dev_attr_pinctl_set.attr, + &dev_attr_device_prepare.attr, + &dev_attr_regulator_enable.attr, + &dev_attr_hw_reset.attr, + &dev_attr_wakeup_enable.attr, + &dev_attr_clk_enable.attr, + &dev_attr_irq.attr, + + &dev_attr_fingerdown_wait.attr, + + &dev_attr_compatible_all.attr, + NULL +}; + +static const struct attribute_group attribute_group = { + .attrs = attributes, +}; + + +static void notification_work(struct work_struct *work) +{ + mdss_prim_panel_fb_unblank(FP_UNLOCK_REJECTION_TIMEOUT); + printk("unblank\n"); +} + + + +static irqreturn_t fpc1020_irq_handler(int irq, void *handle) +{ + struct fpc1020_data *fpc1020 = handle; + + dev_err(fpc1020->dev, "%s\n", __func__); + + + if (atomic_read(&fpc1020->wakeup_enabled)) { + wake_lock_timeout(&fpc1020->ttw_wl, + msecs_to_jiffies(FPC_TTW_HOLD_TIME)); + } + + + sysfs_notify(&fpc1020->dev->kobj, NULL, dev_attr_irq.attr.name); + if (fpc1020->wait_finger_down && fpc1020->fb_black) { + printk("%s enter\n", __func__); + fpc1020->wait_finger_down = false; + schedule_work(&fpc1020->work); + } + + + return IRQ_HANDLED; +} + +static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, + const char *label, int *gpio) +{ + struct device *dev = fpc1020->dev; + struct device_node *np = dev->of_node; + int rc = of_get_named_gpio(np, label, 0); + + if (rc < 0) { + dev_err(dev, "failed to get '%s'\n", label); + return rc; + } + *gpio = rc; + + rc = devm_gpio_request(dev, *gpio, label); + if (rc) { + dev_err(dev, "failed to request gpio %d\n", *gpio); + return rc; + } + dev_dbg(dev, "%s %d\n", label, *gpio); + + return 0; +} + + +static int fpc_fb_notif_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct fpc1020_data *fpc1020 = container_of(nb, struct fpc1020_data, + fb_notifier); + struct fb_event *evdata = data; + unsigned int blank; + + if (!fpc1020) + return 0; + + if (val != FB_EVENT_BLANK) + return 0; + + printk("[info] %s value = %d\n", __func__, (int)val); + + if (evdata && evdata->data && val == FB_EVENT_BLANK) { + blank = *(int *)(evdata->data); + switch (blank) { + case FB_BLANK_POWERDOWN: + fpc1020->fb_black = true; + break; + case FB_BLANK_UNBLANK: + fpc1020->fb_black = false; + break; + default: + printk("%s defalut\n", __func__); + break; + } + } + return NOTIFY_OK; +} + +static struct notifier_block fpc_notif_block = { + .notifier_call = fpc_fb_notif_callback, +}; + + + +static int fpc1020_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int rc = 0; + + struct device_node *np = dev->of_node; + struct fpc1020_data *fpc1020 = devm_kzalloc(dev, sizeof(*fpc1020), + GFP_KERNEL); + + if (!fpc1020) { + dev_err(dev, + "failed to allocate memory for struct fpc1020_data\n"); + rc = -ENOMEM; + goto exit; + } + + fpc1020->dev = dev; + platform_set_drvdata(pdev, fpc1020); + + if (!np) { + dev_err(dev, "no of node found\n"); + rc = -EINVAL; + goto exit; + } + + + mutex_init(&fpc1020->lock); + wake_lock_init(&fpc1020->ttw_wl, WAKE_LOCK_SUSPEND, "fpc_ttw_wl"); + + rc = sysfs_create_group(&dev->kobj, &attribute_group); + if (rc) { + dev_err(dev, "could not create sysfs\n"); + goto exit; + } + + + + + + + + dev_err(dev, "%s: ok\n", __func__); + fpc1020->fb_black = false; + fpc1020->wait_finger_down = false; + INIT_WORK(&fpc1020->work, notification_work); + fpc1020->fb_notifier = fpc_notif_block; + fb_register_client(&fpc1020->fb_notifier); + + +exit: + return rc; +} + +static int fpc1020_remove(struct platform_device *pdev) +{ + struct fpc1020_data *fpc1020 = platform_get_drvdata(pdev); + + + fb_unregister_client(&fpc1020->fb_notifier); + + + sysfs_remove_group(&pdev->dev.kobj, &attribute_group); + mutex_destroy(&fpc1020->lock); + wake_lock_destroy(&fpc1020->ttw_wl); + (void)vreg_setup(fpc1020, "vdd_ana", false); + (void)vreg_setup(fpc1020, "vdd_io", false); + (void)vreg_setup(fpc1020, "vcc_spi", false); + dev_info(&pdev->dev, "%s\n", __func__); + + return 0; +} + +static struct of_device_id fpc1020_of_match[] = { + { .compatible = "fpc,fpc1020", }, + {} +}; +MODULE_DEVICE_TABLE(of, fpc1020_of_match); + +static struct platform_driver fpc1020_driver = { + .driver = { + .name = "fpc1020", + .owner = THIS_MODULE, + .of_match_table = fpc1020_of_match, + }, + .probe = fpc1020_probe, + .remove = fpc1020_remove, +}; + +static int __init fpc1020_init(void) +{ + int rc = platform_driver_register(&fpc1020_driver); + + if (!rc) + pr_info("%s OK\n", __func__); + else + pr_err("%s %d\n", __func__, rc); + + return rc; +} + +static void __exit fpc1020_exit(void) +{ + pr_info("%s\n", __func__); + platform_driver_unregister(&fpc1020_driver); +} + +module_init(fpc1020_init); +module_exit(fpc1020_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Aleksej Makarov"); +MODULE_AUTHOR("Henrik Tillman "); +MODULE_DESCRIPTION("FPC1020 Fingerprint sensor device driver."); diff --git a/drivers/input/fingerprint/goodix/Kconfig b/drivers/input/fingerprint/goodix/Kconfig new file mode 100644 index 0000000000000..90a435276e7fc --- /dev/null +++ b/drivers/input/fingerprint/goodix/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_GOODIX_GF3208 + tristate "generic goodix fingerprint driver" + depends on INPUT_FINGERPRINT + help + Say Y here to enable goodix fingerprint driver support! diff --git a/drivers/input/fingerprint/goodix/Makefile b/drivers/input/fingerprint/goodix/Makefile new file mode 100644 index 0000000000000..f4bdc9596bf7b --- /dev/null +++ b/drivers/input/fingerprint/goodix/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208) += gf_spi.o platform.o netlink.o diff --git a/drivers/input/fingerprint/goodix/gf_spi.c b/drivers/input/fingerprint/goodix/gf_spi.c new file mode 100644 index 0000000000000..2247df31efb76 --- /dev/null +++ b/drivers/input/fingerprint/goodix/gf_spi.c @@ -0,0 +1,940 @@ +/* + * TEE driver for goodix fingerprint sensor + * Copyright (C) 2016 Goodix + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + + +#define WAKELOCK_HOLD_TIME 2000 /* in ms */ +#define FP_UNLOCK_REJECTION_TIMEOUT (WAKELOCK_HOLD_TIME - 500) + + +#define VER_MAJOR 1 +#define VER_MINOR 2 +#define PATCH_LEVEL 11 + + + +#define GF_SPIDEV_NAME "goodix,fingerprint" +/*device name after register in charater*/ +#define GF_DEV_NAME "goodix_fp" +#define GF_INPUT_NAME "uinput-goodix" /*"goodix_fp" */ + +#define CHRD_DRIVER_NAME "goodix_fp_spi" +#define CLASS_NAME "goodix_fp" + +#define N_SPI_MINORS 32 /* ... up to 256 */ +static int SPIDEV_MAJOR; + +static DECLARE_BITMAP(minors, N_SPI_MINORS); +static LIST_HEAD(device_list); +static DEFINE_MUTEX(device_list_lock); +static struct wake_lock fp_wakelock; +static struct gf_dev gf; + +static struct gf_key_map maps[] = { + { EV_KEY, GF_KEY_INPUT_HOME }, + { EV_KEY, GF_KEY_INPUT_MENU }, + { EV_KEY, GF_KEY_INPUT_BACK }, + { EV_KEY, GF_KEY_INPUT_POWER }, +#if defined(SUPPORT_NAV_EVENT) + { EV_KEY, GF_NAV_INPUT_UP }, + { EV_KEY, GF_NAV_INPUT_DOWN }, + { EV_KEY, GF_NAV_INPUT_RIGHT }, + { EV_KEY, GF_NAV_INPUT_LEFT }, + { EV_KEY, GF_KEY_INPUT_CAMERA }, + { EV_KEY, GF_NAV_INPUT_CLICK }, + { EV_KEY, GF_NAV_INPUT_DOUBLE_CLICK }, + { EV_KEY, GF_NAV_INPUT_LONG_PRESS }, + { EV_KEY, GF_NAV_INPUT_HEAVY }, +#endif +}; + +static void gf_enable_irq(struct gf_dev *gf_dev) +{ + if (gf_dev->irq_enabled) { + pr_warn("IRQ has been enabled.\n"); + } else { + enable_irq(gf_dev->irq); + gf_dev->irq_enabled = 1; + } +} + +static void gf_disable_irq(struct gf_dev *gf_dev) +{ + if (gf_dev->irq_enabled) { + gf_dev->irq_enabled = 0; + disable_irq(gf_dev->irq); + } else { + pr_warn("IRQ has been disabled.\n"); + } +} + +#ifdef AP_CONTROL_CLK +static long spi_clk_max_rate(struct clk *clk, unsigned long rate) +{ + long lowest_available, nearest_low, step_size, cur; + long step_direction = -1; + long guess = rate; + int max_steps = 10; + + cur = clk_round_rate(clk, rate); + if (cur == rate) + return rate; + + /* if we got here then: cur > rate */ + lowest_available = clk_round_rate(clk, 0); + if (lowest_available > rate) + return -EINVAL; + + step_size = (rate - lowest_available) >> 1; + nearest_low = lowest_available; + + while (max_steps-- && step_size) { + guess += step_size * step_direction; + cur = clk_round_rate(clk, guess); + + if ((cur < rate) && (cur > nearest_low)) + nearest_low = cur; + /* + * if we stepped too far, then start stepping in the other + * direction with half the step size + */ + if (((cur > rate) && (step_direction > 0)) + || ((cur < rate) && (step_direction < 0))) { + step_direction = -step_direction; + step_size >>= 1; + } + } + return nearest_low; +} + +static void spi_clock_set(struct gf_dev *gf_dev, int speed) +{ + long rate; + int rc; + + rate = spi_clk_max_rate(gf_dev->core_clk, speed); + if (rate < 0) { + pr_info("%s: no match found for requested clock frequency:%d", + __func__, speed); + return; + } + + rc = clk_set_rate(gf_dev->core_clk, rate); +} + +static int gfspi_ioctl_clk_init(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + data->clk_enabled = 0; + data->core_clk = clk_get(&data->spi->dev, "core_clk"); + if (IS_ERR_OR_NULL(data->core_clk)) { + pr_err("%s: fail to get core_clk\n", __func__); + return -EPERM; + } + data->iface_clk = clk_get(&data->spi->dev, "iface_clk"); + if (IS_ERR_OR_NULL(data->iface_clk)) { + pr_err("%s: fail to get iface_clk\n", __func__); + clk_put(data->core_clk); + data->core_clk = NULL; + return -ENOENT; + } + return 0; +} + +static int gfspi_ioctl_clk_enable(struct gf_dev *data) +{ + int err; + + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + return 0; + + err = clk_prepare_enable(data->core_clk); + if (err) { + pr_err("%s: fail to enable core_clk\n", __func__); + return -EPERM; + } + + err = clk_prepare_enable(data->iface_clk); + if (err) { + pr_err("%s: fail to enable iface_clk\n", __func__); + clk_disable_unprepare(data->core_clk); + return -ENOENT; + } + + data->clk_enabled = 1; + + return 0; +} + +static int gfspi_ioctl_clk_disable(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + if (!data->clk_enabled) + return 0; + + clk_disable_unprepare(data->core_clk); + clk_disable_unprepare(data->iface_clk); + data->clk_enabled = 0; + + return 0; +} + +static int gfspi_ioctl_clk_uninit(struct gf_dev *data) +{ + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + gfspi_ioctl_clk_disable(data); + + if (!IS_ERR_OR_NULL(data->core_clk)) { + clk_put(data->core_clk); + data->core_clk = NULL; + } + + if (!IS_ERR_OR_NULL(data->iface_clk)) { + clk_put(data->iface_clk); + data->iface_clk = NULL; + } + + return 0; +} +#endif + +static void nav_event_input(struct gf_dev *gf_dev, gf_nav_event_t nav_event) +{ + uint32_t nav_input = 0; + + switch (nav_event) { + case GF_NAV_FINGER_DOWN: + pr_debug("%s nav finger down\n", __func__); + break; + + case GF_NAV_FINGER_UP: + pr_debug("%s nav finger up\n", __func__); + break; + + case GF_NAV_DOWN: + nav_input = GF_NAV_INPUT_DOWN; + pr_debug("%s nav down\n", __func__); + break; + + case GF_NAV_UP: + nav_input = GF_NAV_INPUT_UP; + pr_debug("%s nav up\n", __func__); + break; + + case GF_NAV_LEFT: + nav_input = GF_NAV_INPUT_LEFT; + pr_debug("%s nav left\n", __func__); + break; + + case GF_NAV_RIGHT: + nav_input = GF_NAV_INPUT_RIGHT; + pr_debug("%s nav right\n", __func__); + break; + + case GF_NAV_CLICK: + nav_input = GF_NAV_INPUT_CLICK; + pr_debug("%s nav click\n", __func__); + break; + + case GF_NAV_HEAVY: + nav_input = GF_NAV_INPUT_HEAVY; + pr_debug("%s nav heavy\n", __func__); + break; + + case GF_NAV_LONG_PRESS: + nav_input = GF_NAV_INPUT_LONG_PRESS; + pr_debug("%s nav long press\n", __func__); + break; + + case GF_NAV_DOUBLE_CLICK: + nav_input = GF_NAV_INPUT_DOUBLE_CLICK; + pr_debug("%s nav double click\n", __func__); + break; + + default: + pr_warn("%s unknown nav event: %d\n", __func__, nav_event); + break; + } + + if ((nav_event != GF_NAV_FINGER_DOWN) && + (nav_event != GF_NAV_FINGER_UP)) { + input_report_key(gf_dev->input, nav_input, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, nav_input, 0); + input_sync(gf_dev->input); + } +} + + +static void notification_work(struct work_struct *work) +{ + mdss_prim_panel_fb_unblank(FP_UNLOCK_REJECTION_TIMEOUT); + pr_debug("unblank\n"); +} + + +static irqreturn_t gf_irq(int irq, void *handle) +{ +#if defined(GF_NETLINK_ENABLE) + struct gf_dev *gf_dev = &gf; + char msg = GF_NET_EVENT_IRQ; + + wake_lock_timeout(&fp_wakelock, msecs_to_jiffies(WAKELOCK_HOLD_TIME)); + + sendnlmsg(&msg); + + + if ((gf_dev->wait_finger_down == true) && (gf_dev->device_available == 1) && (gf_dev->fb_black == 1)) { + gf_dev->wait_finger_down = false; + schedule_work(&gf_dev->work); + } + + +#elif defined(GF_FASYNC) + struct gf_dev *gf_dev = &gf; + + if (gf_dev->async) + kill_fasync(&gf_dev->async, SIGIO, POLL_IN); +#endif + + return IRQ_HANDLED; +} + +static int irq_setup(struct gf_dev *gf_dev) +{ + int status; + + gf_dev->irq = gf_irq_num(gf_dev); + status = request_threaded_irq(gf_dev->irq, NULL, gf_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "gf", gf_dev); + + if (status) { + pr_err("failed to request IRQ:%d\n", gf_dev->irq); + return status; + } + enable_irq_wake(gf_dev->irq); + gf_dev->irq_enabled = 1; + + return status; +} + +static void irq_cleanup(struct gf_dev *gf_dev) +{ + gf_dev->irq_enabled = 0; + disable_irq(gf_dev->irq); + disable_irq_wake(gf_dev->irq); + free_irq(gf_dev->irq, gf_dev); +} + +static void gf_kernel_key_input(struct gf_dev *gf_dev, struct gf_key *gf_key) +{ + uint32_t key_input = 0; + + if (gf_key->key == GF_KEY_HOME) { + key_input = GF_KEY_INPUT_HOME; + } else if (gf_key->key == GF_KEY_POWER) { + key_input = GF_KEY_INPUT_POWER; + } else if (gf_key->key == GF_KEY_CAMERA) { + key_input = GF_KEY_INPUT_CAMERA; + } else { + /* add special key define */ + key_input = gf_key->key; + } + pr_info("%s: received key event[%d], key=%d, value=%d\n", + __func__, key_input, gf_key->key, gf_key->value); + + if ((GF_KEY_POWER == gf_key->key || GF_KEY_CAMERA == gf_key->key) + && (gf_key->value == 1)) { + input_report_key(gf_dev->input, key_input, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, key_input, 0); + input_sync(gf_dev->input); + } + + if (gf_key->key == GF_KEY_HOME) { + input_report_key(gf_dev->input, key_input, gf_key->value); + input_sync(gf_dev->input); + } +} + +static long gf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct gf_dev *gf_dev = &gf; + struct gf_key gf_key; +#if defined(SUPPORT_NAV_EVENT) + gf_nav_event_t nav_event = GF_NAV_NONE; +#endif + int retval = 0; + u8 netlink_route = NETLINK_TEST; + struct gf_ioc_chip_info info; + + if (_IOC_TYPE(cmd) != GF_IOC_MAGIC) + return -ENODEV; + + if (_IOC_DIR(cmd) & _IOC_READ) + retval = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + retval = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (retval) + return -EFAULT; + + switch (cmd) { + case GF_IOC_INIT: + pr_debug("%s GF_IOC_INIT\n", __func__); + if (copy_to_user((void __user *)arg, (void *)&netlink_route, sizeof(u8))) { + pr_err("GF_IOC_INIT failed\n"); + retval = -EFAULT; + break; + } + break; + + case GF_IOC_EXIT: + pr_debug("%s GF_IOC_EXIT\n", __func__); + break; + + case GF_IOC_DISABLE_IRQ: + pr_debug("%s GF_IOC_DISABEL_IRQ\n", __func__); + gf_disable_irq(gf_dev); + break; + + case GF_IOC_ENABLE_IRQ: + pr_debug("%s GF_IOC_ENABLE_IRQ\n", __func__); + gf_enable_irq(gf_dev); + break; + + case GF_IOC_RESET: + pr_debug("%s GF_IOC_RESET\n", __func__); + gf_hw_reset(gf_dev, 3); + break; + + case GF_IOC_INPUT_KEY_EVENT: + if (copy_from_user(&gf_key, (void __user *)arg, sizeof(struct gf_key))) { + pr_err("failed to copy input key event from user to kernel\n"); + retval = -EFAULT; + break; + } + + gf_kernel_key_input(gf_dev, &gf_key); + break; + +#if defined(SUPPORT_NAV_EVENT) + case GF_IOC_NAV_EVENT: + pr_debug("%s GF_IOC_NAV_EVENT\n", __func__); + if (copy_from_user(&nav_event, (void __user *)arg, sizeof(gf_nav_event_t))) { + pr_err("failed to copy nav event from user to kernel\n"); + retval = -EFAULT; + break; + } + + nav_event_input(gf_dev, nav_event); + break; +#endif + + case GF_IOC_ENABLE_SPI_CLK: + pr_debug("%s GF_IOC_ENABLE_SPI_CLK\n", __func__); +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_enable(gf_dev); +#else + pr_debug("doesn't support control clock!\n"); +#endif + break; + + case GF_IOC_DISABLE_SPI_CLK: + pr_debug("%s GF_IOC_DISABLE_SPI_CLK\n", __func__); +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_disable(gf_dev); +#else + pr_debug("doesn't support control clock!\n"); +#endif + break; + + case GF_IOC_ENABLE_POWER: + pr_debug("%s GF_IOC_ENABLE_POWER\n", __func__); + gf_power_on(gf_dev); + break; + + case GF_IOC_DISABLE_POWER: + pr_debug("%s GF_IOC_DISABLE_POWER\n", __func__); + gf_power_off(gf_dev); + break; + + case GF_IOC_ENTER_SLEEP_MODE: + pr_debug("%s GF_IOC_ENTER_SLEEP_MODE\n", __func__); + break; + + case GF_IOC_GET_FW_INFO: + pr_debug("%s GF_IOC_GET_FW_INFO\n", __func__); + break; + + case GF_IOC_REMOVE: + pr_debug("%s GF_IOC_REMOVE\n", __func__); + irq_cleanup(gf_dev); + gf_cleanup(gf_dev); + break; + + case GF_IOC_CHIP_INFO: + pr_debug("%s GF_IOC_CHIP_INFO\n", __func__); + if (copy_from_user(&info, (void __user *)arg, sizeof(struct gf_ioc_chip_info))) { + retval = -EFAULT; + break; + } + pr_info("vendor_id : 0x%x\n", info.vendor_id); + pr_info("mode : 0x%x\n", info.mode); + pr_info("operation: 0x%x\n", info.operation); + break; + + default: + pr_warn("unsupport cmd:0x%x\n", cmd); + break; + } + + return retval; +} + +#ifdef CONFIG_COMPAT +static long gf_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gf_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif /*CONFIG_COMPAT*/ + + +static int gf_open(struct inode *inode, struct file *filp) +{ + struct gf_dev *gf_dev = &gf; + int status = -ENXIO; + + mutex_lock(&device_list_lock); + + list_for_each_entry(gf_dev, &device_list, device_entry) { + if (gf_dev->devt == inode->i_rdev) { + pr_info("Found\n"); + status = 0; + break; + } + } + + if (status == 0) { + if (status == 0) { + gf_dev->users++; + filp->private_data = gf_dev; + nonseekable_open(inode, filp); + pr_info("Succeed to open device. irq = %d\n", + gf_dev->irq); + if (gf_dev->users == 1) { + status = gf_parse_dts(gf_dev); + if (status) + goto err_parse_dt; + + status = irq_setup(gf_dev); + if (status) + goto err_irq; + } + gf_hw_reset(gf_dev, 3); + gf_dev->device_available = 1; + } + } else { + pr_info("No device for minor %d\n", iminor(inode)); + } + mutex_unlock(&device_list_lock); + + return status; +err_irq: + gf_cleanup(gf_dev); +err_parse_dt: + return status; +} + +#ifdef GF_FASYNC +static int gf_fasync(int fd, struct file *filp, int mode) +{ + struct gf_dev *gf_dev = filp->private_data; + int ret; + + ret = fasync_helper(fd, filp, mode, &gf_dev->async); + pr_info("ret = %d\n", ret); + return ret; +} +#endif + +static int gf_release(struct inode *inode, struct file *filp) +{ + struct gf_dev *gf_dev = &gf; + int status = 0; + + mutex_lock(&device_list_lock); + gf_dev = filp->private_data; + filp->private_data = NULL; + + /*last close?? */ + gf_dev->users--; + if (!gf_dev->users) { + + pr_info("disble_irq. irq = %d\n", gf_dev->irq); + + irq_cleanup(gf_dev); + gf_cleanup(gf_dev); + /*power off the sensor*/ + gf_dev->device_available = 0; + gf_power_off(gf_dev); + } + mutex_unlock(&device_list_lock); + return status; +} + +static const struct file_operations gf_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .unlocked_ioctl = gf_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gf_compat_ioctl, +#endif /*CONFIG_COMPAT*/ + .open = gf_open, + .release = gf_release, +#ifdef GF_FASYNC + .fasync = gf_fasync, +#endif +}; + +static int goodix_fb_state_chg_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct gf_dev *gf_dev; + struct fb_event *evdata = data; + unsigned int blank; + char msg = 0; + + + printk("SXF Enter %s val = %d \n ", __func__, (int)val); + if (val != FB_EVENT_BLANK) + return 0; + pr_info("[info] %s go to the goodix_fb_state_chg_callback value = %d\n", + __func__, (int)val); + gf_dev = container_of(nb, struct gf_dev, notifier); + + + if (evdata && evdata->data && val == FB_EVENT_BLANK && gf_dev) { + blank = *(int *)(evdata->data); + printk("SXF_blank = %d\n", blank); + switch (blank) { + case FB_BLANK_POWERDOWN: + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 1; + gf_dev->wait_finger_down = true; +#if defined(GF_NETLINK_ENABLE) + msg = GF_NET_EVENT_FB_BLACK; + +#elif defined(GF_FASYNC) + if (gf_dev->async) + kill_fasync(&gf_dev->async, SIGIO, POLL_IN); +#endif + } + break; + case FB_BLANK_UNBLANK: + printk("SXF-FB_BLANK_UNBLANK \n"); + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 0; +#if defined(GF_NETLINK_ENABLE) + msg = GF_NET_EVENT_FB_UNBLACK; + +#elif defined(GF_FASYNC) + if (gf_dev->async) + kill_fasync(&gf_dev->async, SIGIO, POLL_IN); +#endif + } + break; + default: + pr_info("%s defalut\n", __func__); + break; + } + } + printk("SXF Exit %s\n ", __func__); + return NOTIFY_OK; +} + +static struct notifier_block goodix_noti_block = { + .notifier_call = goodix_fb_state_chg_callback, +}; + +static struct class *gf_class; +#if defined(USE_SPI_BUS) +static int gf_probe(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_probe(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + int status = -EINVAL; + unsigned long minor; + int i; + + /* Initialize the driver data */ + INIT_LIST_HEAD(&gf_dev->device_entry); +#if defined(USE_SPI_BUS) + gf_dev->spi = spi; +#elif defined(USE_PLATFORM_BUS) + gf_dev->spi = pdev; +#endif + gf_dev->irq_gpio = -EINVAL; + gf_dev->reset_gpio = -EINVAL; + gf_dev->pwr_gpio = -EINVAL; + gf_dev->device_available = 0; + gf_dev->fb_black = 0; + + + gf_dev->wait_finger_down = false; + INIT_WORK(&gf_dev->work, notification_work); + + + /* If we can allocate a minor number, hook up this device. + * Reusing minors is fine so long as udev or mdev is working. + */ + mutex_lock(&device_list_lock); + minor = find_first_zero_bit(minors, N_SPI_MINORS); + if (minor < N_SPI_MINORS) { + struct device *dev; + + gf_dev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(gf_class, &gf_dev->spi->dev, gf_dev->devt, + gf_dev, GF_DEV_NAME); + status = IS_ERR(dev) ? PTR_ERR(dev) : 0; + } else { + dev_dbg(&gf_dev->spi->dev, "no minor number available!\n"); + status = -ENODEV; + mutex_unlock(&device_list_lock); + goto error_hw; + } + + if (status == 0) { + set_bit(minor, minors); + list_add(&gf_dev->device_entry, &device_list); + } else { + gf_dev->devt = 0; + goto error_hw; + } + mutex_unlock(&device_list_lock); + + gf_dev->input = input_allocate_device(); + if (gf_dev->input == NULL) { + pr_err("%s, failed to allocate input device\n", __func__); + status = -ENOMEM; + goto error_dev; + } + for (i = 0; i < ARRAY_SIZE(maps); i++) + input_set_capability(gf_dev->input, maps[i].type, maps[i].code); + + gf_dev->input->name = GF_INPUT_NAME; + status = input_register_device(gf_dev->input); + if (status) { + pr_err("failed to register input device\n"); + goto error_input; + } + +#ifdef AP_CONTROL_CLK + pr_info("Get the clk resource.\n"); + /* Enable spi clock */ + if (gfspi_ioctl_clk_init(gf_dev)) + goto gfspi_probe_clk_init_failed; + + if (gfspi_ioctl_clk_enable(gf_dev)) + goto gfspi_probe_clk_enable_failed; + + spi_clock_set(gf_dev, 1000000); +#endif + + gf_dev->notifier = goodix_noti_block; + fb_register_client(&gf_dev->notifier); + + wake_lock_init(&fp_wakelock, WAKE_LOCK_SUSPEND, "fp_wakelock"); + + pr_info("version V%d.%d.%02d\n", VER_MAJOR, VER_MINOR, PATCH_LEVEL); +printk("gf probe success\n"); + return status; + +#ifdef AP_CONTROL_CLK +gfspi_probe_clk_enable_failed: + gfspi_ioctl_clk_uninit(gf_dev); +gfspi_probe_clk_init_failed: +#endif + +error_input: + if (gf_dev->input != NULL) + input_free_device(gf_dev->input); +error_dev: + if (gf_dev->devt != 0) { + pr_info("Err: status = %d\n", status); + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + mutex_unlock(&device_list_lock); + } +error_hw: + gf_dev->device_available = 0; + + return status; +} + +#if defined(USE_SPI_BUS) +static int gf_remove(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_remove(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + + wake_lock_destroy(&fp_wakelock); + fb_unregister_client(&gf_dev->notifier); + if (gf_dev->input) + input_unregister_device(gf_dev->input); + input_free_device(gf_dev->input); + + /* prevent new opens */ + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + mutex_unlock(&device_list_lock); + + return 0; +} + +static const struct of_device_id gx_match_table[] = { + { .compatible = GF_SPIDEV_NAME }, + {}, +}; + +#if defined(USE_SPI_BUS) +static struct spi_driver gf_driver = { +#elif defined(USE_PLATFORM_BUS) +static struct platform_driver gf_driver = { +#endif + .driver = { + .name = GF_DEV_NAME, + .owner = THIS_MODULE, + .of_match_table = gx_match_table, + }, + .probe = gf_probe, + .remove = gf_remove, +}; + +static int __init gf_init(void) +{ + int status; + + /* Claim our 256 reserved device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * the driver which manages those device numbers. + */ + + BUILD_BUG_ON(N_SPI_MINORS > 256); + status = register_chrdev(SPIDEV_MAJOR, CHRD_DRIVER_NAME, &gf_fops); + if (status < 0) { + pr_warn("Failed to register char device!\n"); + return status; + } + SPIDEV_MAJOR = status; + gf_class = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(gf_class)) { + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to create class.\n"); + return PTR_ERR(gf_class); + } +#if defined(USE_PLATFORM_BUS) + status = platform_driver_register(&gf_driver); +#elif defined(USE_SPI_BUS) + status = spi_register_driver(&gf_driver); +#endif + if (status < 0) { + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to register SPI driver.\n"); + } + +#ifdef GF_NETLINK_ENABLE + netlink_init(); +#endif + printk("status = 0x%x\n", status); + return 0; +} +module_init(gf_init); + +static void __exit gf_exit(void) +{ +#ifdef GF_NETLINK_ENABLE + netlink_exit(); +#endif +#if defined(USE_PLATFORM_BUS) + platform_driver_unregister(&gf_driver); +#elif defined(USE_SPI_BUS) + spi_unregister_driver(&gf_driver); +#endif + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); +} +module_exit(gf_exit); + +MODULE_AUTHOR("Jiangtao Yi, "); +MODULE_AUTHOR("Jandy Gou, "); +MODULE_DESCRIPTION("goodix fingerprint sensor device driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/fingerprint/goodix/gf_spi.h b/drivers/input/fingerprint/goodix/gf_spi.h new file mode 100644 index 0000000000000..3ac42ebdcb51f --- /dev/null +++ b/drivers/input/fingerprint/goodix/gf_spi.h @@ -0,0 +1,158 @@ +/* + * driver definition for sensor driver + * + * Coypright (c) 2017 Goodix + */ +#ifndef __GF_SPI_H +#define __GF_SPI_H + +#include +#include +/**********************************************************/ +enum FP_MODE{ + GF_IMAGE_MODE = 0, + GF_KEY_MODE, + GF_SLEEP_MODE, + GF_FF_MODE, + GF_DEBUG_MODE = 0x56 +}; + +#define SUPPORT_NAV_EVENT + +#if defined(SUPPORT_NAV_EVENT) +#define GF_NAV_INPUT_UP 198 +#define GF_NAV_INPUT_DOWN 197 +#define GF_NAV_INPUT_LEFT 195 +#define GF_NAV_INPUT_RIGHT 196 +#define GF_NAV_INPUT_CLICK KEY_VOLUMEDOWN +#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP +#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH +#define GF_NAV_INPUT_HEAVY KEY_CHAT +#endif + +#define GF_KEY_INPUT_HOME KEY_SELECT +#define GF_KEY_INPUT_MENU KEY_MENU +#define GF_KEY_INPUT_BACK KEY_BACK +#define GF_KEY_INPUT_POWER KEY_POWER +#define GF_KEY_INPUT_CAMERA KEY_CAMERA + +#if defined(SUPPORT_NAV_EVENT) +typedef enum gf_nav_event { + GF_NAV_NONE = 0, + GF_NAV_FINGER_UP, + GF_NAV_FINGER_DOWN, + GF_NAV_UP, + GF_NAV_DOWN, + GF_NAV_LEFT, + GF_NAV_RIGHT, + GF_NAV_CLICK, + GF_NAV_HEAVY, + GF_NAV_LONG_PRESS, + GF_NAV_DOUBLE_CLICK, +} gf_nav_event_t; +#endif + +typedef enum gf_key_event { + GF_KEY_NONE = 0, + GF_KEY_HOME, + GF_KEY_POWER, + GF_KEY_MENU, + GF_KEY_BACK, + GF_KEY_CAMERA, +} gf_key_event_t; + +struct gf_key { + enum gf_key_event key; + uint32_t value; /* key down = 1, key up = 0 */ +}; + +struct gf_key_map { + unsigned int type; + unsigned int code; +}; + +struct gf_ioc_chip_info { + unsigned char vendor_id; + unsigned char mode; + unsigned char operation; + unsigned char reserved[5]; +}; + +#define GF_IOC_MAGIC 'g' +#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t) +#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1) +#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2) +#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3) +#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4) +#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t) +#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6) +#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7) +#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8) +#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key) +#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10) +#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t) +#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12) +#define GF_IOC_CHIP_INFO _IOW(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info) + +#if defined(SUPPORT_NAV_EVENT) +#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t) +#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */ +#else +#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */ +#endif + + +#define USE_PLATFORM_BUS 1 + + +#define GF_NETLINK_ENABLE 1 +#define GF_NET_EVENT_IRQ 1 +#define GF_NET_EVENT_FB_BLACK 2 +#define GF_NET_EVENT_FB_UNBLACK 3 +#define NETLINK_TEST 25 + +struct gf_dev { + dev_t devt; + struct list_head device_entry; +#if defined(USE_SPI_BUS) + struct spi_device *spi; +#elif defined(USE_PLATFORM_BUS) + struct platform_device *spi; +#endif + struct clk *core_clk; + struct clk *iface_clk; + + struct input_dev *input; + /* buffer is NULL unless this device is open (users > 0) */ + unsigned users; + signed irq_gpio; + signed reset_gpio; + signed pwr_gpio; + int irq; + int irq_enabled; + int clk_enabled; +#ifdef GF_FASYNC + struct fasync_struct *async; +#endif + struct notifier_block notifier; + char device_available; + char fb_black; + + + char wait_finger_down; + struct work_struct work; +}; + +int gf_parse_dts(struct gf_dev *gf_dev); +void gf_cleanup(struct gf_dev *gf_dev); + +int gf_power_on(struct gf_dev *gf_dev); +int gf_power_off(struct gf_dev *gf_dev); + +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms); +int gf_irq_num(struct gf_dev *gf_dev); + +int sendnlmsg(char *msg); +int netlink_init(void); +void netlink_exit(void); +#endif /*__GF_SPI_H*/ diff --git a/drivers/input/fingerprint/goodix/netlink.c b/drivers/input/fingerprint/goodix/netlink.c new file mode 100644 index 0000000000000..8058d1b38b435 --- /dev/null +++ b/drivers/input/fingerprint/goodix/netlink.c @@ -0,0 +1,104 @@ +/* + * netlink interface + * + * Copyright (c) 2017 Goodix + * Copyright (C) 2019 XiaoMi, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include "gf_spi.h" + +#define NETLINK_TEST 25 +#define MAX_MSGSIZE 32 + +static int pid = -1; +static struct sock *nl_sk; + +int sendnlmsg(char *msg) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + int len = NLMSG_SPACE(MAX_MSGSIZE); + int ret = 0; + + if (!msg || !nl_sk || !pid) + return -ENODEV; + + skb = alloc_skb(len, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + nlh = nlmsg_put(skb, 0, 0, 0, MAX_MSGSIZE, 0); + if (!nlh) { + kfree_skb(skb); + return -EMSGSIZE; + } + + NETLINK_CB(skb).portid = 0; + NETLINK_CB(skb).dst_group = 0; + + memcpy(NLMSG_DATA(nlh), msg, sizeof(char)); + pr_debug("send message: %d\n", *(char *)NLMSG_DATA(nlh)); + + ret = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT); + if (ret > 0) + ret = 0; + + return ret; +} + +static void nl_data_ready(struct sk_buff *__skb) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + char str[100]; + + skb = skb_get(__skb); + if (skb->len >= NLMSG_SPACE(0)) { + nlh = nlmsg_hdr(skb); + + memcpy(str, NLMSG_DATA(nlh), sizeof(str)); + pid = nlh->nlmsg_pid; + + kfree_skb(skb); + } + +} + + +int netlink_init(void) +{ + struct netlink_kernel_cfg netlink_cfg; + + memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg)); + + netlink_cfg.groups = 0; + netlink_cfg.flags = 0; + netlink_cfg.input = nl_data_ready; + netlink_cfg.cb_mutex = NULL; + + nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, + &netlink_cfg); + + if (!nl_sk) { + pr_err("create netlink socket error\n"); + return 1; + } + + return 0; +} + +void netlink_exit(void) +{ + if (nl_sk != NULL) { + netlink_kernel_release(nl_sk); + nl_sk = NULL; + } + + pr_info("self module exited\n"); +} diff --git a/drivers/input/fingerprint/goodix/platform.c b/drivers/input/fingerprint/goodix/platform.c new file mode 100644 index 0000000000000..45d2c24a9cc3e --- /dev/null +++ b/drivers/input/fingerprint/goodix/platform.c @@ -0,0 +1,114 @@ +/* + * platform indepent driver interface + * + * Coypritht (c) 2017 Goodix + */ +#include +#include +#include +#include +#include +#include +#include + +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +int gf_parse_dts(struct gf_dev *gf_dev) +{ + int rc = 0; + struct device *dev = &gf_dev->spi->dev; + struct device_node *np = dev->of_node; + + gf_dev->reset_gpio = of_get_named_gpio(np, "fp-gpio-reset", 0); + if (gf_dev->reset_gpio < 0) { + pr_err("falied to get reset gpio!\n"); + return gf_dev->reset_gpio; + } + + rc = devm_gpio_request(dev, gf_dev->reset_gpio, "goodix_reset"); + if (rc) { + pr_err("failed to request reset gpio, rc = %d\n", rc); + goto err_reset; + } + gpio_direction_output(gf_dev->reset_gpio, 1); + + gf_dev->irq_gpio = of_get_named_gpio(np, "fp-gpio-irq", 0); + if (gf_dev->irq_gpio < 0) { + pr_err("falied to get irq gpio!\n"); + return gf_dev->irq_gpio; + } + + rc = devm_gpio_request(dev, gf_dev->irq_gpio, "goodix_irq"); + if (rc) { + pr_err("failed to request irq gpio, rc = %d\n", rc); + goto err_irq; + } + gpio_direction_input(gf_dev->irq_gpio); + +err_irq: + devm_gpio_free(dev, gf_dev->reset_gpio); +err_reset: + return rc; +} + +void gf_cleanup(struct gf_dev *gf_dev) +{ + pr_info("[info] %s\n", __func__); + + if (gpio_is_valid(gf_dev->irq_gpio)) { + gpio_free(gf_dev->irq_gpio); + pr_info("remove irq_gpio success\n"); + } + if (gpio_is_valid(gf_dev->reset_gpio)) { + gpio_free(gf_dev->reset_gpio); + pr_info("remove reset_gpio success\n"); + } +} + +int gf_power_on(struct gf_dev *gf_dev) +{ + int rc = 0; + + /* TODO: add your power control here */ + return rc; +} + +int gf_power_off(struct gf_dev *gf_dev) +{ + int rc = 0; + + /* TODO: add your power control here */ + + return rc; +} + +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } + gpio_direction_output(gf_dev->reset_gpio, 1); + gpio_set_value(gf_dev->reset_gpio, 0); + mdelay(3); + gpio_set_value(gf_dev->reset_gpio, 1); + mdelay(delay_ms); + return 0; +} + +int gf_irq_num(struct gf_dev *gf_dev) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } else { + return gpio_to_irq(gf_dev->irq_gpio); + } +} diff --git a/drivers/input/fingerprint/goodix_e7/Kconfig b/drivers/input/fingerprint/goodix_e7/Kconfig new file mode 100644 index 0000000000000..498893d8ab98f --- /dev/null +++ b/drivers/input/fingerprint/goodix_e7/Kconfig @@ -0,0 +1,5 @@ +config FINGERPRINT_GOODIX_GF3208_E7 + tristate "Goodix GF3208 fingerprint drvier support" + depends on INPUT_FINGERPRINT + help + Say Y here to enable goodix fingerprint driver support! diff --git a/drivers/input/fingerprint/goodix_e7/Makefile b/drivers/input/fingerprint/goodix_e7/Makefile new file mode 100644 index 0000000000000..56b4b6c49937b --- /dev/null +++ b/drivers/input/fingerprint/goodix_e7/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_FINGERPRINT_GOODIX_GF3208_E7) += gf_spi.o platform.o netlink.o +#obj-y += gf_spi.o platform.o netlink.o diff --git a/drivers/input/fingerprint/goodix_e7/gf_spi.c b/drivers/input/fingerprint/goodix_e7/gf_spi.c new file mode 100644 index 0000000000000..7b6e064a4c05e --- /dev/null +++ b/drivers/input/fingerprint/goodix_e7/gf_spi.c @@ -0,0 +1,1088 @@ +/*Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +#define GF_SPIDEV_NAME "goodix,fingerprint" +/*device name after register in charater*/ +#define GF_DEV_NAME "goodix_fp" +#define GF_INPUT_NAME "uinput-goodix" /*"goodix_fp" */ + +#define CHRD_DRIVER_NAME "goodix_fp_spi" +#define CLASS_NAME "goodix_fp" +#define SPIDEV_MAJOR 225 /* assigned */ +#define N_SPI_MINORS 32 /* ... up to 256 */ + +#define GF_INPUT_HOME_KEY KEY_HOMEPAGE /* KEY_HOME */ +#define GF_INPUT_MENU_KEY KEY_MENU +#define GF_INPUT_BACK_KEY KEY_BACK +#define GF_INPUT_FF_KEY KEY_POWER +#define GF_INPUT_CAMERA_KEY KEY_CAMERA +#define GF_INPUT_OTHER_KEY KEY_VOLUMEDOWN /* temporary key value for capture use */ +#define GF_NAV_UP_KEY KEY_GESTURE_NAV_UP +#define GF_NAV_DOWN_KEY KEY_GESTURE_NAV_DOWN +#define GF_NAV_LEFT_KEY KEY_GESTURE_NAV_LEFT +#define GF_NAV_RIGHT_KEY KEY_GESTURE_NAV_RIGHT + +#define GF_CLICK_KEY 114 +#define GF_DOUBLE_CLICK_KEY 115 +#define GF_LONG_PRESS_KEY 217 + +struct gf_key_map key_map[] = { { "POWER", KEY_POWER }, { "HOME", KEY_HOME }, { + "MENU", KEY_MENU }, { "BACK", KEY_BACK }, { "UP", KEY_UP }, { "DOWN", +KEY_DOWN }, { "LEFT", KEY_LEFT }, { "RIGHT", KEY_RIGHT }, { "FORCE", +KEY_F9 }, { "CLICK", KEY_F19 }, }; + +/**************************debug******************************/ +/*Global variables*/ +/*static MODE g_mode = GF_IMAGE_MODE;*/ +static DECLARE_BITMAP(minors, N_SPI_MINORS); +static LIST_HEAD(device_list); +static DEFINE_MUTEX(device_list_lock); +static struct gf_dev gf; +static struct wake_lock fp_wakelock; +static int driver_init_partial(struct gf_dev *gf_dev); +static void nav_event_input(struct gf_dev *gf_dev, gf_nav_event_t nav_event); + +static void gf_enable_irq(struct gf_dev *gf_dev) { + if (gf_dev->irq_enabled) { + pr_warn("IRQ has been enabled.\n"); + } else { + enable_irq_wake(gf_dev->irq); + gf_dev->irq_enabled = 1; + } +} + +static void gf_disable_irq(struct gf_dev *gf_dev) { + if (gf_dev->irq_enabled) { + gf_dev->irq_enabled = 0; + disable_irq_wake(gf_dev->irq); + } else { + pr_warn("IRQ has been disabled.\n"); + } +} + +#ifdef AP_CONTROL_CLK +static long spi_clk_max_rate(struct clk *clk, unsigned long rate) { + long lowest_available, nearest_low, step_size, cur; + long step_direction = -1; + long guess = rate; + int max_steps = 10; + + cur = clk_round_rate(clk, rate); + if (cur == rate) + return rate; + + /* if we got here then: cur > rate */ + lowest_available = clk_round_rate(clk, 0); + if (lowest_available > rate) + return -EINVAL; + + step_size = (rate - lowest_available) >> 1; + nearest_low = lowest_available; + + while (max_steps-- && step_size) { + guess += step_size * step_direction; + cur = clk_round_rate(clk, guess); + + if ((cur < rate) && (cur > nearest_low)) + nearest_low = cur; + /* + * if we stepped too far, then start stepping in the other + * direction with half the step size + */ + if (((cur > rate) && (step_direction > 0)) + || ((cur < rate) && (step_direction < 0))) { + step_direction = -step_direction; + step_size >>= 1; + } + } + return nearest_low; +} + +static void spi_clock_set(struct gf_dev *gf_dev, int speed) { + long rate; + int rc; + + rate = spi_clk_max_rate(gf_dev->core_clk, speed); + if (rate < 0) { + pr_info("%s: no match found for requested clock frequency:%d", __func__, + speed); + return; + } + + rc = clk_set_rate(gf_dev->core_clk, rate); +} + +static int gfspi_ioctl_clk_init(struct gf_dev *data) { + pr_debug("%s: enter\n", __func__); + + data->clk_enabled = 0; + data->core_clk = clk_get(&data->spi->dev, "core_clk"); + if (IS_ERR_OR_NULL(data->core_clk)) { + pr_err("%s: fail to get core_clk\n", __func__); + return -EPERM; + } + data->iface_clk = clk_get(&data->spi->dev, "iface_clk"); + if (IS_ERR_OR_NULL(data->iface_clk)) { + pr_err("%s: fail to get iface_clk\n", __func__); + clk_put(data->core_clk); + data->core_clk = NULL; + return -ENOENT; + } + return 0; +} + +static int gfspi_ioctl_clk_enable(struct gf_dev *data) { + int err; + + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + return 0; + + err = clk_prepare_enable(data->core_clk); + if (err) { + pr_err("%s: fail to enable core_clk\n", __func__); + return -EPERM; + } + + err = clk_prepare_enable(data->iface_clk); + if (err) { + pr_err("%s: fail to enable iface_clk\n", __func__); + clk_disable_unprepare(data->core_clk); + return -ENOENT; + } + + data->clk_enabled = 1; + + return 0; +} + +static int gfspi_ioctl_clk_disable(struct gf_dev *data) { + pr_debug("%s: enter\n", __func__); + + if (!data->clk_enabled) + return 0; + + clk_disable_unprepare(data->core_clk); + clk_disable_unprepare(data->iface_clk); + data->clk_enabled = 0; + + return 0; +} + +static int gfspi_ioctl_clk_uninit(struct gf_dev *data) { + pr_debug("%s: enter\n", __func__); + + if (data->clk_enabled) + gfspi_ioctl_clk_disable(data); + + if (!IS_ERR_OR_NULL(data->core_clk)) { + clk_put(data->core_clk); + data->core_clk = NULL; + } + + if (!IS_ERR_OR_NULL(data->iface_clk)) { + clk_put(data->iface_clk); + data->iface_clk = NULL; + } + + return 0; +} +#endif + +static long gf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + struct gf_dev *gf_dev = &gf; + struct gf_key gf_key; + int retval = 0; + + u8 netlink_route = NETLINK_TEST; + struct gf_ioc_chip_info info; + uint32_t key_event; + +#if defined(SUPPORT_NAV_EVENT) + gf_nav_event_t nav_event = GF_NAV_NONE; +#endif + + pr_info("gf_ioctl cmd:0x%x \n", cmd); + + + + + if (_IOC_TYPE(cmd) != GF_IOC_MAGIC) + return -ENODEV; + + if (_IOC_DIR(cmd) & _IOC_READ) + retval = !access_ok(VERIFY_WRITE, (void __user *) arg, _IOC_SIZE(cmd)); + if ((retval == 0) && (_IOC_DIR(cmd) & _IOC_WRITE)) + retval = !access_ok(VERIFY_READ, (void __user *) arg, _IOC_SIZE(cmd)); + if (retval) + return -EFAULT; + + if (gf_dev->device_available == 0) { + if ((cmd == GF_IOC_ENABLE_POWER) || (cmd == GF_IOC_DISABLE_POWER)) { + pr_info("power cmd\n"); + } else { + pr_info("Sensor is power off currently. \n"); + return -ENODEV; + } + } + + switch (cmd) { + + case GF_IOC_INIT: + pr_info("%s GF_IOC_INIT .\n", __func__); + + if (copy_to_user((void __user *) arg, (void *) &netlink_route, + sizeof(u8))) { + retval = -EFAULT; + break; + } + break; + case GF_IOC_EXIT: + pr_info("%s GF_IOC_EXIT .\n", __func__); + break; + case GF_IOC_DISABLE_IRQ: + pr_info("%s GF_IOC_DISABEL_IRQ .\n", __func__); + gf_disable_irq(gf_dev); + break; + case GF_IOC_ENABLE_IRQ: + pr_info("%s GF_IOC_ENABLE_IRQ .\n", __func__); + gf_enable_irq(gf_dev); + break; +#if 0 + case GF_IOC_SETSPEED: +#ifdef AP_CONTROL_CLK + retval = __get_user(speed, (u32 __user *) arg); + if (retval == 0) { + if (speed > 12 * 1000 * 1000) { + pr_warn("Set speed:%d is larger than 8Mbps.\n", speed); + } else { + spi_clock_set(gf_dev, speed); + } + } else { + pr_warn("Failed to get speed from user. retval = %d\n", retval); + } +#else + pr_info("This kernel doesn't support control clk in AP\n"); +#endif + + break; +#endif + case GF_IOC_RESET: + pr_info("%s GF_IOC_RESET. \n", __func__); + gf_hw_reset(gf_dev, 3); + break; + case GF_IOC_ENABLE_GPIO: + pr_info("%s GF_IOC_ENABLE_GPIO. \n", __func__); + driver_init_partial(gf_dev); + break; + case GF_IOC_RELEASE_GPIO: + pr_info("%s GF_IOC_RELEASE_GPIO. \n", __func__); + + gf_disable_irq(gf_dev); + + devm_free_irq(&gf_dev->spi->dev, gf_dev->irq, gf_dev); + + + gf_cleanup(gf_dev); + break; + case GF_IOC_INPUT_KEY_EVENT: + pr_info("%s GF_IOC_INPUT_KEY_EVENT. \n", __func__); + if (copy_from_user(&gf_key, (struct gf_key *) arg, + sizeof(struct gf_key))) { + pr_info("Failed to copy input key event from user to kernel\n"); + retval = -EFAULT; + break; + } + + if (GF_KEY_HOME == gf_key.key) { + key_event = KEY_SELECT; + } else if (GF_KEY_POWER == gf_key.key) { + key_event = GF_INPUT_FF_KEY; + } else if (GF_KEY_CAPTURE == gf_key.key) { + key_event = GF_INPUT_CAMERA_KEY; + } else if (GF_KEY_LONG_PRESS == gf_key.key) { + key_event = GF_LONG_PRESS_KEY; + } else if (GF_KEY_DOUBLE_TAP == gf_key.key) { + key_event = GF_DOUBLE_CLICK_KEY; + } else if (GF_KEY_TAP == gf_key.key) { + key_event = GF_CLICK_KEY; + } else { + /* add special key define */ + key_event = gf_key.key; + } + pr_info("%s: received key event[%d], key=%d, value=%d\n", __func__, + key_event, gf_key.key, gf_key.value); + + if ((GF_KEY_POWER == gf_key.key || GF_KEY_CAPTURE == gf_key.key) + && (gf_key.value == 1)) { + input_report_key(gf_dev->input, key_event, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, key_event, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_UP == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_DOWN == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_RIGHT == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 0); + input_sync(gf_dev->input); + } else if (GF_KEY_LEFT == gf_key.key) { + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 0); + input_sync(gf_dev->input); + } else if ((GF_KEY_POWER != gf_key.key) + && (GF_KEY_CAPTURE != gf_key.key)) { + input_report_key(gf_dev->input, key_event, gf_key.value); + input_sync(gf_dev->input); + } + break; + case GF_IOC_ENABLE_SPI_CLK: + pr_info("%s GF_IOC_ENABLE_SPI_CLK. \n", __func__); +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_enable(gf_dev); +#else + pr_info("Doesn't support control clock.\n"); +#endif + break; + case GF_IOC_DISABLE_SPI_CLK: + pr_info("%s GF_IOC_DISABLE_SPI_CLK. \n", __func__); +#ifdef AP_CONTROL_CLK + gfspi_ioctl_clk_disable(gf_dev); +#else + pr_info("Doesn't support control clock.\n"); +#endif + break; + case GF_IOC_ENABLE_POWER: + pr_info("%s GF_IOC_ENABLE_POWER. \n", __func__); + if (gf_dev->device_available == 1) + pr_info("Sensor has already powered-on.\n"); + else + gf_power_on(gf_dev); + gf_dev->device_available = 1; + break; + case GF_IOC_DISABLE_POWER: + pr_info("%s GF_IOC_DISABLE_POWER. \n", __func__); + if (gf_dev->device_available == 0) + pr_info("Sensor has already powered-off.\n"); + else + gf_power_off(gf_dev); + gf_dev->device_available = 0; + break; + case GF_IOC_ENTER_SLEEP_MODE: + pr_info("%s GF_IOC_ENTER_SLEEP_MODE. \n", __func__); + break; + case GF_IOC_GET_FW_INFO: + pr_info("%s GF_IOC_GET_FW_INFO. \n", __func__); + break; + case GF_IOC_REMOVE: + pr_info("%s GF_IOC_REMOVE. \n", __func__); + break; + case GF_IOC_CHIP_INFO: + pr_info("%s GF_IOC_CHIP_INFO. \n", __func__); + if (copy_from_user(&info, (struct gf_ioc_chip_info *) arg, + sizeof(struct gf_ioc_chip_info))) { + retval = -EFAULT; + break; + } + pr_info(" vendor_id : 0x%x \n", info.vendor_id); + pr_info(" mode : 0x%x \n", info.mode); + pr_info(" operation: 0x%x \n", info.operation); + break; + +#if defined(SUPPORT_NAV_EVENT) + case GF_IOC_NAV_EVENT: + pr_debug("%s GF_IOC_NAV_EVENT\n", __func__); + if (copy_from_user(&nav_event, (gf_nav_event_t *)arg, sizeof(gf_nav_event_t))) { + pr_info("Failed to copy nav event from user to kernel\n"); + retval = -EFAULT; + break; + } + + nav_event_input(gf_dev, nav_event); + break; +#endif + + default: + pr_info("Unsupport cmd:0x%x \n", cmd); + break; + } + + return retval; +} + +static void nav_event_input(struct gf_dev *gf_dev, gf_nav_event_t nav_event) +{ + uint32_t nav_input = 0; + + switch (nav_event) { + case GF_NAV_FINGER_DOWN: + pr_debug("%s nav finger down\n", __func__); + break; + + case GF_NAV_FINGER_UP: + + pr_debug("%s nav finger up\n", __func__); + break; + + case GF_NAV_DOWN: + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_UP_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav up\n", __func__); + break; + + case GF_NAV_UP: + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_DOWN_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav down\n", __func__); + break; + + case GF_NAV_LEFT: + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_RIGHT_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav right\n", __func__); + break; + + case GF_NAV_RIGHT: + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, GF_NAV_LEFT_KEY, 0); + input_sync(gf_dev->input); + pr_debug("%s nav left\n", __func__); + break; + + case GF_NAV_CLICK: + + pr_debug("%s nav click\n", __func__); + break; + + case GF_NAV_HEAVY: + nav_input = GF_NAV_INPUT_HEAVY; + pr_debug("%s nav heavy\n", __func__); + break; + + case GF_NAV_LONG_PRESS: + nav_input = GF_NAV_INPUT_LONG_PRESS; + pr_debug("%s nav long press\n", __func__); + break; + + case GF_NAV_DOUBLE_CLICK: + nav_input = GF_NAV_INPUT_DOUBLE_CLICK; + pr_debug("%s nav double click\n", __func__); + break; + + default: + pr_warn("%s unknown nav event: %d\n", __func__, nav_event); + break; + } + + /*if ((nav_event != GF_NAV_FINGER_DOWN) && (nav_event != GF_NAV_FINGER_UP)) { + input_report_key(gf_dev->input, nav_input, 1); + input_sync(gf_dev->input); + input_report_key(gf_dev->input, nav_input, 0); + input_sync(gf_dev->input); + }*/ +} + +#ifdef CONFIG_COMPAT +static long +gf_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return gf_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif /*CONFIG_COMPAT*/ + +static irqreturn_t gf_irq(int irq, void *handle) { +#if defined(GF_NETLINK_ENABLE) + char temp = GF_NET_EVENT_IRQ; +wake_lock_timeout(&fp_wakelock, msecs_to_jiffies(1000)); + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + struct gf_dev *gf_dev = &gf; + if (gf_dev->async) + kill_fasync(&gf_dev->async, SIGIO, POLL_IN); +#endif + + return IRQ_HANDLED; +} + +static int gf_open(struct inode *inode, struct file *filp) { + struct gf_dev *gf_dev; + int status = -ENXIO; + + mutex_lock(&device_list_lock); + + list_for_each_entry(gf_dev, &device_list, device_entry) + { + if (gf_dev->devt == inode->i_rdev) { + pr_info("Found\n"); + status = 0; + break; + } + } + + if (status == 0) { + if (status == 0) { + gf_dev->users++; + filp->private_data = gf_dev; + nonseekable_open(inode, filp); + pr_info("Succeed to open device. irq = %d\n", gf_dev->irq); +/* + if (gf_dev->users == 1) + gf_enable_irq(gf_dev); + //power the sensor + gf_power_on(gf_dev); + gf_hw_reset(gf_dev, 3); +*/ + gf_dev->device_available = 1; + } + } else { + pr_info("No device for minor %d\n", iminor(inode)); + } + mutex_unlock(&device_list_lock); + return status; +} + +#ifdef GF_FASYNC +static int gf_fasync(int fd, struct file *filp, int mode) +{ + struct gf_dev *gf_dev = filp->private_data; + int ret; + + ret = fasync_helper(fd, filp, mode, &gf_dev->async); + pr_info("ret = %d\n", ret); + return ret; +} +#endif + +static int gf_release(struct inode *inode, struct file *filp) { + struct gf_dev *gf_dev; + int status = 0; + + mutex_lock(&device_list_lock); + gf_dev = filp->private_data; + filp->private_data = NULL; + + /*last close?? */ + gf_dev->users--; + if (!gf_dev->users) { + + + + gf_disable_irq(gf_dev); + + devm_free_irq(&gf_dev->spi->dev, gf_dev->irq, gf_dev); + + gf_cleanup(gf_dev); + + /*power off the sensor*/ + gf_dev->device_available = 0; + gf_power_off(gf_dev); + } + mutex_unlock(&device_list_lock); + return status; +} + +static const struct file_operations gf_fops = { .owner = THIS_MODULE, +/* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ +.unlocked_ioctl = gf_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = gf_compat_ioctl, +#endif /*CONFIG_COMPAT*/ + .open = gf_open, .release = gf_release, +#ifdef GF_FASYNC + .fasync = gf_fasync, +#endif + }; + +static int goodix_fb_state_chg_callback(struct notifier_block *nb, + unsigned long val, void *data) { + struct gf_dev *gf_dev; + struct fb_event *evdata = data; + unsigned int blank; + char temp = 0; + + if (val != FB_EARLY_EVENT_BLANK) + return 0; + pr_info("[info] %s go to the goodix_fb_state_chg_callback value = %d\n", + __func__, (int) val); + gf_dev = container_of(nb, struct gf_dev, notifier); + if (evdata && evdata->data && val == FB_EARLY_EVENT_BLANK && gf_dev) { + blank = *(int *) (evdata->data); + switch (blank) { + case FB_BLANK_POWERDOWN: + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 1; +#if defined(GF_NETLINK_ENABLE) + temp = GF_NET_EVENT_FB_BLACK; + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + if (gf_dev->async) { + kill_fasync(&gf_dev->async, SIGIO, + POLL_IN); + } +#endif + /*device unavailable */ + + } + break; + case FB_BLANK_UNBLANK: + if (gf_dev->device_available == 1) { + gf_dev->fb_black = 0; +#if defined(GF_NETLINK_ENABLE) + temp = GF_NET_EVENT_FB_UNBLACK; + sendnlmsg(&temp); +#elif defined (GF_FASYNC) + if (gf_dev->async) { + kill_fasync(&gf_dev->async, SIGIO, + POLL_IN); + } +#endif + /*device available */ + + } + break; + default: + pr_info("%s defalut\n", __func__); + break; + } + } + return NOTIFY_OK; +} + +static struct notifier_block goodix_noti_block = { .notifier_call = + goodix_fb_state_chg_callback, }; + +static void gf_reg_key_kernel(struct gf_dev *gf_dev) { + int i; + + set_bit(EV_KEY, gf_dev->input->evbit); + for (i = 0; i < ARRAY_SIZE(key_map); i++) { + set_bit(key_map[i].val, gf_dev->input->keybit); + } + + set_bit(KEY_SELECT, gf_dev->input->keybit); + + gf_dev->input->name = GF_INPUT_NAME; + if (input_register_device(gf_dev->input)) + pr_warn("Failed to register GF as input device.\n"); +} + +static int driver_init_partial(struct gf_dev *gf_dev) +{ + int ret = 0; + + pr_warn("--------driver_init_partial start.--------\n"); + + gf_dev->device_available = 1; + + if (gf_parse_dts(gf_dev)) + goto error; + + gf_dev->irq = gf_irq_num(gf_dev); + ret = devm_request_threaded_irq(&gf_dev->spi->dev, + gf_dev->irq, + NULL, + gf_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "gf", gf_dev); + if (ret){ + pr_err("Could not request irq %d\n", gpio_to_irq(gf_dev->irq_gpio)); + goto error; + } + if (!ret) { + + gf_enable_irq(gf_dev); + gf_disable_irq(gf_dev); + } + + gf_hw_reset(gf_dev, 360); + + + return 0; + +error: + + gf_cleanup(gf_dev); + + gf_dev->device_available = 0; + + return -EPERM; + + +} + + + + +static struct class *gf_class; +#if defined(USE_SPI_BUS) +static int gf_probe(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_probe(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + int status = -EINVAL; + unsigned long minor; + + + printk("%s %d \n", __func__, __LINE__); + /* Initialize the driver data */ + INIT_LIST_HEAD(&gf_dev->device_entry); +#if defined(USE_SPI_BUS) + gf_dev->spi = spi; +#elif defined(USE_PLATFORM_BUS) + gf_dev->spi = pdev; +#endif + gf_dev->irq_gpio = -EINVAL; + gf_dev->reset_gpio = -EINVAL; + gf_dev->pwr_gpio = -EINVAL; + gf_dev->device_available = 0; + gf_dev->fb_black = 0; + gf_dev->irq_enabled = 0; + gf_dev->fingerprint_pinctrl = NULL; + + + + + + + + /* + if (gf_power_on(gf_dev)) + goto error; + gf_dev->device_available = 1; + */ + /* If we can allocate a minor number, hook up this device. + * Reusing minors is fine so long as udev or mdev is working. + */ + mutex_lock(&device_list_lock); + minor = find_first_zero_bit(minors, N_SPI_MINORS); + if (minor < N_SPI_MINORS) { + struct device *dev; + + gf_dev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(gf_class, &gf_dev->spi->dev, gf_dev->devt, gf_dev, + GF_DEV_NAME); + status = IS_ERR(dev) ? PTR_ERR(dev) : 0; + } else { + dev_dbg(&gf_dev->spi->dev, "no minor number available!\n"); + status = -ENODEV; + } + + + if (status == 0) { + set_bit(minor, minors); + list_add(&gf_dev->device_entry, &device_list); + } else { + gf_dev->devt = 0; + } + mutex_unlock(&device_list_lock); + + + if (status == 0) { + /*input device subsystem */ + + gf_dev->input = input_allocate_device(); + if (gf_dev->input == NULL) { + pr_info("%s, Failed to allocate input device.\n", __func__); + status = -ENOMEM; + goto error; + } + + __set_bit(EV_KEY, gf_dev->input->evbit); + __set_bit(GF_INPUT_HOME_KEY, gf_dev->input->keybit); + + __set_bit(GF_INPUT_MENU_KEY, gf_dev->input->keybit); + __set_bit(GF_INPUT_BACK_KEY, gf_dev->input->keybit); + __set_bit(GF_INPUT_FF_KEY, gf_dev->input->keybit); + + __set_bit(GF_NAV_UP_KEY, gf_dev->input->keybit); + __set_bit(GF_NAV_DOWN_KEY, gf_dev->input->keybit); + __set_bit(GF_NAV_RIGHT_KEY, gf_dev->input->keybit); + __set_bit(GF_NAV_LEFT_KEY, gf_dev->input->keybit); + __set_bit(GF_INPUT_CAMERA_KEY, gf_dev->input->keybit); + __set_bit(GF_CLICK_KEY, gf_dev->input->keybit); + __set_bit(GF_DOUBLE_CLICK_KEY, gf_dev->input->keybit); + __set_bit(GF_LONG_PRESS_KEY, gf_dev->input->keybit); + } +#ifdef AP_CONTROL_CLK + pr_info("Get the clk resource.\n"); + /* Enable spi clock */ + if (gfspi_ioctl_clk_init(gf_dev)) + goto gfspi_probe_clk_init_failed; + + if (gfspi_ioctl_clk_enable(gf_dev)) + goto gfspi_probe_clk_enable_failed; + + spi_clock_set(gf_dev, 1000000); +#endif + + + gf_dev->notifier = goodix_noti_block; + fb_register_client(&gf_dev->notifier); + gf_reg_key_kernel(gf_dev); + +wake_lock_init(&fp_wakelock, WAKE_LOCK_SUSPEND, "fp_wakelock"); + + +/* + gf_dev->irq = gf_irq_num(gf_dev); +#if 1 + ret = request_threaded_irq(gf_dev->irq, NULL, gf_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, "gf", gf_dev); +#else + ret = request_irq(gf_dev->irq, gf_irq, + IRQ_TYPE_EDGE_RISING, //IRQ_TYPE_LEVEL_HIGH, + "gf", gf_dev); +#endif + //printk("%s %d \n", __func__, __LINE__); + if (!ret) { + enable_irq_wake(gf_dev->irq); + gf_disable_irq(gf_dev); + } +*/ + + printk("%s %d end, status = %d\n", __func__, __LINE__, status); + + return status; + + error: gf_cleanup(gf_dev); + gf_dev->device_available = 0; + if (gf_dev->devt != 0) { + pr_info("Err: status = %d\n", status); + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + mutex_unlock(&device_list_lock); +#ifdef AP_CONTROL_CLK + gfspi_probe_clk_enable_failed: gfspi_ioctl_clk_uninit(gf_dev); + gfspi_probe_clk_init_failed: +#endif + if (gf_dev->input != NULL) + input_unregister_device(gf_dev->input); + } + + return status; +} + +/*static int __devexit gf_remove(struct spi_device *spi)*/ +#if defined(USE_SPI_BUS) +static int gf_remove(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_remove(struct platform_device *pdev) +#endif +{ + struct gf_dev *gf_dev = &gf; + + /* make sure ops on existing fds can abort cleanly */ + if (gf_dev->irq) + free_irq(gf_dev->irq, gf_dev); + + if (gf_dev->input != NULL) + input_unregister_device(gf_dev->input); + input_free_device(gf_dev->input); + + /* prevent new opens */ + mutex_lock(&device_list_lock); + list_del(&gf_dev->device_entry); + device_destroy(gf_class, gf_dev->devt); + clear_bit(MINOR(gf_dev->devt), minors); + if (gf_dev->users == 0) + gf_cleanup(gf_dev); + + fb_unregister_client(&gf_dev->notifier); + mutex_unlock(&device_list_lock); +wake_lock_destroy(&fp_wakelock); + return 0; +} + +#if defined(USE_SPI_BUS) +static int gf_suspend(struct spi_device *spi, pm_message_t mesg) +#elif defined(USE_PLATFORM_BUS) +static int gf_suspend(struct platform_device *pdev, pm_message_t state) +#endif +{ +#if 0 + struct gf_dev *gfspi_device; + + pr_debug("%s: enter\n", __func__); + + gfspi_device = spi_get_drvdata(spi); + gfspi_ioctl_clk_disable(gfspi_device); +#endif + pr_info(KERN_ERR "gf_suspend_test.\n"); + return 0; +} + +#if defined(USE_SPI_BUS) +static int gf_resume(struct spi_device *spi) +#elif defined(USE_PLATFORM_BUS) +static int gf_resume(struct platform_device *pdev) +#endif +{ +#if 0 + struct gf_dev *gfspi_device; + + pr_debug("%s: enter\n", __func__); + + gfspi_device = spi_get_drvdata(spi); + gfspi_ioctl_clk_enable(gfspi_device); +#endif + pr_info(KERN_ERR "gf_resume_test.\n"); + return 0; +} + +/* + static const struct dev_pm_ops gx_pm = { + .suspend = gf_suspend_test, + .resume = gf_resume_test + }; + */ +static struct of_device_id gx_match_table[] = { + { .compatible = GF_SPIDEV_NAME, }, { }, }; + +#if defined(USE_SPI_BUS) +static struct spi_driver gf_driver = { +#elif defined(USE_PLATFORM_BUS) + static struct platform_driver gf_driver = { +#endif + .driver = { .name = GF_DEV_NAME, .owner = THIS_MODULE, +#if defined(USE_SPI_BUS) + +#endif + .of_match_table = gx_match_table, }, .probe = gf_probe, + .remove = gf_remove, .suspend = gf_suspend, .resume = gf_resume, }; + +static int __init gf_init(void) { + int status; + + /* Claim our 256 reserved device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * the driver which manages those device numbers. + */ + + BUILD_BUG_ON(N_SPI_MINORS > 256); + status = register_chrdev(SPIDEV_MAJOR, CHRD_DRIVER_NAME, &gf_fops); + if (status < 0) { + pr_warn("Failed to register char device!\n"); + return status; + } + gf_class = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(gf_class)) { + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to create class.\n"); + return PTR_ERR(gf_class); + } +#if defined(USE_PLATFORM_BUS) + status = platform_driver_register(&gf_driver); +#elif defined(USE_SPI_BUS) + status = spi_register_driver(&gf_driver); +#endif + if (status < 0) { + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); + pr_warn("Failed to register SPI driver.\n"); + } + +#ifdef GF_NETLINK_ENABLE + netlink_init(); +#endif + pr_info(" status = 0x%x\n", status); + return 0; +} + +module_init(gf_init); + +static void __exit gf_exit(void) { +#ifdef GF_NETLINK_ENABLE + netlink_exit(); +#endif +#if defined(USE_PLATFORM_BUS) + platform_driver_unregister(&gf_driver); +#elif defined(USE_SPI_BUS) + spi_unregister_driver(&gf_driver); +#endif + class_destroy(gf_class); + unregister_chrdev(SPIDEV_MAJOR, gf_driver.driver.name); +} + +module_exit(gf_exit); + +MODULE_AUTHOR("Jiangtao Yi, "); +MODULE_DESCRIPTION("User mode SPI device interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:gf-spi"); diff --git a/drivers/input/fingerprint/goodix_e7/gf_spi.h b/drivers/input/fingerprint/goodix_e7/gf_spi.h new file mode 100644 index 0000000000000..b8c6e1fe2b9d5 --- /dev/null +++ b/drivers/input/fingerprint/goodix_e7/gf_spi.h @@ -0,0 +1,165 @@ +#ifndef __GF_SPI_H +#define __GF_SPI_H + +#include +#include +/**********************************************************/ +enum FP_MODE { + GF_IMAGE_MODE = 0, + GF_KEY_MODE, + GF_SLEEP_MODE, + GF_FF_MODE, + GF_DEBUG_MODE = 0x56 +}; + +#define SUPPORT_NAV_EVENT +#if defined(SUPPORT_NAV_EVENT) + + + + + +#define GF_NAV_INPUT_DOUBLE_CLICK KEY_VOLUMEUP +#define GF_NAV_INPUT_LONG_PRESS KEY_SEARCH +#define GF_NAV_INPUT_HEAVY KEY_CHAT +#endif + + +#if defined(SUPPORT_NAV_EVENT) +typedef enum gf_nav_event { + GF_NAV_NONE = 0, + GF_NAV_FINGER_UP, + GF_NAV_FINGER_DOWN, + GF_NAV_UP, + GF_NAV_DOWN, + GF_NAV_LEFT, + GF_NAV_RIGHT, + GF_NAV_CLICK, + GF_NAV_HEAVY, + GF_NAV_LONG_PRESS, + GF_NAV_DOUBLE_CLICK, +} gf_nav_event_t; +#endif + +typedef enum gf_key_event { + GF_KEY_NONE = 0, + GF_KEY_HOME, + GF_KEY_POWER, + GF_KEY_MENU, + GF_KEY_BACK, + GF_KEY_CAPTURE, + GF_KEY_UP, + GF_KEY_DOWN, + GF_KEY_RIGHT, + GF_KEY_LEFT, + GF_KEY_TAP, + GF_KEY_HEAVY, + GF_KEY_LONG_PRESS, + GF_KEY_DOUBLE_TAP +} gf_key_event_t; + +struct gf_key { + enum gf_key_event key; + uint32_t value; /* key down = 1, key up = 0 */ +}; + +struct gf_key_map { + char *name; + unsigned short val; +}; + +struct gf_ioc_chip_info { + unsigned char vendor_id; + unsigned char mode; + unsigned char operation; + unsigned char reserved[5]; +}; + +#define GF_IOC_MAGIC 'g' +#define GF_IOC_INIT _IOR(GF_IOC_MAGIC, 0, uint8_t) +#define GF_IOC_EXIT _IO(GF_IOC_MAGIC, 1) +#define GF_IOC_RESET _IO(GF_IOC_MAGIC, 2) +#define GF_IOC_ENABLE_IRQ _IO(GF_IOC_MAGIC, 3) +#define GF_IOC_DISABLE_IRQ _IO(GF_IOC_MAGIC, 4) +#define GF_IOC_ENABLE_SPI_CLK _IOW(GF_IOC_MAGIC, 5, uint32_t) +#define GF_IOC_DISABLE_SPI_CLK _IO(GF_IOC_MAGIC, 6) +#define GF_IOC_ENABLE_POWER _IO(GF_IOC_MAGIC, 7) +#define GF_IOC_DISABLE_POWER _IO(GF_IOC_MAGIC, 8) +#define GF_IOC_INPUT_KEY_EVENT _IOW(GF_IOC_MAGIC, 9, struct gf_key) +#define GF_IOC_ENTER_SLEEP_MODE _IO(GF_IOC_MAGIC, 10) +#define GF_IOC_GET_FW_INFO _IOR(GF_IOC_MAGIC, 11, uint8_t) +#define GF_IOC_REMOVE _IO(GF_IOC_MAGIC, 12) +#define GF_IOC_CHIP_INFO _IOR(GF_IOC_MAGIC, 13, struct gf_ioc_chip_info) +#define GF_IOC_ENABLE_GPIO _IO(GF_IOC_MAGIC, 15) +#define GF_IOC_RELEASE_GPIO _IO(GF_IOC_MAGIC, 16) + +#if defined(SUPPORT_NAV_EVENT) +#define GF_IOC_NAV_EVENT _IOW(GF_IOC_MAGIC, 14, gf_nav_event_t) +#define GF_IOC_MAXNR 15 /* THIS MACRO IS NOT USED NOW... */ +#else +#define GF_IOC_MAXNR 14 /* THIS MACRO IS NOT USED NOW... */ +#endif + + +#define USE_PLATFORM_BUS 1 + + +#define GF_NETLINK_ENABLE 1 +#define GF_NET_EVENT_IRQ 1 +#define GF_NET_EVENT_FB_BLACK 2 +#define GF_NET_EVENT_FB_UNBLACK 3 +#define NETLINK_TEST 25 + + +static const char * const pctl_names[] = { + + "goodixfp_reset_reset", + "goodixfp_reset_active", + "goodixfp_irq_active", +}; + +struct gf_dev { + dev_t devt; + struct list_head device_entry; +#if defined(USE_SPI_BUS) + struct spi_device *spi; +#elif defined(USE_PLATFORM_BUS) + struct platform_device *spi; +#endif + struct clk *core_clk; + struct clk *iface_clk; + + struct pinctrl *fingerprint_pinctrl; + struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)]; + + struct input_dev *input; + /* buffer is NULL unless this device is open (users > 0) */ + unsigned users; + signed irq_gpio; + signed reset_gpio; + signed pwr_gpio; + int irq; + int irq_enabled; + int clk_enabled; +#ifdef GF_FASYNC + struct fasync_struct *async; +#endif + struct notifier_block notifier; + char device_available; + char fb_black; + +}; + +int gf_parse_dts(struct gf_dev *gf_dev); +void gf_cleanup(struct gf_dev *gf_dev); + +int gf_power_on(struct gf_dev *gf_dev); +int gf_power_off(struct gf_dev *gf_dev); + +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms); +int gf_irq_num(struct gf_dev *gf_dev); + +void sendnlmsg(char *message); +int netlink_init(void); +void netlink_exit(void); +#endif /*__GF_SPI_H*/ diff --git a/drivers/input/fingerprint/goodix_e7/netlink.c b/drivers/input/fingerprint/goodix_e7/netlink.c new file mode 100755 index 0000000000000..d97f089df8768 --- /dev/null +++ b/drivers/input/fingerprint/goodix_e7/netlink.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include + +#define NETLINK_TEST 25 +#define MAX_MSGSIZE 32 +int stringlength(char *s); +void sendnlmsg(char *message); +int pid; +int err; +struct sock *nl_sk = NULL; +int flag = 0; + + +struct gf_uk_channel{ + int channel_id; + int reserved; + char buf[3*1024]; + int len; +}; + + +void sendnlmsg(char *message) +{ + struct sk_buff *skb_1; + struct nlmsghdr *nlh; + int len = NLMSG_SPACE(MAX_MSGSIZE); + int slen = 0; + int ret = 0; + if (!message || !nl_sk || !pid) + { + return ; + } + skb_1 = alloc_skb(len, GFP_KERNEL); + if (!skb_1) + { + printk(KERN_ERR "my_net_link:alloc_skb_1 error\n"); + } + slen = strlen(message); + nlh = nlmsg_put(skb_1, 0, 0, 0, MAX_MSGSIZE, 0); + + NETLINK_CB(skb_1).portid = 0; + NETLINK_CB(skb_1).dst_group = 0; + + message[slen] = '\0'; + memcpy(NLMSG_DATA(nlh), message, slen+1); + + + ret = netlink_unicast(nl_sk, skb_1, pid, MSG_DONTWAIT); + if (!ret) { + + printk("send msg from kernel to usespace failed ret 0x%x \n", ret); + } + +} + + +void nl_data_ready(struct sk_buff *__skb) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + char str[100]; + skb = skb_get (__skb); + if (skb->len >= NLMSG_SPACE(0)) + { + nlh = nlmsg_hdr(skb); + + memcpy(str, NLMSG_DATA(nlh), sizeof(str)); + pid = nlh->nlmsg_pid; + + if (pid) + printk("Message pid %d received:%s\n", pid, str) ; + + kfree_skb(skb); + } + +} + + +int netlink_init(void) +{ + struct netlink_kernel_cfg netlink_cfg; + memset(&netlink_cfg, 0, sizeof(struct netlink_kernel_cfg)); + + netlink_cfg.groups = 0; + netlink_cfg.flags = 0; + netlink_cfg.input = nl_data_ready; + netlink_cfg.cb_mutex = NULL; + + + nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, + &netlink_cfg); + + if (!nl_sk){ + printk(KERN_ERR "my_net_link: create netlink socket error.\n"); + return 1; + } + + return 0; +} + +void netlink_exit(void) +{ + if (nl_sk != NULL){ + netlink_kernel_release(nl_sk); + nl_sk = NULL; + } + + printk("my_net_link: self module exited\n"); +} + diff --git a/drivers/input/fingerprint/goodix_e7/platform.c b/drivers/input/fingerprint/goodix_e7/platform.c new file mode 100644 index 0000000000000..616e151a27553 --- /dev/null +++ b/drivers/input/fingerprint/goodix_e7/platform.c @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gf_spi.h" + +#if defined(USE_SPI_BUS) +#include +#include +#elif defined(USE_PLATFORM_BUS) +#include +#endif + +#define gf_dbg(fmt, args...) do { \ + pr_warn("gf:" fmt, ##args);\ + } while (0) + + +static int gf3208_request_named_gpio(struct gf_dev *gf_dev, const char *label, int *gpio) +{ + struct device *dev = &gf_dev->spi->dev; + struct device_node *np = dev->of_node; + int rc = of_get_named_gpio(np, label, 0); + if (rc < 0) { + dev_err(dev, "failed to get '%s'\n", label); + return rc; + } + *gpio = rc; + rc = devm_gpio_request(dev, *gpio, label); + if (rc) { + dev_err(dev, "failed to request gpio %d\n", *gpio); + return rc; + } + dev_err(dev, "%s %d\n", label, *gpio); + return 0; +} + +static int select_pin_ctl(struct gf_dev *gf_dev, const char *name) +{ + size_t i; + int rc; + struct device *dev = &gf_dev->spi->dev; + + for (i = 0; i < ARRAY_SIZE(gf_dev->pinctrl_state); i++) { + const char *n = pctl_names[i]; + if (!strncmp(n, name, strlen(n))) { + rc = pinctrl_select_state(gf_dev->fingerprint_pinctrl, gf_dev->pinctrl_state[i]); + + if (rc) + dev_err(dev, "cannot select '%s'\n", name); + else + dev_err(dev, "Selected '%s'\n", name); + goto exit; + } + } + rc = -EINVAL; + dev_err(dev, "%s:'%s' not found\n", __func__, name); +exit: + return rc; +} + + +/*GPIO pins reference.*/ +int gf_parse_dts(struct gf_dev *gf_dev) +{ + int rc = 0; + int i = 0; + pr_warn("--------gf_parse_dts start haijun.--------\n"); + + /*get reset resource*/ + rc = gf3208_request_named_gpio(gf_dev, "goodix,gpio_reset", &gf_dev->reset_gpio); + if (rc) { + + gf_dbg("Failed to request RESET GPIO. rc = %d\n", rc); + return -EPERM; + } + + + /*get irq resourece*/ + rc = gf3208_request_named_gpio(gf_dev, "goodix,gpio_irq", &gf_dev->irq_gpio); + if (rc) { + + gf_dbg("Failed to request IRQ GPIO. rc = %d\n", rc); + return -EPERM; + } + + + gf_dev->fingerprint_pinctrl = devm_pinctrl_get(&gf_dev->spi->dev); + for (i = 0; i < ARRAY_SIZE(gf_dev->pinctrl_state); i++) { + const char *n = pctl_names[i]; + struct pinctrl_state *state = + pinctrl_lookup_state(gf_dev->fingerprint_pinctrl, n); + if (IS_ERR(state)) { + pr_err("cannot find '%s'\n", n); + rc = -EINVAL; + } + pr_info("found pin control %s\n", n); + gf_dev->pinctrl_state[i] = state; + } + + rc = select_pin_ctl(gf_dev, "goodixfp_reset_active"); + if (rc) + goto exit; + rc = select_pin_ctl(gf_dev, "goodixfp_irq_active"); + if (rc) + goto exit; + + + + + pr_warn("--------gf_parse_dts end---OK.--------\n"); + +exit: + return rc; + + +} + +void gf_cleanup(struct gf_dev * gf_dev) +{ + gf_dbg("[info] enter%s\n", __func__); + + if (gpio_is_valid(gf_dev->irq_gpio)) + { + + devm_gpio_free(&gf_dev->spi->dev, gf_dev->irq_gpio); + gf_dbg("remove irq_gpio success\n"); + } + + if (gpio_is_valid(gf_dev->reset_gpio)) + { + + devm_gpio_free(&gf_dev->spi->dev, gf_dev->reset_gpio); + gf_dbg("remove reset_gpio success\n"); + } + + if (gf_dev->fingerprint_pinctrl != NULL){ + devm_pinctrl_put(gf_dev->fingerprint_pinctrl); + gf_dev->fingerprint_pinctrl = NULL; + + gf_dbg("gx fingerprint_pinctrl release success\n"); + } +/* if (gpio_is_valid(gf_dev->pwr_gpio)) + { + gpio_free(gf_dev->pwr_gpio); + pr_info("remove pwr_gpio success\n"); + } */ +} + +/*power management*/ +int gf_power_on(struct gf_dev *gf_dev) +{ + int rc = 0; +/* if (gpio_is_valid(gf_dev->pwr_gpio)) { + gpio_set_value(gf_dev->pwr_gpio, 1); + } */ + msleep(10); + pr_info("---- power on ok ----\n"); + + return rc; +} + +int gf_power_off(struct gf_dev *gf_dev) +{ + int rc = 0; +/* if (gpio_is_valid(gf_dev->pwr_gpio)) { + gpio_set_value(gf_dev->pwr_gpio, 1); + } */ + pr_info("---- power off ----\n"); + return rc; +} + +static int hw_reset(struct gf_dev *gf_dev) +{ + int irq_gpio; + struct device *dev = &gf_dev->spi->dev; + int rc ; + + + + + + rc = select_pin_ctl(gf_dev, "goodixfp_reset_reset"); + if (rc) + goto exit; + mdelay(3); + rc = select_pin_ctl(gf_dev, "goodixfp_reset_active"); + if (rc) + goto exit; + + irq_gpio = gpio_get_value(gf_dev->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); +exit: + return rc; +} + + +/******************************************************************** + *CPU output low level in RST pin to reset GF. This is the MUST action for GF. + *Take care of this function. IO Pin driver strength / glitch and so on. + ********************************************************************/ +int gf_hw_reset(struct gf_dev *gf_dev, unsigned int delay_ms) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } + hw_reset(gf_dev); + mdelay(delay_ms); + return 0; +} + +int gf_irq_num(struct gf_dev *gf_dev) +{ + if (gf_dev == NULL) { + pr_info("Input buff is NULL.\n"); + return -EPERM; + } else { + return gpio_to_irq(gf_dev->irq_gpio); + } +} + diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index a5826419da4ad..b37dcf6376ee0 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -11,8 +11,8 @@ menuconfig INPUT_TOUCHSCREEN if INPUT_TOUCHSCREEN -source "drivers/input/touchscreen/synaptics_dsx/Kconfig" -source "drivers/input/touchscreen/synaptics_dsx_2.6/Kconfig" +#source "drivers/input/touchscreen/synaptics_dsx/Kconfig" +#source "drivers/input/touchscreen/synaptics_dsx_2.6/Kconfig" config OF_TOUCHSCREEN def_tristate INPUT @@ -1113,16 +1113,6 @@ config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE To compile this driver as a module, choose M here: the module will be called synaptics_dsx_fw_update. -config TOUCHSCREEN_GT9XX - bool "Goodix touchpanel GT9xx series" - depends on I2C - help - Say Y here if you have a Goodix GT9xx touchscreen. - Gt9xx controllers are multi touch controllers which can - report 5 touches at a time. - - If unsure, say N. - config TOUCHSCREEN_MAXIM_STI tristate "Maxim based STI touchscreens" depends on SPI_MASTER @@ -1135,8 +1125,92 @@ config TOUCHSCREEN_MAXIM_STI To compile this driver as a module, choose M here: the module will be called maxim_sti. -source "drivers/input/touchscreen/gt9xx/Kconfig" -source "drivers/input/touchscreen/focaltech_touch/Kconfig" +config TOUCHSCREEN_FT5435 + tristate "FocalTech touchscreens" + depends on I2C + help + Say Y here if you have a ft5435 touchscreen. + Ft5435 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft5435_ts. + +config TOUCHSCREEN_FT5446 + tristate "FocalTech touchscreens" + depends on I2C + help + Say Y here if you have a ft5446 touchscreen. + Ft5446 controllers are multi touch controllers which can + report 10 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ft5446_ts. + +config TOUCHSCREEN_GT917d + tristate "Goodix touchscreens" + depends on I2C + help + Say Y here if you have a GT917d touchscreen. + GT917d controllers are multi touch controllers which can + report 10 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called GT917d. + +config TOUCHSCREEN_TD4310_E7 + tristate "synaptics touchscreens" + depends on I2C + help + Say Y here if you have a ist3038c touchscreen. + Ft5x06 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ist3038c_ts. + +config TOUCHSCREEN_NT36672 + bool "Novatek NT36672" + default y + help + Say Y here if you have a Novatek NT36672 touchscreen connected + to your system. + + If unsure, say N. + +config TOUCHSCREEN_TD4310_LANSI_E7 + tristate "synaptics touchscreens" + depends on I2C + help + Say Y here if you have a ist3038c touchscreen. + Ft5x06 controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called ist3038c_ts. + +config VITURALSAR + bool "Vitural Sar series" + depends on I2C + help + Say Y here if you have a Goodix GT9xx touchscreen. + Gt9xx controllers are multi touch controllers which can + report 5 touches at a time. + + If unsure, say N. + +source "drivers/input/touchscreen/ft5446/Kconfig" +source "drivers/input/touchscreen/gt917d/Kconfig" config TOUCHSCREEN_HIMAX_CHIPSET bool "Himax touchpanel CHIPSET" @@ -1149,5 +1223,4 @@ config TOUCHSCREEN_HIMAX_CHIPSET If unsure, say N. source "drivers/input/touchscreen/hxchipset/Kconfig" - endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 2ee0820986ed1..0c88195ba0041 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -63,8 +63,8 @@ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v21) += synaptics_dsx/ -obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v26) += synaptics_dsx_2.6/ +# obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v21) += synaptics_dsx/ +# obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_v26) += synaptics_dsx_2.6/ obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o @@ -91,4 +91,10 @@ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += hxchipset/ -obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/ +obj-$(CONFIG_TOUCHSCREEN_FT5435) += ft5435/ +obj-$(CONFIG_TOUCHSCREEN_GT917d) += gt917d/ +obj-$(CONFIG_TOUCHSCREEN_FT5446) += ft5446/ +obj-$(CONFIG_TOUCHSCREEN_TD4310_E7) += td4310_e7/ +obj-$(CONFIG_TOUCHSCREEN_NT36672) += nt36672/ +obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += td4310_lansi_e7/ +obj-$(CONFIG_VITURALSAR) += vituralsar_driver.o diff --git a/drivers/input/touchscreen/ft5435/D1S_1_FT5446_Ofilm_TM_Black_V01_D01_20171219_app.i b/drivers/input/touchscreen/ft5435/D1S_1_FT5446_Ofilm_TM_Black_V01_D01_20171219_app.i new file mode 100644 index 0000000000000..8a2e4835b0037 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/D1S_1_FT5446_Ofilm_TM_Black_V01_D01_20171219_app.i @@ -0,0 +1,3164 @@ +0x2, 0x1e,0xcc,0x2, 0xb5,0x84,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x49,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x59,0x22,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x68,0x5b,0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x12,0x96,0x7f,0x6, 0x12,0x4, 0x8d,0x7f,0x6, 0x2, +0x8, 0xd0,0x22,0x2, 0x6c,0x8d,0x2, 0x29,0xba,0x32,0x32,0x2, 0x0, 0x4a,0x12,0xf, +0x69,0x2, 0x12,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x2f,0xf7,0xff,0xff,0x2, 0x0, 0x5a,0xa2,0x16, +0x22,0xff,0xff,0x2, 0xf, 0x19,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xf, 0x7e,0xf, 0x33,0xea, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x33,0xfa,0x7e,0x73,0x33,0xfa,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xe, 0x80,0x2, 0xc2,0xe, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x11,0x9e,0x12,0x70,0x56,0x7e,0x1f,0x33,0xea,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x33,0xea,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x33,0xee,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x33,0xf6,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x33,0xf4,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x3a,0x27,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0xb8,0x5e,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x18,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x18,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1d,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x41, +0x5d,0x74,0x1, 0x7a,0x5b,0xb0,0x41,0x5d,0x7c,0xbe,0x14,0xbe,0xb0,0x15,0x40,0x2, +0x41,0x9, 0x7e,0xa0,0x3, 0xa4,0x90,0x1, 0x8a,0x73,0x2, 0x1, 0xcb,0x2, 0x1, 0xcb, +0x2, 0x2, 0x9, 0x2, 0x1, 0xcb,0x2, 0x2, 0x9, 0x2, 0x1, 0xd1,0x2, 0x1, 0xcb,0x2, +0x2, 0x9, 0x2, 0x2, 0x9, 0x2, 0x1, 0xcb,0x2, 0x2, 0x9, 0x2, 0x1, 0xcb,0x2, 0x2, +0x9, 0x2, 0x2, 0x9, 0x2, 0x1, 0xfb,0x2, 0x2, 0x9, 0x2, 0x1, 0xdf,0x2, 0x1, 0xcb, +0x2, 0x1, 0xed,0x2, 0x1, 0xed,0x2, 0x1, 0xcb,0x21,0xcb,0x7e,0x34,0x1d,0x19,0x41, +0xd, 0x7e,0x34,0x1d,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1c,0xe2,0x41,0x15,0x7e, +0x34,0x1d,0x19,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1c,0xb2,0x41,0x15,0x7e,0x34,0x1c, +0x96,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1c,0xc6,0x41,0x15,0x7e,0x34,0x1d,0xa, 0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1c,0xf1,0x41,0x15,0x7e,0x34,0x1d,0x45,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0x29,0x79,0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x41,0x24, +0x7c,0xfe,0x41,0x3b,0x7e,0xf0,0x16,0xbe,0xe0,0x49,0x68,0x2, 0x41,0x32,0xb, 0xf0, +0x41,0x3b,0xbe,0xe0,0x4a,0x68,0x2, 0x41,0x3b,0xb, 0xf1,0x7e,0x70,0x3, 0xac,0x7f, +0x7d,0x23,0x2e,0x24,0x1d,0x69,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b, +0xb0,0x2e,0x34,0x1d,0x6a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, +0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74,0x1, 0x12,0x12,0xde,0x29,0x73,0x0, +0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, 0xf4,0x12,0x12,0xaf,0x7f,0x3, 0x12, +0xb, 0xe9,0x7f,0x3, 0x12,0x5, 0x93,0x29,0x73,0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x33, +0xea,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3,0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e, +0xf, 0x33,0xea,0x79,0x30,0x0, 0x2, 0x29,0x73,0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, +0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x35,0x29,0xb3,0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, +0xf8,0x29,0x73,0x0, 0xf7,0x12,0xa, 0x24,0x29,0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92, +0x1, 0xe5,0x35,0x12,0x9, 0x95,0x69,0x33,0x0, 0xfd,0x7e,0xf, 0x33,0xea,0x79,0x30, +0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30, +0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x2c, +0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, +0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x2e,0x29,0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, +0x33,0xea,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, 0xa8,0x7e,0xf, 0x33,0xea,0x79,0x30, +0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x1e,0x6c,0xaa, +0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, 0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, +0xa, 0x30,0x7e,0xf, 0x33,0xea,0x2d,0x12,0x79,0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0, +0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f,0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, +0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17,0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, +0xf2,0x74,0xff,0x12,0x1f,0xee,0x7f,0x7, 0x12,0xd, 0xc4,0xa9,0xd6,0xcb,0x6c,0xaa, +0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, 0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e, +0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, 0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff, +0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, 0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e, +0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, 0x6, 0x7e,0xf, 0x3a,0x3d,0x79,0x30, +0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d,0x32,0x7e,0xf, 0x3a,0x3d,0x79,0x30, +0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3a,0x3d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12, +0xe, 0x1c,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18,0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7, +0x7e,0x1f,0x3a,0x3d,0x69,0x41,0x0, 0x26,0x60,0x42,0x1e,0x44,0x14,0x78,0xfb,0x80, +0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b,0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7, +0x7e,0x1f,0x3a,0x3d,0x69,0x41,0x0, 0x28,0x60,0x22,0x1e,0x44,0x14,0x78,0xfb,0x80, +0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3a, +0x3d,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44,0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, +0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, 0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40, +0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6,0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, +0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97,0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, +0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17, +0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80,0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e, +0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90,0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe, +0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60,0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe, +0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26, +0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34, +0x2d,0x32,0x7e,0x7f,0x3a,0x27,0x79,0x37,0x0, 0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b, +0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x33,0xe2,0x79,0x37, +0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x3a,0x27,0x79,0x37,0x0, 0xc, 0x69,0x30, +0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, 0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24, +0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e,0x7f,0x33,0xe2,0x79,0x37,0x0, 0x82, +0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b, +0x2d,0x32,0x7e,0x7f,0x3a,0x27,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f, +0x3a,0x27,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, 0x9a,0x7e,0xf, 0x3a,0x27,0x79,0x30, +0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x12,0xde,0x29,0x36,0x0, 0xf5,0x29,0x26, +0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, 0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10, +0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, 0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34, +0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x12,0x7c, +0x73,0xac,0x70,0xa, 0x21,0x12,0x1d,0xb3,0x7c,0x27,0xa, 0x32,0x7e,0x2f,0x33,0xea, +0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29,0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32, +0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1d,0xb3,0x7c, +0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0,0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe, +0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20,0xa, 0x31,0x12,0x1d,0xb3,0x7d,0xe3, +0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe,0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34, +0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, 0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d, +0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, 0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e, +0x7f,0x33,0xea,0x79,0x17,0x0, 0xa, 0x1e,0x24,0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d, +0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0xc, 0xa, 0x3a,0x7e,0xf, 0x33,0xea,0x79, +0x30,0x0, 0x22,0x22,0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x3a, +0x3d,0x79,0x37,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x3a,0x3d,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x6, 0x7e,0x7f,0x3a,0x3d,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, +0x1, 0x7c,0x47,0x6c,0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x3a,0x3d, +0x79,0x37,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x3a,0x3d, +0x79,0x37,0x0, 0xa, 0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x3a,0x3d,0x79,0x37,0x0, 0xe, +0x69,0x30,0x0, 0xc, 0x7e,0x7f,0x3a,0x3d,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, +0x7e,0x7f,0x3a,0x3d,0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33, +0x7e,0x1f,0x3a,0x3d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xe, 0x1c,0x7e,0x1f, +0x3a,0x3d,0x69,0x11,0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, +0x1, 0x69,0x11,0x0, 0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, +0x4, 0x69,0x11,0x0, 0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, +0x8, 0x69,0x11,0x0, 0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, +0xc, 0xa9,0xc6,0xcb,0x22,0x7c,0x7b,0x7e,0x7f,0x33,0xea,0x69,0x47,0x0, 0xc, 0x6c, +0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54,0x1e, +0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14,0x0, +0x4, 0x70,0x2, 0xe1,0x7a,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad,0xd0, +0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0xe1,0x93,0x1e,0xd4, +0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0xe1,0xa1,0x7e,0xd4,0x1, 0x0, 0xe1, +0xad,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0xe1,0xad,0x7e,0xd4,0x0, 0x10,0x7d,0x3d,0x12, +0x11,0x6a,0xa, 0x1b,0x7e,0x1f,0x33,0xea,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x33,0xea, +0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x33,0xea,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d,0x3d, +0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x33,0xea,0x79,0x11,0x0, 0x94, +0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x96, +0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x98,0x22,0x2, 0x32,0xc0, +0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60,0x3f, +0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e,0x7b, +0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0,0x0, +0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e,0xd0, +0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac, +0xf4,0x2d,0xd7,0x7e,0x7f,0x3a,0x23,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0,0xbe, +0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, 0xb, +0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac, +0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3a,0x23, +0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90,0xf0, +0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x3a,0x23,0x2d,0x5f, +0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28,0xac, +0x5b,0x2d,0x21,0x7e,0xf, 0x3a,0x23,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b,0x22, +0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c,0x65, +0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29,0xb0, +0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, 0xac, +0x9a,0x7e,0x7f,0x33,0xe2,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0,0x23, +0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, 0x4c, +0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89,0x6c, +0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x33,0xe2,0x2d,0xf4,0xb, 0xf5, +0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29,0x47, +0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x33,0xe2,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7,0x6c, +0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46,0x7e, +0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x33,0xe2,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, 0xa0, +0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x5b,0x7e,0xf, 0x33,0xea,0x69,0x40,0x0, 0x22,0x30, +0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe,0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79, +0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c,0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x6f,0x33,0xea,0x79,0x36,0x0, 0x40,0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80, +0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f, +0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x7f,0x33,0xea,0x79,0x37,0x0, 0x42,0x7d,0x34, +0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x33,0xea,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79, +0x30,0x0, 0x40,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x42,0x7e,0x1f,0x33,0xea,0x79, +0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c,0x3b,0x6d,0x33,0x7e,0x2f,0x33,0xea,0x79,0x32, +0x0, 0x40,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x42,0x7e,0x7f,0x33,0xea,0x69,0x57, +0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, 0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34, +0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e,0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, +0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1d,0xb3, +0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c,0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, +0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac,0x72,0xa, 0x2a,0x12,0x1d,0xb3,0x7e,0xf, 0x33, +0xea,0x79,0x30,0x0, 0x16,0x6d,0x33,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x22,0x22, +0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x4, 0x69, +0x30,0x0, 0x8, 0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c, +0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3a,0x3d,0x79, +0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c,0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32, +0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f, +0x3a,0x3d,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33, +0x7e,0x1f,0x3a,0x3d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xc0,0x12,0xe, 0x1c,0xa9,0xc6, +0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57, +0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x3a,0x23,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4,0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa, +0x7e,0x1f,0x3a,0x23,0x2d,0x37,0x79,0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0, +0xa4,0x7e,0xf, 0x3a,0x23,0x2d,0x15,0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6, +0xcb,0xc2,0x1d,0x69,0x30,0x0, 0x4, 0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x4, 0x69, +0x30,0x0, 0x6, 0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e, +0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70, +0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0xc, 0x29,0x70, +0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, +0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4,0x7e,0x1f,0x3a,0x3d,0x1b,0x1a,0x50,0x69,0x30, +0x0, 0xa, 0x12,0xe, 0x1c,0xa9,0xc6,0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x33, +0xea,0x79,0x32,0x0, 0x6, 0x29,0x50,0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d, +0x25,0x7e,0x2f,0x33,0xea,0x79,0x22,0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e, +0x2f,0x33,0xea,0x79,0x22,0x0, 0x38,0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e, +0x34,0x0, 0xa, 0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, +0x37,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29, +0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x8, 0x2, 0x8, 0xd0, +0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x4, 0x69, +0x30,0x0, 0x6, 0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e, +0x2f,0x3a,0x3d,0x79,0x32,0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70, +0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3a,0x3d,0x79,0x32,0x0, 0xc, 0x29,0x70, +0x0, 0x2, 0xa, 0x37,0x7e,0xf, 0x3a,0x3d,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f, +0x3a,0x3d,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xe0,0x12,0xe, 0x1c,0xa9,0xc6,0xcb,0x22, +0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, +0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28,0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, +0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, +0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e, +0x35,0x28,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34, +0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6, +0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f,0x3a,0x3d,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, +0x8, 0x7e,0x2f,0x3a,0x3d,0x79,0x22,0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab, +0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25,0x2d,0x25,0x7e,0x2f,0x3a,0x3d,0x79,0x22,0x0, +0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25,0x7e,0xf, 0x3a,0x3d,0x79,0x20,0x0, 0xe, 0x7e, +0xf, 0x3a,0x3d,0x79,0x30,0x0, 0xa, 0x6d,0x11,0x7e,0x1f,0x3a,0x3d,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0x40,0x12,0xe, 0x1c,0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, +0x1, 0x7e,0xf, 0x3a,0x27,0x79,0x30,0x0, 0xe, 0xc2,0x1c,0xe4,0x7a,0xb3,0x3a,0x22, +0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14,0x7e,0x1f,0x33,0xe2,0x1b,0x1a,0x10,0x7e,0xf, +0x33,0xe2,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74, +0x1, 0x12,0x12,0x56,0x7e,0xf, 0x3a,0x27,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, +0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x3a,0x27,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, +0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9,0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x3a, +0x3d,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, 0x4, 0x7e,0x2f,0x3a,0x3d,0x79,0x12,0x0, +0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f,0x3a,0x3d,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30, +0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad,0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31, +0x7e,0xf, 0x3a,0x3d,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3a,0x3d,0x1b,0x1a, +0x10,0x7e,0x34,0x0, 0x60,0x12,0xe, 0x1c,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d, +0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x3a,0x3d,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30, +0x80,0x1e,0x7e,0xf, 0x3a,0x3d,0xb, 0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe, +0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7,0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1d, +0x7e,0xf, 0x3a,0x3d,0xb, 0xa, 0x30,0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80, +0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b,0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x3a,0x3d,0x1b, +0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, +0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74,0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe, +0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, 0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e, +0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4,0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e, +0x24,0x0, 0x10,0x12,0x1e,0x52,0x7f,0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1d,0xe5,0x7d, +0x1e,0x12,0x1d,0xff,0x74,0x4, 0xac,0xbf,0x7e,0xf, 0x33,0xea,0x2d,0x15,0x79,0x30, +0x0, 0x82,0x79,0x20,0x0, 0x80,0xda,0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca, +0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1c,0x7e, +0xf, 0x3a,0x27,0xb, 0xa, 0x30,0x7c,0x57,0x7a,0x53,0x3a,0x22,0x4e,0x70,0xc, 0x1b, +0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e,0xf, 0x3a,0x27,0x79,0x30,0x0, 0xe, 0x12,0x11, +0x9e,0x12,0x70,0x56,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b, +0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x74,0x3, 0x12,0x12,0x56,0xa9,0xd1, +0xc4,0x7e,0xf, 0x33,0xe2,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b, +0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e,0x1f,0x33,0xe2,0x1b,0x1a,0x10,0x7e,0xf, 0x33, +0xea,0xb, 0x16,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xf, 0xe4,0x7a, +0xb3,0x33,0xfa,0x7e,0x1f,0x33,0xe2,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3, +0x74,0x2, 0x2, 0x12,0x56,0x7c,0x6b,0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a, +0x7e,0x7f,0x3a,0x23,0x2d,0xf4,0xb, 0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20, +0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c,0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e, +0x7f,0x3a,0x23,0x2d,0xf2,0x69,0x27,0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e, +0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xff, +0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60, +0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4, +0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f, +0x3a,0x23,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda, +0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b,0x7e,0xf, 0x33,0xea,0x69,0x30,0x0, 0xc, +0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, 0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25, +0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66,0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c, +0x55,0x7e,0xf, 0x33,0xea,0x2e,0x14,0x0, 0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, +0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a, +0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e,0x7f,0x3a,0x23,0x2d,0xf2,0x69, +0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f,0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b, +0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22, +0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42, +0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e,0x7f,0x3a,0x23,0x2d,0xf2,0x69,0x27,0x1, +0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24, +0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc9,0x22,0x12,0x59,0x4e,0x7c, +0x6b,0x12,0xba,0x93,0x7c,0x7b,0x6c,0xaa,0xbe,0x60,0x15,0x68,0x4, 0xa5,0xbf,0x15, +0x22,0xbc,0x76,0x68,0x5, 0x7e,0xa0,0xf1,0x80,0xb, 0x12,0xbd,0x2, 0xbe,0xb0,0x51, +0x68,0x3, 0x7e,0xa0,0xf2,0x7c,0xba,0x12,0xbc,0xfd,0x4c,0xaa,0x68,0x5, 0x12,0xb7, +0x10,0x80,0xfe,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x3a,0x3d,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x3a,0x3d,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x1f,0x9f,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x1f,0xa0,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x33,0xe2,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x12,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x33,0xe2,0x1b,0x1a,0x10,0x7e, +0x1f,0x33,0xe2,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x12,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x33,0xea,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x3a,0x27,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x33,0xe2,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x33,0xe2,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x33, +0xea,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x33,0xea,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x33,0xea,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x33,0xe2,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x49,0x23,0x1c, +0x4a,0x23,0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, 0xb2,0xd5,0x6e,0x24,0xff,0xff, +0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e,0x34,0xff,0xff,0xb, 0x34,0x8d, +0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d,0x32,0x30,0xd5,0x6, 0x6e,0x34, +0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d,0x2, 0x7d,0x21,0xad,0x5, 0x2d, +0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31,0xad,0x10,0x2d,0x21,0x22,0x6d, +0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78,0x27,0x8d,0x31,0x7d,0x12,0x6d, +0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11,0x2d,0x44,0x50,0x2, 0xa5,0xf, +0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78,0xed,0x7f,0x1, 0x6d,0x22,0x7d, +0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, 0x2f,0x0, 0x40,0x4, 0xbd,0x4, +0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d,0x23,0x7d,0x31,0x7d,0x10,0x6d, +0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2,0xd5,0x9f,0x22,0x9f,0x20,0x7f, +0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22,0x9f,0x21,0x7f,0x12,0x12,0x1e, +0x1, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12,0x1e,0x1, 0x30,0xd5,0x6, 0x9f, +0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1a,0x1e,0x54,0x68,0xe, +0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x50,0x6, +0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1e,0x1e,0x54,0x50, +0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, 0x1c,0xb, 0x14,0xb, 0x1a,0x0, +0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x22,0x75,0x84,0x1, 0x7e, +0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78,0xf9,0x7e,0xf8,0x3a,0x42,0x75, +0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, 0x0, 0xc2,0x8, 0xc2,0x9, 0x75, +0x1f,0x0, 0xc2,0x10,0xc2,0x11,0x75,0x18,0x64,0x75,0x19,0x64,0x75,0x1a,0x0, 0x75, +0x1b,0x0, 0xc2,0x13,0x75,0x5f,0x0, 0x75,0x60,0x0, 0xc2,0xa, 0xc2,0xb, 0x75,0x61, +0x0, 0xc2,0x15,0x75,0x62,0x0, 0xc2,0x16,0x75,0x63,0x0, 0xc2,0x17,0xc2,0x18,0xc2, +0x19,0x75,0x64,0x0, 0xc2,0xc, 0x75,0x5d,0x0, 0x75,0x5e,0x64,0xc2,0x1a,0xc2,0x1b, +0x75,0x65,0x0, 0xd2,0x5, 0xd2,0x6, 0xd2,0x7, 0xd2,0x1c,0xc2,0xe, 0xd2,0xf, 0x7e, +0x4, 0x0, 0xff,0x7e,0x14,0x20,0x40,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20, +0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24, +0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80,0xdf,0x2, 0x35,0xe0,0x0, 0x0, 0x0, 0x47,0x0, +0xcb,0x1, 0x0, 0x0, 0x10,0xfd,0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19, +0x0, 0x21,0x45,0x0, 0xe, 0x1, 0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, +0x14,0x7, 0x15,0x8, 0x16,0x9, 0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf, +0x22,0xc3,0x21,0xa9,0x20,0x94,0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a, +0x1a,0x41,0x19,0x38,0x18,0x31,0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19, +0x12,0x16,0x11,0x13,0x10,0x11,0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e, +0x1b,0xf0,0x7a,0x2b,0xf0,0xb, 0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b, +0xe4,0x79,0xef,0xff,0xfc,0x4d,0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43, +0x7f,0x10,0x80,0x7, 0x1b,0x44,0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0x32,0x1, 0x19,0x1, 0x0, 0x2, 0xf8,0x4, 0xe7,0x5, 0xce,0x6, 0xc2,0x7, 0xb5,0x8, +0xff,0x0, 0x1, 0x2, 0x0, 0xff,0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff, +0x7d,0x23,0xbe,0x24,0x0, 0x0, 0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22, +0x0, 0x4, 0x34,0x8c,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xff,0x1, 0x0, 0x1, 0x25, +0xf6,0x1, 0x0, 0x1, 0x38,0xe1,0x0, 0x0, 0x2, 0x39,0x33,0x0, 0x0, 0x0, 0x2, 0x39, +0x35,0x0, 0x0, 0x0, 0x1, 0x39,0x37,0x0, 0x0, 0x1, 0x35,0x92,0x0, 0x0, 0x1, 0x35, +0x93,0x0, 0x0, 0x4, 0x35,0xa8,0x0, 0xff,0x0, 0xff,0x0, 0xa, 0x36,0x28,0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x36,0x32,0x5, 0x0, 0x1, 0x36, +0x8d,0x0, 0x0, 0x1, 0x33,0xff,0x0, 0x0, 0x1, 0x34,0x4f,0x0, 0x0, 0x2, 0x36,0xa4, +0x0, 0x0, 0x0, 0x1, 0x36,0xc7,0x0, 0x0, 0x1, 0x37,0x36,0x0, 0x0, 0x1, 0x37,0x41, +0x0, 0x0, 0x1, 0x37,0x42,0x0, 0x0, 0x1, 0x37,0x43,0x0, 0x0, 0x3c,0x38,0x69,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x37,0xe5,0x1, +0x0, 0x2, 0x37,0xe8,0x0, 0x0, 0x0, 0x1, 0x0, 0x66,0x0, 0x0, 0x1, 0x0, 0x67,0x0, +0x0, 0x1, 0x0, 0x68,0x0, 0x0, 0x1, 0x37,0xec,0x1, 0x0, 0x1, 0x38,0x66,0x0, 0x0, +0x1, 0x3a,0x41,0x0, 0x0, 0x6, 0x3a,0x2b,0x3f,0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, +0x3a,0x31,0x24,0x0, 0x1, 0x3a,0x38,0x0, 0x0, 0x1, 0x3a,0x39,0x0, 0x0, 0x1, 0x3a, +0x3a,0x0, 0x0, 0x1, 0x3a,0x3b,0x0, 0x0, 0x1, 0x3a,0x3c,0x0, 0x0, 0x1, 0x2f,0xa9, +0x0, 0x0, 0x40,0x30,0x8a,0x80,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x80,0x0, 0x0, 0x0, 0x80,0x0, 0x0, 0x0, 0x80,0x0, 0x0, +0x0, 0x80,0x0, 0x0, 0x0, 0x80,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x80,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x33,0x86,0x0, 0x0, 0x1, 0x2, 0x8a,0x0, 0x0, +0x2, 0x2, 0xab,0x0, 0x0, 0x0, 0x1, 0x2, 0xe9,0x0, 0x0, 0x4, 0x33,0x87,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x3a,0x32,0x0, 0x0, 0x1, 0x3a,0x33,0x0, 0x0, 0x2, 0x3a,0x34, +0x0, 0x0, 0x0, 0x1, 0x3a,0x36,0x64,0x0, 0x1, 0x3a,0x37,0x0, 0x0, 0x1, 0x3a,0x42, +0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, 0x2, 0x2b,0xb9,0x2b, +0xbf,0x0, 0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8,0x0, 0x0, 0x1, 0x3a,0x17,0x0, +0x0, 0x1, 0x39,0x84,0xff,0x0, 0x1, 0x39,0x85,0x0, 0x0, 0x1, 0x39,0x86,0x0, 0x0, +0x1, 0x39,0x87,0x40,0x0, 0x1, 0x39,0x88,0x40,0x0, 0x4, 0x3a,0x23,0x0, 0x0, 0x50, +0x0, 0x0, 0x4, 0x3a,0x27,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x33,0xe2,0x0, 0x0, 0x6c, +0x0, 0x0, 0x4, 0x33,0xe6,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x33,0xea,0x0, 0x0, 0x68, +0x0, 0x0, 0x4, 0x33,0xfb,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x3a,0x3d,0x0, 0x0, 0x60, +0x0, 0x0, 0x0, 0x3, 0xe8,0x0, 0xc, 0x2, 0x26,0x3, 0x20,0x0, 0xa, 0x1, 0xae,0x2, +0xbc,0x0, 0xc, 0x0, 0xc8,0x1, 0xf4,0x0, 0xc, 0x0, 0x3c,0x1, 0x2c,0x0, 0xa, 0x0, +0x3c,0x0, 0x64,0x0, 0x6, 0x0, 0x3c,0x0, 0x50,0x0, 0x6, 0x0, 0x0, 0x0, 0xe, 0x1c, +0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, 0x0, 0x0, 0x1e,0x12,0x3f,0x18, +0x12,0x53,0xb1,0x12,0x22,0x96,0x12,0x28,0xa, 0x12,0x4f,0x45,0x2, 0x22,0x8f,0x74, +0x1, 0x7a,0xb3,0x37,0xf0,0x22,0x12,0x5c,0x56,0x12,0x22,0xcb,0x2, 0x22,0x9f,0x7e, +0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x22,0xa8,0x7d,0x43,0x7e,0xa3,0x34,0x38,0xbe,0xa0, +0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a,0x59,0x43,0x34,0x3b,0x59,0x23,0x34,0x3d, +0x7c,0xba,0x4, 0x7a,0xb3,0x34,0x38,0xc3,0x22,0xd3,0x22,0x6d,0x33,0x7e,0x24,0x6, +0xfc,0x12,0x22,0xa8,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x7, 0x7a,0x2, 0x22,0xa8,0x7e, +0x34,0x60,0xa3,0x12,0x23,0x29,0x12,0x26,0x2c,0x12,0x47,0x21,0x12,0x5c,0xd, 0x12, +0x3f,0x18,0x12,0x53,0xaa,0x12,0xc5,0x5, 0x12,0x22,0x96,0x12,0x28,0xa, 0x12,0x53, +0xe4,0x12,0x4f,0x45,0x2, 0x22,0x8f,0x7e,0x34,0x61,0x4f,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x30,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x61,0x51,0x7e,0x24,0x0, 0xff,0xb, 0x1a, +0x30,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30, +0x22,0x7e,0x34,0x61,0x55,0x12,0x23,0x29,0x7a,0x37,0x28,0x95,0x7e,0x34,0x61,0xba, +0x12,0x23,0x29,0x7a,0x37,0x28,0x99,0x7e,0x34,0x61,0xb8,0x12,0x23,0x29,0x7a,0x37, +0x28,0x97,0x7e,0x34,0x62,0x12,0x12,0x23,0x29,0x7a,0x37,0x28,0x9b,0x7e,0x34,0x61, +0xbc,0x12,0x23,0x29,0x7a,0x37,0x28,0x9d,0x7e,0x34,0x61,0xbe,0x12,0x23,0x29,0x7a, +0x37,0x28,0x9f,0x7e,0x34,0x61,0xc0,0x12,0x23,0x29,0x12,0xab,0x71,0x12,0x23,0x29, +0x7a,0x37,0x28,0xa3,0x90,0x61,0xc4,0xe4,0x93,0x7a,0xb3,0x28,0xa5,0xe4,0x7a,0xb3, +0x28,0xa8,0x12,0x2f,0xf0,0x3e,0x34,0x7e,0x8, 0x25,0xf7,0xe4,0x2, 0x1f,0xee,0x12, +0x25,0x57,0x7e,0xb3,0x37,0xf7,0xb4,0x1, 0x16,0x7e,0x34,0x62,0x34,0x12,0x23,0x29, +0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x36,0x12,0x23,0x29,0x7a,0x37,0x2a,0x5c,0x7e, +0xb3,0x28,0xa8,0xb4,0x1, 0x37,0x7e,0x34,0x62,0x3e,0x12,0x23,0x29,0x7a,0x37,0x2a, +0x5a,0x7e,0x34,0x62,0x40,0x12,0x23,0x29,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x62,0x42, +0x12,0x23,0x29,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x62,0x44,0x12,0x23,0x29,0x7a,0x37, +0x2a,0x51,0x7e,0x34,0x62,0x46,0x12,0x23,0x29,0x7a,0x37,0x2a,0x53,0x7e,0xb3,0x2a, +0x2, 0x70,0x21,0x7e,0x27,0x2a,0x5a,0x7d,0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d, +0x31,0x12,0x24,0xc7,0xbe,0x34,0x0, 0x50,0x28,0x4, 0x7e,0x34,0x0, 0x50,0x2d,0x32, +0x7a,0x37,0x2a,0x5a,0x22,0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, +0x4, 0x69,0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34, +0x0, 0x20,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x6, 0x12,0xb8,0x5e,0x7e,0x34,0x61, +0x4f,0x12,0x23,0x29,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x3, 0x9e,0x7e,0x34,0x61,0x51, +0x12,0x23,0x29,0xe, 0x34,0xe, 0x34,0x7a,0x73,0x3, 0x9f,0x7e,0x34,0x61,0x55,0x12, +0x23,0x29,0x12,0x24,0xc7,0x7a,0x73,0x3, 0xa0,0x7e,0x34,0x61,0x57,0x12,0x23,0x29, +0x12,0x24,0xc7,0x7a,0x73,0x3, 0xa1,0x7e,0x34,0x61,0x59,0x12,0x23,0x29,0x12,0x24, +0xc7,0x7a,0x73,0x3, 0xa2,0x7e,0x34,0x61,0x5b,0x12,0x23,0x29,0x12,0x24,0xc7,0x7a, +0x73,0x3, 0xa3,0x7e,0x34,0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x5f,0x7e,0x24,0x0, +0xff,0x7e,0x8, 0x3, 0xa4,0x12,0x1f,0xc9,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x3, 0xcf, +0xe5,0x28,0x7a,0xb3,0x3, 0xbe,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x22, +0x90,0x60,0x99,0xe4,0x93,0x7a,0xb3,0x2a,0x4d,0x90,0x60,0x9e,0xe4,0x93,0x7a,0xb3, +0x2a,0x4e,0x7e,0x34,0x61,0x55,0x12,0x23,0x29,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61, +0x57,0x12,0x23,0x29,0x7a,0x37,0x2a,0x51,0x7e,0x14,0x61,0x59,0x7e,0x4, 0x0, 0xff, +0xb, 0xa, 0x20,0x7a,0x27,0x2a,0x53,0x7a,0x37,0x2a,0x55,0x90,0x60,0x9d,0xe4,0x93, +0x7a,0xb3,0x2a,0x59,0x12,0x23,0x7, 0x12,0xc5,0x10,0x7e,0x34,0x62,0x12,0x12,0x23, +0x29,0x7a,0x37,0x2a,0x60,0x90,0x60,0x9f,0xe4,0x93,0x7a,0xb3,0x2a,0x64,0x90,0x60, +0xa0,0xe4,0x93,0x7a,0xb3,0x2a,0x65,0x7e,0x34,0x60,0xa1,0x12,0x23,0x29,0x7a,0x37, +0x2a,0x66,0x7e,0x34,0x61,0x5b,0x12,0x23,0x29,0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3, +0x2a,0x6b,0x7a,0xb3,0x16,0x92,0x22,0x12,0x23,0x7, 0x12,0xc5,0x10,0x7e,0x34,0x61, +0x55,0x12,0x23,0x29,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61,0x57,0x12,0x23,0x29,0x7a, +0x37,0x2a,0x51,0x7e,0x34,0x61,0x59,0x12,0x23,0x29,0x7a,0x37,0x2a,0x53,0x22,0x7e, +0x34,0x62,0x48,0x12,0x23,0x29,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x4a,0x12,0x23, +0x29,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x62,0x4c,0x12,0x23,0x29,0x7a,0x37,0x2a,0x4f, +0x7e,0x34,0x62,0x4e,0x12,0x23,0x29,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62,0x50,0x12, +0x23,0x29,0x7a,0x37,0x2a,0x53,0x22,0xca,0xf8,0x7e,0xf3,0x38,0xe6,0xbe,0xf0,0x5, +0x78,0xb, 0x74,0x1, 0x7a,0xb3,0x38,0xe6,0x12,0x0, 0xa, 0x80,0x52,0xbe,0xf0,0x4, +0x78,0x13,0x12,0xc4,0xfa,0x12,0x23,0x29,0x12,0x26,0x2c,0xe4,0x7a,0xb3,0x2b,0x2, +0x12,0x53,0x37,0x80,0x3a,0xbe,0xf0,0x6, 0x78,0x19,0x12,0xc4,0xfa,0x12,0x23,0x29, +0x12,0x26,0x2c,0x12,0x49,0x0, 0xe4,0x7a,0xb3,0x2b,0x1e,0x12,0x57,0x39,0x12,0xc5, +0x8c,0x80,0x1c,0xbe,0xf0,0x7, 0x78,0x1d,0x12,0xc4,0xfa,0x12,0x23,0x29,0x12,0x26, +0x2c,0x12,0x57,0x2e,0x50,0xfb,0x12,0x67,0x10,0x12,0x53,0xba,0x12,0x28,0xa, 0x74, +0x2, 0x7a,0xb3,0x38,0xe6,0xda,0xf8,0x22,0x7e,0x34,0x3, 0xe8,0x6d,0x22,0x7a,0x27, +0x3a,0x6, 0x7a,0x37,0x3a,0x8, 0x22,0x7e,0xb3,0x3, 0xc3,0x14,0x68,0x5a,0x14,0x78, +0x2, 0xc1,0xd5,0x14,0x68,0x6a,0x24,0x3, 0x68,0x2, 0xc1,0xcd,0x12,0xc5,0xa5,0x38, +0x8, 0x30,0x14,0xf, 0x12,0x87,0xb3,0x68,0xa, 0x12,0xc1,0x9a,0xe4,0x7a,0xb3,0x39, +0xcb,0x80,0x72,0x7e,0xb3,0x3, 0xa4,0x30,0xe0,0x6b,0x7e,0x73,0x3, 0xa5,0xa, 0x27, +0x7e,0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x3, 0xee,0xb4,0x1, 0xb, 0x7e,0x34,0x62, +0x64,0x12,0x23,0x29,0x2e,0x34,0x4, 0x0, 0xbe,0x37,0x39,0xc9,0x50,0x47,0x12,0x58, +0xda,0xe4,0x7a,0xb3,0x39,0xcd,0x80,0x3d,0x12,0xc5,0xa5,0x28,0x33,0xe4,0x7a,0xb3, +0x3, 0xc3,0x7e,0xb3,0x39,0xcb,0xb4,0x1, 0x3, 0x12,0x58,0xe0,0xd2,0x1b,0x80,0x20, +0x7e,0x34,0x60,0xa5,0x12,0x23,0x29,0x12,0x26,0x2c,0x12,0x45,0xf2,0x12,0x22,0xdf, +0xe4,0x7a,0xb3,0x3, 0xc3,0x7a,0xb3,0x3a,0x37,0xd2,0x1b,0x80,0x8, 0x12,0x58,0xe0, +0xe4,0x7a,0xb3,0x3a,0x37,0x12,0x47,0xb0,0x2, 0x26,0xdb,0xca,0xd8,0xca,0x79,0x7e, +0xb3,0x3, 0xc3,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x28,0x5, 0x6c,0xdd,0x6c,0xff,0x12, +0x87,0x2c,0x7d,0xf3,0x12,0x57,0x2e,0x50,0xfb,0x74,0x1, 0x7a,0xb3,0x39,0xcc,0x12, +0x3d,0xb3,0x12,0x12,0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x45,0x94,0x6d,0x33,0x12, +0x3f,0xd7,0x7e,0xe7,0x2b,0xd, 0x7a,0xe5,0x24,0x7e,0xe3,0x2a,0xfa,0x74,0x4, 0x7a, +0xb3,0x2a,0xfa,0x7e,0xe7,0x2b,0xd, 0x5e,0xe4,0x0, 0x3f,0x7a,0xe7,0x2b,0xd, 0x7e, +0xb3,0x2a,0xfa,0x12,0xba,0x4c,0x7c,0x7b,0x74,0x8, 0xac,0x7b,0x7e,0x24,0x0, 0x4, +0x12,0x1d,0xb3,0x7d,0x23,0x7d,0x3f,0x12,0x24,0xc7,0xad,0x32,0x7a,0x37,0x2b,0x7, +0x7e,0x8, 0x2a,0x6d,0x12,0x4, 0x8d,0x12,0x87,0x7b,0x12,0x26,0x28,0x7e,0xb3,0x3, +0xee,0xb4,0x1, 0x4, 0x74,0x10,0x80,0x2, 0x74,0x6, 0x12,0x88,0x0, 0x12,0x52,0x50, +0x80,0xf, 0x80,0x7, 0x12,0x46,0x4e,0xe4,0x12,0x46,0x86,0x20,0x93,0xf6,0x12,0x46, +0x1e,0x30,0x1c,0xf7,0x30,0x1b,0xf4,0xd2,0x1, 0x12,0x45,0xd9,0xe4,0x12,0x12,0xde, +0xb, 0xd0,0x12,0x81,0xe4,0x12,0x88,0xa, 0x7e,0xa3,0x39,0xcb,0x4c,0xaa,0x78,0x6, +0x74,0x1, 0x7a,0xb3,0x39,0xcc,0x4c,0xaa,0x68,0xb, 0x7e,0xb3,0x3, 0xee,0x70,0x5, +0xe4,0x7a,0xb3,0x39,0xcb,0x12,0xc5,0x1b,0x78,0x18,0x7e,0xb3,0x39,0xcb,0x60,0x12, +0xe4,0x7a,0xb3,0x39,0xcb,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a,0x3, 0x7e,0xf0,0x1, +0x80,0x1c,0x12,0xc5,0x1b,0x68,0x10,0x7e,0xb3,0x39,0xcb,0x70,0xa, 0x7e,0xf0,0x1, +0xe4,0x7a,0xb3,0x3, 0xc3,0x80,0x7, 0xbe,0xd0,0x14,0x50,0x2, 0xe1,0x5a,0xe4,0x7a, +0xb3,0x2b,0x4, 0x7e,0x35,0x24,0x7a,0x37,0x2b,0xd, 0x7a,0xe3,0x2a,0xfa,0x4c,0xff, +0x68,0x3, 0x12,0x28,0xa, 0xda,0x79,0xda,0xd8,0x22,0xe4,0x7a,0xb3,0x34,0x3a,0x7a, +0xb3,0x34,0x39,0x12,0x4d,0x3, 0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a, +0xb3,0x34,0x3a,0x22,0xca,0x3b,0x12,0x57,0x2e,0x50,0xfb,0x7e,0xf3,0x2b,0xf, 0x7c, +0xbf,0x12,0xa5,0x5b,0x12,0xa6,0x27,0x7e,0xb3,0x2b,0x1f,0xf5,0x28,0x7e,0xb3,0x2b, +0x20,0xf5,0x29,0x7e,0xb3,0x3, 0xc5,0xb4,0x1, 0xf, 0x12,0xa1,0xf4,0x7e,0xb3,0x16, +0x91,0x70,0x6, 0x12,0x28,0xa, 0xc3,0x21,0x32,0x12,0x29,0x35,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x6, 0xfc,0x7e,0x8, 0x4, 0x7e,0x12,0x1f,0xc9,0x1b,0xfd,0x12,0x29,0x35, +0x3e,0x34,0xca,0x39,0x7e,0x18,0x7, 0x7a,0x7e,0x8, 0x4, 0x0, 0x12,0x1f,0xc9,0x1b, +0xfd,0x7e,0xb3,0x3, 0xc5,0xb4,0x3, 0x7, 0x12,0x9f,0xdd,0x7a,0x37,0x39,0x29,0x74, +0x1, 0x7a,0xb3,0x16,0x90,0x12,0x53,0xb1,0x12,0x8f,0xb2,0x7e,0xc3,0x33,0x86,0x12, +0x4e,0xca,0xe4,0x12,0x12,0xde,0x12,0x28,0xa, 0x7e,0x8, 0x4, 0x7e,0x7a,0xd, 0x2a, +0x7e,0x18,0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0xb9,0xf4,0x7e,0x8, 0x4, 0x0, 0x7a, +0xd, 0x2a,0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0,0x12,0xb9,0xf4,0x7e,0xd3,0x2b, +0x1f,0x7e,0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b,0x1f,0xe5,0x29,0x12,0x67,0x1b, +0x50,0x5, 0x7c,0xbc,0x12,0xa7,0xc1,0x7e,0x34,0x8, 0xa, 0x7e,0x4, 0xd, 0xc8,0x7d, +0x20,0x7d,0x10,0x7e,0xb3,0x2a,0x6d,0x12,0x65,0x46,0x7a,0xd3,0x2b,0x1f,0x7a,0xe3, +0x2b,0x20,0x7c,0xbf,0x12,0xa5,0x1, 0x12,0x9f,0x8b,0x7e,0xb3,0x3a,0x37,0x4, 0x7a, +0xb3,0x3a,0x37,0x7e,0x73,0x3a,0x37,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64,0x7a,0xb3, +0x3a,0x37,0x7e,0xb3,0x16,0x90,0x60,0x9, 0x7e,0xb3,0x16,0x91,0x60,0x3, 0xd3,0x80, +0x1, 0xc3,0xda,0x3b,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x27,0x7e,0x73,0x2a,0x73,0xa, +0x37,0x2d,0x32,0x22,0x12,0x47,0xf9,0x7e,0xb3,0x3, 0xc5,0xb4,0x3, 0x66,0x12,0xb7, +0x17,0x12,0x26,0x28,0x12,0x3f,0xfd,0x7e,0xb3,0x38,0xe2,0x30,0xe7,0xe9,0x12,0x28, +0x24,0x12,0x29,0x35,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, 0xfc, +0x12,0x1f,0xc9,0x1b,0xfd,0x12,0x29,0x35,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x7e, +0x7e,0x8, 0x5, 0x7a,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x12, +0x12,0x83,0xef,0x12,0x57,0x2, 0x12,0x67,0x30,0x12,0x6a,0xec,0x12,0x29,0xc4,0x12, +0x57,0xf9,0x12,0x48,0x2f,0x12,0x3a,0xa6,0x7e,0xb3,0x38,0xe2,0x54,0x7f,0x7a,0xb3, +0x38,0xe2,0x80,0x93,0x12,0x57,0x28,0x2, 0x0, 0x46,0xe4,0x7a,0xb3,0x2b,0x2, 0x7a, +0xb3,0x2b,0x1e,0x22,0x12,0x88,0x69,0x12,0x2b,0xb8,0x12,0x2b,0xb8,0x12,0x36,0x2, +0x12,0x2b,0xb8,0x12,0xad,0x2c,0x12,0x2b,0xb8,0x12,0x8e,0x9c,0x12,0x2b,0xb8,0x2, +0x29,0xe2,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca, +0xc9,0x7e,0x18,0x38,0xa5,0x7e,0x8, 0x38,0x69,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0xf3, +0x28,0x84,0xa, 0xcf,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e,0x8, 0x1f,0x34, +0x12,0x1f,0xc9,0x1b,0xfd,0x6c,0x88,0x6c,0xee,0x41,0xb6,0x7e,0xc4,0x3, 0xff,0x7e, +0xc0,0xff,0x6c,0x99,0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f,0x34,0xbe,0xb0, +0xff,0x68,0x3d,0x7c,0xb9,0x12,0xb1,0x84,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75, +0x1f,0x35,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x38,0xa6,0x12,0x7d,0xff,0x7d, +0x13,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, +0x75,0x38,0xa5,0x12,0x7d,0xff,0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9, +0xb, 0x90,0xbc,0xf9,0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c, +0x9, 0xb3,0x1f,0x34,0x9, 0x73,0x1f,0x35,0x12,0x2c,0x1, 0xbe,0x37,0x2a,0x5a,0x48, +0x23,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac,0xbd,0x19,0x55, +0x1f,0x70,0x9, 0x53,0x1f,0x35,0x19,0x55,0x1f,0x71,0x74,0xff,0x19,0xb3,0x1f,0x34, +0xb, 0x80,0xb, 0xd0,0xb, 0xe0,0x7e,0x73,0x38,0x68,0xbc,0x7e,0x28,0x2, 0x41,0x1b, +0x7c,0xe8,0x80,0x6d,0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12, +0xb1,0x84,0x60,0x33,0x12,0xc5,0x3a,0xbe,0xb0,0xff,0x68,0x2b,0x9, 0x73,0x1f,0x35, +0x12,0x30,0x3, 0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, 0x6d,0x55, +0x1b,0x7a,0x50,0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0xd, 0x12,0xc5,0x3a,0xf5,0x24,0x9, +0xc3,0x1f,0x35,0x7d,0xdc,0x7c,0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0,0xbe,0x80,0xff, +0x68,0x1d,0x7e,0x71,0x24,0x74,0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70,0x19,0xc5,0x1f, +0x71,0x7e,0xa0,0xff,0x7e,0x70,0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34,0xb, 0xd0,0xb, +0xe0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbe,0x38,0x8a,0x90,0x60,0x9a,0xe4,0x93,0x7c, +0xab,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f,0x34,0x12,0x1f, +0xc9,0x1b,0xfd,0x7c,0xfd,0x12,0x94,0xba,0x7e,0x8, 0x38,0xa5,0x74,0xff,0x12,0x1f, +0xee,0xbe,0xf0,0x0, 0x28,0x38,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34, +0x7e,0x8, 0x26,0xfa,0x12,0x1f,0xc9,0x1b,0xfd,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e, +0x18,0x1f,0x34,0x7e,0x8, 0x38,0xa5,0x12,0x1f,0xc9,0x1b,0xfd,0x6c,0xee,0x80,0xa, +0x7c,0xbe,0x7e,0x70,0x1, 0x12,0x36,0xca,0xb, 0xe0,0xbc,0xfe,0x38,0xf2,0x7a,0xf3, +0x38,0x68,0x7a,0xf3,0x28,0x84,0x90,0x60,0x99,0xe4,0x93,0xbe,0xb3,0x28,0x84,0x50, +0x4, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0xca,0x79,0x6c,0xff,0x6c,0xee,0x80,0x31, +0x7c,0xbe,0x12,0xb1,0x84,0x60,0x28,0x7e,0x34,0x0, 0x2, 0xca,0x39,0xac,0x7e,0x2e, +0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x26,0xfa,0x6d,0x0, +0x12,0x1f,0xc9,0x1b,0xfd,0x7c,0xbf,0x7e,0x70,0x1, 0x12,0x36,0xca,0xb, 0xf0,0xb, +0xe0,0x12,0x8f,0x80,0x38,0xca,0x7a,0xf3,0x28,0x84,0xda,0x79,0x22,0x7c,0xba,0x7c, +0x79,0x12,0x30,0x3, 0xb, 0x1a,0x30,0x22,0xca,0x3b,0x7c,0xfb,0x75,0x3d,0x0, 0x7e, +0xb3,0x2a,0x6f,0xf5,0x42,0x7e,0xb3,0x2a,0x70,0xf5,0x43,0x75,0x44,0x28,0x7e,0xd3, +0x28,0x84,0xe4,0x7a,0xb3,0x2, 0x8c,0x7a,0xb3,0x2, 0x88,0x7a,0xb3,0x2, 0x89,0x7e, +0x8, 0x2, 0x8d,0x12,0x2f,0xf0,0xe4,0x12,0x1f,0xee,0x12,0x2f,0xf0,0x3e,0x34,0x7e, +0x8, 0x2, 0xad,0xe4,0x12,0x1f,0xee,0xbe,0xd0,0x2, 0x50,0x2, 0xe1,0xe6,0x6c,0xcc, +0xe1,0xe0,0x12,0xaf,0x43,0xf5,0x24,0x9, 0xb3,0x26,0xfb,0xf5,0x25,0x4c,0xcc,0x68, +0x8, 0xa, 0x3c,0x9, 0xb3,0x2, 0x8d,0x70,0xa, 0xa, 0x3c,0xb, 0x34,0xa, 0x2c,0x19, +0x72,0x2, 0x8d,0x7c,0xbd,0x14,0xbc,0xbc,0x78,0x2, 0xe1,0xe6,0xa, 0x5c,0xb, 0x54, +0xf5,0x2e,0xe1,0xd7,0x7e,0x71,0x2e,0x12,0xaf,0x5c,0x7a,0xa1,0x26,0x9, 0xb3,0x26, +0xfb,0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0x2f,0xe9,0x7c,0xb7,0xf5,0x28,0xe5,0x27, +0xa, 0x2b,0xe5,0x25,0x12,0x2f,0xe9,0x7c,0xb7,0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, +0x40,0x2, 0xe1,0xd5,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xe1,0xd5,0x12,0xc5,0x5f, +0x7e,0x51,0x27,0x12,0xae,0xde,0x7a,0xb3,0x2, 0x8b,0x85,0x25,0x54,0x85,0x26,0x55, +0x85,0x27,0x56,0x7e,0x8, 0x0, 0x31,0x7e,0x18,0x0, 0x33,0xe5,0x24,0x12,0xb0,0xc1, +0x75,0x3d,0x0, 0x6c,0xee,0x75,0x30,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x2c,0x1, +0x7a,0x35,0x35,0xe5,0x26,0x7e,0x71,0x27,0x12,0x2c,0x1, 0x7a,0x35,0x37,0x7e,0x35, +0x35,0xbe,0x35,0x37,0x8, 0x5, 0x7e,0x35,0x37,0x80,0x3, 0x7e,0x35,0x35,0x7a,0x35, +0x3b,0xe, 0x34,0x7a,0x35,0x39,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x2c,0xe5,0x29,0xbe, +0xb0,0x1, 0x38,0x25,0x7c,0xbf,0x30,0xe1,0x20,0xe5,0x26,0x7e,0x71,0x25,0x12,0x2c, +0x1, 0x7d,0x43,0xe5,0x24,0x7e,0x71,0x27,0x12,0x2c,0x1, 0x2d,0x34,0xbe,0x35,0x39, +0x18,0x2, 0xe1,0x70,0x75,0x30,0x1, 0xe1,0x70,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x9, +0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x2, 0xe1,0x70,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, +0xe1,0x70,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xe1,0x70,0x7c,0xbf,0x20,0xe0,0x2, +0xe1,0x70,0x6d,0x33,0x7a,0x35,0x4d,0x75,0x4f,0x0, 0x7a,0x35,0x50,0x75,0x52,0x0, +0xc2,0x2, 0xc2,0x3, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x4, 0xe5,0x24,0x80,0x2, 0xe5, +0x26,0xf5,0x2a,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26, +0xf5,0x2c,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5, +0x2b,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2d, +0xe5,0x2c,0xbe,0xb1,0x2a,0x78,0x29,0xd2,0x2, 0xe5,0x2a,0x60,0x8, 0xe5,0x42,0x14, +0xbe,0xb1,0x2a,0x78,0x2, 0xd2,0x3, 0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2a, +0xe5,0x42,0xa, 0x2b,0x1b,0x24,0xe5,0x2c,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2c, +0xe5,0x2d,0xbe,0xb1,0x2b,0x78,0x29,0xd2,0x2, 0xe5,0x2b,0x60,0x8, 0xe5,0x43,0x14, +0xbe,0xb1,0x2b,0x78,0x2, 0xd2,0x3, 0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2b, +0xe5,0x43,0xa, 0x2b,0x1b,0x24,0xe5,0x2d,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2d, +0x85,0x2a,0x3e,0x80,0x5b,0x85,0x2b,0x3f,0x80,0x4d,0xe5,0x3e,0x7e,0x71,0x3f,0x12, +0x2c,0x1, 0x7a,0x35,0x40,0xe5,0x2a,0xbe,0xb1,0x3e,0x68,0x15,0xe5,0x2c,0xbe,0xb1, +0x3e,0x68,0xe, 0xe5,0x2b,0xbe,0xb1,0x3f,0x68,0x7, 0xe5,0x2d,0xbe,0xb1,0x3f,0x78, +0xd, 0x7e,0x35,0x40,0x2e,0x35,0x4d,0x7a,0x35,0x4d,0x5, 0x4f,0x80,0x17,0x5, 0x52, +0x7e,0x35,0x40,0x2e,0x35,0x50,0x7a,0x35,0x50,0x7e,0x35,0x33,0xbe,0x35,0x40,0x58, +0x2, 0x5, 0x3d,0xb, 0xe0,0x5, 0x3f,0xe5,0x2d,0xbe,0xb1,0x3f,0x50,0xac,0x5, 0x3e, +0xe5,0x2c,0xbe,0xb1,0x3e,0x50,0x9e,0xe5,0x2c,0x7e,0x71,0x2b,0x12,0x2c,0x1, 0x7e, +0x45,0x4d,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2d,0x12,0x2c,0x1, 0x9d,0x43,0xe5,0x2a, +0x7e,0x71,0x2b,0x12,0x2c,0x1, 0x9d,0x43,0xe5,0x2c,0x7e,0x71,0x2d,0x12,0x2c,0x1, +0x7d,0x23,0x7d,0x34,0x9d,0x32,0x7a,0x35,0x4d,0x7e,0x35,0x37,0x2e,0x35,0x35,0x7a, +0x35,0x39,0x30,0x2, 0x10,0x20,0x3, 0xd, 0x7e,0x35,0x4d,0x9e,0x35,0x39,0x7a,0x35, +0x4d,0x15,0x4f,0x15,0x4f,0xe5,0x4f,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x4f,0x24,0xfc, +0xf5,0x4f,0x7e,0x35,0x4d,0xbe,0x34,0x0, 0x0, 0x58,0x5, 0x6d,0x33,0x7a,0x35,0x4d, +0x75,0x44,0x28,0xe5,0x42,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, +0xe5,0x24,0x60,0x4, 0xe5,0x26,0x70,0x8, 0x12,0xb1,0x50,0x28,0x3, 0x75,0x44,0x2c, +0x7e,0x15,0x50,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4d,0x1a,0x26,0x1a,0x24,0x2f,0x10, +0xe5,0x44,0xa, 0x1b,0x6d,0x0, 0x12,0x1d,0xe5,0x7f,0x71,0x7a,0x7d,0x45,0x7e,0x15, +0x39,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x31,0x1a,0x26,0x1a,0x24,0x12,0x1d,0xe5,0xe5, +0x52,0xa, 0xdb,0x6d,0xcc,0xe5,0x4f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1d,0xe5, +0x7a,0x1d,0x49,0xbf,0x71,0x8, 0x3, 0x75,0x30,0x2, 0xc2,0x1, 0x20,0xc, 0x11,0x12, +0xc5,0x5f,0x7e,0x51,0x27,0x12,0xb1,0x58,0x92,0x1, 0x20,0x1, 0x3, 0x75,0x30,0x0, +0xe5,0x30,0xbe,0xb0,0x0, 0x28,0x5e,0xe5,0x30,0xa, 0x3b,0x2e,0x34,0x2, 0x87,0x12, +0x74,0x2f,0xe5,0x2e,0xa, 0x3b,0x9, 0xa3,0x2, 0x8d,0x4c,0xaa,0x78,0xc, 0xa, 0x2c, +0x9, 0xb2,0x2, 0x8d,0x19,0xb3,0x2, 0x8d,0x80,0x3b,0xa, 0x2c,0x9, 0xb2,0x2, 0x8d, +0xf5,0x53,0xbc,0xba,0x28,0x3, 0x7a,0xa1,0x53,0x75,0x2f,0x0, 0x80,0x22,0x9, 0x33, +0x2, 0x8d,0xe5,0x2f,0xa, 0x2b,0x9, 0x22,0x2, 0x8d,0xbc,0x23,0x68,0xa, 0xa, 0xc, +0x9, 0x30,0x2, 0x8d,0xbc,0x23,0x78,0x6, 0xe5,0x53,0x19,0xb2,0x2, 0x8d,0x5, 0x2f, +0xbe,0xd1,0x2f,0x38,0xd9,0x5, 0x2e,0xbe,0xd1,0x2e,0x28,0x2, 0x81,0x84,0xb, 0xc0, +0xbc,0xdc,0x28,0x2, 0x81,0x52,0xda,0x3b,0x22,0xa, 0x3b,0x9d,0x32,0x2, 0x20,0x30, +0x90,0x60,0x9a,0x93,0xa, 0x3b,0x22,0x7e,0x73,0x2a,0x6b,0x2e,0x70,0xff,0x22,0x7c, +0xbd,0x7c,0x7e,0x7e,0x13,0x2a,0x6e,0xac,0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37, +0x2d,0x10,0x7e,0x1f,0x13,0x8a,0x2d,0x31,0x22,0xca,0x3b,0x12,0xaf,0x3a,0x74,0x9, +0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x27,0x76,0x6d,0xcc,0x7e,0x37,0x2a,0x66,0x7a,0x35, +0x5b,0xe4,0x39,0xb6,0x0, 0x6, 0x12,0x35,0x44,0xf5,0x49,0x9, 0xb3,0x26,0xfb,0xf5, +0x4a,0x7e,0x73,0x2a,0x6e,0x7c,0x6d,0x7e,0x8, 0x0, 0x4d,0x12,0x32,0x6d,0xf5,0x4b, +0xe5,0x49,0x7e,0x73,0x2a,0x6d,0x7c,0x6c,0x7e,0x8, 0x0, 0x4c,0x12,0x32,0x6d,0x7c, +0xab,0xe5,0x4c,0x7e,0x71,0x4d,0x12,0x30,0x3, 0x7a,0x35,0x57,0x7e,0x34,0x15,0x9e, +0x7a,0x35,0x59,0x85,0x4c,0x51,0x85,0x4d,0x52,0x7a,0xa1,0x53,0x85,0x4b,0x54,0x7e, +0xb3,0x2a,0x59,0xf5,0x55,0x75,0x56,0x0, 0x7e,0x8, 0x0, 0x51,0x12,0x81,0x7c,0x7d, +0x23,0x6d,0x33,0x7e,0x97,0x15,0xa0,0x6d,0x88,0x2f,0x41,0x7e,0x37,0x15,0xa2,0x6d, +0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x43,0x7e,0x37, +0x15,0xa6,0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x15,0xa8,0x6d,0xaa,0x2f,0x51,0x7f,0x74, +0xa, 0x4c,0xe5,0x49,0xa, 0x5b,0x9d,0x54,0xf5,0x47,0x21,0xb4,0xa, 0x4d,0xe5,0x4a, +0xa, 0x5b,0x9d,0x54,0xf5,0x48,0x21,0x9e,0xe5,0x47,0xbe,0xb0,0x0, 0x58,0x2, 0x21, +0x9c,0x7e,0x73,0x2a,0x6d,0xbe,0x71,0x47,0x18,0x2, 0x21,0x9c,0xe5,0x48,0xbe,0xb0, +0x0, 0x58,0x2, 0x21,0x9c,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x48,0x18,0x2, 0x21,0x9c, +0xe5,0x47,0x7e,0x71,0x48,0x12,0x2c,0x1, 0x7e,0x53,0x2a,0x59,0xa, 0x25,0x9d,0x32, +0x7a,0x35,0x4f,0xbe,0x34,0x0, 0x0, 0x18,0x2, 0x21,0x9c,0x7e,0x35,0x5b,0xbe,0x35, +0x4f,0x18,0xd, 0x7f,0x16,0x2e,0x34,0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0, +0xe5,0x49,0xa, 0x2b,0xe5,0x47,0x12,0x32,0x52,0x18,0xb, 0xe5,0x4a,0xa, 0x2b,0xe5, +0x48,0x12,0x32,0x52,0x8, 0x56,0xe5,0x47,0x7e,0x71,0x48,0x7c,0x6e,0x12,0xb9,0x6, +0xf5,0x4e,0xb4,0x2, 0xc, 0x7e,0x35,0x4f,0x7d,0x23,0xe, 0x24,0x9d,0x32,0x7a,0x35, +0x4f,0xe5,0x4e,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x4e,0xb4,0x1, 0x2f,0x7e,0x45,0x4f, +0x7d,0x34,0x1a,0x26,0x1a,0x24,0xe5,0x47,0x12,0x32,0x43,0x7f,0x1, 0x7e,0x1d,0x43, +0x9f,0x10,0x7a,0x1d,0x43,0x7d,0x34,0x1a,0x26,0x1a,0x24,0xe5,0x48,0x12,0x32,0x43, +0x9f,0x51,0x12,0x32,0x4a,0x9f,0x41,0x12,0x32,0x4a,0x9f,0x71,0x5, 0x48,0xa, 0x2d, +0xe5,0x4a,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x48,0x1a,0x3b,0xbd,0x32,0x18,0x2, +0x1, 0xd8,0x5, 0x47,0xa, 0x2c,0xe5,0x49,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x47, +0x1a,0x3b,0xbd,0x32,0x18,0x2, 0x1, 0xcc,0xbe,0x48,0x0, 0x0, 0x78,0x2, 0xb, 0x4c, +0xbe,0x78,0x0, 0x0, 0x78,0x2, 0xb, 0x7c,0x7e,0x1d,0x43,0x7f,0x4, 0x12,0x32,0x5e, +0x1b,0x6a,0x30,0x7f,0x15,0x7f,0x7, 0x12,0x32,0x5e,0x79,0x36,0x0, 0x2, 0x7e,0xb3, +0x2a,0x65,0x60,0xd, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78, +0xf3,0xbe,0x78,0x0, 0x7f,0x28,0x4, 0x7e,0x78,0x0, 0x7f,0x7d,0x3f,0x39,0x76,0x0, +0x5, 0x74,0x9, 0xac,0xbe,0x9, 0x75,0x27,0x7c,0x39,0x76,0x0, 0x6, 0xbe,0x70,0xf, +0x28,0x6, 0x74,0xf, 0x39,0xb6,0x0, 0x6, 0x7e,0xa1,0x49,0x7e,0x70,0x9, 0xac,0x7f, +0x19,0xa3,0x27,0x7d,0x7e,0xa1,0x4a,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x27,0x7e, +0xda,0x3b,0x22,0x1a,0x1b,0x1a,0x2, 0x2, 0x1d,0xe5,0x7e,0x35,0x4f,0x1a,0x26,0x1a, +0x24,0x22,0x1a,0x3b,0x9d,0x32,0x12,0x20,0x30,0xbe,0x34,0x0, 0x1, 0x22,0x74,0x6, +0x2f,0x11,0x14,0x78,0xfb,0x12,0x1e,0x1, 0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c, +0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc, +0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18, +0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d, +0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39, +0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22, +0xca,0x3b,0x75,0x28,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x2b,0x7e,0xd3,0x2a,0x70,0x75, +0x25,0x0, 0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x2, 0x80,0x2, 0x81,0xe8,0x6c,0xcc,0x81, +0xd8,0x12,0xaf,0x43,0xf5,0x29,0x9, 0xb3,0x26,0xfb,0xf5,0x2a,0x75,0x26,0x2, 0x75, +0x27,0x2, 0x7e,0xb3,0x3, 0xa9,0xb4,0x1, 0x1e,0x7e,0xb3,0x2a,0x3, 0xb4,0x1, 0x17, +0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x10,0x7e,0x37,0x28,0x86,0xbe,0x34,0x0, 0xa, 0x40, +0x6, 0x75,0x26,0x3, 0x75,0x27,0x3, 0xe5,0x29,0x60,0x5, 0x12,0x35,0xf, 0x48,0x3, +0x75,0x26,0x1, 0xe5,0x2a,0x60,0xc, 0xa, 0x2d,0x1b,0x24,0xe5,0x2a,0xa, 0x3b,0xbd, +0x32,0x48,0x3, 0x75,0x27,0x1, 0x75,0x25,0x0, 0x75,0x24,0x0, 0x80,0x34,0xe5,0x24, +0xbc,0xbc,0x68,0x2c,0x12,0xaf,0x59,0x9, 0x33,0x26,0xfb,0xa, 0x2a,0xe5,0x29,0x12, +0x2f,0xe9,0xbe,0x34,0x0, 0x4, 0x18,0x18,0xa, 0x23,0xe5,0x2a,0x12,0x2f,0xe9,0xbe, +0x34,0x0, 0x4, 0x18,0xb, 0x75,0x25,0x1, 0x75,0x26,0x1, 0x75,0x27,0x1, 0x80,0xb, +0x5, 0x24,0x7e,0x23,0x28,0x84,0xbe,0x21,0x24,0x38,0xc3,0x12,0x55,0x45,0x50,0x6, +0x75,0x26,0x3, 0x75,0x27,0x3, 0xe5,0x25,0x70,0x2, 0x81,0x78,0x6c,0xff,0x6c,0xee, +0x12,0x35,0x2, 0x18,0x13,0xe5,0x2b,0xa, 0x5b,0xbd,0x35,0x48,0xb, 0x12,0x34,0xf5, +0x18,0x6, 0xa, 0x5d,0xbd,0x35,0x58,0x3, 0x12,0x35,0x1c,0xb, 0xe0,0xbe,0xe0,0x3, +0x78,0xde,0xb, 0xf0,0xbe,0xf0,0x3, 0x78,0xd5,0x7c,0xad,0x1b,0xa0,0xbe,0xa1,0x2a, +0x68,0x6, 0xe5,0x2a,0x60,0x2, 0x81,0x78,0xe5,0x29,0xbe,0xb0,0x0, 0x38,0x2, 0x81, +0x78,0x12,0x35,0xf, 0x48,0x2, 0x81,0x78,0x7e,0x18,0x0, 0x64,0x7a,0x1d,0x3f,0xe5, +0x2a,0x70,0x5, 0x75,0x3e,0x2, 0x80,0x8, 0xbe,0xa1,0x2a,0x78,0x3, 0x75,0x3e,0x0, +0x6c,0xff,0x7e,0xa1,0x3e,0x3e,0xa0,0x7e,0x90,0x6, 0xac,0x9f,0x7c,0xb9,0x2c,0xba, +0x24,0x2c,0x12,0x34,0xeb,0x7e,0x14,0x0, 0x64,0x12,0x1d,0xf6,0x7c,0xb9,0x24,0x2e, +0xa, 0x1b,0xb, 0x18,0x10,0x12,0xc4,0xec,0x7e,0xd, 0x3f,0xbf,0x10,0x58,0x3, 0x7a, +0x1d,0x3f,0xb, 0xf0,0xbe,0xf0,0x3, 0x78,0xc9,0x7e,0x1d,0x3f,0xbe,0x18,0x0, 0x0, +0x58,0x7, 0x7e,0x18,0x0, 0x1, 0x7a,0x1d,0x3f,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x24, +0x2e,0x12,0x34,0xeb,0x7e,0xd, 0x3f,0x12,0x1d,0xe5,0x7e,0x8, 0x0, 0x64,0x12,0x1e, +0x52,0x7d,0x43,0xe5,0x29,0xa, 0x3b,0x1b,0x34,0xa, 0x5f,0x2d,0x53,0x7e,0xa1,0x2a, +0xa, 0x2a,0x1b,0x24,0x7e,0xa1,0x3e,0xa, 0x3a,0x2d,0x32,0x12,0x30,0x3, 0x1b,0x1a, +0x40,0xb, 0xf0,0xbe,0xf0,0x3, 0x78,0xc3,0xe5,0x26,0x7e,0x71,0x27,0x7c,0x6c,0x7e, +0x51,0x28,0x12,0x30,0x19,0xe5,0x25,0x60,0x2d,0x6c,0xff,0x6c,0xee,0x12,0x35,0x2, +0x18,0x13,0xe5,0x2b,0xa, 0x5b,0xbd,0x35,0x48,0xb, 0x12,0x34,0xf5,0x18,0x6, 0xa, +0x5d,0xbd,0x35,0x58,0x3, 0x12,0x35,0x1c,0xb, 0xe0,0xbe,0xe0,0x3, 0x78,0xde,0xb, +0xf0,0xbe,0xf0,0x3, 0x78,0xd5,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x16,0x7e,0x70, +0x9, 0xac,0x7c,0x7d,0x13,0x2e,0x14,0x27,0x76,0x6d,0x0, 0x2e,0x34,0x27,0x78,0x6d, +0x22,0x12,0x70,0xc9,0x5, 0x28,0xb, 0xc0,0x7e,0x73,0x28,0x84,0xbc,0x7c,0x28,0x2, +0x41,0xe1,0xe5,0x28,0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0xa, 0x3b,0xb, 0x38,0x30, +0x1a,0x26,0x1a,0x24,0x22,0xa, 0x2e,0xe5,0x2a,0xa, 0x3b,0x2d,0x32,0xbe,0x34,0x0, +0x1, 0x22,0xa, 0x3f,0xe5,0x29,0xa, 0x4b,0x2d,0x34,0xbe,0x34,0x0, 0x1, 0x22,0xe5, +0x2b,0xa, 0x2b,0x1b,0x24,0xe5,0x29,0xa, 0x3b,0xbd,0x32,0x22,0x1b,0x44,0xa, 0x5f, +0x2d,0x54,0x7e,0xa1,0x2a,0xa, 0x2a,0x1b,0x24,0xa, 0x3e,0x2d,0x32,0x12,0x2c,0x1, +0x7d,0x23,0x7c,0x7e,0x3e,0x70,0x74,0x6, 0xac,0xbf,0x2c,0xb7,0x24,0x2c,0xa, 0x3b, +0x1b,0x38,0x20,0x22,0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x26,0xfa,0x22,0xca,0x3b, +0x7e,0xf3,0x2a,0x74,0x12,0x0, 0x6e,0x50,0x2, 0xa1,0xdd,0x6d,0x33,0x9e,0x37,0x2a, +0x4f,0x3e,0x34,0xbe,0x37,0x7, 0xf8,0x18,0x74,0x7e,0xb3,0x16,0x92,0x70,0x6e,0x7e, +0xb3,0x28,0xa8,0xb4,0x1, 0x58,0x7e,0x37,0x2a,0x51,0x7a,0x35,0x26,0x7e,0x67,0x2a, +0x53,0x6c,0xee,0x80,0x44,0x7c,0xbe,0x12,0xb1,0x84,0x60,0x3b,0x12,0x35,0x44,0xf5, +0x24,0x9, 0xa3,0x26,0xfb,0x7a,0xa1,0x25,0x74,0x2, 0xa4,0x49,0x35,0x4, 0xfc,0xbd, +0x36,0x48,0x13,0xe5,0x24,0xa, 0x2b,0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, +0xfc,0xbe,0x35,0x26,0x58,0x11,0x7c,0xbe,0x6c,0x77,0x12,0x36,0xca,0x12,0x35,0x44, +0x9, 0x73,0x26,0xfb,0x12,0x37,0xb9,0xb, 0xe0,0x12,0x8f,0x80,0x38,0xb7,0x7e,0xb3, +0x2a,0x68,0x70,0x9, 0x7e,0xb3,0x2a,0x6b,0x70,0x3, 0x12,0x98,0x44,0xda,0x3b,0x22, +0x12,0x47,0x21,0x12,0x24,0x25,0x12,0x5c,0xd, 0x12,0x22,0x7d,0x7e,0xb3,0x3, 0xc5, +0x24,0xfd,0x68,0x9, 0xb, 0xb1,0x78,0xf4,0x12,0x55,0x79,0x80,0xef,0x12,0x29,0x44, +0x80,0xea,0x12,0x98,0x2d,0x12,0x35,0x4e,0x12,0x37,0x9, 0x2, 0x36,0xe, 0xca,0x3b, +0x12,0x2b,0xb8,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0xe5,0x60,0x9, 0xe4, +0x7a,0xb3,0x37,0xe7,0x7a,0xb3,0x37,0x6c,0x7e,0xb3,0x37,0xe5,0x70,0x65,0x6c,0x99, +0x80,0x59,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x26,0xfa,0x9, 0xf5,0x26,0xfb,0x7c,0xb9, +0x12,0xb5,0x39,0x40,0x44,0x6c,0xee,0x80,0x38,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x37, +0x6d,0x9, 0xc5,0x37,0x6e,0xa, 0x28,0xa, 0x3d,0x12,0x36,0xb6,0x78,0x21,0xa, 0x2f, +0xa, 0x3c,0x12,0x36,0xb6,0x78,0x18,0x7c,0xb9,0x12,0x37,0xdc,0x7e,0x14,0x62,0x2b, +0x12,0x8f,0xa8,0x58,0xa, 0x12,0x36,0xbe,0x7c,0xb8,0x7c,0x7f,0x12,0x37,0xb9,0xb, +0xe0,0x7e,0x73,0x37,0xe7,0xbc,0x7e,0x38,0xc0,0xb, 0x90,0x7e,0x73,0x28,0x84,0xbc, +0x79,0x38,0x9f,0x7e,0x73,0x37,0x6c,0x7a,0x73,0x37,0xe7,0xa, 0x37,0x3e,0x34,0xca, +0x39,0x7e,0x18,0x37,0xa9,0x7e,0x8, 0x37,0x6d,0x12,0x1f,0xc9,0x1b,0xfd,0xe4,0x7a, +0xb3,0x37,0xe5,0xda,0x3b,0x22,0x9d,0x32,0x12,0x20,0x30,0x4d,0x33,0x22,0x7c,0xb9, +0x6c,0x77,0x2, 0x36,0xca,0x7c,0xb3,0x7e,0x70,0x1, 0x7c,0x67,0x7c,0x7b,0xc4,0x23, +0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e,0x24,0x0, 0x5e,0x12,0x69, +0x8e,0x7c,0x7b,0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24,0x27,0x72,0x7e,0x29,0xb0, +0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a,0x2e,0x24,0x27,0x72, +0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0xca,0xd8,0xca,0x79,0x7e,0x34,0x62, +0x27,0x12,0x37,0xd4,0x12,0x9e,0x44,0x50,0x2, 0xe1,0xb4,0x7e,0x34,0x62,0x2b,0x12, +0x23,0x29,0x7a,0x35,0x2a,0x90,0x62,0x26,0xe4,0x93,0x70,0x2, 0xe1,0xb4,0x7e,0xb3, +0x28,0xa8,0xb4,0x1, 0x7, 0x7e,0x34,0x62,0x29,0x12,0x37,0xd4,0x7e,0x37,0x28,0x8a, +0xbe,0x34,0x4, 0x4c,0x8, 0x6e,0x6c,0xdd,0x80,0x62,0xc2,0x0, 0x7c,0xbd,0x12,0x37, +0xdc,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xb4,0x6e,0x7a,0x35,0x24,0x9e, +0x35,0x26,0x7a,0x35,0x24,0x7e,0x35,0x26,0x3e,0x34,0x3e,0x34,0x12,0x98,0x8d,0x7a, +0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e,0x35,0x28,0xbe,0x35,0x24, +0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35,0x26,0x8, 0x2, 0xd2,0x0, 0x7c,0xbd,0x12,0xb5, +0x39,0x50,0x2, 0xc2,0x0, 0x30,0x0, 0x12,0x7c,0xbd,0x6c,0x77,0x12,0x36,0xca,0x7e, +0x70,0x2, 0xac,0x7d,0x12,0x37,0xe9,0x12,0x37,0xb9,0xb, 0xd0,0x7e,0x73,0x28,0x84, +0xbc,0x7d,0x38,0x96,0xda,0x79,0xda,0xd8,0x22,0x7c,0x6b,0x7e,0xa3,0x37,0x6c,0x7e, +0x50,0x2, 0xac,0x5a,0x19,0x62,0x37,0xa9,0x19,0x72,0x37,0xaa,0x7c,0xba,0x4, 0x7a, +0xb3,0x37,0x6c,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x70,0x22,0x7c,0xab,0x7e,0x70, +0x2, 0xac,0x7a,0x12,0x37,0xe9,0x2, 0x2c,0x1, 0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26, +0xfb,0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0,0x34,0x38,0x3, 0x2, 0x39,0x4, 0xbe,0xa0, +0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0x41,0x23,0xbe,0xa0,0x36,0x68,0x5, 0xbe,0xa0, +0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0x8, 0x2e,0x37,0x34, +0x8a,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, 0x41,0x23,0x75,0x1e,0x36,0x41,0x23, +0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78,0x1b,0x7e,0xf3,0x39,0x6, 0x7c,0xbf, +0x4, 0x7a,0xb3,0x39,0x6, 0xbe,0xa0,0x39,0x78,0x3, 0x75,0x1e,0x38,0xa, 0x3f,0x9, +0xb3,0x2b,0x21,0x41,0x23,0xbe,0xa0,0x3a,0x68,0x5, 0xbe,0xa0,0x3b,0x78,0x1b,0x7e, +0xf3,0x39,0x8, 0x7c,0xbf,0x4, 0x7a,0xb3,0x39,0x8, 0xbe,0xa0,0x3b,0x78,0x3, 0x75, +0x1e,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44,0x41,0x23,0xbe,0xa0,0xfb,0x78,0x6, 0x7e, +0xb3,0x2b,0x12,0x41,0x23,0xbe,0xa0,0x5e,0x78,0x26,0x7e,0xf, 0x33,0xe2,0x69,0x30, +0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x1, 0x3, 0x3, +0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c,0xa7,0x4c,0xba,0x44,0x80,0x41,0x23, +0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78,0x1b,0x7e,0xf3,0x39,0xa, 0x7c,0xbf, +0x4, 0x7a,0xb3,0x39,0xa, 0xbe,0xa0,0x3d,0x78,0x3, 0x75,0x1e,0x3c,0xa, 0x3f,0x9, +0xb3,0x2a,0x7a,0x41,0x23,0xbe,0xa0,0x3e,0x68,0x5, 0xbe,0xa0,0x3f,0x78,0x1b,0x7e, +0xf3,0x39,0xc, 0x7c,0xbf,0x4, 0x7a,0xb3,0x39,0xc, 0xbe,0xa0,0x3f,0x78,0x3, 0x75, +0x1e,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d,0x41,0x23,0xbe,0xa0,0x40,0x40,0xd, 0xbe, +0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x38,0xe2,0x41,0x23,0xbe,0xa0,0x4e,0x68, +0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x39,0x27,0x7c,0xbf,0x4, 0x7a,0xb3,0x39, +0x27,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1e,0x4e,0xa, 0x3f,0x2e,0x37,0x34,0x88,0x7e, +0x39,0xb0,0x41,0x23,0xbe,0xa0,0x51,0x68,0x5, 0xbe,0xa0,0x52,0x78,0x28,0x7e,0x14, +0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e,0xb3,0x39,0x32,0xa, 0x3b,0x6d,0x22, +0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x39,0x32,0xbe,0xa0,0x52,0x78,0x3, 0x75, +0x1e,0x51,0x7c,0xb7,0x41,0x23,0xbe,0xa0,0x5c,0x68,0x5, 0xbe,0xa0,0x5d,0x78,0x1a, +0x7e,0xf3,0x38,0xfb,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xfb,0xbe,0xa0,0x5d,0x78,0x3, +0x75,0x1e,0x5c,0x7c,0xbf,0x12,0x3a,0x26,0x41,0x23,0xbe,0xa0,0x60,0x40,0xd, 0xbe, +0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x39,0xaa,0x41,0x23,0xbe,0xa0,0x6d,0x78, +0x4, 0xe5,0xe, 0x80,0x7e,0xbe,0xa0,0xf4,0x68,0x5, 0xbe,0xa0,0xf5,0x78,0x18,0x7e, +0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, 0x9, 0xb3,0x34,0x90,0xbe,0xa0,0xf5, +0x78,0x61,0x75,0x1e,0xf4,0x80,0x5c,0xbe,0xa0,0xf0,0x68,0x5, 0xbe,0xa0,0xf1,0x78, +0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80,0x49,0xbe,0xa0,0xf2,0x68,0x5, 0xbe, +0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14,0x7e,0x1f,0x34,0x8c,0x2d,0x31,0xb, +0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56,0x80,0x28,0x7d,0x53,0x80,0x24,0xbe, +0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x1b,0xbe,0xa0,0xf7,0x78,0xd, 0x7e,0x34,0x62, +0x48,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x50,0x80,0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4, +0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e,0xb3,0x2a, +0x6e,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51,0x7e,0x13, +0x2a,0x6e,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x2a,0x6d,0xa, 0x10,0xa, 0x21,0x2d,0x12, +0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x32,0xfa, +0x80,0x2d,0x7e,0x3, 0x2a,0x6d,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42,0xa, 0x3a, +0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58,0xe, 0x9d, +0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x32,0xfc,0x80,0x2, 0xe4,0x22,0x7e, +0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80, +0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0x3a,0x26,0xa, +0x1b,0x7e,0x63,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac,0x1f,0x2d, +0x3, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x12,0x3a,0xe5,0x9d,0x35,0x1b,0x1a,0x10,0xb, +0xf0,0x12,0x3a,0xe5,0x7e,0x73,0x2a,0x6e,0xa, 0x27,0x2d,0x25,0xa, 0x3f,0xbd,0x32, +0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x2a,0x6d,0x74,0x2, 0xa4,0x22,0x12,0x3f,0xb3, +0xb4,0x1, 0x14,0xca,0x39,0x7e,0x18,0x39,0x22,0x7e,0x8, 0x25,0xee,0x12,0x1f,0xc9, +0x1b,0xfd,0x12,0x3f,0x52,0x80,0x12,0xca,0x39,0x7e,0x18,0x39,0x22,0x7e,0x8, 0x2b, +0x70,0x12,0x1f,0xc9,0x1b,0xfd,0x12,0x3f,0x70,0x2, 0x3b,0x1c,0x7a,0x1f,0x2a,0xfc, +0x7a,0xf, 0x2a,0xf8,0x22,0xca,0xf8,0x7c,0x6b,0xa5,0xbe,0x0, 0x9, 0x7c,0xb7,0x12, +0x6c,0x94,0xd2,0x8, 0xa1,0xa7,0xa5,0xbe,0x1, 0x3d,0x7a,0x73,0x38,0xe3,0xa5,0xbf, +0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, 0xd2,0x9, 0xa1,0xa7,0xa5,0xbf,0xaa,0x5, +0x12,0xc5,0x83,0x80,0x1e,0xa5,0xbf,0xab,0xa, 0x7e,0x34,0x5, 0x7a,0x7a,0x37,0x34, +0x8a,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80,0x2, 0xa1,0xa7,0x7e,0x34,0x4, 0xfc,0x7a, +0x37,0x34,0x8a,0x6d,0x33,0x81,0x23,0xbe,0x60,0x4, 0x40,0x20,0xbe,0x60,0x8, 0x38, +0x1b,0x12,0x3d,0xaa,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, 0xa1,0xa7,0xa5, +0xbe,0x8, 0x2, 0x80,0x2, 0xa1,0xa7,0x12,0x3f,0xd1,0xa1,0xa7,0xa5,0xbe,0xa, 0x9, +0x43,0xc, 0x20,0x7a,0x73,0x38,0xec,0xa1,0xa7,0xa5,0xbe,0xb, 0x8, 0x12,0x3d,0xaa, +0x12,0x3f,0xd4,0xa1,0xa7,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c,0x38,0x2, 0xa1, +0x3f,0xbe,0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23,0x38,0x8, 0x12,0x3d,0xac,0x43,0xc, +0x40,0xa1,0xa7,0xbe,0x60,0x15,0x40,0x1a,0xbe,0x60,0x18,0x38,0x15,0x12,0x3d,0xac, +0xd2,0x8, 0xa5,0xbe,0x15,0x2, 0x80,0x2, 0xa1,0xa7,0x74,0x7, 0x7a,0xb3,0x38,0xe6, +0xa1,0xa7,0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3,0x38,0xfb,0xa1,0xa7,0xbe,0x60,0x24, +0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0xa1,0x3f,0xa5,0xbe,0x2d,0x1b,0x12,0x3d,0xac, +0x20,0x9, 0x2, 0xa1,0xa7,0x7e,0x63,0x39,0xe, 0x7c,0x46,0x6c,0x55,0xa, 0x37,0x2d, +0x32,0x3e,0x34,0x7a,0x35,0x8, 0xa1,0xa7,0xbe,0x60,0x2f,0x40,0xa, 0xbe,0x60,0x33, +0x38,0x5, 0x43,0xc, 0x8, 0xa1,0x3f,0xa5,0xbe,0x34,0xf, 0x43,0xc, 0x10,0xbe,0x70, +0x64,0x38,0x2, 0xa1,0x3f,0x7e,0x70,0x64,0xa1,0x3f,0xbe,0x60,0x38,0x68,0x4, 0xa5, +0xbe,0x39,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x39,0x7, 0x7c,0xbf,0x4, 0x7a,0xb3,0x39, +0x7, 0xa, 0x2f,0x19,0x72,0x2b,0x21,0xa5,0xbe,0x39,0x2, 0x80,0x2, 0xa1,0xa7,0x75, +0x1e,0x38,0xa1,0xa7,0xbe,0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21,0x43,0xc, 0x2, +0x7e,0xf3,0x39,0x9, 0x7c,0xbf,0x4, 0x7a,0xb3,0x39,0x9, 0xa, 0x2f,0x19,0x72,0x2b, +0x44,0xa5,0xbe,0x3b,0x2, 0x80,0x2, 0xa1,0xa7,0x75,0x1e,0x3a,0xa1,0xa7,0xa5,0xbe, +0xfb,0x9, 0x43,0xc, 0x4, 0x7a,0x73,0x2b,0x12,0xa1,0xa7,0xa5,0xbe,0x50,0x6, 0x7a, +0x73,0x39,0x32,0xa1,0xa7,0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d,0x21,0x43,0xc, +0x1, 0x7e,0xf3,0x39,0xb, 0x7c,0xbf,0x4, 0x7a,0xb3,0x39,0xb, 0xa, 0x2f,0x19,0x72, +0x2a,0x7a,0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0xa1,0xa7,0x75,0x1e,0x3c,0xa1,0xa7,0xbe, +0x60,0x3e,0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x39,0xd, 0x7c, +0xbf,0x4, 0x7a,0xb3,0x39,0xd, 0xa, 0x2f,0x19,0x72,0x2a,0x9d,0xa5,0xbe,0x3f,0x2, +0x80,0x2, 0xa1,0xa7,0x75,0x1e,0x3e,0xa1,0xa7,0xbe,0x60,0x40,0x40,0xd, 0xbe,0x60, +0x42,0x38,0x8, 0x12,0x3d,0xac,0x75,0xd, 0x1, 0x80,0xa, 0xa5,0xbe,0x43,0xb, 0x12, +0x3d,0xac,0x75,0xd, 0x2, 0x12,0x3a,0xed,0x80,0x7d,0xa5,0xbe,0x44,0x8, 0x12,0x3d, +0xac,0x12,0x3f,0x79,0x80,0x71,0xbe,0x60,0x45,0x68,0x4, 0xa5,0xbe,0x46,0x5, 0x12, +0x3d,0xac,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, 0xa5,0xbe,0x4f,0x20,0x43,0xd, 0x4, +0x7e,0xf3,0x39,0x28,0x7c,0xbf,0x4, 0x7a,0xb3,0x39,0x28,0xa, 0x2f,0x2e,0x27,0x34, +0x88,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75,0x1e,0x4e,0x80,0x3a,0xa5,0xbe,0x6d, +0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0,0x40,0x25,0xbe,0x60,0xf3,0x38,0x20, +0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0xf3,0x1a,0x7e,0x15,0x12, +0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x34,0x8c,0x2d,0x30,0x1b,0x1a,0x10,0x80,0x7, +0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8,0x22,0xd2,0x8, 0xa, 0x26,0x19,0x72, +0x38,0xe2,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x14,0x12,0x3f,0x70,0x12,0x3b,0x1c,0x7e, +0x18,0x6, 0x76,0x7a,0x1f,0x6, 0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x10,0xb4,0x1, 0x11, +0x12,0x3f,0x52,0x12,0x3b,0x1c,0x12,0x5f,0xb8,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, +0xf8,0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12,0x3d,0xb3,0x12,0x3d,0xfa,0xe4,0x12, +0x0, 0x1e,0x74,0x1, 0x12,0x3d,0xb3,0x2, 0x3d,0xfa,0xca,0x3b,0x7e,0xd3,0x2a,0x73, +0x7e,0xc3,0x2a,0x74,0x7e,0x8, 0x1f,0x44,0x12,0x3f,0xf4,0x7e,0x8, 0x1f,0x8a,0x7e, +0x34,0x0, 0x46,0x12,0x1f,0xee,0x7e,0x8, 0x1f,0xd0,0x7e,0x34,0x0, 0xa, 0xe4,0x12, +0x1f,0xee,0x7e,0x8, 0x1f,0xda,0x7e,0x34,0x0, 0xa, 0x12,0x1f,0xee,0x7e,0xf3,0x2a, +0xfc,0x7e,0x18,0x2a,0xdc,0x7a,0x1d,0x24,0x7e,0x18,0x1f,0xd0,0x7a,0x1d,0x28,0x7c, +0xbd,0x7c,0x7c,0x7e,0x8, 0x2a,0xb9,0x12,0xbb,0xa0,0x6c,0xee,0x80,0x29,0xa, 0x3e, +0x9, 0xa3,0x2a,0xdc,0xa, 0x3a,0x2e,0x34,0x1f,0x83,0x12,0x57,0xf0,0x7c,0xab,0xbe, +0xa0,0x1c,0x50,0x11,0xa, 0x3e,0x12,0x3f,0xe, 0x19,0xb4,0x1f,0x44,0x7e,0xb3,0x2a, +0xfb,0x19,0xb4,0x1f,0x8a,0xb, 0xe0,0xbc,0xce,0x38,0xd3,0x6c,0xee,0x80,0x22,0xa, +0x3e,0x9, 0xa3,0x2a,0xb9,0xbe,0xa0,0x23,0x50,0x15,0xa, 0x2e,0xa, 0x3c,0x2d,0x32, +0x12,0x3f,0xe, 0x19,0xb4,0x1f,0x60,0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f,0xa6,0xb, +0xe0,0xbc,0xde,0x38,0xda,0x7e,0xb3,0x2a,0xfd,0x7e,0x8, 0x1f,0xe4,0x60,0x9, 0x7e, +0x18,0x1f,0xd0,0x12,0xb9,0x60,0x80,0x3, 0x12,0x3f,0xe4,0x6c,0xee,0x7e,0x18,0x1f, +0xe4,0x7a,0x1f,0x1f,0x34,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xd0,0x7a,0x37,0x1f, +0x38,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xda,0x7a,0x37,0x1f,0x3a,0x7e,0x70,0xe, +0xac,0x7e,0x2e,0x34,0x1f,0x44,0x6d,0x22,0x7a,0x1f,0x1f,0x3c,0x7e,0x70,0xe, 0xac, +0x7e,0x2e,0x34,0x1f,0x8a,0x7a,0x1f,0x1f,0x40,0x7e,0x8, 0x1f,0x34,0x7c,0xbf,0x7c, +0x7e,0x12,0x8, 0x0, 0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b,0x22,0x2e,0x37, +0x2a,0xfe,0x7e,0x39,0xb0,0xa, 0x4a,0x22,0x74,0x1, 0x7a,0xb3,0x3, 0xc5,0x12,0xa8, +0xd1,0x12,0x12,0xf5,0x12,0xba,0xc2,0xe4,0x12,0x7, 0x45,0x7e,0x24,0x3, 0xd4,0x7d, +0x32,0x74,0xfa,0x12,0x11,0xd0,0x74,0x1, 0x12,0x3d,0xb3,0x12,0x3f,0xdd,0x7e,0x34, +0xd0,0xc, 0x12,0x1, 0xe, 0x12,0x3d,0xe2,0x7e,0x34,0x0, 0x1, 0x12,0x3f,0xd7,0x2, +0x10,0xfc,0x7e,0x1f,0x25,0xf2,0x7e,0xf, 0x25,0xee,0x22,0x7a,0xb3,0x2b,0x0, 0x70, +0x5, 0x12,0x3f,0x70,0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x3f,0x52,0x12,0x3b,0x1c,0x22, +0x7e,0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x22,0x12,0x3f,0xb3,0xb4,0x1, 0x17,0xca, +0x39,0x7e,0x18,0x25,0xee,0x7e,0x8, 0x39,0x22,0x12,0x1f,0xc9,0x1b,0xfd,0x12,0xc5, +0x7a,0x12,0x3f,0x52,0x80,0x1a,0xca,0x39,0x7e,0x18,0x2b,0x70,0x7e,0x8, 0x39,0x22, +0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x37,0x2b,0x76,0x7a,0x37,0x34,0x88,0x12,0x3f,0x70, +0x2, 0x3b,0x1c,0x7e,0xb3,0x39,0x26,0x7e,0x34,0x0, 0x4, 0x22,0x7c,0x6b,0x12,0x3f, +0xec,0x78,0x5, 0x7c,0xb6,0x2, 0x6c,0xbf,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x3b,0x25, +0x22,0xb2,0x86,0x22,0xb2,0x82,0x22,0xe4,0x6c,0x55,0x2, 0x12,0x1, 0x7e,0x8, 0x2a, +0x6d,0x2, 0x0, 0x2e,0x7e,0x34,0x0, 0x8, 0xe4,0x2, 0x1f,0xee,0x7e,0xb3,0x38,0xe2, +0xc4,0x54,0x7, 0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x1f,0xee,0x30,0x8, 0x3b, +0xc2,0x8, 0x12,0x25,0xb7,0x7e,0x73,0x38,0xe7,0x7a,0x73,0x2a,0x4d,0x7e,0x73,0x38, +0xe8,0x7a,0x73,0x2b,0x1d,0x7e,0x73,0x38,0xe8,0x7a,0x73,0x2b,0x1, 0x7e,0xb3,0x38, +0xe9,0x60,0x18,0x7e,0x34,0x0, 0x2, 0x12,0x41,0x69,0x7e,0x34,0x0, 0x1, 0x12,0x41, +0x69,0x6d,0x33,0x12,0x41,0x69,0xe4,0x7a,0xb3,0x38,0xe9,0x12,0x50,0x6, 0x2, 0x40, +0x41,0xe5,0xc, 0x70,0x2, 0x21,0x68,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, 0xfe,0x12, +0x5b,0x75,0x12,0x64,0x56,0x7e,0x8, 0x2a,0x6d,0x12,0x8, 0xd0,0xe5,0xc, 0x30,0xe1, +0x6, 0x53,0xc, 0xfd,0x12,0xbb,0x57,0xe5,0xc, 0x30,0xe2,0x32,0x53,0xc, 0xfb,0x7e, +0xb3,0x2b,0x12,0x60,0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0x93,0x80,0xb, 0x7e,0xb3, +0x2b,0x65,0x7e,0x73,0x2b,0x64,0x12,0xa, 0x24,0x7e,0x73,0x2b,0x12,0x2e,0x70,0xff, +0x92,0x1, 0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x2a,0x77,0x12,0x9, 0x95,0xe5,0xc, +0x30,0xe3,0x4b,0x53,0xc, 0xf7,0x7e,0x73,0x39,0x14,0x7a,0x73,0x2b,0xf, 0x12,0xa4, +0xdf,0x7a,0xb3,0x2f,0xa9,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e,0x73,0x2f, +0xa9,0x7a,0x73,0x38,0xec,0x12,0x4d,0xec,0x7e,0x8, 0x2a,0x6d,0x12,0xb, 0xe9,0x7e, +0x73,0x39,0x15,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2,0x10,0x30, +0x10,0x9, 0xc2,0x10,0x12,0xa8,0xd1,0xe4,0x12,0x7, 0x45,0x12,0x4f,0x45,0xe5,0xc, +0x30,0xe4,0x13,0x53,0xc, 0xef,0x7e,0x43,0x39,0x16,0x7e,0x50,0xa, 0xac,0x45,0x7d, +0x32,0x74,0xfa,0x12,0x11,0xd0,0xe5,0xc, 0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e,0x73, +0x39,0x2, 0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x39,0x2, 0xa9,0xd5,0xcb, +0x74,0xe, 0x12,0x43,0xef,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63,0x39,0x2, 0xa, 0x26, +0x2e,0x24,0x0, 0x3, 0x12,0x94,0x98,0x7c,0x65,0x4c,0x76,0x74,0xe, 0x12,0x43,0x63, +0x12,0x43,0xef,0x12,0x43,0xf7,0x7e,0x73,0x39,0x5, 0x7a,0x73,0x2b,0x14,0x7e,0x73, +0x39,0x4, 0x7a,0x73,0x2b,0x1f,0x12,0xc5,0x8c,0xe5,0xc, 0x30,0xe5,0xa, 0x53,0xc, +0xdf,0x7e,0xb3,0x38,0xec,0x2, 0x48,0x6d,0x22,0xca,0xd8,0xca,0x79,0x7d,0xd3,0x90, +0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90,0x60,0x51,0xe4,0x93,0x7c,0x8b,0xa, 0x38,0xa, +0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c,0x7c,0xe7,0x12,0x26,0x28,0xa9,0xd0,0xc4,0xa9, +0xd5,0xcb,0x74,0x7, 0x12,0x43,0xef,0x7c,0x8b,0x74,0x7, 0x7e,0x70,0xf, 0x12,0x43, +0xf4,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x33,0xe6,0x79,0x51,0x0, 0x6, 0x7e,0x54,0x0, +0x80,0x7e,0x1f,0x33,0xe6,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f,0x33, +0xe6,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78,0xb, 0x7e,0x1f,0x33,0xe6,0x12, +0x43,0x4c,0x44,0x1, 0x80,0x20,0x7e,0x1f,0x33,0xe6,0x12,0x43,0x4c,0x44,0x8, 0x1b, +0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x33,0xe6,0x78,0x7, 0x12,0x43,0x4c,0x54,0xfb,0x80, +0x5, 0x12,0x43,0x4c,0x44,0x4, 0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xe2,0x69,0xe1,0x0, +0x84,0x69,0x51,0x0, 0x90,0x7d,0xf5,0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a, +0x50,0x7e,0xb3,0x3, 0xcf,0xbe,0xb0,0x6, 0x40,0x3, 0xb4,0xff,0xe, 0x12,0x43,0x57, +0x54,0xe6,0x12,0x43,0x54,0x4e,0x54,0x1, 0xa4,0x80,0xc, 0x12,0x43,0x57,0x5e,0x54, +0xfe,0xe6,0x12,0x43,0x54,0x44,0xa4,0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x29, +0x7e,0x1f,0x33,0xe6,0x12,0x43,0x4c,0x12,0x45,0x8c,0x7e,0x1f,0x33,0xe6,0x12,0x43, +0x4c,0x44,0x50,0x1b,0x1a,0x50,0x7e,0x34,0x0, 0x2, 0x12,0x44,0x9f,0x12,0x44,0xe1, +0x12,0x44,0xbe,0x7a,0x37,0x34,0x90,0x61,0x8, 0x6c,0xdd,0x61,0x2, 0x4c,0xdd,0x78, +0x4, 0x6c,0x99,0x80,0x2b,0xbc,0xfd,0x40,0x12,0xa, 0xcd,0x9, 0x9c,0x2a,0xb8,0xbe, +0x90,0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, 0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d, +0xc3,0x9, 0x9c,0x2a,0xdb,0xbe,0x90,0x1c,0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24, +0x7e,0x1f,0x33,0xe6,0x12,0x43,0x4c,0x12,0x45,0x8c,0xa, 0xc9,0x3e,0xc4,0x3e,0xc4, +0x3e,0xc4,0x3e,0xc4,0x7e,0x1f,0x33,0xe6,0x12,0x43,0x4c,0x4d,0x5c,0x1b,0x1a,0x50, +0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, 0x80, +0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x44,0x9f,0x12,0x44,0xe1,0xbe,0xd4,0x0, 0x1, 0x78, +0x10,0x12,0x44,0xe1,0x12,0x44,0xbe,0x74,0x2, 0xac,0xbd,0x59,0x35,0x34,0x92,0x80, +0xf, 0x12,0x44,0xbe,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59,0x32,0x34,0x92, +0xb, 0xd0,0xbc,0xed,0x28,0x2, 0x41,0x6d,0xa9,0xd5,0xcb,0x74,0x7, 0x7c,0x78,0x12, +0x43,0xf4,0xa9,0xc0,0xc4,0x7e,0x1f,0x33,0xe2,0x79,0xe1,0x0, 0x84,0x7e,0x1f,0x33, +0xe2,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x33,0xe6,0x79,0x30,0x0, 0x6, 0x7e, +0xf, 0x33,0xe6,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x33,0xe6,0x79,0x30,0x0, 0x10,0x7e, +0xf, 0x33,0xe6,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x2e,0x34,0x0, 0xe, +0xb, 0x1a,0x50,0x22,0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xe2,0x2e,0x34,0x0, 0x84,0xb, +0x1a,0x50,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xca,0x79,0xa9,0xd5,0xcb,0x74,0x2, +0x7e,0x70,0x3f,0x12,0x43,0x63,0x74,0xf, 0x12,0x43,0xef,0x7c,0xfb,0x74,0xf, 0x7c, +0x7f,0x5e,0x70,0xfe,0x12,0x43,0x63,0x74,0xc, 0x12,0x43,0xef,0x7c,0xfb,0x54,0x7f, +0x68,0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x43,0x63,0x90,0x61,0x18,0xe4,0x93,0x7c, +0xab,0xbe,0xa0,0x7, 0x38,0xb, 0x12,0x44,0x2c,0x7c,0xb7,0xa, 0x7b,0xb, 0x75,0x80, +0x16,0x90,0x61,0x17,0xe4,0x93,0xb4,0x1, 0xe, 0xbe,0xa0,0x7, 0x28,0x9, 0x12,0x44, +0x2c,0xa, 0x77,0x2e,0x74,0x0, 0x7, 0x74,0xe, 0x7c,0x7f,0x12,0x43,0x63,0x74,0x7, +0x12,0x43,0xef,0x7c,0xfb,0x5e,0xf0,0xfb,0x90,0x60,0x2, 0xe4,0x93,0xa, 0x3b,0x3e, +0x34,0x3e,0x34,0x4c,0xf7,0x74,0x7, 0x7c,0x7f,0x12,0x43,0xf4,0xda,0x79,0x22,0xf5, +0xfd,0xe5,0xfe,0x22,0x12,0x43,0x63,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0x6d,0x33, +0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x12,0x12,0xb8,0x5e,0xe5,0x34,0x20,0xe7,0x1b, +0xa9,0xd5,0xcb,0x74,0x3, 0x7e,0x71,0x27,0x12,0x43,0x63,0x74,0xb, 0x7e,0x71,0x2f, +0x12,0x43,0x63,0x74,0xc, 0x7e,0x71,0x30,0x12,0x43,0xf4,0x22,0xa, 0x3a,0x2e,0x34, +0x0, 0x3, 0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x7e,0x24,0x3, 0x9e,0x30, +0x11,0x5c,0xc2,0x11,0x9, 0x72,0x0, 0x2, 0xa, 0x37,0x12,0x44,0x32,0x7a,0x37,0x2a, +0x4f,0x9, 0x72,0x0, 0x3, 0xa, 0x37,0x12,0x44,0x32,0x7a,0x37,0x2a,0x51,0x9, 0x72, +0x0, 0x4, 0xa, 0x37,0x12,0x44,0x32,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0x12,0x45, +0x85,0x7a,0x37,0x2a,0x5a,0x9, 0x72,0x0, 0x1, 0x12,0x45,0x85,0x7a,0x37,0x2a,0x5c, +0x9, 0x72,0x0, 0x5, 0xa, 0x37,0x12,0x44,0x32,0x7a,0x37,0x2a,0x62,0x9, 0x72,0x0, +0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a,0x73,0x2a,0x6b,0x2, 0xab,0x7a,0x22,0x7d, +0x23,0x80,0x12,0x7e,0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x45,0x94,0x7c,0x23,0x1b, +0x30,0xa5,0xba,0x0, 0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x7e,0xf, +0x33,0xe6,0x69,0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, 0x6d,0x0, +0x2f,0x10,0x74,0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4, +0x22,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xe6,0x79,0x30,0x0, 0x4, 0x7e,0xf, 0x33, +0xe6,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, 0x79, +0x30,0x0, 0x12,0x22,0x12,0x47,0xd8,0xc2,0x0, 0x12,0x47,0xf0,0xc2,0x2, 0x12,0x45, +0xd0,0xc2,0x0, 0x12,0x47,0xa0,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x43,0xef,0x7a,0x1b, +0xb0,0x74,0xf, 0x6c,0x77,0x12,0x43,0x63,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10, +0x2, 0x43,0xf7,0x24,0xab,0x68,0x10,0x24,0xef,0x68,0x20,0x24,0xde,0x68,0x2e,0x24, +0xde,0x78,0x3b,0x74,0x5, 0x80,0x39,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x36,0x7e,0x34, +0x0, 0x1, 0x12,0x44,0x9f,0x12,0xb5,0xdf,0x2, 0xb6,0xf9,0x7e,0xb3,0x3, 0xff,0xb4, +0x5, 0x22,0x7e,0x34,0x0, 0x1, 0x12,0x44,0x9f,0x75,0xe9,0xff,0x22,0x7e,0xb3,0x3, +0xff,0xb4,0x5, 0x10,0x7e,0x34,0x0, 0x1, 0x12,0x44,0x9f,0x2, 0xb6,0xf3,0x74,0x1, +0x7a,0xb3,0x3, 0xff,0x22,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x22,0x5e,0x54,0x0, 0xf, +0x1b,0x1a,0x50,0x22,0x7c,0xab,0x80,0xe, 0x7e,0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67, +0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xea,0x22,0x7c, +0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x43,0x63,0x7a,0x61,0xfc,0x12,0x43,0xf7,0x12, +0x46,0xe7,0xd2,0x0, 0x12,0x47,0xa0,0x12,0x45,0xea,0x12,0x12,0xde,0x2, 0x12,0x96, +0xa9,0xd0,0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22,0x30,0x1, 0x6, 0x12,0x45,0xea,0x2, +0x12,0x96,0x12,0x47,0xd8,0xc2,0x2, 0x2, 0x45,0xd0,0xd2,0x2, 0x12,0x45,0xd0,0x74, +0x1, 0x22,0x12,0x46,0x4e,0x12,0x47,0xe7,0x75,0xcd,0x0, 0xa9,0xd6,0xeb,0xa9,0xd7, +0xcd,0xc2,0xce,0x12,0x5f,0xc1,0x12,0x45,0x4, 0x74,0x1, 0x12,0x46,0x86,0xa9,0xc6, +0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x45,0xaf,0x30,0x1c, +0x5, 0xc2,0x1, 0x12,0x45,0xd9,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1b,0x3, 0x20, +0x1c,0x14,0x12,0x46,0x4e,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x46,0x86, +0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x1, 0x2, 0x45,0xd9,0x74,0x81, +0x7a,0xb3,0x3a,0x32,0x22,0x80,0x1d,0x12,0x46,0x4e,0x12,0x47,0xdf,0x68,0x5, 0xc2, +0x1, 0x12,0x45,0xd9,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1b,0x15, +0xe4,0x12,0x46,0x86,0x20,0x93,0xe0,0x12,0x46,0x4e,0xa9,0xd1,0xcd,0xa9,0xc5,0xea, +0x74,0x2, 0x2, 0x46,0x86,0x22,0x7c,0xab,0x7e,0xb3,0x3a,0x32,0xb4,0x81,0x38,0x4c, +0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2,0xaf,0xa9, +0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0,0x2, 0x78, +0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1,0x87,0xd2, +0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3a,0x32,0x22,0xd2,0x0, 0x80, +0x12,0x30,0x0, 0xc, 0x12,0x47,0xdf,0x68,0x7, 0xc2,0x0, 0xc2,0x1, 0x12,0x45,0xd9, +0x12,0x46,0x55,0x30,0x1b,0xeb,0x22,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2, +0x0, 0x12,0x47,0xf0,0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9, +0xd0,0x9e,0x75,0x9c,0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41, +0x12,0x45,0x94,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8, +0x22,0xe4,0x12,0x47,0x6f,0x12,0xb6,0x95,0x12,0x26,0x28,0x12,0xb7,0x10,0x12,0x43, +0x69,0x12,0xb5,0xd5,0x12,0xb6,0xac,0x12,0x0, 0x9, 0x12,0xb6,0xb8,0x12,0x6f,0xfa, +0x12,0xb6,0xc8,0xd2,0xaf,0x12,0xb6,0x27,0x12,0xb8,0x44,0x12,0x43,0xfe,0x12,0x46, +0xe7,0x7e,0x8, 0x3a,0xa, 0x12,0xb7,0x30,0x90,0x60,0x50,0xe4,0x93,0xca,0xb8,0x90, +0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24,0xff,0xff,0xda,0xb8,0x2, 0x11,0x34,0xa9, +0xc4,0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0xc5,0x56,0xa9,0xd0,0xce, +0xa9,0xc0,0xc9,0xd2,0x2, 0x12,0x45,0xd0,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75,0xc2, +0xc, 0xd2,0x0, 0x12,0x47,0xa0,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1,0x22, +0xa2,0x0, 0xa9,0x97,0xc1,0xa2,0x0, 0xa9,0x97,0xc2,0x22,0xd2,0x1, 0x2, 0x45,0xd9, +0x74,0x1, 0x12,0x47,0xcf,0x20,0x1b,0x6, 0x12,0x46,0xcd,0x12,0x47,0xab,0x7e,0xb3, +0x34,0x3a,0xb4,0x1, 0x6, 0x12,0x87,0x12,0x12,0x47,0xab,0xe4,0x2, 0x47,0xcf,0xbe, +0xb0,0x8, 0x50,0x3, 0x12,0xc5,0x56,0x22,0xe4,0x12,0x12,0xde,0x2, 0x12,0x96,0x7e, +0xb3,0x34,0x3a,0xbe,0xb0,0x1, 0x22,0x12,0x47,0xdf,0x68,0xfb,0x20,0x93,0xfd,0x22, +0xa9,0xd0,0xce,0xa2,0x0, 0xa9,0x95,0xc9,0x22,0x12,0xc5,0x83,0x12,0xc5,0x7a,0x6d, +0x33,0x7a,0x35,0xa, 0x12,0x48,0x4c,0x12,0x48,0x26,0x74,0x50,0x7a,0xb3,0x39,0x16, +0x7e,0x24,0x3, 0x20,0x7d,0x32,0x74,0xfa,0x12,0x11,0xd0,0xe4,0x12,0xc5,0x7, 0x6d, +0x33,0x7a,0x37,0x3a,0x34,0x22,0x7e,0x73,0x2b,0x62,0x7a,0x73,0x39,0x15,0x22,0xa2, +0xe, 0xe4,0x33,0x7a,0xb3,0x39,0x10,0x7e,0x73,0x39,0x14,0xbe,0x73,0x2b,0xf, 0x68, +0xa, 0xe5,0xc, 0x70,0x6, 0x12,0x48,0x4c,0x12,0x48,0x26,0x22,0x7e,0x73,0x2b,0xf, +0x7a,0x73,0x39,0x14,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x39,0x4, 0x7e,0x73,0x2b,0x20, +0x7a,0x73,0x39,0x3, 0x7e,0x73,0x2b,0x14,0x7a,0x73,0x39,0x5, 0x22,0xca,0xd8,0xca, +0x79,0x7c,0xdb,0x90,0x61,0xc5,0xe4,0x93,0x7c,0xab,0xbe,0xd0,0x80,0x78,0x1a,0x7e, +0xe0,0xff,0x6c,0xff,0x80,0xd, 0x12,0x48,0xdd,0xbc,0xbe,0x38,0x4, 0x7c,0xeb,0x7c, +0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xef,0x80,0x1c,0xbe,0xd0,0x81,0x78,0x17,0x6c,0xee, +0x6c,0xff,0x80,0xd, 0x12,0x48,0xdd,0xbc,0xbe,0x40,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, +0xf0,0xbc,0xaf,0x38,0xef,0xbc,0xad,0x38,0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0x4d,0xf4, +0x12,0x48,0x64,0x12,0x4c,0xc6,0x12,0x48,0xf7,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x39, +0x14,0x12,0x48,0x26,0x7a,0xd3,0x38,0xec,0xda,0x79,0xda,0xd8,0x22,0x7e,0x90,0x5, +0xac,0x9f,0x9, 0xb4,0x26,0x33,0x22,0x30,0x0, 0x3, 0x12,0x48,0x64,0xa2,0x1, 0x92, +0x2, 0x12,0x49,0xb4,0x2, 0x48,0xf7,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x39,0x3, 0x22, +0x74,0x40,0x12,0x67,0x1b,0x50,0x9, 0xd2,0x0, 0xd2,0x1, 0x12,0x48,0xe7,0x80,0x15, +0x74,0x1, 0x12,0x49,0x2e,0x7e,0x43,0x39,0x1, 0x7e,0x50,0x64,0xac,0x45,0x12,0x81, +0x8, 0x7a,0xb3,0x2b,0x1f,0x12,0x48,0xf7,0x12,0x4c,0xc6,0x2, 0x48,0x64,0xca,0x3b, +0x7c,0xdb,0xe4,0x7a,0xb3,0x2b,0x14,0x7e,0x8, 0x2a,0x6d,0x12,0xb, 0xe9,0x7e,0xc0, +0xa, 0x12,0x4c,0xd6,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x1f,0x33,0xfb, +0x12,0x81,0x84,0x7d,0x73,0xbe,0x74,0xff,0xff,0x78,0xc, 0x12,0x49,0xab,0xb, 0xa, +0x30,0x2e,0x34,0x0, 0x3, 0x80,0x1e,0xbe,0x74,0x80,0x0, 0x28,0xa, 0x12,0x49,0xab, +0xb, 0xa, 0x30,0xb, 0x35,0x80,0xe, 0xbe,0x74,0x40,0x0, 0x28,0xf, 0x12,0x49,0xab, +0xb, 0xa, 0x30,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xb5,0xbe,0xd0,0x1, 0x78, +0x9, 0x7e,0x1f,0x33,0xfb,0x12,0x81,0x27,0x7d,0x73,0x7e,0x1f,0x33,0xea,0x69,0x31, +0x0, 0x1a,0x7a,0x73,0x2b,0x14,0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x33,0xea,0x2e, +0x14,0x0, 0x1a,0x22,0xca,0x3b,0x7e,0x34,0xff,0xff,0x7a,0x35,0x35,0x6d,0x66,0x7a, +0x65,0x37,0x7e,0xb3,0x38,0xf7,0xf5,0x2a,0x7e,0xb3,0x2a,0x6d,0xf5,0x2b,0x7e,0xb3, +0x2a,0x6e,0xf5,0x2c,0x7e,0xb3,0x2a,0x70,0xf5,0x2d,0x7e,0xb3,0x2a,0x6f,0xf5,0x2e, +0x7e,0x34,0x27,0x10,0x7a,0x35,0x2f,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x31,0x12,0x4c, +0xcf,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x87,0x0, +0x6c,0xff,0x80,0x53,0x9f,0x77,0x6d,0x66,0x6c,0xee,0x80,0x38,0x74,0x4, 0xac,0xbe, +0x49,0x15,0x30,0x8c,0x49,0x5, 0x30,0x8a,0xa, 0x4f,0x12,0x4c,0x74,0x60,0x5, 0x2f, +0x11,0x14,0x78,0xfb,0x12,0x4c,0x5d,0x78,0x19,0x7e,0x11,0x2c,0xac,0x1e,0x3e,0x4, +0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x31,0x2d,0x31,0xb, 0x1a,0x30,0x12, +0x4c,0x56,0xb, 0xe0,0xe5,0x2e,0xbc,0xbe,0x38,0xc2,0x12,0x4c,0x7f,0x74,0x2, 0xac, +0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2d,0xbc,0xbf,0x38,0xa7,0x6c,0xff,0x41, +0xe9,0x9f,0x77,0x6d,0x66,0x6c,0xee,0x80,0x23,0x12,0x4c,0x66,0x60,0x5, 0x2f,0x11, +0x14,0x78,0xfb,0x12,0x4c,0x5d,0x78,0x12,0x12,0x4c,0x9f,0x1e,0x34,0x1e,0x24,0x50, +0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x12,0x4c,0x56,0xb, 0xe0,0xe5,0x2a,0xbc,0xbe, +0x38,0xd7,0x12,0x4c,0x7f,0x74,0x4, 0xac,0xbf,0x59,0x35,0x32,0xfa,0xe5,0x2a,0xbe, +0xb1,0x2d,0x50,0x37,0x9f,0x77,0x6d,0x66,0x7e,0xe1,0x2a,0x80,0x23,0x12,0x4c,0x66, +0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x4c,0x5d,0x78,0x12,0x12,0x4c,0x9f,0x1e, +0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x12,0x4c,0x56,0xb, 0xe0, +0xe5,0x2d,0xbc,0xbe,0x38,0xd7,0x12,0x4c,0x7f,0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74, +0x4, 0xac,0xbf,0x59,0x35,0x32,0xfc,0xb, 0xf0,0xe5,0x2e,0xbc,0xbf,0x28,0x2, 0x41, +0x61,0xe5,0x2d,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x1, 0x47,0x12,0x1e,0x1, 0x6c,0xff, +0x80,0x2c,0x7e,0x30,0x2, 0xac,0x3f,0x49,0x21,0x34,0x0, 0xa, 0x5f,0xad,0x53,0x7e, +0xf4,0x10,0x0, 0x9d,0xf5,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, 0x4e, +0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x59,0x21,0x34,0x0, 0xb, 0xf0,0xe5,0x2d, +0xbc,0xbf,0x38,0xce,0xe5,0x2b,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0x7a,0x12,0x1e, +0x1, 0x6c,0xff,0x80,0x59,0x7e,0x90,0x4, 0xac,0x9f,0x49,0x24,0x32,0xfa,0xa, 0x1f, +0xad,0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4, +0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x59,0x24,0x32,0xfa,0xe5, +0x2a,0xbe,0xb1,0x2d,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49,0x25,0x32,0xfc,0x2e,0x14, +0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14, +0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x32,0xfc,0xb, 0xf0,0xe5,0x2b, +0xbc,0xbf,0x38,0xa1,0x7e,0x73,0x38,0xf9,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11, +0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x1d,0xff,0x7d,0xe3,0x7a,0xe5, +0x35,0x7e,0x73,0x38,0xfa,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb, +0x7d,0x1f,0x12,0x1d,0xff,0x7a,0x35,0x37,0x6c,0xff,0x80,0x20,0x74,0x2, 0xac,0xbf, +0x49,0x45,0x34,0x0, 0xbe,0x45,0x35,0x28,0x5, 0x7e,0x35,0x35,0x80,0x8, 0xbe,0x45, +0x37,0x50,0x7, 0x7e,0x35,0x37,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2d,0xbc,0xbf, +0x38,0xda,0x6c,0xff,0x80,0x3e,0x74,0x4, 0xac,0xbf,0x49,0x45,0x32,0xfa,0xbe,0x45, +0x35,0x28,0x9, 0x7e,0x35,0x35,0x59,0x35,0x32,0xfa,0x80,0xc, 0xbe,0x45,0x37,0x50, +0x7, 0x7e,0x45,0x37,0x59,0x45,0x32,0xfa,0x49,0x45,0x32,0xfc,0xbe,0x45,0x35,0x28, +0x5, 0x7e,0x35,0x35,0x80,0x8, 0xbe,0x45,0x37,0x50,0x7, 0x7e,0x35,0x37,0x59,0x35, +0x32,0xfc,0xb, 0xf0,0xe5,0x2b,0xbc,0xbf,0x38,0xbc,0x30,0x2, 0x6, 0x74,0x1, 0x7a, +0xb3,0x2b,0x20,0xda,0x3b,0x22,0x6d,0x22,0x2f,0x71,0xb, 0x64,0x22,0x5d,0x31,0x5d, +0x20,0xbe,0x18,0x0, 0x0, 0x22,0x74,0x4, 0xac,0xbf,0x49,0x15,0x30,0x8c,0x49,0x5, +0x30,0x8a,0xa, 0x4e,0x7e,0x54,0x0, 0x1f,0x9d,0x54,0x7e,0x18,0x0, 0x1, 0x22,0x7f, +0x17,0x7d,0x16,0x12,0x1d,0xff,0x7f,0x71,0x7e,0x25,0x2f,0x74,0xc, 0x7d,0x13,0x7d, +0x32,0x6d,0x22,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x1d,0xff,0x7e, +0x11,0x2c,0xac,0x1f,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d,0x31, +0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24,0xf2,0x74,0x2, 0xac,0xbe,0x49,0x35,0x34, +0x0, 0xad,0x23,0x74,0xc, 0x22,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x39,0x4, 0x22,0x7e, +0x8, 0x2a,0x6d,0x12,0xb, 0xe9,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x12, +0x12,0x2c,0x2, 0x0, 0x4e,0xb4,0x3, 0x5, 0x12,0x4c,0xf5,0x80,0x2, 0xe4,0x22,0x12, +0x4c,0xda,0x74,0x1, 0x22,0x12,0xc5,0x44,0xe4,0x12,0x0, 0xe, 0x7e,0x8, 0x2a,0x6d, +0x2, 0xb, 0xe9,0x12,0x70,0xc0,0x38,0x2, 0xe4,0x22,0x12,0x70,0xb8,0x49,0x55,0x34, +0x3b,0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x52,0x91,0x2, 0x4c,0xe5,0x7e,0xb, 0x70,0x7a, +0x73,0x2b,0xf, 0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62,0x29,0x70,0x0, 0x1, 0x7a, +0x73,0x2b,0x14,0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20,0x12,0x4d,0xec,0x12,0x4f, +0xf6,0xd2,0x0, 0xc2,0x1, 0x2, 0x48,0xe7,0xca,0xf8,0x6c,0xff,0x80,0x34,0x7e,0x73, +0x2f,0xa9,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x4d,0xc4,0xca,0x39, +0x7e,0x30,0x38,0xac,0x3f,0x12,0x4d,0xdd,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x34,0x0, +0x8c,0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12,0x4d,0xd2,0x12,0x1f,0xc9,0x1b,0xfd, +0xb, 0xf0,0x90,0x61,0xc5,0xe4,0x93,0xbc,0xbf,0x38,0xc3,0x7e,0x23,0x2f,0xa9,0x7e, +0x30,0x5, 0xac,0x23,0x12,0x4d,0xc4,0xca,0x39,0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x38, +0xac,0x23,0x12,0x4d,0xdd,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39, +0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x8c,0xac,0x23,0x12,0x4d,0xd2,0x12,0x1f,0xc9,0x1b, +0xfd,0xda,0xf8,0x22,0x2e,0x14,0x26,0x33,0x6d,0x0, 0x12,0x4d,0x1c,0x7e,0x34,0x0, +0x38,0x22,0x2e,0x14,0x30,0xca,0x6d,0x0, 0x7e,0x18,0x32,0xfa,0x22,0x2e,0x14,0x2f, +0xaa,0x6d,0x0, 0x7e,0x18,0x34,0x0, 0x22,0x7a,0xb3,0x2b,0xf, 0x12,0x4e,0x2d,0x7a, +0x37,0x2b,0x1b,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac,0xbf,0x12,0xc5,0x68,0x12, +0xa7,0xaf,0x12,0x4f,0xfd,0x12,0xa7,0xa6,0x7a,0xf3,0x2f,0xa9,0x7c,0xbf,0x12,0xa7, +0xc1,0x12,0x4d,0xec,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x26,0x37,0x12,0xa8,0xb6,0x12, +0x4f,0x48,0x12,0x22,0x8f,0xe4,0x7a,0xb3,0x16,0x91,0xda,0xf8,0x22,0x7e,0x23,0x2b, +0xf, 0x7e,0x33,0x39,0x13,0x12,0xc5,0x4d,0xb, 0x1a,0x0, 0xac,0x23,0x2d,0x10,0xbe, +0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x2b,0x10,0xbe,0x14,0xf, +0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x21, +0xbe,0x14,0x3, 0x84,0x40,0x16,0x90,0x61,0x1b,0xe4,0x93,0x7c,0x7b,0xbe,0x70,0x1, +0x28,0x4, 0x74,0x1, 0x80,0xb, 0x7a,0x73,0x2b,0x10,0x80,0x9, 0x90,0x61,0x1b,0xe4, +0x93,0x7a,0xb3,0x2b,0x10,0x7e,0x73,0x2b,0x10,0xbc,0x76,0x68,0x2, 0xd2,0x10,0x7e, +0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10, +0x7, 0x7e,0x1f,0x33,0xe2,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x3e,0x4, 0x3e, +0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x7e, +0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x1e,0x52,0x7e,0xa3,0x2f,0xa9,0xbe,0xa0, +0xff,0x68,0x4b,0xbe,0xa3,0x33,0x86,0x68,0x45,0x74,0x5, 0xa4,0x12,0xc5,0x68,0x12, +0x4f,0x1f,0xa4,0x12,0xa7,0xaf,0x12,0x4f,0x1f,0xa4,0x12,0xa7,0xa6,0x12,0x67,0x1f, +0x50,0x9, 0x7e,0xb3,0x2f,0xa9,0x12,0xa7,0xc1,0x80,0x7, 0x12,0x4f,0x1f,0xa4,0x12, +0x4f,0xfd,0x12,0x4d,0xec,0x12,0x4f,0xf6,0x7e,0x73,0x2b,0x14,0xa, 0x37,0x7e,0xf, +0x33,0xea,0x79,0x30,0x0, 0x1a,0x7e,0x73,0x2f,0xa9,0x7a,0x73,0x33,0x86,0x22,0x7e, +0xa3,0x2f,0xa9,0x74,0x5, 0x22,0x12,0x4d,0xe8,0x30,0x10,0xc, 0xc2,0x10,0x12,0xa8, +0xd1,0x30,0x0, 0x4, 0xe4,0x12,0x7, 0x45,0x30,0x0, 0x9, 0x12,0xa8,0x7a,0x12,0x4f, +0x48,0x2, 0xa2,0x88,0x22,0x12,0xa8,0xac,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c,0xeb, +0x6c,0xff,0x12,0xc5,0x4d,0xb, 0x1a,0xc0,0x7e,0x73,0x39,0x13,0xa, 0xb7,0x7e,0xb3, +0x2b,0x10,0xf5,0x36,0x12,0xa6,0x8b,0xbe,0xd0,0x4, 0x38,0x5, 0xe4,0x7a,0xb3,0x37, +0xf8,0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d,0xac,0x75,0x35,0x0, 0x7e,0xa3,0x37,0xf8, +0xbc,0xad,0x40,0x2, 0x80,0x19,0xbe,0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4,0x9, 0x75, +0x26,0x33,0xbc,0x7e,0x78,0xe, 0x7c,0xbd,0x14,0xbe,0xb3,0x37,0xf8,0x78,0x5, 0xe4, +0x7a,0xb3,0x37,0xf8,0x7e,0xc3,0x37,0xf8,0x80,0x41,0x7e,0xb3,0x37,0xf8,0x4, 0x7a, +0xb3,0x37,0xf8,0x7e,0x90,0x5, 0xac,0x9c,0x9, 0xa4,0x26,0x33,0xbc,0xae,0x68,0x29, +0xe5,0x35,0xa, 0xdb,0x19,0xcd,0x37,0xfc,0xa, 0x9a,0xad,0x9b,0x2d,0x9c,0x7e,0xa1, +0x35,0x7c,0xba,0x4, 0xf5,0x35,0x7c,0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31,0x36,0x12, +0xe, 0xc7,0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x6, 0xb, 0xc0,0xbc,0xdc,0x38,0xbb,0x7a, +0xf3,0x37,0xf9,0xda,0x3b,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0x2, 0x64,0x9, 0x75,0x26, +0x35,0x7a,0x73,0x2b,0x1f,0x22,0xe5,0xd, 0x60,0x56,0xe5,0xd, 0x30,0xe0,0xa, 0x53, +0xd, 0xfe,0x7e,0x8, 0x2a,0x6d,0x12,0x4, 0x8d,0xe5,0xd, 0x30,0xe1,0x14,0x53,0xd, +0xfd,0x7e,0xb3,0x39,0x26,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12,0x53,0x98,0x12, +0x6c,0x17,0xe5,0xd, 0x30,0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a,0xb3,0x39,0x27,0x7e, +0xb3,0x39,0x26,0x70,0xa, 0x74,0x1, 0x12,0x0, 0x1e,0x12,0x3f,0x70,0x80,0x7, 0xe4, +0x12,0x0, 0x1e,0x12,0x3f,0x52,0x12,0x3b,0x1c,0x7e,0xb3,0x2a,0xfc,0x2, 0x50,0x61, +0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x24,0xf2,0x12,0x3f,0xf4,0x7e,0xa3,0x2a,0x73, +0x7e,0x73,0x2a,0x74,0x6c,0xee,0x80,0x1d,0xa, 0x2e,0x9, 0x62,0x2a,0xdc,0xa, 0x26, +0x12,0x69,0x8a,0x7c,0x6b,0xbe,0x60,0x1c,0x50,0x9, 0xa, 0x2e,0x12,0x50,0xd9,0x19, +0xb2,0x24,0xf2,0xb, 0xe0,0xbc,0x7e,0x38,0xdf,0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, +0x62,0x2a,0xb9,0xbe,0x60,0x23,0x50,0xd, 0xa, 0x1e,0xa, 0x27,0x2d,0x21,0x12,0x50, +0xd9,0x19,0xb2,0x25,0xe, 0xb, 0xe0,0xbc,0xae,0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, +0xac,0x3e,0x2e,0x14,0x24,0xf2,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x10,0x82,0xb, +0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x2e,0x27,0x2a,0xfe,0x7e,0x29,0xb0, +0xa, 0x26,0x22,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a,0xfa,0x74,0x1, 0x7a, +0xb3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x4, 0x8d,0x6d,0x33,0x12,0x3f,0xd7,0x12, +0x29,0x35,0x7e,0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x1f,0xee,0x7e,0xd0,0x7, 0x12,0x26, +0x28,0x6c,0xcc,0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14, +0x78,0xfb,0x7c,0x67,0x12,0x51,0xa4,0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x51, +0xae,0xa, 0x3c,0xbd,0x32,0x48,0xde,0x12,0x52,0x3f,0x30,0x1c,0xfd,0x12,0x53,0xa0, +0x7e,0xb3,0x2a,0x73,0x7c,0x7e,0x12,0x53,0x2f,0x6c,0xcc,0x80,0x29,0x74,0x2, 0xac, +0xbc,0x49,0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e,0x34,0x0, 0x1, 0x7c, +0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff,0x12,0x51,0xa4,0x5c, +0x7b,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x51,0xae,0xa, 0x3c,0xbd,0x32,0x48,0xce,0x1b, +0xd0,0xbe,0xd0,0x0, 0x58,0x88,0x12,0x51,0xbd,0x74,0x2, 0x12,0x53,0x98,0x12,0x50, +0x61,0x74,0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x4, +0x8d,0xda,0x3b,0x22,0xa, 0x2c,0x2e,0x27,0x2a,0xfe,0x7e,0x29,0x70,0x22,0x7e,0x73, +0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73,0xa, 0x25,0x2d,0x23,0x22,0xca,0xd8,0xca, +0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a,0xb3,0x2a,0xfa,0x12,0x29,0x35,0x7c,0xe7,0x80, +0x61,0x12,0x26,0x28,0x12,0x52,0x3f,0x30,0x1c,0xfd,0x12,0x53,0xa0,0x12,0x53,0x27, +0x6c,0xdd,0x80,0x41,0x7e,0x50,0x2, 0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14, +0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17,0x2a,0xfe,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28, +0x22,0x14,0x7a,0x19,0xb0,0x80,0x1c,0xbe,0x34,0x19,0x28,0x28,0x14,0xa, 0x3d,0x2e, +0x37,0x2a,0xfe,0x7e,0x39,0xb0,0xbe,0xb0,0xff,0x68,0x8, 0x4, 0x7a,0x39,0xb0,0x80, +0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x51,0xae,0xa, 0x3d,0xbd,0x32,0x48,0xb6,0x4c,0xee, +0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x97,0xda,0x79,0xda,0xd8,0x22,0x74, +0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x50,0x61,0x74,0x2, 0x12,0x0, 0x1e, +0x74,0x5, 0x7e,0x70,0x9b,0x12,0x12,0x2c,0x12,0x52,0x62,0x7e,0xb3,0x2a,0xfc,0x2, +0xd, 0x6b,0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x2a,0xdc,0x2e,0x34,0x1f,0x83, +0x12,0x57,0xf0,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0xf, 0x33,0xe2, +0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x2a,0x74,0xbc,0x6a,0x38,0xd6, +0x22,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0,0x1, 0x28,0x2, 0xe4,0x22,0x12,0x70,0x49,0x7e, +0x8, 0x2a,0x6d,0x12,0x4, 0x8d,0x7a,0xd7,0x2b,0xd, 0x7e,0x73,0x2a,0xfa,0x12,0x45, +0x85,0xe4,0x7e,0x50,0x1, 0x12,0x12,0x1, 0x12,0x52,0x50,0x74,0x1, 0x22,0xca,0xd8, +0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40,0x7f,0x15,0x12,0x66,0x42,0x12,0x3f,0xdd, +0x7e,0xe0,0x1, 0x12,0x52,0x50,0x30,0x1c,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, +0x12,0x53,0x27,0x6c,0xdd,0x80,0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, +0x1a,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x5, 0x2d,0x15,0x12,0xc5,0x71,0xb, 0xd0,0x7e, +0x73,0x2a,0x74,0xa, 0x7, 0x7e,0x63,0x2a,0x73,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd, +0x21,0x48,0xd4,0x1b,0xe0,0x78,0xbc,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12, +0xb9,0xba,0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12, +0xf, 0xb5,0x74,0x2, 0x2, 0x0, 0x1e,0x7e,0xb3,0x2b,0x2, 0x70,0x41,0x12,0x57,0x2e, +0x50,0xfb,0xe4,0x6c,0x77,0x6c,0x66,0x12,0x53,0x7f,0x7e,0x8, 0x6, 0xfc,0x7e,0x1f, +0x6, 0xf4,0x7e,0xb3,0x2b,0x72,0x12,0x52,0xbe,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60, +0x1, 0x12,0x53,0x7f,0x7e,0x8, 0x7, 0x7a,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x25,0xf0, +0x12,0x52,0xbe,0x74,0x2, 0x7a,0xb3,0x2b,0x2, 0xe4,0x7a,0xb3,0x16,0x90,0x22,0x7c, +0x96,0x7c,0xa7,0x12,0x3d,0xb3,0x7c,0xba,0x12,0x12,0xc7,0x74,0xa, 0x12,0x45,0x94, +0x7c,0xb9,0x12,0x0, 0x1e,0x2, 0x50,0xe3,0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x22, +0x74,0x2, 0x12,0x0, 0x1e,0x7e,0x8, 0x6, 0xfc,0x22,0x7e,0x34,0xd, 0xac,0x12,0x26, +0x2c,0x12,0x53,0x37,0x12,0x57,0x39,0x2, 0x53,0xba,0x30,0x13,0x13,0x12,0x67,0x1f, +0x50,0x3, 0x12,0x4d,0x48,0x12,0x57,0xe1,0x12,0x64,0xc2,0x12,0x57,0x62,0xc2,0x13, +0x22,0x12,0xc5,0x5, 0x12,0xc1,0x9a,0x7a,0x37,0x3a,0x34,0x12,0x53,0xaa,0x12,0x28, +0xa, 0x2, 0x53,0xe4,0x12,0x55,0x45,0x50,0x4, 0x74,0x19,0x80,0x2, 0x74,0xa, 0x7a, +0xb3,0x36,0x8e,0xe4,0x7a,0xb3,0x36,0x8f,0x22,0xca,0x79,0x7e,0x13,0x2a,0x2, 0x7e, +0x78,0x29,0xbc,0x12,0x55,0x45,0xe4,0x33,0x7c,0xb, 0x4c,0x0, 0x68,0x8, 0x7e,0x30, +0x19,0x7e,0xa0,0x5, 0x80,0x6, 0x7e,0x30,0xa, 0x7e,0xa0,0x1, 0xa5,0xb9,0x0, 0x5, +0x12,0x53,0xe4,0xa1,0x2e,0xbc,0x20,0x50,0x3, 0x12,0x53,0xe4,0x6c,0x0, 0xa1,0x23, +0x7e,0x70,0x9, 0xac,0x70,0x9, 0x93,0x29,0xc, 0xbe,0x90,0xff,0x78,0x2, 0xa1,0x21, +0xa, 0x29,0x7f,0x67,0x2d,0xd2,0x7e,0x6b,0x80,0xbe,0x80,0x2, 0x68,0x2, 0xa1,0x4, +0x12,0x55,0x3b,0x49,0x33,0x29,0x8, 0x9d,0x32,0x12,0x20,0x30,0x7d,0xd3,0x7e,0x70, +0x4, 0xac,0x79,0x49,0x23,0x37,0x46,0x12,0x55,0x31,0x9d,0x32,0x12,0x20,0x30,0x7d, +0xc3,0x7e,0x73,0x36,0x8e,0xa, 0x27,0xbd,0x2d,0x28,0x53,0xbd,0x2c,0x28,0x4f,0x12, +0x55,0x3b,0x7e,0xf0,0x9, 0xac,0xf0,0x59,0x27,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x59, +0x49,0x22,0x37,0x46,0x7e,0xf0,0x9, 0xac,0xf0,0x59,0x27,0x29,0xa, 0xbe,0x10,0x0, +0x28,0x2, 0x1b,0x10,0xa5,0xb9,0x0, 0x79,0x7e,0xb3,0x36,0x8f,0x4, 0x7a,0xb3,0x36, +0x8f,0x7e,0x63,0x36,0x8f,0xbe,0x60,0x32,0x40,0x67,0xe4,0x7a,0xb3,0x36,0x8f,0x7e, +0xb3,0x36,0x8e,0xbc,0xb3,0x50,0x5a,0x4, 0x7a,0xb3,0x36,0x8e,0x80,0x53,0x7e,0x50, +0x9, 0xac,0x50,0x49,0xb2,0x29,0x8, 0x7e,0xf0,0x4, 0xac,0xf9,0x59,0xb7,0x37,0x44, +0x49,0x22,0x29,0xa, 0x59,0x27,0x37,0x46,0xbc,0x73,0x28,0x6, 0x7a,0xa3,0x36,0x8e, +0x80,0xb, 0xbc,0x7a,0x28,0x7, 0x7c,0xb7,0x14,0x7a,0xb3,0x36,0x8e,0xe4,0x7a,0xb3, +0x36,0x8f,0x80,0x1d,0x4c,0x88,0x78,0x19,0x7e,0x70,0x9, 0xac,0x70,0x49,0x33,0x29, +0x8, 0x7e,0x50,0x4, 0xac,0x59,0x59,0x32,0x37,0x44,0x12,0x55,0x31,0x59,0x32,0x37, +0x46,0xb, 0x0, 0x90,0x60,0x99,0xe4,0x93,0xbc,0xb0,0x28,0x2, 0x81,0x30,0xda,0x79, +0x22,0x7e,0x70,0x9, 0xac,0x70,0x49,0x33,0x29,0xa, 0x22,0x7e,0x50,0x4, 0xac,0x59, +0x49,0x22,0x37,0x44,0x22,0xa2,0xa, 0x22,0x12,0x53,0xf9,0x2, 0x55,0x4e,0x7e,0xb3, +0x2a,0x9, 0x70,0x24,0x7e,0xa3,0x36,0xa6,0x4c,0xaa,0x78,0x3, 0xe4,0x80,0x7, 0xbe, +0xa0,0x2, 0x78,0x6, 0x74,0x3, 0x7a,0xb3,0x36,0xb1,0x7e,0x73,0x36,0xb2,0xbe,0x73, +0x36,0xb1,0x28,0x4, 0x7a,0x73,0x36,0xb1,0x22,0x12,0x53,0xd1,0x12,0x68,0x4b,0x7e, +0xb3,0x3, 0xc5,0xb4,0x1, 0x65,0x12,0xb7,0x17,0x7e,0x34,0x60,0xa5,0x12,0x23,0x29, +0x12,0x26,0x2c,0x12,0x87,0xbb,0x12,0x44,0x3b,0x12,0x28,0x24,0x50,0xde,0x12,0x83, +0xef,0x7e,0xb3,0x3, 0xc2,0xb4,0x1, 0x4, 0xe4,0x12,0x55,0xfd,0x12,0x57,0x2, 0x12, +0x56,0x5, 0x40,0xc8,0x12,0x67,0x30,0x12,0x56,0x5, 0x40,0xc0,0x12,0x6a,0xec,0x12, +0x29,0xc4,0x12,0x7, 0xfd,0x12,0xaa,0xa0,0x12,0x56,0x21,0x12,0x56,0x75,0x12,0x5c, +0xc4,0x12,0x92,0x29,0x12,0x74,0x7b,0x12,0x55,0x48,0x12,0xbe,0xf5,0x12,0x6d,0x89, +0x12,0x58,0xe7,0x12,0x26,0x37,0x12,0x58,0x83,0x80,0x91,0x12,0x57,0x28,0x2, 0x55, +0xf1,0x7e,0xb3,0x3, 0xc2,0xb4,0x1, 0x4, 0xe4,0x2, 0x55,0xfd,0x22,0x70,0x3, 0xd2, +0x86,0x22,0xc2,0x86,0x22,0xc2,0x0, 0x7e,0xb3,0x16,0x91,0x60,0x6, 0x7e,0xb3,0x16, +0x90,0x70,0xb, 0x7e,0x73,0x28,0x84,0xbe,0x70,0x1, 0x28,0x2, 0xd2,0x0, 0xa2,0x0, +0x22,0x2, 0x56,0x24,0xca,0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c,0xee,0x80,0x35, +0x7c,0xbe,0x12,0x37,0xdc,0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0xb1,0x84,0x60,0x23, +0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x27,0x76,0x6d, +0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12,0x1f,0xc9,0x1b, +0xfd,0xb, 0xf0,0xb, 0xe0,0x12,0x8f,0x80,0x38,0xc6,0x7a,0x73,0x28,0x93,0x7a,0xf3, +0x2a,0x2, 0xda,0x79,0x22,0x12,0x97,0x4c,0x2, 0x56,0x7b,0x7e,0xa3,0x2a,0x3, 0xbe, +0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, 0xbe,0xb3, +0x37,0x43,0x28,0x14,0x7e,0xb3,0x37,0x43,0x4, 0x7a,0xb3,0x37,0x43,0x7a,0xa3,0x2a, +0x2, 0x80,0x5, 0xe4,0x7a,0xb3,0x37,0x43,0x7e,0xb3,0x2a,0x2, 0x70,0x5, 0xe4,0x7a, +0xb3,0x2a,0xb, 0x22,0x12,0x57,0x19,0x2, 0x56,0xba,0xe4,0x7a,0xb3,0x28,0x93,0x12, +0xb3,0x34,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, 0x7e,0x73,0x28,0x84,0x7a,0x73,0x28, +0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8,0x12,0x5f,0xb8,0x12,0xb1,0xa8,0x12, +0x84,0x36,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18,0x7e,0x73,0x26,0x83,0x7a,0x73,0x26, +0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26,0xf5,0x7e,0x73,0x26,0x84,0x7a,0x73,0x26, +0xf4,0x22,0x12,0x56,0xb4,0x12,0x0, 0x66,0x12,0x2f,0xf7,0x40,0xb, 0x12,0x23,0x9f, +0xe4,0x7a,0xb3,0x3, 0xfd,0x2, 0x56,0xba,0x22,0x12,0x25,0x57,0x2, 0x57,0x1f,0x12, +0x2f,0xf7,0x50,0x3, 0x2, 0x25,0x7f,0x22,0x12,0x57,0x2e,0x50,0xfb,0x22,0x7e,0xb3, +0x34,0x3a,0xb4,0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x7e,0xb3,0x2b,0x1e,0x70,0x22,0x12, +0x26,0x28,0x12,0x57,0x2e,0x50,0xfb,0x12,0x57,0xe1,0x12,0x64,0xc2,0x12,0x67,0x10, +0x20,0x13,0x3, 0x12,0x57,0x62,0x74,0x2, 0x7a,0xb3,0x2b,0x1e,0xe4,0x7a,0xb3,0x16, +0x91,0x22,0xca,0x3b,0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e,0xf3,0x2b,0x62, +0x12,0xa4,0xe3,0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12,0xa7,0xb8,0xf5, +0x2a,0x7e,0x73,0x2b,0xf, 0xbe,0x71,0x2a,0x68,0x36,0x7e,0x70,0x4, 0xac,0x7d,0xa, +0x2c,0x12,0x57,0xea,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, +0xe0,0xad,0x10,0x2e,0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2b,0x7e,0x70,0x1d,0xac, +0x7e,0x2e,0x34,0x33,0x8b,0x6d,0x22,0x7a,0x1f,0x33,0x87,0x7c,0xbc,0x12,0xa6,0xaf, +0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f,0x68,0x6, 0x7a, +0xf3,0x2b,0x62,0xd2,0x10,0xd2,0x0, 0x7e,0xb3,0x1f,0x33,0x12,0x4f,0x26,0xda,0x3b, +0x22,0x7e,0xf, 0x13,0x8a,0x7e,0x18,0x8, 0xa, 0x22,0x2d,0x32,0x2e,0x34,0x20,0x20, +0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0xca,0xd8,0xca,0x79,0x7e,0x73,0x2a, +0x6e,0x7e,0xf3,0x2a,0x6d,0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f,0x34,0xe4, +0x12,0x1f,0xee,0x7e,0xb3,0x38,0xfd,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xfe,0xbe,0x70, +0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12,0x26,0x28,0x12,0x28,0x24,0x6d,0x33,0x80, +0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33,0xd, 0xc8,0x12,0x20,0x30,0x7a,0x35,0x26, +0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26,0x58,0x7, +0x7e,0x25,0x26,0x59,0x21,0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75,0x24,0x38, +0xd0,0xb, 0xd0,0x7e,0x73,0x38,0xfe,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34,0xca, +0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0xd, 0xc8,0x12,0x1f,0xc9,0x1b,0xfd,0xda,0x79, +0xda,0xd8,0x22,0x7e,0x8, 0x39,0x39,0x12,0x58,0xb7,0x7e,0x8, 0x39,0x41,0x12,0x58, +0xb7,0x12,0x58,0xcc,0x12,0x58,0xd3,0x2, 0x58,0x9a,0x7e,0x37,0x39,0x39,0xbe,0x34, +0x0, 0x0, 0x28,0x12,0x7e,0x73,0x3a,0x37,0xbe,0x70,0x5, 0x50,0x9, 0x7e,0xb3,0x3, +0xee,0x70,0x3, 0x12,0x58,0xda,0x22,0xb, 0xa, 0x30,0xe5,0x65,0xa, 0x2b,0xbd,0x32, +0x28,0x4, 0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x8, 0x2b,0xb7, +0x2, 0x58,0xb7,0x7e,0x8, 0x3a,0x20,0x2, 0x58,0xb7,0x6d,0x33,0x7a,0x37,0x39,0xc9, +0x74,0x1, 0x7a,0xb3,0x3, 0xc3,0x22,0x7e,0x73,0x28,0x93,0x7a,0x73,0x28,0x94,0x7e, +0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, 0xe4,0x7a,0xb3,0x2a,0x6, 0x22,0x7e,0x37,0x3a, +0x6, 0xb, 0x34,0x7a,0x37,0x3a,0x6, 0x7e,0x37,0x3a,0x8, 0xbe,0x37,0x3a,0x6, 0x28, +0x3, 0x2, 0x59,0x18,0x22,0x2, 0x58,0xfd,0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6, +0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x59,0x15,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x74,0x1, +0x22,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e, +0x8, 0x2b,0x70,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x34,0x2a,0xe, 0x7a,0x37,0x2b,0x76, +0xe4,0x7a,0xb3,0x2b,0x74,0x7a,0xb3,0x2b,0x75,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12, +0x5f,0xac,0x7e,0x8, 0x25,0xee,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x34,0x2b,0x78,0x7a, +0x37,0x25,0xf4,0xe4,0x7a,0xb3,0x25,0xf2,0x74,0x1, 0x7a,0xb3,0x25,0xf3,0x22,0xca, +0x79,0x90,0x60,0x50,0xe4,0x93,0x7c,0xab,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e, +0xb3,0x2a,0x74,0xbc,0xbe,0x28,0x4, 0x7c,0xfb,0x80,0x2, 0x7c,0xfe,0x7a,0xa3,0x2a, +0x6d,0x7a,0xe3,0x2a,0x6e,0x7a,0xa3,0x2a,0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xa3,0x2a, +0x73,0x7a,0xe3,0x2a,0x74,0x90,0x60,0xa8,0xe4,0x93,0x7c,0x7b,0x7a,0x73,0x2a,0x77, +0x90,0x60,0xa9,0xe4,0x93,0xa, 0x1b,0xa, 0x2a,0x9d,0x21,0x7c,0x65,0x7a,0x63,0x2a, +0x6f,0xa, 0x27,0xa, 0x3e,0x9d,0x32,0x7c,0xb7,0x7a,0xb3,0x2a,0x70,0x90,0x60,0x91, +0xe4,0x93,0x7a,0xb3,0x2a,0x78,0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x2a,0x79,0xa, +0x3a,0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x7a,0x12, +0x1f,0xc9,0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff, +0x7e,0x8, 0x2a,0x9d,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e, +0x34,0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x21,0x12,0x1f,0xc9,0x1b,0xfd, +0x12,0x5b,0x75,0x12,0x64,0x56,0x12,0x59,0x51,0x74,0x1, 0x12,0x3d,0xb3,0xe4,0x7a, +0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x2, 0x12,0x63,0xcd,0x7a,0x37,0x2b,0xd, 0x74,0x3, +0x7a,0xb3,0x2b,0x3, 0xe4,0x7a,0xb3,0x2b,0x4, 0x74,0x2, 0x7a,0xb3,0x2b,0x5, 0x7e, +0x34,0x61,0x59,0x12,0x23,0x29,0x7a,0x37,0x2b,0x7, 0x74,0x4, 0x7a,0xb3,0x2b,0x6, +0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x2b,0x9, 0x7e,0x34,0x20,0x5f,0x7a,0x37,0x2b,0xb, +0x90,0x61,0x1a,0xe4,0x93,0x7a,0xb3,0x2b,0x62,0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3, +0x2b,0x10,0x90,0x61,0x1c,0xe4,0x93,0x7a,0xb3,0x2b,0x11,0x74,0x4, 0x7a,0xb3,0x2b, +0x13,0x90,0x60,0xd5,0xe4,0x93,0x12,0x4d,0xe8,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3, +0x2b,0x1e,0x7e,0x34,0x61,0x22,0x12,0x23,0x29,0x7a,0x37,0x2b,0x19,0x90,0x60,0xd3, +0x93,0x7a,0xb3,0x2b,0x12,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x2b,0x20,0x90,0x61, +0x19,0xe4,0x93,0x7a,0xb3,0x2b,0x1f,0x7e,0x34,0x61,0x1e,0x12,0x23,0x29,0x7a,0x37, +0x2b,0x15,0x7e,0x34,0x61,0x20,0x12,0x23,0x29,0x7a,0x37,0x2b,0x17,0x90,0x61,0x1d, +0xe4,0x93,0x7a,0xb3,0x2b,0x14,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a,0x74,0x4, +0x7a,0xb3,0x2b,0x67,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b, +0x66,0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74, +0x5, 0x7a,0xb3,0x2b,0x64,0xe4,0x7a,0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60, +0xe4,0x7a,0xb3,0x2b,0x61,0x7e,0x34,0x1f,0x6b,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca, +0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x1f,0xc9, +0x1b,0xfd,0xda,0x79,0x22,0x12,0x5f,0xc1,0x12,0x5b,0xd9,0x90,0x60,0x50,0xe4,0x93, +0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2a,0x7a,0x6d,0x0, 0x9, 0xb3,0x2a,0x79,0x12,0x5b, +0xc2,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2b,0x21,0x6d,0x0, 0x9, 0xb3,0x2b,0x20,0x12, +0x5b,0xc2,0xa, 0x1b,0x2e,0x14,0x2a,0x7c,0x12,0x5b,0xcf,0x1b,0x35,0xe5,0x25,0x12, +0x5b,0xc6,0xa, 0x1b,0x2e,0x14,0x2b,0x23,0x12,0x5b,0xcf,0x1b,0x35,0xe5,0x24,0x2, +0x1f,0xee,0x7e,0x34,0x0, 0x2, 0x12,0x1f,0xee,0x90,0x60,0x50,0xe4,0x93,0x22,0x6d, +0x0, 0x90,0x60,0x91,0xe4,0x93,0xa, 0x3b,0x22,0x6c,0xaa,0x6c,0x99,0x80,0xc, 0xa, +0xf9,0x9, 0xbf,0x2a,0x7a,0xbc,0xba,0x68,0x7, 0xb, 0x90,0x12,0x5c,0x5, 0x38,0xef, +0x12,0x5c,0x5, 0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, 0xa0,0x74, +0x6e,0x7a,0x1b,0xb0,0x22,0x90,0x60,0x50,0xe4,0x93,0xbc,0xb9,0x22,0x12,0x62,0xa5, +0x12,0x59,0x9f,0x12,0x0, 0x42,0x12,0x5f,0xb8,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, +0xf8,0x7e,0xf, 0x6, 0xf8,0x7e,0x1f,0x6, 0xf4,0x12,0x66,0x42,0x7e,0x18,0x8, 0xa, +0x7a,0x1f,0x13,0x86,0x7e,0x18,0xd, 0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, 0x13,0x8a, +0x7e,0x1f,0x13,0x86,0x12,0x64,0x9f,0x12,0x5f,0xb5,0x12,0x24,0xd0,0x12,0x64,0x18, +0x12,0x5c,0x64,0x2, 0x5c,0x56,0xe4,0x7a,0xb3,0x34,0x38,0x7a,0xb3,0x34,0x39,0x7a, +0xb3,0x34,0x3a,0x22,0x12,0x5f,0xe0,0x7e,0x24,0x0, 0x3, 0xad,0x32,0x7e,0x8, 0x28, +0xae,0x74,0xff,0x12,0x1f,0xee,0x12,0x5f,0xd4,0x7e,0x8, 0x29,0xbc,0x12,0x5c,0x8c, +0x7e,0x8, 0x2a,0x2, 0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x1f,0xee,0x6c,0xaa,0x80,0x20, +0x74,0x3, 0x12,0x5f,0xca,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, 0x12,0x5c,0xba, +0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, 0x28,0xb, 0xa0, +0x90,0x60,0x99,0xe4,0x93,0xbc,0xba,0x38,0xd7,0x22,0x7e,0x44,0x7f,0xff,0x7e,0x70, +0x2, 0xac,0x7a,0x22,0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x80,0x19,0x7e,0x70, +0xff,0x12,0x5f,0x8b,0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19,0xb4,0x1f, +0x46,0x19,0xb4,0x1f,0x50,0xb, 0xa0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba,0x38,0xde, +0x7e,0x73,0x2a,0x2, 0xa5,0xbf,0x0, 0x27,0x7e,0xb3,0x33,0xff,0x70,0x2, 0xc1,0xf3, +0x6c,0xaa,0x80,0x10,0x7e,0x44,0x7f,0xff,0x12,0x5f,0x95,0x79,0x40,0x0, 0x14,0x12, +0x5f,0x82,0xb, 0xa0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba,0x38,0xe7,0xc1,0xf3,0x7e, +0xb3,0x33,0xff,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38,0x6c,0xaa,0x80,0x2a,0x7e,0x90, +0x9, 0xac,0x9a,0x49,0x34,0x28,0xae,0x12,0x5f,0x95,0x79,0x30,0x0, 0x14,0x49,0x34, +0x28,0xb0,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74,0x1, 0xa, 0x3a,0x19,0xb3, +0x1f,0x34,0x19,0xa4,0x28,0xb2,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc,0xba,0x38,0xce, +0xc1,0xf3,0x6c,0xaa,0x80,0x17,0x12,0x5c,0xba,0x3e,0x34,0x59,0x43,0x15,0x4e,0x59, +0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15,0x78,0xb, 0xa0,0x90,0x60,0x99, +0xe4,0x93,0xbc,0xba,0x38,0xe0,0x6c,0xaa,0x80,0x41,0x6c,0xff,0x80,0x32,0x7e,0x70, +0x2, 0xac,0x7f,0x7f,0x6, 0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f,0xff,0x68, +0x1d,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x14,0x12,0x5f,0x7a,0x59,0x32,0x15, +0x4e,0x69,0x30,0x0, 0x28,0x59,0x32,0x15,0x50,0x12,0x5f,0x9f,0x80,0xb, 0xb, 0xf0, +0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x38,0xc5,0xb, 0xa0,0x7e,0xb3,0x33,0xff,0xbc, +0xba,0x38,0xb7,0x6c,0xaa,0x80,0x28,0xa, 0x3a,0x9, 0xb3,0x1f,0x46,0xb4,0xff,0x1d, +0x6c,0xff,0x80,0x10,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, 0x12,0x5f,0x9f, +0x80,0xb, 0xb, 0xf0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x38,0xe7,0xb, 0xa0,0x90, +0x60,0x99,0xe4,0x93,0xbc,0xba,0x38,0xcf,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x9, 0xac, +0x7a,0x49,0x43,0x28,0xae,0x12,0x5f,0x7a,0x59,0x42,0x15,0x76,0x49,0x33,0x28,0xb0, +0x59,0x32,0x15,0x78,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc,0xba,0x38,0xde,0x7e,0x34, +0x15,0x4e,0x7a,0x37,0x1f,0x40,0x7e,0x34,0x15,0x76,0x7a,0x37,0x1f,0x42,0x7e,0x34, +0x15,0x9e,0x7a,0x37,0x1f,0x44,0x7e,0x73,0x33,0xff,0x7a,0x73,0x1f,0x3e,0x7e,0x73, +0x2a,0x2, 0x7a,0x73,0x1f,0x3f,0x7e,0x8, 0x1f,0x3e,0x12,0x3, 0x86,0x6c,0xaa,0x80, +0x5d,0x7e,0x70,0xff,0x6c,0xff,0x80,0x19,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12,0x15, +0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, 0x73,0x1f,0x46,0x80,0xb, 0xb, +0xf0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x38,0xde,0xbe,0x70,0xff,0x68,0x2d,0x12, +0x5f,0x8b,0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34,0x7e,0x90,0x9, 0xac,0x9a,0x49, +0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20,0x0, 0x14, +0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12,0x5f,0x82,0xb, 0xa0,0x7e,0x63, +0x2a,0x2, 0xbc,0x6a,0x38,0x9b,0x6c,0xaa,0x80,0x20,0xa, 0x3a,0x9, 0xb3,0x1f,0x34, +0xbe,0xb0,0x1, 0x68,0x13,0x12,0x5c,0xba,0x7f,0x6, 0x2d,0x13,0x79,0x40,0x0, 0x14, +0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x90,0x60,0x99,0xe4,0x93,0xbc, +0xba,0x38,0xd7,0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x33,0xff,0x6c,0xaa,0x80,0x68,0xa, +0x3a,0x9, 0xb3,0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x5f,0x73,0x29,0xb1,0x0, 0xa, 0xb4, +0x1, 0x6, 0x74,0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x5f,0x73,0x29,0x31,0x0, 0xa, 0xa5, +0xbb,0x3, 0x6, 0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a, +0x1b,0xb0,0x80,0x27,0x12,0x5f,0x73,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, +0x70,0x14,0x74,0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23, +0x19,0xa1,0x28,0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x5f,0x73,0x7e,0x1b, +0xb0,0x39,0xb1,0x0, 0xa, 0xb, 0xa0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba,0x38,0x8f, +0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e, +0x24,0x22,0x7f,0x6, 0x2d,0x12,0x79,0x40,0x0, 0x28,0x22,0x7e,0x50,0x9, 0xac,0x5a, +0x19,0x72,0x28,0xb2,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0xa, +0x3a,0x19,0xf3,0x1f,0x46,0x74,0x1, 0x19,0xb4,0x1f,0x50,0x22,0x7e,0x34,0x61,0x29, +0x7e,0x24,0x0, 0xff,0x22,0x2, 0x23,0x31,0x7e,0x18,0x5, 0xf8,0x7a,0x1f,0x6, 0xf4, +0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18,0x0, 0x24,0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34, +0x7a,0x1b,0xb0,0x22,0x7e,0x8, 0x36,0xa6,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x1f,0xee, +0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x9, 0xac,0x7b,0x22,0x7e,0xb3,0x2a,0x73, +0xbc,0xba,0x22,0x7e,0x73,0x2a,0x6e,0xac,0x7e,0x3e,0x34,0x7d,0xbd,0x2d,0xb3,0x22, +0x70,0x8f,0x0, 0xff,0x51,0xae,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x34,0x36,0x32,0x1, 0xd1,0x53,0x34,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x1, 0xfe,0x44,0x31,0x53,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xd, 0x1b,0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11, +0x10,0xf, 0xe, 0x9, 0x1, 0xa, 0x2, 0xb, 0x3, 0xc, 0x4, 0xd, 0x5, 0x6, 0x7, 0x8, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x1e,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x19,0x28,0x1, 0xf4,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x0, 0x4, 0x67,0x20,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x62,0x40,0xd, 0x1b,0x28,0x15,0x19,0x6, 0x80,0x15,0x19,0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x4d,0x4d,0x2, 0x90,0x2, 0xae,0x1, +0x4e,0x1, 0x50,0x8, 0xe8,0x47,0x47,0x2, 0x4a,0x2, 0x36,0x1, 0x56,0x1, 0x57,0x0, +0x96,0x0, 0x96,0x0, 0x96,0x1, 0x18,0x1, 0x18,0x1, 0x18,0xa, 0x0, 0x1, 0x4a,0x1, +0x1e,0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf7,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x1, 0x0, 0x1, 0x54,0x1, 0x0, 0x1, +0x1, 0x51,0x1, 0x13,0x0, 0x0, 0x1, 0x1, 0xe, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96,0x2, 0x26,0x0, 0x50,0x0, 0x2b, +0x0, 0x1, 0x0, 0x2, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8,0x0, 0x50,0x1, 0xf4,0x0, 0x96, +0x1, 0x2c,0x1, 0x2c,0x4, 0x28,0x3, 0x67,0x62,0x20,0x14,0x3, 0x59,0x52,0x20,0x20, +0x2, 0x32,0x2e,0x20,0x34,0x1, 0x38,0x3d,0x20,0x28,0x3, 0x67,0x62,0x20,0x28,0x3, +0x67,0x62,0x20,0x28,0x3, 0x67,0x62,0x20,0x28,0x3, 0x67,0x62,0x20,0x4, 0x5, 0x19, +0x1a,0x1b,0x1c,0x1d,0x4, 0x0, 0xd2,0x2, 0x30,0x32,0x0, 0xc8,0x1, 0x5e,0x0, 0x64, +0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, 0x6, 0x80,0x1, 0x90,0x1, 0x2c, +0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, 0xb0,0x3, 0x20,0x1, 0x2, 0x2, +0x4, 0x4, 0x6, 0x40,0x1, 0x18,0x1, 0x18,0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x5e, +0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, 0x50,0x0, 0x46,0x0, 0x78,0x0, 0x78, +0x0, 0x78,0x1, 0x18,0x1, 0x18,0xa, 0x5, 0x0, 0x50,0x3, 0xe8,0x0, 0x50,0x8, 0x98, +0x0, 0x32,0x1, 0xf4,0x1, 0xf4,0x3, 0x20,0x0, 0x14,0x0, 0x53,0x0, 0x1e,0x0, 0x80, +0x1, 0xe, 0x1, 0x1d,0x0, 0x3c,0x3, 0xe8,0x2, 0x3a,0x0, 0x87,0x0, 0x3c,0x3, 0xe8, +0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x8, 0xe8,0x0, 0x64,0x0, 0xa0,0x0, 0xa0,0x13,0x88, +0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, 0xc, 0xb, 0x5, 0x5, 0x8, 0x8, +0x6, 0x6, 0xc, 0x64,0xc8,0xe4,0x7a,0xb3,0x38,0xe2,0x7a,0xb3,0x38,0xe3,0x90,0x60, +0x50,0x93,0x7a,0xb3,0x38,0xe4,0x90,0x60,0x51,0xe4,0x93,0x7a,0xb3,0x38,0xe5,0xe4, +0x7a,0xb3,0x38,0xe6,0x90,0x60,0x99,0x93,0x7a,0xb3,0x38,0xe7,0xe4,0x7a,0xb3,0x38, +0xe8,0x7a,0xb3,0x38,0xe9,0x90,0x61,0xc4,0x93,0x7a,0xb3,0x38,0xeb,0x7e,0x34,0x61, +0x4f,0x12,0x23,0x29,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x38,0xef,0x7e,0x34,0x61,0x55, +0x12,0x23,0x29,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x38,0xf0,0x74,0x64,0x7a,0xb3,0x39, +0x1, 0x90,0x61,0x18,0xe4,0x93,0x7a,0xb3,0x39,0x2, 0x90,0x61,0x17,0xe4,0x93,0x7a, +0xb3,0x38,0xee,0x90,0x61,0x19,0xe4,0x93,0x7a,0xb3,0x39,0x4, 0x90,0x61,0x24,0xe4, +0x93,0x7a,0xb3,0x39,0x3, 0x90,0x61,0x1d,0xe4,0x93,0x7a,0xb3,0x39,0x5, 0x90,0x61, +0x25,0xe4,0x93,0x7a,0xb3,0x39,0x0, 0xe4,0x7a,0xb3,0x38,0xfb,0x74,0xfa,0x7a,0xb3, +0x38,0xf9,0x74,0x1e,0x7a,0xb3,0x38,0xfa,0x74,0x1, 0x7a,0xb3,0x38,0xf8,0x74,0xe, +0x7a,0xb3,0x38,0xf7,0x74,0x1, 0x7a,0xb3,0x38,0xfc,0xe4,0x7a,0xb3,0x38,0xfd,0x7a, +0xb3,0x38,0xfe,0x7e,0x8, 0x39,0x6, 0x7e,0x34,0x0, 0x2c,0x12,0x1f,0xee,0x7e,0x34, +0x60,0xd6,0x12,0x23,0x29,0xa, 0x36,0x7a,0x73,0x39,0x11,0x7e,0x34,0x60,0xd6,0x12, +0x23,0x29,0x7a,0x73,0x39,0x12,0x90,0x60,0xd4,0x93,0x7a,0xb3,0x39,0x13,0x90,0x60, +0xd5,0xe4,0x93,0x7a,0xb3,0x39,0x14,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5f,0xac, +0x7e,0x8, 0x39,0x22,0x12,0x1f,0xc9,0x1b,0xfd,0x74,0x5, 0x7a,0xb3,0x39,0x2f,0x74, +0x1, 0x7a,0xb3,0x39,0x26,0x7e,0x34,0x0, 0x28,0xca,0x39,0x7e,0x34,0x61,0xd5,0x7e, +0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33,0x12,0x1f,0xc9,0x1b,0xfd,0x22,0x6d,0x33,0x6c, +0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2,0x2a,0xdc,0x54,0x1, 0x78,0x5, 0x4e,0x70,0x1, +0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x2a,0x74,0xbc,0x5a,0x38,0xe4,0x6c, +0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2,0x2a,0xb9,0xbe,0xb0,0xd, 0x38,0x5, 0x4e,0x70, +0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e,0x60,0x50, +0xb, 0xa0,0x12,0x5f,0xec,0x38,0xdc,0x22,0x7e,0x8, 0x26,0x5b,0x7e,0x34,0x2, 0x3a, +0xe4,0x12,0x1f,0xee,0x90,0x60,0x9c,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0x8c, +0x74,0xff,0x12,0x1f,0xee,0x90,0x60,0x9c,0xe4,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, +0x26,0xb4,0x74,0xff,0x12,0x1f,0xee,0x90,0x60,0x9a,0x12,0x5f,0xe3,0x7e,0x8, 0x27, +0x76,0x74,0xff,0x2, 0x1f,0xee,0xca,0xf8,0x7e,0x73,0x2a,0x78,0xa, 0x47,0x7e,0x73, +0x2a,0x71,0xa, 0x57,0x2d,0x54,0x7e,0xa3,0x2a,0x73,0xbc,0xab,0x28,0x2, 0x7c,0xba, +0x7e,0xf3,0x2a,0x72,0x7e,0xa3,0x2a,0x74,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25, +0x1, 0x7e,0x8, 0x2a,0xb9,0x7e,0x18,0x2a,0x7a,0x12,0xc, 0xb0,0x75,0x25,0x1, 0x7e, +0x8, 0x2a,0xdc,0x7e,0x18,0x2a,0x9d,0x7c,0xbf,0x12,0xe, 0x73,0xda,0xf8,0x22,0x7f, +0x60,0x7e,0xa3,0x2a,0x6d,0x7e,0xb3,0x2a,0x6e,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, +0x7d,0x3f,0xe4,0x12,0x1f,0xee,0x7f,0x6, 0x7d,0x3f,0x12,0x1f,0xee,0x7a,0xb3,0x16, +0x91,0x22,0xca,0x3b,0x7a,0x1d,0x2a,0x7f,0x30,0x12,0xa6,0xa5,0x7a,0x55,0x32,0x7e, +0xb3,0x2b,0x1d,0xf5,0x2f,0xe4,0x7a,0xb3,0x2b,0x1d,0x7f,0x3, 0x7e,0x1d,0x2a,0x12, +0x64,0x9f,0x12,0xc5,0x44,0x7e,0x8, 0x2a,0x6d,0x12,0xb, 0xe9,0x75,0x2e,0x0, 0x12, +0x4c,0xd6,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x66,0xcb,0x7e,0x14,0x40,0x0, 0x7d,0x21, +0x7d,0x7, 0x7e,0xb3,0x2a,0x6d,0x12,0x65,0x46,0x12,0x66,0x81,0x6d,0x33,0x80,0x19, +0x7e,0x35,0x30,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x2a,0x2d, +0x13,0x12,0xc5,0x71,0x7e,0x35,0x30,0xb, 0x34,0x7a,0x35,0x30,0x7e,0x35,0x32,0xbe, +0x35,0x30,0x38,0xdc,0x5, 0x2e,0xe5,0x2e,0xbe,0xb0,0x1, 0x40,0xb2,0xe5,0x2f,0x7a, +0xb3,0x2b,0x1d,0xda,0x3b,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7d,0xc0,0x7d,0xd1, +0x7d,0xf2,0x7d,0xe3,0x12,0x67,0x1f,0x50,0x5e,0x6c,0xee,0x80,0xd, 0x12,0x5f,0xf3, +0x12,0x66,0x28,0x7e,0x34,0x34,0x0, 0x12,0x66,0x69,0x7e,0x73,0x2a,0x6f,0xbc,0x7e, +0x38,0xeb,0x6c,0xee,0x80,0x3b,0x12,0x5f,0xf3,0x6c,0xdd,0x80,0x22,0x7e,0x73,0x38, +0xf7,0xbc,0x7d,0x74,0x4, 0x28,0x8, 0xac,0xbe,0x49,0x35,0x32,0xfa,0x80,0x6, 0xac, +0xbe,0x49,0x35,0x32,0xfc,0x74,0x2, 0xac,0xbd,0x59,0x35,0x34,0x50,0xb, 0xd0,0x7e, +0x73,0x2a,0x70,0xbc,0x7d,0x38,0xd6,0x12,0x66,0x28,0x7e,0x34,0x34,0x50,0x12,0x66, +0x69,0xbc,0xfe,0x38,0xc1,0x80,0x2c,0x7a,0xf3,0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a, +0x73,0x25,0xb7,0xe4,0x7a,0xb3,0x25,0xb9,0x74,0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0xd7, +0x25,0xba,0x7a,0xd7,0x25,0xbe,0x7e,0x8, 0x25,0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37, +0x12,0xd, 0xe, 0x7a,0xc7,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x66,0x39,0x7a, +0xf3,0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9,0x7a,0xd7, +0x25,0xba,0x7e,0x34,0x0, 0x20,0x80,0x10,0x74,0x1, 0x7a,0xb3,0x25,0xb9,0x7a,0xe7, +0x25,0xba,0x7a,0xf7,0x25,0xbc,0x6d,0x33,0x7a,0x37,0x25,0xc0,0x7e,0x8, 0x25,0xb6, +0x12,0xb, 0x7e,0xda,0x79,0xda,0xd8,0x22,0x74,0xc, 0x7a,0xb3,0x25,0xb8,0x74,0x1, +0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x25, +0xb7,0x22,0x7f,0x70,0x7e,0x33,0x2a,0x74,0xa, 0x43,0x7e,0x33,0x2a,0x73,0xa, 0x53, +0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x16,0x90,0x7f,0x1, 0xa, 0x3a,0x12, +0x1f,0xee,0x7f,0x7, 0xa, 0x3a,0x2, 0x1f,0xee,0x7a,0x37,0x25,0xba,0x7d,0x3b,0x7a, +0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e,0x8, 0x25,0xb6,0x12,0xc, 0x50,0xb, 0xe0, +0x22,0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4,0x12,0x1f, +0xee,0x90,0x60,0x93,0x93,0xa, 0x3b,0x7e,0xb3,0x2a,0x71,0xa, 0x2b,0x2d,0x23,0xa, +0x3a,0xad,0x32,0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12,0xa6,0x9c, +0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18,0x20,0x2d, +0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0x12,0x0, 0xe, 0x7e,0x1f, +0x13,0x86,0x22,0x7e,0x8, 0x24,0xf2,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x1f,0xee,0x12, +0x9f,0xd4,0x12,0x9f,0xcb,0xa9,0xd1,0xcb,0x12,0x66,0xcb,0x7a,0x37,0x24,0xf6,0x7e, +0x1f,0x33,0xfb,0x7a,0x37,0x24,0xf8,0x7e,0x1f,0x13,0x86,0x7a,0x37,0x24,0xfa,0x6d, +0x33,0x12,0xa6,0x93,0x2, 0xb, 0x7e,0x12,0xa0,0x55,0x12,0x66,0xd3,0x2, 0x67,0x10, +0x12,0x67,0x1f,0x50,0x3, 0xd2,0x13,0x22,0xc2,0x13,0x22,0x7a,0xb3,0x2b,0x20,0x7e, +0xb3,0x3, 0xc5,0xb4,0x3, 0x8, 0x7e,0xb3,0x38,0xf8,0x70,0x2, 0xc3,0x22,0xd3,0x22, +0x12,0x8a,0x73,0x12,0x98,0x94,0x12,0xaa,0xf5,0x12,0x67,0x99,0x7e,0xb3,0x3, 0xc3, +0xb4,0x1, 0x1e,0x7e,0x34,0x61,0xc0,0x12,0x67,0xf6,0x7e,0x24,0x0, 0x5, 0xad,0x12, +0x7a,0x17,0x28,0xa1,0x7e,0x14,0x61,0xc2,0x12,0x67,0x91,0xad,0x32,0x7a,0x37,0x28, +0xa3,0x7e,0xb3,0x34,0x4f,0x60,0x7, 0x14,0x7a,0xb3,0x34,0x4f,0x80,0x6, 0x7e,0xb3, +0x28,0xac,0x60,0x9, 0x12,0x67,0x7, 0x12,0xa2,0x88,0x12,0xb5,0x5b,0x7e,0xb3,0x28, +0xad,0x60,0x9, 0x12,0xbd,0xf4,0x12,0xbd,0xa3,0x2, 0xa2,0xa5,0x22,0x7e,0x14,0x61, +0xc8,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x22,0x12,0xa9,0xda,0x60,0x17,0x12,0x67, +0xef,0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1,0x7e,0x37,0x28,0xa3,0x3e, +0x34,0x7a,0x37,0x28,0xa3,0x22,0x7d,0x13,0x7e,0x54,0x62,0x58,0x12,0x67,0xe5,0x50, +0x21,0x7e,0x54,0x62,0x5a,0x12,0x67,0xe5,0x28,0x18,0x7e,0x14,0x62,0x5c,0x12,0x67, +0x91,0xbd,0x32,0x50,0xd, 0x7e,0x14,0x62,0x5e,0x12,0x67,0x91,0xbd,0x32,0x28,0x2, +0xe4,0x22,0x74,0x1, 0x22,0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x30,0xbd,0x31,0x22,0x74, +0x1, 0x7a,0xb3,0x28,0xad,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x10,0x22,0x7e,0xa3, +0x2f,0xa8,0x7e,0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x39,0x33,0x40,0x39,0x7e, +0x37,0x39,0x33,0xb, 0x34,0x7a,0x37,0x39,0x33,0xbe,0x34,0x0, 0x1, 0x78,0x5, 0x7e, +0xb3,0x3, 0xf1,0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba,0x22,0xbe,0x34,0x0, +0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x3a,0x2b,0x22,0x9e,0x34,0x0, 0x3, +0x2e,0x37,0x2b,0xb9,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x7e,0xa3,0x38,0xe1,0x7c, +0xba,0x4, 0x7a,0xb3,0x38,0xe1,0x7a,0xa3,0x3, 0xaf,0x22,0xca,0x7b,0xca,0x2b,0xca, +0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82,0x12,0x68,0x77,0xd0,0x82,0xd0,0x83,0xda,0xb, +0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32,0x30,0x90,0x19,0xc2,0x90,0xe5,0x1c,0x70,0x9, +0x75,0x1c,0x1, 0xe5,0x91,0xf5,0x1e,0x80,0x11,0x7e,0x71,0x91,0xe5,0x1e,0x12,0x3f, +0xbc,0x5, 0x1e,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x1e,0xe5,0x1e,0x12,0x68,0xa2,0xf5, +0x91,0x22,0x7c,0x7b,0x6c,0xaa,0x12,0x3f,0xec,0x78,0x9, 0x7c,0xb7,0x12,0x68,0xc1, +0x7c,0xab,0x80,0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x37,0xf2,0x7c,0xab,0x7c,0xba, +0x22,0x70,0x5, 0x7e,0xb3,0x38,0xe2,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x1f,0x0, +0x30,0x12,0x6, 0x7e,0x18,0x35,0xac,0x80,0x4, 0x7e,0x18,0x35,0xea,0x7a,0x1d,0x14, +0x80,0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1f,0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d, +0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4, +0xd3,0x8, 0x6d,0x33,0x7a,0x37,0x39,0x33,0x80,0x2, 0x15,0x1e,0x2, 0x67,0xfe,0xbe, +0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x69,0x58,0xbe,0xb0,0x80,0x40,0xc, 0xbe, +0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x3, 0x1e,0x22,0xb4,0xfc,0x5, 0x7e,0xb3, +0x3, 0xc5,0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e,0xb3,0x28,0xa8,0x60,0x3, 0x4e,0xa0, +0x1, 0x7e,0xb3,0x37,0xf7,0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba,0x22,0xb4,0xfe,0x5, +0x7e,0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x39,0x38, +0x7e,0x73,0x39,0x38,0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x69,0x8e,0x7c,0xab,0x7c, +0xb7,0x4, 0x7a,0xb3,0x39,0x38,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x39,0x38,0x6d,0x33, +0x7a,0x37,0x39,0x35,0x75,0x1e,0xeb,0x7c,0xba,0x22,0x2e,0x24,0x1f,0x83,0x7a,0x51, +0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0xca,0x3b,0x6d,0xee,0x7e,0xc3,0x2a,0x6e,0x7e, +0xd3,0x2a,0x6d,0x7e,0xb3,0x3, 0xee,0xb4,0x1, 0x3, 0xe4,0x41,0xcd,0x7e,0xb3,0x28, +0x84,0x70,0x2, 0x41,0x3c,0x7e,0xb3,0x2a,0x3, 0x60,0x2, 0x80,0x7f,0x7e,0xa3,0x26, +0xfa,0x7e,0x73,0x26,0xfb,0x7a,0x71,0x24,0x6c,0xee,0x6d,0xff,0x6c,0xff,0xa, 0x47, +0x80,0x20,0x12,0x2b,0xfd,0xbe,0x34,0x0, 0x96,0x8, 0x1d,0xb, 0xe0,0xbe,0xa0,0x0, +0x28,0x6, 0x7c,0xba,0x14,0x12,0x6a,0xd3,0x12,0x6a,0xe3,0x58,0x3, 0x12,0x6a,0xd0, +0x1b,0x44,0xbe,0x44,0x0, 0x0, 0x58,0xda,0xe5,0x24,0xa, 0x4b,0x80,0x1e,0x12,0x2b, +0xfd,0xbe,0x34,0x0, 0x96,0x8, 0x21,0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba, +0x14,0x12,0x6a,0xd3,0x12,0x6a,0xe3,0x58,0x3, 0x12,0x6a,0xd0,0x7d,0x24,0xb, 0x24, +0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xd6,0xbe,0xe0,0x3, 0x50,0x2, 0x80,0xd, 0xa, +0x2f,0x7d,0x3f,0x12,0x1d,0xb3,0xbe,0x34,0x0, 0x28,0x8, 0x7, 0xe4,0x7a,0xb3,0x37, +0x42,0x41,0xcd,0x6d,0xdd,0xbe,0xa0,0x0, 0x28,0x8, 0x7c,0xba,0x14,0x12,0x6a,0xdd, +0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, 0xca,0xbd,0xc3,0x58,0x8, 0x7c,0xba,0x4, 0x12, +0x6a,0xdd,0x2d,0xd3,0x7e,0x70,0x8, 0x80,0x2a,0x7e,0x50,0x2, 0xac,0x57,0x7d,0xc2, +0x2e,0xc4,0x20,0x10,0x7d,0x1c,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0x1a,0xcb, +0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x20,0x11,0x7d,0x2c,0x12,0x69,0x8e,0x1a, +0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xce,0x7c,0xba,0x12,0x6a,0xdd, +0x12,0x20,0x30,0xbe,0x34,0xa, 0xf0,0x8, 0x4, 0x2e,0xe4,0x0, 0x28,0xbe,0xe4,0x0, +0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x37,0x42,0xa, 0x3b,0xbd,0x3e,0x50, +0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x37,0x42,0x7e,0xb3,0x37,0x42,0xda,0x3b,0x22, +0x7c,0xba,0x4, 0x7c,0x79,0x12,0x2c,0x1, 0x2d,0xf3,0xb, 0xf0,0x22,0x7e,0x71,0x24, +0x2, 0x2c,0x1, 0xa, 0x2d,0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0x12,0x6a,0xf7,0x12, +0x69,0x97,0x7a,0xb3,0x2a,0xc, 0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x36,0xa6, +0x6c,0x33,0x80,0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10,0x1, +0x6c,0x0, 0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93,0x26, +0xfb,0xa, 0x29,0xa, 0x32,0x12,0x32,0x54,0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40, +0x8, 0x74,0x2, 0x7a,0xb3,0x36,0xa6,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, +0x30,0xbc,0xa3,0x38,0xbf,0x2, 0x6b,0x48,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c,0x22, +0x80,0x45,0x74,0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e,0xa0, +0x1, 0x6c,0x99,0x80,0x2c,0xbc,0x92,0x68,0x26,0x7e,0x70,0x2, 0xac,0x79,0x9, 0x83, +0x26,0xfa,0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, 0x31,0x12,0x32,0x54,0x18,0xb, 0xa, +0x2f,0xa, 0x30,0x12,0x32,0x54,0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, +0x90,0xbc,0x39,0x38,0xd0,0xb, 0x20,0xbc,0x32,0x38,0xb7,0x7e,0xb3,0x37,0x41,0xbe, +0xb0,0x0, 0x28,0x12,0x14,0x7a,0xb3,0x37,0x41,0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34, +0x0, 0x8c,0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x3, 0xa9,0x70,0x58,0x7e,0xb3,0x3a,0x3b, +0x70,0x52,0x7e,0xb3,0x37,0xf7,0x70,0x4c,0x7e,0x37,0x39,0x43,0xbe,0x34,0x0, 0x14, +0x50,0x42,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x28,0x84, +0xbe,0xb0,0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x26,0x85,0xbe,0xb0, +0x3, 0x50,0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x26,0xf6, +0xbe,0xb0,0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7,0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e, +0x7a,0xb3,0x37,0x41,0xda,0xf8,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12, +0x3f,0xf4,0x7e,0xa3,0x2a,0x73,0x7e,0x63,0x2a,0x74,0x6c,0xee,0x80,0x1e,0xa, 0x2e, +0x9, 0x72,0x2a,0xdc,0xbe,0x70,0x1c,0x50,0x11,0xa, 0x27,0x12,0x69,0x8a,0x7c,0x7b, +0x7e,0xb3,0x2a,0xfb,0xa, 0x27,0x19,0xb2,0x1f,0x34,0xb, 0xe0,0xbc,0x6e,0x38,0xde, +0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73,0x2a,0xb9,0xbe,0x70,0x23,0x50,0xa, 0x7e, +0x63,0x2a,0xfb,0xa, 0x27,0x19,0x62,0x1f,0x50,0xb, 0xe0,0xbc,0xae,0x38,0xe5,0x6c, +0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x1f,0x34,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e, +0x12,0x10,0xc0,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0xa9,0xc0,0x93, +0x75,0x1c,0x0, 0x32,0x7a,0xb3,0x38,0xe2,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, +0xb4,0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3, +0x3, 0xc5,0x22,0x74,0x1, 0x7a,0xb3,0x3, 0xc5,0xe4,0x7a,0xb3,0x38,0xe2,0x22,0x7c, +0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, 0x7c,0xba,0x12,0x6c,0x94,0x80,0x2c,0xbe,0x30, +0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, 0x7c,0xb3,0x7c,0x7a,0x12,0x6d,0x2e,0x80,0x1a, +0xbe,0x30,0x80,0x40,0x15,0xbe,0x30,0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a, +0x12,0x6d,0xa, 0xa5,0xbb,0x8f,0x3, 0x75,0x1d,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba, +0x2, 0x45,0x33,0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68, +0x1c,0x2e,0x60,0xfd,0x68,0x17,0x1b,0x61,0x68,0x13,0x2e,0x60,0xfa,0x68,0xe, 0x1b, +0x60,0x68,0xa, 0x80,0x0, 0xa, 0x2b,0x19,0x72,0x3, 0x9e,0xd2,0x11,0x22,0xbe,0xb0, +0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x39,0x35,0x4d,0x22,0x78,0xe, 0xa5,0xbf, +0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x39,0x35,0x15,0x1e,0x7e,0x27,0x39,0x35, +0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x2, +0x6d,0x33,0x7a,0x37,0x39,0x35,0x75,0x1e,0xea,0x22,0x7e,0xb3,0x39,0x37,0x4, 0x7a, +0xb3,0x39,0x37,0xe5,0x1d,0xb4,0x1, 0x8, 0xe4,0x7a,0xb3,0x39,0x37,0x75,0x1d,0x0, +0x7e,0x73,0x39,0x37,0x7a,0x73,0x3, 0xad,0x22,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff, +0x75,0x25,0x0, 0x75,0x26,0x0, 0x75,0x28,0x3, 0x6c,0xee,0x75,0x29,0x0, 0x7e,0x48, +0x29,0xbc,0x12,0x74,0x17,0x7e,0xb3,0x2a,0xb, 0x70,0xe, 0x7e,0xb3,0x2a,0x7, 0x70, +0x8, 0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0xe1,0xab,0x30,0x12,0x6, 0x7e,0x68,0x35,0xea, +0x80,0x4, 0x7e,0x68,0x35,0xac,0x7f,0x6, 0x12,0x6f,0xf1,0x7e,0x73,0x2a,0x4, 0x7a, +0x6b,0x70,0x6c,0xdd,0xe1,0x5c,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x29,0xc, 0x7c,0xbc, +0x54,0xf, 0x12,0x6f,0xdf,0xf5,0x28,0x7c,0xbc,0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, +0xe1,0x5a,0x7a,0x4d,0x2a,0x7e,0x18,0x0, 0x29,0x7a,0x1d,0x2e,0x7e,0x8, 0x0, 0x28, +0x7c,0xbc,0x7c,0x7d,0x12,0x71,0x1a,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, 0xe1,0x5a, +0x7e,0x8, 0x0, 0x28,0x7c,0xbc,0x12,0x97,0xd9,0x50,0x2, 0xe1,0x5a,0x74,0x9, 0xac, +0xbd,0x9, 0xb5,0x29,0xd, 0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xe, 0xc4, +0x54,0xf0,0xf5,0x26,0x7e,0x73,0x2a,0x4d,0xbc,0x7c,0x28,0x57,0x7e,0xb3,0x2a,0x9, +0x70,0x2a,0x75,0x2a,0xf, 0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x35,0x94,0x6d, +0x22,0x74,0x1, 0x12,0x70,0xd8,0x75,0x2a,0x20,0x7e,0x8, 0x0, 0x26,0xa, 0x3c,0x2e, +0x34,0x35,0x9e,0x6d,0x22,0x74,0x10,0x12,0x70,0xd8,0x80,0xe, 0xa, 0x3c,0x9, 0xb3, +0x35,0x94,0xf5,0x25,0x9, 0xb3,0x35,0x9e,0xf5,0x26,0xa, 0x3c,0x12,0x6f,0xe1,0xb4, +0x1, 0x11,0xe4,0xa, 0x3c,0x19,0xb3,0x35,0x94,0x19,0xb3,0x35,0x9e,0x75,0x25,0x0, +0x75,0x26,0x0, 0x7e,0xb3,0x2a,0x64,0xb4,0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac, +0xbd,0x9, 0xb5,0x29,0xc, 0xbe,0xb0,0xff,0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, +0xac,0x9d,0x49,0xb4,0x29,0x8, 0x49,0xa4,0x29,0xa, 0xe5,0x28,0xb4,0x1, 0x3b,0xe4, +0xa, 0x3c,0x19,0xb3,0x36,0x28,0x2d,0x39,0x7d,0x28,0x39,0xb1,0x0, 0x3c,0x75,0x27, +0x0, 0x80,0x1d,0x7e,0x71,0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x36,0x37,0x54,0xf, +0xbc,0xbc,0x78,0xa, 0x49,0xb3,0x36,0x33,0x49,0xa3,0x36,0x35,0x80,0xc, 0x5, 0x27, +0x90,0x60,0x99,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd9,0x5e,0xb4,0xf, 0xff,0x5e,0xa4, +0xf, 0xff,0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x2d,0xa5, +0xbe,0x70,0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x24,0xb, 0xf0, +0xe5,0x28,0xa, 0x5b,0x12,0x6f,0xe9,0x2d,0xb5,0x80,0x4, 0x2e,0xb4,0xc0,0x0, 0x7e, +0x70,0x6, 0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, 0x7f,0x6, 0x2d,0x13, +0x79,0xa0,0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0,0x0, 0x6, 0xe5,0x26, +0x2d,0x3d,0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0,0x7e,0x73,0x2a,0x4d, +0xbc,0x7d,0x28,0x2, 0xa1,0xd6,0xe5,0x24,0x39,0xb6,0x0, 0x1, 0x7e,0xb3,0x3, 0xee, +0xb4,0x1, 0x9, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x17,0x80,0xd, 0xbe,0xf0,0x0, 0x38, +0x6, 0x7e,0xb3,0x2a,0x8, 0x60,0xa, 0xb2,0x12,0x12,0x6d,0x6a,0x74,0x1, 0x12,0x55, +0xfd,0x7e,0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x5c,0x8c,0xe4,0x7a,0xb3,0x2a, +0xb, 0x7a,0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4,0x12,0x55,0xfd,0x12, +0x94,0x1d,0xca,0x59,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x36,0x33,0x12,0x1f,0xc9,0x1b, +0xfd,0x4c,0xff,0x78,0xc, 0x12,0x5f,0xe0,0x7e,0x8, 0x36,0x33,0x74,0xff,0x12,0x1f, +0xee,0xe5,0x29,0x12,0x74,0x3f,0xe5,0x29,0x7a,0xb3,0x2a,0xd, 0xda,0x3b,0x22,0xa, +0x3b,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0x22,0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4, +0x22,0x7e,0x34,0x0, 0x3e,0x74,0xff,0x2, 0x1f,0xee,0xe4,0x7a,0xb3,0x38,0xe2,0x7e, +0x8, 0x35,0xac,0x12,0x6f,0xf1,0x7e,0x8, 0x35,0xea,0x7e,0x34,0x0, 0x3e,0x12,0x1f, +0xee,0x7e,0x18,0x35,0xac,0x7a,0x1d,0x14,0x12,0x70,0x2b,0x2, 0x70,0x1e,0x75,0x1c, +0x0, 0x75,0x1e,0x0, 0x7e,0xb3,0x38,0xe2,0xf5,0x91,0x22,0x2, 0x70,0x2e,0x90,0x60, +0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2,0xc9,0x54,0xfe, +0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0x7c,0xab,0x12,0x3f,0x5b,0x7c,0xba, +0x12,0x12,0xc7,0x2, 0x0, 0x1e,0x30,0x1c,0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12,0x12, +0x2c,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x4f,0x12,0x70,0xb8,0x49,0x35,0x34,0x3b,0x49, +0x15,0x34,0x3d,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15, +0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0x73,0x7e,0x73, +0x2a,0x74,0x12,0xf, 0xb5,0x7e,0xb3,0x34,0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12,0x70, +0xc0,0x28,0xe, 0x12,0x4d,0x3, 0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80, +0x2, 0x74,0x2, 0x7a,0xb3,0x34,0x3a,0x22,0x7e,0xa3,0x34,0x39,0x74,0x4, 0xa4,0x22, +0x7e,0x73,0x34,0x38,0xbe,0x73,0x34,0x39,0x22,0x7f,0x20,0xb, 0x2a,0x10,0xb, 0x1a, +0x0, 0x1b,0x2a,0x0, 0x1b,0x1a,0x10,0x22,0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80,0x4c, +0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b,0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80,0xa, +0x38,0x9d,0x32,0x12,0x20,0x30,0xe5,0x2a,0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e,0x7b, +0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9, +0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, 0x70,0x22,0xca,0xf8,0x7c,0xa7,0x7c,0xfb, +0x7f,0x70,0x7e,0x70,0x9, 0xac,0x7a,0x9, 0xb3,0x29,0xf, 0x9, 0x73,0x29,0x10,0x7c, +0x6f,0x12,0x71,0x6c,0xb4,0x1, 0x32,0x7e,0x7b,0xa0,0x4c,0xaa,0x78,0x4, 0x74,0x3, +0x80,0x7, 0xbe,0xa0,0x2, 0x78,0x5, 0x74,0x1, 0x7a,0x7b,0xb0,0x74,0x1, 0x7e,0x1d, +0x2e,0x7a,0x1b,0xb0,0x74,0x3, 0xa, 0x1f,0x7e,0x1d,0x2a,0x2d,0x31,0x7a,0x1b,0xb0, +0x7e,0x1d,0x2a,0x2d,0x31,0x39,0xb1,0x0, 0xa, 0xda,0xf8,0x22,0xca,0xd8,0xca,0x79, +0x7c,0x56,0x7c,0x6b,0xc2,0x0, 0xc2,0x1, 0xc2,0x2, 0xc2,0x3, 0x75,0x36,0xff,0x75, +0x37,0x0, 0x6c,0xdd,0x7a,0x51,0x32,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x8, 0x12,0x73, +0x55,0x12,0x1f,0xee,0x61,0x36,0x74,0x4, 0x7a,0xb3,0x36,0x32,0x7e,0x44,0x0, 0xfa, +0x7e,0xb3,0x35,0x92,0xbe,0xb0,0x0, 0x28,0xf, 0x14,0x7a,0xb3,0x35,0x92,0x7e,0x44, +0x0, 0x96,0x74,0x2, 0x7a,0xb3,0x36,0x32,0x75,0x38,0x0, 0x75,0x39,0x0, 0x80,0x1c, +0x7e,0x51,0x32,0x74,0x2, 0xac,0x5b,0x9, 0xb2,0x26,0xfa,0xf5,0x33,0x5, 0x38,0x5, +0x39,0x5, 0x32,0x7e,0xb3,0x28,0x84,0xbe,0xb1,0x32,0x38,0xe4,0x7a,0x61,0x33,0x7c, +0xa7,0xc2,0x0, 0xc2,0x1, 0x7e,0x71,0x33,0x85,0x33,0x34,0x80,0xa, 0x12,0x73,0x3b, +0xbd,0x24,0x8, 0x8, 0x7a,0x71,0x34,0x12,0x73,0x95,0x58,0xf1,0x7e,0x71,0x33,0x7e, +0xe1,0x33,0x80,0x9, 0x12,0x73,0x3b,0xbd,0x24,0x8, 0xf, 0x7c,0xe7,0x12,0x73,0x84, +0x7e,0x63,0x2a,0x6f,0x1a,0x26,0xbd,0x12,0x48,0xea,0x75,0x35,0x0, 0x7e,0x73,0x2a, +0x6f,0x7c,0xb7,0x14,0xbc,0xbe,0x78,0xc, 0xd2,0x1, 0xa, 0x37,0x1b,0x34,0x7c,0xb7, +0xf5,0x36,0x80,0x8, 0xe5,0x34,0x70,0x4, 0xd2,0x0, 0xf5,0x36,0x7c,0x7a,0x7c,0xfa, +0x20,0x1, 0x13,0x30,0x0, 0x40,0x80,0xe, 0x12,0x73,0x9e,0x1a,0x17,0x12,0x73,0x47, +0xbd,0x24,0x8, 0x7, 0x7c,0xf7,0x12,0x73,0x95,0x58,0xed,0x7c,0x7a,0x7c,0xda,0x80, +0xe, 0x12,0x73,0x9e,0x1a,0x17,0x12,0x73,0x47,0xbd,0x24,0x8, 0xf, 0x7c,0xd7,0x12, +0x73,0x84,0x7e,0x63,0x2a,0x6e,0x1a,0x26,0xbd,0x12,0x48,0xe5,0xa, 0x2f,0xa, 0x3d, +0x9d,0x32,0x7c,0xb7,0xf5,0x35,0x7e,0xb3,0x35,0xa8,0xbe,0xb1,0x33,0x38,0x79,0x7e, +0xb3,0x35,0xa9,0xbe,0xb1,0x33,0x40,0x70,0x7e,0xb3,0x35,0xaa,0xbc,0xba,0x38,0x68, +0x7e,0xb3,0x35,0xab,0xbc,0xba,0x40,0x60,0x7e,0xb3,0x36,0x32,0xbe,0xb1,0x35,0x50, +0x4b,0xe5,0x32,0xa, 0x3b,0x9, 0xb3,0x36,0x28,0xbe,0xb0,0x2, 0x50,0xc, 0x7e,0xb3, +0x36,0x8d,0x70,0x6, 0x12,0x73,0x8c,0x12,0x73,0xa8,0xe5,0x32,0xa, 0x4b,0x7d,0x34, +0x2e,0x34,0x36,0x28,0x12,0x74,0x2f,0x9, 0xb4,0x36,0x28,0xbe,0xb0,0x1, 0x50,0x7, +0x7e,0xb3,0x36,0x8d,0xb4,0x1, 0x4d,0xd2,0x2, 0x12,0x73,0x7a,0x12,0x1f,0xee,0x7e, +0x70,0x2, 0xe5,0x32,0xa, 0x2b,0x19,0x72,0x36,0x28,0x80,0x7, 0x7e,0xb3,0x36,0x8d, +0xb4,0x1, 0x31,0x75,0x37,0x1, 0x80,0x2c,0x7e,0xb3,0x36,0x8d,0xb4,0x1, 0x25,0x20, +0x1, 0x3, 0x30,0x0, 0x1f,0xe5,0x35,0xbe,0xb0,0x5, 0x40,0x18,0x7e,0xb3,0x28,0x84, +0xb4,0x1, 0x11,0xd2,0x2, 0x75,0x37,0x1, 0x12,0x73,0x7a,0x12,0x1f,0xee,0x12,0x73, +0x8c,0x12,0x73,0xa8,0xe5,0x37,0xda,0x79,0xda,0xd8,0x22,0x7e,0x63,0x2a,0x6e,0xa, +0x6, 0x1a,0x17,0xad,0x10,0xa, 0x2a,0x2d,0x21,0x3e,0x24,0x7e,0xf, 0x13,0x8a,0x2d, +0x12,0xb, 0xa, 0x20,0x22,0xe4,0x7a,0xb3,0x36,0x8d,0x7a,0xb3,0x35,0x93,0x74,0x5, +0x7a,0xb3,0x36,0x32,0xe4,0x7a,0xb3,0x35,0xa8,0x74,0xff,0x7a,0xb3,0x35,0xa9,0xe4, +0x7a,0xb3,0x35,0xaa,0x74,0xff,0x7a,0xb3,0x35,0xab,0x7e,0x8, 0x36,0x28,0x7e,0x34, +0x0, 0xa, 0xe4,0x22,0x7c,0xb7,0x4, 0x7c,0x7b,0x1a,0x1b,0x22,0xe5,0x34,0x7c,0x7e, +0x7c,0x6f,0x7c,0x5d,0x22,0x7c,0xb7,0x14,0x7c,0x7b,0xbe,0xb0,0x0, 0x22,0x7e,0x63, +0x2a,0x6e,0x7e,0x51,0x36,0xac,0x56,0x22,0x7c,0x4b,0xe5,0x19,0xbc,0xb4,0x8, 0x3, +0x7a,0x41,0x19,0xe5,0x1b,0xbc,0xb7,0x58,0x3, 0x7a,0x71,0x1b,0xe5,0x18,0xbc,0xb6, +0x8, 0x3, 0x7a,0x61,0x18,0xe5,0x1a,0xbc,0xb5,0x58,0x3, 0x7a,0x51,0x1a,0xe5,0x19, +0x1a,0x3b,0x1b,0x34,0xbe,0x34,0x0, 0x0, 0x8, 0x8, 0xe5,0x19,0x1a,0x3b,0x1b,0x34, +0x80,0x2, 0x6c,0x77,0x7a,0x73,0x35,0xa8,0xe5,0x1b,0x1a,0x3b,0xb, 0x35,0x7a,0x73, +0x35,0xa9,0xe5,0x18,0x1a,0x3b,0x1b,0x35,0xbe,0x34,0x0, 0x0, 0x8, 0x8, 0xe5,0x18, +0x1a,0x3b,0x1b,0x35,0x80,0x2, 0x6c,0x77,0x7a,0x73,0x35,0xaa,0xe5,0x1a,0x1a,0x3b, +0xb, 0x35,0x7a,0x73,0x35,0xab,0x22,0x7e,0xb3,0x2a,0x2, 0x70,0x11,0x12,0x74,0x37, +0x28,0x6, 0x14,0x7a,0xb3,0x35,0x93,0x22,0x12,0x73,0x55,0x2, 0x1f,0xee,0x22,0x7e, +0x39,0xb0,0x4, 0x7a,0x39,0xb0,0x22,0x7e,0xb3,0x35,0x93,0xbe,0xb0,0x0, 0x22,0x7c, +0xab,0xbe,0xa0,0x1, 0x78,0x6, 0x74,0x5, 0x7a,0xb3,0x35,0x92,0xbe,0xa0,0x1, 0x78, +0xd, 0x74,0x1, 0x7a,0xb3,0x36,0x8d,0x74,0xa, 0x7a,0xb3,0x35,0x93,0x22,0x12,0x74, +0x37,0x28,0x12,0x14,0x7a,0xb3,0x35,0x93,0x75,0x19,0x64,0x75,0x1b,0x0, 0x75,0x18, +0x64,0x75,0x1a,0x0, 0x22,0xe4,0x7a,0xb3,0x36,0x8d,0x22,0xca,0xf8,0x7e,0xa3,0x2a, +0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, 0xbe,0xb0,0x0, 0x28,0x13,0x74,0x1, +0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x2a, +0xb, 0x12,0x94,0x1d,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x8, 0x12,0x1f, +0xc9,0x1b,0xfd,0x90,0x61,0x35,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x31,0x6c,0xff,0x80, +0x24,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xae,0x12,0x7f,0xf9,0x74,0x9, 0xac,0xbf, +0x59,0x35,0x29,0x8, 0x49,0x35,0x28,0xb0,0x12,0x74,0xf1,0x74,0x9, 0xac,0xbf,0x59, +0x35,0x29,0xa, 0xb, 0xf0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x38,0xd3,0xda,0xf8, +0x22,0x7d,0xe3,0x9f,0x11,0x7e,0x14,0x61,0x43,0x12,0x76,0x6, 0x90,0x61,0x35,0xe4, +0x93,0x70,0x3, 0x7d,0x3e,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83, +0x2a,0x6f,0x80,0x4, 0x7e,0x83,0x2a,0x70,0x12,0x81,0x0, 0xbe,0xe4,0x0, 0x3f,0x38, +0x1d,0x7e,0x24,0x0, 0x3f,0x9d,0x2e,0x7e,0x14,0x61,0x47,0x12,0x67,0x91,0x12,0x75, +0xed,0x12,0x75,0xf8,0xbf,0x10,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0x7d,0x14, +0x9e,0x14,0x0, 0x3f,0xbd,0x1e,0x38,0x33,0x7d,0x34,0x9e,0x34,0x0, 0x40,0x7d,0x2e, +0x9d,0x23,0x7e,0xd4,0x61,0x49,0x7e,0xc4,0x0, 0xff,0xb, 0x6a,0x30,0x12,0x75,0xed, +0x90,0x61,0x46,0xe4,0x93,0xa, 0xdb,0x6d,0xcc,0xbf,0x16,0x48,0x4, 0x7f,0x16,0x1b, +0x1c,0xa, 0xb, 0x7d,0xdf,0x9d,0xd0,0x6d,0xcc,0x2f,0x16,0xbe,0xe4,0x0, 0x3f,0x28, +0x6b,0xbd,0x1e,0x28,0x67,0x7d,0xd4,0xb, 0xd4,0x1e,0xd4,0x7d,0x5d,0x1b,0x54,0xbd, +0x5e,0x40,0xc, 0x7d,0x35,0x9d,0x3e,0x6d,0x22,0x7e,0x14,0x61,0x4b,0x80,0xa, 0x7d, +0x3e,0x9d,0x3d,0x6d,0x22,0x7e,0x14,0x61,0x4d,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10, +0x12,0x1d,0xf6,0x12,0x75,0xf1,0xbd,0x5e,0x7d,0x1f,0x40,0xc, 0x1e,0x14,0x1b,0x14, +0x6d,0x0, 0x9f,0x1, 0x7f,0x10,0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0x12,0x75, +0xf8,0xbf,0x10,0x58,0x4, 0x7f,0x10,0x80,0x13,0x90,0x61,0x46,0xe4,0x93,0xa, 0xb, +0x7d,0x1f,0x9d,0x10,0x6d,0x0, 0xbf,0x10,0x8, 0x2, 0x7f,0x10,0x22,0xad,0x32,0x6d, +0x22,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x90,0x61,0x45,0xe4,0x93,0xa, 0x1b,0x6d, +0x0, 0x22,0x7e,0x14,0x62,0x8e,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xf0,0x22,0xca,0xf8, +0x6c,0xff,0x7e,0xb7,0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e,0x97,0x2f,0x84,0x7e,0xd7, +0x2f,0x86,0x7e,0xa7,0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4,0x7e,0x73,0x2f,0xa8,0x1b, +0x70,0x7d,0x2b,0x7d,0x1c,0x12,0x77,0x56,0x70,0x2, 0xe1,0x49,0x7e,0x73,0x2f,0xa8, +0xbe,0x70,0xa, 0x28,0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27,0x2f,0xa0,0x7e,0x17,0x2f, +0xa2,0x12,0x77,0x56,0x70,0x2, 0xe1,0x49,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0x14,0x28, +0x13,0xe4,0x7e,0x70,0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17,0x2f,0xa6,0x12,0x77,0x56, +0x70,0x2, 0xe1,0x49,0x7e,0x34,0x62,0x72,0x12,0x77,0x4e,0xbd,0xfc,0x28,0x50,0x7e, +0x34,0x62,0x70,0x12,0x77,0x4e,0xbd,0xfb,0x50,0x45,0x7e,0xb3,0x2f,0x81,0x70,0x3f, +0x7e,0x34,0x62,0x76,0x12,0x23,0x29,0x12,0x76,0x2, 0x7d,0x8f,0x9d,0x83,0xbe,0x87, +0x2f,0x82,0x50,0x2b,0x7e,0x34,0x62,0x74,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x80,0x9d, +0xf8,0xbe,0xf7,0x2f,0x82,0x28,0x18,0x7d,0xfc,0x3e,0xf4,0xbd,0xfb,0x40,0x2, 0xe1, +0x49,0xbd,0xa9,0x50,0x5, 0x7e,0xf0,0x20,0x80,0x7f,0x7e,0xf0,0x21,0x80,0x7a,0x7e, +0x34,0x62,0x7a,0x12,0x77,0x4e,0xbd,0xfb,0x28,0x6f,0x7e,0x34,0x62,0x78,0x12,0x77, +0x4e,0xbd,0xfc,0x50,0x64,0x7e,0xb3,0x2f,0x81,0x70,0x5e,0x7e,0x34,0x62,0x7e,0x12, +0x23,0x29,0x12,0x76,0x2, 0x7d,0xaf,0x9d,0xa3,0xbe,0xa7,0x2f,0x82,0x50,0x4a,0x7e, +0x34,0x62,0x7c,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xa0,0x9d,0xfa,0xbe,0xf7,0x2f,0x82, +0x28,0x37,0x7d,0xfb,0x3e,0xf4,0xbd,0xfc,0x50,0x2f,0xbd,0xed,0x50,0x5, 0x7e,0xf0, +0x22,0x80,0x26,0x12,0xc2,0x3a,0x49,0x35,0x2b,0xbb,0x49,0x15,0x2b,0xbd,0x49,0x25, +0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d,0x10,0xbe,0x14,0x0, 0x20,0x18,0x8, 0x9d,0x32, +0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e,0xf0,0x23,0x7c,0xbf,0xda,0xf8,0x22,0x7e,0x24, +0x0, 0xff,0xb, 0x1a,0xf0,0x22,0x7d,0x41,0x7d,0x2, 0x7c,0x37,0x7c,0x2b,0x74,0x4, +0xac,0xb2,0x49,0x35,0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74,0x4, 0xac,0xb3,0x49,0x25, +0x2b,0xbf,0x49,0x55,0x2b,0xc1,0x12,0xa0,0x4d,0x7d,0x3f,0x9d,0x35,0x12,0x20,0x30, +0x9d,0x34,0x12,0x20,0x30,0x7e,0x54,0x62,0x6a,0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x20, +0xbd,0x32,0x50,0xf, 0x12,0xc1,0xa1,0x7e,0x14,0x62,0x6a,0x12,0x8f,0xa8,0x50,0x3, +0x74,0x1, 0x22,0xe4,0x22,0x12,0xbf,0xba,0x7a,0x37,0x2f,0x9c,0x12,0xbf,0xb1,0x7a, +0x37,0x2f,0x9e,0x12,0x76,0xe, 0x60,0x1, 0x22,0x7e,0x73,0x2f,0xa8,0xa, 0x37,0x7a, +0x35,0x24,0x7e,0x8, 0x2b,0xbf,0x7e,0x18,0x2f,0x80,0x2, 0x77,0xcd,0xca,0xf8,0x7e, +0x45,0x24,0x7c,0xb9,0x7a,0xb3,0x39,0x85,0x74,0xff,0x7a,0xb3,0x39,0x84,0x6d,0x55, +0x80,0x19,0x7d,0xf5,0x3e,0xf4,0x12,0xa6,0x3, 0x7d,0xe5,0x3e,0xe4,0x59,0xfe,0x1f, +0x34,0x69,0xf6,0x0, 0x2, 0x59,0xfe,0x21,0x14,0xb, 0x54,0xbd,0x45,0x38,0xe3,0x7e, +0x33,0x39,0x85,0xbe,0x30,0x4, 0x38,0x2, 0x1, 0x8f,0x69,0xf1,0x0, 0x1c,0x69,0x11, +0x0, 0x1e,0xbd,0x1f,0x18,0x19,0x4d,0x11,0x78,0x4, 0x7e,0x14,0x0, 0x1, 0x7d,0x3f, +0x7d,0x21,0x12,0x1d,0xb3,0x7c,0xf7,0x74,0x40,0x7a,0xb3,0x39,0x88,0x80,0x43,0x4d, +0xff,0x78,0x4, 0x7e,0xf4,0x0, 0x1, 0x7d,0x31,0x7d,0x2f,0x12,0x1d,0xb3,0x7c,0xf7, +0x74,0x80,0x7a,0xb3,0x39,0x88,0x7d,0xf, 0x2d,0xf, 0xbd,0x1, 0x8, 0x24,0x1a,0x2, +0x1a,0x0, 0x7e,0x73,0x39,0x88,0xa, 0x37,0x6d,0x22,0x12,0x1d,0xe5,0x7d,0x5f,0x1a, +0x4a,0x1a,0x48,0x7d,0x1f,0x1a,0x2, 0x1a,0x0, 0x2f,0x2, 0x12,0x1e,0x1, 0x7a,0x73, +0x39,0x88,0xbe,0xf0,0x5, 0x58,0x14,0x12,0x78,0xae,0x12,0x7a,0x2f,0x12,0x78,0xae, +0x12,0x78,0xb7,0x12,0x78,0xae,0x12,0x7a,0xda,0x80,0xa, 0x74,0x7d,0x80,0x2, 0x74, +0x7f,0x7a,0xb3,0x39,0x84,0xe4,0x7a,0xb3,0x39,0x85,0x7e,0x73,0x3a,0x31,0xbe,0x73, +0x39,0x84,0x48,0x6, 0x7e,0xb3,0x39,0x86,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7e,0x8, +0x1f,0x34,0x7e,0x18,0x21,0x14,0x22,0xca,0x3b,0x7f,0x71,0x7e,0x60,0x1, 0xb, 0xa, +0x20,0xb, 0x7a,0x50,0x7c,0x4b,0x7a,0x53,0x22,0xf4,0x7a,0x43,0x23,0xe4,0x7e,0x70, +0x1, 0x7e,0xa0,0x1, 0x21,0xd8,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x60,0x2d,0xd4,0xb, +0x6a,0xd0,0x7d,0x7d,0x7c,0xbf,0xf5,0x26,0x7f,0x67,0x2d,0xd4,0xb, 0x6a,0x40,0xa, +0xd5,0xa, 0xbb,0x7d,0xab,0x9d,0xad,0x7d,0x7a,0x7c,0x8f,0xbe,0x80,0x0, 0x58,0x5, +0x6e,0x80,0xff,0xb, 0x80,0xa, 0xa4,0xa, 0x79,0x9d,0x7a,0xbe,0xf0,0x0, 0x58,0x5, +0x6e,0xf0,0xff,0xb, 0xf0,0xbe,0x80,0x2, 0x58,0x7, 0xbe,0xf0,0x2, 0x58,0x2, 0x21, +0xd6,0xbe,0x60,0x0, 0x18,0x2, 0x21,0xbe,0xbe,0x70,0xec,0x28,0x2, 0x21,0xe2,0xbe, +0x80,0x8, 0x58,0x5, 0xbe,0xf0,0x8, 0x48,0x61,0xa, 0xa7,0xb, 0xa4,0x7d,0x6a,0x7c, +0x7d,0xa, 0xa5,0x2d,0xab,0x12,0x7a,0x26,0x19,0xba,0x22,0xf4,0xa, 0xd9,0xa, 0xa4, +0x2d,0xad,0x12,0x7a,0x26,0x19,0xba,0x23,0xe4,0x9, 0xba,0x22,0xf4,0xa, 0xdb,0xa, +0xc5,0x2d,0xcd,0xe, 0xc4,0x7d,0x6c,0x7c,0xbd,0xa, 0xc7,0x19,0xbc,0x22,0xf3,0x9, +0xbc,0x23,0xe4,0xa, 0xcb,0xa, 0xa4,0x2d,0xac,0x12,0x7a,0x26,0x19,0xba,0x23,0xe3, +0x2d,0xdb,0x12,0x7a,0x1d,0x19,0xbd,0x22,0xf5,0xa, 0xd9,0x12,0x7a,0x1b,0x19,0xbd, +0x23,0xe5,0xb, 0xd5,0x7d,0x6d,0x7c,0x7d,0x80,0x24,0xbe,0x80,0x4, 0x58,0x5, 0xbe, +0xf0,0x4, 0x48,0x1a,0xe5,0x26,0xa, 0xcb,0xa, 0xd5,0x12,0x7a,0x1b,0x19,0xbd,0x22, +0xf4,0xa, 0xc9,0xa, 0xd4,0x12,0x7a,0x1b,0x19,0xbd,0x23,0xe4,0xb, 0x70,0xbe,0x70, +0xf0,0x50,0x1f,0x7e,0x51,0x26,0x7c,0x49,0xe5,0x26,0xa, 0xd7,0x19,0xbd,0x22,0xf4, +0x19,0x9d,0x23,0xe4,0xb, 0x70,0xb, 0xa0,0x7e,0xb3,0x39,0x85,0xbc,0xba,0x28,0x2, +0x1, 0xd6,0x7a,0x73,0x39,0x85,0x7e,0xa0,0x1, 0x80,0x25,0xa, 0x3a,0x9, 0xb3,0x22, +0xf4,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x60,0x2d,0xd3,0x1b,0x6a,0x20,0xa, +0x2a,0x9, 0xb2,0x23,0xe4,0xa, 0x4b,0x2d,0x3f,0x7d,0x2e,0x1b,0x1a,0x40,0xb, 0xa0, +0x7e,0xb3,0x39,0x85,0xbc,0xba,0x38,0xd3,0xda,0x3b,0x22,0x2d,0xdc,0xe, 0xd4,0x7d, +0x6d,0x7c,0xbd,0xa, 0xd7,0x22,0xe, 0xa4,0x7d,0x6a,0x7c,0xbd,0xa, 0xa7,0x22,0xca, +0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x2f,0x90,0x7a,0x35,0x2a,0x7e,0x37,0x2f,0x8e, +0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c,0x7a,0x35,0x26,0x7e,0x37,0x2f,0x9e,0x7a,0x35, +0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x26,0x7e,0x14,0x0, 0x2f,0x74,0x9, 0x12, +0x1e,0x86,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d,0x15,0x7f,0x15,0x2d,0x35,0x12,0x7a, +0x7e,0xb, 0xf0,0x7e,0x73,0x39,0x85,0xbc,0x7f,0x38,0xda,0xda,0xf8,0x22,0x7f,0x71, +0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34,0x0, 0x0, 0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a, +0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, 0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a, +0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35,0x33,0x6d,0x22,0x7e,0x33,0x39,0x87,0x12,0x7a, +0xd3,0x7e,0x15,0x2f,0x12,0x1d,0xff,0x1b,0x6a,0x30,0xb, 0x7a,0x30,0x9e,0x35,0x35, +0x6d,0x22,0x7e,0x33,0x39,0x88,0x12,0x7a,0xd3,0x7e,0x15,0x31,0x12,0x1d,0xff,0x1b, +0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x1d,0xe5,0xca,0x3b,0x7f,0x61,0x7f,0x50, +0x7e,0x73,0x39,0x85,0xbe,0x70,0x20,0x40,0x52,0x7e,0xf0,0x2, 0x80,0x3c,0xa, 0x3f, +0x6d,0x22,0x74,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0x33,0x39,0x85,0xa, 0x13,0x6d, +0x0, 0x12,0x1e,0x1, 0x7c,0xe7,0xbe,0xe0,0x2, 0x50,0x3, 0x7e,0xe0,0x2, 0xa, 0x6f, +0x1b,0x64,0xa, 0x3e,0x1b,0x34,0x7c,0xc7,0x7f,0x5, 0x7c,0xbd,0x12,0x7b,0x44,0x7f, +0x6, 0x7c,0xbd,0x7c,0x7c,0x12,0x7b,0x44,0xb, 0xf0,0x7e,0x73,0x39,0x85,0xbc,0x7f, +0x50,0xbc,0x7f,0x5, 0x7f,0x16,0x12,0x7b,0x96,0x80,0x6, 0x74,0x7e,0x7a,0xb3,0x39, +0x84,0xda,0x3b,0x22,0x7c,0x97,0x7c,0xab,0x7f,0x10,0x7e,0x30,0x2, 0xac,0x3a,0x2d, +0x13,0x7d,0x2, 0xb, 0xa, 0x10,0x7e,0x10,0x2, 0xac,0x19,0x7f,0x71,0x2d,0xf0,0xb, +0x7a,0x0, 0x7c,0x21,0xa5,0xba,0x0, 0x14,0x1a,0x3, 0x1b,0x7a,0x0, 0xbc,0x9a,0x68, +0x24,0x6d,0x44,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x40,0x22,0xbc,0x9a,0x68,0x15, +0x1a,0x2, 0x1a,0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a,0x10,0x6d,0x11,0x74,0x2, 0xa4, +0x2d,0x35,0x1b,0x1a,0x10,0x22,0xca,0x79,0x6c,0xaa,0x12,0x87,0x8, 0xb, 0x7a,0xf0, +0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39,0x89,0x7f,0x71,0x2d,0xf4,0xb, 0x7a, +0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0xa9,0xb, 0xa0,0xbe,0xa0,0x20,0x40,0xda, +0x7e,0x8, 0x39,0x89,0x7e,0x18,0x39,0xa9,0x74,0x20,0x12,0x7b,0xd0,0xda,0x79,0x22, +0xca,0x3b,0xf5,0x2a,0x7f,0x31,0x7a,0xd, 0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3, +0x22,0xf7,0x7a,0xb3,0x22,0xf8,0x7e,0x34,0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c, +0x7a,0xb3,0x22,0xf5,0x75,0x2f,0x46,0x75,0x2b,0x0, 0xa1,0xc1,0x12,0x7f,0xf1,0x28, +0x1e,0x7e,0x34,0x0, 0x44,0xca,0x39,0x7e,0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34, +0x13,0x6, 0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x22,0xff,0x12,0x1f,0xc9,0x1b,0xfd,0x6d, +0x33,0x7a,0x37,0x22,0xf9,0x7a,0x35,0x30,0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a, +0x35,0x34,0x7e,0x34,0x22,0xff,0x7a,0x35,0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38, +0x75,0x2c,0x0, 0x80,0x59,0xe5,0x2c,0xa, 0x3b,0x7e,0xd, 0x26,0x12,0xc5,0x95,0x2e, +0x35,0x36,0x12,0x7d,0xfc,0x7d,0xd3,0x7e,0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a, +0xd7,0x22,0xfb,0xe5,0x2c,0xa, 0x3b,0x7f,0x3, 0x12,0xc5,0x95,0x2e,0x35,0x38,0x12, +0x7d,0xfc,0x7d,0xc3,0x7e,0x35,0x32,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37, +0x22,0xf9,0x2d,0x3d,0x7a,0x37,0x22,0xf9,0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30, +0x2d,0xcd,0x7e,0x35,0x34,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a, +0xbe,0xb1,0x2c,0x38,0xa0,0xe5,0x2a,0xb4,0xa, 0x2a,0x7e,0x37,0x22,0xfb,0xbe,0x34, +0x0, 0x40,0x48,0xb, 0x7e,0x25,0x32,0xbe,0x24,0x0, 0x40,0x48,0x2, 0xa1,0xbf,0xbe, +0x34,0x0, 0x60,0x8, 0x2, 0xa1,0xbf,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x2, +0xa1,0xbf,0x80,0x28,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x20,0x8, 0xb, 0x7e,0x25, +0x32,0xbe,0x24,0x0, 0x20,0x8, 0x2, 0xa1,0xbf,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xa1, +0xbf,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xa1,0xbf,0x7e,0xa3,0x39,0x87, +0x74,0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58,0x2, 0xa1,0xbf,0x7e,0xa3,0x39,0x88,0x74, +0xc, 0xa4,0xbe,0x55,0x30,0x58,0x2, 0xa1,0xbf,0x7e,0x15,0x36,0x6d,0x0, 0x7e,0x1d, +0x26,0xe5,0x2a,0x12,0xc3,0x97,0x7a,0xb3,0x22,0xf4,0x7e,0x15,0x38,0x6d,0x0, 0x7f, +0x13,0xe5,0x2a,0x12,0xc3,0x97,0xf5,0x2d,0x7e,0x73,0x22,0xf5,0xbe,0x73,0x22,0xf4, +0x38,0x7d,0xbe,0x71,0x2d,0x38,0x78,0xe5,0x2d,0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, +0x1a,0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d, +0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4,0xa, 0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1e, +0x1, 0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe,0xb1,0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb, +0x2e,0x35,0x32,0x2e,0x35,0x34,0x7a,0x35,0x3a,0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, +0x64,0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a,0x7a,0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe, +0x35,0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a,0x37,0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22, +0xf7,0x7e,0x73,0x23,0x41,0x7a,0x73,0x22,0xf8,0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, +0x2b,0x12,0x7f,0xf1,0x28,0x2, 0x61,0xfc,0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40, +0x20,0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, 0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e, +0x73,0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a,0x73,0x39,0x84,0x7a,0xb3,0x39,0x86,0x80, +0x6, 0x74,0x7c,0x7a,0xb3,0x39,0x84,0x7c,0xba,0xda,0x3b,0x22,0x7e,0x39,0x70,0xa, +0x37,0x9d,0x32,0x2, 0x20,0x30,0xca,0x79,0x7f,0x70,0x7e,0xb4,0xff,0xff,0x6c,0xee, +0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc,0x76,0x78,0xe, 0x29, +0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2,0x2, 0x6c,0xff,0x12, +0x7f,0xde,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xc1,0xc0,0x7f,0x6, 0x7e, +0x7b,0xb0,0x12,0x7f,0xeb,0x50,0x2d,0x7f,0x6, 0x29,0xb7,0x0, 0x2, 0x12,0x7f,0xeb, +0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0xae,0xa9,0x50,0x15,0x7f, +0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0xae,0xa9,0x50,0x8, 0x7c,0xef,0xd2,0x1, +0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70,0x12,0x7d,0xff,0x2d, +0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12,0x7d,0xff,0x2d,0xa3, +0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x7d,0xff,0x2d,0xa3,0x29, +0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x7d,0xff,0x2d,0xa3,0xbd,0xab, +0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, 0xd2,0x1, 0x80,0x9, +0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0xc1,0x2f,0x20,0x1, 0xb, 0x20,0x2, 0x8, 0xbe, +0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, 0x2, 0xe1,0x81,0x74,0x6, 0xac,0xbe, +0x12,0x7f,0xe2,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xbe,0xb0,0x1f, +0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e,0x60,0x8, 0x5e,0x60,0xf8, +0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x2, 0x11,0x29,0xb6,0x0, 0x4, 0xbe, +0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b,0xb0,0x29,0x67,0x0, 0x3, +0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x3, 0x80,0x4, 0x29,0x77, +0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29,0x76,0x0, 0x2, 0xbc,0x76, +0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, 0x2, 0x39,0x76,0x0, 0x2, +0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50,0x6, 0x29,0x76,0x0, 0x1, +0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e,0x7b,0x60,0x7e,0x6b,0x70, +0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b,0x70,0x7a,0x6b,0x70,0x80, +0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x2, 0xef,0x30,0xe1,0x7, 0xb, 0xf0, +0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x39,0x74,0x1, 0x39,0xb7,0x0, 0x4, +0x12,0x7f,0xde,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f,0x17,0x7f,0x6, 0x12,0x1f,0xc9, +0x1b,0xfd,0x7f,0x16,0x12,0x7f,0xd6,0x44,0x1, 0x7a,0x1b,0xb0,0x7f,0x16,0x12,0x7f, +0xd6,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x2, 0xa, 0x7f,0x16,0x12,0x7f,0xd6,0x44,0x4, +0x7a,0x1b,0xb0,0xda,0x79,0x22,0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x74,0x6, +0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x2, 0xea,0x6d,0xcc,0x22,0x7e,0x70,0x1, 0x2, 0xae, +0xa9,0x7e,0x73,0x3a,0x31,0xbe,0x71,0x2b,0x22,0x7d,0xc3,0x7e,0x34,0x61,0x37,0x12, +0x8f,0x97,0x90,0x61,0x35,0xe4,0x93,0x70,0x3, 0x7d,0x3c,0x22,0x90,0x61,0x36,0xe4, +0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x2a,0x70,0x80,0x4, 0x7e,0x83,0x2a,0x6f,0x12,0x81, +0x0, 0xbe,0xc4,0x0, 0x3f,0x38,0x1f,0x7e,0xe4,0x0, 0x3f,0x9d,0xec,0x7e,0x34,0x61, +0x3b,0x12,0x77,0x4e,0x12,0x80,0xf1,0x12,0x80,0xe0,0xbf,0x71,0x40,0x2, 0x7f,0x71, +0x9f,0x17,0x7f,0x71,0x1, 0xdd,0x7d,0x54,0x9e,0x54,0x0, 0x3f,0xbd,0x5c,0x38,0x24, +0x7d,0xec,0x9d,0xe5,0x7e,0x34,0x61,0x3d,0x12,0x77,0x4e,0x12,0x80,0xf1,0x90,0x61, +0x3a,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40,0x4, 0x7f,0x71,0x1b,0x7c,0x12,0x80,0xe8, +0x2f,0x71,0x80,0x69,0x7d,0xb4,0xb, 0xb4,0x1e,0xb4,0x7d,0x5b,0x1b,0x54,0xbd,0x5c, +0x40,0xc, 0x7d,0xf5,0x9d,0xfc,0x6d,0xee,0x7e,0x34,0x61,0x3f,0x80,0xa, 0x7d,0xfc, +0x9d,0xfb,0x6d,0xee,0x7e,0x34,0x61,0x41,0x12,0x67,0xf6,0x7f,0x17,0x12,0x1d,0xf6, +0x7f,0x71,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x7f,0x71,0xbd,0x5c,0x7d,0x3d,0x40,0xc, +0x1e,0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x6, 0x1e,0x34,0x6d,0x22, +0x2f,0x71,0x12,0x80,0xe0,0x6d,0x22,0xbf,0x71,0x50,0x4, 0x7f,0x71,0x80,0xe, 0x90, +0x61,0x3a,0xe4,0x93,0x12,0x80,0xe8,0xbf,0x71,0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22, +0x90,0x61,0x39,0xe4,0x93,0xa, 0x3b,0x22,0xa, 0x2b,0x7d,0x3d,0x9d,0x32,0x6d,0x22, +0x22,0xad,0xfe,0x6d,0xee,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x7c,0x65,0x7f,0x71,0x22, +0x7e,0x90,0x40,0xac,0x89,0x1b,0x44,0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, +0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x12,0x1d,0xff,0x7d,0x53,0xbe,0x54,0x0, 0xff, +0x28,0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca,0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f, +0x3a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3, +0x1f,0x35,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3, +0x1f,0x38,0x7a,0xb3,0x1f,0x39,0x7e,0x8, 0x1f,0x34,0x12,0x81,0x7c,0x6d,0x22,0x7d, +0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa0,0x2f,0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12, +0x1e,0x1, 0xa, 0x1f,0x6d,0x0, 0x12,0x1e,0x1, 0xda,0xf8,0x22,0x12,0xa, 0xa0,0x7e, +0x37,0x15,0x9e,0x22,0x7a,0x37,0x1f,0x38,0x7e,0x34,0x15,0xa8,0x7a,0x37,0x1f,0x3c, +0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x35, +0x7e,0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x3e, +0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x42, +0x74,0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3,0x1f,0x37,0x7e,0x8, 0x1f,0x34,0x7e,0x18, +0x1f,0x44,0x12,0x6, 0x74,0x7e,0x37,0x1f,0x4e,0x7e,0x27,0x1f,0x4a,0xbd,0x23,0x28, +0x2, 0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, 0x1f,0x34,0x12,0x87,0x0, 0x7e,0x1f,0x3a, +0x23,0x7a,0x1d,0x26,0x7e,0xb3,0x2a,0x74,0xf5,0x2d,0x7e,0xb3,0x39,0xcc,0xb4,0x1, +0x6, 0x7e,0x38,0x39,0xce,0x80,0x4, 0x7e,0x38,0x5, 0xf8,0x6d,0x33,0x7a,0x35,0x2a, +0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39,0xcd,0x70,0xe, 0x7e,0xb3,0x39,0xcb,0x70, +0x8, 0x74,0x1, 0x7a,0xb3,0x39,0xcd,0x41,0xac,0x7e,0xb3,0x39,0xcd,0x70,0x6, 0x74, +0x1, 0x7a,0xb3,0x39,0xcd,0x7e,0xb3,0x39,0xcc,0xb4,0x1, 0x14,0x75,0x2c,0x0, 0x80, +0x6, 0x12,0x82,0xee,0x12,0x82,0xfc,0xe5,0x2d,0xbe,0xb1,0x2c,0x38,0xf3,0x80,0x18, +0x75,0x2c,0x0, 0x80,0xc, 0x12,0x82,0xee,0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0x82, +0xfc,0xe5,0x2d,0xbe,0xb1,0x2c,0x38,0xed,0x7e,0x34,0x61,0x59,0x12,0x23,0x29,0x7a, +0x35,0x2e,0x7e,0x18,0x1f,0x34,0x7f,0x1, 0x12,0x83,0xd, 0x75,0x2c,0x0, 0x80,0x10, +0x12,0x82,0xe1,0xbe,0x35,0x2a,0x8, 0x6, 0x12,0x82,0xe1,0x7a,0x35,0x2a,0x5, 0x2c, +0xe5,0x2d,0xbe,0xb1,0x2c,0x38,0xe9,0x12,0x82,0xd9,0x40,0x25,0x7e,0xb3,0x39,0xcc, +0xb4,0x1, 0x1e,0x5, 0x5f,0xe5,0x5f,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x5f,0x0, 0xe5, +0x2d,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x26,0x7f,0x3, 0x12,0x1f,0xc9,0x1b, +0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x82,0xd9,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x3a, +0x22,0xe4,0x7a,0xb3,0x39,0xcd,0xda,0x3b,0x22,0x7e,0x37,0x2b,0x7, 0xbe,0x35,0x2a, +0x22,0x7e,0xa1,0x2c,0x74,0x2, 0xa4,0x49,0x35,0x1f,0x34,0x2, 0x20,0x30,0x7e,0xa1, +0x2c,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7e,0xd, 0x26,0x2d, +0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35,0x1f,0x34,0x5, 0x2c,0x22,0xca,0x3b,0x7f, +0x61,0x7f,0x50,0x7e,0x73,0x2a,0x6e,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f, +0x5, 0x12,0x1f,0xc9,0x1b,0xfd,0x6c,0xdd,0x12,0x86,0xc2,0x7a,0xb3,0x1f,0x6c,0x6c, +0xcc,0x80,0x45,0x12,0x83,0xb1,0x78,0x3e,0x12,0x86,0xca,0xb, 0x1a,0xe0,0x7d,0x3f, +0x12,0x20,0x30,0x7d,0x13,0x7d,0x3e,0x12,0x20,0x30,0xbd,0x31,0x58,0x2, 0x7d,0xfe, +0xbe,0xe5,0x2e,0x8, 0x5, 0x7e,0xe5,0x2e,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2e,0xbd, +0x3e,0x8, 0x2, 0x7d,0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f, +0x6c,0x4, 0x7a,0xb3,0x1f,0x6c,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xb3, +0x7e,0x73,0x1f,0x6c,0x4c,0x77,0x68,0x1d,0x12,0x86,0xe8,0x8, 0x2, 0x7d,0x7f,0x6c, +0xcc,0x80,0xa, 0x12,0x83,0xb1,0x78,0x3, 0x12,0x86,0xd3,0xb, 0xc0,0x7e,0x73,0x2a, +0x70,0xbc,0x7c,0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0x61,0x28,0xda,0x3b, +0x22,0xa, 0xec,0x9, 0x7e,0x2a,0xdc,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd, +0x3e,0x22,0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2e,0x7e, +0xd, 0x24,0x7f,0x13,0x12,0x83,0xd, 0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x84,0x2e, +0x7e,0xd, 0x24,0x2d,0x15,0x7f,0x13,0x2d,0x35,0x12,0x85,0xd3,0xda,0x3b,0x22,0x7e, +0x37,0x2a,0x4f,0x1e,0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, +0x12,0x83,0xc2,0x7e,0x37,0x28,0x99,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a, +0x7e,0x18,0x4, 0x7e,0x12,0x83,0xc2,0x12,0x85,0xa7,0x2, 0x84,0x1d,0xe4,0x7a,0xb3, +0x3, 0xfe,0x7e,0xb3,0x28,0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xfe,0x22,0x7e,0xa3, +0x2a,0x74,0x74,0x2, 0xa4,0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab,0x7d,0x8b, +0x6d,0x22,0x7d,0x32,0x7d,0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, 0xfc,0x7e, +0x8, 0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3,0x26,0xf6, +0x7a,0xb3,0x26,0xf8,0x7a,0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa,0x80,0x5f, +0x12,0x85,0x9d,0xb, 0x6a,0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3,0x8, 0x2, +0x7d,0x3c,0x2d,0x71,0x7d,0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d,0x9d,0x7e, +0x67,0x2a,0x53,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, 0x24,0x12, +0x85,0x8a,0xb, 0x3a,0xd0,0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x26,0xf7,0x4, 0x7a,0xb3, +0x26,0xf7,0x80,0x19,0x12,0x85,0x93,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff,0xb, 0xd4, +0xbd,0xcd,0x58,0x9, 0x7e,0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, 0xa0,0x7e, +0xb3,0x2a,0x74,0xbc,0xba,0x38,0x99,0x7a,0xa7,0x7, 0xfe,0x7a,0x37,0x8, 0x2, 0xe5, +0x24,0x7a,0xb3,0x8, 0x9, 0x7a,0x97,0x8, 0x6, 0x12,0x84,0x2e,0x2d,0xf5,0x6c,0xaa, +0x80,0x50,0x12,0x85,0x9d,0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d,0xbd,0xd2, +0x8, 0x2, 0x7d,0x2d,0x7e,0x67,0x2a,0x51,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xd7, +0x8, 0x2, 0xb, 0x90,0x12,0x85,0x8a,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, 0x7e,0xb3, +0x26,0xf6,0x4, 0x7a,0xb3,0x26,0xf6,0x80,0x17,0x12,0x85,0x93,0xb, 0x3a,0xd0,0x6d, +0x99,0x9d,0x9c,0xbd,0xd9,0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3,0x26,0xf8, +0xb, 0xa0,0x12,0x5f,0xec,0x38,0xab,0x7a,0x87,0x7, 0xfc,0x7a,0x27,0x8, 0x0, 0x7a, +0x93,0x8, 0x8, 0x12,0x84,0x2e,0x2d,0x15,0x6c,0xaa,0x80,0xe, 0x12,0x87,0x8, 0xb, +0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x5f,0xec,0x38,0xed,0x7a, +0xb7,0x8, 0x4, 0xbd,0x8a,0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0xf8,0xbd,0x32,0x58, +0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b,0x22,0x7e,0x74,0x62,0x10,0x7e,0x64, +0x0, 0xff,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x2d,0x7f,0x7d,0x6e,0x22,0x7e,0xf0,0x2, +0xac,0xfa,0x7f,0x67,0x2d,0xd7,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e,0xe3,0x2a, +0x6f,0x7e,0xd3,0x2a,0x70,0x6c,0xcc,0x80,0x13,0x7c,0x7c,0xac,0x7f,0x3e,0x34,0x7e, +0xf, 0x13,0x8a,0x2d,0x13,0x7c,0xbd,0x12,0x9e,0x6a,0xb, 0xc0,0xbc,0xec,0x38,0xe9, +0xda,0x3b,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x22,0x6d,0x7e,0x4, 0x0, +0xff,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x2a,0x6d,0xa, +0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x1f,0xc9,0x1b,0xfd,0x6c,0xdd, +0x12,0x86,0xc2,0x7a,0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4a,0x12,0x86,0xb2,0x40,0x43, +0x12,0x86,0xa8,0x50,0x3e,0x12,0x86,0xca,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x20,0x30, +0x7d,0x3, 0x7d,0x31,0x12,0x20,0x30,0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15,0x2a, +0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, 0x2, +0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34,0x4, 0x7a, +0xb3,0x1f,0x34,0xb, 0xc0,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x38,0xae,0x7e,0x73,0x1f, +0x34,0x4c,0x77,0x68,0x37,0x12,0x86,0xe8,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, +0x5, 0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d, +0x7e,0x6c,0xcc,0x80,0xf, 0x12,0x86,0xb2,0x40,0x8, 0x12,0x86,0xa8,0x50,0x3, 0x12, +0x86,0xd3,0xb, 0xc0,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x38,0xe9,0xb, 0xd0,0xbe,0xd0, +0x3, 0x50,0x2, 0xc1,0x0, 0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc, +0xab,0x22,0xa, 0xec,0x9, 0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc, +0xab,0x22,0x7e,0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16, +0x2d,0x35,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7, +0x7f,0x15,0x2d,0x35,0x1b,0x1a,0xe0,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12,0x1e, +0x52,0x7d,0x73,0x12,0x20,0x30,0x7d,0xe3,0x7d,0x3f,0x12,0x20,0x30,0xbd,0x3e,0x22, +0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x1f,0xee,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d, +0xf4,0x22,0x74,0xc8,0x7a,0xb3,0x3a,0x36,0xc2,0x1b,0x80,0xa, 0x12,0x46,0x55,0x30, +0x1b,0x4, 0x75,0xe9,0xff,0x22,0x12,0x47,0xdf,0x68,0xf1,0x22,0x7e,0x34,0x61,0x59, +0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x20,0x1e,0x24,0x1e,0x24,0x12,0x87,0x4b,0x50,0x8, +0x7e,0x27,0x2a,0x4f,0x1e,0x24,0x1e,0x24,0x7d,0x32,0x22,0xc2,0x0, 0x12,0x87,0x73, +0x68,0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17,0x7e,0xb3,0x37,0xf7,0x70,0x11,0x12, +0x2f,0xf7,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe,0x34,0x1, 0x90,0x58,0x2, 0xd2,0x0, +0xa2,0x0, 0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, 0x22,0x12,0x87,0x4b,0x50,0x12, +0x7e,0x37,0x2b,0x7, 0xbe,0x34,0x1, 0x2c,0x28,0x8, 0x7e,0x34,0x1, 0x2c,0x7a,0x37, +0x2b,0x7, 0x22,0x7c,0xab,0x7e,0xb3,0x3a,0x3b,0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70, +0x11,0x12,0x87,0xb3,0x68,0xc, 0x12,0x87,0x73,0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, +0x36,0xca,0x22,0x7e,0xb3,0x3, 0xee,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x3, 0xc3,0x70, +0x2e,0x7e,0x73,0x3, 0xa6,0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77,0x7e,0xb3,0x3, 0xee, +0xb4,0x1, 0x3, 0x7e,0x70,0x6, 0xa, 0x37,0x2e,0x34,0x20,0x0, 0x12,0x57,0xf0,0x7c, +0xab,0xe5,0x65,0xa, 0x3b,0x2e,0x37,0x39,0xc9,0x7a,0x37,0x39,0xc9,0x80,0xc, 0x7e, +0xa3,0x3, 0xa7,0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, 0x88,0x0, +0x75,0x65,0x0, 0x7a,0xb3,0x3a,0x36,0xc2,0x1b,0x22,0x7e,0xb3,0x39,0xcc,0x70,0x4, +0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0xcc,0x22,0x7f,0x20,0xc2,0x1, 0x7e,0x2b, +0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x20,0x30,0x7c,0x27,0x29,0x72, +0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x20,0x30,0x7c,0x37,0x1a, +0x23,0x1a,0x32,0x9d,0x32,0x12,0x20,0x30,0x7c,0x67,0x7c,0x72,0xbc,0x32,0x58,0x2, +0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e,0x37,0x39,0x39, +0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6d, +0x88,0x7a,0x87,0x39,0x82,0xe4,0x7a,0xb3,0x1f,0x58,0xe5,0x60,0xbe,0xb0,0xff,0x50, +0x2, 0x5, 0x60,0x7e,0xb3,0x28,0x84,0x60,0xc, 0x12,0x8f,0x9f,0xb, 0x1a,0x80,0xbe, +0x87,0x7, 0xfa,0x28,0xa, 0xc2,0x14,0x6d,0x88,0x7a,0x87,0x39,0x43,0x21,0x98,0x12, +0x90,0x0, 0x60,0x16,0x7e,0x34,0x62,0xe, 0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x80,0x7a, +0x87,0x39,0x39,0x12,0x8a,0x6, 0x7a,0x87,0x39,0x43,0x7e,0x87,0x39,0x39,0x4d,0x88, +0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x77,0xe4,0xa, 0x3f,0x19, +0xb3,0x1f,0x34,0x12,0x8a,0x20,0x7e,0x8, 0x1f,0x52,0x7c,0xbd,0x7c,0x7e,0x12,0x8b, +0x98,0x7d,0x93,0x7e,0x87,0x39,0x43,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x43,0x7e, +0x87,0x39,0x82,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x82,0xe5,0x60,0xbe,0xb0,0x5, +0x38,0x1f,0x7e,0x8, 0x39,0x45,0x12,0x8a,0x2d,0x50,0x7, 0x12,0x8a,0x17,0xd2,0x0, +0x80,0x2f,0x7e,0x8, 0x39,0x45,0x7e,0x18,0x1f,0x52,0x12,0x8e,0x6a,0x50,0x22,0x80, +0x10,0x12,0x8a,0x6, 0xbd,0x89,0x38,0x19,0x7e,0x8, 0x1f,0x52,0x12,0x88,0x1a,0x50, +0x10,0x12,0x8a,0x17,0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52,0x12,0x8f,0xda,0xd2, +0x0, 0xb, 0xf0,0x12,0x89,0xff,0x38,0x84,0x30,0x0, 0x33,0x6c,0xff,0x80,0x1c,0x12, +0x8a,0x20,0x7e,0x8, 0x1f,0x58,0x12,0x8a,0x2d,0x40,0x9, 0xa, 0x3f,0x9, 0xb3,0x1f, +0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x87,0x93,0xb, 0xf0,0x12,0x89,0xff,0x38,0xdf, +0x75,0x60,0x0, 0x7e,0x34,0x62,0xe, 0x12,0x23,0x29,0x7a,0x37,0x39,0x39,0x7e,0x63, +0x1f,0x58,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1f,0x58,0x7e, +0x8, 0x39,0x45,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x37,0x39,0x39,0x4d,0x33,0x78,0x39, +0x90,0x62,0x9, 0xe4,0x93,0xa, 0x3b,0xbe,0x37,0x39,0x43,0x38,0x40,0x7c,0x7b,0x1e, +0x70,0xa, 0x37,0xbe,0x37,0x39,0x82,0x38,0x34,0x90,0x60,0x51,0x12,0x8a,0xe, 0x7e, +0x73,0x26,0xf7,0xa, 0x37,0xbd,0x32,0x8, 0x24,0x90,0x60,0x50,0x12,0x8a,0xe, 0x7e, +0x73,0x26,0xf6,0xa, 0x37,0xbd,0x32,0x8, 0x14,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12, +0x87,0x93,0xb, 0xf0,0x12,0x89,0xff,0x38,0xf4,0xd2,0x0, 0x80,0x6, 0x6d,0x33,0x7a, +0x37,0x39,0x43,0xa2,0x0, 0x92,0x14,0x12,0x8e,0x53,0xda,0x79,0xda,0xd8,0x22,0x7e, +0x73,0x28,0x84,0xbc,0x7f,0x22,0x90,0x62,0x9, 0xe4,0x93,0xa, 0x8b,0x22,0xe4,0x93, +0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, 0x8f,0x19,0xb8,0x1f,0x34,0x22, +0x74,0x2, 0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5,0x26,0xfb,0x22,0x7c,0xbd,0x7c, +0x7e,0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a,0x7f,0x70, +0x2d,0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b,0xb0,0xbc, +0xb6,0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, 0x1, 0xbc, +0xb7,0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x38,0xc9, +0xa2,0x1, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28,0x99,0xe4, +0x7a,0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x4c,0x7e,0x73,0x28, +0x85,0xbe,0x70,0x0, 0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, +0xd2,0x27,0x36,0x9, 0xe2,0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xfc, +0x6d,0x22,0x9e,0x27,0x2a,0x53,0xbd,0x12,0x58,0x19,0x12,0x8b,0x85,0x49,0x12,0x4, +0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28, +0xa6,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7,0x7e,0xb3, +0x26,0x83,0x70,0x40,0x12,0x8f,0x87,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, +0xac,0x5f,0x9, 0xd2,0x26,0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x8b,0x85,0x49,0x2, 0x5, +0x7a,0x6d,0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20, +0x5, 0x7a,0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, 0xb, 0xf0, +0xbc,0x7f,0x38,0xc9,0x12,0x9b,0xd7,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37,0x28,0x88, +0x2e,0x37,0x28,0x86,0xbe,0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9, +0x74,0x1, 0x7a,0xb3,0x28,0xaa,0x6c,0xff,0x80,0x1f,0x12,0x8b,0x8e,0x49,0x25,0x25, +0xf7,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x20,0x30,0xbe,0x37,0x28,0x9d,0x8, 0x7, +0xe4,0x7a,0xb3,0x28,0xaa,0x80,0x7, 0xb, 0xf0,0x12,0x89,0xff,0x38,0xdc,0x6c,0xff, +0x80,0x9, 0x12,0x8b,0x8e,0x59,0x35,0x25,0xf7,0xb, 0xf0,0x12,0x89,0xff,0x38,0xf2, +0xda,0x79,0xda,0xd8,0x22,0xa, 0x1d,0xa, 0x2a,0x2d,0x21,0x3e,0x24,0x22,0x7c,0xbf, +0x12,0x37,0xdc,0x74,0x2, 0xac,0xbf,0x22,0xca,0x3b,0x7c,0xc7,0x7c,0xfb,0x7f,0x40, +0x6d,0x33,0x7a,0x35,0x24,0x7e,0xa3,0x2a,0x6d,0x7e,0x73,0x2a,0x6e,0x4c,0xcc,0x78, +0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc,0xbc,0x78,0x6, 0xa, 0x6c,0x1b, +0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, 0x80,0xb, 0x7c,0xba,0x14,0xbc, +0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e,0x34,0x0, 0x6, 0xe4,0x12,0x1f, +0xee,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b,0x34,0x7a,0x4b,0x70,0x7e,0x73,0x2a,0x6e, +0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec,0x80,0x1c,0x75,0x26,0x0, 0x7c, +0xdf,0x80,0xa, 0x12,0x8c,0xb2,0x70,0xa, 0x12,0x8e,0x48,0x1b,0xd0,0xbe,0xd0,0x0, +0x58,0xf1,0xe5,0x26,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xdf,0x7c,0xec,0x80, +0x23,0x75,0x26,0x0, 0x1a,0x3f,0xb, 0x34,0x7c,0xd7,0x80,0xa, 0x12,0x8c,0xb2,0x70, +0xd, 0x12,0x8e,0x48,0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xee,0xe5,0x26, +0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xd8,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80, +0x1c,0x75,0x26,0x0, 0x7c,0xdf,0x80,0xa, 0x12,0x8c,0xb2,0x70,0xa, 0x12,0x8e,0x48, +0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf1,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x2a, +0x6e,0xbc,0x7e,0x18,0xdc,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x21,0x75,0x26,0x0, +0x1a,0x6f,0xb, 0x64,0x80,0xa, 0x12,0x8c,0xb2,0x70,0xd, 0x12,0x8e,0x48,0xb, 0xd0, +0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xee,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73, +0x2a,0x6e,0xbc,0x7e,0x18,0xd7,0x7e,0x35,0x24,0x7d,0x23,0x39,0x54,0x0, 0x5, 0xda, +0x3b,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70,0x7c,0xe7,0x7c,0xdb, +0x7e,0xc0,0x4, 0x7e,0xb3,0x2a,0x6d,0xf5,0x28,0x7e,0xb3,0x2a,0x6e,0xf5,0x27,0x7e, +0x34,0x62,0xa, 0x12,0x8f,0x97,0x6c,0xff,0x12,0x2f,0xff,0x7f,0x51,0xe5,0x28,0xa, +0x3b,0x1b,0x34,0xa, 0xcd,0xbd,0xc3,0x58,0x14,0xe5,0x27,0xa, 0x3b,0x1b,0x34,0xa, +0xce,0xbd,0xc3,0x58,0x8, 0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e,0xf0,0x10, +0xb, 0x5a,0x30,0x7e,0x14,0x62,0xa, 0x12,0x8f,0xa8,0x8, 0xc, 0x7e,0x27,0x28,0x8a, +0xbe,0x24,0x3, 0x20,0x8, 0x2, 0xc1,0x7, 0xb, 0xa, 0xc0,0x1e,0xc4,0xbd,0x3c,0x8, +0xc, 0x7e,0xc7,0x28,0x8a,0xbe,0xc4,0x3, 0x20,0x58,0x2, 0xc1,0x7, 0x6c,0xaa,0x7c, +0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8, +0x8, 0x9, 0x12,0x8e,0x3e,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a, +0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8,0xbd,0xc3,0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e, +0xf0,0x1, 0xc1,0x7, 0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48, +0x11,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x8e,0x3e,0x58,0x14,0xb, 0xa0, +0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a,0x2c,0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3, +0x48,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x2, 0x80,0x6c,0x6c,0xaa,0x7c,0x9e,0x80, +0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0x9, +0x12,0x8e,0x3e,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a, +0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3,0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, +0x80,0x35,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e, +0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0x9, 0x12,0x8e,0x3e,0x58,0x14,0xb, 0xa0,0x80,0x2, +0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a,0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd8, +0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, 0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd, +0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7,0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, +0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe,0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, +0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7,0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xb8, +0x7c,0x79,0x12,0x2c,0x1, 0xbd,0x3d,0x22,0x5, 0x26,0x7e,0x35,0x24,0xb, 0x34,0x7a, +0x35,0x24,0x22,0x30,0x14,0x13,0x12,0x8f,0x8f,0x68,0x6, 0x7e,0xb3,0x3a,0x3b,0x60, +0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x39,0x41,0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b, +0x90,0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12, +0x8a,0x31,0x50,0x2, 0xd3,0x22,0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9, +0xb, 0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79,0x50,0xd9,0xc3,0x22,0xca,0xf8,0x7e,0xd4, +0x0, 0x9, 0x7e,0xb3,0x28,0x84,0x70,0x8, 0xf5,0x61,0xc2,0xa, 0xc2,0xb, 0x80,0x71, +0xbe,0xb0,0x2, 0x38,0x66,0xb4,0x2, 0x28,0x7e,0x73,0x26,0xfc,0xa, 0x27,0x7e,0x73, +0x26,0xfa,0x12,0x7d,0xff,0xbe,0x34,0x0, 0x5, 0x58,0x15,0x7e,0x73,0x26,0xfd,0xa, +0x27,0x7e,0x73,0x26,0xfb,0x12,0x7d,0xff,0xbe,0x34,0x0, 0x5, 0x58,0x2, 0x80,0x4e, +0x6c,0xff,0x80,0x30,0x7c,0xbf,0x12,0x8f,0x36,0x1a,0x4b,0x7c,0xbf,0x12,0x37,0xdc, +0x7d,0x5d,0x3e,0x54,0xbd,0x54,0x58,0x4, 0xd2,0xb, 0x80,0xa, 0x7d,0x5d,0xe, 0x54, +0xbd,0x54,0x48,0x2, 0xc2,0xb, 0x20,0xb, 0x4, 0xbd,0xd4,0x58,0x5, 0x75,0x61,0x28, +0x80,0xf, 0xb, 0xf0,0x12,0x89,0xff,0x38,0xcb,0x80,0x6, 0xe5,0x61,0x24,0xfb,0xf5, +0x61,0xe5,0x61,0xbe,0xb0,0x0, 0x8, 0x6, 0xd2,0xa, 0x15,0x61,0x80,0x5, 0x75,0x61, +0x0, 0xc2,0xa, 0xda,0xf8,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x70,0x2, 0x12,0xb4,0x6e, +0x7f,0x71,0x7c,0xbf,0x12,0x37,0xdc,0x12,0x8f,0x54,0x7f,0x17,0x12,0x1e,0x52,0x7c, +0xb7,0xda,0xf8,0x22,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x22,0xca,0xd8,0xca,0x79,0x6c, +0xff,0x6c,0xee,0x80,0xf, 0x7c,0xbe,0x12,0x8f,0x36,0x7c,0xdb,0xbc,0xfd,0x58,0x2, +0x7c,0xfd,0xb, 0xe0,0x12,0x8f,0x80,0x38,0xec,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22, +0x7e,0x73,0x28,0x84,0xbc,0x7e,0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0x7e, +0xb3,0x28,0xa8,0xbe,0xb0,0x1, 0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x22,0x7e, +0x34,0x61,0x55,0x7e,0x24,0x0, 0xff,0x22,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd, +0x32,0x22,0x12,0x9f,0xdd,0x7e,0x14,0x62,0x7, 0x12,0x8f,0xa8,0x28,0x3, 0xd2,0x16, +0x22,0xc2,0x16,0x22,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0xe8,0x8, 0xa, 0x12,0x8f, +0x5b,0xbe,0xb0,0x8, 0x48,0x2, 0xd3,0x22,0xc3,0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe, +0xa0,0xa, 0x50,0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d, +0x15,0xb, 0x14,0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22, +0x6c,0xaa,0x7e,0x63,0x2a,0x6e,0x7e,0x73,0x2a,0x6d,0xac,0x76,0x7d,0x13,0x1e,0x14, +0x7e,0x27,0x28,0x88,0x2e,0x27,0x28,0x86,0xbd,0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34, +0xbe,0x37,0x28,0x86,0x50,0x29,0x90,0x60,0x51,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e, +0xb3,0x26,0xf7,0xa, 0x3b,0xbd,0x32,0x8, 0x16,0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0, +0xa, 0x2b,0x7e,0xb3,0x26,0xf6,0xa, 0x3b,0xbd,0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c, +0xba,0x22,0x2, 0x90,0x55,0xca,0x79,0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c, +0xb4,0x12,0x96,0x8b,0x7d,0x3, 0x7e,0x70,0x9, 0xac,0x7e,0x49,0x13,0x28,0xb0,0xbe, +0x14,0x2, 0x60,0x50,0x5, 0x12,0x91,0x2f,0x40,0xb, 0xbe,0x14,0x69,0xb0,0x28,0x1f, +0x12,0x91,0x2f,0x28,0x1a,0x3e,0x4, 0xbe,0x14,0x2, 0x30,0x50,0x5, 0x12,0x91,0x2f, +0x40,0xb, 0xbe,0x14,0x69,0xe0,0x28,0x7, 0x12,0x91,0x2f,0x28,0x2, 0x3e,0x4, 0xbe, +0x4, 0x1, 0x0, 0x28,0x4, 0x7e,0x4, 0x1, 0x0, 0x74,0x9, 0xac,0xbf,0x49,0x25,0x29, +0x62,0x49,0x33,0x28,0xae,0x9d,0x32,0x12,0x20,0x30,0x12,0x91,0x3a,0x7e,0x70,0x9, +0xac,0x7f,0x49,0xf3,0x29,0x62,0x74,0x9, 0xac,0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f, +0x28,0xf, 0x7d,0x53,0x2e,0x54,0x29,0x62,0x7d,0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80, +0xd, 0xbd,0xf1,0x40,0x9, 0x2e,0x34,0x29,0x62,0x9d,0xf1,0x1b,0x38,0xf0,0x74,0x9, +0xac,0xbf,0x12,0x91,0xcc,0x12,0x91,0x3a,0x7e,0x50,0x9, 0xac,0x5f,0x49,0x32,0x29, +0x64,0x74,0x9, 0xac,0xbe,0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d,0x2, 0x2e, +0x4, 0x29,0x64,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x12,0xbd,0x31,0x40,0xe, 0x7e,0x50, +0x9, 0xac,0x5f,0x2e,0x24,0x29,0x64,0x9d,0x31,0x1b,0x28,0x30,0xda,0x79,0x22,0x74, +0x9, 0xac,0xbf,0x49,0x25,0x29,0x64,0xbd,0x12,0x22,0x7d,0x13,0x7d,0x30,0xad,0x31, +0x7c,0x76,0x7c,0x65,0xa, 0x24,0x7d,0x13,0x5d,0x1e,0x22,0xca,0x3b,0x7c,0xfb,0x6c, +0xee,0x80,0x72,0x6c,0xdd,0x80,0x16,0x74,0x9, 0xac,0xbd,0x9, 0x65,0x29,0x66,0x74, +0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb2,0xbc,0x67,0x68,0xb, 0xb, 0xd0,0x90,0x60,0x99, +0xe4,0x93,0xbc,0xbd,0x38,0xe1,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbd,0x28,0x4a,0x74, +0x9, 0xac,0xbd,0x9, 0xc5,0x29,0x66,0x12,0x91,0xcc,0x7d,0x13,0x74,0x9, 0xac,0xbd, +0x49,0x25,0x29,0x62,0x74,0x9, 0xac,0xbe,0x12,0x94,0x14,0x2d,0x31,0x7a,0x35,0x24, +0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, 0x6d,0x33,0x74,0x2, 0xac,0xbc,0x59, +0x35,0x36,0x90,0x59,0x35,0x36,0xb3,0x7e,0x35,0x24,0x7c,0xbd,0x7c,0x5e,0x7c,0x4c, +0x12,0x90,0x52,0xb, 0xe0,0xbc,0xfe,0x38,0x8a,0xda,0x3b,0x22,0x49,0x25,0x29,0x64, +0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xb0,0x9d,0x32,0x2, 0x20,0x30,0xca,0x79,0x7e, +0xf3,0x2a,0x2, 0x7e,0xe3,0x2a,0x3, 0x7c,0xbf,0x7c,0x7e,0x12,0x94,0x28,0x7c,0xbf, +0x12,0x94,0xc6,0x4c,0xee,0x78,0x14,0x12,0x94,0x1d,0xca,0x59,0x7e,0x18,0x28,0xae, +0x7e,0x8, 0x29,0x62,0x12,0x1f,0xc9,0x1b,0xfd,0x80,0xb, 0x7e,0xb3,0x2a,0x9, 0x70, +0x5, 0x7c,0xbf,0x12,0x91,0x4b,0x7c,0xbf,0x12,0x96,0xdb,0xbe,0xf0,0x0, 0x28,0x6, +0x74,0x1, 0x7a,0xb3,0x2a,0xb, 0xda,0x79,0x22,0x7e,0xb3,0x3, 0xee,0x70,0x3, 0x12, +0x92,0x35,0x2, 0x91,0xdd,0xca,0x3b,0x6d,0x11,0x7e,0xe3,0x2a,0x2, 0x7e,0xb3,0x2a, +0xd, 0xb4,0x1, 0x4, 0x74,0x64,0x80,0xa, 0x7e,0xb3,0x37,0x36,0xbe,0xb0,0x0, 0x28, +0x5, 0x14,0x7a,0xb3,0x37,0x36,0x4c,0xee,0x78,0x27,0x6c,0xff,0x80,0x1a,0x74,0x2, +0xac,0xbf,0x12,0x94,0x3, 0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x36,0xcc,0x74,0x2, +0xa, 0x3f,0x19,0xb3,0x37,0x37,0xb, 0xf0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x38, +0xdd,0x12,0x96,0x4f,0x7e,0x24,0x0, 0x14,0xad,0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20, +0x6c,0xff,0x61,0xdc,0x74,0x9, 0xac,0xbf,0x9, 0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0x90, +0x60,0x99,0xe4,0x93,0xbc,0xbd,0x38,0x2, 0x61,0xda,0xa, 0x1d,0x9, 0xb1,0x29,0xbc, +0xbe,0xb0,0x1, 0x78,0x2, 0x61,0xc0,0x75,0x24,0x0, 0x61,0xb2,0x7e,0xa1,0x24,0x74, +0x9, 0xa4,0x9, 0xc5,0x36,0xcc,0xbc,0xcd,0x68,0x2, 0x61,0xb0,0x49,0x25,0x36,0xca, +0x74,0x9, 0xac,0xbf,0x12,0x91,0xd4,0x7d,0x3, 0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49, +0x25,0x36,0xc8,0x74,0x9, 0xac,0xbf,0x12,0x94,0x14,0x2d,0x3, 0xa, 0x1c,0x9, 0xa1, +0x37,0x37,0xbe,0xa0,0x0, 0x28,0x1d,0x7e,0x30,0x2, 0xac,0x3c,0x59,0x1, 0x37,0x22, +0xa, 0x1c,0x2e,0x14,0x37,0x37,0x7c,0xba,0x14,0x7a,0x19,0xb0,0x7e,0xb3,0x37,0x36, +0x70,0x2, 0x61,0xda,0x74,0x2, 0xac,0xbc,0x49,0x15,0x37,0x22,0xbe,0x14,0x0, 0x32, +0x28,0x8, 0x7d,0x31,0x2d,0x34,0xbd,0x30,0x40,0x20,0xbe,0x14,0x0, 0x32,0x28,0x8, +0xbe,0x4, 0x0, 0x32,0x28,0x2, 0x80,0x72,0x7d,0x31,0x2e,0x34,0x0, 0x32,0xbd,0x30, +0x50,0x8, 0xbe,0x14,0x0, 0x32,0x28,0x2, 0x80,0x60,0xbe,0x4, 0x0, 0xa0,0x28,0x56, +0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0x70,0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, 0xa, 0x1d, +0x19,0xb1,0x29,0xbc,0x74,0x3, 0xa, 0x1c,0x19,0xb1,0x29,0xc6,0xbe,0xe0,0x0, 0x28, +0x69,0x1b,0xe0,0x7e,0x70,0x9, 0xac,0x7f,0x2e,0x34,0x28,0xae,0x7e,0x14,0x1f,0x34, +0x74,0x9, 0x12,0x1e,0x86,0x7e,0x70,0x9, 0xac,0x7e,0x12,0x96,0x47,0xac,0x3f,0x12, +0x94,0xb, 0x7e,0x34,0x1f,0x34,0x7e,0x30,0x9, 0xac,0x3e,0x12,0x94,0xb, 0x1b,0xf0, +0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74,0x2, 0xac,0xbc,0x59,0x5, 0x37,0x22,0x80,0x2a, +0x5, 0x24,0x90,0x60,0x99,0xe4,0x93,0xbe,0xb1,0x24,0x28,0x2, 0x41,0xbc,0x80,0x1a, +0x6d,0x11,0x74,0x2, 0xac,0xbd,0x12,0x94,0x3, 0x7e,0x30,0x9, 0xac,0x3d,0x19,0xa1, +0x36,0xcc,0x74,0x2, 0xa, 0x1d,0x19,0xb1,0x37,0x37,0xb, 0xf0,0xbc,0xef,0x28,0x2, +0x41,0x94,0xe4,0x7a,0xb3,0x16,0x92,0x90,0x60,0x99,0x12,0x94,0x21,0xca,0x59,0x7e, +0x18,0x28,0xae,0x7e,0x8, 0x36,0xc8,0x12,0x1f,0xc9,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, +0xda,0x3b,0x22,0x59,0x15,0x37,0x22,0x7e,0xa0,0xff,0x22,0x2e,0x14,0x28,0xae,0x74, +0x9, 0x2, 0x1e,0x86,0x49,0x35,0x28,0xae,0x9d,0x32,0x2, 0x20,0x30,0x90,0x60,0x99, +0xe4,0x93,0x7c,0xab,0x74,0x9, 0xa4,0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17, +0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0xe4,0x7a,0xb3,0x2a,0x9, +0x7a,0xb3,0x2a,0xa, 0x2, 0x94,0xa1,0xa5,0xbe,0x0, 0x21,0x6c,0xaa,0x80,0xe, 0x7e, +0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62,0x29,0x66,0xb, 0xa0,0x90,0x60,0x99, +0xe4,0x93,0xbc,0xba,0x38,0xe9,0x74,0x1, 0x7a,0xb3,0x2a,0x6, 0x6c,0xaa,0x80,0x20, +0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0x94,0x95,0x1b,0x18,0x20,0x7e, +0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0x94,0x95,0x1b,0x18,0x20,0xb, 0xa0, +0xbc,0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x22,0x12,0x94,0xba,0x7e,0x8, 0x36,0xb3,0xe4,0x12,0x1f,0xee,0x90,0x60,0x99,0x12, +0x94,0xbe,0x7e,0x8, 0x36,0x90,0xe4,0x2, 0x1f,0xee,0x90,0x60,0x99,0xe4,0x93,0x7c, +0x7b,0x74,0x2, 0xac,0x7b,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x60,0x99,0xe4, +0x93,0x7c,0xfb,0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, +0x1f,0x38,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x34,0x74,0x9, +0xac,0xb1,0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c, +0x6d,0x12,0x96,0x3d,0x7c,0x7d,0x7c,0x6f,0x12,0x96,0x3d,0x6c,0x0, 0x80,0x39,0x6c, +0xee,0x80,0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38,0x74,0x9, 0xac,0xb0,0x9, +0x75,0x28,0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78, +0x15,0x7e,0x70,0x9, 0xac,0x70,0x12,0x96,0x47,0xac,0x31,0x2e,0x14,0x1f,0x34,0x74, +0x9, 0x12,0x1e,0x86,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf, +0xca,0x59,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12,0x1f,0xc9,0x1b,0xfd,0xda, +0x79,0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0xc1,0x23,0x7c,0x57, +0xc1,0x1b,0x7e,0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66,0x7c,0x98,0x7e,0xd0,0x9, +0xac,0xd5,0x9, 0xb6,0x28,0xb2,0xbc,0xb9,0x68,0x2, 0xc1,0x19,0xbe,0x90,0xff,0x78, +0x2, 0xc1,0x19,0x12,0x96,0x33,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x29,0xbc, +0x7e,0xf0,0x9, 0x70,0xc, 0xac,0xf5,0x7d,0x97,0x2e,0x94,0x28,0xae,0x6d,0x88,0x80, +0xa, 0xac,0xf6,0x7d,0x97,0x2e,0x94,0x29,0x62,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x96, +0x33,0x1b,0x7a,0xd0,0x69,0xf4,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d, +0xd7,0x79,0xf6,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb3,0x12,0x96, +0x33,0x39,0x87,0x0, 0x5, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb4,0x12,0x96, +0x33,0x39,0x87,0x0, 0x6, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb5,0x12,0x96, +0x33,0x39,0x87,0x0, 0x7, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb6,0x12,0x96, +0x33,0x39,0x87,0x0, 0x8, 0xb, 0xa0,0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0xa1, +0x72,0xb, 0x60,0x90,0x60,0x99,0xe4,0x93,0xbc,0xb6,0x28,0x2, 0xa1,0x6e,0x7c,0xba, +0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x70,0x2d,0xf7,0x22,0x7e,0x8, 0x1f, +0x34,0x12,0x95,0x64,0x7c,0x1b,0x22,0x2e,0x34,0x28,0xae,0x7e,0x30,0x9, 0x22,0x7e, +0x73,0x2a,0x3, 0xbe,0x73,0x2a,0x2, 0x78,0x17,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, +0x40,0xe, 0x7e,0x37,0x36,0xa4,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, +0x7e,0x37,0x36,0xa4,0x1e,0x34,0x7a,0x37,0x36,0xa4,0x7e,0xb3,0x2a,0x2, 0x70,0x6, +0x6d,0x33,0x7a,0x37,0x36,0xa4,0x7e,0x37,0x36,0xa4,0x22,0xca,0xf8,0x7c,0xfb,0x7d, +0xf3,0x7e,0x17,0x2a,0x62,0xbd,0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d, +0x22,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x1d,0xff,0xbe,0x34,0x0, 0x10,0x50,0x4, +0x7e,0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf,0x49,0x25,0x36,0xb3,0xbd,0x2f,0x28,0x6, +0x49,0x35,0x36,0x90,0x80,0x4, 0x59,0x35,0x36,0x90,0x59,0xf5,0x36,0xb3,0xbe,0x34, +0x1, 0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, 0xda,0xf8,0x22,0x6c,0xaa,0x80,0x63,0x7e, +0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x62,0x12,0x24,0xc7,0x59,0x32,0x28,0xae,0x7e, +0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x64,0x12,0x24,0xc7,0x59,0x32,0x28,0xb0,0x7e, +0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x66,0x19,0xb4,0x28,0xb2,0x7e,0x90,0x9, 0xac, +0x9a,0x9, 0xb4,0x29,0x67,0x19,0xb4,0x28,0xb3,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4, +0x29,0x68,0x19,0xb4,0x28,0xb4,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x69,0x19, +0xb4,0x28,0xb5,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x6a,0x19,0xb4,0x28,0xb6, +0xb, 0xa0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba,0x38,0x94,0x22,0x7e,0xb3,0x2a,0x2, +0x70,0x29,0x12,0x97,0x85,0x28,0x24,0x7e,0xb3,0x36,0xc7,0x70,0x18,0x12,0x97,0x8d, +0x7e,0x73,0x2a,0x3, 0x7a,0x73,0x2a,0x2, 0x74,0x1, 0x7a,0xb3,0x2a,0x9, 0x7e,0xb3, +0x36,0xc7,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x36,0xc7,0x22,0xe4,0x7a,0xb3,0x36,0xc7, +0x7a,0xb3,0x2a,0x9, 0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x22,0x7e,0x34,0x0, +0x3c,0xca,0x39,0x7e,0x18,0x38,0x69,0x7e,0x8, 0x38,0xa5,0x12,0x1f,0xc9,0x1b,0xfd, +0x7e,0x73,0x28,0x94,0x7a,0x73,0x38,0x68,0x7a,0x73,0x28,0x93,0x22,0x12,0x97,0x85, +0x28,0x8, 0x7e,0xb3,0x28,0x84,0x70,0x2, 0xf5,0x5d,0x7e,0xb3,0x28,0x84,0x70,0x18, +0xe5,0x5d,0xbe,0xb0,0xfa,0x50,0x2, 0x5, 0x5d,0xe5,0x5d,0xbe,0xb0,0x5, 0x40,0x8, +0xe4,0x7a,0xb3,0x2, 0xe9,0x75,0x5d,0xfa,0x22,0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, +0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x36,0xa7,0xbe,0x73,0x36,0xb1,0x50,0xe, 0x7d, +0x24,0x2e,0x24,0x36,0xa7,0x7c,0xb7,0x4, 0x7a,0x29,0xb0,0xd3,0x22,0xbe,0x73,0x36, +0xb1,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, 0xe4,0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4, +0x36,0xa7,0x80,0x17,0xa, 0x3a,0x9, 0xb3,0x36,0xa7,0xbe,0xb0,0xff,0x68,0x7, 0xe4, +0x19,0xb3,0x36,0xa7,0xd3,0x22,0xe4,0x19,0xb3,0x36,0xa7,0xc3,0x22,0xe4,0x7a,0xb3, +0x37,0x6c,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0xe5,0x60,0x5, 0xe4,0x7a, +0xb3,0x37,0xe7,0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12,0x9b,0x75,0x28,0x35, +0x6d,0x22,0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x98,0x8d,0xbe,0x37,0x7, +0xfa,0x8, 0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, 0x70,0x17,0x7e,0xb3, +0x3, 0xc5,0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x62,0xe5,0x62,0xbe,0xb0,0x10,0x28,0x5, +0xd2,0x15,0x75,0x62,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x62,0x0, 0x22,0x7e,0x24,0x0, +0x2, 0x2, 0x1d,0xb3,0x7e,0x90,0x1, 0x7e,0x94,0x61,0xc0,0x7e,0x84,0x0, 0xff,0xb, +0x4a,0x30,0x7a,0x37,0x28,0xa1,0x7e,0xb4,0x61,0xc2,0x7e,0xa4,0x0, 0xff,0xb, 0x5a, +0x30,0x7a,0x37,0x28,0xa3,0x12,0x8f,0x9f,0xb, 0x1a,0x20,0x7e,0x14,0x61,0x4f,0x7e, +0x4, 0x0, 0xff,0xb, 0xa, 0xd0,0xe4,0x7a,0xb3,0x28,0xac,0x12,0x67,0xef,0x7e,0x34, +0xff,0xfa,0xad,0x32,0x12,0x98,0x8d,0x7d,0xc3,0xe, 0x34,0x7e,0x27,0x7, 0xfe,0xbd, +0x2c,0x58,0x1c,0x7e,0xc7,0x7, 0xfc,0xbd,0xc3,0x58,0x14,0x6d,0xcc,0x9e,0xc7,0x2a, +0x5a,0xbe,0xc7,0x28,0x8e,0x8, 0x8, 0x12,0x9d,0xa4,0x60,0x3, 0x12,0x9d,0xb1,0x12, +0x9d,0xc0,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12,0x8f,0x8f,0x68,0x6, 0x7e,0xb3, +0x3a,0x3b,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x7b,0x7e,0x83,0x28,0x84,0xbe, +0x80,0x0, 0x28,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x30,0x14,0x5, 0xe4,0x7a,0xb3,0x28, +0xad,0x12,0x9d,0xfe,0x50,0xa, 0x12,0x67,0xef,0x12,0x9a,0x18,0x7c,0x9b,0x80,0x1b, +0x7e,0xb3,0x26,0x84,0x70,0x15,0x7e,0xb3,0x26,0x85,0x70,0xf, 0x7e,0x83,0x28,0x84, +0xbe,0x80,0x0, 0x28,0x6, 0x7e,0x90,0x3, 0x12,0x67,0xef,0x7e,0xc7,0x7, 0xfa,0xbe, +0xc4,0x5, 0xdc,0x8, 0x1b,0x7e,0x83,0x28,0x84,0xbe,0x80,0x0, 0x28,0x12,0x6d,0xcc, +0x9d,0xcd,0xbe,0xc7,0x28,0x8e,0x58,0x8, 0x12,0x9a,0xa, 0xe4,0x7a,0xb3,0x28,0xad, +0xa, 0x29,0xb, 0x4a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa1,0xa, 0x29,0xb, 0x5a,0x30, +0xad,0x32,0x7a,0x37,0x28,0xa3,0x12,0x0, 0x6e,0x50,0xd, 0xe4,0x7a,0xb3,0x28,0xad, +0x12,0x8f,0x87,0x28,0x3, 0x12,0x9a,0xa, 0x7e,0xc7,0x28,0x8a,0xbd,0xcd,0x8, 0x1f, +0x7e,0x24,0x0, 0x2, 0x7d,0x3d,0x12,0x1d,0xb3,0x6e,0x34,0xff,0xff,0xb, 0x34,0xbe, +0x37,0x28,0x8e,0x58,0xa, 0x12,0x0, 0x6e,0x50,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12, +0x9a,0x84,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x9b,0x7d,0x7e,0xb3,0x0, +0x66,0xbe,0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x0, 0x66,0x70,0x1c,0xe4,0x7a,0xb3, +0x28,0xad,0x74,0x1, 0x7a,0xb3,0x28,0xac,0xe4,0x7a,0xb3,0x16,0x91,0x7a,0xb3,0x16, +0x90,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x26,0x83,0x22,0xe4,0x7a,0xb3,0x0, 0x66,0x7a, +0xb3,0x28,0xac,0x74,0x2, 0x2, 0x29,0xbb,0x7e,0xa0,0x1, 0x7e,0x47,0x7, 0xf8,0x12, +0x8f,0x9f,0xb, 0x1a,0x0, 0x7e,0x34,0xff,0xfa,0xad,0x30,0x7e,0x14,0x0, 0x2, 0x12, +0x9a,0x7c,0x8, 0x12,0x7e,0xb3,0x28,0xac,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80, +0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x12,0x9a,0x7c,0x8, +0x5, 0x7e,0xa0,0x4, 0x80,0x23,0x7e,0x34,0xff,0xfc,0xad,0x30,0x12,0x9a,0x7c,0x8, +0x5, 0x7e,0xa0,0x3, 0x80,0x13,0x7e,0x34,0xff,0xfd,0xad,0x30,0x12,0x9a,0x7c,0x8, +0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7d,0x21,0x12,0x1d, +0xb3,0xbd,0x34,0x22,0xca,0x3b,0x12,0x9b,0x75,0x38,0x2, 0x61,0x4b,0x7e,0xc3,0x0, +0x69,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x0, 0x69,0xe4,0x7a,0xb3,0x0, 0x6b,0x6c,0xaa, +0x80,0x26,0x12,0x9b,0x56,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3,0x26,0xfa,0x9, 0xe3, +0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12, +0x9b,0x60,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xd2, +0x80,0x7f,0x7c,0xfc,0x6c,0xaa,0x80,0x35,0x12,0x9b,0x56,0x7e,0x49,0xd0,0x9, 0xe4, +0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1f,0x12,0x9b,0x60,0x7d, +0x23,0x49,0x34,0x0, 0x2, 0x9d,0x32,0x12,0x20,0x30,0x7d,0xf3,0xbe,0xf4,0x0, 0x23, +0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x63,0x1, 0xb, 0xa0,0xbc,0xfa,0x38, +0xc7,0x4c,0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x0, 0x6b,0xbe,0x70,0x4, 0x40,0x22, +0x6c,0xaa,0x80,0xe, 0x12,0x9b,0x56,0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, +0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x63,0x0, 0x12,0x9b,0x67, +0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3,0x0, 0x6b,0x80,0x6, 0x12,0x9b,0x67,0x75,0x63, +0x0, 0xe5,0x63,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x0, 0x6c,0x22, +0x7c,0xbd,0x7c,0x7e,0x2, 0x2c,0x1, 0xe4,0x7a,0xb3,0x0, 0x6a,0x7a,0xb3,0x0, 0x69, +0x7a,0xb3,0x0, 0x6b,0x22,0x7e,0xb3,0x28,0x84,0xbe,0xb0,0x0, 0x22,0x7e,0x60,0x4, +0x7e,0x27,0x3a,0x34,0xbe,0x24,0x3, 0xe8,0x28,0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x28, +0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x0, 0x67,0xbc,0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x28, +0xad,0x12,0x9a,0xa, 0x7e,0xb3,0x0, 0x67,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a, +0xb3,0x0, 0x67,0x7e,0xb3,0x28,0xad,0xb4,0x1, 0x17,0x7e,0xa3,0x0, 0x68,0xbe,0xa0, +0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad,0x7c,0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80, +0x1, 0xe4,0x7a,0xb3,0x0, 0x68,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6c,0xdd,0x7e, +0x57,0x28,0x99,0x7d,0xf5,0x7e,0xe7,0x28,0x97,0x7e,0x37,0x39,0x41,0x4d,0x33,0x68, +0x4, 0x7d,0xf5,0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x2a,0x6e,0x7c,0x8a,0x7e,0xb3,0x28, +0xa5,0x14,0x68,0x21,0x14,0x68,0x14,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0x16,0x24, +0x45,0x78,0x10,0x7c,0xfa,0x7e,0x83,0x2a,0x6d,0x80,0xa, 0x7e,0x73,0x2a,0x6d,0x2c, +0x87,0x80,0x2, 0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c,0xb9,0x12,0x37,0xdc,0xbe,0x34, +0x2, 0x58,0x8, 0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33,0x28,0x84,0xbc,0x39,0x38,0xe9, +0xbe,0xd0,0x3, 0x40,0x2, 0xa1,0x98,0x7e,0xa3,0x28,0x85,0xbe,0xa0,0x0, 0x38,0xb, +0xbe,0x30,0x0, 0x28,0x37,0x7e,0xb3,0x26,0x83,0x70,0x31,0x6c,0x99,0x80,0x29,0xa, +0x29,0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, 0x7a,0xbd,0x2f,0x8, 0x17,0x49, +0x3, 0x4, 0xfc,0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d,0x3e,0x12,0x98,0x8d,0xbd,0x3, +0x8, 0x4, 0xd2,0x0, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xd3,0x6d,0xee,0x9e,0xe7, +0x2a,0x4f,0xbe,0xe7,0x7, 0xf8,0x8, 0x2, 0xc2,0x0, 0x30,0x0, 0x20,0x7e,0xb3,0x3a, +0x3b,0x4, 0x7a,0xb3,0x3a,0x3b,0x7e,0x23,0x3a,0x3b,0xbe,0x20,0xa, 0x28,0x1d,0x74, +0xa, 0x7a,0xb3,0x3a,0x3b,0x74,0x1, 0x7a,0xb3,0x28,0xa8,0x80,0xf, 0x7e,0x23,0x3a, +0x3b,0xbe,0x20,0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23,0x3a,0x3b,0x6c,0xee,0xbe,0x30, +0x0, 0x38,0x5, 0xbe,0xa0,0x0, 0x28,0x69,0x7e,0xb3,0x28,0xa7,0xb4,0x1, 0x9, 0x7e, +0xb3,0x28,0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x52,0x6c, +0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x26,0xfa,0x9, 0xd3,0x26,0xfb, +0x12,0x9d,0x9d,0xbe,0x34,0x0, 0x96,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90, +0x7e,0xb3,0x28,0x84,0xbc,0xb9,0x38,0xdb,0x6c,0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac, +0x79,0x9, 0xa3,0x27,0x36,0x9, 0xd3,0x27,0x37,0x12,0x9d,0x9d,0xbe,0x34,0xff,0x6a, +0x58,0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x28,0x85,0xbc,0xb9,0x38, +0xdb,0x6c,0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d,0x5e,0x3e,0x54,0x49,0x55,0x5, +0x7a,0xbd,0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xe5, +0x4c,0xee,0x78,0x25,0x7e,0xb3,0x3a,0x3c,0x4, 0x7a,0xb3,0x3a,0x3c,0x7e,0x73,0x3a, +0x3c,0xbe,0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3,0x3a,0x3c,0x7e,0xb3,0x28,0xa8, +0x60,0x2, 0xd2,0x18,0x12,0x9d,0xa7,0x80,0xf, 0x7e,0x73,0x3a,0x3c,0xbe,0x70,0x0, +0x28,0x6, 0x1e,0x70,0x7a,0x73,0x3a,0x3c,0xda,0x79,0xda,0xd8,0x22,0x7c,0xba,0x7c, +0x7d,0x2, 0x2c,0x1, 0x74,0x1, 0x22,0xe4,0x7a,0xb3,0x28,0xa8,0x7a,0xb3,0x3a,0x3b, +0x22,0x74,0x2, 0x7a,0xb3,0x0, 0x66,0x74,0x1, 0x7a,0xb3,0x28,0xac,0x2, 0x29,0xba, +0xd2,0x0, 0x6c,0xaa,0x6c,0x77,0x80,0x1f,0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xa, 0x27, +0x2d,0x21,0x7c,0x65,0x7e,0x50,0x2, 0xac,0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe, +0xc, 0x58,0x2, 0xb, 0xa0,0xb, 0x70,0x7e,0xb3,0x2a,0x6d,0xbc,0xb7,0x38,0xd9,0xa, +0x2b,0x1e,0x24,0xa, 0x3a,0xbd,0x32,0x8, 0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0xc2,0x0, +0x7e,0xa3,0x2a,0x70,0x7e,0xb3,0x26,0xf1,0x60,0x4, 0xd2,0x0, 0x80,0x33,0x7e,0x70, +0x2, 0x80,0x22,0x7e,0x50,0x2, 0xac,0x57,0x49,0x12,0x4, 0xfc,0x7e,0xf4,0x61,0x59, +0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, 0x6d,0x22,0x9d,0x20,0xbd,0x12,0x58,0x4, 0xd2, +0x0, 0x80,0xe, 0xb, 0x70,0xa, 0x1a,0x9e,0x14,0x0, 0x3, 0xa, 0x27,0xbd,0x21,0x48, +0xd2,0xa2,0x0, 0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12,0x37,0xdc,0xbe, +0x34,0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38, +0xe9,0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb, +0x7f,0x70,0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x22,0x71,0x7e,0x24,0x0, 0xff, +0x7e,0x14,0x1f,0x34,0x74,0xc, 0x12,0x1e,0xa7,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c, +0xee,0x80,0x13,0x12,0x9f,0x7d,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, +0x28,0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, +0x7e,0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0xe1,0x65,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, +0xd2,0x0, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1f,0x34,0xbd,0x4d,0x58,0x6, +0x49,0xd5,0x1f,0x36,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, +0x78,0x4, 0x6d,0x33,0x80,0x7f,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xd0,0x9f, +0x55,0x6c,0xee,0x80,0xb, 0x12,0x9f,0x7d,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0, +0xbc,0xfe,0x38,0xf1,0xa, 0x1f,0x12,0x9f,0x73,0x9f,0x55,0x6c,0xee,0x80,0x1d,0x12, +0x9f,0x6a,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x20,0x30,0x7d,0xc3,0xbd,0x1c,0x28,0xa, +0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xdf, +0x6d,0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0x9f,0x73,0xbd,0x1d,0x8, 0x4, +0x7d,0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c,0xee, +0x80,0xd, 0x12,0x9f,0x6a,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc, +0xfe,0x38,0xef,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17, +0x2d,0x35,0x22,0x6d,0x0, 0x7f,0x15,0x12,0x1e,0x52,0x7d,0x13,0x22,0x74,0x2, 0xac, +0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x20,0x30,0x7e,0xb3,0x2b,0x1d,0xb4, +0x1, 0x31,0x12,0x9f,0xc4,0x7e,0x1f,0x33,0xfb,0x7a,0x37,0x24,0xfa,0x7e,0x34,0xd, +0xc8,0x7a,0x37,0x24,0xf6,0x12,0x9f,0xcb,0x12,0x9f,0xd4,0xe4,0x7a,0xb3,0x24,0xf5, +0x7e,0x34,0x0, 0x20,0x7a,0x37,0x24,0xfc,0x7a,0xb3,0x24,0xf4,0x7e,0x8, 0x24,0xf2, +0x2, 0xb, 0x7e,0x22,0xa9,0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0x73,0x2a,0x6d,0x7a, +0x73,0x24,0xf2,0x22,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x6d,0x11,0xe4, +0x12,0x0, 0x1e,0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x3a,0x23, +0x2d,0xf0,0x69,0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d,0x32,0x12,0x20,0x30,0xbd, +0x31,0x28,0x16,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x3a,0x23,0x2d,0x13,0x69,0x20, +0x1, 0x0, 0x69,0x30,0x0, 0x80,0x12,0xa0,0x4d,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f, +0x3a,0x23,0x2d,0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14, +0x7f,0xff,0x69,0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff, +0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x9d,0x7d,0x31,0x22,0x9d,0x32,0x12, +0x20,0x30,0x7d,0x13,0x22,0x6c,0xaa,0x80,0x26,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12, +0x5, 0xf8,0x49,0x32,0x4, 0x0, 0x2d,0x31,0x59,0x32,0x5, 0xf8,0x30,0x6, 0xe, 0x49, +0x12,0x4, 0x7e,0x49,0x32,0x6, 0x76,0x2d,0x31,0x59,0x32,0x6, 0x76,0xb, 0xa0,0x7e, +0xb3,0x2a,0x74,0xa, 0x3b,0x7e,0xb3,0x2a,0x73,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd, +0x32,0x48,0xc6,0x22,0x7e,0xb3,0x37,0xfb,0xb4,0x1, 0x3, 0x2, 0xa0,0xeb,0x7e,0xb3, +0x38,0x61,0x4, 0x7a,0xb3,0x38,0x61,0x7e,0xb3,0x37,0xef,0xb4,0x2, 0x18,0x7e,0xb3, +0x38,0x60,0x4, 0x7a,0xb3,0x38,0x60,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x38,0x61, +0x74,0x1, 0x7a,0xb3,0x37,0xef,0x7e,0x73,0x38,0x60,0xbe,0x70,0x3, 0x40,0xf, 0x74, +0x1, 0x7a,0xb3,0x37,0xfb,0x12,0xa0,0xeb,0x12,0xa1,0xc9,0x12,0xa0,0xf2,0x7e,0x73, +0x38,0x61,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0xa0,0xf2,0x22,0x74,0x2, 0x7a,0xb3,0x37, +0xef,0x22,0xe4,0x7a,0xb3,0x38,0x61,0x7a,0xb3,0x38,0x60,0x22,0x7e,0x73,0x37,0xef, +0x7a,0x73,0x38,0x65,0x7e,0x27,0x33,0xf8,0x12,0x67,0x8d,0x1e,0x34,0xbd,0x32,0x50, +0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xef,0x12,0x67,0x8d,0xbd,0x32,0x50,0x8, 0xe4,0x7a, +0xb3,0x37,0xed,0x12,0xa0,0xeb,0x7e,0x37,0x37,0xf5,0xbd,0x32,0x50,0x4, 0x7a,0x27, +0x37,0xf5,0x12,0xa4,0xc0,0x38,0xa, 0x12,0xa4,0xb8,0x38,0x5, 0x12,0xa4,0xb0,0x28, +0x39,0x12,0xa0,0x94,0x12,0x67,0x8d,0x1e,0x34,0x1e,0x34,0xbd,0x32,0x28,0x21,0x7e, +0xb3,0x37,0xed,0x4, 0x7a,0xb3,0x37,0xed,0x7e,0x73,0x37,0xed,0xbe,0x70,0x32,0x28, +0x14,0x74,0x32,0x7a,0xb3,0x37,0xed,0x12,0xa2,0x3b,0x7a,0xb3,0x38,0x62,0x80,0x5, +0xe4,0x7a,0xb3,0x37,0xed,0x7d,0x32,0x2, 0xa7,0xf6,0x2, 0xa1,0x7d,0x12,0xa0,0xf2, +0xe4,0x7a,0xb3,0x37,0xfb,0x22,0x12,0xa0,0xfc,0x2, 0xa1,0x8c,0x7e,0xb3,0x37,0xef, +0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xf7,0x7e,0xb3,0x38,0x65,0x70,0x3, 0x12,0xa1, +0xc9,0x7e,0xb3,0x37,0xf7,0xb4,0x1, 0xc, 0x74,0x3, 0x12,0xa1,0xc0,0x12,0x23,0x29, +0x3e,0x34,0x80,0x7, 0xe4,0x12,0xa1,0xc0,0x12,0x23,0x29,0x7a,0x37,0x2a,0x62,0x22, +0x7a,0xb3,0x36,0xb2,0x7e,0x34,0x61,0x5b,0x22,0xe4,0x7a,0xb3,0x37,0xed,0x6c,0xaa, +0x80,0xd, 0x6d,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x38,0x4, 0xb, 0xa0,0x12, +0xa2,0x80,0x38,0xee,0xe4,0x7a,0xb3,0x37,0xee,0x6d,0x33,0x7a,0x37,0x37,0xf5,0x7a, +0x37,0x37,0xea,0x22,0x7e,0xb3,0x37,0xec,0x60,0x6, 0x14,0x7a,0xb3,0x37,0xec,0x22, +0x12,0xa2,0x45,0x90,0x61,0xc5,0xe4,0x93,0xbe,0xb0,0x4, 0x28,0x3, 0x12,0x4f,0x48, +0x7e,0xb3,0x3, 0xa9,0x70,0xe, 0x7e,0xb3,0x3a,0x41,0xb4,0x1, 0x7, 0xe4,0x12,0x4d, +0xf4,0x12,0xa2,0x3b,0x12,0xa1,0x86,0x12,0xa3,0x1, 0x7e,0xa3,0x3, 0xa9,0x7a,0xa3, +0x3a,0x41,0xbe,0xb0,0xff,0x68,0x3, 0x2, 0x4d,0xf4,0x22,0xe4,0x7a,0xb3,0x37,0xef, +0x7a,0xb3,0x37,0xf7,0x22,0x7e,0x37,0x33,0xf4,0x12,0x24,0xc7,0x7a,0x37,0x38,0x63, +0x6c,0xaa,0x80,0x23,0x12,0xa2,0x80,0x28,0x26,0xa, 0x4a,0x9, 0x64,0x37,0xfc,0xbc, +0x6b,0x50,0x12,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42,0x33,0xee,0x7e,0x70,0xc, 0xac, +0x67,0x59,0x43,0x38,0x6, 0xb, 0xa0,0x7e,0xb3,0x37,0xf9,0xbc,0xba,0x38,0xd5,0x22, +0x90,0x61,0xc5,0xe4,0x93,0xbc,0xba,0x22,0x12,0xa2,0x45,0x6d,0x33,0x7a,0x37,0x38, +0x63,0x6c,0xaa,0x80,0x5, 0x12,0xa2,0xf3,0xb, 0xa0,0x12,0xa2,0x80,0x38,0xf6,0xe4, +0x7a,0xb3,0x37,0xf8,0x22,0x6c,0xaa,0x80,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x12,0xa4, +0xd2,0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0xa2,0xf3,0x80,0x2f,0x7e,0x50,0xc, 0xac, +0x5a,0x49,0x32,0x38,0xa, 0x49,0x12,0x38,0x6, 0xbd,0x13,0x28,0xf, 0x7d,0x2, 0x2e, +0x4, 0x38,0xa, 0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, 0xbe,0x34,0x0, 0x2, +0x28,0x9, 0x2e,0x24,0x38,0xa, 0x1b,0x35,0x1b,0x28,0x30,0xb, 0xa0,0x12,0xa2,0x80, +0x38,0xb7,0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x38,0x6, 0x59,0x32,0x38,0xa, +0x22,0xca,0xd8,0xca,0x79,0x7e,0xe0,0xff,0x12,0xa5,0x6a,0x7e,0xb3,0x37,0xf1,0xb4, +0x1, 0x8, 0x12,0x67,0x7, 0xe4,0x7a,0xb3,0x37,0xf1,0x7e,0xb3,0x37,0xf0,0x60,0x4, +0x74,0xff,0x81,0x24,0x7e,0xb3,0x37,0xef,0xb4,0x2, 0x2, 0x80,0x2, 0x81,0x18,0x12, +0xa4,0xc0,0x38,0xc, 0x12,0xa4,0xb8,0x38,0x7, 0x12,0xa4,0xb0,0x38,0x2, 0x81,0x18, +0x12,0xa6,0x8b,0xa, 0x3d,0x1b,0x34,0xbe,0x34,0x0, 0x3, 0x48,0x4, 0x74,0x3, 0x80, +0x3, 0x7c,0xbd,0x14,0x12,0xa4,0x29,0x7c,0xfb,0x7e,0xb3,0x37,0xee,0x4, 0x7a,0xb3, +0x37,0xee,0x90,0x61,0xc5,0xe4,0x93,0x14,0x12,0xa4,0x29,0x7c,0xab,0xbe,0xa0,0xff, +0x68,0x2c,0xbe,0xf0,0xff,0x68,0x25,0x7e,0x30,0xc, 0xac,0x3f,0x49,0x21,0x38,0x4, +0x7e,0xf4,0x61,0xcc,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x30,0xbd,0x23,0x28,0xf, 0x12, +0xa4,0xc8,0x3e,0x34,0xbd,0x23,0x28,0x6, 0x7c,0xfa,0x80,0x2, 0x7c,0xfa,0xbe,0xf0, +0xff,0x78,0x11,0xe4,0x7a,0xb3,0x37,0xee,0x7a,0xb3,0x37,0xef,0x7a,0xb3,0x37,0xfb, +0x74,0xff,0x80,0x70,0x90,0x61,0xd4,0xe4,0x93,0xbe,0xb3,0x37,0xee,0x50,0x59,0x74, +0xc, 0xac,0xbf,0x49,0x25,0x38,0x4, 0x7e,0x14,0x61,0xcc,0x12,0x67,0x91,0xbd,0x23, +0x50,0x3d,0x7e,0x34,0x61,0xd0,0x12,0x23,0x29,0xbe,0x37,0x37,0xea,0x40,0xd, 0x7e, +0x34,0x61,0xd2,0x12,0x23,0x29,0xbe,0x37,0x37,0xf5,0x50,0x23,0x74,0x5, 0xac,0xbf, +0x9, 0x75,0x26,0x33,0xbe,0x73,0x2b,0xf, 0x68,0x15,0x7c,0xef,0xbe,0xe0,0x4, 0x50, +0x8, 0x12,0xa4,0xdf,0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xf1,0xe4, +0x7a,0xb3,0x37,0xfb,0x7a,0xb3,0x37,0xef,0xbe,0xe0,0xff,0x68,0x5, 0xe4,0x7a,0xb3, +0x37,0xee,0x7c,0xbe,0xda,0x79,0xda,0xd8,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c, +0x22,0x80,0x2a,0x12,0xa4,0xa2,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0xa4,0xd2, +0x7d,0x23,0x7e,0x70,0xc, 0xac,0x72,0x59,0x23,0x38,0x8, 0x49,0x3, 0x38,0x8, 0x49, +0x23,0x38,0x4, 0xbd,0x20,0x50,0x4, 0x59,0x3, 0x38,0x4, 0xb, 0x20,0xbc,0x32,0x50, +0xd2,0x6c,0xaa,0x6c,0x22,0x80,0x18,0x12,0xa4,0xa2,0x68,0x11,0x7e,0x70,0xc, 0xac, +0x72,0x49,0x3, 0x38,0x4, 0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20,0xbc, +0x32,0x50,0xe4,0x7e,0x37,0x37,0xea,0xbe,0x37,0x38,0x63,0x50,0x8, 0x7e,0x37,0x38, +0x63,0x7a,0x37,0x37,0xea,0x12,0xa4,0xc8,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c, +0xba,0x22,0x7e,0x10,0x5, 0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, 0x22, +0x7e,0x73,0x26,0xf5,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x26,0xf4,0xbe,0x70,0x0, 0x22, +0x7e,0x73,0x28,0x92,0xbe,0x70,0x0, 0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x38, +0x4, 0x22,0x49,0x23,0x38,0xa, 0x49,0x33,0x38,0x6, 0x9d,0x32,0x2, 0x20,0x30,0x7e, +0xb3,0x2b,0xf, 0x7c,0xab,0x6c,0x77,0x7e,0x50,0x5, 0xac,0x57,0x9, 0x62,0x26,0x33, +0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff, +0x22,0x7c,0x2b,0x7e,0xb3,0x1f,0x33,0xbc,0x2b,0x68,0x4f,0x12,0xa4,0xe3,0x7c,0x3b, +0x7c,0xb2,0x12,0xa4,0xe3,0x7c,0xab,0xbe,0x30,0xff,0x68,0x3e,0xbe,0xa0,0xff,0x68, +0x39,0x7e,0x70,0x4, 0xac,0x73,0xa, 0x2a,0x12,0x57,0xea,0xbe,0xb0,0x2, 0x38,0x2a, +0xa, 0x2b,0x7e,0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30,0x1a, +0x3, 0x2, 0xa5,0x99,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0xf, 0x12,0xa6,0xa5,0x7a,0x55, +0x2a,0x7e,0x8, 0xd, 0xc8,0x74,0x1, 0x2, 0xa5,0xca,0x22,0x7c,0xab,0x12,0xa6,0x1f, +0xd2,0x1a,0x7c,0xba,0x12,0xa5,0x1, 0xc2,0x1a,0x22,0x7e,0xb3,0x37,0xf0,0xb4,0x1, +0x27,0x7e,0xb3,0x38,0x66,0x4, 0x7a,0xb3,0x38,0x66,0x7e,0x73,0x38,0x66,0xbe,0x70, +0x3, 0x40,0x15,0x12,0xa2,0x88,0x7e,0x73,0x38,0x66,0xbe,0x70,0x6, 0x40,0x9, 0xe4, +0x7a,0xb3,0x38,0x66,0x7a,0xb3,0x37,0xf0,0x22,0x7c,0x7b,0x90,0x60,0x93,0xe4,0x93, +0xa, 0x1b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2d,0x1, 0x7e,0x63,0x2a,0x6e,0xa, 0x16, +0xad,0x10,0x7d,0x21,0x12,0xa6,0x9c,0xa, 0x26,0x7a,0x25,0x2a,0x74,0x1d,0xac,0x7b, +0x2e,0x34,0x33,0x8b,0x6d,0x22,0xe4,0x2, 0xa5,0xca,0x7c,0xab,0x6d,0x44,0x80,0x29, +0x4c,0xaa,0x68,0x11,0x12,0xa6,0xd, 0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0xa6, +0x1, 0x2d,0xfe,0x80,0xf, 0x12,0xa6,0xd, 0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12, +0xa6,0x1, 0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e,0xf5,0x2a,0xbd,0xf4,0x38,0xd0, +0x22,0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0,0x22,0x7f,0x71,0x2d, +0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5,0x2a,0x7e,0x6b,0xb0,0x22,0xa9, +0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x12,0xa6,0x1f,0x7e,0x34,0xd, 0xc8,0x7e,0xb3, +0x2a,0x6d,0x12,0xa6,0x60,0x12,0xa6,0x43,0x7a,0x37,0x33,0xf8,0x74,0x1, 0x7a,0xb3, +0x16,0x91,0x22,0x6d,0x33,0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, +0xbd,0x8, 0x90,0x60,0x92,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xbc,0x64,0x22, +0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e,0x7a,0x53,0x24,0xf3,0x7a,0x37,0x24,0xfa, +0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24,0xf5,0x7e,0x34,0x40,0x0, 0x7a,0x37,0x24, +0xf6,0x7e,0x34,0x0, 0x20,0x12,0xa6,0x93,0x2, 0xb, 0x7e,0x90,0x61,0xc5,0xe4,0x93, +0x7c,0xdb,0x22,0x7a,0x37,0x24,0xfc,0x7e,0x8, 0x24,0xf2,0x22,0x3e,0x24,0x7e,0xf, +0x33,0xfb,0x2d,0x12,0x22,0x7e,0xa3,0x2a,0x6e,0x7e,0xb3,0x2a,0x6d,0xa4,0x22,0xca, +0x3b,0x7a,0xd, 0x2f,0x7c,0xcb,0x7e,0xb3,0x2b,0x1d,0xf5,0x33,0x7e,0xb3,0x2b,0xf, +0xf5,0x34,0x7e,0xd3,0x2b,0x14,0x7e,0xe3,0x2b,0x1f,0x7e,0xf3,0x2b,0x20,0x7e,0x34, +0x0, 0x38,0xca,0x39,0x7e,0x18,0x34,0x0, 0x7e,0x8, 0x24,0xf2,0x12,0x1f,0xc9,0x1b, +0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x32,0xfa,0x7e,0x8, 0x25,0x2a,0x12, +0x1f,0xc9,0x1b,0xfd,0x7c,0xbc,0x12,0xa7,0xc1,0x74,0x1, 0x7a,0xb3,0x2b,0x1d,0x74, +0x5, 0xac,0xbc,0x12,0xa7,0xaf,0x74,0x5, 0xac,0xbc,0x12,0x4f,0xfd,0x74,0x5, 0xac, +0xbc,0x12,0xa7,0xa6,0x74,0x5, 0xac,0xbc,0x9, 0x75,0x26,0x37,0xbe,0x73,0x2b,0x62, +0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2,0x10,0xc2,0x0, 0x12,0xa7,0xb8,0x12,0x4f,0x26, +0x12,0x4c,0xcf,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d, +0x31,0x7e,0x2f,0x13,0x86,0x7d,0x25,0x7e,0x4, 0xd, 0xc8,0x7e,0xb3,0x2a,0x6d,0x12, +0x65,0x46,0x12,0xa6,0xa5,0x7a,0x55,0x35,0x7e,0xd, 0x2f,0x7e,0x18,0xd, 0xc8,0x12, +0xa8,0xe1,0x12,0xa9,0x8b,0xe5,0x33,0x7a,0xb3,0x2b,0x1d,0xe5,0x34,0x7a,0xb3,0x2b, +0xf, 0x7a,0xd3,0x2b,0x14,0x7a,0xe3,0x2b,0x1f,0x7a,0xf3,0x2b,0x20,0x7e,0x34,0x0, +0x38,0xca,0x39,0x7e,0x18,0x24,0xf2,0x7e,0x8, 0x34,0x0, 0x12,0x1f,0xc9,0x1b,0xfd, +0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x25,0x2a,0x7e,0x8, 0x32,0xfa,0x12,0x1f, +0xc9,0x1b,0xfd,0xda,0x3b,0x22,0x9, 0x75,0x26,0x36,0x7a,0x73,0x2b,0x20,0x22,0x9, +0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33, +0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x2f, +0xaa,0x6d,0x22,0x7e,0x8, 0x34,0x0, 0x12,0x1f,0xc9,0x1b,0xfd,0x7e,0x34,0x0, 0x8c, +0xca,0x39,0xac,0x7f,0x2e,0x34,0x30,0xca,0x6d,0x22,0x7e,0x8, 0x32,0xfa,0x12,0x1f, +0xc9,0x1b,0xfd,0xda,0xf8,0x22,0x7d,0x23,0x12,0x67,0x8d,0x7e,0x14,0x0, 0x5, 0xad, +0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x38,0x62,0xbe,0x30,0x8, 0x50,0x45, +0x74,0x8, 0x80,0x3d,0x7d,0x13,0x3e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x38,0x62, +0xbe,0x30,0x6, 0x50,0x30,0x74,0x6, 0x80,0x28,0x7e,0x14,0x0, 0x3, 0xad,0x13,0x1e, +0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x38,0x62,0xbe,0x30,0x4, 0x50,0x17,0x74,0x4, +0x80,0xf, 0xbd,0x32,0x50,0xf, 0x7e,0x73,0x38,0x62,0xbe,0x70,0x2, 0x50,0x6, 0x74, +0x2, 0x7a,0xb3,0x38,0x62,0x7e,0xb3,0x38,0x62,0xbe,0xb0,0x0, 0x28,0x1b,0x14,0x7a, +0xb3,0x38,0x62,0x74,0x1, 0x7a,0xb3,0x16,0x92,0x90,0x61,0xfd,0xe4,0x93,0xbe,0xb3, +0x38,0x62,0x50,0x5, 0xe4,0x7a,0xb3,0x16,0x91,0x22,0x7e,0x8, 0x38,0x0, 0x7e,0x34, +0x0, 0x60,0xe4,0x12,0x1f,0xee,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac, +0x7a,0x59,0x43,0x38,0x2, 0x59,0x43,0x38,0xa, 0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8, +0x7e,0x8, 0x37,0xee,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x1f,0xee,0x12,0xa8,0x7a,0x74, +0x1, 0x7a,0xb3,0x37,0xec,0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab,0x68,0x6, 0x7a,0xb3, +0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10,0x12,0xa8,0xd1,0xe4,0x2, 0x7, 0x45, +0x22,0x7e,0x8, 0x2a,0x6d,0x12,0x2, 0x64,0x7e,0x8, 0x2a,0x6d,0x74,0x3, 0x2, 0x10, +0x42,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x80,0xc2,0x0, 0x6d,0x44, +0x80,0x32,0x12,0xa9,0x82,0x12,0x9f,0x85,0xbd,0x3d,0x48,0x26,0x12,0xa9,0x82,0xb, +0x1a,0x30,0xbe,0x34,0x0, 0x0, 0x8, 0x4, 0xd2,0x0, 0x80,0x9, 0x12,0x20,0x30,0xbd, +0x3d,0x68,0x2, 0xc2,0x0, 0x7d,0x34,0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x12,0x9f,0x85, +0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x35,0xbd,0xc4,0x38,0xc7,0x30,0x0, 0xc, 0x7e,0xf0, +0x7f,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, +0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x35, +0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, +0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x35,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78, +0xfb,0x7c,0xb7,0x12,0x5f,0xcc,0xb, 0x44,0x7e,0x55,0x35,0xbd,0x54,0x38,0xd8,0xda, +0xf8,0x22,0x7d,0xc4,0x3e,0xc4,0x7f,0x17,0x2d,0x3c,0x22,0x90,0x60,0x93,0xe4,0x93, +0xa, 0xb, 0x7e,0x73,0x2a,0x71,0xa, 0x17,0x2d,0x10,0x7e,0xa3,0x2a,0x6e,0xa, 0x3a, +0xad,0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f, +0x33,0xfb,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x13,0x8e, +0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, 0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x35,0x7e, +0xf, 0x33,0x87,0x7e,0x18,0x25,0xb6,0x2, 0xa8,0xe1,0x6d,0x33,0x7d,0x23,0x7d,0x3, +0x6c,0x33,0x80,0x45,0x6c,0x22,0x80,0x37,0x7e,0xb3,0x2a,0x6e,0xac,0xb3,0xa, 0x42, +0x2d,0x54,0x7d,0x45,0x3e,0x44,0x7e,0x7f,0x13,0x8a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe, +0x44,0x0, 0x32,0x8, 0x8, 0xbe,0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff, +0xce,0x58,0x8, 0xbe,0x44,0xfd,0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e, +0x93,0x2a,0x6e,0xbc,0x92,0x38,0xc1,0xb, 0x31,0x7e,0xb3,0x2a,0x6d,0xbc,0xb3,0x38, +0xb3,0x7e,0x54,0x0, 0x6, 0xad,0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12, +0x24,0xc9,0xbd,0x12,0x50,0x22,0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x3a,0x38,0x7e, +0xb3,0x3a,0x39,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3a,0x39,0x80,0x3c,0xe4, +0x7a,0xb3,0x3a,0x39,0x74,0x1, 0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e, +0xe4,0x7a,0xb3,0x3a,0x39,0x7e,0xb3,0x3a,0x38,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a, +0xb3,0x3a,0x38,0x80,0x16,0xe4,0x7a,0xb3,0x3a,0x38,0x74,0x2, 0x80,0x9, 0xe4,0x7a, +0xb3,0x3a,0x38,0x7a,0xb3,0x3a,0x39,0x7a,0xb3,0x3a,0x3a,0x7e,0xb3,0x3a,0x3a,0x22, +0xca,0xf8,0x12,0x2f,0xf7,0x50,0x4b,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x44,0x6c,0xff, +0x80,0x3b,0x74,0x9, 0xac,0xbf,0x49,0x35,0x27,0x76,0x12,0x7f,0xf9,0x7d,0xa3,0x74, +0x9, 0xac,0xbf,0x49,0x35,0x27,0x78,0x12,0x74,0xf1,0x7d,0x93,0xbe,0xa4,0x0, 0x0, +0x40,0x12,0xbe,0x94,0x0, 0x0, 0x40,0xc, 0xbe,0xa4,0x4, 0x1a,0x38,0x6, 0xbe,0x94, +0x5, 0x78,0x28,0x7, 0x7c,0xbf,0x6c,0x77,0x12,0x36,0xca,0xb, 0xf0,0x12,0x89,0xff, +0x38,0xc0,0xda,0xf8,0x22,0xc2,0x0, 0x12,0x2f,0xf7,0x50,0x4b,0x6c,0xaa,0x80,0x39, +0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26,0xfb,0xbe,0x70,0x0, +0x28,0x25,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27,0xbd,0x21,0x58,0x17, +0xbe,0x60,0x0, 0x28,0x12,0x7e,0xb3,0x2a,0x70,0xa, 0x1b,0x1b,0x14,0xa, 0x26,0xbd, +0x21,0x58,0x4, 0xd2,0x0, 0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38, +0xbf,0x20,0x0, 0x3, 0x12,0x67,0xef,0x30,0x19,0x23,0x5, 0x64,0xe5,0x64,0xbe,0xb0, +0x50,0x50,0x16,0x7e,0x34,0x61,0xc0,0x12,0x23,0x29,0x3e,0x34,0x12,0xab,0x71,0x12, +0x23,0x29,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0xc2,0x19,0x80,0x0, 0x75,0x64,0x0, +0x22,0x7a,0x37,0x28,0xa1,0x7e,0x34,0x61,0xc2,0x22,0x12,0x2f,0xf7,0xd2,0x19,0x2, +0x29,0xba,0x6c,0xaa,0x12,0xae,0x46,0x6d,0x22,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e, +0x90,0x1, 0x3e,0x90,0x7f,0x1, 0x2e,0x14,0x0, 0x5, 0x7c,0xb8,0x54,0xfd,0x4c,0xb9, +0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54, +0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0, +0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xbd,0x22,0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x28,0x84, +0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60, +0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, 0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, +0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff, +0x7e,0xc0,0x1, 0xa1,0x16,0x75,0x2d,0x0, 0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25, +0x7a,0x35,0x27,0x7e,0x18,0x1f,0x70,0x7a,0x1d,0x29,0x74,0xff,0x7e,0x34,0x1f,0x71, +0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x7e,0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d, +0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12, +0x7f,0xd6,0x44,0x1, 0x7a,0x1b,0xb0,0x75,0x24,0x0, 0x80,0x6c,0x12,0xaf,0x59,0x9, +0x93,0x26,0xfb,0xe5,0x24,0x12,0x6f,0xdf,0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a, +0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, 0x39,0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x2b, +0xfd,0xbe,0x35,0x2e,0x8, 0x6, 0x12,0x2b,0xfd,0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e, +0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a,0x1b,0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, +0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, 0x2, 0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc, +0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, 0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9, +0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, 0x24,0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe, +0xb0,0x0, 0x28,0x50,0x7e,0xd, 0x29,0x12,0x7e,0x6, 0xe5,0x2d,0xa, 0x2b,0x7e,0x15, +0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e,0x35,0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55, +0x25,0x12,0xad,0x24,0x19,0xa3,0x2, 0xad,0x7e,0x55,0x27,0x12,0xad,0x24,0x19,0xa3, +0x2, 0xae,0x7e,0x37,0x2, 0xab,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27, +0x12,0x2c,0x1, 0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x2, 0xab,0x1b, +0x38,0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x81,0x5, 0x12,0xab,0x82,0x7c, +0xbf,0xda,0x3b,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0xca,0x79,0xc2,0x0, +0x7e,0xf0,0x3, 0x12,0x97,0xad,0x7e,0xe3,0x2a,0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37, +0x2, 0xab,0x7e,0x73,0x28,0x84,0xbe,0x70,0x1, 0x38,0x2, 0xc1,0xf, 0x12,0xae,0x50, +0x92,0xd, 0x12,0xae,0x18,0x7c,0xbf,0x12,0x2c,0x8, 0x4c,0xee,0x68,0xe, 0x7e,0xa3, +0x2, 0x88,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x2, 0x89,0x70,0x4, 0xd2,0x0, 0x80,0x25, +0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x5e,0xbe,0xb0,0x8, 0x28,0x4, 0xd2,0x0, 0x80,0x15, +0xd2,0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xbe,0x78,0xb, 0x20,0xd, 0x8, 0x4c,0xaa,0x78, +0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c,0xbf,0x12,0x2c,0x8, 0x7e,0x8, 0x2, +0x8d,0x12,0xab,0xc8,0x7a,0xb3,0x2, 0x8c,0xbe,0xb3,0x28,0x84,0x50,0x40,0x7e,0x33, +0x2, 0x8c,0x80,0x2c,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x2, 0xad,0x9, 0x13,0x2, +0xae,0x2e,0x37,0x2, 0xab,0xb, 0x38,0x50,0x7e,0x93,0x2a,0x6e,0xac,0x92,0xa, 0x31, +0x2d,0x43,0x3e,0x44,0x7e,0x1f,0x13,0x8a,0x2d,0x34,0x1b,0x1a,0x50,0x12,0x36,0xc5, +0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xcc,0x74,0x1, 0x7a,0xb3,0x2, 0x8a,0x7e,0xa3, +0x2, 0x8c,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x2, 0xad,0x7e, +0x8, 0x26,0xfa,0x12,0x1f,0xc9,0x1b,0xfd,0x12,0xaf,0x65,0xf5,0x5e,0x80,0x6, 0x75, +0x5e,0x64,0x12,0xaf,0x4d,0xda,0x79,0x22,0x6c,0xaa,0x12,0xae,0x46,0x6d,0x22,0x12, +0xae,0x3c,0x54,0xfe,0x12,0xae,0x39,0x54,0x7, 0x12,0xae,0x39,0x54,0xfb,0x7a,0xb, +0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xe2,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14, +0x0, 0x5, 0x7e,0xb, 0xb0,0x22,0x7e,0x70,0x6, 0xac,0x7a,0x2e,0x34,0x2, 0xea,0x22, +0xca,0x3b,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0xaf, +0x2d,0x30,0xe0,0x37,0x6c,0xcc,0x80,0x27,0x12,0xaf,0x43,0x7a,0xb3,0x1f,0x70,0x9, +0xa3,0x26,0xfb,0x7a,0xa3,0x1f,0x71,0x7f,0x7, 0x12,0xae,0xa6,0x50,0xf, 0x7f,0x7, +0x7e,0xb3,0x1f,0x71,0x6c,0x77,0x12,0xae,0xa9,0x50,0x2, 0xb, 0xf0,0xb, 0xc0,0xbc, +0xec,0x38,0xd5,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0x1e, +0x40,0xb6,0xc3,0xda,0x3b,0x22,0x7e,0x70,0x1, 0x7c,0x87,0x7c,0x9b,0x29,0xa0,0x0, +0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, 0x78,0x7, 0x29,0xa0,0x0, +0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, 0x16,0xbd,0x1, 0x48,0xc, +0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3,0x22,0xc3,0x22,0xca,0x3b, +0x12,0xaf,0x3a,0x75,0x54,0x0, 0x7e,0xa1,0x54,0x74,0x6, 0xa4,0x12,0xaf,0x2d,0x30, +0xe1,0x2e,0x7f,0x7, 0x7c,0xbc,0x12,0x7f,0xeb,0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12, +0xae,0xa6,0x50,0x1c,0x7f,0x7, 0x7c,0xbd,0x6c,0x77,0x12,0xae,0xa9,0x50,0x11,0x7f, +0x7, 0x7c,0xbf,0x6c,0x77,0x12,0xae,0xa9,0x50,0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, +0x5, 0x54,0xe5,0x54,0xbe,0xb0,0x1e,0x40,0xbd,0xe4,0xda,0x3b,0x22,0x7d,0xf5,0x2e, +0xf4,0x2, 0xea,0x6d,0xee,0x29,0xb7,0x0, 0x5, 0x22,0x7c,0xf5,0x7c,0xe6,0x7c,0xd7, +0x7c,0xcb,0x22,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x22,0x7e,0x8, 0x2, +0xea,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x1f,0xee,0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b, +0x9, 0xa3,0x26,0xfa,0x22,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4a,0xa, +0x31,0xb, 0x34,0x7c,0x7, 0x80,0x38,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26,0xfa, +0x12,0xaf,0xda,0x9, 0xb3,0x26,0xfa,0x12,0x2f,0xe9,0x7c,0x97,0x7e,0x70,0x2, 0xac, +0x70,0x9, 0xb3,0x26,0xfb,0x12,0xaf,0xda,0x9, 0xb3,0x26,0xfb,0x12,0x2f,0xe9,0x7c, +0x87,0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28,0xb, 0x0, 0x7e, +0xb3,0x28,0x84,0xbc,0xb0,0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x28,0x84,0xbc,0xb1,0x38, +0xae,0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22,0xbc,0x23,0x28, +0x4, 0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b,0x7e,0x70,0x2, 0xac, +0x71,0x22,0xca,0x3b,0x7c,0x45,0x7c,0x6, 0x7c,0x57,0x7c,0x1b,0x7e,0x34,0x4, 0xfc, +0x7e,0xb3,0x26,0x83,0x7e,0xf3,0x2a,0x6e,0x7c,0x31,0x7c,0xe0,0x7c,0x25,0x7c,0xa4, +0xbc,0x1, 0x50,0x4, 0x7c,0x30,0x7c,0xe1,0xbc,0x45,0x50,0x4, 0x7c,0x24,0x7c,0xa5, +0xbe,0xb0,0x1, 0x50,0x2, 0x1, 0xa7,0x7e,0x90,0x2, 0xac,0x9f,0x7e,0x50,0x2, 0xac, +0x53,0x2d,0x24,0x2d,0x23,0xb, 0x28,0x20,0x7e,0x10,0x2, 0xac,0x1e,0x2d,0x4, 0x2d, +0x3, 0xb, 0x8, 0x40,0xa, 0x3, 0xb, 0x4, 0x7c,0x31,0x80,0x28,0x7e,0xd0,0x2, 0xac, +0xdf,0x7e,0x10,0x2, 0xac,0x13,0x2d,0x6, 0x12,0xb0,0xab,0x58,0x15,0xad,0xf4,0xbd, +0xdf,0x58,0xf, 0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3, +0x80,0x46,0xb, 0x30,0xbc,0xe3,0x38,0xd4,0x7e,0x50,0x2, 0xac,0x52,0x2d,0x23,0xb, +0x28,0x20,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x43,0xb, 0x48,0x40,0xa, 0x12,0xb, 0x14, +0x80,0x21,0x7e,0x10,0x2, 0xac,0x13,0x12,0xb0,0xab,0x58,0x15,0xad,0xf4,0xbd,0xdf, +0x58,0xf, 0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80, +0x7, 0xb, 0x30,0xbc,0xa3,0x38,0xdb,0xd3,0xda,0x3b,0x22,0x2d,0x3, 0xb, 0x8, 0x0, +0x7e,0xf4,0x0, 0x9, 0x7d,0xb2,0xad,0xbf,0x7e,0xd4,0x0, 0xa, 0xad,0xd0,0xbd,0xdb, +0x22,0xca,0xf8,0x7c,0xfb,0x7f,0x61,0x7f,0x50,0x7e,0x34,0x22,0x43,0x7e,0x24,0x0, +0xff,0x7e,0x14,0x1f,0x70,0x74,0x2a,0x12,0x1e,0xa7,0x7e,0x48,0x1f,0x70,0x12,0x8f, +0xc4,0x92,0xc, 0x7c,0xbf,0x7e,0x71,0x54,0x12,0x2c,0x1, 0x7d,0x43,0xe5,0x55,0x7e, +0x71,0x56,0x12,0x2c,0x1, 0x2d,0x34,0xe, 0x34,0x7f,0x4, 0x7e,0x50,0x7, 0xb, 0xa, +0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b,0x5a,0x30,0x69,0x30,0x0, 0x4, +0x1b,0x6a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78,0xe1,0x12,0xb1,0x50, +0x28,0x2b,0xb, 0x5a,0x20,0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e,0x24,0x0, 0x10,0x12, +0x1d,0xb3,0x1b,0x5a,0x30,0xb, 0x6a,0x30,0x1a,0x26,0x1a,0x24,0x7e,0x14,0x0, 0xd, +0x12,0x1d,0xf6,0x7e,0x8, 0x0, 0x10,0x12,0x1e,0x52,0x1b,0x6a,0x30,0xda,0xf8,0x22, +0x7e,0x73,0x2, 0x8b,0xbe,0x70,0x5, 0x22,0x12,0xaf,0xe2,0x92,0x4, 0x30,0x4, 0xc, +0x7e,0xb3,0x2, 0xe9,0xbe,0xb0,0xfa,0x50,0x11,0x4, 0x80,0xa, 0x7e,0xb3,0x2, 0xe9, +0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x2, 0xe9,0x7e,0xb3,0x2, 0xe9,0x70,0x2, +0xc3,0x22,0xd3,0x22,0x7c,0x7b,0x12,0xb1,0xa1,0x9, 0xa2,0x27,0x72,0x7c,0xb7,0x54, +0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x12,0x57,0xf0,0x5c,0xba,0x22,0x7c,0xa5,0x7c, +0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x7e,0x8, 0x26,0x86,0x7e,0x34,0x0, 0x3, +0xe4,0x12,0x1f,0xee,0x7e,0x8, 0x26,0x89,0x7e,0x34,0x0, 0x3, 0x12,0x1f,0xee,0x7a, +0xb3,0x26,0x83,0x7a,0xb3,0x26,0x84,0x7a,0xb3,0x26,0x85,0x7a,0xb3,0x26,0xf0,0x7a, +0xb3,0x26,0xf1,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0x6f,0x12,0xb3,0xb, 0x6c,0x55, +0x12,0xb2,0x6e,0x7a,0xb3,0x26,0x85,0x7e,0x18,0x26,0x5b,0x12,0xb3,0x1b,0x6c,0x55, +0x12,0xb2,0x6e,0x7a,0xb3,0x26,0x84,0x6c,0x77,0x80,0x14,0x12,0xb2,0xf7,0x60,0x5, +0x3e,0x24,0x14,0x78,0xfb,0x12,0xb1,0x9d,0x2e,0x24,0x26,0x86,0x12,0xb3,0x0, 0x7e, +0x63,0x26,0x84,0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0xb2,0xf7,0x60,0x5, +0x3e,0x24,0x14,0x78,0xfb,0x12,0xb1,0x9d,0x2e,0x24,0x26,0x89,0x12,0xb3,0x0, 0x7e, +0xa3,0x26,0x85,0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x26,0x84,0xa4,0x7a,0xb3,0x26,0x83, +0x7e,0x18,0x26,0xe6,0x12,0xb3,0xb, 0x7e,0x50,0x1, 0x12,0xb2,0x6e,0x7a,0xb3,0x26, +0xf2,0x7e,0x18,0x26,0xdc,0x12,0xb3,0x1b,0x7e,0x50,0x1, 0x12,0xb2,0x6e,0x7c,0xab, +0x7a,0xa3,0x26,0xf1,0x7e,0xb3,0x26,0xf2,0xa4,0x7a,0xb3,0x26,0xf0,0x22,0xca,0x69, +0xca,0xf8,0x7c,0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff,0x80,0x70,0x7e,0xd0,0x2, 0xac, +0xdf,0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4,0xff,0xff, +0xb, 0xe4,0xbd,0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0,0x0, 0x2, +0x80,0x1b,0x7c,0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, 0x5a,0x40, +0x6d,0xff,0x80,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c,0x55,0x68, +0xc, 0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd,0x4e,0x58, +0x19,0xbd,0xfe,0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b,0xf0,0xb, +0xa0,0x90,0x60,0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, 0xb, 0xf0,0xbc,0x4f,0x38,0x8c, +0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0xb7,0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x22, +0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70,0x22,0x7a,0x1d,0x24,0x7e,0xf, +0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a,0x53,0x22,0x7a,0x1d,0x24,0x7e,0xa3, +0x2a,0x6e,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0xf8,0x2d,0x15,0x7e,0xb3,0x2a,0x6d,0x7e, +0x37,0x2a,0x51,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33,0x19,0xb3,0x27,0x72,0xb, +0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0xb1,0xa1,0xb, 0x24,0xa, 0x33,0xbd,0x32,0x48, +0xe7,0xe4,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x28,0x85,0x6d,0x33,0x7a,0x37,0x28,0x86, +0x7a,0x37,0x28,0x88,0x7a,0x37,0x28,0x8a,0x7a,0x37,0x28,0x8e,0x7e,0xd4,0x1f,0x36, +0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x13,0x8a,0x7a,0x37,0x1f,0x76,0x7d,0x3d, +0x7a,0x37,0x1f,0x7a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x78,0x7e,0x73,0x2a,0x6d, +0x7a,0x73,0x1f,0x73,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x1f,0x72,0x7e,0x37,0x2a,0x5c, +0x7a,0x37,0x1f,0x7c,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x7e,0x7e,0x37,0x2a,0x60, +0x7a,0x37,0x1f,0x80,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1f,0x74,0x7e,0x73,0x3, 0xfe, +0x7a,0x73,0x1f,0x75,0x7e,0x8, 0x1f,0x72,0x7e,0x18,0x1f,0x82,0x12,0x6, 0x74,0x7e, +0x73,0x1f,0x82,0x7a,0x73,0x28,0x84,0x7e,0x73,0x1f,0x83,0x7a,0x73,0x28,0x85,0x7e, +0x37,0x1f,0x84,0x7a,0x37,0x28,0x86,0x7e,0x37,0x1f,0x86,0x7a,0x37,0x28,0x88,0x7e, +0x37,0x1f,0x8c,0x7a,0x37,0x28,0x8a,0x7e,0x37,0x1f,0x8e,0x7d,0x23,0x7a,0x53,0x28, +0x8c,0xa, 0x36,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x1f,0x88,0x7a,0x37,0x28,0x8e,0x7e, +0x37,0x1f,0x8a,0x7d,0x23,0x7a,0x53,0x28,0x90,0xa, 0x36,0x7a,0x73,0x28,0x91,0x6c, +0x33,0x80,0x1b,0x12,0x36,0xc5,0x74,0x2, 0xac,0xb3,0x49,0x45,0x15,0x9e,0xa, 0x38, +0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29,0x19,0x25,0x26,0xfb,0xb, 0x30,0x7e,0x23, +0x28,0x84,0xbc,0x23,0x38,0xdd,0x6c,0x33,0x80,0x1b,0x74,0x2, 0xac,0xb3,0x7f,0x16, +0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25,0x27,0x36,0x7c,0x29,0x19, +0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28,0x85,0xbc,0x23,0x38,0xdd,0x22,0xca,0x79, +0x7c,0xa7,0x7c,0x8b,0x7e,0xb3,0x2a,0x6f,0x7a,0xb3,0x1f,0x9a,0x7e,0xb3,0x2a,0x70, +0x7a,0xb3,0x1f,0x9b,0x7e,0x70,0x2, 0xac,0x78,0x9, 0x93,0x26,0xfa,0x9, 0x83,0x26, +0xfb,0x9f,0x77,0x1a,0x3a,0x1a,0x79,0x9d,0x73,0xa1,0x26,0x7a,0xf1,0x58,0xbe,0xf0, +0x0, 0x58,0xe, 0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5, +0x58,0x7e,0xb3,0x1f,0x9a,0xbc,0xbf,0x18,0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a, +0x39,0x9d,0x32,0x7c,0xb7,0xf5,0x58,0x1a,0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5, +0x57,0x80,0x43,0x85,0x57,0x59,0xe5,0x57,0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x57,0x1a, +0x3b,0x1a,0x28,0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c,0xb7,0xf5,0x59,0x7e,0xb3,0x1f, +0x9b,0xbe,0xb1,0x57,0x18,0x10,0x1a,0x38,0xe5,0x57,0x1a,0x2b,0x9d,0x23,0x1a,0x38, +0x9d,0x32,0x7c,0xb7,0xf5,0x59,0xe5,0x58,0x7e,0x71,0x59,0x12,0x2c,0x1, 0x1a,0x26, +0x1a,0x24,0x2f,0x71,0x5, 0x57,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x57,0x1a,0x3b, +0xbd,0x32,0x8, 0xaf,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32, +0x18,0x2, 0x81,0x9b,0x7f,0x17,0xda,0x79,0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, +0x55,0x26,0xfa,0x9, 0x65,0x26,0xfb,0x7e,0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e, +0x73,0x28,0x8d,0xbc,0x76,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0xaa,0x80,0x1c,0x7e, +0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32,0x13,0x8e,0xbd,0x31,0x28,0x9, +0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, 0xa0,0x7e,0xb3,0x2a,0x6e,0xbc, +0xba,0x38,0xdc,0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9,0xc5,0xea, +0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x65,0x7e,0x73,0x3a,0x36, +0xbe,0x71,0x65,0x38,0x2, 0xd2,0x1b,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9,0x34,0xe5, +0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9,0x33,0xe5, +0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5,0x3, 0xa9, +0xc6,0xcd,0xda,0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22,0x7e, +0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50,0x79, +0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79,0x30, +0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79,0x30, +0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79,0x30, +0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0xa9,0xd5,0xcb,0x74,0x10,0x12,0x43,0xef,0x7c, +0x7b,0x12,0x43,0xf7,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24,0x0, 0xef, +0x7e,0xf, 0x33,0xe2,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, 0x33,0xe2, +0x79,0x20,0x0, 0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x33,0xe2,0x79,0x20,0x0, 0x90, +0x7c,0x67,0x6c,0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x33,0xe2,0x79,0x30,0x0, 0x86, +0x7e,0x34,0x29,0x90,0x7e,0xf, 0x33,0xe2,0x79,0x30,0x0, 0x8a,0x7e,0x34,0x6a,0xd1, +0x7e,0xf, 0x33,0xe2,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, 0x33,0xe2, +0x79,0x30,0x0, 0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86, +0xa9,0xc2,0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9, +0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, +0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7, +0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0, +0xf7,0xd2,0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7, +0xc2,0xbe,0x22,0x75,0xe7,0x6b,0x2, 0xb6,0xf9,0xe4,0x7e,0x34,0xd7,0xfc,0x7e,0x24, +0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff,0x22, +0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3a,0x34,0xb, 0x34,0x7a,0x37,0x3a, +0x34,0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3a,0x34,0x22, +0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c,0xaa, +0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6,0x12,0x5f,0xca,0xb, 0xa0,0xbe,0xa0, +0xd, 0x40,0xed,0xc2,0xc9,0x22,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3,0x3a,0x42, +0xb4,0xa5,0x46,0x12,0xb7,0xe0,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0x12,0xb7,0xb2, +0xa9,0x36,0xb3,0xfc,0x12,0xb7,0xb2,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61, +0xb5,0xa9,0x36,0xb3,0xfc,0x12,0xb7,0xb2,0xa9,0x36,0xb3,0xfc,0x12,0xb7,0xb2,0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d, +0x32,0x22,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0x22,0x74,0x6, 0x12,0xb7,0x56,0x7d,0x3, +0x6c,0x11,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0xb7,0x56,0x4c,0xff,0x78,0x5, +0x5e,0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0xb7,0xeb,0xda,0xf8,0x22, +0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, +0x14,0x7c,0x73,0x7d,0x52,0x7c,0xab,0x7e,0xb3,0x3a,0x42,0xb4,0xa5,0x3c,0x12,0xb7, +0xe0,0x75,0xb5,0x1, 0xa9,0x36,0xb3,0xfc,0x12,0xb7,0xb2,0xa9,0x36,0xb3,0xfc,0x12, +0xb7,0xb2,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5, +0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0xa9,0xc5,0xca,0xe4,0x7a, +0xb3,0x3a,0x42,0x22,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13,0xa9,0xd1, +0xb4,0xa9,0xc0,0xb4,0x12,0xb8,0xda,0xe4,0x12,0xb7,0xc3,0x2, 0xb8,0x3b,0x7d,0x42, +0x7f,0x60,0x7d,0x3, 0x12,0xb8,0xda,0x74,0x2, 0x12,0xb7,0x56,0x7d,0xf3,0x4e,0xf4, +0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0xb8,0x8f,0x7a,0x45,0x36,0x7d,0x30,0x6d,0x22, +0x7f,0x6, 0x12,0xb8,0x96,0x5e,0xf4,0xff,0xfd,0x12,0xb8,0x8f,0x2, 0xb8,0x3b,0x74, +0x2, 0x7d,0x3f,0x2, 0xb7,0xeb,0x12,0xb8,0xa4,0x7e,0x35,0x36,0x12,0xb8,0xea,0xa9, +0xd2,0xb4,0xd3,0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39, +0x7f,0x21,0xf5,0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0xb8,0xcf,0xe5,0x3a,0x12,0xb8, +0xcf,0xe5,0x39,0x12,0xb8,0xcf,0xe5,0x38,0x12,0xb8,0xcf,0xe4,0x2, 0xb8,0xcf,0xf5, +0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xa9,0xd5,0xca,0xa9,0xd1,0xea, +0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x3a,0x42,0x22,0x6d,0x22,0x80,0x13,0x75,0xb5, +0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0,0xb, 0x14,0xb, +0x24,0xbd,0x32,0x38,0xe9,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4,0x6c,0x11,0x80, +0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x26,0xfb,0xa, 0x20,0xa, +0x33,0x9d,0x32,0x12,0x20,0x30,0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, 0x74,0x26,0xfa, +0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x20,0x30,0x7c,0x97,0xbe,0x90,0x1, 0x18,0x8, +0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, 0xbe,0x0, 0x2, +0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x28,0x84,0xbc,0x81,0x18,0xb2,0x22, +0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0x6f,0xe9,0xb, 0x7a,0x20,0x2d,0x25, +0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x1e, +0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, 0x7d,0x53,0x7c, +0xab,0xe4,0x3e,0x54,0x3e,0x54,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x2d,0x25, +0x79,0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12,0x24,0xc7,0x1e, +0x34,0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7, +0x7f,0x70,0x12,0xba,0x4c,0x7c,0xeb,0x6c,0xdd,0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f, +0x67,0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, +0x1e,0x6d,0x0, 0x12,0x1e,0x1, 0x1b,0x6a,0x30,0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda, +0x79,0xda,0xd8,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40,0x7e,0xa3,0x2a,0x74,0xa, 0x3a, +0x7e,0xa3,0x2a,0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, 0x2a,0x7c,0x7f,0x12,0xb9,0xba, +0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x2a,0x7f,0x4, 0x12,0x1f,0xc9,0x1b,0xfd, +0x7e,0xb3,0x2b,0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x2, 0xac,0x7a, +0x7f,0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d,0x13,0xb, 0xa, 0x30,0x9d,0x32, +0x1b,0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda,0x79,0x22,0x7c,0x7b,0xa5,0xbf, +0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x70, +0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0,0x2, +0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xa, +0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78,0xfb, +0x7c,0xb9,0x22,0x7e,0xb3,0x3, 0xbe,0x22,0x7c,0xab,0x9f,0x11,0x30,0x0, 0x22,0x6c, +0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b,0xb0,0x7e,0x78,0x0, 0x1, +0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e,0xb, 0x90,0xbc,0xa9,0x38, +0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12, +0x3f,0xe4,0x7e,0x8, 0x1f,0x3c,0x12,0xbb,0x4e,0xd2,0x0, 0x7e,0x8, 0x2a,0xdc,0x7c, +0xbf,0x12,0xba,0x98,0x7e,0x8, 0x1f,0x34,0x7a,0xf, 0x1f,0x58,0x7f,0x1, 0x7a,0x17, +0x1f,0x5c,0x7d,0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18,0x1f,0x3c,0x7a,0x1f,0x1f,0x64, +0x6c,0x77,0x80,0xe, 0x12,0xbb,0x96,0x50,0x7, 0x12,0xbb,0x8d,0x19,0x51,0x1f,0x3c, +0xb, 0x70,0xbc,0xf7,0x38,0xee,0x12,0xbb,0x3b,0xe4,0x12,0xbb,0x43,0xe4,0x12,0xb, +0x12,0x6d,0x33,0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f,0x5e,0x12,0xbb,0x3b,0x74,0x1, +0x12,0xbb,0x43,0x74,0x1, 0x12,0xb, 0x12,0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e,0x8, +0x1f,0x58,0x22,0x12,0xb, 0x12,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x7e,0x34, +0x0, 0x1c,0x74,0x3f,0x2, 0x1f,0xee,0x7e,0x8, 0x1f,0x34,0x12,0xbb,0x4e,0x6c,0x77, +0x80,0xe, 0x12,0xbb,0x96,0x50,0x7, 0x12,0xbb,0x8d,0x19,0x51,0x1f,0x34,0xb, 0x70, +0x7e,0x53,0x2a,0x6e,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x34,0xe4, +0x12,0x10,0x0, 0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x34,0x2, 0x10,0x0, 0xa, 0x27,0x9, +0x52,0x2b,0x44,0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x2a,0xdc,0xbe,0x60,0x1c,0x22, +0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80,0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e, +0x7b,0x60,0xa, 0x46,0x2e,0x44,0x1f,0x83,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93, +0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e, +0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, +0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a, +0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80,0x58, +0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12,0xbc, +0x5d,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe, +0x60,0x1b,0x38,0x16,0x9e,0x60,0xe, 0x12,0xbc,0x5d,0x60,0x5, 0x3e,0x44,0x14,0x78, +0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0xbc,0x5d, +0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a, +0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, +0x1, 0x7c,0xb6,0x22,0xca,0xf8,0x6d,0xee,0x7d,0xfe,0x7e,0x83,0x2a,0x6e,0xa, 0xd8, +0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x2f,0x7e,0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x18, +0x7e,0x70,0x2, 0xac,0x7a,0x49,0x23,0x13,0xfe,0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0, +0x9d,0xc2,0x59,0xc3,0x13,0xc6,0xb, 0xa0,0xbc,0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4, +0x93,0x7c,0x9b,0x6d,0xdd,0x80,0x11,0x7e,0x8, 0x13,0xfe,0x90,0x60,0x92,0xe4,0x93, +0xa, 0xcb,0x1b,0xc4,0x7d,0x3c,0x7c,0x97,0x6c,0xff,0x80,0x38,0x6c,0xaa,0x80,0x28, +0xa, 0x3a,0x7d,0x23,0x2d,0x2e,0x3e,0x24,0x49,0xc2,0x13,0xfe,0x2d,0x3d,0x3e,0x34, +0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xb0,0x7d,0x3c,0x9d,0x3b,0x12,0x20,0x30,0x7d,0xa3, +0xbd,0xfa,0x58,0x2, 0x7d,0xfa,0xb, 0xa0,0xbc,0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec, +0x2d,0xdc,0xb, 0xf0,0xbc,0x9f,0x38,0xc4,0x7d,0x3f,0xda,0xf8,0x22,0x7a,0xb3,0x3, +0xc9,0x22,0x90,0x61,0x81,0xe4,0x93,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x2a,0x6e, +0x90,0x60,0x93,0xe4,0x93,0xa, 0xfb,0x7e,0xb3,0x2a,0x6d,0xa, 0xeb,0x2d,0xef,0xa, +0xff,0xad,0xfe,0xa, 0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e, +0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x33, +0xfb,0x2d,0x3d,0xb, 0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, +0x5a,0x30,0x9d,0x3d,0x59,0x32,0x13,0xc6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, +0x7d,0x5e,0x3e,0x54,0x7e,0xf, 0x33,0xfb,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea, +0x2d,0xef,0x3e,0xe4,0x7e,0x1f,0x33,0xfb,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, +0xac,0x7a,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x20,0x30, +0x7d,0xc3,0xbd,0x4c,0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34, +0xda,0xf8,0x22,0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d,0xac,0x54,0x7e,0x17,0x28, +0xa1,0x12,0x9f,0xc4,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x33,0xfb, +0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x8, 0xa, 0xb, +0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, +0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd, +0x20,0x38,0xc5,0x22,0x7e,0x27,0x28,0xa3,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64, +0x30,0x5, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, 0x0, +0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59, +0xf4,0x5, 0xf8,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, +0xf8,0x30,0x7, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, 0x4, +0x7e,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3, +0x59,0xf4,0x6, 0x76,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, +0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0xb, 0x7e,0xb3,0x2a,0x73,0xa, 0x4b, +0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54,0x0, +0x20,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60,0xf0, +0xa5,0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24, +0x14,0x78,0xfb,0x7e,0x73,0x3a,0x2b,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x3, 0xef,0x80, +0x36,0xa5,0xbe,0x30,0x18,0x12,0xbe,0xec,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e, +0x53,0x3a,0x2c,0xa, 0x45,0x5d,0x43,0x7e,0x73,0x3, 0xf0,0x80,0x1a,0x12,0xbe,0xec, +0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x3a,0x2b,0xa, 0x4b,0x5d, +0x43,0xa, 0x5a,0x9, 0x75,0x3, 0xf1,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54,0xf, +0x7e,0x34,0x0, 0x1, 0x22,0x7e,0xb3,0x3, 0xee,0x70,0x6, 0x12,0xbf,0x2e,0x2, 0xbf, +0x34,0x12,0xc0,0x8d,0x12,0xbf,0x3a,0x50,0xa, 0x12,0x77,0xa5,0x7c,0x3b,0x12,0xbf, +0x2e,0x80,0x5, 0x12,0xc2,0x6d,0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12,0xbe, +0x79,0x60,0xa, 0x7a,0x33,0x3, 0xf1,0x74,0x1, 0x7a,0xb3,0x2a,0x8, 0x22,0xe4,0x7a, +0xb3,0x2f,0x80,0x22,0xe4,0x7a,0xb3,0x3a,0x17,0x22,0x7e,0xb3,0x2f,0x80,0xb4,0x4, +0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x17,0x2f,0x90,0xbd,0x13,0x28,0xa, 0x7a,0x37,0x2f, +0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e,0x17,0x2f,0x88,0xbd,0x13,0x50,0x8, 0x7a, +0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e,0x17,0x2f,0x8e,0xbd,0x12,0x28,0xa, 0x7a, +0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80,0x10,0x7e,0x17,0x2f,0x96,0xbd,0x12,0x50, +0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f,0x94,0x7e,0xb3,0x2f,0xa8,0xb4,0xa, 0xf, +0x12,0xbf,0xba,0x7a,0x37,0x2f,0xa0,0x12,0xbf,0xb1,0x7a,0x37,0x2f,0xa2,0x22,0xb4, +0x14,0xe, 0x12,0xbf,0xba,0x7a,0x37,0x2f,0xa4,0x12,0xbf,0xb1,0x7a,0x37,0x2f,0xa6, +0x22,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37, +0x2f,0x90,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42,0x7d,0x13,0x7d,0x24,0x12,0xc2,0x19, +0x7d,0x31,0x12,0xbf,0x45,0x2, 0xbf,0xd8,0x7e,0x3, 0x2f,0xa8,0xbe,0x0, 0xf0,0x50, +0x3, 0x2, 0xc0,0x74,0x2, 0xc0,0x68,0x6c,0x99,0x7e,0xb3,0x2f,0x7f,0xbe,0xb0,0x20, +0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f,0x2b,0xbf,0x7a,0x1f,0x1f,0x34,0x7e, +0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2b,0xbf,0x49,0x25,0x2b,0xc1, +0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12,0xc0,0x75,0x7c,0x1b,0x7e,0x3, 0x2f, +0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70,0x4, 0xac,0x78,0x2e,0x34,0x2b,0xbf, +0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1e,0x86,0x7e,0x34,0x1f,0x34,0x7e,0x30,0x4, +0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12,0x1e,0x86,0xb, 0x80,0x7e,0x3, 0x2f, +0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54,0x7c,0xb, 0x7a,0x3, 0x2f,0xa8,0x7e, +0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xc, 0x7e,0x3, 0x2f,0xa8,0xbe,0x0, 0xec,0x40, +0x3, 0x2, 0xbf,0xe7,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x20,0x30,0x7c,0xa7, +0x12,0xc1,0xa1,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22,0xca,0xf8,0x7e, +0xa3,0x2a,0x2, 0x7e,0xb3,0x2a,0x3, 0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0,0x1, 0x38, +0x1c,0x7e,0x47,0x28,0x86,0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x2f, +0x80,0x4c,0xff,0x68,0x17,0x7e,0x47,0x2b,0xb7,0x4d,0x44,0x78,0xf, 0x12,0xc1,0x9a, +0x74,0x1, 0x7a,0xb3,0x39,0xcb,0x7a,0xb3,0x3, 0xc3,0x80,0x35,0x4c,0xaa,0x78,0x36, +0xb4,0x1, 0x33,0x7e,0x37,0x2b,0xb7,0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f,0x80,0xb4, +0x3, 0x1f,0x7e,0x37,0x2b,0xb7,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a,0xb3, +0x2f,0x80,0x7e,0x37,0x2f,0x98,0x7e,0x27,0x2f,0x9a,0x12,0xbf,0xc7,0x21,0x97,0x80, +0x0, 0x12,0xc1,0xa8,0x21,0x97,0x7e,0xc7,0x29,0x8, 0x7e,0xd7,0x29,0xa, 0x4c,0xff, +0x78,0x19,0x70,0x57,0xbe,0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12,0xc1,0xb4, +0x12,0xbf,0xc3,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x40,0xbe,0xf0,0x1, 0x78,0x2e, +0x7e,0x27,0x2f,0x88,0x9e,0x27,0x2f,0x90,0x7e,0x14,0x62,0x8a,0x12,0x67,0x91,0xbd, +0x23,0x38,0x13,0x7e,0x27,0x2f,0x96,0x9e,0x27,0x2f,0x8e,0x7e,0x14,0x62,0x8c,0x12, +0x67,0x91,0xbd,0x23,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, 0xbe,0xf0, +0x3, 0x78,0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f,0x80,0x60, +0x26,0x7d,0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12,0xc0,0x75, +0xa, 0x2b,0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0xbf,0xc3,0x7a, +0xc7,0x2b,0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x6d,0x33,0x7a,0x37,0x39,0xc9, +0x22,0x7d,0x31,0x9d,0x30,0x2, 0x20,0x30,0x74,0xfe,0x7a,0xb3,0x3, 0xf1,0xe4,0x7a, +0xb3,0x2f,0x80,0x22,0x7d,0xf2,0x7d,0xe3,0x7e,0x8, 0x2f,0x80,0x7e,0x34,0x0, 0x28, +0xe4,0x12,0x1f,0xee,0x7e,0x8, 0x2b,0xbf,0x7e,0x34,0x3, 0xc0,0x12,0x1f,0xee,0x7a, +0xb3,0x3, 0xf1,0x7e,0x34,0x62,0x8e,0x12,0x23,0x29,0x7a,0x37,0x2b,0xb7,0x7a,0xe7, +0x2f,0x84,0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88,0x7a,0xe7,0x2f,0x8c,0x7a,0xe7, +0x2f,0x90,0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a,0x7a,0xf7,0x2f,0x8e,0x7a,0xf7, +0x2f,0x92,0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb,0x7a,0xf7,0x2b,0xbd,0x7a,0xb3, +0x2f,0xa8,0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x7e,0xa3,0x2f,0xa8,0xbe,0xa0,0xf0, +0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0xc2,0x3a,0x59,0x25,0x2b,0xc1, +0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e,0xa3,0x2f,0xa8,0x74,0x4, +0xa4,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x3a,0x1c,0x9e,0x37, +0x3a,0x18,0x12,0x20,0x30,0xbd,0x31,0x38,0x12,0x7e,0x37,0x3a,0x1e,0x9e,0x37,0x3a, +0x1a,0x12,0x20,0x30,0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xd8,0xca, +0x79,0x6c,0xff,0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x2a,0x2, 0x7e,0xe3,0x2a, +0x3, 0x7e,0xb3,0x3a,0x17,0x60,0x11,0x7e,0xc7,0x3a,0x20,0x4d,0xcc,0x78,0x2, 0x61, +0x65,0xbe,0xd0,0x1, 0x28,0x2, 0x61,0x65,0xbe,0xd0,0x1, 0x78,0x1d,0xbe,0xb0,0x4, +0x78,0x2, 0x61,0x65,0x7e,0xe7,0x29,0x8, 0x7e,0xf7,0x29,0xa, 0x7d,0x3e,0x7d,0x2f, +0x12,0x67,0xb6,0xbe,0xb0,0x1, 0x78,0x2, 0x61,0x65,0x7e,0xa3,0x3a,0x17,0x7c,0xba, +0x14,0x68,0x29,0x14,0x68,0x56,0x14,0x68,0x23,0x14,0x78,0x2, 0x61,0x62,0xb, 0xb2, +0x68,0x2, 0x61,0x65,0xbe,0xd0,0x1, 0x68,0x2, 0x61,0x74,0x4c,0xee,0x68,0x2, 0x61, +0x74,0x74,0x1, 0x7a,0xb3,0x3a,0x17,0x12,0xc3,0x85,0x80,0x69,0x4c,0xdd,0x78,0x1d, +0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x3a,0x17,0x7e,0x34,0x62,0x64,0x80, +0x58,0x74,0x4, 0x7a,0xb3,0x3a,0x17,0x7e,0x34,0x62,0x68,0x80,0x4c,0x12,0xc3,0x8e, +0x90,0x62,0x57,0x12,0xc3,0x7b,0x4d,0xdd,0x68,0x4b,0x80,0x58,0xbe,0xd0,0x1, 0x78, +0x53,0x4c,0xee,0x78,0x4f,0x12,0xc3,0x8e,0x7e,0x34,0x62,0x60,0x12,0x23,0x29,0x7e, +0x14,0x62,0x64,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7,0x3a,0x20, +0x40,0x23,0x90,0x62,0x56,0x12,0xc3,0x7b,0x4d,0xdd,0x68,0x19,0x12,0xc3,0x85,0x74, +0x3, 0x7a,0xb3,0x3a,0x17,0x7e,0x34,0x62,0x64,0x12,0x23,0x29,0x7a,0x37,0x3a,0x20, +0x80,0x12,0x7e,0xf0,0x24,0xe4,0x7a,0xb3,0x3a,0x17,0x6d,0x33,0x7a,0x37,0x3a,0x20, +0x7c,0xbf,0x80,0x2, 0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xe4,0x93,0xa, 0x3b,0x12, +0xc2,0x42,0xa, 0xdb,0x22,0x7a,0xe7,0x3a,0x18,0x7a,0xf7,0x3a,0x1a,0x22,0x7a,0xe7, +0x3a,0x1c,0x7a,0xf7,0x3a,0x1e,0x22,0xca,0x3b,0x7c,0xfb,0x7f,0x61,0x7f,0x40,0x9f, +0x11,0x7f,0x51,0x7f,0x71,0x7a,0x1d,0x3c,0x7a,0x1d,0x40,0x7a,0x1d,0x44,0xbe,0xf0, +0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80,0x4, 0x7e,0x54,0x2, 0x35,0x7a,0x57,0x23, +0x43,0x6c,0xee,0x80,0x60,0xa, 0x5e,0x7f,0x14,0x12,0xc4,0xe4,0x7a,0x55,0x4a,0xa, +0x5e,0x7f,0x16,0x12,0xc4,0xe4,0x7a,0x55,0x48,0x7e,0x35,0x48,0x12,0x8f,0x54,0x2f, +0x50,0x7e,0x65,0x4a,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x2f,0x70,0x12,0x8f,0x54,0x12, +0xc4,0xda,0x7e,0x1d,0x3c,0x2f,0x10,0x7a,0x1d,0x3c,0x7d,0x16,0x1a,0x2, 0x1a,0x0, +0x7e,0x35,0x4a,0x12,0xc4,0xda,0x7e,0x1d,0x40,0x2f,0x10,0x7a,0x1d,0x40,0x7e,0x15, +0x4a,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x48,0x12,0xc4,0xda,0x7e,0x1d,0x44,0x2f,0x10, +0x7a,0x1d,0x44,0xb, 0xe0,0xbc,0xfe,0x38,0x9c,0xa, 0xdf,0x6d,0xcc,0x7f,0x15,0x7f, +0x6, 0x12,0x1e,0x52,0x7f,0x51,0x7f,0x17,0x7f,0x6, 0x12,0x1e,0x52,0x7f,0x71,0x7e, +0x94,0x0, 0x64,0x7e,0x1d,0x3c,0x7d,0x19,0x12,0x1d,0xf6,0x7e,0x87,0x23,0x43,0x7d, +0x18,0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f,0x6, 0x12,0x1e,0x52,0x7a,0x1d,0x3c,0x7e, +0x1d,0x40,0x7d,0x19,0x12,0x1d,0xf6,0x7f,0x6, 0x12,0x1e,0x52,0x7a,0x1d,0x40,0x7e, +0x1d,0x44,0x7d,0x19,0x12,0x1d,0xf6,0x7d,0x18,0x12,0xc4,0xec,0x7a,0x1d,0x44,0x7f, +0x15,0x7f,0x7, 0x12,0x1d,0xe5,0x7e,0x6d,0x44,0x9f,0x61,0x7f,0x15,0x7f,0x5, 0x12, +0x1d,0xe5,0x7e,0x5d,0x3c,0x9f,0x51,0x7f,0x17,0x7f,0x7, 0x12,0x1d,0xe5,0x7e,0x7d, +0x40,0x9f,0x71,0xbe,0x58,0x0, 0x0, 0x68,0x6, 0xbe,0x78,0x0, 0x0, 0x78,0x6, 0x7e, +0x44,0x0, 0x64,0x80,0x18,0x7f,0x16,0x7d,0x19,0x12,0x1d,0xf6,0x7f,0x5, 0x12,0x1e, +0x52,0x7f,0x6, 0x12,0x1d,0xe5,0x7f,0x7, 0x12,0x1e,0x52,0x7d,0x43,0xbe,0x44,0x0, +0x0, 0x18,0x2, 0x6d,0x44,0x7c,0xb9,0xda,0x3b,0x22,0x1a,0x26,0x1a,0x24,0x12,0x1d, +0xe5,0x7f,0x1, 0x22,0x2d,0x35,0x7e,0x1b,0x70,0xa, 0x57,0x22,0x1a,0x2, 0x1a,0x0, +0x2, 0x1e,0x52,0x74,0x4, 0x7d,0x30,0x2, 0xb7,0xeb,0x74,0x1, 0x7a,0xb3,0x38,0xe6, +0x7e,0x34,0x60,0xa3,0x22,0x74,0x1, 0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x1d,0x22, +0x6e,0x34,0xff,0xff,0xb, 0x34,0x7a,0x37,0x2a,0x5e,0x22,0x7e,0x73,0x3a,0x22,0xa, +0x37,0x5e,0x34,0x0, 0x2, 0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4,0x7e,0x7b,0x60,0x22, +0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x31,0xb, 0xa0,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, +0xb3,0x1f,0x34,0x22,0x74,0x1, 0x12,0x12,0xde,0xe4,0x2, 0x0, 0x1e,0x7e,0x34,0x60, +0xd6,0x7e,0x24,0x0, 0xff,0x22,0xa, 0x5b,0x2e,0x54,0x0, 0x8, 0xf5,0xcc,0x22,0xe5, +0x24,0x7e,0x71,0x25,0x7e,0x61,0x26,0x22,0x9, 0x75,0x26,0x33,0x7a,0x73,0x2b,0xf, +0x22,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0x37,0x25,0xf4,0x7a,0x37, +0x34,0x88,0x22,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x34,0x8a,0x22,0x7e,0x73,0x39,0x3, +0x7a,0x73,0x2b,0x20,0x22,0x2d,0x13,0x7e,0xb, 0x50,0xa, 0x25,0x22,0x7d,0x2e,0x12, +0x1d,0xb3,0x7d,0xf3,0x22,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x0, 0x22,0xff,0xc5,0xae, +0x3a,0x51,0xfc,0x3, 0x1, 0x51, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft5435/HQ_D2A_XiaoMi_FT5435_BIEL0X3b_Black_V10_D01_20170817_app.i b/drivers/input/touchscreen/ft5435/HQ_D2A_XiaoMi_FT5435_BIEL0X3b_Black_V10_D01_20170817_app.i new file mode 100644 index 0000000000000..11d15984b5daf --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_D2A_XiaoMi_FT5435_BIEL0X3b_Black_V10_D01_20170817_app.i @@ -0,0 +1,3027 @@ +0x2, 0x16,0x42,0x2, 0xb3,0xb1,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x5a,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x50,0x85,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x69,0x92,0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x69,0xbe,0xd2,0x1, 0x2, 0x28,0xd2,0x2, 0x0, 0x71,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0xf5,0xfd,0xe5,0xfe,0x22,0x2, 0x0, 0x72,0x2, 0x33, +0x6d,0x32,0x32,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xd, 0x7e,0xf, 0x33,0xea, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x33,0xfa,0x7e,0x73,0x33,0xfa,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xc, 0x80,0x2, 0xc2,0xc, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x6a,0x46,0x7e,0x1f,0x33,0xea,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x33,0xea,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x33,0xee,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x33,0xf6,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x33,0xf4,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x3c,0xca,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x52,0x3, 0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x14,0xb5,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x14,0x99,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x14, +0xb5,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x14,0x52,0x61,0x3f,0x7e,0x34,0x14,0x89,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x14,0x99,0x61,0x3f,0x7e,0x34,0x14,0x89,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x14,0x22,0x61,0x3f,0x7e,0x34,0x14,0x6, 0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x14,0x36,0x61,0x3f,0x7e,0x34,0x14,0x7a,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x14, +0x61,0x61,0x3f,0x7e,0x34,0x14,0xb5,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x14,0x99,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x14,0xd9,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x14,0xda,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x33,0xea,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xea,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x33, +0xea,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x33,0xea,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x17,0x56,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x3c,0xd9,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x3c,0xd9,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3c,0xd9,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x3c,0xd9,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3c,0xd9,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3c,0xd9,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x3c,0xca,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x33,0xe2,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x3c, +0xca,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x33,0xe2,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x3c,0xca,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x3c,0xca,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x3c,0xca,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x33,0xea,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x15,0x29,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x15,0x29,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x15,0x29,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x33,0xea,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x3c,0xd9,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0xd9,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x3c,0xd9,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x3c,0xd9,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0x2, 0x37,0xf3,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x3c,0xd9,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x3c,0xd9, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x3c,0xd9, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x3c,0xd9,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3c,0xc6,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3c, +0xc6,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x3c,0xc6,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x3c,0xc6,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x33,0xe2,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x33,0xe2,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x33,0xe2,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x33,0xe2,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x33,0xea,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x33,0xea,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x33, +0xea,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x33,0xea,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x33,0xea,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x33,0xea,0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x33,0xea,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x33,0xea,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x33, +0xea,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x33,0xea, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x33,0xea,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x33,0xea,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x33,0xea,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x15,0x29,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x15,0x29,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0xd9, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x3c,0xd9,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x3c,0xc6,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x3c,0xc6,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x3c,0xc6,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1d,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x3c,0xd9, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0xd9,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x3c,0xd9,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x3c, +0xd9,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x3c,0xd9,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x33,0xea,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x33,0xea,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x33,0xea,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x33,0xea, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x33,0xea,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x33,0xea,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x3c,0xd9,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x3c,0xd9,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x3c,0xd9,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x3c,0xd9,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x3c,0xd9,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x3c,0xd9,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3c,0xca,0x79,0x30, +0x0, 0xe, 0xc2,0x1c,0xe4,0x7a,0xb3,0x3c,0xc5,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x33,0xe2,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xe2,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x3c, +0xca,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x3c, +0xca,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x3c,0xd9,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x3c,0xd9,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x3c,0xd9,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x3c,0xd9,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x3c,0xd9,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x3c, +0xd9,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x3c,0xd9,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1d,0x7e,0xf, 0x3c,0xd9,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x3c,0xd9,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x15,0xc8,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x15,0x5b,0x7d,0x1e,0x12,0x15,0x75,0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x33,0xea,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1c,0x7e,0xf, 0x3c,0xca,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x3c,0xc5,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x3c,0xca,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x6a,0x46,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x33,0xe2,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x33,0xe2,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xea,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xd, 0xe4,0x7a,0xb3,0x33,0xfa,0x7e,0x1f,0x33,0xe2, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x3c,0xc6,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x3c,0xc6,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x3c,0xc6,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x33,0xea,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x33,0xea,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x3c,0xc6,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x3c,0xc6,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x3c,0xd9,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x3c,0xd9,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x17,0x7, 0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x17,0x8, 0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x33,0xe2,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x33,0xe2,0x1b,0x1a,0x10,0x7e, +0x1f,0x33,0xe2,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x33,0xea,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x3c,0xca,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x33,0xe2,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x33,0xe2,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x33, +0xea,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x33,0xea,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x33,0xea,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x33,0xe2,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x15,0x77,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x15,0x77,0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x3c,0xde,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x61,0x0, 0xc2,0xe, 0xc2,0xf, 0xc2,0x11,0x75,0x62, +0x0, 0x75,0x63,0x0, 0xc2,0x13,0xc2,0x14,0x75,0x64,0x0, 0xc2,0x16,0x75,0x65,0x0, +0xc2,0x17,0xc2,0x18,0xc2,0x19,0x75,0x66,0x0, 0xc2,0xa, 0x75,0x5d,0x0, 0x75,0x5e, +0x64,0xc2,0x1a,0xc2,0x1b,0x75,0x67,0x0, 0xd2,0x5, 0xd2,0x6, 0xd2,0x7, 0xd2,0x1c, +0xc2,0xc, 0xd2,0xd, 0x75,0x68,0x0, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x17,0x98,0xb, +0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80,0xa, +0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80,0xdf, +0x2, 0x2f,0x9e,0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd,0xc7,0xfb, +0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, 0xf, 0x2, +0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, 0x17,0xa, +0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94,0x1f,0x81, +0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31,0x17,0x2b, +0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11,0xf, 0x10, +0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, 0x34,0xb, +0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d,0xff,0x78, +0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44,0x7a,0xb, +0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0x32,0x1, 0x19,0x1, 0x0, 0x2, 0xf8,0x4, +0xe7,0x5, 0xce,0x6, 0xc2,0x7, 0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff,0x1, 0x2, +0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, 0x48,0x3, +0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x32,0xdc,0x0, 0x0, 0x0, 0x0, +0x0, 0x1, 0x3, 0xff,0x1, 0x0, 0x1, 0x2d,0x17,0x1, 0x0, 0x1, 0x3b,0xcc,0x0, 0x0, +0x2, 0x3c,0x1e,0x0, 0x0, 0x0, 0x1, 0x3c,0x20,0x0, 0x0, 0x1, 0x3b,0x6c,0xff,0x0, +0x1, 0x33,0xff,0x0, 0x0, 0x1, 0x34,0x4f,0x0, 0x0, 0x2, 0x39,0x26,0x0, 0x0, 0x0, +0x1, 0x39,0x49,0x0, 0x0, 0x1, 0x39,0xc2,0x0, 0x0, 0x1, 0x39,0xc3,0x1, 0x0, 0x1, +0x39,0xc4,0x0, 0x0, 0x3c,0x39,0xf6,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x1, 0x3a,0x6e,0x0, 0x0, 0x1, 0x3a,0x6f,0x0, 0x0, 0x1, 0x3a, +0x70,0x0, 0x0, 0x4, 0x0, 0x14,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3a,0xea,0x1, 0x0, +0x2, 0x3a,0xed,0x0, 0x0, 0x0, 0x1, 0x0, 0x69,0x0, 0x0, 0x1, 0x0, 0x6a,0x0, 0x0, +0x1, 0x0, 0x6b,0x0, 0x0, 0x1, 0x0, 0x6c,0x0, 0x0, 0x1, 0x3a,0xf1,0x1, 0x0, 0x1, +0x3b,0x6b,0x0, 0x0, 0x1, 0x3c,0xdd,0x0, 0x0, 0x1, 0x3c,0xd4,0x0, 0x0, 0x1, 0x3c, +0xd5,0x0, 0x0, 0x1, 0x3c,0xd6,0x0, 0x0, 0x1, 0x3c,0xd7,0x0, 0x0, 0x1, 0x3c,0xd8, +0x0, 0x0, 0x1, 0x34,0x88,0x0, 0x0, 0x1, 0x38,0x25,0x0, 0x0, 0x1, 0x2, 0x8e,0x0, +0x0, 0x2, 0x2, 0xaf,0x0, 0x0, 0x0, 0x1, 0x2, 0xed,0x0, 0x0, 0x4, 0x3, 0xa2,0x0, +0x0, 0x0, 0x0, 0x0, 0x1, 0x3c,0xce,0x0, 0x0, 0x1, 0x3c,0xcf,0x0, 0x0, 0x2, 0x3c, +0xd0,0x0, 0x0, 0x0, 0x1, 0x3c,0xd2,0x64,0x0, 0x1, 0x3c,0xd3,0x0, 0x0, 0x1, 0x3c, +0xde,0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, 0x4, 0x3c,0xc6, +0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x3c,0xca,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x33,0xe2, +0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x33,0xe6,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x33,0xea, +0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x33,0xfb,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x3c,0xd9, +0x0, 0x0, 0x60,0x0, 0x0, 0x7e,0x1f,0x77,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xbe,0x20,0x19,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7e,0x25,0xd7,0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x20,0x0, 0xc, +0x1, 0xf4,0x2, 0x58,0x0, 0xa, 0x1, 0x4a,0x1, 0xf4,0x0, 0xa, 0x0, 0xc8,0x1, 0x5e, +0x0, 0x8, 0x0, 0x78,0x0, 0xfa,0x0, 0x8, 0x0, 0x3c,0x0, 0x64,0x0, 0x6, 0x0, 0xa, +0x0, 0x50,0x0, 0x4, 0x0, 0x0, 0x0, 0xe, 0x1c,0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8, +0x0, 0x28,0x0, 0x0, 0x0, 0x1e,0x74,0x1, 0x7a,0xb3,0x3b,0x94,0x12,0x2e,0xec,0x12, +0x44,0x76,0x12,0x20,0x22,0x12,0x41,0xc7,0x12,0x54,0xde,0x74,0x1, 0x7a,0xb3,0x3a, +0xf5,0x22,0x12,0x5b,0x9a,0x12,0x20,0x57,0x2, 0x20,0x2b,0x7e,0x34,0x0, 0x3, 0x6d, +0x22,0x2, 0x20,0x34,0x7d,0x43,0x7e,0xa3,0x34,0x38,0xbe,0xa0,0x5, 0x50,0x16,0x7e, +0x70,0x4, 0xac,0x7a,0x59,0x43,0x34,0x3b,0x59,0x23,0x34,0x3d,0x7c,0xba,0x4, 0x7a, +0xb3,0x34,0x38,0xc3,0x22,0xd3,0x22,0x6d,0x33,0x7e,0x24,0x6, 0xfc,0x12,0x20,0x34, +0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x7, 0x7a,0x2, 0x20,0x34,0x12,0xaa,0x88,0x74,0x1, +0x7a,0xb3,0x3a,0xf1,0x22,0x7e,0x34,0x60,0xa3,0x12,0x20,0xc9,0x12,0x23,0xda,0x12, +0x50,0xb1,0x12,0x5b,0x51,0x74,0x1, 0x7a,0xb3,0x3b,0x94,0x12,0x2e,0xec,0x12,0x44, +0x6f,0x12,0xbc,0x39,0x12,0x20,0x22,0x12,0x41,0xc7,0x12,0x44,0xba,0x12,0x54,0xde, +0x74,0x1, 0x7a,0xb3,0x3a,0xf5,0x22,0x7e,0x34,0x61,0x4f,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x30,0x7a,0x37,0x31,0x7b,0x7e,0x34,0x61,0x51,0x7e,0x24,0x0, 0xff,0xb, 0x1a, +0x30,0x7a,0x37,0x31,0x7d,0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30, +0x22,0x7e,0x34,0x61,0x55,0x12,0x20,0xc9,0x7a,0x37,0x2f,0xb6,0x7e,0x34,0x61,0xc0, +0x12,0x20,0xc9,0x7a,0x37,0x2f,0xba,0x7e,0x34,0x61,0xbe,0x12,0x20,0xc9,0x7a,0x37, +0x2f,0xb8,0x7e,0x34,0x62,0x18,0x12,0x20,0xc9,0x7a,0x37,0x2f,0xbc,0x7e,0x34,0x61, +0xc2,0x12,0x20,0xc9,0x7a,0x37,0x2f,0xbe,0x7e,0x34,0x61,0xc4,0x12,0x20,0xc9,0x7a, +0x37,0x2f,0xc0,0x7e,0x34,0x61,0xc6,0x12,0x20,0xc9,0x12,0x7f,0x91,0x12,0x20,0xc9, +0x7a,0x37,0x2f,0xc4,0x90,0x61,0xca,0xe4,0x93,0x7a,0xb3,0x2f,0xc6,0xe4,0x7a,0xb3, +0x2f,0xc9,0x12,0x9f,0x2a,0x7e,0x8, 0x2d,0x18,0xe4,0x2, 0x17,0x56,0x12,0x22,0xf3, +0x7e,0xb3,0x3a,0xfc,0xb4,0x1, 0x16,0x7e,0x34,0x62,0x3a,0x12,0x20,0xc9,0x7a,0x37, +0x31,0x7b,0x7e,0x34,0x62,0x3c,0x12,0x20,0xc9,0x7a,0x37,0x31,0x7d,0x7e,0xb3,0x2f, +0xc9,0xb4,0x1, 0x37,0x7e,0x34,0x62,0x44,0x12,0x20,0xc9,0x7a,0x37,0x31,0x7b,0x7e, +0x34,0x62,0x46,0x12,0x20,0xc9,0x7a,0x37,0x31,0x7d,0x7e,0x34,0x62,0x48,0x12,0x20, +0xc9,0x7a,0x37,0x31,0x70,0x7e,0x34,0x62,0x4a,0x12,0x20,0xc9,0x7a,0x37,0x31,0x72, +0x7e,0x34,0x62,0x4c,0x12,0x20,0xc9,0x7a,0x37,0x31,0x74,0x7e,0xb3,0x31,0x23,0x70, +0x21,0x7e,0x27,0x31,0x7b,0x7d,0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12, +0x22,0x65,0xbe,0x34,0x0, 0x28,0x28,0x4, 0x7e,0x34,0x0, 0x28,0x2d,0x32,0x7a,0x37, +0x31,0x7b,0x22,0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69, +0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34,0x0, 0x20, +0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x6, 0x12,0x52,0x3, 0x7e,0x34,0x61,0x4f,0x12, +0x20,0xc9,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x3b,0x6d,0x7e,0x34,0x61,0x51,0x12,0x20, +0xc9,0xe, 0x34,0xe, 0x34,0x7a,0x73,0x3b,0x6e,0x7e,0x34,0x61,0x55,0x12,0x20,0xc9, +0x12,0x22,0x65,0x7a,0x73,0x3b,0x6f,0x7e,0x34,0x61,0x59,0x12,0x20,0xc9,0x12,0x22, +0x65,0x7a,0x73,0x3b,0x70,0x7e,0x34,0x61,0x5b,0x12,0x20,0xc9,0x12,0x22,0x65,0x7a, +0x73,0x3b,0x71,0x7e,0x34,0x61,0x5d,0x12,0x20,0xc9,0x12,0x22,0x65,0x7a,0x73,0x3b, +0x72,0x7e,0x34,0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24,0x0, 0xff,0x7e, +0x8, 0x3b,0x73,0x12,0x17,0x31,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x3b,0x9e,0xe5,0x28, +0x7a,0xb3,0x3b,0x8d,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x22,0x90,0x60, +0x99,0xe4,0x93,0x7a,0xb3,0x31,0x6e,0x90,0x60,0x9e,0xe4,0x93,0x7a,0xb3,0x31,0x6f, +0x7e,0x34,0x61,0x55,0x12,0x20,0xc9,0x12,0xbc,0xae,0x12,0x20,0xc9,0x7a,0x37,0x31, +0x72,0x7e,0x14,0x61,0x5b,0x12,0x5f,0xc8,0x7a,0x27,0x31,0x74,0x7a,0x37,0x31,0x76, +0x90,0x60,0x9d,0xe4,0x93,0x7a,0xb3,0x31,0x7a,0x12,0x20,0xa7,0x6e,0x34,0xff,0xff, +0xb, 0x34,0x7a,0x37,0x31,0x7f,0x7e,0x34,0x62,0x18,0x12,0x20,0xc9,0x7a,0x37,0x31, +0x81,0x90,0x60,0x9f,0xe4,0x93,0x7a,0xb3,0x31,0x85,0x90,0x60,0xa0,0xe4,0x93,0x7a, +0xb3,0x31,0x86,0x7e,0x34,0x60,0xa1,0x12,0x20,0xc9,0x7a,0x37,0x31,0x87,0x7e,0x34, +0x61,0x5d,0x12,0x20,0xc9,0x7a,0x37,0x31,0x83,0xe4,0x7a,0xb3,0x31,0x8c,0x7a,0xb3, +0x16,0x92,0x22,0x12,0x20,0xa7,0x6e,0x34,0xff,0xff,0xb, 0x34,0x7a,0x37,0x31,0x7f, +0x7e,0x34,0x61,0x55,0x12,0x20,0xc9,0x12,0xbc,0xae,0x12,0x20,0xc9,0x7a,0x37,0x31, +0x72,0x7e,0x34,0x61,0x5b,0x12,0x20,0xc9,0x7a,0x37,0x31,0x74,0x22,0x7e,0x34,0x62, +0x4e,0x12,0x20,0xc9,0x7a,0x37,0x31,0x7b,0x7e,0x34,0x62,0x50,0x12,0x20,0xc9,0x7a, +0x37,0x31,0x7d,0x7e,0x34,0x62,0x52,0x12,0x20,0xc9,0x7a,0x37,0x31,0x70,0x7e,0x34, +0x62,0x54,0x12,0x20,0xc9,0x7a,0x37,0x31,0x72,0x7e,0x34,0x62,0x56,0x12,0x20,0xc9, +0x7a,0x37,0x31,0x74,0x22,0xca,0xf8,0x7e,0xf3,0x3b,0xd1,0xbe,0xf0,0x5, 0x78,0x8, +0x12,0x23,0xcf,0x12,0x0, 0x9, 0x80,0x5e,0xbe,0xf0,0x4, 0x78,0x17,0x12,0x23,0xcf, +0x7e,0x34,0x60,0xa3,0x12,0x20,0xc9,0x12,0x23,0xda,0xe4,0x7a,0xb3,0x32,0x23,0x12, +0x2f,0x56,0x80,0x42,0xbe,0xf0,0x6, 0x78,0x1d,0x12,0x23,0xcf,0x7e,0x34,0x60,0xa3, +0x12,0x20,0xc9,0x12,0x23,0xda,0x12,0x3d,0xee,0xe4,0x7a,0xb3,0x32,0x3f,0x12,0x45, +0x4e,0x12,0xbc,0xed,0x80,0x20,0xbe,0xf0,0x7, 0x78,0x21,0x12,0x23,0xcf,0x7e,0x34, +0x60,0xa3,0x12,0x20,0xc9,0x12,0x23,0xda,0x12,0x47,0xcb,0x50,0xfb,0x12,0x47,0xdc, +0x12,0x44,0x7f,0x12,0x41,0xc7,0x74,0x2, 0x7a,0xb3,0x3b,0xd1,0xda,0xf8,0x22,0x74, +0x1, 0x7a,0xb3,0x3b,0xd1,0x22,0x7e,0x34,0x3, 0xe8,0x6d,0x22,0x7a,0x27,0x3c,0xaa, +0x7a,0x37,0x3c,0xac,0x22,0xca,0xd8,0xca,0x79,0x7d,0xd3,0x90,0x60,0x50,0xe4,0x93, +0x7c,0xfb,0x90,0x60,0x51,0xe4,0x93,0x7c,0x8b,0xa, 0x38,0xa, 0xcf,0x2d,0xc3,0xb, +0xc4,0x7d,0x3c,0x7c,0xe7,0x12,0x23,0xd6,0xa9,0xd0,0xc4,0xa9,0xd5,0xcb,0x74,0x7, +0x12,0x0, 0x66,0x7c,0x8b,0x74,0x7, 0x7e,0x70,0xf, 0x12,0x2e,0xe2,0x7e,0x54,0x0, +0x78,0x7e,0x1f,0x33,0xe6,0x79,0x51,0x0, 0x6, 0x7e,0x54,0x0, 0x80,0x7e,0x1f,0x33, +0xe6,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f,0x33,0xe6,0x79,0x51,0x0, +0x10,0xbe,0xd4,0x0, 0x2, 0x78,0xb, 0x7e,0x1f,0x33,0xe6,0x12,0x25,0xc8,0x44,0x1, +0x80,0x20,0x7e,0x1f,0x33,0xe6,0x12,0x25,0xc8,0x44,0x8, 0x1b,0x1a,0x50,0x4d,0xdd, +0x7e,0x1f,0x33,0xe6,0x78,0x7, 0x12,0x25,0xc8,0x54,0xfb,0x80,0x5, 0x12,0x25,0xc8, +0x44,0x4, 0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xe2,0x69,0xe1,0x0, 0x84,0x69,0x51,0x0, +0x90,0x7d,0xf5,0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3,0x3b, +0x9e,0xbe,0xb0,0x6, 0x40,0x3, 0xb4,0xff,0xe, 0x12,0x25,0xd3,0x54,0xe6,0x12,0x25, +0xd0,0x4e,0x54,0x1, 0xa4,0x80,0xc, 0x12,0x25,0xd3,0x5e,0x54,0xfe,0xe6,0x12,0x25, +0xd0,0x44,0xa4,0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x29,0x7e,0x1f,0x33,0xe6, +0x12,0x25,0xc8,0x12,0xbc,0xff,0x7e,0x1f,0x33,0xe6,0x12,0x25,0xc8,0x44,0x50,0x1b, +0x1a,0x50,0x7e,0x34,0x0, 0x2, 0x12,0x3b,0xfd,0x12,0x40,0x1b,0x12,0x3f,0xf8,0x7a, +0x37,0x32,0xe0,0xa1,0x84,0x6c,0xdd,0xa1,0x7e,0x4c,0xdd,0x78,0x4, 0x6c,0x99,0x80, +0x2b,0xbc,0xfd,0x40,0x12,0xa, 0xcd,0x9, 0x9c,0x31,0xd9,0xbe,0x90,0x23,0x40,0x3, +0x7e,0x90,0x22,0xb, 0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3,0x9, 0x9c,0x31, +0xfc,0xbe,0x90,0x1c,0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x7e,0x1f,0x33,0xe6, +0x12,0x25,0xc8,0x12,0xbc,0xff,0xa, 0xc9,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4, +0x7e,0x1f,0x33,0xe6,0x12,0x25,0xc8,0x4d,0x5c,0x1b,0x1a,0x50,0xe5,0xe, 0x60,0x7, +0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x4, 0xe5,0xe, 0xa, +0x3b,0x12,0x3b,0xfd,0x12,0x40,0x1b,0xbe,0xd4,0x0, 0x1, 0x78,0x10,0x12,0x40,0x1b, +0x12,0x3f,0xf8,0x74,0x2, 0xac,0xbd,0x59,0x35,0x32,0xe2,0x80,0xf, 0x12,0x3f,0xf8, +0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59,0x32,0x32,0xe2,0xb, 0xd0,0xbc,0xed, +0x28,0x2, 0x81,0xe9,0xa9,0xd5,0xcb,0x74,0x7, 0x7c,0x78,0x12,0x2e,0xe2,0xa9,0xc0, +0xc4,0x7e,0x1f,0x33,0xe2,0x79,0xe1,0x0, 0x84,0x7e,0x1f,0x33,0xe2,0x79,0xf1,0x0, +0x90,0x6d,0x33,0x7e,0xf, 0x33,0xe6,0x79,0x30,0x0, 0x6, 0x7e,0xf, 0x33,0xe6,0x79, +0x30,0x0, 0x8, 0x7e,0xf, 0x33,0xe6,0x79,0x30,0x0, 0x10,0x7e,0xf, 0x33,0xe6,0x79, +0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x2e,0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22, +0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xe2,0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50,0x22,0x30, +0x8, 0x3b,0xc2,0x8, 0x12,0x23,0x55,0x7e,0x73,0x3b,0xd2,0x7a,0x73,0x31,0x6e,0x7e, +0x73,0x3b,0xd3,0x7a,0x73,0x32,0x3e,0x7e,0x73,0x3b,0xd3,0x7a,0x73,0x32,0x22,0x7e, +0xb3,0x3b,0xd4,0x60,0x18,0x7e,0x34,0x0, 0x2, 0x12,0x23,0xe5,0x7e,0x34,0x0, 0x1, +0x12,0x23,0xe5,0x6d,0x33,0x12,0x23,0xe5,0xe4,0x7a,0xb3,0x3b,0xd4,0x12,0x2e,0x45, +0x2, 0x26,0x23,0xe5,0xc, 0x70,0x2, 0xe1,0x42,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, +0xfe,0x12,0x5a,0xb9,0x12,0x67,0xc3,0x7e,0x8, 0x31,0x8e,0x12,0x9, 0xa1,0xe5,0xc, +0x30,0xe1,0x6, 0x53,0xc, 0xfd,0x12,0xb7,0x9e,0xe5,0xc, 0x30,0xe2,0x32,0x53,0xc, +0xfb,0x7e,0xb3,0x32,0x33,0x60,0x9, 0x7e,0x8, 0x31,0x8e,0x12,0x6, 0xba,0x80,0xb, +0x7e,0xb3,0x32,0x86,0x7e,0x73,0x32,0x85,0x12,0xb, 0xad,0x7e,0x73,0x32,0x33,0x2e, +0x70,0xff,0x92,0x1, 0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x31,0x98,0x12,0xb, 0x1e, +0xe5,0xc, 0x30,0xe3,0x47,0x53,0xc, 0xf7,0x7e,0x73,0x3b,0xff,0x7a,0x73,0x32,0x30, +0x12,0x44,0x4d,0x7a,0xb3,0x34,0x88,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e, +0x73,0x34,0x88,0x7a,0x73,0x3b,0xd7,0x12,0x3f,0xac,0x12,0x3f,0x9e,0x7e,0x73,0x3c, +0x0, 0xbe,0x73,0x32,0x83,0x68,0x6, 0x7a,0x73,0x32,0x83,0xd2,0xe, 0x30,0xe, 0x9, +0xc2,0xe, 0x12,0xaa,0xd5,0xe4,0x12,0xa, 0x66,0x12,0x54,0xde,0xe5,0xc, 0x30,0xe4, +0xf, 0x53,0xc, 0xef,0x7e,0x43,0x3c,0x1, 0x7e,0x50,0xa, 0xac,0x45,0x12,0x3d,0xce, +0xe5,0xc, 0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e,0x73,0x3b,0xed,0xbe,0x70,0x7, 0x28, +0x6, 0x74,0x7, 0x7a,0xb3,0x3b,0xed,0xa9,0xd5,0xcb,0x74,0xe, 0x12,0x0, 0x66,0x7c, +0x7b,0x5e,0x70,0xf, 0x7e,0x63,0x3b,0xed,0xa, 0x26,0x2e,0x24,0x0, 0x3, 0x12,0xa0, +0x60,0x7c,0x65,0x4c,0x76,0x74,0xe, 0x12,0x27,0x43,0x12,0x0, 0x66,0x12,0x2e,0xe5, +0x7e,0x73,0x3b,0xf0,0x7a,0x73,0x32,0x35,0x7e,0x73,0x3b,0xef,0x7a,0x73,0x32,0x40, +0x12,0xbc,0xed,0xe5,0xc, 0x30,0xe5,0xa, 0x53,0xc, 0xdf,0x7e,0xb3,0x3b,0xd7,0x2, +0x3e,0x66,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0x7e,0xb3,0x3b,0x92,0x14,0x68,0x42, +0x14,0x68,0x78,0x14,0x68,0x4a,0x24,0x3, 0x78,0x69,0x12,0xbd,0x17,0x38,0x3, 0x30, +0x12,0xd, 0x6d,0x33,0x7a,0x37,0x3c,0x6d,0xe4,0x7a,0xb3,0x3c,0x6f,0x80,0x5c,0x7e, +0xb3,0x3b,0x73,0x30,0xe0,0x55,0x7e,0x73,0x3b,0x74,0xa, 0x27,0x7e,0x34,0x4, 0x0, +0xad,0x32,0xbe,0x37,0x3c,0x6d,0x50,0x43,0x12,0x50,0x28,0xe4,0x7a,0xb3,0x3c,0x71, +0x80,0x39,0x12,0xbd,0x17,0x28,0x2f,0xe4,0x7a,0xb3,0x3b,0x92,0xd2,0x1b,0x80,0x26, +0x74,0xff,0x7a,0xb3,0x3b,0x6c,0x7e,0x34,0x60,0xa5,0x12,0x20,0xc9,0x12,0x23,0xda, +0x12,0x2a,0xd, 0x12,0x20,0x75,0xe4,0x7a,0xb3,0x3b,0x92,0x7a,0xb3,0x3c,0xd3,0xd2, +0x1b,0x80,0x8, 0x12,0x50,0x2e,0xe4,0x7a,0xb3,0x3c,0xd3,0x12,0x8d,0xf3,0x2, 0x27, +0xd1,0xca,0x3b,0x7e,0xb3,0x3b,0x92,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x28,0xcf,0x6c, +0xee,0x6c,0xff,0x90,0x61,0x61,0xe4,0x93,0x7c,0xdb,0x90,0x61,0x63,0xe4,0x93,0x7c, +0xcb,0x12,0x8e,0x44,0x7d,0xf3,0x12,0x47,0xcb,0x50,0xfb,0x74,0x1, 0x7a,0xb3,0x3c, +0x70,0x12,0x2a,0x62,0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x29,0xf2,0x12, +0x2f,0xcf,0x7e,0xe7,0x32,0x2e,0x7a,0xe5,0x25,0x7e,0xb3,0x32,0x1b,0xf5,0x24,0x74, +0x4, 0x7a,0xb3,0x32,0x1b,0x7e,0xe7,0x32,0x2e,0x5e,0xe4,0x0, 0x3f,0x7a,0xe7,0x32, +0x2e,0x7e,0xb3,0x32,0x1b,0x12,0x69,0x3b,0x7c,0x7b,0x74,0x6, 0xac,0x7b,0x7e,0x24, +0x0, 0x4, 0x12,0x15,0x29,0x7d,0x23,0x7d,0x3f,0x12,0x22,0x65,0xad,0x32,0x7a,0x37, +0x32,0x28,0x12,0x2c,0xb1,0x12,0x8e,0x8b,0x80,0x58,0x12,0x23,0xd6,0x20,0xf, 0x56, +0x7c,0xbd,0x12,0x8e,0xdd,0x12,0x2d,0x45,0x80,0xf, 0x80,0x7, 0x12,0x29,0x1c,0xe4, +0x12,0x29,0x54,0x20,0x93,0xf6,0x12,0x28,0xec,0x30,0x1c,0xf7,0x30,0x1b,0xf4,0xd2, +0x1, 0x12,0x28,0xd2,0xe4,0x12,0x13,0xde,0xb, 0xe0,0x12,0x88,0x54,0x12,0x8e,0xe7, +0x7e,0xb3,0x3c,0x6f,0x70,0x6, 0x74,0x1, 0x7a,0xb3,0x3c,0x70,0x7e,0x73,0x3c,0xc5, +0xa, 0x37,0x5e,0x34,0x0, 0x2, 0x68,0xa, 0x7e,0xf0,0x1, 0xe4,0x7a,0xb3,0x3b,0x92, +0x80,0x4, 0xbc,0xce,0x38,0xa4,0xe4,0x7a,0xb3,0x32,0x25,0x7e,0x35,0x25,0x7a,0x37, +0x32,0x2e,0xe5,0x24,0x7a,0xb3,0x32,0x1b,0x4c,0xff,0x68,0x3, 0x12,0x41,0xc7,0xda, +0x3b,0x22,0x30,0x1, 0x6, 0x12,0x2a,0x5a,0x2, 0x13,0x96,0x12,0x2f,0xc0,0xc2,0x2, +0x2, 0x28,0xe3,0xa9,0xd0,0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22,0x30,0x1c,0x5, 0xc2, +0x1, 0x12,0x28,0xd2,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1b,0x3, 0x20,0x1c,0x14, +0x12,0x29,0x1c,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x29,0x54,0xa9,0xd0, +0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x1, 0x2, 0x28,0xd2,0x74,0x81,0x7a,0xb3, +0x3c,0xce,0x22,0x80,0x1d,0x12,0x29,0x1c,0x12,0x2f,0xc7,0x68,0x5, 0xc2,0x1, 0x12, +0x28,0xd2,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1b,0x15,0xe4,0x12, +0x29,0x54,0x20,0x93,0xe0,0x12,0x29,0x1c,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x74,0x2, +0x2, 0x29,0x54,0x22,0x7c,0xab,0x7e,0xb3,0x3c,0xce,0xb4,0x81,0x38,0x4c,0xaa,0x78, +0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2,0xaf,0xa9,0xd0,0xce, +0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0,0x2, 0x78,0x16,0xc2, +0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3c,0xce,0x22,0x7a,0x35,0x5f,0x12,0x29, +0xd0,0xb4,0x2, 0x29,0x80,0x7, 0x12,0x29,0x1c,0xe4,0x12,0x29,0x54,0x30,0x1b,0xf6, +0x80,0x11,0x12,0x29,0x1c,0xe4,0x12,0x29,0x54,0x7e,0xb3,0x3b,0xcd,0x44,0x80,0x7a, +0xb3,0x3b,0xcd,0x12,0x29,0xd0,0xbe,0xb0,0x2, 0x68,0xe7,0xe4,0x22,0x74,0x1, 0x22, +0x7e,0xb3,0x3b,0xcd,0xc4,0x54,0x7, 0x22,0xd2,0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12, +0x2f,0xc7,0x68,0x7, 0xc2,0x0, 0xc2,0x1, 0x12,0x28,0xd2,0x12,0x29,0x23,0x30,0x1b, +0xeb,0x22,0x7c,0xab,0x80,0xe, 0x7e,0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70, +0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xea,0x22,0x12,0x29,0x1c, +0x12,0x2f,0xdf,0x75,0xcd,0x0, 0xa9,0xd6,0xeb,0xa9,0xd7,0xcd,0xc2,0xce,0x12,0xbc, +0xdb,0x12,0x2e,0xb3,0x74,0x1, 0x12,0x29,0x54,0xa9,0xc6,0xeb,0xa9,0xc7,0xcd,0xd2, +0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x2a,0x39,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, +0x12,0x27,0x43,0x7a,0x61,0xfc,0x12,0x2e,0xe5,0x12,0x2f,0x1c,0xd2,0x0, 0x12,0xb5, +0x20,0x12,0x2a,0x5a,0x12,0x13,0xde,0x2, 0x13,0x96,0xd2,0x2, 0x12,0x28,0xe3,0x74, +0x1, 0x22,0x7a,0xb3,0x32,0x21,0x70,0x14,0x12,0x38,0x2a,0x12,0x2a,0x91,0x7e,0x18, +0x6, 0x76,0x7a,0x1f,0x6, 0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x10,0xb4,0x1, 0x11,0x12, +0x2f,0xf1,0x12,0x2a,0x91,0x12,0xbc,0x44,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8, +0x22,0x7a,0x1f,0x32,0x1d,0x7a,0xf, 0x32,0x19,0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4, +0x12,0x2a,0x62,0x12,0x2a,0xb2,0xe4,0x12,0x0, 0x1e,0x74,0x1, 0x12,0x2a,0x62,0x2, +0x2a,0xb2,0xca,0x3b,0x7e,0xd3,0x31,0x94,0x7e,0xc3,0x31,0x95,0x7e,0x8, 0x26,0x65, +0x12,0xb6,0xc2,0x7e,0x8, 0x26,0xab,0x7e,0x34,0x0, 0x46,0x12,0x17,0x56,0x7e,0x8, +0x26,0xf1,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x17,0x56,0x7e,0x8, 0x26,0xfb,0x7e,0x34, +0x0, 0xa, 0x12,0x17,0x56,0x7e,0xf3,0x32,0x1d,0x7e,0x18,0x31,0xfd,0x7a,0x1d,0x24, +0x7e,0x18,0x26,0xf1,0x7a,0x1d,0x28,0x7c,0xbd,0x7c,0x7c,0x7e,0x8, 0x31,0xda,0x12, +0xb7,0xe0,0x6c,0xee,0x80,0x2b,0xa, 0x3e,0x9, 0xa3,0x31,0xfd,0xa, 0x3a,0x2e,0x34, +0x16,0xeb,0x12,0x47,0xed,0x7c,0xab,0xbe,0xa0,0x1c,0x50,0x13,0xa, 0x3e,0x12,0x2b, +0xca,0xa, 0x4a,0x19,0xb4,0x26,0x65,0x7e,0xb3,0x32,0x1c,0x19,0xb4,0x26,0xab,0xb, +0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee,0x80,0x24,0xa, 0x3e,0x9, 0xa3,0x31,0xda,0xbe, +0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, 0x3c,0x2d,0x32,0x12,0x2b,0xca,0xa, 0x4a,0x19, +0xb4,0x26,0x81,0x7e,0xb3,0x32,0x1c,0x19,0xb4,0x26,0xc7,0xb, 0xe0,0xbc,0xde,0x38, +0xd8,0x7e,0xb3,0x32,0x1e,0x7e,0x8, 0x27,0x5, 0x60,0x9, 0x7e,0x18,0x26,0xf1,0x12, +0xb5,0xf2,0x80,0x3, 0x12,0xb7,0x8d,0x6c,0xee,0x7e,0x18,0x27,0x5, 0x7a,0x1f,0x26, +0x55,0x74,0x2, 0xac,0xbe,0x49,0x35,0x26,0xf1,0x7a,0x37,0x26,0x59,0x74,0x2, 0xac, +0xbe,0x49,0x35,0x26,0xfb,0x7a,0x37,0x26,0x5b,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34, +0x26,0x65,0x6d,0x22,0x7a,0x1f,0x26,0x5d,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x26, +0xab,0x7a,0x1f,0x26,0x61,0x7e,0x8, 0x26,0x55,0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1, +0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b,0x22,0x2e,0x37,0x32,0x1f,0x7e,0x39, +0xb0,0x22,0x7c,0x96,0x7c,0xa7,0x12,0x2a,0x62,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, +0x12,0x29,0xf2,0x7c,0xb9,0x12,0x0, 0x1e,0x2, 0x2b,0xeb,0xca,0x3b,0x7e,0xe3,0x31, +0x95,0x7e,0xf3,0x32,0x1b,0x74,0x1, 0x7a,0xb3,0x32,0x1b,0x12,0x2c,0xb1,0x12,0x2f, +0xcf,0x12,0x2e,0xa4,0x7e,0x17,0x32,0x1f,0x6d,0x0, 0x12,0x17,0x56,0x7e,0xd0,0x7, +0x12,0x23,0xd6,0x6c,0xcc,0x80,0x1f,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e, +0x34,0x14,0x78,0xfb,0x7c,0x67,0xa, 0x2c,0x2e,0x27,0x32,0x1f,0x7e,0x29,0x70,0x4c, +0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x2e,0xa, 0xa, 0x3c,0xbd,0x32,0x48,0xd8,0x12, +0x2d,0x34,0x30,0x1c,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0x8, 0x6, 0xfc,0x7e,0xb3, +0x31,0x94,0x7c,0x7e,0x12,0x69,0x33,0x6c,0xcc,0x80,0x2a,0x74,0x2, 0xac,0xbc,0x49, +0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x1a,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60, +0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff,0xa, 0x2c,0x2e,0x27,0x32,0x1f, +0x12,0x74,0xcd,0xb, 0xc0,0x12,0x2e,0xa, 0xa, 0x3c,0xbd,0x32,0x48,0xcd,0x1b,0xd0, +0xbe,0xd0,0x0, 0x48,0x2, 0x81,0x10,0x12,0x2d,0x57,0x74,0x2, 0x12,0x2f,0xd7,0x12, +0x2c,0xb8,0x74,0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x32,0x1b,0x12,0x2c,0xb1,0xda,0x3b, +0x22,0x7e,0x8, 0x31,0x8e,0x2, 0x5, 0xb4,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x2c,0x13, +0x12,0xb6,0xc2,0x7e,0xa3,0x31,0x94,0x7e,0x73,0x31,0x95,0x6c,0xee,0x80,0x1f,0xa, +0x2e,0x9, 0x62,0x31,0xfd,0xa, 0x26,0x12,0x77,0xf1,0x7c,0x6b,0xbe,0x60,0x1c,0x50, +0xb, 0xa, 0x2e,0x12,0x2e,0x9c,0xa, 0x26,0x19,0xb2,0x2c,0x13,0xb, 0xe0,0xbc,0x7e, +0x38,0xdd,0x6c,0xee,0x80,0x1c,0xa, 0x2e,0x9, 0x62,0x31,0xda,0xbe,0x60,0x23,0x50, +0xf, 0xa, 0x1e,0xa, 0x27,0x2d,0x21,0x12,0x2e,0x9c,0xa, 0x26,0x19,0xb2,0x2c,0x2f, +0xb, 0xe0,0xbc,0xae,0x38,0xe0,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x2c, +0x13,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40, +0xe7,0xda,0x79,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x32,0x1d,0x12,0x2c,0xb8, +0x74,0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x2d,0xdb, +0x7e,0xb3,0x32,0x1d,0x2, 0xe, 0x94,0xca,0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, +0x7a,0xb3,0x32,0x1b,0x12,0x2e,0xa4,0x7c,0xe7,0x80,0x63,0x12,0x23,0xd6,0x12,0x2d, +0x34,0x30,0x1c,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0x8, 0x6, 0xfc,0x12,0x69,0x2b, +0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, 0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14, +0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17,0x32,0x1f,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28, +0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18,0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12, +0x2b,0xca,0xbe,0xb0,0xff,0x68,0x8, 0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, +0xd0,0x12,0x2e,0xa, 0xa, 0x3d,0xbd,0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf, +0x1b,0xf0,0x4c,0xaa,0x78,0x95,0xda,0x79,0xda,0xd8,0x22,0x6c,0xaa,0x80,0x22,0xa, +0x3a,0x9, 0x73,0x31,0xfd,0x2e,0x34,0x16,0xeb,0x12,0x47,0xed,0x7c,0x7b,0xa, 0x47, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0xf, 0x33,0xe2,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, +0xa0,0x7e,0x63,0x31,0x95,0xbc,0x6a,0x38,0xd6,0x22,0x7e,0x73,0x31,0x95,0xa, 0x37, +0x7e,0x53,0x31,0x94,0xa, 0x25,0x2d,0x23,0x22,0x7e,0xd7,0x32,0x2e,0xbe,0xb0,0x1, +0x28,0x2, 0xe4,0x22,0x12,0x68,0x21,0x12,0x2c,0xb1,0x7a,0xd7,0x32,0x2e,0x7e,0x73, +0x32,0x1b,0xa, 0x37,0x3e,0x34,0x3e,0x34,0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, 0x12, +0x2d,0x45,0x74,0x1, 0x22,0xe5,0xd, 0x60,0x52,0xe5,0xd, 0x30,0xe0,0x6, 0x53,0xd, +0xfe,0x12,0x2c,0xb1,0xe5,0xd, 0x30,0xe1,0x14,0x53,0xd, 0xfd,0x7e,0xb3,0x3c,0x11, +0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12,0x2f,0xd7,0x12,0xb6,0x4c,0xe5,0xd, 0x30, +0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a,0xb3,0x3c,0x12,0x7e,0xb3,0x3c,0x11,0x70,0xa, +0x74,0x1, 0x12,0x0, 0x1e,0x12,0x38,0x2a,0x80,0x7, 0xe4,0x12,0x0, 0x1e,0x12,0x2f, +0xf1,0x12,0x2a,0x91,0x7e,0xb3,0x32,0x1d,0x2, 0x2c,0xb8,0x22,0x2e,0x27,0x32,0x1f, +0x7e,0x29,0xb0,0x22,0x7e,0x73,0x31,0x95,0xa, 0x27,0x7e,0x73,0x31,0x94,0xa, 0x37, +0x2d,0x32,0x22,0x12,0x2f,0xc0,0xc2,0x0, 0x12,0x2f,0xe8,0xc2,0x2, 0x12,0x28,0xe3, +0xc2,0x0, 0x12,0xb5,0x20,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x0, 0x66,0x7a,0x1b,0xb0, +0x74,0xf, 0x6c,0x77,0x12,0x27,0x43,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, +0x2e,0xe5,0x12,0x27,0x43,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0x12,0xaa,0xd5,0x12, +0x13,0xf5,0x12,0xb6,0xf5,0xe4,0x12,0xa, 0x66,0x7e,0x24,0x3, 0xd4,0x12,0x3d,0xce, +0x74,0x1, 0x12,0x2a,0x62,0x12,0x69,0x1b,0x7e,0x34,0xd0,0xc, 0x12,0x1, 0xe, 0x12, +0x2a,0x9a,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13,0x1, 0xca,0xf8,0xa2,0xaf, +0xe4,0x33,0x7c,0xfb,0xd2,0x0, 0x12,0x2f,0xe8,0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0, +0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e, +0xa9,0xd0,0xcd,0x74,0x41,0x12,0x29,0xf2,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0, +0xff,0x92,0xaf,0xda,0xf8,0x22,0x7e,0xb3,0x32,0x23,0x70,0x41,0x12,0x47,0xcb,0x50, +0xfb,0xe4,0x6c,0x77,0x6c,0x66,0x12,0x2b,0xd2,0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, +0xf4,0x7e,0xb3,0x32,0x93,0x12,0x68,0x78,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, +0x12,0x2b,0xd2,0x7e,0x8, 0x7, 0x7a,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x2d,0x11,0x12, +0x68,0x78,0x74,0x2, 0x7a,0xb3,0x32,0x23,0xe4,0x7a,0xb3,0x16,0x90,0x22,0x12,0x50, +0xb1,0x12,0x21,0xc3,0x12,0x5b,0x51,0x12,0x20,0x6, 0x7e,0xb3,0x3b,0x94,0x24,0xfd, +0x68,0x9, 0xb, 0xb1,0x78,0xf4,0x12,0x45,0xfe,0x80,0xef,0x12,0x32,0xf4,0x80,0xea, +0xe4,0x12,0x13,0xde,0x2, 0x13,0x96,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x1, 0x22,0x6d, +0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x12,0x0, 0x1e,0x7e,0xb3,0x32,0x1d,0x22,0x12, +0x2f,0xc7,0x68,0xfb,0x20,0x93,0xfd,0x22,0xa9,0xd0,0xce,0xa2,0x0, 0xa9,0x95,0xc9, +0x22,0x7e,0x1f,0x2d,0x13,0x7e,0xf, 0x2d,0xf, 0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0, +0x34,0x38,0x2, 0x21,0xb, 0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x32,0x31,0x41,0x2a, +0xbe,0xa0,0x36,0x68,0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, +0x24,0x7a,0x25,0x8, 0x2e,0x37,0x32,0xda,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, +0x41,0x2a,0x75,0x5c,0x36,0x41,0x2a,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78, +0x1b,0x7e,0xf3,0x3b,0xf1,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0xf1,0xbe,0xa0,0x39,0x78, +0x3, 0x75,0x5c,0x38,0xa, 0x3f,0x9, 0xb3,0x32,0x42,0x41,0x2a,0xbe,0xa0,0x3a,0x68, +0x5, 0xbe,0xa0,0x3b,0x78,0x1b,0x7e,0xf3,0x3b,0xf3,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b, +0xf3,0xbe,0xa0,0x3b,0x78,0x3, 0x75,0x5c,0x3a,0xa, 0x3f,0x9, 0xb3,0x32,0x65,0x41, +0x2a,0xbe,0xa0,0xfb,0x78,0x6, 0x7e,0xb3,0x32,0x33,0x41,0x2a,0xbe,0xa0,0x5e,0x78, +0x26,0x7e,0xf, 0x33,0xe2,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e, +0x54,0x5e,0x54,0x0, 0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c, +0xa7,0x4c,0xba,0x44,0x80,0x41,0x2a,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78, +0x1b,0x7e,0xf3,0x3b,0xf5,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0xf5,0xbe,0xa0,0x3d,0x78, +0x3, 0x75,0x5c,0x3c,0xa, 0x3f,0x9, 0xb3,0x31,0x9b,0x41,0x2a,0xbe,0xa0,0x3e,0x68, +0x5, 0xbe,0xa0,0x3f,0x78,0x1b,0x7e,0xf3,0x3b,0xf7,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b, +0xf7,0xbe,0xa0,0x3f,0x78,0x3, 0x75,0x5c,0x3e,0xa, 0x3f,0x9, 0xb3,0x31,0xbe,0x41, +0x2a,0xbe,0xa0,0x40,0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x3b, +0xcd,0x41,0x2a,0xbe,0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x3c, +0x12,0x7c,0xbf,0x4, 0x7a,0xb3,0x3c,0x12,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x5c,0x4e, +0xa, 0x3f,0x2e,0x37,0x32,0xd8,0x7e,0x39,0xb0,0x41,0x2a,0xbe,0xa0,0x51,0x68,0x5, +0xbe,0xa0,0x52,0x78,0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e, +0xb3,0x3c,0x1d,0xa, 0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x3c, +0x1d,0xbe,0xa0,0x52,0x78,0x3, 0x75,0x5c,0x51,0x7c,0xb7,0x41,0x2a,0xbe,0xa0,0x5c, +0x68,0x5, 0xbe,0xa0,0x5d,0x78,0x1a,0x7e,0xf3,0x3b,0xe6,0x7c,0xbf,0x4, 0x7a,0xb3, +0x3b,0xe6,0xbe,0xa0,0x5d,0x78,0x3, 0x75,0x5c,0x5c,0x7c,0xbf,0x12,0x32,0x2d,0x41, +0x2a,0xbe,0xa0,0x60,0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x3c, +0x4e,0x41,0x2a,0xbe,0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x7e,0xbe,0xa0,0xf4,0x68, +0x5, 0xbe,0xa0,0xf5,0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, +0x9, 0xb3,0x32,0xe0,0xbe,0xa0,0xf5,0x78,0x61,0x75,0x5c,0xf4,0x80,0x5c,0xbe,0xa0, +0xf0,0x68,0x5, 0xbe,0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80, +0x49,0xbe,0xa0,0xf2,0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14, +0x7e,0x1f,0x32,0xdc,0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56, +0x80,0x28,0x7d,0x53,0x80,0x24,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x1b,0xbe, +0xa0,0xf7,0x78,0xd, 0x7e,0x34,0x62,0x4e,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x50,0x80, +0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7c,0xab,0xbe, +0xa0,0x0, 0x40,0x11,0x7e,0xb3,0x31,0x8f,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49, +0x25,0x34,0x0, 0x80,0x51,0x7e,0x13,0x31,0x8f,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x31, +0x8e,0xa, 0x10,0xa, 0x21,0x2d,0x12,0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e, +0x34,0x3e,0x34,0x49,0x23,0x37,0x99,0x80,0x2d,0x7e,0x3, 0x31,0x8e,0xa, 0x20,0xa, +0x11,0x7d,0x41,0x2d,0x42,0xa, 0x3a,0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, +0x2d,0x1, 0xbd,0x30,0x58,0xe, 0x9d,0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23, +0x37,0x9b,0x80,0x2, 0xe4,0x22,0x7e,0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34, +0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80, +0x38,0x7c,0xbf,0x12,0x32,0x2d,0xa, 0x1b,0x7e,0x63,0x31,0x8f,0x7e,0x70,0x2, 0xac, +0x67,0x7e,0x10,0x2, 0xac,0x1f,0x2d,0x3, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x12,0x32, +0xec,0x9d,0x35,0x1b,0x1a,0x10,0xb, 0xf0,0x12,0x32,0xec,0x7e,0x73,0x31,0x8f,0xa, +0x27,0x2d,0x25,0xa, 0x3f,0xbd,0x32,0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x31,0x8e, +0x74,0x2, 0xa4,0x22,0x12,0x3d,0x9a,0x7e,0xb3,0x3b,0x94,0xb4,0x3, 0x69,0x12,0xb5, +0x2b,0x12,0x23,0xd6,0x12,0x25,0xdf,0x7e,0xb3,0x3b,0xcd,0x30,0xe7,0xe9,0x12,0x40, +0xc8,0x12,0x2e,0xa4,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, 0xfc, +0x12,0x17,0x31,0x1b,0xfd,0x12,0x2e,0xa4,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x7e, +0x7e,0x8, 0x5, 0x7a,0x12,0x17,0x31,0x1b,0xfd,0x7e,0xb3,0x32,0x3e,0xb4,0x1, 0x15, +0x12,0xa7,0x66,0x12,0x8a,0x5f,0x12,0x4c,0xbe,0x12,0x56,0x77,0x12,0x87,0x75,0x12, +0x33,0x77,0x12,0x40,0x3e,0x12,0x3e,0x43,0x12,0x32,0xad,0x7e,0xb3,0x3b,0xcd,0x54, +0x7f,0x7a,0xb3,0x3b,0xcd,0x80,0x90,0x12,0x47,0xd6,0x2, 0x0, 0x6e,0xe4,0x7a,0xb3, +0x32,0x23,0x7a,0xb3,0x32,0x3f,0x22,0x74,0x1, 0x12,0x33,0xc9,0x74,0x2, 0x12,0x33, +0xc9,0x74,0x3, 0x12,0x33,0xc9,0x12,0x34,0x28,0x12,0x33,0xe6,0x12,0x33,0xe6,0x74, +0x4, 0x12,0x33,0xc9,0x12,0xa3,0x72,0x12,0x33,0xe6,0x12,0x78,0xd7,0x74,0x5, 0x12, +0x33,0xc9,0x12,0x77,0x6a,0x12,0x4e,0xf5,0x12,0x33,0xe6,0x12,0x98,0x8a,0x12,0x33, +0xe6,0x74,0x6, 0x12,0x33,0xc9,0x12,0x35,0xc5,0x12,0x33,0xe6,0x74,0x7, 0x12,0x33, +0xc9,0x12,0xa0,0x8e,0x74,0x8, 0x2, 0x33,0xc9,0xca,0xf8,0x7c,0xfb,0x12,0x33,0xe6, +0xa, 0x2f,0x12,0xa0,0x60,0x7e,0x73,0x2f,0xa5,0xa, 0x37,0x2d,0x32,0xa, 0x2f,0x19, +0x72,0x1f,0x33,0xda,0xf8,0x22,0xca,0x79,0x6c,0xff,0x6c,0xee,0x80,0x2e,0x7c,0xbe, +0x12,0x4e,0xdc,0x60,0x25,0x7e,0x34,0x0, 0x2, 0xca,0x39,0xac,0x7e,0x2e,0x34,0x2e, +0x1b,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x2e,0x1b,0x6d,0x0, 0x12,0x17, +0x31,0x1b,0xfd,0x7c,0xbf,0x12,0x74,0x91,0xb, 0xf0,0xb, 0xe0,0x12,0x4f,0xdb,0x38, +0xcd,0x7a,0xf3,0x2f,0xa5,0xda,0x79,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6d,0x88, +0x7a,0x87,0x3c,0x6b,0xe4,0x7a,0xb3,0x26,0x79,0xe5,0x63,0xbe,0xb0,0xff,0x50,0x2, +0x5, 0x63,0x7e,0xb3,0x2f,0xa5,0x60,0xc, 0x12,0x7e,0x3e,0xb, 0x1a,0x80,0xbe,0x87, +0x7, 0xfa,0x28,0xa, 0xc2,0x12,0x6d,0x88,0x7a,0x87,0x3c,0x2c,0xa1,0x57,0x12,0x92, +0xbb,0x60,0x16,0x7e,0x34,0x62,0x14,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x80,0x7a,0x87, +0x3c,0x22,0x12,0x37,0xd0,0x7a,0x87,0x3c,0x2c,0x7e,0x87,0x3c,0x22,0x4d,0x88,0x68, +0x6, 0x74,0x1, 0x7a,0xb3,0x2f,0xca,0x6c,0xff,0x80,0x77,0xe4,0xa, 0x3f,0x19,0xb3, +0x26,0x55,0x12,0xbc,0x7f,0x7e,0x8, 0x26,0x73,0x7c,0xbd,0x7c,0x7e,0x12,0x90,0xe1, +0x7d,0x93,0x7e,0x87,0x3c,0x2c,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x3c,0x2c,0x7e,0x87, +0x3c,0x6b,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x3c,0x6b,0xe5,0x63,0xbe,0xb0,0x5, 0x38, +0x1f,0x7e,0x8, 0x3c,0x2e,0x12,0x92,0x2c,0x50,0x7, 0x12,0x37,0xea,0xd2,0x0, 0x80, +0x2f,0x7e,0x8, 0x3c,0x2e,0x7e,0x18,0x26,0x73,0x12,0x92,0x72,0x50,0x22,0x80,0x10, +0x12,0x37,0xd0,0xbd,0x89,0x38,0x19,0x7e,0x8, 0x26,0x73,0x12,0x8e,0xf7,0x50,0x10, +0x12,0x37,0xea,0x7e,0x8, 0x26,0x79,0x7e,0x18,0x26,0x73,0x12,0x92,0x6, 0xd2,0x0, +0xb, 0xf0,0x12,0x35,0xbe,0x38,0x84,0x30,0x0, 0x33,0x6c,0xff,0x80,0x1c,0x12,0xbc, +0x7f,0x7e,0x8, 0x26,0x79,0x12,0x92,0x2c,0x40,0x9, 0xa, 0x3f,0x9, 0xb3,0x26,0x55, +0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x74,0xd6,0xb, 0xf0,0x12,0x35,0xbe,0x38,0xdf,0x75, +0x63,0x0, 0x7e,0x34,0x62,0x14,0x12,0x20,0xc9,0x7a,0x37,0x3c,0x22,0x7e,0x63,0x26, +0x79,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x26,0x79,0x7e,0x8, +0x3c,0x2e,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x37,0x3c,0x22,0x4d,0x33,0x78,0x39,0x90, +0x62,0xf, 0xe4,0x93,0xa, 0x3b,0xbe,0x37,0x3c,0x2c,0x38,0x40,0x7c,0x7b,0x1e,0x70, +0xa, 0x37,0xbe,0x37,0x3c,0x6b,0x38,0x34,0x90,0x60,0x51,0x12,0x37,0xe1,0x7e,0x73, +0x2e,0x18,0xa, 0x37,0xbd,0x32,0x8, 0x24,0x90,0x60,0x50,0x12,0x37,0xe1,0x7e,0x73, +0x2e,0x17,0xa, 0x37,0xbd,0x32,0x8, 0x14,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12,0x74, +0xd6,0xb, 0xf0,0x12,0x35,0xbe,0x38,0xf4,0xd2,0x0, 0x80,0x6, 0x6d,0x33,0x7a,0x37, +0x3c,0x2c,0xa2,0x0, 0x92,0x12,0x12,0x92,0xa4,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73, +0x2f,0xa5,0xbc,0x7f,0x22,0xca,0xd8,0xca,0x79,0x7e,0xd4,0x0, 0x6, 0x7e,0xb3,0x2f, +0xa5,0x70,0x14,0x12,0x37,0xd8,0xc2,0x13,0x9f,0x11,0x7a,0x1d,0x18,0x12,0xbc,0x72, +0xe4,0x7a,0xb3,0x39,0xef,0xe1,0x9c,0xe4,0x7a,0xb3,0x39,0xef,0x6c,0xdd,0xe1,0x5c, +0x7e,0x73,0x39,0xef,0xbe,0x70,0x2, 0x40,0x20,0x7c,0xfd,0x80,0x15,0x7e,0x18,0x0, +0x1, 0x7c,0xbf,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x37,0xa8,0x7a,0x1d,0x18, +0xb, 0xf0,0x12,0x35,0xbe,0x38,0xe6,0xe1,0x66,0x7e,0x44,0x0, 0xff,0x6c,0xff,0x80, +0x36,0xbc,0xdf,0x68,0x30,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x2e,0x1b,0xa, 0x27,0x12, +0x37,0xb7,0x12,0x37,0xc9,0xbe,0x34,0x0, 0x4, 0x58,0x1a,0x74,0x2, 0xac,0xbf,0x9, +0x75,0x2e,0x1c,0xa, 0x27,0x12,0x37,0xc0,0x12,0x37,0xc9,0xbe,0x34,0x0, 0x4, 0x58, +0x4, 0x6d,0x44,0x80,0x7, 0xb, 0xf0,0x12,0x35,0xbe,0x38,0xc5,0x4d,0x44,0x78,0x12, +0x12,0x37,0xa1,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x37,0xa8,0x7a,0x1d,0x18, +0xe1,0x5a,0x7c,0xbd,0x12,0x9f,0x63,0x1a,0x4b,0x7c,0xbd,0x12,0x75,0xcd,0x7d,0xc3, +0xbe,0xc4,0x2, 0x58,0x58,0x4, 0x7e,0xd4,0x0, 0x5, 0xbd,0xd4,0x58,0x12,0x12,0x37, +0xa1,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x4e,0x35,0x1a,0x4e,0x25,0x18,0x80,0x15, +0x7d,0x5d,0x1b,0x55,0xbd,0x54,0x48,0x10,0x12,0x37,0xa1,0x60,0x5, 0x2f,0x11,0x14, +0x78,0xfb,0x12,0x37,0xa8,0x7a,0x1d,0x18,0x12,0x37,0xa1,0x60,0x5, 0x2f,0x11,0x14, +0x78,0xfb,0x12,0x37,0xb0,0xbe,0x18,0x0, 0x0, 0x28,0x31,0x7e,0x24,0x1, 0x90,0x7e, +0xa3,0x39,0xef,0x7c,0xba,0x3e,0xb0,0x24,0x14,0xa, 0x3b,0x1b,0x38,0x20,0xa, 0x5a, +0x19,0xd5,0x39,0xf0,0x12,0x37,0xb7,0x7e,0x63,0x39,0xef,0xa, 0x56,0x19,0x75,0x39, +0xf2,0x12,0x37,0xc0,0x7e,0x63,0x39,0xef,0xa, 0x56,0x80,0x3f,0x7e,0x73,0x39,0xf0, +0xbc,0x7d,0x68,0x8, 0x7e,0x63,0x39,0xf1,0xbc,0x6d,0x78,0x4e,0xbc,0x7d,0x78,0x4, +0x6c,0xee,0x80,0x3, 0x7e,0xe0,0x1, 0x7c,0xbe,0x3e,0xb0,0x24,0x14,0xa, 0x3b,0xb, +0x38,0x50,0xbe,0x54,0x0, 0x0, 0x28,0x22,0x1b,0x54,0x1b,0x38,0x50,0x12,0x37,0xb7, +0xa, 0x5e,0x19,0x75,0x39,0xf2,0x12,0x37,0xc0,0xa, 0x5e,0x19,0x75,0x39,0xf4,0x7e, +0xb3,0x39,0xef,0x4, 0x7a,0xb3,0x39,0xef,0x80,0x10,0x74,0xff,0xa, 0x3e,0x19,0xb3, +0x39,0xf0,0x19,0xb3,0x39,0xf2,0x19,0xb3,0x39,0xf4,0xb, 0xd0,0x7e,0x73,0x2f,0xa5, +0xbc,0x7d,0x28,0x2, 0xa1,0xf0,0x7e,0xa3,0x39,0xef,0xbe,0xa0,0x0, 0x28,0x25,0x20, +0x13,0x8, 0xd2,0x13,0x74,0x14,0x7a,0xb3,0x39,0x10,0xbe,0xa0,0x1, 0x78,0x1d,0x74, +0xff,0x7a,0xb3,0x39,0xf1,0x7a,0xb3,0x39,0xf3,0x7a,0xb3,0x39,0xf5,0x6d,0x33,0x7a, +0x35,0x16,0x80,0x8, 0xc2,0x13,0x12,0xbc,0x72,0x12,0x37,0xd8,0xda,0x79,0xda,0xd8, +0x22,0x7e,0x18,0x0, 0x1, 0x7c,0xbd,0x22,0x6e,0x34,0xff,0xff,0x6e,0x24,0xff,0xff, +0x5e,0x35,0x1a,0x5e,0x25,0x18,0x22,0x74,0x2, 0xac,0xbd,0x9, 0x75,0x2e,0x1b,0x22, +0x74,0x2, 0xac,0xbd,0x9, 0x75,0x2e,0x1c,0x22,0xa, 0x37,0x9d,0x32,0x2, 0x17,0x88, +0x90,0x62,0xf, 0xe4,0x93,0xa, 0x8b,0x22,0x6d,0x33,0x7a,0x35,0x16,0x7a,0x35,0x14, +0x22,0xe4,0x93,0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, 0x8f,0x19,0xb8, +0x26,0x55,0x22,0x7e,0x73,0x31,0x8c,0x2e,0x70,0xff,0x22,0x12,0xbc,0xf6,0xb4,0x1, +0x14,0xca,0x39,0x7e,0x18,0x3c,0xd, 0x7e,0x8, 0x2d,0xf, 0x12,0x17,0x31,0x1b,0xfd, +0x12,0x2f,0xf1,0x80,0x12,0xca,0x39,0x7e,0x18,0x3c,0xd, 0x7e,0x8, 0x32,0x91,0x12, +0x17,0x31,0x1b,0xfd,0x12,0x38,0x2a,0x2, 0x2a,0x91,0x7e,0x1f,0x32,0x95,0x7e,0xf, +0x32,0x91,0x22,0x12,0xbc,0xf6,0xb4,0x1, 0x17,0xca,0x39,0x7e,0x18,0x2d,0xf, 0x7e, +0x8, 0x3c,0xd, 0x12,0x17,0x31,0x1b,0xfd,0x12,0x3d,0x91,0x12,0x2f,0xf1,0x80,0x1a, +0xca,0x39,0x7e,0x18,0x32,0x91,0x7e,0x8, 0x3c,0xd, 0x12,0x17,0x31,0x1b,0xfd,0x7e, +0x37,0x32,0x97,0x7a,0x37,0x32,0xd8,0x12,0x38,0x2a,0x2, 0x2a,0x91,0xca,0xf8,0x7c, +0x6b,0xa5,0xbe,0x0, 0x9, 0x7c,0xb7,0x12,0x3d,0x2c,0xd2,0x8, 0x61,0x5, 0xa5,0xbe, +0x1, 0x53,0x7a,0x73,0x3b,0xce,0xa5,0xbf,0xad,0x2, 0x80,0x45,0xa5,0xbf,0xae,0x4, +0xd2,0x9, 0x61,0x5, 0xa5,0xbf,0xaa,0x9, 0x7e,0x35,0x5f,0x7a,0x37,0x32,0xda,0x80, +0x30,0xa5,0xbf,0xab,0xa, 0x7e,0x34,0x5, 0x7a,0x7a,0x37,0x32,0xda,0x80,0x22,0xa5, +0xbf,0xac,0xa, 0x7e,0x34,0x4, 0xfc,0x7a,0x37,0x32,0xda,0x80,0x14,0xa5,0xbf,0xd0, +0x5, 0x12,0x3b,0x11,0x80,0xb, 0xa5,0xbf,0xd1,0x2, 0x80,0x2, 0x61,0x5, 0x12,0x3b, +0x11,0x6d,0x33,0x21,0x81,0xbe,0x60,0x4, 0x40,0x20,0xbe,0x60,0x8, 0x38,0x1b,0x12, +0x3b,0x8, 0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, 0x61,0x5, 0xa5,0xbe,0x8, +0x2, 0x80,0x2, 0x61,0x5, 0x12,0x3d,0x8b,0x61,0x5, 0xa5,0xbe,0xa, 0x9, 0x43,0xc, +0x20,0x7a,0x73,0x3b,0xd7,0x61,0x5, 0xa5,0xbe,0xb, 0x8, 0x12,0x3b,0x8, 0x12,0x3d, +0x8e,0x61,0x5, 0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c,0x38,0x2, 0x41,0x9d,0xbe, +0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23,0x38,0x8, 0x12,0x3b,0xa, 0x43,0xc, 0x40,0x61, +0x5, 0xbe,0x60,0x15,0x40,0x1a,0xbe,0x60,0x18,0x38,0x15,0x12,0x3b,0xa, 0xd2,0x8, +0xa5,0xbe,0x15,0x2, 0x80,0x2, 0x61,0x5, 0x74,0x7, 0x7a,0xb3,0x3b,0xd1,0x61,0x5, +0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3,0x3b,0xe6,0x61,0x5, 0xbe,0x60,0x24,0x40,0x7, +0xbe,0x60,0x2c,0x38,0x2, 0x41,0x9d,0xa5,0xbe,0x2d,0x1b,0x12,0x3b,0xa, 0x20,0x9, +0x2, 0x61,0x5, 0x7e,0x63,0x3b,0xf9,0x7c,0x46,0x6c,0x55,0xa, 0x37,0x2d,0x32,0x3e, +0x34,0x7a,0x35,0x8, 0x61,0x5, 0xbe,0x60,0x2f,0x40,0xa, 0xbe,0x60,0x33,0x38,0x5, +0x43,0xc, 0x8, 0x41,0x9d,0xa5,0xbe,0x34,0xf, 0x43,0xc, 0x10,0xbe,0x70,0x64,0x38, +0x2, 0x41,0x9d,0x7e,0x70,0x64,0x41,0x9d,0xbe,0x60,0x38,0x68,0x4, 0xa5,0xbe,0x39, +0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x3b,0xf2,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0xf2,0xa, +0x2f,0x19,0x72,0x32,0x42,0xa5,0xbe,0x39,0x2, 0x80,0x2, 0x61,0x5, 0x75,0x5c,0x38, +0x61,0x5, 0xbe,0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21,0x43,0xc, 0x2, 0x7e,0xf3, +0x3b,0xf4,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0xf4,0xa, 0x2f,0x19,0x72,0x32,0x65,0xa5, +0xbe,0x3b,0x2, 0x80,0x2, 0x61,0x5, 0x75,0x5c,0x3a,0x61,0x5, 0xa5,0xbe,0xfb,0x9, +0x43,0xc, 0x4, 0x7a,0x73,0x32,0x33,0x61,0x5, 0xa5,0xbe,0x50,0x6, 0x7a,0x73,0x3c, +0x1d,0x61,0x5, 0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d,0x21,0x43,0xc, 0x1, 0x7e, +0xf3,0x3b,0xf6,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0xf6,0xa, 0x2f,0x19,0x72,0x31,0x9b, +0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0x61,0x5, 0x75,0x5c,0x3c,0x61,0x5, 0xbe,0x60,0x3e, +0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x3b,0xf8,0x7c,0xbf,0x4, +0x7a,0xb3,0x3b,0xf8,0xa, 0x2f,0x19,0x72,0x31,0xbe,0xa5,0xbe,0x3f,0x2, 0x80,0x2, +0x61,0x5, 0x75,0x5c,0x3e,0x61,0x5, 0xbe,0x60,0x40,0x40,0xd, 0xbe,0x60,0x42,0x38, +0x8, 0x12,0x3b,0xa, 0x75,0xd, 0x1, 0x80,0xa, 0xa5,0xbe,0x43,0xb, 0x12,0x3b,0xa, +0x75,0xd, 0x2, 0x12,0x37,0xfb,0x80,0x7d,0xa5,0xbe,0x44,0x8, 0x12,0x3b,0xa, 0x12, +0x38,0x33,0x80,0x71,0xbe,0x60,0x45,0x68,0x4, 0xa5,0xbe,0x46,0x5, 0x12,0x3b,0xa, +0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, 0xa5,0xbe,0x4f,0x20,0x43,0xd, 0x4, 0x7e,0xf3, +0x3c,0x13,0x7c,0xbf,0x4, 0x7a,0xb3,0x3c,0x13,0xa, 0x2f,0x2e,0x27,0x32,0xd8,0x7a, +0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75,0x5c,0x4e,0x80,0x3a,0xa5,0xbe,0x6d,0x5, 0x7a, +0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0,0x40,0x25,0xbe,0x60,0xf3,0x38,0x20,0x7c,0x16, +0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0xf3,0x1a,0x7e,0x15,0x12,0x7e,0x5, +0x10,0x3e,0x4, 0x7e,0x1f,0x32,0xdc,0x2d,0x30,0x1b,0x1a,0x10,0x80,0x7, 0xa5,0xbe, +0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8,0x22,0xd2,0x8, 0xa, 0x26,0x19,0x72,0x3b,0xcd, +0x22,0x7e,0x34,0x1f,0x53,0x7a,0x37,0x32,0xda,0x22,0x7c,0x6b,0x12,0x29,0xd0,0x78, +0x5, 0x7c,0xb6,0x2, 0x3b,0x68,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x38,0x6d,0xb4,0x2, +0x5, 0x7c,0xb6,0x2, 0x3b,0x37,0x22,0xca,0x79,0x7c,0xf7,0x7c,0xeb,0x4c,0xee,0x78, +0xa, 0x12,0x29,0xd0,0x68,0x18,0x12,0x3b,0x64,0x80,0x13,0xbe,0xe0,0x80,0x50,0xe, +0x7e,0xb3,0x3b,0xcd,0x30,0xe7,0x7, 0x7c,0xbe,0x7c,0x7f,0x12,0x38,0x6d,0x12,0x3b, +0x64,0xda,0x79,0x22,0x7c,0xbe,0x7c,0x7f,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, +0x7c,0xba,0x12,0x3d,0x2c,0x80,0x2c,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, +0x7c,0xb3,0x7c,0x7a,0x12,0x69,0xc5,0x80,0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30, +0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x70,0x58,0xa5,0xbb,0x8f,0x3, +0x75,0x5b,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, 0x3b,0xb3,0x74,0x1, 0x7a,0xb3, +0x3, 0xff,0x22,0x24,0xab,0x68,0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24, +0xde,0x78,0x2f,0x74,0x5, 0x80,0x2d,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x2a,0x12,0x3b, +0xf9,0x12,0xb4,0xc, 0x2, 0x3c,0x22,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x1a,0x12,0x3b, +0xf9,0x75,0xe9,0xff,0x22,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0xc, 0x12,0x3b,0xf9,0x2, +0x3c,0x1c,0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80, +0x12,0x7e,0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x29,0xf2,0x7c,0x23,0x1b,0x30,0xa5, +0xba,0x0, 0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x75,0xe7,0x6b,0x2, +0x3c,0x22,0xe4,0x7e,0x34,0xd7,0xfc,0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34, +0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff,0x22,0x30,0x90,0x19,0xc2,0x90,0xe5,0x5a, +0x70,0x9, 0x75,0x5a,0x1, 0xe5,0x91,0xf5,0x5c,0x80,0x11,0x7e,0x71,0x91,0xe5,0x5c, +0x12,0x3b,0x1a,0x5, 0x5c,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x5c,0xe5,0x5c,0x12,0x3c, +0x64,0xf5,0x91,0x22,0x7c,0x7b,0x6c,0xaa,0x12,0x29,0xd0,0x78,0x9, 0x7c,0xb7,0x12, +0x3c,0xad,0x7c,0xab,0x80,0x16,0xb4,0x4, 0x9, 0x7c,0xb7,0x12,0x2f,0xfa,0x7c,0xab, +0x80,0xa, 0xb4,0x2, 0x7, 0x7c,0xb7,0x12,0x3c,0x8f,0x7c,0xab,0x7c,0xba,0x22,0x7c, +0xab,0x4c,0xaa,0x78,0x2, 0x80,0x11,0xbe,0xa0,0x80,0x50,0xc, 0x7e,0xb3,0x3b,0xcd, +0x30,0xe7,0x5, 0x7c,0xba,0x2, 0x2f,0xfa,0x7c,0xba,0x2, 0x3c,0xad,0x70,0x5, 0x7e, +0xb3,0x3b,0xcd,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x61,0x0, 0x30,0x10,0x6, 0x7e, +0x18,0x38,0x3a,0x80,0x4, 0x7e,0x18,0x38,0x78,0x7a,0x1d,0x1c,0x80,0x8, 0xbe,0xb0, +0x5e,0x38,0x10,0x75,0x61,0x0, 0xa, 0x1b,0x7e,0x1d,0x1c,0x2d,0x31,0x1b,0x34,0x7e, +0x1b,0xb0,0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x3d,0x59,0xbe,0xb0, +0x80,0x40,0xc, 0xbe,0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x3a,0xed,0x22,0xb4, +0xfc,0x5, 0x7e,0xb3,0x3b,0x94,0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e,0xb3,0x2f,0xc9, +0x60,0x3, 0x4e,0xa0,0x1, 0x7e,0xb3,0x3a,0xfc,0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba, +0x22,0xb4,0xfe,0x5, 0x7e,0xb3,0x32,0x30,0x22,0x74,0xff,0x22,0x7a,0xb3,0x3b,0xcd, +0xc4,0x54,0x7, 0xb4,0x4, 0x4, 0x74,0x3, 0x80,0xe, 0x60,0x3, 0xb4,0x1, 0x4, 0x74, +0x1, 0x80,0x5, 0xb4,0x2, 0x7, 0x74,0x1, 0x7a,0xb3,0x3b,0x94,0x22,0x74,0x1, 0x7a, +0xb3,0x3b,0x94,0xe4,0x7a,0xb3,0x3b,0xcd,0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x3c, +0x21,0x7e,0x73,0x3c,0x21,0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x77,0xf5,0x7c,0xab, +0x7c,0xb7,0x4, 0x7a,0xb3,0x3c,0x21,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x3c,0x21,0x6d, +0x33,0x7a,0x37,0x3c,0x1e,0x75,0x5c,0xeb,0x7c,0xba,0x22,0xb2,0x86,0x22,0xb2,0x82, +0x22,0x7e,0x37,0x2d,0x15,0x7a,0x37,0x32,0xd8,0x22,0x7e,0x34,0xd, 0xc8,0x7a,0x37, +0x32,0xda,0x12,0x3d,0x91,0x6d,0x33,0x7a,0x35,0xa, 0x12,0x3e,0xd3,0x12,0x3e,0x32, +0x12,0x3d,0xd5,0x12,0x3e,0xca,0x74,0x50,0x7a,0xb3,0x3c,0x1, 0x7e,0x24,0x3, 0x20, +0x12,0x3d,0xce,0xe4,0x12,0xbc,0x3b,0x6d,0x33,0x7a,0x37,0x3c,0xd0,0x22,0x7d,0x32, +0x74,0xfa,0x2, 0x12,0xd0,0x7e,0x73,0x32,0x35,0x7a,0x73,0x3b,0xf0,0x22,0x30,0x0, +0x3, 0x12,0x3d,0xd5,0xa2,0x1, 0x92,0x2, 0x12,0x6a,0xc7,0x2, 0x3e,0x3a,0x74,0x40, +0x7a,0xb3,0x32,0x41,0x12,0x44,0x93,0x50,0x9, 0xd2,0x0, 0xd2,0x1, 0x12,0x3d,0xde, +0x80,0x22,0x74,0x1, 0x12,0x3e,0xe8,0x7e,0x43,0x3b,0xec,0x7e,0x50,0x64,0xac,0x45, +0x12,0x80,0x3e,0x7a,0xb3,0x32,0x40,0x7e,0xf, 0x33,0xfb,0x12,0x6d,0xb1,0xb, 0x34, +0x7a,0x73,0x32,0x41,0x12,0x3e,0x3a,0x7e,0x73,0x32,0x40,0x7a,0x73,0x3b,0xef,0x2, +0x3d,0xd5,0x7e,0x73,0x32,0x40,0x7a,0x73,0x3b,0xef,0x7e,0x73,0x32,0x41,0x7a,0x73, +0x3b,0xee,0x22,0xa2,0xc, 0xe4,0x33,0x7a,0xb3,0x3b,0xfb,0x7e,0x73,0x3b,0xff,0xbe, +0x73,0x32,0x30,0x68,0x10,0xe5,0xc, 0x70,0xc, 0x12,0x3e,0xd3,0x12,0x3e,0x32,0x12, +0x3d,0xd5,0x12,0x3e,0xca,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x61,0xcb,0xe4, +0x93,0x7c,0xab,0xbe,0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff,0x80,0xb, 0x12, +0x3e,0xdc,0x38,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0x80,0x1a, +0xbe,0xd0,0x81,0x78,0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x3e,0xdc,0x40,0x4, +0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38,0x2, 0x6c,0xdd, +0x7c,0xbd,0x12,0x3f,0xb4,0x12,0x3d,0xd5,0x12,0x3e,0x32,0x12,0x3e,0xd3,0x12,0x3e, +0xca,0x7a,0xd3,0x3b,0xd7,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73,0x32,0x83,0x7a,0x73, +0x3c,0x0, 0x22,0x7e,0x73,0x32,0x30,0x7a,0x73,0x3b,0xff,0x22,0x7e,0x90,0x5, 0xac, +0x9f,0x9, 0xb4,0x2d,0x54,0xbc,0xbe,0x22,0xca,0x3b,0x7c,0xdb,0xe4,0x7a,0xb3,0x32, +0x35,0x12,0x3f,0x9e,0x7e,0xc0,0xa, 0x12,0x6a,0xb8,0x30,0xd, 0xfd,0x74,0x1, 0x12, +0x0, 0xe, 0x7e,0x1f,0x33,0xfb,0x12,0x87,0xf4,0x7d,0x73,0xbe,0x74,0xff,0xff,0x78, +0x9, 0x12,0x3f,0x58,0x2e,0x34,0x0, 0x3, 0x80,0x18,0xbe,0x74,0x80,0x0, 0x28,0x7, +0x12,0x3f,0x58,0xb, 0x35,0x80,0xb, 0xbe,0x74,0x40,0x0, 0x28,0xc, 0x12,0x3f,0x58, +0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xbe,0xbe,0xd0,0x1, 0x78,0x9, 0x7e,0x1f, +0x33,0xfb,0x12,0x80,0x5d,0x7d,0x73,0x7e,0x1f,0x33,0xea,0x69,0x31,0x0, 0x1a,0x7a, +0x73,0x32,0x35,0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x33,0xea,0x2e,0x14,0x0, 0x1a, +0xb, 0xa, 0x30,0x22,0x7e,0xb, 0x70,0x7a,0x73,0x32,0x30,0x29,0x70,0x0, 0x4, 0x7a, +0x73,0x32,0x83,0x29,0x70,0x0, 0x1, 0x7a,0x73,0x32,0x35,0x29,0x70,0x0, 0x3, 0x7a, +0x73,0x32,0x41,0x12,0x3f,0xac,0x12,0x3f,0xa5,0xd2,0x0, 0xc2,0x1, 0x2, 0x3d,0xde, +0x2e,0x14,0x2d,0x54,0x6d,0x0, 0x12,0x3f,0x64,0x7e,0x34,0x0, 0x38,0x22,0x7e,0x8, +0x31,0x8e,0x2, 0xd, 0x72,0x7e,0x8, 0x31,0x8e,0x2, 0x3, 0x8b,0x12,0x53,0x71,0x7a, +0x37,0x32,0x3c,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac,0xbf,0x12,0xbc,0xc9,0x12, +0xbc,0x69,0x12,0xbc,0x57,0x12,0xbc,0x60,0x7a,0xf3,0x34,0x88,0x7c,0xbf,0x12,0xb0, +0x4, 0x12,0x3f,0xac,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x2d,0x58,0x12,0xaa,0xba,0x12, +0x54,0xe1,0x74,0x1, 0x7a,0xb3,0x3a,0xf5,0xe4,0x7a,0xb3,0x16,0x91,0x7a,0xb3,0x3b, +0x67,0x7a,0xb3,0x16,0x92,0xda,0xf8,0x22,0x7e,0xf, 0x33,0xe6,0x69,0x30,0x0, 0xa, +0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74,0x7, 0x1e,0x34, +0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x7e,0x34,0x0, 0x1, 0x7e, +0xf, 0x33,0xe6,0x79,0x30,0x0, 0x4, 0x7e,0xf, 0x33,0xe6,0x69,0x30,0x0, 0x12,0x5e, +0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, 0x79,0x30,0x0, 0x12,0x22,0xca,0xd8, +0xca,0x79,0x7e,0x73,0x31,0x8f,0x7e,0xf3,0x31,0x8e,0xac,0xf7,0x7d,0x37,0x3e,0x34, +0x7e,0x8, 0x26,0x55,0xe4,0x12,0x17,0x56,0x7e,0xb3,0x3b,0xe8,0xb4,0x1, 0x64,0x7e, +0x73,0x3b,0xe9,0xbe,0x70,0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12,0x23,0xd6,0x12, +0x40,0xc8,0x6d,0x33,0x80,0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33,0xd, 0xc8,0x12, +0x17,0x88,0x7a,0x35,0x26,0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49,0x21,0x26,0x55, +0xbe,0x25,0x26,0x58,0x7, 0x7e,0x25,0x26,0x59,0x21,0x26,0x55,0xb, 0x34,0x7a,0x35, +0x24,0xbe,0x75,0x24,0x38,0xd0,0xb, 0xd0,0x7e,0x73,0x3b,0xe9,0xbc,0x7d,0x38,0xbc, +0x7d,0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x26,0x55,0x7e,0x8, 0xd, 0xc8,0x12,0x17, +0x31,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0xca,0x3b,0x12,0x47,0xcb,0x50,0xfb,0x7e, +0xf3,0x32,0x30,0x7c,0xbf,0x12,0x43,0xe4,0x12,0xa6,0x3b,0x7e,0xb3,0x32,0x40,0xf5, +0x28,0x7e,0xc3,0x32,0x41,0x7e,0xb3,0x3b,0x94,0xb4,0x1, 0xf, 0x12,0x54,0x91,0x7e, +0xb3,0x16,0x91,0x70,0x6, 0x12,0x41,0xc7,0xc3,0x21,0xc4,0x12,0x2e,0xa4,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, 0x4, 0x7e,0x12,0x17,0x31,0x1b,0xfd,0x12, +0x2e,0xa4,0x3e,0x34,0xca,0x39,0x7e,0x18,0x7, 0x7a,0x7e,0x8, 0x4, 0x0, 0x12,0x17, +0x31,0x1b,0xfd,0x7e,0xb3,0x3b,0x94,0xb4,0x3, 0x7, 0x12,0x97,0x3a,0x7a,0x37,0x3c, +0x14,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12,0x44,0x76,0x12,0x97,0xaa,0x12,0x41,0xe1, +0xe4,0x12,0x13,0xde,0x12,0x41,0xc7,0x7e,0x8, 0x4, 0x7e,0x7a,0xd, 0x29,0x7e,0x18, +0x6, 0x76,0x7e,0xb3,0x32,0x93,0x12,0x42,0x3b,0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29, +0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x2d,0x11,0x12,0x42,0x3b,0x7e,0xd3,0x32,0x40,0x7e, +0xe3,0x32,0x41,0xe5,0x28,0x7a,0xb3,0x32,0x40,0x7a,0xc3,0x32,0x41,0x7e,0x34,0x8, +0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d,0x10,0x12,0x42,0x93,0x7a,0xd3,0x32,0x40, +0x7a,0xe3,0x32,0x41,0x7c,0xbf,0x12,0x43,0xf3,0x12,0xa5,0x79,0x7e,0xb3,0x3c,0xd3, +0x4, 0x7a,0xb3,0x3c,0xd3,0x7e,0x73,0x3c,0xd3,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64, +0x7a,0xb3,0x3c,0xd3,0x7e,0xb3,0x16,0x90,0x60,0x9, 0x7e,0xb3,0x16,0x91,0x60,0x3, +0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0xe4,0x7a,0xb3,0x34,0x3a,0x7a,0xb3,0x34,0x39, +0x12,0x6a,0x25,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x34,0x3a, +0x22,0x7e,0xa3,0x34,0x88,0xbe,0xa0,0xff,0x68,0x48,0xbe,0xa3,0x38,0x25,0x68,0x42, +0x74,0x5, 0xa4,0x12,0xbc,0xc9,0x12,0x42,0x33,0x12,0xbc,0x69,0x12,0x42,0x33,0x12, +0xbc,0x60,0x12,0x44,0x93,0x50,0x9, 0x7e,0xb3,0x34,0x88,0x12,0xb0,0x4, 0x80,0x6, +0x12,0x42,0x33,0x12,0xbc,0x57,0x12,0x3f,0xac,0x12,0x3f,0xa5,0x7e,0x73,0x32,0x35, +0xa, 0x37,0x7e,0xf, 0x33,0xea,0x79,0x30,0x0, 0x1a,0x7e,0x73,0x34,0x88,0x7a,0x73, +0x38,0x25,0x22,0x7e,0xa3,0x34,0x88,0x74,0x5, 0xa4,0x22,0xca,0x79,0x7f,0x51,0x7f, +0x40,0x7e,0xa3,0x31,0x95,0xa, 0x3a,0x7e,0xa3,0x31,0x94,0xa, 0x7a,0x2d,0x73,0x7e, +0xd, 0x29,0x7c,0x7f,0x12,0x68,0xe1,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29, +0x7f,0x4, 0x12,0x17,0x31,0x1b,0xfd,0x7e,0xb3,0x32,0x22,0xb4,0x1, 0x22,0x6c,0xaa, +0x80,0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, +0x2d,0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2, +0xda,0x79,0x22,0x7e,0xb3,0x31,0x8e,0xca,0x3b,0x7c,0xdb,0x7a,0x5, 0x38,0x7d,0x71, +0x7a,0x25,0x36,0x7a,0x35,0x34,0x12,0x44,0x93,0x40,0x2, 0x61,0x2c,0x6c,0xcc,0x80, +0x11,0x7e,0x73,0x31,0x8f,0x12,0x43,0xc3,0x12,0x43,0xa9,0x7e,0x34,0x34,0x0, 0x12, +0x43,0xcc,0x7e,0x73,0x31,0x90,0xbc,0x7c,0x38,0xe7,0x6c,0xcc,0x80,0x58,0x7e,0xa3, +0x31,0x8f,0x7c,0x7a,0x12,0x43,0xc3,0x75,0x3a,0x0, 0x80,0x27,0x7e,0xb3,0x3b,0xe2, +0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac,0x7c,0x49,0x43,0x37,0x99,0x80,0x6, +0xac,0x7c,0x49,0x43,0x37,0x9b,0x7e,0x71,0x3a,0x74,0x2, 0xac,0x7b,0x59,0x43,0x34, +0x50,0x5, 0x3a,0x7e,0xb3,0x31,0x91,0xbe,0xb1,0x3a,0x38,0xd0,0x12,0xbc,0xc0,0x68, +0xb, 0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34,0x4e,0x12,0x43,0xa9,0x7e, +0x34,0x34,0x50,0x12,0x43,0xcc,0xbc,0xdc,0x38,0xa4,0x80,0x2c,0x7a,0xd3,0x2c,0xd7, +0x7e,0x73,0x31,0x91,0x7a,0x73,0x2c,0xd8,0xe4,0x7a,0xb3,0x2c,0xda,0x74,0x6, 0x7a, +0xb3,0x2c,0xd9,0x7a,0x77,0x2c,0xdb,0x7a,0x77,0x2c,0xdf,0x7e,0x8, 0x2c,0xd7,0x7e, +0x73,0x32,0x40,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12,0x6f,0xfc,0x7e,0x35,0x38, +0x7a,0x37,0x2c,0xdf,0xe4,0x7a,0xb3,0x2c,0xd9,0x12,0x43,0xba,0x7a,0xd3,0x2c,0xd7, +0x7e,0xb3,0x32,0x3e,0x70,0xf, 0xe4,0x7a,0xb3,0x2c,0xda,0x7a,0x77,0x2c,0xdb,0x7e, +0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x2c,0xda,0x7e,0x35,0x34,0x7a,0x37, +0x2c,0xdb,0x7e,0x35,0x36,0x7a,0x37,0x2c,0xdd,0x6d,0x33,0x7a,0x37,0x2c,0xe1,0x7e, +0x8, 0x2c,0xd7,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x74,0xc, 0x7a,0xb3,0x2c,0xd9,0x74, +0x1, 0x7a,0xb3,0x2c,0xd7,0xe4,0x7a,0xb3,0x2c,0xda,0x7e,0x73,0x31,0x8f,0x7a,0x73, +0x2c,0xd8,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3,0x22,0x7a,0x37,0x2c,0xdb, +0x7d,0x3f,0x7a,0x37,0x2c,0xdd,0x7a,0x37,0x2c,0xdf,0x7e,0x8, 0x2c,0xd7,0x12,0x7, +0x9b,0xb, 0xc0,0x22,0x7c,0xab,0x12,0xa6,0x74,0xd2,0x1a,0x7c,0xba,0x12,0x43,0xf3, +0xc2,0x1a,0x22,0x7c,0x2b,0x7e,0xb3,0x1f,0x33,0xbc,0x2b,0x68,0x4f,0x12,0x44,0x51, +0x7c,0x3b,0x7c,0xb2,0x12,0x44,0x51,0x7c,0xab,0xbe,0x30,0xff,0x68,0x3e,0xbe,0xa0, +0xff,0x68,0x39,0x7e,0x70,0x4, 0xac,0x73,0xa, 0x2a,0x12,0x47,0xe7,0xbe,0xb0,0x2, +0x38,0x2a,0xa, 0x2b,0x7e,0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22, +0x30,0x1a,0x3, 0x2, 0xab,0x40,0x7e,0xb3,0x32,0x3e,0xb4,0x1, 0xf, 0x12,0x47,0xc1, +0x7a,0x55,0x29,0x7e,0x8, 0xd, 0xc8,0x74,0x1, 0x2, 0xaa,0xe5,0x22,0x7e,0xb3,0x32, +0x30,0x7c,0xab,0x6c,0x77,0x7e,0x50,0x5, 0xac,0x57,0x9, 0x62,0x2d,0x54,0xbc,0x6a, +0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0x7e, +0x34,0xd, 0xac,0x12,0x23,0xda,0x12,0x2f,0x56,0x12,0x45,0x4e,0x2, 0x44,0x7f,0x30, +0x11,0x10,0x12,0x44,0x93,0x50,0x3, 0x12,0xaf,0x88,0x12,0x45,0x74,0x12,0x44,0xcf, +0xc2,0x11,0x22,0x7e,0xb3,0x3b,0x94,0xb4,0x3, 0x8, 0x7e,0xb3,0x3b,0xe3,0x70,0x2, +0xc3,0x22,0xd3,0x22,0x12,0xbc,0x39,0x6d,0x33,0x7a,0x37,0x3c,0x6d,0x7a,0x37,0x3c, +0xd0,0x12,0x44,0x6f,0x12,0x41,0xc7,0x2, 0x44,0xba,0x7e,0x70,0xa, 0x12,0x4b,0x35, +0x50,0x3, 0x7e,0x70,0x19,0x7a,0x73,0x39,0x10,0xe4,0x7a,0xb3,0x39,0x11,0x22,0xca, +0x3b,0x7e,0xb3,0x32,0x30,0x7a,0xb3,0x1f,0x33,0x7e,0xf3,0x32,0x83,0x12,0x44,0x51, +0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12,0xbc,0xd2,0xf5,0x29,0x7e,0x73, +0x32,0x30,0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, 0xac,0x7d,0xa, 0x2c,0x12,0x47, +0xe7,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, 0xe0,0xad,0x10, +0x2e,0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x1d,0xac,0x7e,0x2e,0x34, +0x3, 0xa6,0x6d,0x22,0x7a,0x1f,0x3, 0xa2,0x7c,0xbc,0x12,0x6e,0x33,0xb, 0xc0,0xbe, +0xc0,0x4, 0x40,0xb5,0x7e,0x73,0x32,0x83,0xbc,0x7f,0x68,0x6, 0x7a,0xf3,0x32,0x83, +0xd2,0xe, 0xd2,0x0, 0x7e,0xb3,0x1f,0x33,0x12,0x54,0xe, 0xda,0x3b,0x22,0x7e,0xb3, +0x32,0x3f,0x70,0x1f,0x12,0x23,0xd6,0x12,0x47,0xcb,0x50,0xfb,0x12,0x45,0x74,0x12, +0x47,0xdc,0x20,0x11,0x3, 0x12,0x44,0xcf,0x74,0x2, 0x7a,0xb3,0x32,0x3f,0xe4,0x7a, +0xb3,0x16,0x91,0x22,0x7e,0xf, 0x13,0x8a,0x7e,0x18,0x8, 0xa, 0xca,0x3b,0x7a,0x1d, +0x29,0x7f,0x30,0x12,0x47,0xc1,0x7a,0x55,0x31,0x7e,0xb3,0x32,0x3e,0xf5,0x2e,0xe4, +0x7a,0xb3,0x32,0x3e,0x7f,0x3, 0x7e,0x1d,0x29,0x12,0x68,0x2e,0x74,0x1, 0x12,0x13, +0xde,0xe4,0x12,0x0, 0x1e,0x12,0x3f,0x9e,0x75,0x2d,0x0, 0x12,0x6a,0xb8,0x30,0xd, +0xfd,0x74,0x1, 0x12,0xa5,0xff,0x7e,0x14,0x40,0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x42, +0x93,0x12,0xab,0x7a,0x6d,0x33,0x80,0x19,0x7e,0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d, +0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13,0x12,0x69,0x22,0x7e,0x35,0x2f,0xb, +0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35,0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d, +0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3,0x32,0x3e,0xda,0x3b,0x22,0x12,0x44, +0xa4,0x12,0xbc,0x2d,0x12,0x69,0x82,0x7e,0xb3,0x3b,0x94,0xb4,0x1, 0x6e,0x12,0xb5, +0x2b,0x12,0xbc,0x21,0x7e,0x34,0x60,0xa5,0x12,0x20,0xc9,0x12,0x23,0xda,0x12,0x8e, +0xa3,0x12,0x46,0xae,0x12,0x40,0xc8,0x50,0xdb,0x12,0xa7,0x66,0x12,0x8a,0x5f,0x7e, +0xb3,0x3b,0x91,0xb4,0x1, 0x4, 0xe4,0x12,0x46,0x8e,0x12,0x4c,0xbe,0x12,0x46,0x96, +0x40,0xc2,0x12,0x56,0x77,0x12,0x46,0x96,0x40,0xba,0x12,0x87,0x75,0x12,0x33,0x77, +0x12,0x47,0xf6,0x12,0x71,0x8b,0x12,0x7f,0xea,0x12,0x97,0xf7,0x12,0x5c,0x2, 0x12, +0x67,0x2d,0x12,0x67,0x33,0x12,0x4c,0x7e,0x12,0x5f,0x7, 0x12,0x64,0x6b,0x12,0xbb, +0x75,0x12,0x50,0x4a,0x12,0x8e,0x24,0x12,0x4f,0xfa,0x80,0x88,0x12,0x47,0xd6,0x2, +0x46,0x82,0x7e,0xb3,0x3b,0x91,0xb4,0x1, 0x4, 0xe4,0x2, 0x46,0x8e,0x22,0x70,0x3, +0xd2,0x86,0x22,0xc2,0x86,0x22,0xc2,0x0, 0x7e,0xb3,0x16,0x91,0x60,0x6, 0x7e,0xb3, +0x16,0x90,0x70,0x7, 0x12,0x7f,0xa2,0x28,0x2, 0xd2,0x0, 0xa2,0x0, 0x22,0x7e,0x24, +0x3b,0x6d,0x30,0xf, 0x5a,0xc2,0xf, 0x9, 0x72,0x0, 0x2, 0x12,0x47,0x10,0x7a,0x37, +0x31,0x70,0x9, 0x72,0x0, 0x3, 0x12,0x47,0x10,0x7a,0x37,0x31,0x72,0x9, 0x72,0x0, +0x4, 0x12,0x47,0x10,0x7a,0x37,0x31,0x74,0x7e,0x29,0x70,0xa, 0x37,0x3e,0x34,0x3e, +0x34,0x7a,0x37,0x31,0x7b,0x9, 0x72,0x0, 0x1, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a, +0x37,0x31,0x7d,0x9, 0x72,0x0, 0x5, 0x12,0x47,0x10,0x7a,0x37,0x31,0x83,0x9, 0x72, +0x0, 0x41,0xbe,0x73,0x31,0x8c,0x68,0x7, 0x7a,0x73,0x31,0x8c,0x2, 0xb0,0x39,0x22, +0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x7e,0x73,0x2d,0xa4,0x7a, +0x73,0x1f,0x53,0x7e,0x73,0x2f,0xa5,0x7a,0x73,0x1f,0x54,0x7e,0x73,0x2e,0x11,0x7a, +0x73,0x1f,0x55,0x7e,0x73,0x2f,0xa6,0x7a,0x73,0x1f,0x56,0x7e,0x73,0x2f,0xc7,0x7a, +0x73,0x1f,0x57,0x7e,0x73,0x2f,0xc8,0xa, 0x37,0x12,0x47,0xb6,0x7e,0x73,0x2f,0xc9, +0xa, 0x37,0x12,0x47,0xb4,0x7e,0x73,0x2f,0xca,0xa, 0x37,0x12,0x47,0x14,0x12,0x47, +0xb8,0x7e,0x73,0x2f,0xcb,0x12,0x47,0x10,0x12,0x47,0xb8,0x7e,0x73,0x2f,0xcc,0x12, +0x47,0x10,0x12,0x47,0xb6,0x7e,0x73,0x2f,0xcd,0x12,0x47,0x10,0x12,0x47,0xb4,0x7e, +0x73,0x2f,0xce,0x12,0x47,0x10,0x12,0x47,0x14,0x12,0x47,0xb8,0xe5,0x24,0xa, 0x3b, +0x2e,0x34,0x0, 0x80,0x7a,0x73,0x1f,0x58,0x7e,0x73,0x0, 0x69,0x7a,0x73,0x1f,0x5a, +0x7e,0x34,0x0, 0x1a,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x1f,0x5d,0x12,0x17, +0x31,0x1b,0xfd,0x22,0x3e,0x34,0x3e,0x34,0x4e,0x73,0x1f,0x57,0x7a,0x73,0x1f,0x57, +0x22,0x7e,0xa3,0x31,0x8f,0x7e,0xb3,0x31,0x8e,0xa4,0x22,0x7e,0xb3,0x34,0x3a,0xb4, +0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x12,0x47,0xcb,0x50,0xfb,0x22,0x12,0x44,0x93,0x50, +0x3, 0xd2,0x11,0x22,0xc2,0x11,0x22,0x2d,0x32,0x2e,0x34,0x17,0x78,0x7a,0x71,0x82, +0x7a,0x61,0x83,0xe4,0x93,0x22,0x2, 0x47,0xf9,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x31, +0x90,0xf5,0x27,0x7e,0xb3,0x31,0x91,0xf5,0x28,0x75,0x2b,0x0, 0x7e,0xb3,0x16,0x91, +0xbe,0xb0,0x1, 0x68,0xf, 0x60,0x2, 0x21,0x54,0x7e,0xb3,0x2f,0xa5,0xb4,0x1, 0x2, +0x80,0x2, 0x21,0x54,0x6c,0xee,0x21,0x49,0x12,0x7f,0xc7,0x75,0x25,0x2, 0x75,0x26, +0x2, 0x7c,0xbe,0x12,0x49,0x57,0xd2,0x0, 0x12,0x4a,0xd2,0x4c,0xdd,0x68,0x7, 0xe5, +0x27,0x12,0xbc,0xe4,0x48,0x3, 0x75,0x25,0x1, 0x4c,0xcc,0x68,0xc, 0xe5,0x28,0xa, +0x2b,0x1b,0x24,0xa, 0x3c,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, 0x75,0x24,0x0, 0x80, +0x3c,0xe5,0x24,0xbc,0xbe,0x68,0x34,0x12,0x9f,0x3f,0x7a,0xa1,0x29,0x9, 0xb3,0x2e, +0x1c,0xf5,0x2a,0xa, 0x2a,0xa, 0x3d,0x9d,0x32,0x12,0x17,0x88,0xbe,0x34,0x0, 0x3, +0x18,0x19,0xe5,0x2a,0xa, 0x2b,0xa, 0x3c,0x9d,0x32,0x12,0x17,0x88,0xbe,0x34,0x0, +0x3, 0x18,0x8, 0x75,0x25,0x1, 0x75,0x26,0x1, 0x80,0x7, 0x5, 0x24,0x12,0x4f,0xea, +0x38,0xbf,0x7c,0xbd,0x7c,0x7c,0x12,0x4f,0x5f,0x50,0xb, 0x12,0x4a,0x82,0x75,0x25, +0x0, 0x75,0x26,0x0, 0x80,0x2b,0x12,0x4b,0x35,0x50,0x26,0x7e,0x73,0x39,0xf2,0xbc, +0x7d,0x78,0x8, 0x7e,0x73,0x39,0xf4,0xbc,0x7c,0x68,0x10,0x7e,0x73,0x39,0xf3,0xbc, +0x7d,0x78,0xe, 0x7e,0x73,0x39,0xf5,0xbc,0x7c,0x78,0x6, 0x75,0x25,0x3, 0x75,0x26, +0x3, 0x4c,0xdd,0x78,0x2, 0x80,0x7, 0xe5,0x27,0x14,0xbc,0xbd,0x78,0xd, 0x12,0x4b, +0x22,0xb, 0xa, 0x30,0x9e,0x34,0x0, 0x32,0x1b,0xa, 0x30,0xe5,0x28,0x14,0xbc,0xbc, +0x78,0x2, 0x80,0x4, 0x4c,0xcc,0x78,0xd, 0x12,0x4b,0x22,0xb, 0xa, 0x30,0x9e,0x34, +0x0, 0x3c,0x1b,0xa, 0x30,0xe5,0x25,0x7e,0x71,0x26,0x7c,0x6e,0x7c,0x5f,0x7e,0x41, +0x2b,0x12,0x80,0xba,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x16,0x7e,0x70,0x9, 0xac, +0x7e,0x7d,0x13,0x2e,0x14,0x2e,0x97,0x6d,0x0, 0x2e,0x34,0x2e,0x99,0x6d,0x22,0x12, +0x70,0x49,0x12,0x4a,0x82,0xb, 0xf0,0xb, 0xe0,0x12,0x4f,0xdb,0x28,0x2, 0x1, 0x28, +0x7a,0xf3,0x2f,0xa5,0xda,0x3b,0x22,0xca,0x3b,0x7c,0x5b,0x7e,0x43,0x2f,0xa5,0xbe, +0x40,0x1, 0x28,0x2, 0x41,0x52,0x7e,0xa3,0x31,0x8f,0x7e,0x70,0x2, 0xac,0x75,0x9, +0xd3,0x2e,0x1b,0x9, 0xc3,0x2e,0x1c,0x7c,0xbd,0x7c,0x7c,0x12,0x87,0x84,0x7f,0x1, +0x90,0x60,0xaa,0xe4,0x93,0x70,0x12,0x7c,0xfc,0x7c,0x9d,0x7e,0x83,0x31,0x91,0x7e, +0xe3,0x31,0x90,0xa, 0xca,0x6d,0xbb,0x9d,0xbc,0xa, 0xa8,0x1b,0xa5,0xa, 0x5f,0xbd, +0x5a,0x58,0x2, 0x41,0x52,0xa, 0x59,0x1b,0x54,0xbe,0x54,0x0, 0x0, 0x48,0x4e,0x7c, +0xb9,0x14,0x12,0x4a,0xb0,0x50,0x46,0x7c,0xb9,0x14,0x12,0x4a,0x55,0xb, 0x1a,0xe0, +0x7d,0x3b,0x12,0x4b,0x14,0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, 0x58,0x4, 0x6d, +0x55,0x80,0x2, 0x7d,0x5a,0x12,0x4b,0xc, 0x7c,0xb8,0x24,0xfe,0xbc,0xbf,0x78,0x1d, +0x90,0x60,0xaa,0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f,0x12,0x4a,0x5c, +0xb, 0x1a,0x30,0xbd,0x3a,0x8, 0x6, 0x12,0x4a,0x5e,0x1b,0x1a,0xa0,0xa, 0xa9,0xb, +0xa4,0xa, 0x5e,0xbd,0xa5,0x58,0x4b,0x7c,0xb9,0x4, 0x12,0x4a,0xb0,0x50,0x43,0x7c, +0xb9,0x4, 0x12,0x4a,0x55,0xb, 0x1a,0xe0,0x7d,0x3c,0x12,0x4b,0x14,0x8, 0x11,0x9d, +0xae,0xbe,0xa4,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a,0x12,0x4b,0xc, +0x7c,0xb8,0x24,0xfe,0xbc,0xbf,0x78,0x1a,0x90,0x60,0xaa,0xe4,0x93,0x70,0x4, 0x7d, +0xfd,0x1b,0xf4,0x7d,0x5f,0x12,0x4a,0x5c,0xb, 0x1a,0x50,0xbd,0x5a,0x8, 0x3, 0x1b, +0x1a,0xa0,0xda,0x3b,0x22,0x12,0x4a,0x65,0x7d,0xd3,0x7d,0x5d,0x3e,0x54,0x7e,0x1f, +0x13,0x8a,0x2d,0x35,0x22,0x7c,0x5b,0x7e,0x43,0x31,0x8f,0x90,0x60,0xab,0xe4,0x93, +0x7c,0xab,0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7c,0x75,0xac,0x74,0xa, 0x2a,0x2d, +0x32,0x22,0x12,0x4c,0xb6,0x60,0x28,0x6c,0x22,0x80,0x1c,0x7c,0xb2,0x12,0x4a,0xb0, +0x50,0x13,0x7c,0xb2,0x12,0x4a,0x65,0x7d,0x3, 0x12,0x4c,0xae,0x49,0x55,0x3c,0xbb, +0x7d,0x40,0x12,0x9f,0x57,0xb, 0x20,0x7e,0x73,0x31,0x96,0xbc,0x72,0x38,0xdc,0x22, +0x7c,0xab,0x6c,0x77,0x80,0x11,0xa, 0x27,0x2e,0x24,0x60,0xac,0x12,0x77,0xf5,0xbc, +0xba,0x78,0x2, 0xd3,0x22,0xb, 0x70,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xb7,0x38,0xe6, +0xc3,0x22,0x12,0x4c,0xb6,0x60,0x34,0x6c,0x22,0x80,0x28,0x7c,0xb2,0x12,0x4a,0xb0, +0x50,0x1f,0x7c,0xb2,0x12,0x4a,0x65,0x3e,0x34,0x7e,0x7f,0x13,0x8a,0x2d,0xf3,0xb, +0x7a,0x30,0x12,0x4c,0xae,0x59,0x35,0x3c,0xbb,0x30,0x0, 0x5, 0x6d,0x33,0x1b,0x7a, +0x30,0xb, 0x20,0x7e,0x73,0x31,0x96,0xbc,0x72,0x38,0xd0,0x22,0x2d,0x31,0x7d,0x20, +0x1b,0x1a,0x50,0x22,0x3e,0x34,0x7f,0x40,0x2d,0x93,0xb, 0x4a,0xa0,0xbe,0xe4,0x0, +0x0, 0x22,0x7e,0x73,0x31,0x8f,0xac,0x7d,0xa, 0x2c,0x2d,0x32,0x3e,0x34,0x7e,0xf, +0x13,0x8a,0x2d,0x13,0x22,0xa2,0x13,0x22,0xca,0x79,0x7e,0xa3,0x31,0x23,0x7e,0x8, +0x30,0xdd,0x7e,0x90,0xa, 0x12,0x4b,0x35,0x50,0x3, 0x7e,0x90,0x19,0x4c,0xaa,0x78, +0x5, 0x12,0x44,0xba,0x81,0x6a,0x6c,0x88,0x81,0x5f,0x7e,0x70,0x9, 0xac,0x78,0x9, +0xf3,0x30,0x2d,0xbe,0xf0,0xff,0x78,0x2, 0x81,0x5d,0xa, 0x2f,0x7f,0x70,0x2d,0xf2, +0x7e,0x7b,0xe0,0xbe,0xe0,0x2, 0x68,0x2, 0x81,0x3f,0x7e,0x50,0x4, 0xac,0x5f,0x49, +0x22,0x39,0xc5,0x49,0x33,0x30,0x29,0x12,0x4f,0xe2,0x7e,0x70,0x4, 0xac,0x7f,0x49, +0x23,0x39,0xc7,0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x30,0x2b,0x9d,0x32,0x12,0x17, +0x88,0x7d,0xe3,0x7e,0xb3,0x39,0x10,0xa, 0x3b,0xbd,0x3f,0x28,0x52,0xbd,0x3e,0x28, +0x4e,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x39,0xc5,0x7e,0x50,0x9, 0xac,0x58,0x59, +0x32,0x30,0x29,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x39,0xc7,0x7e,0x50,0x9, 0xac, +0x58,0x59,0x32,0x30,0x2b,0xbe,0xa0,0x0, 0x28,0x2, 0x1b,0xa0,0x4c,0xaa,0x78,0x7d, +0x7e,0xb3,0x39,0x11,0x4, 0x7a,0xb3,0x39,0x11,0xbe,0xb0,0x32,0x40,0x6f,0xe4,0x7a, +0xb3,0x39,0x11,0x12,0x4c,0x6d,0x50,0x65,0x4, 0x7a,0xb3,0x39,0x10,0x80,0x5e,0x7e, +0x70,0x9, 0xac,0x78,0x49,0xd3,0x30,0x29,0x7e,0x50,0x4, 0xac,0x5f,0x59,0xd2,0x39, +0xc5,0x12,0x4c,0x75,0x12,0x4b,0x35,0x50,0x7, 0x12,0x4c,0x6d,0x28,0x1a,0x80,0x13, +0x7e,0x73,0x39,0x10,0xbc,0x79,0x40,0x4, 0x74,0x1, 0x80,0x8, 0xbe,0x70,0x1, 0x28, +0x7, 0x7c,0xb7,0x14,0x7a,0xb3,0x39,0x10,0xe4,0x7a,0xb3,0x39,0x11,0x80,0x1e,0x4c, +0xee,0x78,0x1a,0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x30,0x29,0x7e,0x50,0x4, 0xac, +0x5f,0x59,0x32,0x39,0xc5,0x7e,0x70,0x9, 0xac,0x78,0x12,0x4c,0x75,0xb, 0x80,0x90, +0x60,0x99,0xe4,0x93,0xbc,0xb8,0x28,0x2, 0x61,0x5a,0xda,0x79,0x22,0x7e,0xb3,0x39, +0x10,0xbe,0xb0,0x1, 0x22,0x49,0x33,0x30,0x2b,0x59,0x32,0x39,0xc7,0x22,0x12,0x4b, +0x38,0x2, 0x4c,0x84,0x7e,0xb3,0x31,0x2a,0x70,0x23,0x7e,0xb3,0x39,0x28,0xb4,0x2, +0x9, 0x12,0x4f,0xf2,0x28,0x4, 0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x33,0x7e, +0x73,0x39,0x34,0xbe,0x73,0x39,0x33,0x28,0x4, 0x7a,0x73,0x39,0x33,0x22,0x7c,0xa3, +0xb, 0x30,0x74,0x2, 0xa4,0x22,0x6c,0x33,0x90,0x60,0xa7,0xe4,0x93,0x22,0x12,0x4c, +0xd7,0x12,0x7, 0xfb,0x12,0x4e,0xcb,0x90,0x60,0xa7,0xe4,0x93,0x60,0x8, 0x30,0x15, +0x5, 0x12,0x4a,0x82,0xc2,0x15,0x22,0x12,0x4e,0xbc,0x2, 0x4c,0xdd,0xe4,0x7a,0xb3, +0x2f,0xb4,0x12,0xb9,0xc6,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, 0x7e,0x73,0x2f,0xa5, +0x7a,0x73,0x2f,0xb3,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8,0x12,0xbc,0x44,0x12, +0x4d,0x25,0x12,0x8a,0xa9,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18,0x7e,0x73,0x2d,0xa4, +0x7a,0x73,0x2e,0x14,0x7e,0x73,0x2d,0xa6,0x7a,0x73,0x2e,0x16,0x7e,0x73,0x2d,0xa5, +0x7a,0x73,0x2e,0x15,0x22,0x7e,0x8, 0x2d,0xa7,0x7e,0x34,0x0, 0x3, 0xe4,0x12,0x17, +0x56,0x7e,0x8, 0x2d,0xaa,0x7e,0x34,0x0, 0x3, 0x12,0x17,0x56,0x7a,0xb3,0x2d,0xa4, +0x7a,0xb3,0x2d,0xa5,0x7a,0xb3,0x2d,0xa6,0x7a,0xb3,0x2e,0x11,0x7a,0xb3,0x2e,0x12, +0x7a,0xb3,0x2e,0x13,0x7e,0x18,0x2d,0x90,0x12,0x4e,0x93,0x6c,0x55,0x12,0x4d,0xeb, +0x7a,0xb3,0x2d,0xa6,0x7e,0x18,0x2d,0x7c,0x12,0x4e,0xa3,0x6c,0x55,0x12,0x4d,0xeb, +0x7a,0xb3,0x2d,0xa5,0x6c,0x77,0x80,0x14,0x12,0x4e,0x74,0x60,0x5, 0x3e,0x24,0x14, +0x78,0xfb,0x12,0x4e,0x7d,0x2e,0x24,0x2d,0xa7,0x12,0x4e,0x88,0x7e,0x63,0x2d,0xa5, +0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0x4e,0x74,0x60,0x5, 0x3e,0x24,0x14, +0x78,0xfb,0x12,0x4e,0x7d,0x2e,0x24,0x2d,0xaa,0x12,0x4e,0x88,0x7e,0xa3,0x2d,0xa6, +0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x2d,0xa5,0xa4,0x7a,0xb3,0x2d,0xa4,0x7e,0x18,0x2e, +0x7, 0x12,0x4e,0x93,0x7e,0x50,0x1, 0x12,0x4d,0xeb,0x7a,0xb3,0x2e,0x13,0x7e,0x18, +0x2d,0xfd,0x12,0x4e,0xa3,0x7e,0x50,0x1, 0x12,0x4d,0xeb,0x7c,0xab,0x7a,0xa3,0x2e, +0x12,0x7e,0xb3,0x2e,0x13,0xa4,0x7a,0xb3,0x2e,0x11,0x22,0xca,0x69,0xca,0xf8,0x7c, +0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff,0x80,0x70,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60, +0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd, +0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c, +0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80, +0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44, +0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x19,0xbd,0xfe, +0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0x90,0x60, +0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, 0xb, 0xf0,0xbc,0x4f,0x38,0x8c,0x7c,0xba,0xda, +0xf8,0xda,0x69,0x22,0x7c,0xb7,0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x22,0x7c,0xa5,0x7c, +0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60, +0xb, 0x70,0x22,0x7a,0x1d,0x24,0x7e,0xf, 0x6, 0xf8,0x7e,0xb3,0x31,0x8f,0x7e,0x37, +0x31,0x74,0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x31,0x8f,0x74,0x2, 0xa4,0x7e,0xf, 0x6, +0xf8,0x2d,0x15,0x7e,0xb3,0x31,0x8e,0x7e,0x37,0x31,0x72,0x22,0x12,0x22,0xf3,0x2, +0x4e,0xc2,0x12,0x37,0xf3,0x50,0x3, 0x2, 0x23,0x1d,0x22,0x12,0x37,0xf3,0x40,0xb, +0x12,0x21,0x3d,0xe4,0x7a,0xb3,0x3, 0xfd,0x2, 0x4c,0xdd,0x22,0x7c,0x7b,0x12,0x4e, +0x81,0x9, 0xa2,0x2e,0x93,0x7c,0xb7,0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x12, +0x47,0xed,0x5c,0xba,0x22,0x6c,0x0, 0x6c,0x11,0x80,0x13,0x7c,0xb1,0x12,0x4e,0xdc, +0x60,0xa, 0x12,0x4f,0x4f,0x40,0x5, 0x7e,0x0, 0x1, 0x80,0xa, 0xb, 0x10,0x7e,0x73, +0x2f,0xa5,0xbc,0x71,0x38,0xe5,0x7c,0xb0,0x6c,0x77,0x12,0x4f,0x79,0xbe,0x0, 0x1, +0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, 0x12,0x4f,0x79,0xb4,0x1, 0x21,0x6c,0x11,0x80, +0x15,0x7c,0xb1,0x12,0x4e,0xdc,0x60,0xc, 0x12,0x4f,0x4f,0x50,0x7, 0x7c,0xb1,0x6c, +0x77,0x12,0x74,0x94,0xb, 0x10,0x7e,0x3, 0x2f,0xa5,0xbc,0x1, 0x38,0xe3,0x22,0x74, +0x2, 0xac,0xb1,0x9, 0x25,0x2e,0x1b,0x9, 0x35,0x2e,0x1c,0x7c,0xb2,0x7c,0x73,0x7c, +0xa7,0x7c,0x7b,0x90,0x60,0xaa,0xe4,0x93,0x60,0x2, 0x7c,0xa7,0x90,0x60,0xab,0xe4, +0x93,0xbc,0xba,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x7c,0xab,0xa5,0xbf,0x0, 0xc, 0x7e, +0xb3,0x3a,0x6e,0x7a,0xb3,0x3a,0x6f,0x7a,0xa3,0x3a,0x6e,0x7e,0xb3,0x3a,0x6f,0x60, +0x4, 0x74,0x8, 0x80,0xd, 0x7e,0xb3,0x2f,0xa5,0x70,0xb, 0x7e,0xb3,0x3a,0x70,0x60, +0x5, 0x14,0x7a,0xb3,0x3a,0x70,0x7e,0x73,0x3a,0x70,0xbe,0x70,0x0, 0x28,0x3, 0x74, +0x1, 0x22,0xe4,0x22,0xca,0x3b,0x7e,0xf3,0x31,0x8f,0x7e,0xe3,0x31,0x90,0x7e,0xd3, +0x31,0x91,0x6c,0xcc,0x80,0xe, 0x7c,0x7c,0xac,0x7f,0x12,0x4b,0x2c,0x7c,0xbd,0x12, +0xa4,0x57,0xb, 0xc0,0xbc,0xec,0x38,0xee,0xda,0x3b,0x22,0x7e,0x73,0x2f,0xa5,0xbc, +0x7e,0x22,0x9d,0x32,0x12,0x17,0x88,0x7d,0xf3,0x22,0x7e,0x73,0x2f,0xa5,0xbe,0x71, +0x24,0x22,0x7e,0x73,0x31,0x23,0xbe,0x70,0x1, 0x22,0x7e,0x8, 0x3c,0x22,0x12,0x50, +0x35,0x7e,0x8, 0x3c,0x2a,0x12,0x50,0x35,0x2, 0x50,0xb, 0x7e,0x37,0x3c,0x22,0xbe, +0x34,0x0, 0x0, 0x28,0x12,0x7e,0x73,0x3c,0xd3,0xbe,0x70,0x5, 0x50,0x9, 0x7e,0xb3, +0x3b,0xbd,0x70,0x3, 0x12,0x50,0x28,0x22,0x6d,0x33,0x7a,0x37,0x3c,0x6d,0x74,0x1, +0x7a,0xb3,0x3b,0x92,0x22,0xb, 0xa, 0x30,0xe5,0x67,0xa, 0x2b,0xbd,0x32,0x28,0x4, +0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x73,0x2f,0xb4,0x7a,0x73, +0x2f,0xb5,0x7e,0x73,0x31,0x23,0x7a,0x73,0x31,0x24,0xe4,0x7a,0xb3,0x31,0x27,0x22, +0x7e,0x37,0x3c,0xaa,0xb, 0x34,0x7a,0x37,0x3c,0xaa,0x7e,0x37,0x3c,0xac,0xbe,0x37, +0x3c,0xaa,0x28,0x3, 0x2, 0x50,0x7b,0x22,0x2, 0x50,0x60,0xe5,0x9a,0x60,0x5, 0xd2, +0x9c,0xa9,0xd6,0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca, +0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x50,0x78,0xd0,0x82,0xd0,0x83, +0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b, +0x32,0xe4,0x12,0x53,0x40,0x12,0xb4,0xc2,0x12,0x23,0xd6,0x12,0x57,0xd5,0x12,0xb5, +0x44,0x12,0xb4,0x2, 0x12,0xb4,0xd9,0x12,0x0, 0xa, 0x12,0xb4,0xe5,0x12,0x52,0xbd, +0x12,0xb4,0xf5,0xd2,0xaf,0x12,0xb4,0x54,0x12,0x50,0xff,0x12,0x53,0x12,0x12,0x2f, +0x1c,0x7e,0x8, 0x3c,0xae,0x12,0x52,0x97,0x90,0x60,0x50,0xe4,0x93,0xca,0xb8,0x90, +0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24,0xff,0xff,0xda,0xb8,0x2, 0x12,0x34,0xd2, +0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12, +0x52,0x87,0xe4,0x12,0x51,0x22,0x2, 0x51,0x19,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x3c, +0xde,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0x51,0xa4,0x4c,0xff,0x78,0x5, 0x5e, +0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0x51,0x43,0xda,0xf8,0x22,0x74, +0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c,0x73,0x7d,0x52,0x7c,0xab,0x7e, +0xb3,0x3c,0xde,0xb4,0xa5,0x3f,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x75,0xb5,0x1, 0xa9, +0x36,0xb3,0xfc,0x12,0x51,0x9d,0xa9,0x36,0xb3,0xfc,0x12,0x51,0x9d,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x71, +0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0x74,0x4, 0x7d,0x30,0x2, 0x51,0x43,0xa9,0xc6,0xb3, +0x75,0xb5,0x0, 0x22,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3,0x3c,0xde,0xb4,0xa5, +0x49,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0x12,0x51, +0x9d,0xa9,0x36,0xb3,0xfc,0x12,0x51,0x9d,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a, +0x61,0xb5,0xa9,0x36,0xb3,0xfc,0x12,0x51,0x9d,0xa9,0x36,0xb3,0xfc,0x12,0x51,0x9d, +0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a, +0x4d,0x32,0x22,0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x52,0x87,0x74,0x2, 0x12,0x51, +0xa4,0x7d,0xf3,0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x52,0x34,0x7a,0x45, +0x36,0x7d,0x30,0x6d,0x22,0x7f,0x6, 0x12,0x52,0x43,0x5e,0xf4,0xff,0xfd,0x12,0x52, +0x34,0x2, 0x51,0x19,0x74,0x2, 0x7d,0x3f,0x2, 0x51,0x43,0x74,0x6, 0x12,0x51,0xa4, +0x7d,0x3, 0x22,0x12,0x52,0x51,0x7e,0x35,0x36,0x12,0xb5,0xd6,0xa9,0xd2,0xb4,0xd3, +0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39,0x7f,0x21,0xf5, +0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x52,0x7c,0xe5,0x3a,0x12,0x52,0x7c,0xe5,0x39, +0x12,0x52,0x7c,0xe5,0x38,0x12,0x52,0x7c,0xe4,0x2, 0x52,0x7c,0xf5,0xb5,0xa9,0x36, +0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xa9,0xd5,0xca,0xa9,0xd1,0xea,0xa9,0xc1,0xea, +0x74,0xa5,0x7a,0xb3,0x3c,0xde,0x22,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75, +0xf4,0xc, 0x75,0xf5,0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6, +0x12,0xbc,0x4d,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xed,0xc2,0xc9,0x22,0xe4,0x7a,0xb3, +0x3b,0xcd,0x7e,0x8, 0x38,0x3a,0x7e,0x34,0x0, 0x3e,0x74,0xff,0x12,0x17,0x56,0x7e, +0x8, 0x38,0x78,0x7e,0x34,0x0, 0x3e,0x12,0x17,0x56,0x7e,0x18,0x38,0x3a,0x7a,0x1d, +0x1c,0x12,0x52,0xf4,0x2, 0x52,0xe7,0x75,0x5a,0x0, 0x75,0x5c,0x0, 0x7e,0xb3,0x3b, +0xcd,0xf5,0x91,0x22,0x2, 0x52,0xf7,0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91, +0x0, 0xc2,0x90,0xc2,0x91,0xc2,0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2, +0xad,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x12,0x12,0x52,0x3, 0xe5, +0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, 0x7e,0x71,0x27,0x12,0x27,0x43,0x74, +0xb, 0x7e,0x71,0x2f,0x12,0x27,0x43,0x74,0xc, 0x7e,0x71,0x30,0x12,0x2e,0xe2,0x22, +0xa9,0xc4,0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x8e,0x1b,0xa9,0xd0, +0xce,0xa9,0xc0,0xc9,0xd2,0x2, 0x12,0x28,0xe3,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75, +0xc2,0xc, 0xd2,0x0, 0x12,0xb5,0x20,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1, +0x22,0x7e,0x23,0x32,0x30,0x7e,0x33,0x3b,0xfe,0x12,0x57,0x2b,0xb, 0x1a,0x0, 0xac, +0x23,0x2d,0x10,0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x32, +0x31,0xbe,0x14,0xf, 0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40, +0x3, 0xe4,0x80,0x21,0xbe,0x14,0x3, 0x84,0x40,0x16,0x90,0x61,0x1b,0xe4,0x93,0x7c, +0x7b,0xbe,0x70,0x1, 0x28,0x4, 0x74,0x1, 0x80,0xb, 0x7a,0x73,0x32,0x31,0x80,0x9, +0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x32,0x31,0x7e,0x73,0x32,0x31,0xbc,0x76,0x68, +0x2, 0xd2,0xe, 0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, +0x28,0x3, 0x7e,0x10,0x7, 0x7e,0x1f,0x33,0xe2,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, +0x1, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79,0x1, 0x0, +0x86,0x6d,0x0, 0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x15,0xc8,0x7a,0xb3, +0x32,0x30,0x12,0x3f,0xac,0x30,0xe, 0xc, 0xc2,0xe, 0x12,0xaa,0xd5,0x30,0x0, 0x4, +0xe4,0x12,0xa, 0x66,0x30,0x0, 0x9, 0x12,0xaa,0x88,0x12,0x54,0xe1,0x2, 0x54,0x31, +0x22,0x12,0x54,0x4e,0x6d,0x33,0x7a,0x37,0x3b,0x68,0x6c,0xaa,0x80,0x5, 0x12,0x57, +0xc7,0xb, 0xa0,0x12,0x54,0x89,0x38,0xf6,0xe4,0x7a,0xb3,0x3a,0xfd,0x22,0x7e,0x37, +0x33,0xf4,0x12,0x22,0x65,0x7a,0x37,0x3b,0x68,0x6c,0xaa,0x80,0x23,0x12,0x54,0x89, +0x28,0x26,0xa, 0x4a,0x9, 0x64,0x3b,0x1, 0xbc,0x6b,0x50,0x12,0x7e,0x50,0x2, 0xac, +0x5a,0x49,0x42,0x33,0xee,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x3b,0xb, 0xb, 0xa0, +0x7e,0xb3,0x3a,0xfe,0xbc,0xba,0x38,0xd5,0x22,0x90,0x61,0xcb,0xe4,0x93,0xbc,0xba, +0x22,0x7e,0xb3,0x3a,0xf1,0x60,0x6, 0x14,0x7a,0xb3,0x3a,0xf1,0x22,0x12,0x54,0x4e, +0x90,0x61,0xcb,0xe4,0x93,0xbe,0xb0,0x4, 0x28,0x3, 0x12,0x54,0xe1,0x7e,0xb3,0x3b, +0x78,0x70,0x14,0x7e,0xb3,0x3c,0xdd,0xb4,0x1, 0xd, 0xe4,0x12,0x3f,0xb4,0xe4,0x7a, +0xb3,0x3a,0xf4,0x7a,0xb3,0x3a,0xfc,0x12,0x55,0x8f,0x12,0xa9,0x18,0x7e,0xa3,0x3b, +0x78,0x7a,0xa3,0x3c,0xdd,0xbe,0xb0,0xff,0x68,0x3, 0x2, 0x3f,0xb4,0x22,0x12,0x20, +0x6b,0x7e,0xb3,0x32,0x30,0xca,0x3b,0x7c,0xeb,0x6c,0xff,0x12,0x57,0x2b,0xb, 0x1a, +0xc0,0x7e,0x73,0x3b,0xfe,0xa, 0xb7,0x7e,0xb3,0x32,0x31,0xf5,0x35,0x12,0x57,0xdc, +0xbe,0xd0,0x4, 0x38,0x5, 0xe4,0x7a,0xb3,0x3a,0xfd,0xa, 0x3e,0xad,0x3b,0x7d,0xa3, +0x2d,0xac,0x75,0x34,0x0, 0x7e,0xa3,0x3a,0xfd,0xbc,0xad,0x40,0x2, 0x80,0x19,0xbe, +0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4,0x9, 0x75,0x2d,0x54,0xbc,0x7e,0x78,0xe, 0x7c, +0xbd,0x14,0xbe,0xb3,0x3a,0xfd,0x78,0x5, 0xe4,0x7a,0xb3,0x3a,0xfd,0x7e,0xc3,0x3a, +0xfd,0x80,0x41,0x7e,0xb3,0x3a,0xfd,0x4, 0x7a,0xb3,0x3a,0xfd,0x7e,0x90,0x5, 0xac, +0x9c,0x9, 0xa4,0x2d,0x54,0xbc,0xae,0x68,0x29,0xe5,0x34,0xa, 0xdb,0x19,0xcd,0x3b, +0x1, 0xa, 0x9a,0xad,0x9b,0x2d,0x9c,0x7e,0xa1,0x34,0x7c,0xba,0x4, 0xf5,0x34,0x7c, +0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31,0x35,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, +0x50,0x6, 0xb, 0xc0,0xbc,0xdc,0x38,0xbb,0x7a,0xf3,0x3a,0xfe,0xda,0x3b,0x22,0x12, +0x55,0xd2,0x2, 0x55,0x95,0x7e,0xb3,0x3a,0xf4,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x3a, +0xfc,0x7e,0xb3,0x3b,0x6a,0x70,0x3, 0x12,0x57,0x9c,0x7e,0xb3,0x3a,0xfc,0xb4,0x1, +0xc, 0x74,0x3, 0x12,0x55,0xc9,0x12,0x20,0xc9,0x3e,0x34,0x80,0x7, 0xe4,0x12,0x55, +0xc9,0x12,0x20,0xc9,0x7a,0x37,0x31,0x83,0x22,0x7a,0xb3,0x39,0x34,0x7e,0x34,0x61, +0x5d,0x22,0x7e,0x73,0x3a,0xf4,0x7a,0x73,0x3b,0x6a,0x7e,0x27,0x33,0xf8,0x12,0x56, +0x6b,0x1e,0x34,0xbd,0x32,0x50,0x6, 0x74,0x1, 0x7a,0xb3,0x3a,0xf4,0x12,0x56,0x6b, +0xbd,0x32,0x50,0xb, 0xe4,0x7a,0xb3,0x3a,0xf2,0x74,0x2, 0x7a,0xb3,0x3a,0xf4,0x7e, +0x37,0x3a,0xfa,0xbd,0x32,0x50,0x4, 0x7a,0x27,0x3a,0xfa,0x12,0x57,0xf4,0x38,0x10, +0x12,0x57,0xec,0x38,0xb, 0x12,0x57,0xe4,0x38,0x6, 0x7e,0xb3,0x16,0x91,0x70,0x3f, +0x12,0x57,0x3e,0x12,0x56,0x6b,0x1e,0x34,0x1e,0x34,0xbd,0x32,0x28,0x27,0x7e,0xb3, +0x3a,0xf2,0x4, 0x7a,0xb3,0x3a,0xf2,0x7e,0x73,0x3a,0xf2,0xbe,0x70,0x32,0x28,0x1a, +0x74,0x32,0x7a,0xb3,0x3a,0xf2,0xe4,0x7a,0xb3,0x3a,0xf4,0x7a,0xb3,0x3a,0xfc,0x7a, +0xb3,0x3b,0x67,0x80,0x5, 0xe4,0x7a,0xb3,0x3a,0xf2,0x7d,0x32,0x2, 0x57,0xfc,0x2, +0x56,0x62,0x12,0x57,0x34,0xe4,0x7a,0xb3,0x3b,0x0, 0x22,0x7e,0x14,0x61,0xce,0x7e, +0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x22,0x12,0xae,0x61,0x12,0x7a,0x71,0x12,0x7f,0x15, +0x12,0x7e,0x47,0x7e,0xb3,0x3b,0x92,0xb4,0x1, 0x1e,0x7e,0x34,0x61,0xc6,0x12,0xbd, +0x7, 0x7e,0x24,0x0, 0x5, 0xad,0x12,0x7a,0x17,0x2f,0xc2,0x7e,0x14,0x61,0xc8,0x12, +0x56,0x6f,0xad,0x32,0x7a,0x37,0x2f,0xc4,0x7e,0xb3,0x34,0x4f,0x60,0x7, 0x14,0x7a, +0xb3,0x34,0x4f,0x80,0x6, 0x7e,0xb3,0x2f,0xcd,0x60,0x9, 0x12,0x57,0x22,0x12,0x54, +0x31,0x12,0xb3,0x88,0x7e,0xb3,0x2f,0xce,0x60,0x9, 0x12,0xb9,0x41,0x12,0xa6,0x7c, +0x2, 0x56,0xd4,0x22,0x6c,0xaa,0x80,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x12,0xaa,0x4c, +0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0x57,0xc7,0x80,0x2f,0x7e,0x50,0xc, 0xac,0x5a, +0x49,0x32,0x3b,0xf, 0x49,0x12,0x3b,0xb, 0xbd,0x13,0x28,0xf, 0x7d,0x2, 0x2e,0x4, +0x3b,0xf, 0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, 0xbe,0x34,0x0, 0x2, 0x28, +0x9, 0x2e,0x24,0x3b,0xf, 0x1b,0x35,0x1b,0x28,0x30,0xb, 0xa0,0x12,0x54,0x89,0x38, +0xb7,0x22,0x12,0xa7,0x99,0x12,0xa5,0xc2,0x2, 0x47,0xdc,0x7e,0x34,0x60,0xd6,0x7e, +0x24,0x0, 0xff,0x22,0xe4,0x7a,0xb3,0x3b,0x66,0x7a,0xb3,0x3b,0x65,0x22,0x7e,0xb3, +0x3b,0x0, 0xb4,0x1, 0x7, 0x74,0x2, 0x7a,0xb3,0x3a,0xf4,0x22,0x7e,0xb3,0x3b,0x66, +0x4, 0x7a,0xb3,0x3b,0x66,0x7e,0xb3,0x3a,0xf4,0xb4,0x2, 0x18,0x7e,0xb3,0x3b,0x65, +0x4, 0x7a,0xb3,0x3b,0x65,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x3b,0x66,0x74,0x1, +0x7a,0xb3,0x3a,0xf4,0x7e,0x73,0x3b,0x65,0xbe,0x70,0x3, 0x40,0x12,0x74,0x1, 0x7a, +0xb3,0x3b,0x0, 0x74,0x2, 0x7a,0xb3,0x3a,0xf4,0x12,0x57,0x9c,0x12,0x57,0x34,0x7e, +0x73,0x3b,0x66,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0x57,0x34,0x22,0xe4,0x7a,0xb3,0x3a, +0xf2,0x6c,0xaa,0x80,0xd, 0x6d,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x3b,0x9, +0xb, 0xa0,0x12,0x54,0x89,0x38,0xee,0xe4,0x7a,0xb3,0x3a,0xf3,0x6d,0x33,0x7a,0x37, +0x3a,0xfa,0x7a,0x37,0x3a,0xef,0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x3b,0xb, +0x59,0x32,0x3b,0xf, 0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x90,0x61,0xcb,0xe4, +0x93,0x7c,0xdb,0x22,0x7e,0x73,0x2e,0x16,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x2e,0x15, +0xbe,0x70,0x0, 0x22,0x7e,0x73,0x2f,0xb3,0xbe,0x70,0x0, 0x22,0x7d,0x23,0x12,0x56, +0x6b,0x7e,0x14,0x0, 0x5, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x3b, +0x67,0xbe,0x30,0x8, 0x50,0x45,0x74,0x8, 0x80,0x3d,0x7d,0x13,0x3e,0x14,0xbd,0x12, +0x50,0xd, 0x7e,0x33,0x3b,0x67,0xbe,0x30,0x6, 0x50,0x30,0x74,0x6, 0x80,0x28,0x7e, +0x14,0x0, 0x3, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x3b,0x67,0xbe, +0x30,0x4, 0x50,0x17,0x74,0x4, 0x80,0xf, 0xbd,0x32,0x50,0xf, 0x7e,0x73,0x3b,0x67, +0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a,0xb3,0x3b,0x67,0x7e,0xb3,0x3b,0x67,0xbe, +0xb0,0x0, 0x28,0x1b,0x14,0x7a,0xb3,0x3b,0x67,0x74,0x1, 0x7a,0xb3,0x16,0x92,0x90, +0x62,0x3, 0xe4,0x93,0xbe,0xb3,0x3b,0x67,0x50,0x5, 0xe4,0x7a,0xb3,0x16,0x91,0x22, +0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, +0x32,0x91,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x31,0x2f,0x7a,0x37,0x32,0x97,0xe4, +0x7a,0xb3,0x32,0x95,0x7a,0xb3,0x32,0x96,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5f, +0xbc,0x7e,0x8, 0x2d,0xf, 0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x32,0x99,0x7a,0x37, +0x2d,0x15,0xe4,0x7a,0xb3,0x2d,0x13,0x74,0x1, 0x7a,0xb3,0x2d,0x14,0x22,0xca,0xd8, +0xca,0x79,0x90,0x60,0x50,0xe4,0x93,0x7c,0xdb,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb, +0x7e,0x73,0x31,0x95,0xbc,0x7e,0x28,0x4, 0x7c,0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3, +0x31,0x8e,0x7a,0xe3,0x31,0x8f,0x7a,0xd3,0x31,0x92,0x7a,0xe3,0x31,0x93,0x7a,0xd3, +0x31,0x94,0x7a,0xe3,0x31,0x95,0x90,0x60,0xa8,0xe4,0x93,0x7c,0xab,0x7a,0xa3,0x31, +0x98,0x90,0x60,0xa9,0xe4,0x93,0xa, 0x2b,0xa, 0x3d,0x9d,0x32,0x7c,0xb7,0x7a,0xb3, +0x31,0x90,0xa, 0x2a,0xa, 0x3e,0x9d,0x32,0x7a,0x73,0x31,0x91,0x90,0x60,0x91,0xe4, +0x93,0x7a,0xb3,0x31,0x99,0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x31,0x9a,0xa, 0x3d, +0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x31,0x9b,0x12,0x17, +0x31,0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff,0x7e, +0x8, 0x31,0xbe,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e,0x34, +0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x32,0x42,0x12,0x17,0x31,0x1b,0xfd,0x12, +0x5a,0xb9,0x12,0x67,0xc3,0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7a,0xd3,0x31,0x96, +0x7a,0xe3,0x31,0x97,0x12,0x58,0x80,0x74,0x1, 0x12,0x2a,0x62,0xe4,0x7a,0xb3,0x32, +0x22,0x7a,0xb3,0x32,0x23,0x12,0x63,0xd3,0x7a,0x37,0x32,0x2e,0x74,0x3, 0x7a,0xb3, +0x32,0x24,0xe4,0x7a,0xb3,0x32,0x25,0x74,0x2, 0x7a,0xb3,0x32,0x26,0x7e,0x34,0x61, +0x5b,0x12,0x20,0xc9,0x7a,0x37,0x32,0x28,0x74,0x4, 0x7a,0xb3,0x32,0x27,0x7e,0x34, +0x0, 0xf, 0x7a,0x37,0x32,0x2a,0x7e,0x34,0x20,0x5f,0x7a,0x37,0x32,0x2c,0x90,0x61, +0x1a,0xe4,0x93,0x7a,0xb3,0x32,0x83,0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x32,0x31, +0x90,0x61,0x1c,0xe4,0x93,0x7a,0xb3,0x32,0x32,0x74,0x4, 0x7a,0xb3,0x32,0x34,0x90, +0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x32,0x30,0x12,0x3f,0xac,0xe4,0x7a,0xb3,0x32,0x3e, +0x7a,0xb3,0x32,0x3f,0x7e,0x34,0x61,0x22,0x12,0x20,0xc9,0x7a,0x37,0x32,0x3a,0x90, +0x60,0xd3,0x93,0x7a,0xb3,0x32,0x33,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x32,0x41, +0x90,0x61,0x19,0xe4,0x93,0x7a,0xb3,0x32,0x40,0x7e,0x34,0x61,0x1e,0x12,0x20,0xc9, +0x7a,0x37,0x32,0x36,0x7e,0x34,0x61,0x20,0x12,0x20,0xc9,0x7a,0x37,0x32,0x38,0x90, +0x61,0x1d,0xe4,0x93,0x7a,0xb3,0x32,0x35,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x32,0x8b, +0x74,0x1, 0x7a,0xb3,0x32,0x88,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x32,0x89,0xe4,0x7a, +0xb3,0x32,0x87,0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x32,0x8d,0x74,0x1, 0x7a,0xb3,0x32, +0x84,0x74,0x2, 0x7a,0xb3,0x32,0x85,0xe4,0x7a,0xb3,0x32,0x86,0x74,0x1, 0x7a,0xb3, +0x32,0x81,0xe4,0x7a,0xb3,0x32,0x82,0x7e,0x34,0x16,0xd3,0x7a,0x37,0x32,0x8f,0xa, +0x3e,0xca,0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x32,0x65,0x12, +0x17,0x31,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x12,0xbc,0xdb,0x12,0x5b,0x1d,0x90, +0x60,0x50,0xe4,0x93,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x31,0x9b,0x6d,0x0, 0x9, 0xb3, +0x31,0x9a,0x12,0x5b,0x5, 0x93,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x32,0x42,0x6d,0x0, +0x9, 0xb3,0x32,0x41,0x12,0x5b,0x5, 0x93,0xa, 0x1b,0x2e,0x14,0x31,0x9d,0x12,0x5b, +0x11,0xe5,0x25,0x12,0x5b,0x9, 0x93,0xa, 0x1b,0x2e,0x14,0x32,0x44,0x12,0x5b,0x11, +0xe5,0x24,0x2, 0x17,0x56,0x7e,0x34,0x0, 0x2, 0x12,0x17,0x56,0x90,0x60,0x50,0xe4, +0x22,0x6d,0x0, 0x90,0x60,0x91,0xe4,0x93,0xa, 0x3b,0x1b,0x35,0x22,0x6c,0xaa,0x6c, +0x99,0x80,0xc, 0xa, 0xf9,0x9, 0xbf,0x31,0x9b,0xbc,0xba,0x68,0x7, 0xb, 0x90,0x12, +0x5b,0x49,0x38,0xef,0x12,0x5b,0x49,0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xdf, +0x7a,0xb, 0xa0,0x74,0x6e,0x7a,0x1b,0xb0,0x22,0x90,0x60,0x50,0xe4,0x93,0xbc,0xb9, +0x22,0x12,0x62,0xab,0x12,0x58,0xce,0x12,0x0, 0x42,0x12,0xbc,0x44,0x7e,0x18,0x4, +0x0, 0x7a,0x1f,0x6, 0xf8,0x7e,0xf, 0x6, 0xf8,0x7e,0x1f,0x6, 0xf4,0x12,0x68,0x51, +0x7e,0x18,0x8, 0xa, 0x7a,0x1f,0x13,0x86,0x7e,0x18,0xd, 0xc8,0x7a,0x1f,0x13,0x8a, +0x7e,0xf, 0x13,0x8a,0x7e,0x1f,0x13,0x86,0x12,0x68,0x2e,0x12,0x5f,0xc5,0x12,0x22, +0x6e,0x12,0x64,0x21,0x12,0x5b,0xa8,0x2, 0x5b,0x9a,0xe4,0x7a,0xb3,0x34,0x38,0x7a, +0xb3,0x34,0x39,0x7a,0xb3,0x34,0x3a,0x22,0x12,0x64,0x5f,0x7e,0x24,0x0, 0x3, 0xad, +0x32,0x7e,0x8, 0x2f,0xcf,0x74,0xff,0x12,0x17,0x56,0x12,0xa3,0x66,0x7e,0x8, 0x30, +0xdd,0x12,0x5b,0xd0,0x7e,0x8, 0x31,0x23,0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x17,0x56, +0x6c,0xaa,0x80,0x20,0x74,0x3, 0x12,0xbc,0x4d,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, +0xa, 0x12,0x5e,0xac,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41, +0x0, 0x28,0xb, 0xa0,0x12,0x5b,0xfa,0x38,0xdb,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc, +0xba,0x22,0xca,0xf8,0x7e,0x68,0x30,0xdd,0x6c,0xaa,0x80,0x1f,0x7e,0x70,0xff,0x7e, +0x50,0x9, 0xac,0x5a,0x19,0x72,0x2f,0xd3,0xe4,0xa, 0x4a,0x19,0xb4,0x26,0x55,0x74, +0xff,0x19,0xb4,0x26,0x67,0x19,0xb4,0x26,0x71,0xb, 0xa0,0x12,0x5b,0xfa,0x38,0xdc, +0x7e,0x73,0x31,0x23,0xa5,0xbf,0x0, 0x25,0x7e,0xb3,0x33,0xff,0x70,0x2, 0xc1,0x21, +0x6c,0xaa,0x80,0x12,0x7e,0x44,0x7f,0xff,0x12,0x5e,0xbe,0x2d,0x12,0x79,0x40,0x0, +0x14,0x12,0x5e,0xc6,0xb, 0xa0,0x12,0x5b,0xfa,0x38,0xe9,0xc1,0x21,0x7e,0xb3,0x33, +0xff,0x70,0x3f,0xbe,0x70,0x0, 0x28,0x3a,0x6c,0xaa,0x80,0x2c,0x7e,0x90,0x9, 0xac, +0x9a,0x49,0x34,0x2f,0xcf,0x12,0x5e,0xbe,0x2d,0x12,0x79,0x30,0x0, 0x14,0x49,0x34, +0x2f,0xd1,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74,0x1, 0xa, 0x3a,0x19,0xb3, +0x26,0x55,0x19,0xa4,0x2f,0xd3,0xb, 0xa0,0x7e,0xb3,0x31,0x23,0xbc,0xba,0x38,0xcc, +0xc1,0x21,0x6c,0xaa,0x80,0x17,0x12,0x5e,0xac,0x3e,0x34,0x59,0x43,0x15,0x4e,0x59, +0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15,0x78,0xb, 0xa0,0x12,0x5b,0xfa, +0x38,0xe4,0x6c,0xaa,0x80,0x3d,0x6c,0xff,0x80,0x32,0x7e,0x70,0x2, 0xac,0x7f,0x7f, +0x6, 0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f,0xff,0x68,0x1d,0xa, 0x4f,0x9, +0xb4,0x26,0x71,0xb4,0xff,0x14,0x12,0x5e,0xb6,0x59,0x32,0x15,0x4e,0x69,0x30,0x0, +0x28,0x59,0x32,0x15,0x50,0x12,0x5e,0xcf,0x80,0x7, 0xb, 0xf0,0x12,0x5e,0xa4,0x38, +0xc9,0xb, 0xa0,0x7e,0xb3,0x33,0xff,0xbc,0xba,0x38,0xbb,0x6c,0xaa,0x80,0x24,0xa, +0x3a,0x9, 0xb3,0x26,0x67,0xb4,0xff,0x19,0x6c,0xff,0x80,0x10,0xa, 0x4f,0x9, 0xb4, +0x26,0x71,0xb4,0xff,0x5, 0x12,0x5e,0xcf,0x80,0x7, 0xb, 0xf0,0x12,0x5e,0xa4,0x38, +0xeb,0xb, 0xa0,0x12,0x5b,0xfa,0x38,0xd7,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x9, 0xac, +0x7a,0x49,0x43,0x2f,0xcf,0x12,0x5e,0xb6,0x59,0x42,0x15,0x76,0x49,0x33,0x2f,0xd1, +0x59,0x32,0x15,0x78,0xb, 0xa0,0x7e,0xb3,0x31,0x23,0xbc,0xba,0x38,0xde,0x7e,0x34, +0x15,0x4e,0x7a,0x37,0x26,0x61,0x7e,0x34,0x15,0x76,0x7a,0x37,0x26,0x63,0x7e,0x34, +0x15,0x9e,0x7a,0x37,0x26,0x65,0x7e,0x73,0x33,0xff,0x7a,0x73,0x26,0x5f,0x7e,0x73, +0x31,0x23,0x7a,0x73,0x26,0x60,0x7e,0x8, 0x26,0x5f,0x12,0x4, 0xad,0x6c,0xaa,0x80, +0x5f,0x7e,0x70,0xff,0x6c,0xff,0x80,0x19,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12,0x15, +0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, 0x73,0x26,0x67,0x80,0x7, 0xb, +0xf0,0x12,0x5e,0xa4,0x38,0xe2,0xbe,0x70,0xff,0x68,0x33,0x7e,0x50,0x9, 0xac,0x5a, +0x19,0x72,0x2f,0xd3,0x74,0x1, 0xa, 0x47,0x19,0xb4,0x26,0x55,0x7e,0x90,0x9, 0xac, +0x9a,0x49,0x24,0x2f,0xcf,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20, +0x0, 0x14,0x49,0x44,0x2f,0xd1,0x7e,0x50,0x2, 0xac,0x57,0x12,0x5e,0xc6,0xb, 0xa0, +0x7e,0x63,0x31,0x23,0xbc,0x6a,0x38,0x99,0x6c,0xaa,0x80,0x20,0xa, 0x3a,0x9, 0xb3, +0x26,0x55,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x5e,0xac,0x7f,0x6, 0x2d,0x13,0x79,0x40, +0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x12,0x5b,0xfa,0x38, +0xdb,0x7e,0xf3,0x31,0x23,0x7a,0xf3,0x33,0xff,0x6c,0xaa,0x80,0x68,0xa, 0x3a,0x9, +0xb3,0x26,0x55,0xb4,0x1, 0x2c,0x12,0x5e,0x9d,0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, +0x74,0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x5e,0x9d,0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, +0x6, 0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a,0x1b,0xb0, +0x80,0x27,0x12,0x5e,0x9d,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14, +0x74,0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1, +0x2f,0xd3,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x5e,0x9d,0x7e,0x1b,0xb0,0x39, +0xb1,0x0, 0xa, 0xb, 0xa0,0x12,0x5b,0xfa,0x38,0x93,0xda,0xf8,0x22,0xa, 0x3a,0x2d, +0x3d,0x7d,0x2c,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x22,0x7e,0x44,0x7f,0xff, +0x7e,0x70,0x2, 0xac,0x7a,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x22,0x7e,0x50, +0x2, 0xac,0x5a,0x7f,0x6, 0x22,0x7f,0x6, 0x2d,0x12,0x79,0x40,0x0, 0x28,0x22,0xa, +0x3a,0x19,0xf3,0x26,0x67,0x74,0x1, 0x19,0xb4,0x26,0x71,0x22,0x7c,0xab,0x7e,0x8, +0x30,0xdd,0x12,0x5b,0xfa,0x28,0x1f,0xa, 0x3a,0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0, +0xb4,0x2, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x31, +0x7d,0x20,0x39,0xb1,0x0, 0xa, 0x22,0xca,0xd8,0xca,0x79,0x12,0xbc,0xb7,0xb, 0x1a, +0x40,0x90,0x61,0x35,0xe4,0x93,0x70,0x2, 0xe1,0xae,0x90,0x60,0xa7,0xe4,0x93,0x70, +0x2, 0xe1,0xae,0x6c,0xff,0xe1,0xa7,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x30,0x2d, +0x5e,0xe0,0xf, 0x49,0xc3,0x30,0x2b,0x7e,0x14,0x60,0xd1,0x12,0x5f,0xc8,0x2d,0x24, +0xbd,0xc2,0x40,0x42,0x49,0xd3,0x30,0x29,0x7d,0x3d,0x12,0x5f,0xd0,0x7c,0xdb,0x90, +0x60,0xa7,0xe4,0x93,0xbc,0xbd,0x38,0xe, 0x7d,0x34,0x1b,0x34,0x12,0x5f,0xb3,0x7c, +0xbe,0x12,0x5e,0xdc,0x80,0x3f,0x7e,0x70,0x2, 0xac,0x7d,0x2e,0x34,0x60,0xc5,0x12, +0x7f,0x9a,0x74,0x9, 0xac,0xbf,0x59,0xd5,0x30,0x29,0x7e,0x34,0x60,0xcf,0x12,0x20, +0xc9,0x12,0x5f,0xb3,0x80,0x1f,0xbd,0xc4,0x40,0x1b,0x7d,0x54,0x2e,0x54,0x0, 0xa, +0xbd,0xc5,0x40,0x5, 0x7c,0xbe,0x12,0x5e,0xdc,0x7d,0xc4,0x1b,0xc4,0x74,0x9, 0xac, +0xbf,0x59,0xc5,0x30,0x2b,0xb, 0xf0,0x12,0x5e,0xa4,0x28,0x2, 0xe1,0x27,0xda,0x79, +0xda,0xd8,0x22,0x74,0x9, 0xac,0xbf,0x59,0x35,0x30,0x2b,0x22,0x7e,0x34,0x61,0x29, +0x7e,0x24,0x0, 0xff,0x22,0x2, 0x20,0xd1,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x22, +0x6c,0xaa,0x80,0x1f,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e,0xf4,0x60,0xb1,0x12, +0xa8,0x83,0xbd,0x23,0x38,0xb, 0x2e,0x14,0x60,0xb3,0x12,0x5f,0xc8,0xbd,0x23,0x50, +0xb, 0xb, 0xa0,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xba,0x38,0xd8,0x7c,0xba,0x22,0xff, +0x70,0x8f,0x0, 0xff,0x3b,0xc4,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x31,0x36,0x32,0x1, 0xd2,0x0, 0x31,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x10,0xef,0x44,0x32,0x41,0x5f,0x42,0x69,0x65,0x6c,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0xf, 0xe, 0xd, +0xc, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xb, 0xa, 0x9, 0x8, 0x18,0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x6, 0xb, 0x0, +0x0, 0x0, 0x64,0x0, 0xfa,0x1, 0x2c,0x2, 0xbc,0x2, 0xee,0x4, 0x1a,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x1e,0x1, 0xf4,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x0, 0x4, 0x3e,0x28,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x5a,0x40,0xe, 0x19,0x27,0x13,0xd, 0x6, 0x80,0x13,0xd, 0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x46,0x45,0x2, 0x4e,0x2, 0x4e,0x1, +0x38,0x1, 0x3b,0x7, 0x80,0x46,0x48,0x2, 0xe, 0x2, 0xe, 0x1, 0x43,0x1, 0x43,0x0, +0xa0,0x0, 0x8c,0x0, 0x8c,0x0, 0xc8,0x0, 0x64,0x0, 0xb4,0x0, 0xb4,0xa, 0x0, 0x0, +0xdc,0x6, 0xa, 0x14,0x28,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0x10,0x1, 0x3b,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x3, 0x3e,0x5a,0x28, +0x24,0x3, 0x41,0x5c,0x28,0x2b,0x3, 0x43,0x5d,0x28,0x33,0x3, 0x47,0x5f,0x28,0x1e, +0x3, 0x3e,0x5a,0x28,0x1e,0x3, 0x3e,0x5a,0x28,0x1e,0x3, 0x3e,0x5a,0x28,0x1e,0x3, +0x3e,0x5a,0x28,0x4, 0x5, 0xd, 0xe, 0xf, 0x10,0x11,0x4, 0x0, 0x96,0x1, 0x90,0x28, +0x1, 0x2c,0x1, 0x5e,0x0, 0xc8,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, 0x90, +0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, 0x50, +0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x8, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x32,0x1, 0xf4,0x1, 0xf4,0x2, 0x58,0x0, 0xc8, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0xe4,0x7a,0xb3,0x3b,0xcd, +0x7a,0xb3,0x3b,0xce,0x90,0x60,0x50,0x93,0x7a,0xb3,0x3b,0xcf,0x90,0x60,0x51,0xe4, +0x93,0x7a,0xb3,0x3b,0xd0,0xe4,0x7a,0xb3,0x3b,0xd1,0x90,0x60,0x99,0x93,0x7a,0xb3, +0x3b,0xd2,0xe4,0x7a,0xb3,0x3b,0xd3,0x7a,0xb3,0x3b,0xd4,0x90,0x61,0xca,0x93,0x7a, +0xb3,0x3b,0xd6,0x7e,0x34,0x61,0x4f,0x12,0x20,0xc9,0x1e,0x34,0x1e,0x34,0x7a,0x73, +0x3b,0xda,0x7e,0x34,0x61,0x55,0x12,0x20,0xc9,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x3b, +0xdb,0x74,0x64,0x7a,0xb3,0x3b,0xec,0x90,0x61,0x18,0xe4,0x93,0x7a,0xb3,0x3b,0xed, +0x90,0x61,0x17,0xe4,0x93,0x7a,0xb3,0x3b,0xd9,0x90,0x61,0x19,0xe4,0x93,0x7a,0xb3, +0x3b,0xef,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x3b,0xee,0x90,0x61,0x1d,0xe4,0x93, +0x7a,0xb3,0x3b,0xf0,0x90,0x61,0x25,0xe4,0x93,0x7a,0xb3,0x3b,0xeb,0xe4,0x7a,0xb3, +0x3b,0xe6,0x74,0xc8,0x7a,0xb3,0x3b,0xe4,0x74,0x1e,0x7a,0xb3,0x3b,0xe5,0x74,0x1, +0x7a,0xb3,0x3b,0xe3,0x74,0xc, 0x7a,0xb3,0x3b,0xe2,0x74,0x1, 0x7a,0xb3,0x3b,0xe7, +0xe4,0x7a,0xb3,0x3b,0xe8,0x7a,0xb3,0x3b,0xe9,0x7e,0x8, 0x3b,0xf1,0x7e,0x34,0x0, +0x2c,0x12,0x17,0x56,0x7e,0x34,0x60,0xd6,0x12,0x20,0xc9,0xa, 0x36,0x7a,0x73,0x3b, +0xfc,0x7e,0x34,0x60,0xd6,0x12,0x20,0xc9,0x7a,0x73,0x3b,0xfd,0x90,0x60,0xd4,0x93, +0x7a,0xb3,0x3b,0xfe,0x90,0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x3b,0xff,0x7e,0x34,0x0, +0x4, 0xca,0x39,0x12,0x5f,0xbc,0x7e,0x8, 0x3c,0xd, 0x12,0x17,0x31,0x1b,0xfd,0x74, +0x5, 0x7a,0xb3,0x3c,0x1a,0x74,0x1, 0x7a,0xb3,0x3c,0x11,0x7e,0x34,0x0, 0x28,0xca, +0x39,0x7e,0x34,0x61,0xdb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2d,0x54,0x12,0x17,0x31, +0x1b,0xfd,0x22,0x6d,0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2,0x31,0xfd,0x54, +0x1, 0x78,0x5, 0x4e,0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x31, +0x95,0xbc,0x5a,0x38,0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2,0x31,0xda,0xbe, +0xb0,0xd, 0x38,0x5, 0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60, +0x8, 0x80,0x3, 0x4e,0x60,0x50,0xb, 0xa0,0x7e,0xb3,0x31,0x94,0xbc,0xba,0x38,0xd9, +0x22,0x7e,0x8, 0x2d,0x7c,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x17,0x56,0x90,0x60,0x9c, +0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x2d,0xad,0x74,0xff,0x12,0x17,0x56,0x90,0x60, +0x9c,0xe4,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x2d,0xd5,0x74,0xff,0x12,0x17,0x56, +0x90,0x60,0x9a,0x12,0x64,0x62,0x7e,0x8, 0x2e,0x97,0x74,0xff,0x2, 0x17,0x56,0x90, +0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x9, 0xac,0x7b,0x22,0xca,0x3b,0x75,0x24,0x0, +0x6c,0xff,0x75,0x25,0x0, 0x75,0x26,0x0, 0x75,0x28,0x3, 0x6c,0xee,0x7e,0x48,0x30, +0xdd,0x7e,0xb3,0x31,0x2c,0x70,0xe, 0x7e,0xb3,0x31,0x28,0x70,0x8, 0x7e,0xb3,0x31, +0x29,0x70,0x2, 0xc1,0x59,0x30,0x10,0x6, 0x7e,0x68,0x38,0x78,0x80,0x4, 0x7e,0x68, +0x38,0x3a,0x7f,0x6, 0x7e,0x34,0x0, 0x3e,0x74,0xff,0x12,0x17,0x56,0x7e,0x73,0x31, +0x25,0x7a,0x6b,0x70,0x6c,0xdd,0xc1,0x1a,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x30,0x2d, +0x7c,0xbc,0x54,0xf, 0x12,0x66,0x82,0xf5,0x28,0x7c,0xbc,0x54,0xf0,0xbe,0xb0,0x0, +0x28,0x2, 0xc1,0x18,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, 0xc1,0x18,0x7e,0x8, 0x0, +0x28,0x7c,0xbc,0x12,0xa2,0x6f,0x50,0x2, 0xc1,0x18,0x74,0x9, 0xac,0xbd,0x9, 0xb5, +0x30,0x2e,0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x30,0x2f,0xc4,0x54,0xf0,0xf5, +0x26,0x7e,0x73,0x31,0x6e,0xbc,0x7c,0x28,0x57,0x7e,0xb3,0x31,0x2a,0x70,0x2a,0x75, +0x29,0xf, 0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x38,0x26,0x6d,0x22,0x74,0x1, +0x12,0x66,0x8c,0x75,0x29,0x20,0x7e,0x8, 0x0, 0x26,0xa, 0x3c,0x2e,0x34,0x38,0x30, +0x6d,0x22,0x74,0x10,0x12,0x66,0x8c,0x80,0xe, 0xa, 0x3c,0x9, 0xb3,0x38,0x26,0xf5, +0x25,0x9, 0xb3,0x38,0x30,0xf5,0x26,0xa, 0x3c,0x12,0x66,0x84,0xb4,0x1, 0x11,0xe4, +0xa, 0x3c,0x19,0xb3,0x38,0x26,0x19,0xb3,0x38,0x30,0x75,0x25,0x0, 0x75,0x26,0x0, +0x7e,0xb3,0x31,0x85,0xb4,0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd,0x9, 0xb5, +0x30,0x2d,0xbe,0xb0,0xff,0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, 0xac,0x9d,0x49, +0xb4,0x30,0x29,0x49,0xa4,0x30,0x2b,0xe5,0x28,0xb4,0x1, 0x2c,0x75,0x27,0x0, 0x80, +0x1d,0x7e,0x71,0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x38,0xba,0x54,0xf, 0xbc,0xbc, +0x78,0xa, 0x49,0xb3,0x38,0xb6,0x49,0xa3,0x38,0xb8,0x80,0xc, 0x5, 0x27,0x90,0x60, +0x99,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd9,0x5e,0xb4,0xf, 0xff,0x5e,0xa4,0xf, 0xff, +0x9, 0x74,0x30,0x2d,0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x2d,0xa5,0xbe,0x70, +0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x24,0xb, 0xf0,0xe5,0x28, +0xa, 0x5b,0x12,0x66,0xce,0x2d,0xb5,0x80,0x4, 0x2e,0xb4,0xc0,0x0, 0x7e,0x70,0x6, +0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, 0x7f,0x6, 0x2d,0x13,0x79,0xa0, +0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0,0x0, 0x6, 0xe5,0x26,0x2d,0x3d, +0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0,0x7e,0x73,0x31,0x6e,0xbc,0x7d, +0x28,0x2, 0x81,0xb8,0xe5,0x24,0x39,0xb6,0x0, 0x1, 0xbe,0xf0,0x0, 0x38,0x6, 0x7e, +0xb3,0x31,0x29,0x60,0xa, 0xb2,0x10,0x12,0x67,0xa4,0x74,0x1, 0x12,0x46,0x8e,0x7e, +0xb3,0x31,0x28,0x60,0x5, 0x7f,0x4, 0x12,0x5b,0xd0,0xe4,0x7a,0xb3,0x31,0x2c,0x7a, +0xb3,0x31,0x28,0x7a,0xb3,0x31,0x29,0x80,0x4, 0xe4,0x12,0x46,0x8e,0x12,0x66,0xd6, +0xca,0x59,0x7e,0x18,0x30,0x29,0x7e,0x8, 0x38,0xb6,0x12,0x17,0x31,0x1b,0xfd,0x4c, +0xff,0x78,0xc, 0x12,0x64,0x5f,0x7e,0x8, 0x38,0xb6,0x74,0xff,0x12,0x17,0x56,0xda, +0x3b,0x22,0xa, 0x3b,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0x22,0x7c,0x9b,0x7f,0x71, +0x7e,0x7b,0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b,0x90,0x22,0xa, 0x28, +0x7e,0xb, 0x80,0xa, 0x38,0x9d,0x32,0x12,0x17,0x88,0xe5,0x29,0xa, 0x2b,0xbd,0x32, +0x8, 0x15,0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba,0x28,0x4, 0x2c,0xb9, +0x80,0x2, 0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, 0x70,0x22,0x3, 0x3, +0x54,0xc0,0x7c,0xab,0xe4,0x22,0x90,0x60,0x99,0xe4,0x93,0x7c,0xab,0x74,0x9, 0xa4, +0x22,0xca,0x79,0x7e,0xf3,0x31,0x23,0x7e,0xe3,0x31,0x24,0x7c,0xbf,0x7c,0x7e,0x12, +0x9f,0xf4,0x7c,0xbf,0x12,0x95,0x8d,0x4c,0xee,0x78,0x14,0x12,0x66,0xd6,0xca,0x59, +0x7e,0x18,0x2f,0xcf,0x7e,0x8, 0x30,0x83,0x12,0x17,0x31,0x1b,0xfd,0x80,0xb, 0x7e, +0xb3,0x31,0x2a,0x70,0x5, 0x7c,0xbf,0x12,0x93,0x10,0x7c,0xbf,0x12,0xa3,0x13,0xbe, +0xf0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x31,0x2c,0xda,0x79,0x22,0x12,0x93,0x8f, +0x2, 0x66,0xe1,0xca,0xf8,0x7e,0xa3,0x31,0x23,0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x31, +0x24,0xbe,0xb0,0x0, 0x28,0x13,0x74,0x1, 0x7a,0xb3,0x31,0x28,0x80,0xb, 0xbe,0xa0, +0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x31,0x2c,0x12,0x66,0xd6,0xca,0x59,0x7e,0x18, +0x2f,0xcf,0x7e,0x8, 0x30,0x29,0x12,0x17,0x31,0x1b,0xfd,0x90,0x61,0x35,0xe4,0x93, +0xbe,0xb0,0x0, 0x28,0x23,0x6c,0xff,0x80,0x1a,0x12,0x67,0x9b,0x12,0x70,0x86,0x74, +0x9, 0xac,0xbf,0x59,0x35,0x30,0x29,0x49,0x35,0x2f,0xd1,0x12,0x72,0x70,0x12,0x5f, +0xb3,0xb, 0xf0,0x12,0x5e,0xa4,0x38,0xe1,0xda,0xf8,0x22,0x74,0x9, 0xac,0xbf,0x49, +0x35,0x2f,0xcf,0x22,0x7e,0xb3,0x3c,0x20,0x4, 0x7a,0xb3,0x3c,0x20,0xe5,0x5b,0xb4, +0x1, 0x8, 0xe4,0x7a,0xb3,0x3c,0x20,0x75,0x5b,0x0, 0x7e,0x73,0x3c,0x20,0x7a,0x73, +0x3b,0x7c,0x22,0xca,0xf8,0x7e,0x73,0x31,0x99,0xa, 0x47,0x7e,0x73,0x31,0x92,0xa, +0x57,0x2d,0x54,0x7e,0xa3,0x31,0x94,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x31, +0x93,0x7e,0xa3,0x31,0x95,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, +0x31,0xda,0x7e,0x18,0x31,0x9b,0x12,0xd, 0xd9,0x75,0x25,0x15,0x7e,0x8, 0x31,0xfd, +0x7e,0x18,0x31,0xbe,0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7a,0xb3,0x32,0x21, +0x70,0x5, 0x12,0x38,0x2a,0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x2f,0xf1,0x12,0x2a,0x91, +0x22,0x7c,0xab,0x12,0x68,0xc, 0x7c,0xba,0x12,0x13,0xc7,0x2, 0x0, 0x1e,0x7f,0x60, +0x7e,0xa3,0x31,0x8e,0x7e,0xb3,0x31,0x8f,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d, +0x3f,0xe4,0x12,0x17,0x56,0x7f,0x6, 0x7d,0x3f,0x12,0x17,0x56,0x7a,0xb3,0x16,0x91, +0x22,0x7f,0x70,0x7e,0x33,0x31,0x95,0xa, 0x43,0x7e,0x33,0x31,0x94,0xa, 0x53,0x2d, +0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x16,0x90,0x7f,0x1, 0xa, 0x3a,0x12,0x17, +0x56,0x7f,0x7, 0xa, 0x3a,0x2, 0x17,0x56,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x51, +0x7f,0x40,0x7f,0x15,0x12,0x68,0x51,0x12,0x69,0x1b,0x7e,0xe0,0x1, 0x12,0x2d,0x45, +0x30,0x1c,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x69,0x2b,0x6c,0xdd,0x80, +0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, 0xac,0xbd, +0x7f,0x5, 0x2d,0x15,0x12,0x69,0x22,0xb, 0xd0,0x7e,0x73,0x31,0x95,0xa, 0x7, 0x7e, +0x63,0x31,0x94,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b,0xe0,0x78, +0xbc,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x31,0x94,0x12,0x68,0xe1,0xda,0x79,0xda,0xd8, +0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f,0x70,0x12,0x69,0x3b,0x7c,0xeb,0x6c,0xdd, +0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74, +0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e,0x6d,0x0, 0x12,0x15,0x77,0x1b,0x6a,0x30, +0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79,0xda,0xd8,0x22,0x7e,0x8, 0x31,0x8e,0x2, +0x0, 0x2e,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0xb3,0x31,0x94,0x7e, +0x73,0x31,0x95,0x12,0x10,0xee,0x74,0x2, 0x2, 0x0, 0x1e,0x7c,0x7b,0xa5,0xbf,0x0, +0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x70,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xa, 0x47, +0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78,0xfb,0x7c, +0xb9,0x22,0x7e,0xa3,0x3b,0xcc,0x7c,0xba,0x4, 0x7a,0xb3,0x3b,0xcc,0x7a,0xa3,0x3b, +0x7e,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x3c,0x39,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0xa9,0xc0, +0x93,0x75,0x5a,0x0, 0x32,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x3c, +0x1e,0x4d,0x22,0x78,0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x3c, +0x1e,0x15,0x5c,0x7e,0x27,0x3c,0x1e,0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, +0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x3c,0x1e,0x75,0x5c,0xea, +0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x12,0x0, 0x1e,0xe4,0x12,0x0, 0xe, 0x7e,0x8, +0x31,0x8e,0x2, 0xd, 0x72,0xb4,0x3, 0x5, 0x12,0x6a,0x1, 0x80,0x2, 0xe4,0x22,0x12, +0x6a,0xbc,0x74,0x1, 0x22,0x12,0x6a,0xa8,0x38,0x2, 0xe4,0x22,0x12,0x6a,0x3e,0x49, +0x55,0x34,0x3b,0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x2e,0x19,0x2, 0x6a,0x15,0x7e,0xa3, +0x34,0x39,0x74,0x4, 0xa4,0x22,0x30,0x1c,0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12,0x13, +0x2c,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x4f,0x12,0x6a,0x3e,0x49,0x35,0x34,0x3b,0x49, +0x15,0x34,0x3d,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15, +0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x31,0x94,0x7e,0x73, +0x31,0x95,0x12,0x10,0xee,0x7e,0xb3,0x34,0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12,0x6a, +0xa8,0x28,0xe, 0x12,0x6a,0x25,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80, +0x2, 0x74,0x2, 0x7a,0xb3,0x34,0x3a,0x22,0x7e,0x73,0x34,0x38,0xbe,0x73,0x34,0x39, +0x22,0x7e,0x8, 0x31,0x8e,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70, +0x99,0x12,0x13,0x2c,0x2, 0x0, 0x4e,0xca,0x3b,0x7e,0x34,0xff,0xff,0x7a,0x35,0x34, +0x7e,0xb3,0x3b,0xe2,0xf5,0x29,0x7e,0xb3,0x31,0x8e,0xf5,0x2a,0x7e,0xb3,0x31,0x8f, +0xf5,0x2b,0x7e,0xb3,0x31,0x91,0xf5,0x2c,0x7e,0xb3,0x31,0x90,0xf5,0x2d,0x7e,0x34, +0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30,0x12,0x6a,0xb1,0x30, +0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x8d,0x59,0x6c,0xff, +0x80,0x33,0x12,0x6d,0x81,0x80,0x19,0x7e,0x11,0x2b,0xac,0x1e,0x3e,0x4, 0x7e,0x30, +0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x10,0x12,0x6d,0x4c, +0xe5,0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x6d,0x5b,0x74,0x2, 0xac,0xbf,0x59, +0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xc7,0x12,0xbc,0xc0,0x68,0xe, +0x7e,0x34,0x10,0x0, 0x7e,0xa1,0x2b,0x74,0x2, 0xa4,0x59,0x35,0x33,0xfe,0x6c,0xff, +0x80,0x79,0x12,0x6d,0x81,0x80,0x14,0x12,0x6d,0x8a,0x1e,0x34,0x1e,0x24,0x50,0x3, +0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x13,0x12,0x6d,0x4c,0xe5,0x29,0xbc,0xbe,0x38, +0xe6,0xe5,0x29,0x12,0x6d,0x5b,0x74,0x4, 0xac,0xbf,0x59,0x35,0x37,0x99,0xe5,0x29, +0xbe,0xb1,0x2c,0x50,0x38,0x9f,0x11,0x7a,0x1f,0x2c,0x15,0x7e,0xe1,0x29,0x80,0x14, +0x12,0x6d,0x8a,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d, +0x13,0x12,0x6d,0x4c,0xe5,0x2c,0xbc,0xbe,0x38,0xe6,0xe5,0x29,0xa, 0x3b,0x6d,0x22, +0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x6d,0x5f,0x80,0x4, 0x7e,0x34,0x10, +0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x37,0x9b,0xb, 0xf0,0xe5,0x2d,0xbc,0xbf,0x38, +0x81,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0xcc,0x12,0x15,0x77,0x6c,0xff, +0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, 0x5f,0xad,0x53,0x7e,0x14, +0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20, +0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59,0x25,0x34,0x0, 0xb, 0xf0, +0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0x28, +0x12,0x15,0x77,0x6c,0xff,0x80,0x5c,0x74,0x4, 0xac,0xbf,0x49,0x25,0x37,0x99,0xa, +0x1f,0xad,0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e, +0xe4,0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x74,0x4, 0xac,0xbf, +0x59,0x25,0x37,0x99,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49, +0x25,0x37,0x9b,0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50, +0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x37, +0x9b,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73,0x3b,0xe4,0xa, 0x37,0x6d, +0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x15, +0x75,0x7d,0xe3,0x7a,0xe5,0x34,0x7e,0x73,0x3b,0xe5,0xa, 0x37,0x6d,0x22,0x74,0xc, +0x2f,0x11,0x14,0x78,0xfb,0x7d,0x1f,0x12,0x15,0x75,0x7d,0x63,0x6c,0xff,0x80,0x20, +0x74,0x2, 0xac,0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34, +0x59,0x35,0x34,0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x34,0x0, 0xb, 0xf0, +0xe5,0x2c,0xbc,0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74,0x4, 0xac,0xbf,0x49,0x45, +0x37,0x99,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x37,0x99,0x80,0x8, +0xbd,0x46,0x50,0x4, 0x59,0x65,0x37,0x99,0x49,0x45,0x37,0x9b,0xbe,0x45,0x34,0x28, +0x9, 0x7e,0x35,0x34,0x59,0x35,0x37,0x9b,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65, +0x37,0x9b,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30,0x2, 0xc, 0x7e,0xd, 0x30, +0x12,0x6d,0xb1,0xb, 0x34,0x7a,0x73,0x32,0x41,0xda,0x3b,0x22,0x6d,0x0, 0x7e,0x1f, +0x2c,0x15,0x2f,0x10,0x7a,0x1f,0x2c,0x15,0xb, 0xe0,0x22,0xa, 0x1b,0x6d,0x0, 0x7e, +0x1f,0x2c,0x15,0x12,0x15,0x77,0x7a,0x1f,0x2c,0x15,0x7e,0x25,0x2e,0x74,0xc, 0x7d, +0x13,0x7d,0x32,0x6d,0x22,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x15, +0x75,0x9f,0x11,0x7a,0x1f,0x2c,0x15,0x6c,0xee,0x22,0x7e,0x11,0x2b,0xac,0x1f,0x3e, +0x4, 0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20, +0x7a,0x27,0x2c,0x13,0x74,0x2, 0xac,0xbe,0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, +0x22,0xca,0x79,0x7f,0x10,0x9f,0x0, 0x12,0xbd,0x1f,0x4c,0xaa,0x78,0x6, 0x7e,0x34, +0x0, 0x40,0x80,0x6c,0x6c,0x99,0x80,0x38,0xa, 0xe9,0x2e,0xe4,0x60,0xac,0x7d,0x7e, +0x7a,0xf1,0x82,0x7a,0xe1,0x83,0xe4,0x93,0x7c,0x8b,0x90,0x60,0xaa,0xe4,0x93,0x70, +0xe, 0x7e,0xf3,0x31,0x8f,0xac,0xf8,0x7e,0xb3,0x31,0x91,0xa, 0xfb,0x2d,0xf7,0x7d, +0xef,0x3e,0xe4,0x7f,0x61,0x2d,0xde,0xb, 0x6a,0xd0,0x6d,0xcc,0x2f,0x6, 0xb, 0x90, +0xbc,0xa9,0x38,0xc4,0xbe,0x8, 0x0, 0x0, 0x78,0x2, 0xb, 0xc, 0xa, 0x5a,0x6d,0x44, +0x7f,0x10,0x7f,0x2, 0x12,0x15,0x77,0x7f,0x1, 0xb, 0xc, 0x7e,0x34,0xc4,0x0, 0x7e, +0x24,0x0, 0x9, 0x12,0x15,0x77,0xbe,0x34,0x0, 0xfa,0x28,0x4, 0x7e,0x34,0x0, 0xfa, +0xda,0x79,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c,0xcb,0x7e,0xb3,0x32,0x3e,0xf5,0x32, +0x7e,0xb3,0x32,0x30,0xf5,0x33,0x7e,0xd3,0x32,0x35,0x7e,0xe3,0x32,0x40,0x7e,0xf3, +0x32,0x41,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x34,0x0, 0x7e,0x8, 0x2c,0x13, +0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x37,0x99,0x7e, +0x8, 0x2c,0x4b,0x12,0x17,0x31,0x1b,0xfd,0x7c,0xbc,0x12,0xb0,0x4, 0x74,0x1, 0x7a, +0xb3,0x32,0x3e,0x74,0x5, 0xac,0xbc,0x12,0xbc,0x69,0x74,0x5, 0xac,0xbc,0x12,0xbc, +0x57,0x74,0x5, 0xac,0xbc,0x12,0xbc,0x60,0x74,0x5, 0xac,0xbc,0x9, 0x75,0x2d,0x58, +0xbe,0x73,0x32,0x83,0x68,0x6, 0x7a,0x73,0x32,0x83,0xd2,0xe, 0xc2,0x0, 0x12,0xbc, +0xd2,0x12,0x54,0xe, 0x12,0x6a,0xb1,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e, +0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x13,0x86,0x7d,0x25,0x7e,0x4, 0xd, 0xc8,0x12, +0x42,0x93,0x12,0x47,0xc1,0x7a,0x55,0x34,0x7e,0xd, 0x2e,0x7e,0x18,0xd, 0xc8,0x12, +0x6f,0x75,0x12,0x6f,0x26,0xe5,0x32,0x7a,0xb3,0x32,0x3e,0xe5,0x33,0x7a,0xb3,0x32, +0x30,0x7a,0xd3,0x32,0x35,0x7a,0xe3,0x32,0x40,0x7a,0xf3,0x32,0x41,0x7e,0x34,0x0, +0x38,0xca,0x39,0x7e,0x18,0x2c,0x13,0x7e,0x8, 0x34,0x0, 0x12,0x17,0x31,0x1b,0xfd, +0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x2c,0x4b,0x7e,0x8, 0x37,0x99,0x12,0x17, +0x31,0x1b,0xfd,0xda,0x3b,0x22,0x90,0x60,0x93,0xe4,0x93,0xa, 0xb, 0x7e,0x73,0x31, +0x92,0xa, 0x17,0x2d,0x10,0x7e,0xa3,0x31,0x8f,0xa, 0x3a,0xad,0x13,0x7d,0x21,0x6c, +0x33,0x80,0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f,0x33,0xfb,0x2d,0xf0,0xb, +0x7a,0x0, 0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x13,0x8e,0x9d,0xf, 0x59,0x4, 0x2c, +0xd7,0xb, 0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e,0xf, 0x3, 0xa2,0x7e,0x18, +0x2c,0xd7,0x2, 0x6f,0x75,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x7f, +0xc2,0x0, 0x6d,0x44,0x80,0x1e,0x7d,0xc4,0x3e,0xc4,0x7f,0x17,0x2d,0x3c,0x12,0xa5, +0x73,0xbd,0x3d,0x48,0xd, 0x7d,0x34,0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x12,0xa5,0x73, +0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4,0x38,0xdb,0x80,0x7, 0xb, 0xa0,0xbe, +0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0xa, +0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34,0x7a,0x1b,0xa0,0x6d,0x44,0x80, +0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x7f,0x60,0x2e,0xd5, +0x34,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0x7c,0xb7,0x12,0xbc,0x4f, +0xb, 0x44,0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda,0xf8,0x22,0x7d,0xf3,0x6d,0xee, +0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x4a,0x65,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f, +0x57,0x2d,0xbc,0xb, 0x5a,0x10,0x1a,0x2, 0x1a,0x0, 0x7e,0x83,0x32,0x41,0xa, 0x98, +0x6d,0x88,0x7f,0x10,0x7f,0x4, 0x12,0x15,0x5b,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e, +0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90, +0x7e,0x83,0x31,0x96,0xbc,0x89,0x38,0xbc,0x22,0x7f,0x20,0xb, 0x2a,0x10,0xb, 0x1a, +0x0, 0x1b,0x2a,0x0, 0x1b,0x1a,0x10,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e, +0x60,0xfd,0x68,0x21,0x1b,0x61,0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b,0x61,0x68,0x15, +0x1b,0x60,0x68,0x11,0x2e,0x60,0xa, 0x78,0x4, 0x7a,0x73,0x3b,0x6c,0xa, 0x2b,0x19, +0x72,0x3b,0x6d,0xd2,0xf, 0x22,0x7d,0xc3,0x7e,0x34,0x61,0x37,0x12,0x7f,0x9a,0x90, +0x61,0x35,0xe4,0x93,0x70,0x3, 0x7d,0x3c,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, +0x6, 0x7e,0x83,0x31,0x91,0x80,0x4, 0x7e,0x83,0x31,0x90,0x12,0x74,0x89,0xbe,0xc4, +0x0, 0x3f,0x38,0x1c,0x7e,0xe4,0x0, 0x3f,0x9d,0xec,0x7e,0x34,0x61,0x3b,0x12,0x71, +0x75,0x12,0x71,0x64,0xbf,0x71,0x40,0x2, 0x7f,0x71,0x9f,0x17,0x7f,0x71,0x21,0x61, +0x7d,0x54,0x9e,0x54,0x0, 0x3f,0xbd,0x5c,0x38,0x21,0x7d,0xec,0x9d,0xe5,0x7e,0x34, +0x61,0x3d,0x12,0x71,0x75,0x90,0x61,0x3a,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40,0x4, +0x7f,0x71,0x1b,0x7c,0x12,0x71,0x6c,0x2f,0x71,0x80,0x66,0x7d,0xb4,0xb, 0xb4,0x1e, +0xb4,0x7d,0x5b,0x1b,0x54,0xbd,0x5c,0x40,0xc, 0x7d,0xf5,0x9d,0xfc,0x6d,0xee,0x7e, +0x34,0x61,0x3f,0x80,0xa, 0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x34,0x61,0x41,0x12, +0xbd,0x7, 0x7f,0x17,0x12,0x15,0x6c,0x7f,0x71,0x12,0x72,0x69,0x7f,0x71,0xbd,0x5c, +0x7d,0x3d,0x40,0xc, 0x1e,0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x6, +0x1e,0x34,0x6d,0x22,0x2f,0x71,0x12,0x71,0x64,0x6d,0x22,0xbf,0x71,0x50,0x4, 0x7f, +0x71,0x80,0xe, 0x90,0x61,0x3a,0xe4,0x93,0x12,0x71,0x6c,0xbf,0x71,0x28,0x2, 0x7f, +0x71,0x7d,0x3f,0x22,0x90,0x61,0x39,0xe4,0x93,0xa, 0x3b,0x22,0xa, 0x2b,0x7d,0x3d, +0x9d,0x32,0x6d,0x22,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xad,0xfe,0x6d,0xee, +0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x7c,0x65,0x7f,0x71,0x22,0xca,0x3b,0x7e,0x73,0x3b, +0xb1,0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e,0x33,0x3b,0xb3,0xa, 0x13,0x6d,0x0, +0x7a,0xd, 0x2a,0x7e,0x33,0x3b,0xb2,0xa, 0x93,0x6d,0x88,0x7e,0x33,0x3b,0xb4,0xa, +0x73,0x6d,0x66,0x7e,0x14,0x61,0x37,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x40,0x7d,0x14, +0x12,0x15,0x6c,0x12,0x72,0x69,0x7a,0x1d,0x26,0x12,0xbc,0xb7,0xb, 0x1a,0x50,0x7e, +0x1d,0x2a,0x7d,0x15,0x12,0x15,0x6c,0x12,0x72,0x69,0x7a,0x1d,0x2a,0x7f,0x14,0x7d, +0x14,0x12,0x15,0x6c,0x12,0x72,0x69,0x7f,0x41,0x7f,0x13,0x7d,0x15,0x12,0x15,0x6c, +0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12,0x37,0xf3,0x50,0x60,0x7e,0xb3,0x16,0x91,0xb4, +0x1, 0x59,0x75,0x2e,0x0, 0x80,0x4b,0x7e,0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x2e, +0x97,0x12,0x70,0x86,0x7a,0x35,0x24,0x7e,0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x2e, +0x99,0x12,0x72,0x70,0x7d,0xa3,0x7e,0x35,0x24,0x6d,0x22,0x7e,0xd, 0x26,0xbf,0x10, +0x40,0x17,0x7d,0x5a,0x6d,0x44,0x7e,0xd, 0x2a,0xbf,0x20,0x40,0xc, 0xbf,0x14,0x38, +0x8, 0x7d,0x3a,0x6d,0x22,0xbf,0x13,0x28,0x7, 0xe5,0x2e,0x6c,0x77,0x12,0x74,0x94, +0x5, 0x2e,0x7e,0x73,0x2f,0xa5,0xbe,0x71,0x2e,0x38,0xac,0xda,0x3b,0x22,0x9d,0x32, +0x12,0x17,0x88,0x7d,0x13,0x7d,0x30,0xad,0x31,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x22, +0x7d,0xe3,0x9f,0x11,0x7e,0x14,0x61,0x43,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xf0,0x90, +0x61,0x35,0xe4,0x93,0x70,0x3, 0x7d,0x3e,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, +0x6, 0x7e,0x83,0x31,0x90,0x80,0x4, 0x7e,0x83,0x31,0x91,0x12,0x74,0x89,0xbe,0xe4, +0x0, 0x3f,0x38,0x1b,0x7e,0x24,0x0, 0x3f,0x9d,0x2e,0x7e,0x14,0x61,0x47,0x12,0x73, +0x97,0x90,0x61,0x45,0x12,0x73,0xac,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0x12, +0xbd,0x1f,0xbe,0xa0,0x0, 0x28,0x2f,0x7d,0x14,0x9e,0x14,0x0, 0x3f,0xbd,0x1e,0x38, +0x13,0x12,0x73,0xbe,0x40,0xe, 0x12,0x73,0x89,0x12,0x73,0xa9,0x48,0x2d,0x7f,0x10, +0x1b,0x1c,0x80,0x27,0x12,0x73,0xbe,0x50,0x2c,0x7d,0x34,0x9e,0x34,0x0, 0x20,0x12, +0x73,0x8f,0x7d,0x1f,0x80,0x1b,0x4c,0xaa,0x78,0x1b,0x12,0x73,0xb5,0x38,0x16,0x12, +0x73,0x89,0x12,0x73,0xa9,0x48,0x4, 0x7f,0x10,0x1b,0x1c,0xa, 0xb, 0x7d,0x1f,0x9d, +0x10,0x6d,0x0, 0x2f,0x10,0xbe,0xe4,0x0, 0x3f,0x28,0x6d,0x12,0x73,0xb5,0x28,0x68, +0x7d,0xd4,0xb, 0xd4,0x1e,0xd4,0x7d,0x5d,0x1b,0x54,0xbd,0x5e,0x40,0xc, 0x7d,0x35, +0x9d,0x3e,0x6d,0x22,0x7e,0x14,0x61,0x4b,0x80,0xa, 0x7d,0x3e,0x9d,0x3d,0x6d,0x22, +0x7e,0x14,0x61,0x4d,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10,0x12,0x15,0x6c,0x12,0x73, +0xa2,0xbd,0x5e,0x7d,0x1f,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d,0x0, 0x9f,0x1, 0x7f, +0x10,0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0x90,0x61,0x45,0x12,0x73,0xac,0x58, +0x4, 0x7f,0x10,0x80,0x13,0x90,0x61,0x46,0xe4,0x93,0xa, 0xb, 0x7d,0x1f,0x9d,0x10, +0x6d,0x0, 0xbf,0x10,0x8, 0x2, 0x7f,0x10,0x22,0x7d,0x34,0x9e,0x34,0x0, 0x40,0x7d, +0x2e,0x9d,0x23,0x7e,0x14,0x61,0x49,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0xad,0x32, +0x6d,0x22,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x90,0x61,0x46,0xe4,0x93,0xa, 0x1b, +0x6d,0x0, 0xbf,0x10,0x22,0x7d,0x54,0x9e,0x54,0x0, 0x3f,0xbd,0x5e,0x22,0x7d,0x4, +0x9e,0x4, 0x0, 0x1f,0x7e,0xd4,0x60,0xd1,0x7e,0xc4,0x0, 0xff,0xb, 0x6a,0x10,0x2d, +0x10,0xbd,0x1e,0x22,0xca,0x79,0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c,0xb4, +0x12,0xa2,0xc3,0x7d,0x3, 0x30,0x13,0x2a,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x2f,0xd6, +0xbe,0x73,0x39,0xf2,0x78,0xa, 0x9, 0x65,0x2f,0xd7,0xbe,0x63,0x39,0xf4,0x68,0x10, +0xbe,0x73,0x39,0xf3,0x78,0xc, 0x9, 0x75,0x2f,0xd7,0xbe,0x73,0x39,0xf5,0x78,0x2, +0x1e,0x4, 0x74,0x9, 0xac,0xbf,0x12,0x96,0xf5,0x12,0x72,0x5e,0x7d,0x13,0x5d,0x1e, +0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x30,0x83,0x74,0x9, 0xac,0xbe,0x49,0x25,0x2f, +0xcf,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x30,0x83,0x7d,0x2f,0x2d,0x21,0x1b, +0x58,0x20,0x80,0x9, 0x2e,0x34,0x30,0x83,0x9d,0xf1,0x1b,0x38,0xf0,0x74,0x9, 0xac, +0xbf,0x12,0x96,0xe8,0x12,0x72,0x5e,0x7d,0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f, +0x49,0x32,0x30,0x85,0x74,0x9, 0xac,0xbe,0x49,0x5, 0x2f,0xd1,0xbd,0x3, 0x28,0xd, +0x7d,0x2, 0x2e,0x4, 0x30,0x85,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x30, +0x85,0x9d,0x31,0x1b,0x28,0x30,0xda,0x79,0x22,0x7e,0x90,0x40,0xac,0x89,0x1b,0x44, +0x22,0x7e,0x70,0x1, 0x7c,0x67,0x7c,0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7, +0x54,0x7, 0xa, 0x2b,0x2e,0x24,0x0, 0x5e,0x12,0x77,0xf5,0x7c,0x7b,0x4c,0x66,0x68, +0xf, 0xa, 0x2a,0x2e,0x24,0x2e,0x93,0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22, +0x7c,0xb7,0x64,0xff,0xa, 0x2a,0x2e,0x24,0x2e,0x93,0x2, 0x74,0xcd,0x7e,0x29,0x70, +0x5c,0x7b,0x7a,0x29,0x70,0x22,0x7c,0xab,0x7e,0xb3,0x3c,0xd7,0x70,0xd, 0x7e,0xb3, +0x2f,0xc9,0x70,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x74,0x94,0x22,0xca,0xf8,0x6c,0xff, +0x80,0x17,0x7c,0xbf,0x12,0x75,0xcd,0xbe,0x37,0x31,0x7d,0x58,0xa, 0x7c,0xbf,0x12, +0x75,0x14,0xac,0x7f,0x12,0x77,0xfe,0xb, 0xf0,0x12,0x35,0xbe,0x38,0xe4,0x12,0x33, +0xe6,0xda,0xf8,0x22,0x6c,0x77,0x12,0x74,0x94,0x7e,0x70,0x2, 0x22,0xca,0xd8,0xca, +0x79,0x7e,0x34,0x62,0x2d,0x12,0x75,0xc5,0x12,0xa4,0x23,0x50,0x2, 0xa1,0xc0,0x7e, +0x34,0x62,0x31,0x12,0x20,0xc9,0x7a,0x35,0x2a,0x90,0x62,0x2c,0xe4,0x93,0x70,0x2, +0xa1,0xc0,0x7e,0xb3,0x2f,0xc9,0xb4,0x1, 0x7, 0x7e,0x34,0x62,0x2f,0x12,0x75,0xc5, +0x7e,0x37,0x2f,0xab,0xbe,0x34,0x2, 0xbc,0x8, 0x66,0x6c,0xdd,0x80,0x5a,0xc2,0x0, +0x7c,0xbd,0x12,0x75,0xcd,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xb2,0x9b, +0x7a,0x35,0x24,0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x35,0x26,0x3e,0x34,0x3e,0x34, +0x12,0x7e,0xad,0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e,0x35, +0x28,0xbe,0x35,0x24,0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35,0x26,0x8, 0x2, 0xd2,0x0, +0x7c,0xbd,0x12,0xb3,0x66,0x50,0x2, 0xc2,0x0, 0x30,0x0, 0xa, 0x7c,0xbd,0x12,0x75, +0x14,0xac,0x7d,0x12,0x77,0xfe,0xb, 0xd0,0x7e,0x73,0x2f,0xa5,0xbc,0x7d,0x38,0x9e, +0xda,0x79,0xda,0xd8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x70,0x22,0x7c,0xab,0x7e, +0x70,0x2, 0xac,0x7a,0x9, 0xb3,0x2e,0x1b,0x9, 0x73,0x2e,0x1c,0x2, 0x75,0xe3,0x7c, +0xba,0x7c,0x79,0x12,0x87,0x84,0xb, 0x1a,0x30,0x22,0xca,0x3b,0x6d,0xee,0x7e,0xc3, +0x31,0x8f,0x7e,0xb3,0x31,0x8e,0xf5,0x24,0x7e,0xb3,0x3b,0xbd,0xb4,0x1, 0x3, 0xe4, +0xe1,0x52,0x7e,0xb3,0x2f,0xa5,0x70,0x2, 0xc1,0x8c,0x7e,0xb3,0x31,0x24,0x60,0x2, +0x80,0x7a,0x7e,0xa3,0x2e,0x1b,0x7e,0xe3,0x2e,0x1c,0x6c,0xdd,0x6d,0xff,0x6c,0xff, +0xa, 0x4e,0x80,0x20,0x12,0x75,0xdf,0xbe,0x34,0x0, 0x96,0x8, 0x1d,0xb, 0xd0,0xbe, +0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x77,0x58,0x12,0x77,0xe6,0x58,0x3, 0x12, +0x77,0x55,0x1b,0x44,0xbe,0x44,0x0, 0x0, 0x58,0xda,0xa, 0x4e,0x80,0x1e,0x12,0x75, +0xdf,0xbe,0x34,0x0, 0x96,0x8, 0x21,0xb, 0xd0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba, +0x14,0x12,0x77,0x58,0x12,0x77,0xe6,0x58,0x3, 0x12,0x77,0x55,0x7d,0x24,0xb, 0x24, +0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xd6,0xbe,0xd0,0x3, 0x50,0x2, 0x80,0xd, 0xa, +0x2f,0x7d,0x3f,0x12,0x15,0x29,0xbe,0x34,0x0, 0x28,0x8, 0x8, 0x74,0x1, 0x7a,0xb3, +0x39,0xc3,0xe1,0x52,0x6c,0x77,0x80,0x28,0x7e,0x50,0x2, 0xac,0x57,0x9, 0xa2,0x2e, +0x1b,0x9, 0xe2,0x2e,0x1c,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x22,0x4, 0xfc,0xbe,0x24, +0x0, 0x64,0x58,0xa, 0x7e,0xb3,0x39,0xc3,0x24,0x14,0x7a,0xb3,0x39,0xc3,0xb, 0x70, +0x7e,0x63,0x2f,0xa5,0xbc,0x67,0x38,0xd0,0x6d,0xdd,0xbe,0xa0,0x0, 0x28,0x6, 0x7c, +0xba,0x14,0x12,0x77,0x62,0xe5,0x24,0xa, 0x3b,0x1b,0x34,0xa, 0xca,0xbd,0xc3,0x58, +0x6, 0x7c,0xba,0x4, 0x12,0x77,0x62,0x7e,0x70,0x8, 0x80,0x2a,0x7e,0x50,0x2, 0xac, +0x57,0x7d,0xc2,0x2e,0xc4,0x17,0x68,0x7d,0x1c,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4, +0x93,0x1a,0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x17,0x69,0x7d,0x2c,0x12, +0x77,0xf5,0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xce,0x7c,0xba, +0x7c,0x7e,0x12,0x75,0xe3,0x12,0x17,0x88,0xbe,0x34,0xa, 0xf0,0x8, 0x4, 0x2e,0xe4, +0x0, 0x28,0xbe,0xe4,0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x39,0xc3, +0xa, 0x3b,0xbd,0x3e,0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x39,0xc3,0x7e,0xb3, +0x39,0xc3,0xda,0x3b,0x22,0x7c,0xba,0x4, 0x7c,0x79,0x12,0x75,0xe3,0x2d,0xf3,0xb, +0xf0,0x22,0x7c,0x7e,0x12,0x75,0xe3,0x2d,0xd3,0x22,0xca,0x79,0x6c,0x88,0x80,0x6b, +0x12,0xa4,0x3, 0x9, 0x75,0x2e,0x1c,0x7a,0x71,0x24,0x7c,0xbf,0x12,0x7f,0xd4,0x50, +0x58,0x6c,0xee,0x80,0x4f,0xbc,0xe8,0x68,0x49,0x7e,0x70,0x2, 0xac,0x7e,0x12,0x7f, +0xba,0x6c,0x99,0x90,0x60,0xaa,0xe4,0x93,0x70,0x18,0x7e,0xb3,0x31,0x91,0x14,0xbe, +0xb1,0x26,0x78,0xe, 0xa, 0x2f,0xe5,0x25,0xa, 0x3b,0x12,0x83,0x2, 0x18,0x3, 0x7e, +0x90,0x1, 0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe,0x12,0x75,0xcd,0x7d,0xf3,0x7c,0xb8, +0x12,0x75,0xcd,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe,0x80,0x2, 0x7c,0xb8,0x6c,0x77,0x12, +0x74,0x94,0xb, 0xe0,0x12,0x4f,0xdb,0x38,0xac,0xb, 0x80,0x7e,0x73,0x2f,0xa5,0xbc, +0x78,0x38,0x8d,0xda,0x79,0x22,0xe5,0x24,0xa, 0x2b,0x1b,0x24,0xa, 0x3a,0xbd,0x32, +0x22,0x2e,0x24,0x16,0xeb,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0x9, 0xb3, +0x2e,0x1b,0x9, 0x73,0x2e,0x1c,0x7c,0x6b,0x7e,0xa3,0x3a,0x71,0x7e,0x50,0x2, 0xac, +0x5a,0x19,0x62,0x3a,0xae,0x19,0x72,0x3a,0xaf,0x7c,0xba,0x4, 0x7a,0xb3,0x3a,0x71, +0x22,0xca,0x3b,0x12,0x33,0xe6,0x7e,0xb3,0x2f,0xa5,0x60,0x6, 0x7e,0xb3,0x3a,0xea, +0x60,0x9, 0xe4,0x7a,0xb3,0x3a,0xec,0x7a,0xb3,0x3a,0x71,0x7e,0xb3,0x3a,0xea,0x70, +0x6b,0x6c,0x99,0x80,0x5f,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x2e,0x1b,0x9, 0xf5,0x2e, +0x1c,0x7c,0xb9,0x12,0xb3,0x66,0x40,0x4a,0x6c,0xee,0x80,0x3e,0x74,0x2, 0xac,0xbe, +0x9, 0xd5,0x3a,0x72,0x9, 0xc5,0x3a,0x73,0xa, 0x28,0xa, 0x3d,0x12,0x78,0xcf,0x78, +0x27,0xa, 0x2f,0xa, 0x3c,0x12,0x78,0xcf,0x78,0x1e,0x7c,0xb9,0x12,0x75,0xcd,0x7e, +0x14,0x62,0x31,0x12,0x5f,0xc8,0xbd,0x32,0x58,0xe, 0x7c,0xb9,0x6c,0x77,0x12,0x74, +0x94,0x7c,0xb8,0x7c,0x7f,0x12,0x78,0x6, 0xb, 0xe0,0x7e,0x73,0x3a,0xec,0xbc,0x7e, +0x38,0xba,0xb, 0x90,0x7e,0x73,0x2f,0xa5,0xbc,0x79,0x38,0x99,0x7e,0x73,0x3a,0x71, +0x7a,0x73,0x3a,0xec,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x3a,0xae,0x7e,0x8, +0x3a,0x72,0x12,0x17,0x31,0x1b,0xfd,0xe4,0x7a,0xb3,0x3a,0xea,0xda,0x3b,0x22,0x9d, +0x32,0x12,0x17,0x88,0x4d,0x33,0x22,0x12,0xa4,0xc, 0x12,0x78,0xe6,0x12,0x79,0xc3, +0x12,0x75,0x1d,0x2, 0x78,0x21,0xca,0x3b,0x7e,0x77,0x31,0x7d,0x12,0x79,0x93,0x7d, +0x63,0x3e,0x34,0x3e,0x34,0x7e,0xe4,0x0, 0xa, 0x12,0x79,0x8b,0x7e,0xb3,0x2f,0xc9, +0x60,0xf, 0x7e,0x37,0x3a,0xed,0xbd,0x36,0x48,0x7, 0x3e,0x34,0x3e,0x34,0x12,0x79, +0x8b,0xbe,0x64,0x2, 0xbc,0x8, 0xb, 0x12,0xa4,0x23,0x50,0x1d,0x7e,0xb3,0x2f,0xc9, +0x70,0x17,0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xe0,0x6e,0xe4,0xff, +0xff,0xb, 0xe4,0xbe,0xe7,0x2f,0xaf,0x8, 0x4, 0x74,0xa, 0x80,0x13,0x7e,0xb3,0x2f, +0xc9,0x60,0xc, 0x7e,0xb3,0x3a,0xeb,0xbe,0xb0,0x0, 0x28,0x8, 0x14,0x80,0x1, 0xe4, +0x7a,0xb3,0x3a,0xeb,0x7e,0xe7,0x31,0x7d,0x7d,0x3e,0x12,0x47,0x14,0x7e,0x53,0x3a, +0xeb,0xbe,0x50,0x0, 0x28,0x12,0xbd,0x3f,0x58,0x4, 0x7d,0xf3,0x80,0x6, 0xbd,0xef, +0x8, 0x2, 0x7d,0xfe,0x7a,0xf7,0x31,0x7d,0x12,0x7f,0xa2,0x28,0x3, 0x12,0x74,0xec, +0x7a,0x67,0x3a,0xed,0x7a,0x77,0x31,0x7d,0xda,0x3b,0x22,0x7d,0x2e,0x12,0x15,0x29, +0x7d,0xf3,0x22,0xca,0x3b,0x6d,0x44,0x7e,0xf3,0x2f,0xa5,0x6c,0xee,0x80,0x1b,0x7c, +0xbe,0x12,0x4e,0xdc,0x60,0x12,0x12,0x7f,0xc7,0x7c,0xbd,0x7c,0x7c,0x12,0x75,0xe3, +0x7d,0xf3,0xbd,0x4f,0x58,0x2, 0x7d,0x4f,0xb, 0xe0,0xbc,0xfe,0x38,0xe1,0x7d,0x34, +0xda,0x3b,0x22,0xca,0x3b,0x7e,0xb3,0x31,0x95,0xf5,0x27,0x12,0x7a,0x6e,0x50,0x2, +0x41,0x63,0x6d,0x33,0x9e,0x37,0x31,0x70,0x3e,0x34,0xbe,0x37,0x7, 0xf8,0x8, 0x2, +0x41,0x63,0x7e,0xb3,0x16,0x92,0x70,0x7b,0x7e,0xb3,0x2f,0xc9,0xb4,0x1, 0x65,0x7e, +0x77,0x31,0x72,0x7e,0x67,0x31,0x74,0x75,0x24,0x0, 0x80,0x53,0xe5,0x24,0x12,0x4e, +0xdc,0x60,0x4a,0x12,0x7a,0x66,0x12,0x7f,0xba,0x7e,0xb3,0x31,0x24,0xb4,0x1, 0xe, +0x90,0x60,0xab,0xe4,0x93,0xbe,0xb1,0x26,0x78,0x4, 0xe, 0x64,0xe, 0x74,0x7e,0xa1, +0x26,0x74,0x2, 0xa4,0x49,0x35,0x4, 0xfc,0xbd,0x36,0x48,0x14,0xe5,0x25,0xa, 0x2b, +0xe5,0x27,0xa, 0x3b,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xfc,0xbd,0x37,0x58,0xd, +0xe5,0x24,0x6c,0x77,0x12,0x74,0x94,0x12,0x7a,0x66,0x12,0x77,0xfe,0x5, 0x24,0x12, +0x4f,0xea,0x38,0xa8,0x7e,0xb3,0x31,0x89,0x70,0x9, 0x7e,0xb3,0x31,0x8c,0x70,0x3, +0x12,0x7e,0x64,0xda,0x3b,0x22,0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b,0x22,0xa2,0x16, +0x22,0x7e,0x90,0x1, 0x7e,0xb3,0x0, 0x69,0xbe,0xb0,0xff,0x50,0x5, 0x4, 0x7a,0xb3, +0x0, 0x69,0x7e,0x34,0x61,0xc6,0x12,0x20,0xc9,0x12,0x7f,0x91,0x12,0x20,0xc9,0x7a, +0x37,0x2f,0xc4,0x12,0x7e,0x3e,0xb, 0x1a,0xf0,0x7e,0x34,0x61,0x4f,0x12,0x7f,0x9a, +0xe4,0x7a,0xb3,0x2f,0xcd,0x12,0x7c,0x35,0x7e,0x34,0xff,0xfa,0xad,0x3f,0x12,0x7e, +0xad,0x7d,0xc3,0xe, 0xc4,0x7e,0xe7,0x7, 0xfe,0xbd,0xe3,0x58,0x15,0x7e,0xe7,0x7, +0xfc,0xbd,0xec,0x58,0xd, 0x12,0x7c,0x3c,0x8, 0x8, 0x12,0x7c,0xd1,0x60,0x3, 0x12, +0x7c,0x55,0x12,0x7c,0xd1,0xa, 0xeb,0x4d,0xee,0x68,0x3b,0x6d,0xee,0x9d,0xef,0xbe, +0xe7,0x7, 0xfe,0x18,0x6, 0xbe,0xe7,0x7, 0xfc,0x8, 0x2b,0x12,0x7c,0x3c,0x8, 0x26, +0x7e,0x37,0x2f,0xaf,0x12,0x17,0x88,0xbe,0x37,0x2f,0xab,0x8, 0x19,0x12,0x7c,0x2d, +0x28,0x14,0x7e,0x83,0x2f,0xa6,0xbe,0x80,0x1, 0x28,0xb, 0x7e,0xc7,0x7, 0xfa,0xbd, +0xcf,0x58,0x3, 0x12,0x7c,0x55,0x12,0xa7,0xd8,0x40,0x5, 0xe4,0x7a,0xb3,0x2f,0xc9, +0x12,0x7f,0xb2,0x68,0x6, 0x7e,0xb3,0x3c,0xd7,0x60,0x7, 0xe4,0x7a,0xb3,0x2f,0xce, +0x80,0x77,0x12,0x7c,0x2d,0x28,0x5, 0xe4,0x7a,0xb3,0x2f,0xce,0x30,0x12,0x5, 0xe4, +0x7a,0xb3,0x2f,0xce,0x12,0xa8,0x16,0x50,0xa, 0x12,0x7c,0x35,0x12,0x7c,0x69,0x7c, +0x9b,0x80,0x17,0x7e,0xb3,0x2d,0xa5,0x70,0x11,0x7e,0xb3,0x2d,0xa6,0x70,0xb, 0x12, +0x7c,0x2d,0x28,0x6, 0x7e,0x90,0x3, 0x12,0x7c,0x35,0x7e,0xc7,0x7, 0xfa,0xbe,0xc4, +0x5, 0xdc,0x8, 0x17,0x12,0x7c,0x2d,0x28,0x12,0x6d,0xcc,0x9d,0xcd,0xbe,0xc7,0x2f, +0xaf,0x58,0x8, 0x12,0x7c,0x47,0xe4,0x7a,0xb3,0x2f,0xce,0xa, 0x29,0x7e,0x14,0x61, +0xc6,0x12,0x56,0x6f,0xad,0x32,0x7a,0x37,0x2f,0xc2,0xa, 0x29,0x7e,0x14,0x61,0xc8, +0x12,0x56,0x6f,0xad,0x32,0x7a,0x37,0x2f,0xc4,0x12,0x7a,0x6e,0x50,0xd, 0xe4,0x7a, +0xb3,0x2f,0xce,0x12,0x7f,0xaa,0x28,0x3, 0x12,0x7c,0x47,0x7e,0xc7,0x2f,0xab,0xbd, +0xcd,0x8, 0x1f,0x7e,0x24,0x0, 0x2, 0x7d,0x3d,0x12,0x15,0x29,0x6e,0x34,0xff,0xff, +0xb, 0x34,0xbe,0x37,0x2f,0xaf,0x58,0xa, 0x12,0x7a,0x6e,0x50,0x5, 0xe4,0x7a,0xb3, +0x2f,0xce,0x12,0x7d,0x51,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x2f,0xce,0x7e,0xb3,0x2f, +0xcd,0xb4,0x1, 0x9, 0xe4,0x7a,0xb3,0x2f,0xa5,0x7a,0xb3,0x31,0x23,0x12,0x7e,0xbc, +0x7e,0xb3,0x0, 0x6a,0xbe,0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x0, 0x6a,0x70,0x1c, +0xe4,0x7a,0xb3,0x2f,0xce,0x74,0x1, 0x7a,0xb3,0x2f,0xcd,0xe4,0x7a,0xb3,0x16,0x91, +0x7a,0xb3,0x16,0x90,0x7a,0xb3,0x2f,0xa5,0x7a,0xb3,0x2d,0xa4,0x22,0x7e,0x83,0x2f, +0xa5,0xbe,0x80,0x0, 0x22,0x74,0x1, 0x7a,0xb3,0x2f,0xce,0x22,0x6d,0xee,0x9e,0xe7, +0x31,0x7b,0xbe,0xe7,0x2f,0xaf,0x22,0xe4,0x7a,0xb3,0x0, 0x6a,0x7a,0xb3,0x2f,0xcd, +0x74,0x2, 0x2, 0x33,0x6e,0x74,0x2, 0x7a,0xb3,0x0, 0x6a,0xe4,0x7a,0xb3,0x0, 0x69, +0x74,0x1, 0x7a,0xb3,0x2f,0xcd,0x2, 0x33,0x6d,0x7e,0xa0,0x1, 0x7e,0x47,0x7, 0xf8, +0x12,0x7e,0x3e,0xb, 0x1a,0x0, 0x7e,0x34,0xff,0xfa,0xad,0x30,0x7e,0x14,0x0, 0x2, +0x12,0x7c,0xc9,0x8, 0x12,0x7e,0xb3,0x2f,0xcd,0x60,0x7, 0xe4,0x7a,0xb3,0x2f,0xce, +0x80,0x32,0x7e,0xa0,0x5, 0x80,0x2d,0x7e,0x34,0xff,0xfb,0x12,0x7c,0xc7,0x8, 0x5, +0x7e,0xa0,0x4, 0x80,0x1f,0x7e,0x34,0xff,0xfc,0x12,0x7c,0xc7,0x8, 0x5, 0x7e,0xa0, +0x3, 0x80,0x11,0x7e,0x34,0xff,0xfd,0x12,0x7c,0xc7,0x8, 0x5, 0x7e,0xa0,0x2, 0x80, +0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0xad,0x30,0x7d,0x21,0x12,0x15,0x29,0xbd,0x34, +0x22,0x6c,0x66,0x90,0x60,0xa7,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x71,0x90,0x60,0xaa, +0xe4,0x93,0x70,0x6a,0x7e,0xb3,0x2f,0xc9,0xb4,0x1, 0x63,0x7e,0x73,0x2e,0x13,0xbe, +0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80,0x4e,0xa, 0x23,0x9, 0x72,0x2e,0x7, 0x7e,0xb3, +0x31,0x8f,0x14,0xbc,0x7b,0x78,0x3d,0x6c,0x22,0x80,0x27,0x7c,0xb2,0x7c,0x73,0x12, +0x7f,0xd4,0x50,0x1c,0xa, 0x22,0x7e,0x73,0x31,0x8f,0xa, 0x7, 0x2d,0x2, 0x3e,0x4, +0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e,0x7, 0x31,0x70,0xbd,0x20,0x58,0x2, 0xb, 0x60, +0xb, 0x20,0x7e,0x73,0x31,0x8e,0xbc,0x72,0x38,0xd1,0xbe,0x60,0x0, 0x28,0x3, 0x74, +0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e,0x73,0x2e,0x13,0xbc,0x73,0x38,0xaa,0x74,0x1, +0x22,0xca,0x3b,0x12,0x7e,0xb4,0x38,0x2, 0xc1,0x14,0x7e,0xc3,0x0, 0x6d,0x4c,0xcc, +0x78,0x3d,0x7a,0xb3,0x0, 0x6d,0xe4,0x7a,0xb3,0x0, 0x6f,0x6c,0xaa,0x80,0x26,0x12, +0x7e,0x1f,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3,0x2e,0x1b,0x9, 0xe3,0x2e,0x1c,0x7a, +0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12,0x7e,0x29,0x59, +0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x2f,0xa5,0xbc,0xba,0x38,0xd2,0x80,0x7b,0x7c, +0xfc,0x6c,0xaa,0x80,0x31,0x12,0x7e,0x1f,0x7e,0x49,0xd0,0x9, 0xe4,0x0, 0x1, 0x9, +0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1b,0x12,0x7e,0x29,0x7d,0x23,0x49,0x34, +0x0, 0x2, 0x12,0x4f,0xe2,0xbe,0xf4,0x0, 0x23,0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, +0x8, 0x75,0x65,0x1, 0xb, 0xa0,0xbc,0xfa,0x38,0xcb,0x4c,0xff,0x78,0x2, 0x80,0x26, +0x7e,0x73,0x0, 0x6f,0xbe,0x70,0x4, 0x40,0x22,0x6c,0xaa,0x80,0xe, 0x12,0x7e,0x1f, +0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, 0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc, +0xfa,0x78,0x3, 0x75,0x65,0x0, 0x12,0x7e,0x30,0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3, +0x0, 0x6f,0x80,0x6, 0x12,0x7e,0x30,0x75,0x65,0x0, 0xe5,0x65,0xda,0x3b,0x22,0x7e, +0x90,0x9, 0xac,0x9a,0x2e,0x44,0x0, 0x70,0x22,0x7c,0xbd,0x7c,0x7e,0x2, 0x75,0xe3, +0xe4,0x7a,0xb3,0x0, 0x6e,0x7a,0xb3,0x0, 0x6d,0x7a,0xb3,0x0, 0x6f,0x22,0x7e,0x34, +0x61,0x55,0x7e,0x24,0x0, 0xff,0x22,0x12,0xab,0xc4,0x60,0x17,0x12,0x7c,0x35,0x7e, +0x37,0x2f,0xc2,0x3e,0x34,0x7a,0x37,0x2f,0xc2,0x7e,0x37,0x2f,0xc4,0x3e,0x34,0x7a, +0x37,0x2f,0xc4,0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x31,0x70,0x12,0x7e,0xb4,0x28,0x35, +0x6d,0x22,0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x7e,0xad,0xbe,0x37,0x7, +0xfa,0x8, 0x22,0xe4,0x7a,0xb3,0x2f,0xa5,0x7e,0xb3,0x31,0x24,0x70,0x17,0x7e,0xb3, +0x3b,0x94,0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x64,0xe5,0x64,0xbe,0xb0,0x10,0x28,0x5, +0xd2,0x14,0x75,0x64,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x64,0x0, 0x22,0x7e,0x24,0x0, +0x2, 0x2, 0x15,0x29,0x7e,0xb3,0x2f,0xa5,0xbe,0xb0,0x0, 0x22,0x6c,0x66,0x7e,0x27, +0x3c,0xd0,0xbe,0x24,0x3, 0xe8,0x28,0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x2f,0xcd,0xb4, +0x1, 0x1a,0x7e,0x73,0x0, 0x6b,0xbc,0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x2f,0xce,0x12, +0x7c,0x47,0x7e,0xb3,0x0, 0x6b,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x0, +0x6b,0x7e,0xb3,0x2f,0xce,0xb4,0x1, 0x17,0x7e,0xa3,0x0, 0x6c,0xbe,0xa0,0x5, 0x50, +0xa, 0xe4,0x7a,0xb3,0x2f,0xce,0x7c,0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4, +0x7a,0xb3,0x0, 0x6c,0x22,0xc2,0x0, 0x12,0x37,0xf3,0x50,0x4b,0x6c,0xaa,0x80,0x39, +0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x2e,0x1b,0x9, 0x62,0x2e,0x1c,0xbe,0x70,0x0, +0x28,0x25,0x7e,0xb3,0x31,0x90,0xa, 0x1b,0x1b,0x14,0xa, 0x27,0xbd,0x21,0x58,0x17, +0xbe,0x60,0x0, 0x28,0x12,0x7e,0xb3,0x31,0x91,0x1e,0xb0,0xa, 0x1b,0xa, 0x26,0xbd, +0x21,0x58,0x4, 0xd2,0x0, 0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x2f,0xa5,0xbc,0xba,0x38, +0xbf,0x20,0x0, 0x3, 0x12,0x7c,0x35,0x30,0x19,0x23,0x5, 0x66,0xe5,0x66,0xbe,0xb0, +0x50,0x50,0x16,0x7e,0x34,0x61,0xc6,0x12,0x20,0xc9,0x3e,0x34,0x12,0x7f,0x91,0x12, +0x20,0xc9,0x3e,0x34,0x7a,0x37,0x2f,0xc4,0x22,0xc2,0x19,0x80,0x0, 0x75,0x66,0x0, +0x22,0x7a,0x37,0x2f,0xc2,0x7e,0x34,0x61,0xc8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a, +0xd0,0x22,0x7e,0x73,0x2f,0xa5,0xbe,0x70,0x1, 0x22,0x7e,0x73,0x2f,0xa5,0xbe,0x70, +0x0, 0x22,0x7e,0xb3,0x2f,0xc9,0xbe,0xb0,0x1, 0x22,0x9, 0xb3,0x2e,0x1b,0xf5,0x25, +0x9, 0xb3,0x2e,0x1c,0xf5,0x26,0x22,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x2e,0x1b,0x9, +0xc5,0x2e,0x1c,0x22,0x7c,0xab,0x90,0x60,0xab,0xe4,0x93,0xbc,0xb7,0x78,0x9, 0x7c, +0xba,0x12,0x4a,0xb0,0x50,0x2, 0xd3,0x22,0xc3,0x22,0x2, 0x7f,0xed,0xca,0x79,0x6c, +0xff,0x7e,0xd7,0x31,0x7b,0x6c,0xee,0x80,0x35,0x7c,0xbe,0x12,0x75,0xcd,0xbd,0x3d, +0x48,0x2a,0x7c,0xbe,0x12,0x4e,0xdc,0x60,0x23,0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e, +0x70,0x9, 0xac,0x7e,0x2e,0x34,0x2e,0x97,0x6d,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e, +0x14,0x2f,0xcf,0x6d,0x0, 0x12,0x17,0x31,0x1b,0xfd,0xb, 0xf0,0xb, 0xe0,0x12,0x4f, +0xdb,0x38,0xc6,0x7a,0x73,0x2f,0xb4,0x7a,0xf3,0x31,0x23,0xda,0x79,0x22,0x7d,0x13, +0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x12,0x15,0x75, +0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28,0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca,0xf8,0x7e, +0xf3,0x31,0x91,0x7a,0x37,0x26,0x5b,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x26,0x5d,0xe4, +0x7a,0xb3,0x26,0x55,0x7a,0xb3,0x26,0x56,0x7e,0x73,0x31,0x90,0x7a,0x73,0x26,0x57, +0x7a,0xf3,0x26,0x58,0x7a,0xb3,0x26,0x59,0x7a,0xb3,0x26,0x5a,0x7e,0x8, 0x26,0x55, +0x12,0x80,0xb2,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa0,0x2f,0x10,0x7e, +0x33,0x26,0x57,0x6d,0x0, 0x12,0x15,0x77,0xa, 0x1f,0x6d,0x0, 0x12,0x15,0x77,0xda, +0xf8,0x22,0x12,0xc, 0x29,0x7e,0x37,0x15,0x9e,0x22,0xca,0x3b,0x7a,0x41,0x2c,0x12, +0x84,0x8e,0x74,0x9, 0xac,0xbf,0x7d,0x95,0x2e,0x94,0x2e,0x97,0x6d,0x88,0x7e,0xe7, +0x31,0x87,0xe4,0x39,0xb4,0x0, 0x6, 0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x2e,0x1b, +0xf5,0x37,0x9, 0xb3,0x2e,0x1c,0xf5,0x38,0x7e,0x73,0x31,0x8f,0x7c,0x6d,0x7e,0x8, +0x0, 0x3b,0x12,0x83,0x1b,0xf5,0x39,0xe5,0x37,0x7e,0x73,0x31,0x8e,0x7c,0x6c,0x7e, +0x8, 0x0, 0x3a,0x12,0x83,0x1b,0x7c,0xab,0xe5,0x3a,0x7e,0x71,0x3b,0x12,0x87,0x84, +0x7d,0xf3,0x7a,0xf5,0x43,0x7e,0xf4,0x15,0x9e,0x7a,0xf5,0x45,0x85,0x3a,0x3d,0x85, +0x3b,0x3e,0x7a,0xa1,0x3f,0x85,0x39,0x40,0x7e,0xb3,0x31,0x7a,0xf5,0x41,0x75,0x42, +0x0, 0xe5,0x2c,0xb4,0x1, 0x8, 0xe5,0x41,0x1e,0xb0,0x1e,0xb0,0xf5,0x41,0x7e,0x8, +0x0, 0x3d,0x12,0x80,0xb2,0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f, +0x51,0x7e,0x37,0x15,0xa2,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f, +0x10,0x7a,0x1d,0x2d,0x7e,0x37,0x15,0xa6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8, +0x2f,0x10,0x7a,0x1d,0x31,0x7f,0x65,0xa, 0x4c,0xe5,0x37,0xa, 0x5b,0x9d,0x54,0xf5, +0x35,0x41,0x69,0xa, 0x4d,0xe5,0x38,0xa, 0x5b,0x9d,0x54,0xf5,0x36,0x41,0x53,0xe5, +0x35,0xbe,0xb0,0x0, 0x58,0x2, 0x41,0x51,0x7e,0x73,0x31,0x8e,0xbe,0x71,0x35,0x18, +0x2, 0x41,0x51,0xe5,0x36,0xbe,0xb0,0x0, 0x58,0x2, 0x41,0x51,0x7e,0x73,0x31,0x8f, +0xbe,0x71,0x36,0x18,0x2, 0x41,0x51,0xe5,0x35,0x7e,0x71,0x36,0x12,0x75,0xe3,0x7e, +0x53,0x31,0x7a,0xa, 0x25,0x7d,0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x18,0x2, 0x41, +0x51,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e,0x34,0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a, +0x1b,0xb0,0xe5,0x37,0xa, 0x2b,0xe5,0x35,0x12,0x83,0x0, 0x18,0xb, 0xe5,0x38,0xa, +0x2b,0xe5,0x36,0x12,0x83,0x0, 0x8, 0x59,0xe5,0x35,0x7e,0x71,0x36,0x7c,0x6e,0x12, +0x87,0x9a,0xf5,0x3c,0xb4,0x2, 0x6, 0x7d,0x3f,0xe, 0x34,0x9d,0xf3,0xe5,0x3c,0xbe, +0xb0,0x2, 0x68,0x5, 0xe5,0x3c,0xb4,0x1, 0x38,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0xe5, +0x35,0x12,0x82,0xf9,0x7f,0x1, 0x7e,0x1d,0x2d,0x9f,0x10,0x7a,0x1d,0x2d,0x7d,0x3f, +0x1a,0x26,0x1a,0x24,0xe5,0x36,0x12,0x82,0xf9,0x7f,0x1, 0x7e,0x1d,0x31,0x9f,0x10, +0x7a,0x1d,0x31,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f, +0x61,0x5, 0x36,0xa, 0x2d,0xe5,0x38,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x36,0x1a, +0x3b,0xbd,0x32,0x18,0x2, 0x21,0x8f,0x5, 0x35,0xa, 0x2c,0xe5,0x37,0xa, 0x3b,0x2d, +0x32,0x1a,0x37,0xe5,0x35,0x1a,0xfb,0xbd,0xf3,0x18,0x2, 0x21,0x83,0xbe,0x58,0x0, +0x0, 0x78,0x2, 0xb, 0x5c,0xbe,0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2d, +0x7f,0x5, 0x12,0x83,0xc, 0x1b,0x4a,0x30,0x7e,0x1d,0x31,0x7f,0x6, 0x12,0x83,0xc, +0x79,0x34,0x0, 0x2, 0x7e,0xb3,0x31,0x86,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, +0x4e,0xd4,0x80,0x0, 0x14,0x78,0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, +0x7f,0x7d,0x3d,0x39,0x74,0x0, 0x5, 0x74,0x9, 0xac,0xbe,0x9, 0x75,0x2e,0x9d,0x39, +0x74,0x0, 0x6, 0xbe,0x70,0xf, 0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0x7e,0xa1, +0x37,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x2e,0x9e,0x7e,0xa1,0x38,0x7e,0x70,0x9, +0xac,0x7f,0x19,0xa3,0x2e,0x9f,0xda,0x3b,0x22,0x1a,0x1b,0x1a,0x2, 0x2, 0x15,0x5b, +0x1a,0x3b,0x9d,0x32,0x12,0x17,0x88,0xbe,0x34,0x0, 0x1, 0x22,0x74,0x6, 0x2f,0x11, +0x14,0x78,0xfb,0x12,0x15,0x77,0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c, +0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38, +0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c, +0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, +0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53, +0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22,0x7e,0xa3, +0x2f,0xa5,0xe4,0x7a,0xb3,0x39,0x28,0x6c,0x33,0x80,0x3d,0x7e,0x70,0x2, 0xac,0x73, +0x9, 0x23,0x2e,0x1c,0x7e,0x10,0x1, 0x6c,0x0, 0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e, +0x70,0x2, 0xac,0x70,0x9, 0x93,0x2e,0x1c,0xa, 0x29,0xa, 0x32,0x12,0x83,0x2, 0x18, +0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74,0x2, 0x7a,0xb3,0x39,0x28,0x80,0x6, +0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc,0xa3,0x38,0xbf,0x2, 0x83,0xbf,0xca, +0xf8,0x7e,0x33,0x2f,0xa5,0x6c,0x22,0x80,0x45,0x74,0x2, 0xac,0xb2,0x9, 0x15,0x2e, +0x1b,0x9, 0x5, 0x2e,0x1c,0x7e,0xa0,0x1, 0x6c,0x99,0x80,0x2c,0xbc,0x92,0x68,0x26, +0x7e,0x70,0x2, 0xac,0x79,0x9, 0x83,0x2e,0x1b,0x9, 0xf3,0x2e,0x1c,0xa, 0x28,0xa, +0x31,0x12,0x83,0x2, 0x18,0xb, 0xa, 0x2f,0xa, 0x30,0x12,0x83,0x2, 0x8, 0x2, 0xb, +0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc,0x39,0x38,0xd0,0xb, 0x20,0xbc,0x32, +0x38,0xb7,0x7e,0xb3,0x39,0xc2,0xbe,0xb0,0x0, 0x28,0x12,0x14,0x7a,0xb3,0x39,0xc2, +0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c,0x7a,0x37,0x31,0x7b,0x7e,0xb3,0x3b, +0x78,0x70,0x58,0x7e,0xb3,0x3c,0xd7,0x70,0x52,0x7e,0xb3,0x3a,0xfc,0x70,0x4c,0x7e, +0x37,0x3c,0x2c,0xbe,0x34,0x0, 0x14,0x50,0x42,0x7e,0x37,0x2f,0xab,0xbe,0x34,0x3, +0x20,0x58,0x38,0x7e,0xb3,0x2f,0xa5,0xbe,0xb0,0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40, +0x2a,0x7e,0xb3,0x2d,0xa6,0xbe,0xb0,0x3, 0x50,0x9, 0x7e,0xb3,0x2d,0xa5,0xbe,0xb0, +0x3, 0x40,0x18,0x7e,0xb3,0x2e,0x17,0xbe,0xb0,0x8, 0x50,0x9, 0x7e,0xb3,0x2e,0x18, +0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3,0x39,0xc2,0xda,0xf8,0x22,0x7c,0xf5, +0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x22,0xca,0x3b,0x12,0x84,0x8e,0x75,0x54,0x0, 0x7e, +0xa1,0x54,0x74,0x6, 0xa4,0x12,0x87,0x68,0x30,0xe1,0x31,0x7f,0x7, 0x7c,0xbc,0x7e, +0x70,0x1, 0x12,0x84,0xec,0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x84,0xe9,0x50,0x1c, +0x7f,0x7, 0x7c,0xbd,0x6c,0x77,0x12,0x84,0xec,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c, +0x77,0x12,0x84,0xec,0x50,0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x54,0xe5,0x54, +0xbe,0xb0,0x1e,0x40,0xba,0xe4,0xda,0x3b,0x22,0x7e,0x70,0x1, 0x7c,0x87,0x7c,0x9b, +0x29,0xa0,0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, 0x78,0x7, +0x29,0xa0,0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, 0x16,0xbd, +0x1, 0x48,0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3,0x22,0xc3, +0x22,0xca,0x79,0x7f,0x70,0x7e,0xb4,0xff,0xff,0x6c,0xee,0xc2,0x1, 0xc2,0x2, 0x29, +0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc,0x76,0x78,0xe, 0x29,0x67,0x0, 0x3, 0x29,0x77, +0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2,0x2, 0x6c,0xff,0x12,0x87,0x1, 0x6d,0xcc,0x6d, +0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xa1,0xe3,0x7f,0x6, 0x7e,0x7b,0xb0,0x7e, +0x70,0x1, 0x12,0x84,0xec,0x50,0x30,0x7f,0x6, 0x29,0xb7,0x0, 0x2, 0x7e,0x70,0x1, +0x12,0x84,0xec,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0x84,0xec, +0x50,0x15,0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x84,0xec,0x50,0x8, 0x7c, +0xef,0xd2,0x1, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70,0x12, +0x37,0xc9,0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12,0x37, +0xc9,0x2d,0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x37,0xc9, +0x2d,0xa3,0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x37,0xc9,0x2d, +0xa3,0xbd,0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, 0xd2, +0x1, 0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0xa1,0x4a,0x20,0x1, 0xb, 0x20, +0x2, 0x8, 0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, 0x2, 0xc1,0xa6,0x74, +0x6, 0xac,0xbe,0x12,0x87,0x5, 0x6d,0xcc,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23, +0x54,0x1f,0xbe,0xb0,0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e, +0x60,0x8, 0x5e,0x60,0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x2, 0x11, +0x29,0xb6,0x0, 0x4, 0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b, +0xb0,0x29,0x67,0x0, 0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, +0x3, 0x80,0x4, 0x29,0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29, +0x76,0x0, 0x2, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, +0x2, 0x39,0x76,0x0, 0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50, +0x6, 0x29,0x76,0x0, 0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e, +0x7b,0x60,0x7e,0x6b,0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b, +0x70,0x7a,0x6b,0x70,0x80,0x33,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x2, 0xf3, +0x30,0xe1,0x7, 0xb, 0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x35,0x74, +0x1, 0x39,0xb7,0x0, 0x4, 0x12,0x87,0x1, 0x6d,0xcc,0x7e,0x34,0x0, 0x6, 0xca,0x39, +0x7f,0x17,0x7f,0x6, 0x12,0x17,0x31,0x1b,0xfd,0x12,0x86,0xf7,0x44,0x1, 0x7a,0x1b, +0xb0,0x12,0x86,0xf7,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x2, 0x8, 0x12,0x86,0xf7,0x44, +0x4, 0x7a,0x1b,0xb0,0xda,0x79,0x22,0x7f,0x16,0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0, +0x22,0x74,0x6, 0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x2, 0xee,0x22,0xca,0x3b,0x7e,0xe3, +0x2f,0xa5,0x6c,0xdd,0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0x87,0x68,0x30,0xe0,0x3d, +0x6c,0xcc,0x80,0x2d,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x2e,0x1b,0x7a,0xb3,0x26, +0x91,0x9, 0xa3,0x2e,0x1c,0x7a,0xa3,0x26,0x92,0x7f,0x7, 0x12,0x84,0xe9,0x50,0xf, +0x7f,0x7, 0x7e,0xb3,0x26,0x92,0x6c,0x77,0x12,0x84,0xec,0x50,0x2, 0xb, 0xf0,0xb, +0xc0,0xbc,0xec,0x38,0xcf,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, 0xd0,0xbe, +0xd0,0x1e,0x40,0xb0,0xc3,0xda,0x3b,0x22,0x7d,0xf5,0x2e,0xf4,0x2, 0xee,0x6d,0xee, +0x29,0xb7,0x0, 0x5, 0x22,0x12,0x83,0x6e,0x12,0x75,0xea,0x7a,0xb3,0x31,0x2d,0x22, +0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x31,0x8f,0xac,0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac, +0x37,0x2d,0x10,0x7e,0x1f,0x13,0x8a,0x2d,0x31,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b, +0xe4,0x6c,0x11,0x80,0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x2e, +0x1c,0xa, 0x20,0xa, 0x33,0x9d,0x32,0x12,0x17,0x88,0x7c,0x7, 0x1a,0x41,0x3e,0x44, +0x9, 0x74,0x2e,0x1b,0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x17,0x88,0x7c,0x97,0xbe, +0x90,0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18, +0x8, 0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x2f,0xa5,0xbc, +0x81,0x18,0xb2,0x22,0x7a,0x37,0x26,0x59,0x7e,0x34,0x15,0xa8,0x7a,0x37,0x26,0x5d, +0x7e,0x34,0x15,0x9e,0x7a,0x37,0x26,0x5b,0x7e,0x73,0x31,0x90,0x7a,0x73,0x26,0x56, +0x7e,0x73,0x31,0x91,0x7a,0x73,0x26,0x55,0x7e,0x37,0x31,0x7d,0x7a,0x37,0x26,0x5f, +0x7e,0x37,0x31,0x7f,0x7a,0x37,0x26,0x61,0x7e,0x37,0x31,0x81,0x7a,0x37,0x26,0x63, +0x74,0x1, 0x7a,0xb3,0x26,0x57,0x7a,0xb3,0x26,0x58,0x7e,0x8, 0x26,0x55,0x7e,0x18, +0x26,0x65,0x12,0x8, 0x0, 0x7e,0x37,0x26,0x6f,0x7e,0x27,0x26,0x6b,0xbd,0x23,0x28, +0x2, 0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, 0x26,0x55,0x12,0x8d,0x59,0x7e,0x1f,0x3c, +0xc6,0x7a,0x1d,0x27,0x7e,0xb3,0x31,0x95,0xf5,0x2e,0x7e,0xb3,0x3c,0x70,0xb4,0x1, +0x6, 0x7e,0x38,0x3c,0x72,0x80,0x4, 0x7e,0x38,0x5, 0xf8,0x6d,0x33,0x7a,0x35,0x2b, +0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x3c,0x71,0x70,0xe, 0x7e,0xb3,0x3c,0x6f,0x70, +0x8, 0x74,0x1, 0x7a,0xb3,0x3c,0x71,0x21,0x1c,0x7e,0xb3,0x3c,0x71,0x70,0x6, 0x74, +0x1, 0x7a,0xb3,0x3c,0x71,0x7e,0xb3,0x3c,0x70,0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80, +0x6, 0x12,0x89,0x5e,0x12,0x89,0x6c,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18, +0x75,0x2d,0x0, 0x80,0xc, 0x12,0x89,0x5e,0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0x89, +0x6c,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e,0x34,0x61,0x5b,0x12,0x20,0xc9,0x7a, +0x35,0x2f,0x7e,0x18,0x26,0x55,0x7f,0x1, 0x12,0x89,0x7d,0x75,0x2d,0x0, 0x80,0x10, +0x12,0x89,0x51,0xbe,0x35,0x2b,0x8, 0x6, 0x12,0x89,0x51,0x7a,0x35,0x2b,0x5, 0x2d, +0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xe9,0x12,0x89,0x49,0x40,0x25,0x7e,0xb3,0x3c,0x70, +0xb4,0x1, 0x1e,0x5, 0x62,0xe5,0x62,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x62,0x0, 0xe5, +0x2e,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, 0x12,0x17,0x31,0x1b, +0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x89,0x49,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x3c, +0xc5,0xe4,0x7a,0xb3,0x3c,0x71,0xda,0x3b,0x22,0x7e,0x37,0x32,0x28,0xbe,0x35,0x2b, +0x22,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x49,0x35,0x26,0x55,0x2, 0x17,0x88,0x7e,0xa1, +0x2d,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7e,0xd, 0x27,0x2d, +0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35,0x26,0x55,0x5, 0x2d,0x22,0xca,0x3b,0x7f, +0x61,0x7f,0x50,0x7e,0x73,0x31,0x8f,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f, +0x5, 0x12,0x17,0x31,0x1b,0xfd,0x6c,0xdd,0x12,0x8d,0x1b,0x7a,0xb3,0x26,0x8d,0x6c, +0xcc,0x80,0x45,0x12,0x8a,0x21,0x78,0x3e,0x12,0x8d,0x23,0xb, 0x1a,0xe0,0x7d,0x3f, +0x12,0x17,0x88,0x7d,0x13,0x7d,0x3e,0x12,0x17,0x88,0xbd,0x31,0x58,0x2, 0x7d,0xfe, +0xbe,0xe5,0x2f,0x8, 0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd, +0x3e,0x8, 0x2, 0x7d,0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x26, +0x8d,0x4, 0x7a,0xb3,0x26,0x8d,0xb, 0xc0,0x7e,0x73,0x31,0x91,0xbc,0x7c,0x38,0xb3, +0x7e,0x73,0x26,0x8d,0x4c,0x77,0x68,0x1d,0x12,0x8d,0x41,0x8, 0x2, 0x7d,0x7f,0x6c, +0xcc,0x80,0xa, 0x12,0x8a,0x21,0x78,0x3, 0x12,0x8d,0x2c,0xb, 0xc0,0x7e,0x73,0x31, +0x91,0xbc,0x7c,0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0x21,0x98,0xda,0x3b, +0x22,0xa, 0xec,0x9, 0x7e,0x31,0xfd,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd, +0x3e,0x22,0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e, +0xd, 0x24,0x7f,0x13,0x12,0x89,0x7d,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x8a,0xa1, +0x7e,0xd, 0x24,0x2d,0x15,0x7f,0x13,0x2d,0x35,0x12,0x8c,0x2a,0xda,0x3b,0x22,0x7e, +0x37,0x31,0x70,0x1e,0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, +0x12,0x8a,0x32,0x7e,0x37,0x2f,0xba,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a, +0x7e,0x18,0x4, 0x7e,0x12,0x8a,0x32,0x12,0x4f,0xb4,0x12,0x8d,0x61,0x2, 0x8a,0x90, +0xe4,0x7a,0xb3,0x3, 0xfe,0x7e,0xb3,0x2f,0xc9,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xfe, +0x22,0x7e,0xa3,0x31,0x95,0x74,0x2, 0xa4,0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d, +0xab,0x7d,0x8b,0x6d,0x22,0x7d,0x32,0x7d,0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78, +0x4, 0xfc,0x7e,0x8, 0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a, +0xb3,0x2e,0x17,0x7a,0xb3,0x2e,0x19,0x7a,0xb3,0x2e,0x18,0x7a,0xb3,0x2e,0x1a,0x6c, +0xaa,0x80,0x63,0x12,0x8c,0x19,0x2d,0xd7,0xb, 0x6a,0xc0,0xbd,0xca,0x58,0x2, 0x7d, +0xac,0xbd,0xc3,0x8, 0x2, 0x7d,0x3c,0x2d,0x71,0x7d,0x60,0xb, 0x3a,0xd0,0xbd,0xd9, +0x58,0x2, 0x7d,0x9d,0x7e,0x67,0x31,0x74,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xc7, +0x8, 0x2, 0x5, 0x24,0x12,0x8c,0x21,0xb, 0x3a,0xd0,0xbd,0xcd,0x8, 0xb, 0x7e,0xb3, +0x2e,0x18,0x4, 0x7a,0xb3,0x2e,0x18,0x80,0x1b,0x12,0x8c,0x11,0x7d,0x6e,0xb, 0x3a, +0xc0,0x6e,0xd4,0xff,0xff,0xb, 0xd4,0xbd,0xcd,0x58,0x9, 0x7e,0xb3,0x2e,0x1a,0x4, +0x7a,0xb3,0x2e,0x1a,0xb, 0xa0,0x7e,0xb3,0x31,0x95,0xbc,0xba,0x38,0x95,0x7a,0xa7, +0x7, 0xfe,0x7a,0x37,0x8, 0x2, 0xe5,0x24,0x7a,0xb3,0x8, 0x9, 0x7a,0x97,0x8, 0x6, +0x12,0x8a,0xa1,0x2d,0xf5,0x6c,0xaa,0x80,0x54,0x12,0x8c,0x19,0x2d,0xd7,0xb, 0x6a, +0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d,0xbd,0xd2,0x8, 0x2, 0x7d,0x2d,0x7e,0x67,0x31, +0x72,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xd7,0x8, 0x2, 0xb, 0x90,0x12,0x8c,0x21, +0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, 0x7e,0xb3,0x2e,0x17,0x4, 0x7a,0xb3,0x2e,0x17, +0x80,0x19,0x12,0x8c,0x11,0x7d,0x6e,0xb, 0x3a,0xd0,0x6d,0x99,0x9d,0x9c,0xbd,0xd9, +0x58,0x9, 0x7e,0xb3,0x2e,0x19,0x4, 0x7a,0xb3,0x2e,0x19,0xb, 0xa0,0x7e,0xb3,0x31, +0x94,0xbc,0xba,0x38,0xa4,0x7a,0x87,0x7, 0xfc,0x7a,0x27,0x8, 0x0, 0x7a,0x93,0x8, +0x8, 0x12,0x8a,0xa1,0x2d,0x15,0x6c,0xaa,0x80,0x14,0x7e,0x90,0x2, 0xac,0x9a,0x7f, +0x70,0x2d,0xf4,0xb, 0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x7e,0xb3, +0x31,0x94,0xbc,0xba,0x38,0xe4,0x7a,0xb7,0x8, 0x4, 0xbd,0x8a,0x58,0x2, 0x7d,0xa8, +0x7a,0xa7,0x7, 0xf8,0xbd,0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b, +0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x2d,0x7f,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x7f,0x67, +0x22,0x7e,0x74,0x62,0x16,0x7e,0x64,0x0, 0xff,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50, +0x7e,0x14,0x1f,0xf6,0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x7a, +0x1d,0x2c,0x7e,0x73,0x31,0x8e,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, +0x12,0x17,0x31,0x1b,0xfd,0x6c,0xdd,0x12,0x8d,0x1b,0x7a,0xb3,0x26,0x55,0x6c,0xcc, +0x80,0x4c,0x12,0x8d,0xb, 0x40,0x45,0x12,0x8d,0x3, 0xbc,0xab,0x50,0x3e,0x12,0x8d, +0x23,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x17,0x88,0x7d,0x3, 0x7d,0x31,0x12,0x17,0x88, +0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15,0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, +0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a, +0x24,0x2f,0x41,0x7e,0xb3,0x26,0x55,0x4, 0x7a,0xb3,0x26,0x55,0xb, 0xc0,0x7e,0x73, +0x31,0x90,0xbc,0x7c,0x38,0xac,0x7e,0x73,0x26,0x55,0x4c,0x77,0x68,0x39,0x12,0x8d, +0x41,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, 0x5, 0x7e,0x75,0x2a,0x80,0xb, 0x6d, +0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e,0x6c,0xcc,0x80,0x11,0x12,0x8d, +0xb, 0x40,0xa, 0x12,0x8d,0x3, 0xbc,0xab,0x50,0x3, 0x12,0x8d,0x2c,0xb, 0xc0,0x7e, +0x73,0x31,0x90,0xbc,0x7c,0x38,0xe7,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x2, 0x81,0x57, +0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0x22,0xa, 0xec,0x9, 0xae,0x31, +0xda,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0x7e,0xf4,0x7f,0xff,0x9f, +0x44,0xe4,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0x22,0x74,0x2, 0xac,0xbc, +0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b,0x1a,0xe0, +0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12,0x15,0xc8,0x7d,0x73,0x12,0x17,0x88,0x7d, +0xe3,0x7d,0x3f,0x12,0x17,0x88,0xbd,0x3e,0x22,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x17, +0x56,0x7e,0x63,0x31,0x8f,0x90,0x60,0xa7,0xe4,0x93,0x60,0x6c,0xc2,0x15,0x6c,0x33, +0x80,0x56,0x90,0x60,0xaa,0xe4,0x93,0x70,0x13,0x7c,0x96,0xac,0x93,0x90,0x60,0xab, +0xe4,0x93,0xa, 0x5b,0x1b,0x54,0x2d,0x45,0x7d,0xd4,0xb, 0xd4,0x7d,0x54,0x3e,0x54, +0x7e,0x7f,0x13,0x8a,0x2d,0xf5,0xb, 0x7a,0x50,0xbe,0x57,0x31,0x7b,0x8, 0x27,0x7c, +0xb3,0x12,0x4a,0xb0,0x50,0x20,0x7d,0x5d,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x7f,0x57, +0x2d,0xb5,0xb, 0x5a,0xc0,0x7d,0x54,0x3e,0x54,0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x5c, +0x8, 0x4, 0xd2,0x15,0x80,0xa, 0xb, 0x30,0x7e,0x73,0x31,0x96,0xbc,0x73,0x38,0xa2, +0x30,0x15,0x5, 0xd2,0x0, 0x2, 0x4a,0xd2,0x22,0x74,0xc8,0x7a,0xb3,0x3c,0xd2,0xc2, +0x1b,0x80,0xa, 0x12,0x29,0x23,0x30,0x1b,0x4, 0x75,0xe9,0xff,0x22,0x12,0x2f,0xc7, +0x68,0xf1,0x22,0x74,0x1, 0x12,0x8e,0x12,0x20,0x1b,0x6, 0x12,0x29,0xd8,0x12,0x0, +0x46,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x6, 0x12,0x8d,0xd9,0x12,0x0, 0x46,0xe4,0x2, +0x8e,0x12,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x8e,0x1b,0x22,0xa, 0x5b,0x2e,0x54,0x0, +0x8, 0xf5,0xcc,0x22,0x12,0x27,0x49,0x7e,0x73,0x3b,0x6c,0xbe,0x70,0xff,0x68,0x13, +0xbe,0x73,0x3b,0x92,0x68,0xd, 0x7a,0x73,0x3b,0x92,0x74,0xff,0x7a,0xb3,0x3b,0x6c, +0x2, 0x27,0x49,0x22,0x7e,0x34,0x61,0x57,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x20,0x12, +0x8e,0x5f,0x50,0x8, 0x7e,0x27,0x31,0x70,0x1e,0x24,0x1e,0x24,0x7d,0x32,0x22,0xc2, +0x0, 0x7e,0xb3,0x31,0x8c,0xbe,0xb0,0x1, 0x68,0x7, 0x7e,0xb3,0x31,0x89,0xb4,0x1, +0x17,0x7e,0xb3,0x3a,0xfc,0x70,0x11,0x12,0x37,0xf3,0x40,0xa, 0x7e,0x37,0x2f,0xab, +0xbe,0x34,0x1, 0x90,0x58,0x2, 0xd2,0x0, 0xa2,0x0, 0x22,0x12,0x8e,0x5f,0x50,0x12, +0x7e,0x37,0x32,0x28,0xbe,0x34,0x1, 0x2c,0x28,0x8, 0x7e,0x34,0x1, 0x2c,0x7a,0x37, +0x32,0x28,0x22,0x7e,0xb3,0x3b,0x92,0x70,0x23,0x7e,0xb3,0x3b,0x75,0xbe,0xb0,0x10, +0x40,0x1, 0xe4,0xa, 0x3b,0x2e,0x34,0xf, 0xf0,0x12,0x47,0xed,0x7c,0xab,0xe5,0x67, +0xa, 0x3b,0x2e,0x37,0x3c,0x6d,0x7a,0x37,0x3c,0x6d,0x80,0xc, 0x7e,0xa3,0x3b,0x76, +0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, 0x8e,0xdd,0x75,0x67,0x0, +0x7a,0xb3,0x3c,0xd2,0xc2,0x1b,0x22,0x7e,0xb3,0x3c,0x70,0x70,0x4, 0x74,0x1, 0x80, +0x1, 0xe4,0x7a,0xb3,0x3c,0x70,0x22,0x7f,0x20,0xc2,0x1, 0x7e,0x2b,0x60,0x29,0x72, +0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x17,0x88,0x7c,0x27,0x29,0x72,0x0, 0x1, 0x29, +0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x17,0x88,0x7c,0x37,0x1a,0x23,0x1a,0x32, +0x9d,0x32,0x12,0x17,0x88,0x7c,0x67,0x7c,0x72,0xbc,0x32,0x58,0x2, 0x7c,0x73,0xbe, +0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e,0x37,0x3c,0x22,0x4d,0x33,0x68, +0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70, +0x7c,0xe7,0x7c,0xdb,0x7e,0xc0,0x4, 0x7e,0xb3,0x31,0x8e,0xf5,0x28,0x7e,0xb3,0x31, +0x8f,0xf5,0x27,0x7e,0x34,0x62,0x10,0x12,0x7f,0x9a,0x6c,0xff,0x12,0x87,0x80,0x7f, +0x51,0xe5,0x28,0xa, 0x3b,0x1b,0x34,0xa, 0xcd,0xbd,0xc3,0x58,0x14,0xe5,0x27,0xa, +0x3b,0x1b,0x34,0xa, 0xce,0xbd,0xc3,0x58,0x8, 0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78, +0x3, 0x4e,0xf0,0x10,0xb, 0x5a,0x30,0x7e,0x14,0x62,0x10,0x12,0x5f,0xc8,0xbd,0x32, +0x8, 0xd, 0x7e,0x27,0x2f,0xab,0xbe,0x24,0x3, 0x20,0x8, 0x3, 0x2, 0x90,0xa0,0xb, +0xa, 0xc0,0x1e,0xc4,0xbd,0x3c,0x8, 0xd, 0x7e,0xc7,0x2f,0xab,0xbe,0xc4,0x3, 0x20, +0x58,0x3, 0x2, 0x90,0xa0,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, +0x48,0x11,0x7e,0xb3,0x31,0x8e,0xbc,0xb8,0x8, 0x9, 0x12,0x90,0xd7,0x58,0x14,0xb, +0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8,0xbd, +0xc3,0x18,0xd8,0xbc,0xca,0x18,0x6, 0x4e,0xf0,0x1, 0x2, 0x90,0xa0,0x6c,0xaa,0x7c, +0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x31,0x8e,0xbc,0xb8, +0x8, 0x9, 0x12,0x90,0xd7,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a, +0x2c,0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x5, 0x4e, +0xf0,0x2, 0x80,0x6c,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48, +0x11,0x7e,0xb3,0x31,0x8f,0xbc,0xb9,0x8, 0x9, 0x12,0x90,0xd7,0x58,0x14,0xb, 0xa0, +0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3, +0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x35,0x6c,0xaa,0x7c,0x9e,0x80, +0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x31,0x8f,0xbc,0xb9,0x8, 0x9, +0x12,0x90,0xd7,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a, +0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, +0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7, +0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe, +0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7, +0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x12,0x75,0xe3,0xbd,0x3d, +0x22,0xca,0x3b,0x7c,0xc7,0x7c,0xfb,0x7f,0x40,0x6d,0x33,0x7a,0x35,0x24,0x7e,0xa3, +0x31,0x8e,0x7e,0x73,0x31,0x8f,0x4c,0xcc,0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c, +0xb7,0x14,0xbc,0xbc,0x78,0x6, 0xa, 0x6c,0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, +0x7e,0xf0,0x1, 0x80,0xb, 0x7c,0xba,0x14,0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75, +0x7f,0x4, 0x7e,0x34,0x0, 0x6, 0xe4,0x12,0x17,0x56,0x7e,0x73,0x31,0x8e,0xa, 0x37, +0x1b,0x34,0x7a,0x4b,0x70,0x7e,0x73,0x31,0x8f,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, +0x1, 0x7c,0xec,0x80,0x1c,0x75,0x26,0x0, 0x7c,0xdf,0x80,0xa, 0x12,0x8f,0x46,0x70, +0xa, 0x12,0x91,0xfb,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf1,0xe5,0x26,0x60,0x7, 0x1b, +0xe0,0xbe,0xe0,0x0, 0x58,0xdf,0x7c,0xec,0x80,0x23,0x75,0x26,0x0, 0x1a,0x3f,0xb, +0x34,0x7c,0xd7,0x80,0xa, 0x12,0x8f,0x46,0x70,0xd, 0x12,0x91,0xfb,0xb, 0xd0,0x7e, +0x73,0x31,0x8e,0xbc,0x7d,0x18,0xee,0xe5,0x26,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, +0x58,0xd8,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x1c,0x75,0x26,0x0, 0x7c,0xdf,0x80, +0xa, 0x12,0x8f,0x46,0x70,0xa, 0x12,0x91,0xfb,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf1, +0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x31,0x8f,0xbc,0x7e,0x18,0xdc,0x1a,0x3c, +0xb, 0x34,0x7c,0xe7,0x80,0x21,0x75,0x26,0x0, 0x1a,0x6f,0xb, 0x64,0x80,0xa, 0x12, +0x8f,0x46,0x70,0xd, 0x12,0x91,0xfb,0xb, 0xd0,0x7e,0x73,0x31,0x8e,0xbc,0x7d,0x18, +0xee,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x31,0x8f,0xbc,0x7e,0x18,0xd7,0x7e, +0x35,0x24,0x7d,0x23,0x39,0x54,0x0, 0x5, 0xda,0x3b,0x22,0x5, 0x26,0x7e,0x35,0x24, +0xb, 0x34,0x7a,0x35,0x24,0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe,0xa0,0xa, 0x50,0x1b, +0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d,0x15,0xb, 0x14,0x12, +0x17,0x31,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22,0x7c,0xbd,0x7c,0x7e, +0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a,0x7f,0x70,0x2d, +0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b,0xb0,0xbc,0xb6, +0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, 0x1, 0xbc,0xb7, +0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x38,0xc9,0xa2, +0x1, 0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90,0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80, +0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x92,0x30,0x50,0x2, 0xd3,0x22,0xb, 0x80, +0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, 0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79, +0x50,0xd9,0xc3,0x22,0x30,0x12,0x13,0x12,0x7f,0xb2,0x68,0x6, 0x7e,0xb3,0x3c,0xd7, +0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x3c,0x2a,0x22,0x6c,0xaa,0x7e,0x63,0x31, +0x8f,0x7e,0x73,0x31,0x8e,0xac,0x76,0x7d,0x13,0x1e,0x14,0x7e,0x27,0x2f,0xa9,0x2e, +0x27,0x2f,0xa7,0xbd,0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34,0xbe,0x37,0x2f,0xa7,0x50, +0x29,0x90,0x60,0x51,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x2e,0x18,0xa, 0x3b, +0xbd,0x32,0x8, 0x16,0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x2e, +0x17,0xa, 0x3b,0xbd,0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x2, 0x73,0xd4, +0xca,0x3b,0x7c,0xfb,0x6c,0xee,0x80,0x68,0x6c,0xdd,0x80,0x16,0x74,0x9, 0xac,0xbd, +0x9, 0x65,0x30,0x87,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x2f,0xd3,0xbc,0x67,0x68,0x7, +0xb, 0xd0,0x12,0x93,0x87,0x38,0xe5,0x12,0x93,0x87,0x28,0x48,0x74,0x9, 0xac,0xbd, +0x9, 0xc5,0x30,0x87,0x12,0x96,0xe8,0x12,0x95,0x7d,0x74,0x9, 0xac,0xbd,0x12,0x96, +0xf5,0x9d,0x32,0x12,0x17,0x88,0x2d,0x31,0x7a,0x35,0x24,0xa, 0x3c,0x9, 0xb3,0x30, +0xdd,0xb4,0x1, 0xe, 0x6d,0x33,0x74,0x2, 0xac,0xbc,0x59,0x35,0x39,0x12,0x59,0x35, +0x39,0x35,0x7e,0x35,0x24,0x7c,0xbd,0x7c,0x5e,0x7c,0x4c,0x12,0x93,0xd, 0xb, 0xe0, +0xbc,0xfe,0x38,0x94,0xda,0x3b,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbd,0x22,0xca, +0x3b,0x6d,0x11,0x7d,0x1, 0x7e,0xe3,0x31,0x23,0x4c,0xee,0x78,0x23,0x6c,0xff,0x80, +0x1a,0x74,0x2, 0xac,0xbf,0x12,0x95,0x6c,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x39, +0x4e,0x74,0x2, 0xa, 0x3f,0x19,0xb3,0x39,0xb8,0xb, 0xf0,0x12,0x5e,0xa4,0x38,0xe1, +0x12,0x97,0x2, 0x7e,0x24,0x0, 0x14,0xad,0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c, +0xff,0xa1,0x45,0x74,0x9, 0xac,0xbf,0x9, 0xd5,0x2f,0xd3,0x5e,0xd0,0xf, 0x12,0x93, +0x87,0x38,0x2, 0xa1,0x43,0xa, 0x1d,0x9, 0xb1,0x30,0xdd,0xbe,0xb0,0x1, 0x78,0x2, +0xa1,0x29,0x75,0x24,0x0, 0xa1,0x1b,0x7e,0x31,0x24,0x74,0x9, 0xac,0x3b,0x9, 0xc1, +0x39,0x4e,0xbc,0xcd,0x68,0x2, 0xa1,0x19,0x7e,0xa3,0x31,0x91,0x74,0x40,0xa4,0x9e, +0x54,0x0, 0x20,0x7e,0x34,0x60,0xd1,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0x2d,0xf5, +0x49,0x21,0x39,0x4c,0xbd,0x2f,0x28,0x9, 0x12,0x95,0x74,0xbd,0x3f,0x38,0x2, 0x81, +0xb9,0x12,0x95,0x74,0x9d,0x32,0x12,0x17,0x88,0x7d,0x3, 0x7e,0xa1,0x24,0x74,0x9, +0xa4,0x49,0x25,0x39,0x4a,0x12,0x67,0x9b,0x9d,0x32,0x12,0x17,0x88,0x2d,0x3, 0xa, +0x1c,0x9, 0xa1,0x39,0xb8,0xbe,0xa0,0x0, 0x28,0x17,0x7e,0x30,0x2, 0xac,0x3c,0x59, +0x1, 0x39,0xa4,0xa, 0x1c,0x2e,0x14,0x39,0xb8,0x7c,0xba,0x14,0x7a,0x19,0xb0,0xa1, +0x43,0x74,0x2, 0xac,0xbc,0x49,0x15,0x39,0xa4,0xbe,0x14,0x0, 0x32,0x28,0x8, 0x7d, +0xe1,0x2d,0xe4,0xbd,0xe0,0x40,0x20,0xbe,0x14,0x0, 0x32,0x28,0x8, 0xbe,0x4, 0x0, +0x32,0x28,0x2, 0x80,0x7e,0x7d,0xe1,0x2e,0xe4,0x0, 0x32,0xbd,0xe0,0x50,0x8, 0xbe, +0x14,0x0, 0x32,0x28,0x2, 0x80,0x6c,0xbe,0x4, 0x0, 0xa0,0x28,0x62,0xa, 0x1d,0x9, +0xb1,0x30,0xdd,0x70,0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, 0xa, 0x1d,0x19,0xb1,0x30, +0xdd,0x74,0x3, 0xa, 0x1c,0x19,0xb1,0x30,0xe7,0xbe,0xe0,0x0, 0x28,0x75,0x1b,0xe0, +0x7e,0x70,0x9, 0xac,0x7f,0x2e,0x34,0x2f,0xcf,0x7e,0x14,0x26,0x55,0x74,0x9, 0x12, +0x15,0xfc,0x7e,0x70,0x9, 0xac,0x7e,0x12,0x95,0x85,0xac,0x3f,0x2e,0x14,0x2f,0xcf, +0x74,0x9, 0x12,0x15,0xfc,0x7e,0x34,0x26,0x55,0x7e,0x30,0x9, 0xac,0x3e,0x2e,0x14, +0x2f,0xcf,0x74,0x9, 0x12,0x15,0xfc,0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74, +0x2, 0xac,0xbc,0x59,0x5, 0x39,0xa4,0x80,0x2a,0x5, 0x24,0x90,0x60,0x99,0xe4,0x93, +0xbe,0xb1,0x24,0x28,0x2, 0x61,0xf7,0x80,0x1a,0x6d,0x11,0x74,0x2, 0xac,0xbd,0x12, +0x95,0x6c,0x7e,0x30,0x9, 0xac,0x3d,0x19,0xa1,0x39,0x4e,0x74,0x2, 0xa, 0x1d,0x19, +0xb1,0x39,0xb8,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x61,0xd3,0xe4,0x7a,0xb3,0x16,0x92, +0x90,0x60,0x99,0x12,0x66,0xda,0xca,0x59,0x7e,0x18,0x2f,0xcf,0x7e,0x8, 0x39,0x4a, +0x12,0x17,0x31,0x1b,0xfd,0x7a,0xe3,0x31,0x23,0xda,0x3b,0x22,0x59,0x15,0x39,0xa4, +0x7e,0xa0,0xff,0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x2f,0xd1,0x22,0x9d,0x32,0x12, +0x17,0x88,0x7d,0x13,0x22,0x2e,0x34,0x2f,0xcf,0x7e,0x30,0x9, 0x22,0xca,0xd8,0xca, +0x79,0x7c,0xdb,0x90,0x60,0x99,0xe4,0x93,0x7c,0xfb,0x6c,0x11,0x80,0x21,0x7e,0x0, +0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x26,0x59,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac, +0xb1,0x59,0x35,0x26,0x55,0x74,0x9, 0xac,0xb1,0x59,0x35,0x26,0x57,0xb, 0x10,0xbc, +0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d,0x12,0x96,0x2f,0x7c,0x1b,0x7c,0x7d,0x7c, +0x6f,0x12,0x96,0x2f,0x7c,0x1b,0x6c,0x0, 0x80,0x39,0x6c,0xee,0x80,0x16,0x74,0x9, +0xac,0xbe,0x9, 0x65,0x26,0x59,0x74,0x9, 0xac,0xb0,0x9, 0x75,0x2f,0xd3,0xbc,0x76, +0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x15,0x7e,0x70,0x9, 0xac, +0x70,0x12,0x95,0x85,0xac,0x31,0x2e,0x14,0x26,0x55,0x74,0x9, 0x12,0x15,0xfc,0xb, +0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf,0xca,0x59,0x7e,0x18,0x26, +0x55,0x7e,0x8, 0x30,0x83,0x12,0x17,0x31,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x7e, +0x8, 0x26,0x55,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0xc1,0xce,0x7c,0x57,0xc1, +0xc6,0x7e,0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x30,0x87,0x7c,0x98,0x7e,0xd0,0x9, 0xac, +0xd5,0x9, 0xb6,0x2f,0xd3,0xbc,0xb9,0x78,0x6b,0xbe,0x90,0xff,0x68,0x66,0x12,0x96, +0xde,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x30,0xdd,0x7e,0xf0,0x9, 0x70,0xc, +0xac,0xf5,0x7d,0x97,0x2e,0x94,0x2f,0xcf,0x6d,0x88,0x80,0xa, 0xac,0xf6,0x7d,0x97, +0x2e,0x94,0x30,0x83,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x96,0xde,0x1b,0x7a,0xd0,0x69, +0xf4,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6,0x0, 0x2, +0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x2f,0xd4,0x12,0x96,0xde,0x39,0x87,0x0, 0x5, +0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x2f,0xd5,0x12,0x96,0xde,0x39,0x87,0x0, 0x6, +0xb, 0xa0,0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0xc1,0x41,0xb, 0x60,0x90,0x60, +0x99,0xe4,0x93,0xbc,0xb6,0x28,0x2, 0xc1,0x3d,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0, +0x9, 0xac,0xfa,0x7f,0x70,0x2d,0xf7,0x22,0x49,0x25,0x30,0x85,0x74,0x9, 0xac,0xbe, +0x49,0x35,0x2f,0xd1,0x22,0x49,0x25,0x30,0x83,0x74,0x9, 0xac,0xbe,0x49,0x35,0x2f, +0xcf,0x22,0x7e,0x73,0x31,0x24,0xbe,0x73,0x31,0x23,0x78,0x13,0x12,0x4f,0xf2,0x40, +0xe, 0x7e,0x37,0x39,0x26,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, 0x7e, +0x37,0x39,0x26,0x1e,0x34,0x7a,0x37,0x39,0x26,0x7e,0xb3,0x31,0x23,0x70,0x6, 0x6d, +0x33,0x7a,0x37,0x39,0x26,0x7e,0x37,0x39,0x26,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e, +0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x3c,0xc6,0x2d,0xf0,0x69, +0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d,0x32,0x12,0x17,0x88,0xbd,0x31,0x28,0x16, +0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x3c,0xc6,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69, +0x30,0x0, 0x80,0x12,0x95,0x7d,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x3c,0xc6,0x2d, +0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69, +0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e, +0xb3,0x31,0x95,0xbc,0xba,0x38,0x9d,0x7d,0x31,0x22,0x12,0x97,0x3a,0x7e,0x14,0x62, +0xd, 0x12,0x5f,0xc8,0xbd,0x32,0x28,0x3, 0xd2,0x16,0x22,0xc2,0x16,0x22,0x7e,0xa3, +0x31,0x24,0xbe,0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x31,0x23,0x50,0x19,0x7e,0xb3,0x31, +0x2d,0xbe,0xb3,0x39,0xc4,0x28,0x14,0x7e,0xb3,0x39,0xc4,0x4, 0x7a,0xb3,0x39,0xc4, +0x7a,0xa3,0x31,0x23,0x80,0x5, 0xe4,0x7a,0xb3,0x39,0xc4,0x7e,0xb3,0x31,0x23,0x70, +0x5, 0xe4,0x7a,0xb3,0x31,0x2c,0x22,0x12,0x97,0xfd,0x2, 0x97,0xbe,0x7e,0xb3,0x31, +0x23,0x70,0x29,0x12,0x98,0x36,0x28,0x24,0x7e,0xb3,0x39,0x49,0x70,0x18,0x12,0x98, +0x3e,0x7e,0x73,0x31,0x24,0x7a,0x73,0x31,0x23,0x74,0x1, 0x7a,0xb3,0x31,0x2a,0x7e, +0xb3,0x39,0x49,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x49,0x22,0xe4,0x7a,0xb3,0x39, +0x49,0x7a,0xb3,0x31,0x2a,0x22,0x7e,0x73,0x31,0x24,0xbe,0x70,0x0, 0x22,0x7e,0x34, +0x0, 0x3c,0xca,0x39,0x7e,0x18,0x39,0xf6,0x7e,0x8, 0x3a,0x32,0x12,0x17,0x31,0x1b, +0xfd,0x7e,0x73,0x2f,0xb5,0x7a,0x73,0x39,0xee,0x7a,0x73,0x2f,0xb4,0x22,0x12,0x98, +0x36,0x28,0x8, 0x7e,0xb3,0x2f,0xa5,0x70,0x2, 0xf5,0x5d,0x7e,0xb3,0x2f,0xa5,0x70, +0x18,0xe5,0x5d,0xbe,0xb0,0xfa,0x50,0x2, 0x5, 0x5d,0xe5,0x5d,0xbe,0xb0,0x5, 0x40, +0x8, 0xe4,0x7a,0xb3,0x2, 0xed,0x75,0x5d,0xfa,0x22,0xca,0x79,0xc2,0x0, 0x7e,0xf0, +0x3, 0x12,0x98,0x5e,0x7e,0xe3,0x31,0x24,0x7e,0x34,0x26,0x55,0x7a,0x37,0x2, 0xaf, +0x12,0x7f,0xa2,0x38,0x2, 0x21,0x66,0x12,0x87,0xc, 0x92,0xb, 0x12,0x9e,0x20,0x7c, +0xbf,0x12,0x99,0x6f,0x4c,0xee,0x68,0xe, 0x7e,0xa3,0x2, 0x8c,0x4c,0xaa,0x78,0xa, +0x7e,0xb3,0x2, 0x8d,0x70,0x4, 0xd2,0x0, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5, +0x5e,0xbe,0xb0,0x8, 0x28,0x4, 0xd2,0x0, 0x80,0x15,0xd2,0x0, 0x7e,0xb3,0x2f,0xa5, +0xbc,0xbe,0x78,0xb, 0x20,0xb, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20, +0x0, 0x5, 0x7c,0xbf,0x12,0x99,0x6f,0x7e,0x8, 0x2, 0x91,0x12,0xb0,0x41,0x7a,0xb3, +0x2, 0x90,0xbe,0xb3,0x2f,0xa5,0x50,0x3d,0x7e,0x33,0x2, 0x90,0x80,0x29,0x7e,0x70, +0x2, 0xac,0x73,0x9, 0x23,0x2, 0xb1,0x9, 0x13,0x2, 0xb2,0x2e,0x37,0x2, 0xaf,0xb, +0x38,0x50,0x7e,0x93,0x31,0x8f,0xac,0x92,0xa, 0x31,0x2d,0x43,0x12,0x9f,0x57,0x7c, +0xb3,0x7e,0x70,0x1, 0x12,0x74,0x94,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xcf,0x74, +0x1, 0x7a,0xb3,0x2, 0x8e,0x7e,0xa3,0x2, 0x90,0x7a,0xa3,0x2f,0xa5,0x74,0x2, 0xa4, +0xca,0x59,0x7e,0x18,0x2, 0xb1,0x7e,0x8, 0x2e,0x1b,0x12,0x17,0x31,0x1b,0xfd,0x12, +0x9d,0xa3,0xf5,0x5e,0x80,0x6, 0x75,0x5e,0x64,0x12,0x9f,0x33,0xda,0x79,0x22,0xca, +0x3b,0x7c,0xfb,0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x7e,0xb3,0x31,0x90,0xf5,0x43,0x7e, +0xb3,0x31,0x91,0xf5,0x44,0x7e,0xd3,0x2f,0xa5,0xe4,0x7a,0xb3,0x2, 0x90,0x7a,0xb3, +0x2, 0x8c,0x7a,0xb3,0x2, 0x8d,0x7e,0x8, 0x2, 0x91,0x90,0x60,0x9a,0x93,0xa, 0x3b, +0xe4,0x12,0x17,0x56,0x12,0x9f,0x2a,0x7e,0x8, 0x2, 0xb1,0xe4,0x12,0x17,0x56,0xbe, +0xd0,0x2, 0x50,0x2, 0xa1,0x99,0x6c,0xcc,0xa1,0x93,0x7e,0x70,0x2, 0xac,0x7c,0x9, +0xb3,0x2e,0x1b,0xf5,0x24,0x9, 0xb3,0x2e,0x1c,0xf5,0x25,0x4c,0xcc,0x68,0x8, 0xa, +0x3c,0x9, 0xb3,0x2, 0x91,0x70,0xa, 0xa, 0x3c,0xb, 0x34,0xa, 0x2c,0x19,0x72,0x2, +0x91,0x7c,0xbd,0x14,0xbc,0xbc,0x78,0x2, 0xa1,0x99,0xa, 0x5c,0xb, 0x54,0xf5,0x2e, +0xa1,0x8a,0x7e,0x71,0x2e,0x12,0x9f,0x42,0x7a,0xa1,0x26,0x9, 0xb3,0x2e,0x1c,0xf5, +0x27,0xa, 0x2a,0xe5,0x24,0x12,0x9d,0x9c,0x7c,0xb7,0xf5,0x28,0xe5,0x27,0xa, 0x2b, +0xe5,0x25,0x12,0x9d,0x9c,0x7c,0xb7,0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, +0xa1,0x88,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xa1,0x88,0x12,0x9e,0x4c,0x12,0x84, +0x97,0x7a,0xb3,0x2, 0x8f,0x85,0x25,0x54,0x85,0x26,0x55,0x85,0x27,0x56,0x7e,0x8, +0x0, 0x31,0x7e,0x18,0x0, 0x33,0xe5,0x24,0x12,0x9e,0x60,0x75,0x3d,0x0, 0x75,0x3e, +0x0, 0x75,0x30,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x75,0xe3,0x7a,0x35,0x35,0xe5, +0x26,0x7e,0x71,0x27,0x12,0x75,0xe3,0x7a,0x35,0x37,0x7e,0x35,0x35,0xbe,0x35,0x37, +0x8, 0x5, 0x7e,0x35,0x37,0x80,0x3, 0x7e,0x35,0x35,0x7a,0x35,0x3b,0xe, 0x34,0x7a, +0x35,0x39,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x2c,0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x25, +0x7c,0xbf,0x30,0xe1,0x20,0xe5,0x26,0x7e,0x71,0x25,0x12,0x75,0xe3,0x7d,0x43,0xe5, +0x24,0x7e,0x71,0x27,0x12,0x75,0xe3,0x2d,0x34,0xbe,0x35,0x39,0x18,0x2, 0xa1,0x1f, +0x75,0x30,0x1, 0xa1,0x1f,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x9, 0xe5,0x29,0xbe,0xb0, +0x1, 0x38,0x2, 0xa1,0x1f,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, 0xa1,0x1f,0xe5,0x29, +0xbe,0xb0,0x5, 0x40,0x2, 0xa1,0x1f,0x7c,0xbf,0x20,0xe0,0x2, 0xa1,0x1f,0x6d,0x33, +0x7a,0x35,0x4d,0x75,0x4f,0x0, 0x7a,0x35,0x50,0x75,0x52,0x0, 0xc2,0x2, 0xc2,0x3, +0xe5,0x26,0xbe,0xb1,0x24,0x28,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2a,0xe5, +0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2c,0xe5,0x27, +0xbe,0xb1,0x25,0x28,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2b,0xe5,0x27,0xbe, +0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2d,0xe5,0x2c,0xbe,0xb1, +0x2a,0x78,0x29,0xd2,0x2, 0xe5,0x2a,0x60,0x8, 0xe5,0x43,0x14,0xbe,0xb1,0x2a,0x78, +0x2, 0xd2,0x3, 0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2a,0xe5,0x43,0xa, 0x2b, +0x1b,0x24,0xe5,0x2c,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2c,0xe5,0x2d,0xbe,0xb1, +0x2b,0x78,0x29,0xd2,0x2, 0xe5,0x2b,0x60,0x8, 0xe5,0x44,0x14,0xbe,0xb1,0x2b,0x78, +0x2, 0xd2,0x3, 0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2b,0xe5,0x44,0xa, 0x2b, +0x1b,0x24,0xe5,0x2d,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2d,0x85,0x2a,0x3f,0x80, +0x5b,0x85,0x2b,0x40,0x80,0x4d,0xe5,0x3f,0x7e,0x71,0x40,0x12,0x75,0xe3,0x7a,0x35, +0x41,0xe5,0x2a,0xbe,0xb1,0x3f,0x68,0x15,0xe5,0x2c,0xbe,0xb1,0x3f,0x68,0xe, 0xe5, +0x2b,0xbe,0xb1,0x40,0x68,0x7, 0xe5,0x2d,0xbe,0xb1,0x40,0x78,0xd, 0x7e,0x35,0x41, +0x2e,0x35,0x4d,0x7a,0x35,0x4d,0x5, 0x4f,0x80,0x17,0x5, 0x52,0x7e,0x35,0x41,0x2e, +0x35,0x50,0x7a,0x35,0x50,0x7e,0x35,0x33,0xbe,0x35,0x41,0x58,0x2, 0x5, 0x3d,0x5, +0x3e,0x5, 0x40,0xe5,0x2d,0xbe,0xb1,0x40,0x50,0xac,0x5, 0x3f,0xe5,0x2c,0xbe,0xb1, +0x3f,0x50,0x9e,0xe5,0x2c,0x7e,0x71,0x2b,0x12,0x75,0xe3,0x7e,0x45,0x4d,0x9d,0x43, +0xe5,0x2a,0x7e,0x71,0x2d,0x12,0x75,0xe3,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2b,0x12, +0x75,0xe3,0x9d,0x43,0xe5,0x2c,0x7e,0x71,0x2d,0x12,0x75,0xe3,0x7d,0x23,0x7d,0x34, +0x9d,0x32,0x7a,0x35,0x4d,0x7e,0x35,0x37,0x2e,0x35,0x35,0x7a,0x35,0x39,0x30,0x2, +0x10,0x20,0x3, 0xd, 0x7e,0x35,0x4d,0x9e,0x35,0x39,0x7a,0x35,0x4d,0x15,0x4f,0x15, +0x4f,0xe5,0x4f,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x4f,0x24,0xfc,0xf5,0x4f,0x7e,0x35, +0x4d,0xbe,0x34,0x0, 0x0, 0x58,0x5, 0x6d,0x33,0x7a,0x35,0x4d,0x7e,0xe0,0x22,0xe5, +0x43,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, 0xe5,0x24,0x60,0x4, +0xe5,0x26,0x70,0xa, 0x12,0x9e,0x58,0x28,0x4b,0x7e,0xe0,0x2c,0x80,0x46,0x30,0x13, +0x43,0x7e,0x73,0x39,0xf2,0xbe,0x71,0x2c,0x38,0x13,0xbe,0x71,0x2a,0x40,0xe, 0x7e, +0x73,0x39,0xf4,0xbe,0x71,0x2d,0x38,0x5, 0xbe,0x71,0x2b,0x50,0x1c,0x7e,0x73,0x39, +0xf3,0xbe,0x71,0x2c,0x38,0x1e,0xbe,0x71,0x2a,0x40,0x19,0x7e,0x73,0x39,0xf5,0xbe, +0x71,0x2d,0x38,0x10,0xbe,0x71,0x2b,0x40,0xb, 0xa, 0x3e,0x7e,0x24,0x0, 0x3, 0x12, +0x15,0x29,0x2c,0xe7,0x7e,0x15,0x50,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4d,0x1a,0x26, +0x1a,0x24,0x2f,0x10,0xa, 0x1e,0x6d,0x0, 0x12,0x15,0x5b,0x7f,0x71,0x7a,0x7d,0x45, +0x7e,0x15,0x39,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x31,0x1a,0x26,0x1a,0x24,0x12,0x15, +0x5b,0xe5,0x52,0xa, 0xdb,0x6d,0xcc,0xe5,0x4f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12, +0x15,0x5b,0x7a,0x1d,0x49,0xbf,0x71,0x8, 0x3, 0x75,0x30,0x2, 0xc2,0x1, 0x20,0xa, +0xe, 0x12,0x9e,0x4c,0x12,0x9f,0x84,0x92,0x1, 0x20,0x1, 0x3, 0x75,0x30,0x0, 0xe5, +0x30,0xbe,0xb0,0x0, 0x28,0x62,0xe5,0x30,0xa, 0x3b,0x2e,0x34,0x2, 0x8b,0x7e,0x39, +0xb0,0x4, 0x7a,0x39,0xb0,0xe5,0x2e,0xa, 0x3b,0x9, 0xa3,0x2, 0x91,0x4c,0xaa,0x78, +0xc, 0xa, 0x2c,0x9, 0xb2,0x2, 0x91,0x19,0xb3,0x2, 0x91,0x80,0x3b,0xa, 0x2c,0x9, +0xb2,0x2, 0x91,0xf5,0x53,0xbc,0xba,0x28,0x3, 0x7a,0xa1,0x53,0x75,0x2f,0x0, 0x80, +0x22,0x9, 0x33,0x2, 0x91,0xe5,0x2f,0xa, 0x2b,0x9, 0x22,0x2, 0x91,0xbc,0x23,0x68, +0xa, 0xa, 0xc, 0x9, 0x30,0x2, 0x91,0xbc,0x23,0x78,0x6, 0xe5,0x53,0x19,0xb2,0x2, +0x91,0x5, 0x2f,0xbe,0xd1,0x2f,0x38,0xd9,0x5, 0x2e,0xbe,0xd1,0x2e,0x28,0x2, 0x21, +0xf2,0xb, 0xc0,0xbc,0xdc,0x28,0x2, 0x21,0xba,0xda,0x3b,0x22,0xa, 0x3b,0x9d,0x32, +0x2, 0x17,0x88,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4a,0xa, 0x31,0xb, +0x34,0x7c,0x7, 0x80,0x38,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x2e,0x1b,0x12,0x9e, +0x18,0x9, 0xb3,0x2e,0x1b,0x12,0x9d,0x9c,0x7c,0x97,0x7e,0x70,0x2, 0xac,0x70,0x9, +0xb3,0x2e,0x1c,0x12,0x9e,0x18,0x9, 0xb3,0x2e,0x1c,0x12,0x9d,0x9c,0x7c,0x87,0xbc, +0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28,0xb, 0x0, 0x7e,0xb3,0x2f, +0xa5,0xbc,0xb0,0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x2f,0xa5,0xbc,0xb1,0x38,0xae,0xa5, +0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22,0xbc,0x23,0x28,0x4, 0x7c, +0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x71,0x22, +0x6c,0xaa,0x12,0x9f,0x4b,0x12,0x9e,0x42,0x54,0xfe,0x12,0x9e,0x3f,0x54,0x7, 0x12, +0x9e,0x3f,0x54,0xfb,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xe4,0x22,0x7a, +0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, 0x5, 0x7e,0xb, 0xb0,0x22,0xe5,0x24,0x7e,0x71, +0x25,0x7e,0x61,0x26,0x7e,0x51,0x27,0x22,0x7e,0x73,0x2, 0x8f,0xbe,0x70,0x5, 0x22, +0xca,0xf8,0x7c,0xfb,0x7f,0x61,0x7f,0x50,0x7e,0x34,0x1f,0xcc,0x7e,0x24,0x0, 0xff, +0x7e,0x14,0x26,0x91,0x74,0x2a,0x12,0x16,0x1d,0x7e,0x48,0x26,0x91,0x12,0x9e,0xef, +0x92,0xa, 0x7c,0xbf,0x7e,0x71,0x54,0x12,0x75,0xe3,0x7d,0x43,0xe5,0x55,0x7e,0x71, +0x56,0x12,0x75,0xe3,0x2d,0x34,0xe, 0x34,0x7f,0x4, 0x7e,0x50,0x7, 0xb, 0xa, 0x50, +0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b,0x5a,0x30,0x69,0x30,0x0, 0x4, 0x1b, +0x6a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78,0xe1,0x12,0x9e,0x58,0x28, +0x2b,0xb, 0x5a,0x20,0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e,0x24,0x0, 0x10,0x12,0x15, +0x29,0x1b,0x5a,0x30,0xb, 0x6a,0x30,0x1a,0x26,0x1a,0x24,0x7e,0x14,0x0, 0xd, 0x12, +0x15,0x6c,0x7e,0x8, 0x0, 0x10,0x12,0x15,0xc8,0x1b,0x6a,0x30,0xda,0xf8,0x22,0x7e, +0x37,0x2f,0xab,0xbe,0x34,0x3, 0xe8,0x8, 0xa, 0x12,0x9f,0x5, 0xbe,0xb0,0x8, 0x48, +0x2, 0xd3,0x22,0xc3,0x22,0xca,0xd8,0xca,0x79,0x6c,0xff,0x6c,0xee,0x80,0xf, 0x7c, +0xbe,0x12,0x9f,0x63,0x7c,0xdb,0xbc,0xfd,0x58,0x2, 0x7c,0xfd,0xb, 0xe0,0x12,0x4f, +0xdb,0x38,0xec,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0x90,0x60,0x9a,0x93,0xa, 0x3b, +0x3e,0x34,0x22,0x7e,0x8, 0x2, 0xee,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x17,0x56,0x7e, +0x71,0x24,0x74,0x2, 0xac,0x7b,0x9, 0xa3,0x2e,0x1b,0x22,0x7e,0x70,0x6, 0xac,0x7a, +0x2e,0x34,0x2, 0xee,0x6d,0x22,0x22,0x3e,0x44,0x7e,0x1f,0x13,0x8a,0x2d,0x34,0x1b, +0x1a,0x50,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x70,0x2, 0x12,0xb2,0x9b,0x7f,0x71,0x7c, +0xbf,0x12,0x75,0xcd,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x7f,0x17,0x12,0x15,0xc8,0x7c, +0xb7,0xda,0xf8,0x22,0x12,0xb1,0xbc,0x92,0x4, 0x30,0x4, 0xc, 0x7e,0xb3,0x2, 0xed, +0xbe,0xb0,0xfa,0x50,0x11,0x4, 0x80,0xa, 0x7e,0xb3,0x2, 0xed,0xbe,0xb0,0x0, 0x28, +0x5, 0x14,0x7a,0xb3,0x2, 0xed,0x7e,0xb3,0x2, 0xed,0x70,0x2, 0xc3,0x22,0xd3,0x22, +0x6c,0xaa,0x12,0x9f,0x4b,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90, +0x7f,0x1, 0x2e,0x14,0x0, 0x5, 0x7c,0xb8,0x54,0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29, +0xb1,0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, +0x7f,0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0, +0x1e,0x40,0xbf,0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28, +0xf, 0x74,0x1, 0x7a,0xb3,0x31,0x28,0xe4,0x7a,0xb3,0x31,0x2a,0x7a,0xb3,0x31,0x2b, +0x2, 0xa0,0x69,0xa5,0xbe,0x0, 0x1d,0x6c,0xaa,0x80,0xe, 0x7e,0x60,0xff,0x7e,0x50, +0x9, 0xac,0x5a,0x19,0x62,0x30,0x87,0xb, 0xa0,0x12,0x5b,0xfa,0x38,0xed,0x74,0x1, +0x7a,0xb3,0x31,0x27,0x6c,0xaa,0x80,0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x2f, +0xcf,0x12,0xa0,0x5d,0x1b,0x18,0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x2f,0xd1, +0x12,0xa0,0x5d,0x1b,0x18,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20, +0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22,0x12,0xa0,0x82,0x7e,0x8, 0x39,0x35, +0xe4,0x12,0x17,0x56,0x90,0x60,0x99,0x12,0xa0,0x86,0x7e,0x8, 0x39,0x12,0xe4,0x2, +0x17,0x56,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x2, 0xac,0x7b,0x22,0xca,0x3b, +0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x3a, +0x32,0x7e,0x8, 0x39,0xf6,0x12,0x17,0x31,0x1b,0xfd,0x7e,0xf3,0x2f,0xa5,0xa, 0xcf, +0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x2e,0x1b,0x7e,0x8, 0x26,0x55,0x12,0x17,0x31,0x1b, +0xfd,0x6c,0x88,0x6c,0xee,0x21,0x62,0x7e,0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99, +0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x26,0x55,0xbe,0xb0,0xff,0x68,0x3d,0x7c, +0xb9,0x12,0x4e,0xdc,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x26,0x56,0xa, 0x27, +0x74,0x2, 0xac,0xbe,0x9, 0x75,0x3a,0x33,0x12,0x37,0xc9,0x7d,0x13,0x74,0x2, 0xac, +0xb9,0x9, 0x75,0x26,0x55,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x3a,0x32,0x12, +0x37,0xc9,0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9, +0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0x55, +0x9, 0x73,0x26,0x56,0x12,0x75,0xe3,0xbe,0x37,0x31,0x7b,0x48,0x23,0x7e,0x70,0x2, +0xac,0x7c,0x9, 0x53,0x26,0x55,0x74,0x2, 0xac,0xbd,0x19,0x55,0x26,0x91,0x9, 0x53, +0x26,0x56,0x19,0x55,0x26,0x92,0x74,0xff,0x19,0xb3,0x26,0x55,0xb, 0x80,0xb, 0xd0, +0xb, 0xe0,0x7e,0x73,0x39,0xee,0xbc,0x7e,0x28,0x2, 0x1, 0xc7,0x7c,0xe8,0x80,0x79, +0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99,0x80,0x48,0x7c,0xb9,0x12,0x4e,0xdc,0x60,0x3f, +0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3,0x26,0x55,0xbe,0xb0,0xff,0x68,0x31,0x9, 0x73, +0x26,0x56,0x12,0x87,0x84,0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, +0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0x13,0x7e,0x70,0x2, 0xac, +0x79,0x9, 0xb3,0x26,0x55,0xf5,0x24,0x9, 0xc3,0x26,0x56,0x7d,0xdc,0x7c,0x89,0xb, +0x90,0xbc,0xf9,0x38,0xb4,0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74,0x2, 0xac, +0xbd,0x19,0x75,0x26,0x91,0x19,0xc5,0x26,0x92,0x7e,0xa0,0xff,0x7e,0x70,0x2, 0xac, +0x78,0x19,0xa3,0x26,0x55,0xb, 0xd0,0xb, 0xe0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbe, +0x28,0x2, 0x21,0x70,0x90,0x60,0x9a,0xe4,0x93,0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59, +0x7e,0x18,0x26,0x91,0x7e,0x8, 0x26,0x55,0x12,0x17,0x31,0x1b,0xfd,0x7c,0xfd,0x12, +0xa0,0x82,0x7e,0x8, 0x3a,0x32,0x74,0xff,0x12,0x17,0x56,0xbe,0xf0,0x0, 0x28,0x35, +0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x26,0x55,0x7e,0x8, 0x2e,0x1b,0x12,0x17, +0x31,0x1b,0xfd,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x26,0x55,0x7e,0x8, 0x3a, +0x32,0x12,0x17,0x31,0x1b,0xfd,0x6c,0xee,0x80,0x7, 0x7c,0xbe,0x12,0x74,0x91,0xb, +0xe0,0xbc,0xfe,0x38,0xf5,0x7a,0xf3,0x39,0xee,0x7a,0xf3,0x2f,0xa5,0x90,0x60,0x99, +0xe4,0x93,0xbe,0xb3,0x2f,0xa5,0x50,0x4, 0x7a,0xb3,0x2f,0xa5,0xda,0x3b,0x22,0x7c, +0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x39,0x29,0xbe, +0x73,0x39,0x33,0x50,0xe, 0x7d,0x24,0x2e,0x24,0x39,0x29,0x7c,0xb7,0x4, 0x7a,0x29, +0xb0,0xd3,0x22,0xbe,0x73,0x39,0x33,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, 0xe4,0x7a, +0xb, 0xb0,0x74,0xff,0x19,0xb4,0x39,0x29,0x80,0x17,0xa, 0x3a,0x9, 0xb3,0x39,0x29, +0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x39,0x29,0xd3,0x22,0xe4,0x19,0xb3,0x39, +0x29,0xc3,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x31,0x83,0xbd,0x13,0x38, +0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12, +0x15,0x75,0xbe,0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf, +0x49,0x25,0x39,0x35,0xbd,0x2f,0x28,0x6, 0x49,0x35,0x39,0x12,0x80,0x4, 0x59,0x35, +0x39,0x12,0x59,0xf5,0x39,0x35,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, +0xda,0xf8,0x22,0x6c,0xaa,0x80,0x49,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x30,0x83, +0x12,0x22,0x65,0x59,0x32,0x2f,0xcf,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x30,0x85, +0x12,0x22,0x65,0x59,0x32,0x2f,0xd1,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x30,0x87, +0x19,0xb4,0x2f,0xd3,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x30,0x88,0x19,0xb4,0x2f, +0xd4,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x30,0x89,0x19,0xb4,0x2f,0xd5,0xb, 0xa0, +0x12,0x5b,0xfa,0x38,0xb2,0x22,0x7e,0x8, 0x39,0x28,0x7e,0x34,0x0, 0xd, 0xe4,0x2, +0x17,0x56,0xca,0x3b,0x6c,0x88,0x80,0x7e,0x12,0xa4,0x3, 0x9, 0xe5,0x2e,0x1c,0xa, +0x6f,0x1b,0x64,0x80,0x37,0xa, 0x5e,0x1b,0x54,0x7c,0xab,0x80,0x23,0xbe,0xd0,0x0, +0x40,0x1c,0xbc,0xfd,0x28,0x18,0xbe,0xa0,0x0, 0x40,0x13,0xbc,0xea,0x28,0xf, 0x7c, +0xbd,0x7c,0x7a,0x12,0x75,0xe3,0xbe,0x34,0x0, 0x0, 0x58,0x2, 0xb, 0x90,0xb, 0xa0, +0xa, 0x2e,0xb, 0x24,0xa, 0x3a,0xbd,0x32,0x8, 0xd3,0xb, 0xd0,0xa, 0x2f,0xb, 0x24, +0xa, 0x3d,0xbd,0x32,0x8, 0xbf,0x7e,0x70,0x2, 0xac,0x7e,0x49,0x53,0x4, 0xfc,0xbe, +0x54,0x0, 0x50,0x48,0x18,0xbe,0x54,0x0, 0x64,0x58,0x19,0xbe,0x90,0x2, 0x40,0x14, +0x7c,0xbf,0x7c,0x7e,0x12,0x75,0xe3,0xbe,0x34,0x0, 0xc8,0x58,0x7, 0x7c,0xb8,0x6c, +0x77,0x12,0x74,0x94,0xb, 0x80,0x7e,0x73,0x2f,0xa5,0xbc,0x78,0x28,0x2, 0x61,0x78, +0xda,0x3b,0x22,0x74,0x2, 0xac,0xb8,0x9, 0xf5,0x2e,0x1b,0x22,0xe4,0x7a,0xb3,0x3a, +0x71,0x7e,0xb3,0x2f,0xa5,0x60,0x6, 0x7e,0xb3,0x3a,0xea,0x60,0x5, 0xe4,0x7a,0xb3, +0x3a,0xec,0x22,0x6c,0x99,0x6c,0x88,0x80,0x1d,0x7c,0xb8,0x12,0x75,0xcd,0xbe,0x34, +0x0, 0xb4,0x8, 0x10,0x74,0x2, 0xac,0xb8,0x49,0x55,0x4, 0xfc,0xbe,0x54,0x0, 0xc8, +0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x2f,0xa5,0xbc,0x78,0x38,0xdb,0xbe,0x90, +0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x70,0xc2, +0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x1f,0xfa,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x26, +0x55,0x74,0xc, 0x12,0x16,0x1d,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c,0xee,0x80,0x13, +0x12,0xa5,0x6b,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, 0x28,0x2, 0x7d, +0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, 0x7e,0xb3,0x2f, +0xb5,0x70,0x4, 0x6d,0x33,0xa1,0x56,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, 0xd2,0x0, 0x6c, +0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x26,0x55,0xbd,0x4d,0x58,0x6, 0x49,0xd5,0x26, +0x57,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, 0x78,0x4, 0x6d, +0x33,0xa1,0x56,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xd0,0x9f,0x55,0x6c,0xee, +0x80,0xb, 0x12,0xa5,0x6b,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0,0xbc,0xfe,0x38, +0xf1,0xa, 0x1f,0x12,0xa5,0x5b,0x7d,0x13,0x9f,0x55,0x6c,0xee,0x80,0x1d,0x12,0xa5, +0x62,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x17,0x88,0x7d,0xc3,0xbd,0x1c,0x28,0xa, 0x7d, +0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xdf,0x6d, +0x11,0xbe,0xd0,0x0, 0x28,0x7, 0xa, 0x1d,0x12,0xa5,0x5b,0x7d,0x13,0xbd,0x1d,0x8, +0x4, 0x7d,0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c, +0xee,0x80,0xd, 0x12,0xa5,0x62,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0, +0xbc,0xfe,0x38,0xef,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x6d,0x0, 0x7f,0x15,0x2, +0x15,0xc8,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0x22,0x74,0x2, 0xac,0xbe,0x7f, +0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x17,0x88,0x7e,0xb3,0x32,0x3e,0xb4,0x1, 0x31, +0x12,0xa5,0xb2,0x7e,0x1f,0x33,0xfb,0x7a,0x37,0x2c,0x1b,0x7e,0x34,0xd, 0xc8,0x7a, +0x37,0x2c,0x17,0x12,0xa5,0xb9,0x12,0xa5,0xf6,0xe4,0x7a,0xb3,0x2c,0x16,0x7e,0x34, +0x0, 0x20,0x7a,0x37,0x2c,0x1d,0x7a,0xb3,0x2c,0x15,0x7e,0x8, 0x2c,0x13,0x2, 0xd, +0x7, 0x22,0xa9,0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0x73,0x31,0x8e,0x7a,0x73,0x2c, +0x13,0x22,0x7e,0x8, 0x2c,0x13,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x17,0x56,0x12,0xa5, +0xf6,0x12,0xa5,0xb9,0xa9,0xd1,0xcb,0x12,0xa5,0xff,0x7a,0x37,0x2c,0x17,0x7e,0x1f, +0x33,0xfb,0x7a,0x37,0x2c,0x19,0x7e,0x1f,0x13,0x86,0x7a,0x37,0x2c,0x1b,0x6d,0x33, +0x12,0xa6,0x7, 0x2, 0xd, 0x7, 0x7e,0x73,0x31,0x8f,0x7a,0x73,0x2c,0x14,0x22,0x12, +0x0, 0xe, 0x7e,0x1f,0x13,0x86,0x22,0x7a,0x37,0x2c,0x1d,0x7e,0x8, 0x2c,0x13,0x22, +0x7a,0xb3,0x2c,0x13,0x7e,0x53,0x31,0x8f,0x7a,0x53,0x2c,0x14,0x7a,0x37,0x2c,0x1b, +0xe4,0x7a,0xb3,0x2c,0x15,0x7a,0xb3,0x2c,0x16,0x7e,0x34,0x40,0x0, 0x7a,0x37,0x2c, +0x17,0x7e,0x34,0x0, 0x20,0x12,0xa6,0x7, 0x2, 0xd, 0x7, 0x12,0xa6,0x74,0x7e,0x34, +0xd, 0xc8,0x7e,0xb3,0x31,0x8e,0x12,0xa6,0x10,0x12,0xa6,0x57,0x7a,0x37,0x33,0xf8, +0x74,0x1, 0x7a,0xb3,0x16,0x91,0x22,0x6d,0x33,0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0, +0x0, 0x28,0x3, 0x2, 0xb8,0xa6,0x90,0x60,0x92,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, +0x2, 0xa6,0xcd,0x22,0xa9,0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x7e,0x43,0x31,0x8f, +0x7e,0x53,0x31,0x8e,0xac,0x54,0x7e,0x17,0x2f,0xc2,0x12,0xa5,0xb2,0x6d,0x0, 0x80, +0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x33,0xfb,0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13, +0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x8, 0xa, 0xb, 0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50, +0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48, +0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5,0x22,0xca,0xf8,0x6d, +0xee,0x7d,0xfe,0x7e,0x83,0x31,0x8f,0xa, 0xd8,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff, +0x2f,0x7e,0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x18,0x7e,0x70,0x2, 0xac,0x7a,0x49,0x23, +0x13,0xfe,0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0,0x9d,0xc2,0x59,0xc3,0x13,0xc6,0xb, +0xa0,0xbc,0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4,0x93,0x7c,0x9b,0x6d,0xdd,0x80,0x11, +0x7e,0x8, 0x13,0xfe,0x90,0x60,0x92,0xe4,0x93,0xa, 0xcb,0x1b,0xc4,0x7d,0x3c,0x7c, +0x97,0x6c,0xff,0x80,0x38,0x6c,0xaa,0x80,0x28,0xa, 0x3a,0x7d,0x23,0x2d,0x2e,0x3e, +0x24,0x49,0xc2,0x13,0xfe,0x2d,0x3d,0x3e,0x34,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xb0, +0x7d,0x3c,0x9d,0x3b,0x12,0x17,0x88,0x7d,0xa3,0xbd,0xfa,0x58,0x2, 0x7d,0xfa,0xb, +0xa0,0xbc,0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec,0x2d,0xdc,0xb, 0xf0,0xbc,0x9f,0x38, +0xc4,0x7d,0x3f,0xda,0xf8,0x22,0x90,0x60,0xa7,0xe4,0x93,0x60,0x2b,0x6c,0x33,0x80, +0x1f,0x7c,0xb3,0x12,0x4a,0xb0,0x40,0x16,0x7c,0xb3,0x12,0x4a,0x65,0x7d,0x43,0x6d, +0x55,0x7d,0x4, 0x3e,0x4, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50,0xb, 0x30, +0x7e,0x23,0x31,0x96,0xbc,0x23,0x38,0xd9,0x22,0x6c,0xaa,0x80,0x26,0x7e,0x50,0x2, +0xac,0x5a,0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, 0x2d,0x31,0x59,0x32,0x5, 0xf8, +0x30,0x6, 0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, 0x76,0x2d,0x31,0x59,0x32,0x6, +0x76,0xb, 0xa0,0x7e,0xb3,0x31,0x95,0xa, 0x3b,0x7e,0xb3,0x31,0x94,0xa, 0x2b,0x2d, +0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0xd2,0x0, 0x6c,0xaa,0x6c,0x77,0x80,0x1f, +0x7e,0x63,0x31,0x8f,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c,0x65,0x7e,0x50,0x2, 0xac, +0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, 0xb, 0xa0,0xb, 0x70,0x7e, +0xb3,0x31,0x8e,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24,0xa, 0x3a,0xbd,0x32,0x8, +0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0x7e,0x63,0x31,0x90,0x7e,0xa3,0x31,0x91,0x7e,0x70, +0x1, 0x80,0x25,0xa, 0x17,0x7e,0xb3,0x31,0x8f,0xa, 0x2b,0x2d,0x21,0x3e,0x24,0x49, +0x12,0x4, 0xfc,0x7e,0xf4,0x61,0x59,0x12,0xa8,0x83,0x6e,0x24,0xff,0xff,0xb, 0x24, +0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b,0x14,0xa, 0x27,0xbd,0x21, +0x48,0xd1,0x7e,0x70,0x2, 0x80,0x20,0x7e,0x50,0x2, 0xac,0x57,0x49,0x12,0x4, 0xfc, +0x7e,0xf4,0x61,0x5b,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, 0x6d,0x22,0x9d,0x20,0xbd, +0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27,0xbd,0x21,0x48, +0xd6,0xc3,0x22,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0x22,0x7c,0x3b,0x7e,0x44,0xff, +0xff,0x6c,0x22,0x80,0x2a,0x12,0xa9,0xa, 0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12, +0xaa,0x4c,0x7d,0x23,0x7e,0x70,0xc, 0xac,0x72,0x59,0x23,0x3b,0xd, 0x49,0x3, 0x3b, +0xd, 0x49,0x23,0x3b,0x9, 0xbd,0x20,0x50,0x4, 0x59,0x3, 0x3b,0x9, 0xb, 0x20,0xbc, +0x32,0x50,0xd2,0x6c,0xaa,0x6c,0x22,0x80,0x18,0x12,0xa9,0xa, 0x68,0x11,0x7e,0x70, +0xc, 0xac,0x72,0x49,0x3, 0x3b,0x9, 0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, +0x20,0xbc,0x32,0x50,0xe4,0x7e,0x37,0x3a,0xef,0xbe,0x37,0x3b,0x68,0x50,0x8, 0x7e, +0x37,0x3b,0x68,0x7a,0x37,0x3a,0xef,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x3b,0x9, +0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e,0x10,0x5, 0xac,0x12,0x9, +0xb0,0x2d,0x54,0xbe,0xb3,0x32,0x30,0x22,0xca,0xd8,0xca,0x79,0x7e,0xe0,0xff,0x12, +0xaa,0x59,0x7e,0xb3,0x3a,0xf6,0xb4,0x1, 0x8, 0x12,0x57,0x22,0xe4,0x7a,0xb3,0x3a, +0xf6,0x7e,0xb3,0x3a,0xf5,0x60,0x4, 0x74,0xff,0x41,0x47,0x7e,0xb3,0x3a,0xf4,0xb4, +0x2, 0x2, 0x80,0x2, 0x41,0x3b,0x12,0x57,0xf4,0x38,0x12,0x12,0x57,0xec,0x38,0xd, +0x12,0x57,0xe4,0x38,0x8, 0x7e,0xb3,0x16,0x91,0x60,0x2, 0x41,0x3b,0x12,0x57,0xdc, +0xa, 0x3d,0x1b,0x34,0xbe,0x34,0x0, 0x3, 0x48,0x4, 0x74,0x3, 0x80,0x3, 0x7c,0xbd, +0x14,0x12,0xa8,0x8b,0x7c,0xfb,0x7e,0xb3,0x3a,0xf3,0x4, 0x7a,0xb3,0x3a,0xf3,0x90, +0x61,0xcb,0xe4,0x93,0x14,0x12,0xa8,0x8b,0x7c,0xab,0xbe,0xa0,0xff,0x68,0x32,0xbe, +0xf0,0xff,0x68,0x2b,0x7e,0x30,0xc, 0xac,0x3f,0x49,0x21,0x3b,0x9, 0x7e,0xf4,0x61, +0xd2,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x30,0xbd,0x23,0x28,0x15,0x7e,0x70,0xc, 0xac, +0x7a,0x49,0x33,0x3b,0x9, 0x3e,0x34,0xbd,0x23,0x28,0x6, 0x7c,0xfa,0x80,0x2, 0x7c, +0xfa,0xbe,0xf0,0xff,0x78,0x11,0xe4,0x7a,0xb3,0x3a,0xf3,0x7a,0xb3,0x3a,0xf4,0x7a, +0xb3,0x3b,0x0, 0x74,0xff,0x80,0x70,0x90,0x61,0xda,0xe4,0x93,0xbe,0xb3,0x3a,0xf3, +0x50,0x59,0x74,0xc, 0xac,0xbf,0x49,0x25,0x3b,0x9, 0x7e,0x14,0x61,0xd2,0x12,0x56, +0x6f,0xbd,0x23,0x50,0x3d,0x7e,0x34,0x61,0xd6,0x12,0x20,0xc9,0xbe,0x37,0x3a,0xef, +0x40,0xd, 0x7e,0x34,0x61,0xd8,0x12,0x20,0xc9,0xbe,0x37,0x3a,0xfa,0x50,0x23,0x74, +0x5, 0xac,0xbf,0x9, 0x75,0x2d,0x54,0xbe,0x73,0x32,0x30,0x68,0x15,0x7c,0xef,0xbe, +0xe0,0x4, 0x50,0x8, 0x12,0x44,0x4d,0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3, +0x3a,0xf6,0xe4,0x7a,0xb3,0x3b,0x0, 0x7a,0xb3,0x3a,0xf4,0xbe,0xe0,0xff,0x68,0x5, +0xe4,0x7a,0xb3,0x3a,0xf3,0x7c,0xbe,0xda,0x79,0xda,0xd8,0x22,0x49,0x23,0x3b,0xf, +0x49,0x33,0x3b,0xb, 0x9d,0x32,0x2, 0x17,0x88,0x7e,0xb3,0x3a,0xf5,0xb4,0x1, 0x27, +0x7e,0xb3,0x3b,0x6b,0x4, 0x7a,0xb3,0x3b,0x6b,0x7e,0x73,0x3b,0x6b,0xbe,0x70,0x3, +0x40,0x15,0x12,0x54,0x31,0x7e,0x73,0x3b,0x6b,0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a, +0xb3,0x3b,0x6b,0x7a,0xb3,0x3a,0xf5,0x22,0x7e,0x8, 0x3b,0x5, 0x7e,0x34,0x0, 0x60, +0xe4,0x12,0x17,0x56,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac,0x7a,0x59, +0x43,0x3b,0x7, 0x59,0x43,0x3b,0xf, 0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8,0x7e,0x8, +0x3a,0xf3,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x17,0x56,0x7e,0xa3,0x32,0x83,0xbc,0xab, +0x68,0x6, 0x7a,0xb3,0x32,0x83,0xd2,0xe, 0x30,0xe, 0x9, 0xc2,0xe, 0x12,0xaa,0xd5, +0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x31,0x8e,0x12,0x3, 0x8b,0x7e,0x8, 0x31,0x8e, +0x74,0x3, 0x2, 0x11,0x7a,0x7c,0xab,0x6d,0x44,0x80,0x35,0x4c,0xaa,0x68,0x17,0x12, +0xab,0x34,0x2e,0xd5,0x29,0x7e,0x6b,0xb0,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12, +0xab,0x28,0x2d,0xfe,0x80,0x15,0x12,0xab,0x34,0x2e,0xd5,0x29,0x7e,0x6b,0xb0,0x60, +0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0xab,0x28,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44, +0x7e,0xf5,0x29,0xbd,0xf4,0x38,0xc4,0x22,0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf, +0xb, 0x6a,0xf0,0x22,0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x22, +0x7c,0x7b,0x90,0x60,0x93,0xe4,0x93,0xa, 0x1b,0x7e,0x63,0x31,0x92,0xa, 0x6, 0x2d, +0x1, 0x7e,0x63,0x31,0x8f,0xa, 0x16,0xad,0x10,0x7d,0x21,0x12,0xab,0x71,0xa, 0x26, +0x7a,0x25,0x29,0x74,0x1d,0xac,0x7b,0x2e,0x34,0x3, 0xa6,0x6d,0x22,0xe4,0x2, 0xaa, +0xe5,0x3e,0x24,0x7e,0xf, 0x33,0xfb,0x2d,0x12,0x22,0x7e,0xa3,0x31,0x8f,0xa, 0x3a, +0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4,0x12,0x17,0x56,0x90,0x60,0x93,0x93,0xa, 0x3b, +0x7e,0xb3,0x31,0x92,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xad,0x32,0x7d,0x43,0x6c,0x77, +0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12,0xab,0x71,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac, +0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18,0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc, +0xa7,0x38,0xdf,0x22,0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c,0x22, +0x80,0x37,0x7e,0xb3,0x31,0x8f,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e,0x44, +0x7e,0x7f,0x13,0x8a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, 0xbe, +0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44,0xfd, +0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x31,0x8f,0xbc,0x92,0x38, +0xc1,0xb, 0x31,0x7e,0xb3,0x31,0x8e,0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, 0xad, +0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12,0x22,0x67,0xbd,0x12,0x50,0x22, +0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x3c,0xd4,0x7e,0xb3,0x3c,0xd5,0xbe,0xb0,0x5, +0x50,0x7, 0x4, 0x7a,0xb3,0x3c,0xd5,0x80,0x3c,0xe4,0x7a,0xb3,0x3c,0xd5,0x74,0x1, +0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x3c,0xd5,0x7e, +0xb3,0x3c,0xd4,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3c,0xd4,0x80,0x16,0xe4, +0x7a,0xb3,0x3c,0xd4,0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x3c,0xd4,0x7a,0xb3,0x3c, +0xd5,0x7a,0xb3,0x3c,0xd6,0x7e,0xb3,0x3c,0xd6,0x22,0xe4,0x7a,0xb3,0x2f,0xc9,0x7a, +0xb3,0x3c,0xd7,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6c,0xdd,0x7e,0x57,0x2f,0xba, +0x7d,0xf5,0x7e,0xe7,0x2f,0xb8,0x7e,0x37,0x3c,0x2a,0x4d,0x33,0x68,0x4, 0x7d,0xf5, +0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x31,0x8f,0x7c,0x8a,0x7e,0xb3,0x2f,0xc6,0x14,0x68, +0x21,0x14,0x68,0x14,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0x16,0x24,0x45,0x78,0x10, +0x7c,0xfa,0x7e,0x83,0x31,0x8e,0x80,0xa, 0x7e,0x73,0x31,0x8e,0x2c,0x87,0x80,0x2, +0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c,0xb9,0x12,0x75,0xcd,0xbe,0x34,0x2, 0x58,0x8, +0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33,0x2f,0xa5,0xbc,0x39,0x38,0xe9,0xbe,0xd0,0x3, +0x40,0x2, 0xc1,0x55,0x7e,0xa3,0x2f,0xa6,0xbe,0xa0,0x0, 0x38,0xb, 0xbe,0x30,0x0, +0x28,0x37,0x7e,0xb3,0x2d,0xa4,0x70,0x31,0x6c,0x99,0x80,0x29,0xa, 0x29,0xa, 0x3f, +0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, 0x7a,0xbd,0x2f,0x8, 0x17,0x49,0x3, 0x4, 0xfc, +0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d,0x3e,0x12,0x7e,0xad,0xbd,0x3, 0x8, 0x4, 0xd2, +0x0, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xd3,0x6d,0xee,0x9e,0xe7,0x31,0x70,0xbe, +0xe7,0x7, 0xf8,0x8, 0x2, 0xc2,0x0, 0x30,0x0, 0x20,0x7e,0xb3,0x3c,0xd7,0x4, 0x7a, +0xb3,0x3c,0xd7,0x7e,0x23,0x3c,0xd7,0xbe,0x20,0xa, 0x28,0x1d,0x74,0xa, 0x7a,0xb3, +0x3c,0xd7,0x74,0x1, 0x7a,0xb3,0x2f,0xc9,0x80,0xf, 0x7e,0x23,0x3c,0xd7,0xbe,0x20, +0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23,0x3c,0xd7,0x6c,0xee,0xbe,0x30,0x0, 0x38,0x5, +0xbe,0xa0,0x0, 0x28,0x69,0x7e,0xb3,0x2f,0xc8,0xb4,0x1, 0x9, 0x7e,0xb3,0x2f,0xcb, +0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3,0x2f,0xc9,0xb4,0x1, 0x52,0x6c,0x99,0x80,0x1d, +0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x2e,0x1b,0x9, 0xd3,0x2e,0x1c,0x12,0xae,0x5a, +0xbe,0x34,0x0, 0x96,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x2f, +0xa5,0xbc,0xb9,0x38,0xdb,0x6c,0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3, +0x2e,0x57,0x9, 0xd3,0x2e,0x58,0x12,0xae,0x5a,0xbe,0x34,0xff,0x6a,0x58,0x5, 0x7e, +0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x2f,0xa6,0xbc,0xb9,0x38,0xdb,0x6c,0x99, +0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d,0x5e,0x3e,0x54,0x49,0x55,0x5, 0x7a,0xbd,0x5f, +0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xe5,0x4c,0xee,0x78, +0x25,0x7e,0xb3,0x3c,0xd8,0x4, 0x7a,0xb3,0x3c,0xd8,0x7e,0x73,0x3c,0xd8,0xbe,0x70, +0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3,0x3c,0xd8,0x7e,0xb3,0x2f,0xc9,0x60,0x2, 0xd2, +0x18,0x12,0xac,0x8a,0x80,0xf, 0x7e,0x73,0x3c,0xd8,0xbe,0x70,0x0, 0x28,0x6, 0x1e, +0x70,0x7a,0x73,0x3c,0xd8,0xda,0x79,0xda,0xd8,0x22,0x7c,0xba,0x7c,0x7d,0x2, 0x75, +0xe3,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x31,0x8f,0x7e,0x47,0x2f,0xba,0xe4,0x7a,0xb3, +0x2f,0xc7,0x7e,0xb3,0x2e,0x11,0xbe,0xb0,0x0, 0x28,0x4c,0x7e,0x73,0x2f,0xa6,0xbe, +0x70,0x0, 0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x2e, +0x57,0x9, 0xe2,0x2e,0x58,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xfc,0x6d,0x22, +0x9e,0x27,0x31,0x74,0xbd,0x12,0x58,0x19,0x12,0xaf,0x7f,0x49,0x12,0x4, 0xfc,0x6d, +0x22,0x9e,0x27,0x31,0x72,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x2f,0xc7,0x80, +0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x2f,0xc8,0x7e,0xb3,0x2d,0xa4, +0x70,0x40,0x12,0x7f,0xaa,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, 0xac,0x5f, +0x9, 0xd2,0x2e,0x1b,0x9, 0xe2,0x2e,0x1c,0x12,0xaf,0x7f,0x49,0x2, 0x5, 0x7a,0x6d, +0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20,0x5, 0x7a, +0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x2f,0xc8,0x80,0x6, 0xb, 0xf0,0xbc,0x7f, +0x38,0xc9,0x12,0xac,0x94,0xe4,0x7a,0xb3,0x2f,0xca,0x7e,0x37,0x2f,0xa9,0x2e,0x37, +0x2f,0xa7,0xbe,0x37,0x2f,0xc0,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x2f,0xca,0x74,0x1, +0x7a,0xb3,0x2f,0xcb,0x6c,0xff,0x80,0x21,0x12,0xaf,0x77,0xac,0xbf,0x49,0x25,0x2d, +0x18,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x17,0x88,0xbe,0x37,0x2f,0xbe,0x8, 0x7, +0xe4,0x7a,0xb3,0x2f,0xcb,0x80,0x7, 0xb, 0xf0,0x12,0x35,0xbe,0x38,0xda,0x6c,0xff, +0x80,0xb, 0x12,0xaf,0x77,0xac,0xbf,0x59,0x35,0x2d,0x18,0xb, 0xf0,0x12,0x35,0xbe, +0x38,0xf0,0xda,0x79,0xda,0xd8,0x22,0x7c,0xbf,0x12,0x75,0xcd,0x74,0x2, 0x22,0xa, +0x1d,0xa, 0x2a,0x2d,0x21,0x3e,0x24,0x22,0xca,0xf8,0x6c,0xff,0x80,0x34,0x7e,0x73, +0x34,0x88,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x3f,0x90,0xca,0x39, +0x7e,0x30,0x38,0xac,0x3f,0x12,0xbc,0xa3,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x0, +0x8c,0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12,0xbc,0x98,0x12,0x17,0x31,0x1b,0xfd, +0xb, 0xf0,0x90,0x61,0xcb,0xe4,0x93,0xbc,0xbf,0x38,0xc3,0x7e,0x23,0x34,0x88,0x7e, +0x30,0x5, 0xac,0x23,0x12,0x3f,0x90,0xca,0x39,0x7e,0x23,0x34,0x88,0x7e,0x30,0x38, +0xac,0x23,0x12,0xbc,0xa3,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39, +0x7e,0x23,0x34,0x88,0x7e,0x30,0x8c,0xac,0x23,0x12,0xbc,0x98,0x12,0x17,0x31,0x1b, +0xfd,0xda,0xf8,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f, +0x2e,0x34,0x34,0x89,0x6d,0x22,0x7e,0x8, 0x34,0x0, 0x12,0x17,0x31,0x1b,0xfd,0x7e, +0x34,0x0, 0x8c,0xca,0x39,0xac,0x7f,0x2e,0x34,0x35,0x69,0x6d,0x22,0x7e,0x8, 0x37, +0x99,0x12,0x17,0x31,0x1b,0xfd,0xda,0xf8,0x22,0x12,0x37,0xf3,0xd2,0x19,0x2, 0x33, +0x6d,0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x2f,0xa5,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a, +0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e, +0xb, 0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d, +0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0x21,0xa6,0x75,0x2d, +0x0, 0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18,0x26,0x91, +0x7a,0x1d,0x29,0x74,0xff,0x7e,0x34,0x26,0x92,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0, +0x7e,0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d, +0x29,0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12,0x86,0xf9,0x44,0x1, 0x7a,0x1b,0xb0, +0x75,0x24,0x0, 0x80,0x6c,0x12,0x9f,0x3f,0x9, 0x93,0x2e,0x1c,0xe5,0x24,0x12,0x66, +0x82,0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, +0x39,0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x75,0xdf,0xbe,0x35,0x2e,0x8, 0x6, 0x12, +0x75,0xdf,0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a, +0x1b,0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, +0x2, 0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, +0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, +0x24,0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e,0xd, 0x29, +0x12,0x85,0x21,0xe5,0x2d,0xa, 0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e, +0x35,0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55,0x25,0x12,0xb1,0xb4,0x19,0xa3,0x2, +0xb1,0x7e,0x55,0x27,0x12,0xb1,0xb4,0x19,0xa3,0x2, 0xb2,0x7e,0x37,0x2f,0xab,0xbe, +0x35,0x2e,0x78,0xe, 0x7e,0x35,0x25,0x7a,0x73,0x2f,0xad,0x7e,0x35,0x27,0x7a,0x73, +0x2f,0xae,0x7e,0x37,0x2, 0xaf,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27, +0x12,0x75,0xe3,0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x2, 0xaf,0x1b, +0x38,0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x1, 0x7e,0x12,0x9f,0xb0,0x7c, +0xbf,0xda,0x3b,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0xca,0x3b,0x7c,0x45, +0x7c,0x6, 0x7c,0x57,0x7c,0x1b,0x7e,0x34,0x4, 0xfc,0x7e,0xb3,0x2d,0xa4,0x7e,0xf3, +0x31,0x8f,0x7c,0x31,0x7c,0xe0,0x7c,0x25,0x7c,0xa4,0xbc,0x1, 0x50,0x4, 0x7c,0x30, +0x7c,0xe1,0xbc,0x45,0x50,0x4, 0x7c,0x24,0x7c,0xa5,0xbe,0xb0,0x1, 0x50,0x2, 0x41, +0x81,0x7e,0x90,0x2, 0xac,0x9f,0x7e,0x50,0x2, 0xac,0x53,0x2d,0x24,0x2d,0x23,0xb, +0x28,0x20,0x7e,0x10,0x2, 0xac,0x1e,0x2d,0x4, 0x2d,0x3, 0xb, 0x8, 0x40,0xa, 0x3, +0xb, 0x4, 0x7c,0x31,0x80,0x28,0x7e,0xd0,0x2, 0xac,0xdf,0x7e,0x10,0x2, 0xac,0x13, +0x2d,0x6, 0x12,0xb2,0x85,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, 0xbe,0x24,0x0, +0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x46,0xb, 0x30,0xbc,0xe3, +0x38,0xd4,0x7e,0x50,0x2, 0xac,0x52,0x2d,0x23,0xb, 0x28,0x20,0x7e,0x90,0x2, 0xac, +0x9a,0x2d,0x43,0xb, 0x48,0x40,0xa, 0x12,0xb, 0x14,0x80,0x21,0x7e,0x10,0x2, 0xac, +0x13,0x12,0xb2,0x85,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, 0xbe,0x24,0x0, 0x0, +0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x7, 0xb, 0x30,0xbc,0xa3,0x38, +0xdb,0xd3,0xda,0x3b,0x22,0x2d,0x3, 0xb, 0x8, 0x0, 0x7e,0xf4,0x0, 0x9, 0x7d,0xb2, +0xad,0xbf,0x7e,0xd4,0x0, 0xa, 0xad,0xd0,0xbd,0xdb,0x22,0xca,0x79,0x7c,0xa7,0x7c, +0x8b,0x7e,0xb3,0x31,0x90,0x7a,0xb3,0x26,0xbb,0x7e,0xb3,0x31,0x91,0x7a,0xb3,0x26, +0xbc,0x7e,0x70,0x2, 0xac,0x78,0x9, 0x93,0x2e,0x1b,0x9, 0x83,0x2e,0x1c,0x9f,0x77, +0x1a,0x3a,0x1a,0x79,0x9d,0x73,0x61,0x53,0x7a,0xf1,0x58,0xbe,0xf0,0x0, 0x58,0xe, +0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x58,0x7e,0xb3, +0x26,0xbb,0xbc,0xbf,0x18,0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32, +0x7c,0xb7,0xf5,0x58,0x1a,0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x57,0x80,0x43, +0x85,0x57,0x59,0xe5,0x57,0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x57,0x1a,0x3b,0x1a,0x28, +0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c,0xb7,0xf5,0x59,0x7e,0xb3,0x26,0xbc,0xbe,0xb1, +0x57,0x18,0x10,0x1a,0x38,0xe5,0x57,0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c, +0xb7,0xf5,0x59,0xe5,0x58,0x7e,0x71,0x59,0x12,0x75,0xe3,0x1a,0x26,0x1a,0x24,0x2f, +0x71,0x5, 0x57,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x57,0x1a,0x3b,0xbd,0x32,0x8, +0xaf,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18,0x2, 0x41, +0xc8,0x7f,0x17,0xda,0x79,0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x2e,0x1b, +0x9, 0x65,0x2e,0x1c,0x7e,0x73,0x2f,0xad,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x2f,0xae, +0xbc,0x76,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac, +0x5a,0x49,0x12,0x13,0xc6,0x49,0x32,0x13,0x8e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x13, +0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, 0xa0,0x7e,0xb3,0x31,0x8f,0xbc,0xba,0x38,0xdc, +0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9,0xc5,0xea,0xa9,0x30,0xe5, +0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x67,0x7e,0x73,0x3c,0xd2,0xbe,0x71,0x67, +0x38,0x2, 0xd2,0x1b,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9,0x34,0xe5,0x5, 0xa9,0xc4, +0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9,0x33,0xe5,0x3, 0xa9,0xc3, +0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5,0x3, 0xa9,0xc6,0xcd,0xda, +0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8, +0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50,0x79,0x30,0x0, 0x2, +0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79,0x30,0x0, 0x6, 0x79, +0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79, +0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79, +0x20,0x0, 0xc, 0x22,0xa9,0xd5,0xcb,0x74,0x10,0x12,0x0, 0x66,0x7c,0x7b,0x12,0x2e, +0xe5,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x33, +0xe2,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, 0x33,0xe2,0x79,0x20,0x0, +0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x33,0xe2,0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c, +0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x33,0xe2,0x79,0x30,0x0, 0x86,0x7e,0x34,0x29, +0x90,0x7e,0xf, 0x33,0xe2,0x79,0x30,0x0, 0x8a,0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x33, +0xe2,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, 0x33,0xe2,0x79,0x30,0x0, +0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb, +0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2, +0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, +0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8, +0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8, +0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22, +0xa2,0x0, 0xa9,0x97,0xc1,0xa2,0x0, 0xa9,0x97,0xc2,0x22,0x7e,0x37,0x3c,0xd0,0xb, +0x34,0x7a,0x37,0x3c,0xd0,0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a, +0x37,0x3c,0xd0,0x22,0xca,0x79,0xa9,0xd5,0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x27, +0x43,0x74,0xf, 0x12,0x0, 0x66,0x7c,0xfb,0x74,0xf, 0x7c,0x7f,0x5e,0x70,0xfe,0x12, +0x27,0x43,0x74,0xc, 0x12,0x0, 0x66,0x7c,0xfb,0x54,0x7f,0x68,0x8, 0x74,0xc, 0x7e, +0x70,0xf8,0x12,0x27,0x43,0x90,0x61,0x18,0xe4,0x93,0x7c,0xab,0xbe,0xa0,0x7, 0x38, +0x11,0xa, 0x3a,0x2e,0x34,0x0, 0x3, 0x12,0x47,0x12,0x7c,0xb7,0xa, 0x7b,0xb, 0x75, +0x80,0x1c,0x90,0x61,0x17,0xe4,0x93,0xb4,0x1, 0x14,0xbe,0xa0,0x7, 0x28,0xf, 0xa, +0x3a,0x2e,0x34,0x0, 0x3, 0x12,0x47,0x12,0xa, 0x77,0x2e,0x74,0x0, 0x7, 0x74,0xe, +0x7c,0x7f,0x12,0x27,0x43,0x74,0x7, 0x12,0x0, 0x66,0x7c,0xfb,0x5e,0xf0,0xfb,0x90, +0x60,0x2, 0xe4,0x93,0xa, 0x3b,0x3e,0x34,0x3e,0x34,0x4c,0xf7,0x74,0x7, 0x7c,0x7f, +0x12,0x2e,0xe2,0xda,0x79,0x22,0x6d,0x22,0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38, +0xe9,0x22,0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0x66,0xce,0xb, 0x7a,0x20, +0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c,0xab, +0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, 0x7d, +0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e,0x54,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x1e,0x24, +0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12,0x22, +0x65,0x1e,0x34,0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22,0xca,0x79,0x7c,0xfb, +0x7e,0x8, 0x26,0x55,0x12,0xb6,0xc2,0x7e,0xa3,0x31,0x94,0x7e,0x63,0x31,0x95,0x6c, +0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x31,0xfd,0xbe,0x70,0x1c,0x50,0x11,0xa, 0x27, +0x12,0x77,0xf1,0x7c,0x7b,0x7e,0xb3,0x32,0x1c,0xa, 0x27,0x19,0xb2,0x26,0x55,0xb, +0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73,0x31,0xda,0xbe, +0x70,0x23,0x50,0xa, 0x7e,0x63,0x32,0x1c,0xa, 0x27,0x19,0x62,0x26,0x71,0xb, 0xe0, +0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x26,0x55,0x6d, +0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda, +0x79,0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x17,0x56,0x7c,0xab,0x9f,0x11,0x30, +0x0, 0x22,0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b,0xb0,0x7e, +0x78,0x0, 0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e,0xb, 0x90, +0xbc,0xa9,0x38,0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c,0xfb,0x7e,0x8, +0x26,0x55,0x12,0xb7,0x8d,0x7e,0x8, 0x26,0x5d,0x7e,0x34,0x0, 0x1c,0x74,0x3f,0x12, +0x17,0x56,0xd2,0x0, 0x7e,0x8, 0x31,0xfd,0x7c,0xbf,0x12,0xb6,0xcb,0x7e,0x8, 0x26, +0x55,0x7a,0xf, 0x26,0x79,0x7f,0x1, 0x7a,0x17,0x26,0x7d,0x7d,0x32,0x7a,0x37,0x26, +0x7f,0x7e,0x18,0x26,0x5d,0x7a,0x1f,0x26,0x85,0x6c,0x77,0x80,0x14,0xa, 0x27,0x9, +0x62,0x31,0xfd,0xbe,0x60,0x1c,0x50,0x7, 0x12,0xb7,0x95,0x19,0x51,0x26,0x5d,0xb, +0x70,0xbc,0xf7,0x38,0xe8,0x12,0xb7,0x7a,0xe4,0x12,0xb7,0x82,0xe4,0x12,0xc, 0x9b, +0x6d,0x33,0x7a,0x37,0x26,0x7d,0x7a,0x37,0x26,0x7f,0x12,0xb7,0x7a,0x74,0x1, 0x12, +0xb7,0x82,0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e,0x8, 0x26, +0x79,0x22,0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, 0x26,0x79,0x22,0x7e,0x34,0x0, +0x8, 0xe4,0x2, 0x17,0x56,0xa, 0x27,0x9, 0x52,0x32,0x65,0xa, 0x16,0x22,0x7e,0x8, +0x26,0x55,0x7e,0x34,0x0, 0x1c,0x74,0x3f,0x12,0x17,0x56,0x6c,0x77,0x80,0x14,0xa, +0x27,0x9, 0x62,0x31,0xfd,0xbe,0x60,0x1c,0x50,0x7, 0x12,0xb7,0x95,0x19,0x51,0x26, +0x55,0xb, 0x70,0x7e,0x53,0x31,0x8f,0xbc,0x57,0x38,0xe4,0xa9,0xc6,0xea,0x7e,0x8, +0x26,0x55,0xe4,0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e,0x8, 0x26,0x55,0x2, 0x11,0x38, +0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80,0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e, +0x7b,0x60,0xa, 0x46,0x2e,0x44,0x16,0xeb,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93, +0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e, +0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, +0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a, +0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80,0x61, +0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x14,0x7e,0x44, +0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6, +0x80,0x35,0xbe,0x60,0x1b,0x38,0x19,0x9e,0x60,0xe, 0x7e,0x44,0x0, 0x1, 0x7c,0xb6, +0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x6, 0x80,0x17, +0x9e,0x60,0x1c,0x7e,0x44,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, +0x70,0xbc,0xa7,0x38,0x9b,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x31,0x8f,0x90,0x60, +0x93,0xe4,0x93,0xa, 0xfb,0x7e,0xb3,0x31,0x8e,0xa, 0xeb,0x2d,0xef,0xa, 0xff,0xad, +0xfe,0xa, 0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e,0x8, 0x13, +0x8e,0x6c,0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x33,0xfb,0x2d, +0x3d,0xb, 0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, 0x5a,0x30, +0x9d,0x3d,0x59,0x32,0x13,0xc6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, 0x7d,0x5e, +0x3e,0x54,0x7e,0xf, 0x33,0xfb,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea,0x2d,0xef, +0x3e,0xe4,0x7e,0x1f,0x33,0xfb,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, 0xac,0x7a, +0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x17,0x88,0x7d,0xc3, +0xbd,0x4c,0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34,0xda,0xf8, +0x22,0x7e,0x27,0x2f,0xc4,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64,0x30,0x5, 0x2e, +0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, 0x0, 0xbd,0x2, 0x8, +0x11,0x7e,0xb3,0x2d,0x17,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x5, 0xf8, +0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, 0xf8,0x30,0x7, +0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, 0x4, 0x7e,0xbd,0x2, +0x8, 0x11,0x7e,0xb3,0x2d,0x17,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x6, +0x76,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x6, 0x76,0xb, +0xa0,0x7e,0xb3,0x31,0x95,0xa, 0xb, 0x7e,0xb3,0x31,0x94,0xa, 0x4b,0x2d,0x40,0xa, +0xa, 0xbd,0x4, 0x48,0x88,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33,0x19,0xb3,0x2e, +0x93,0xb, 0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0x4e,0x81,0xb, 0x24,0xa, 0x33,0xbd, +0x32,0x48,0xe7,0xe4,0x7a,0xb3,0x2f,0xa5,0x7a,0xb3,0x2f,0xa6,0x6d,0x33,0x7a,0x37, +0x2f,0xa7,0x7a,0x37,0x2f,0xa9,0x7a,0x37,0x2f,0xab,0x7a,0x37,0x2f,0xaf,0x7e,0xd4, +0x26,0x57,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x13,0x8a,0x7a,0x37,0x26,0x97, +0x7d,0x3d,0x7a,0x37,0x26,0x9b,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x26,0x99,0x7e,0x73, +0x31,0x8e,0x7a,0x73,0x26,0x94,0x7e,0x73,0x31,0x8f,0x7a,0x73,0x26,0x93,0x7e,0x37, +0x31,0x7d,0x7a,0x37,0x26,0x9d,0x7e,0x37,0x31,0x7f,0x7a,0x37,0x26,0x9f,0x7e,0x37, +0x31,0x81,0x7a,0x37,0x26,0xa1,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x26,0x95,0x7e,0x73, +0x3, 0xfe,0x7a,0x73,0x26,0x96,0x7e,0x8, 0x26,0x93,0x7e,0x18,0x26,0xa3,0x12,0x8, +0x0, 0x7e,0x73,0x26,0xa3,0x7a,0x73,0x2f,0xa5,0x7e,0x73,0x26,0xa4,0x7a,0x73,0x2f, +0xa6,0x7e,0x37,0x26,0xa5,0x7a,0x37,0x2f,0xa7,0x7e,0x37,0x26,0xa7,0x7a,0x37,0x2f, +0xa9,0x7e,0x37,0x26,0xad,0x7a,0x37,0x2f,0xab,0x7e,0x37,0x26,0xaf,0x7d,0x23,0x7a, +0x53,0x2f,0xad,0xa, 0x36,0x7a,0x73,0x2f,0xae,0x7e,0x37,0x26,0xa9,0x7a,0x37,0x2f, +0xaf,0x7e,0x37,0x26,0xab,0x7d,0x23,0x7a,0x53,0x2f,0xb1,0xa, 0x36,0x7a,0x73,0x2f, +0xb2,0x6c,0x33,0x80,0x20,0x7c,0xb3,0x7e,0x70,0x1, 0x12,0x74,0x94,0x74,0x2, 0xac, +0xb3,0x49,0x45,0x15,0x9e,0xa, 0x38,0x7c,0x27,0x19,0x25,0x2e,0x1b,0x7c,0x29,0x19, +0x25,0x2e,0x1c,0xb, 0x30,0x7e,0x23,0x2f,0xa5,0xbc,0x23,0x38,0xd8,0x6c,0x33,0x80, +0x1b,0x74,0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27, +0x19,0x25,0x2e,0x57,0x7c,0x29,0x19,0x25,0x2e,0x58,0xb, 0x30,0x7e,0x23,0x2f,0xa6, +0xbc,0x23,0x38,0xdd,0x22,0x90,0x60,0x50,0xe4,0x93,0x7c,0xab,0x90,0x60,0x51,0x12, +0xbb,0xde,0xa, 0x3b,0xa, 0xda,0x2d,0xd3,0x3e,0xd4,0x7e,0xb3,0x31,0x24,0xb4,0x1, +0xc, 0x7e,0xb3,0x31,0x23,0xbe,0xb0,0x1, 0x68,0x3, 0x75,0x68,0x1, 0xe5,0x68,0x60, +0x43,0xca,0xc9,0x7e,0x18,0xd, 0xc8,0x7e,0x8, 0x20,0x19,0x12,0x17,0x31,0x1b,0xfd, +0xca,0xd9,0x7e,0x18,0x4, 0xfc,0x7e,0x8, 0x25,0xd7,0x12,0x17,0x31,0x1b,0xfd,0xca, +0xd9,0x7e,0x18,0x5, 0x7a,0x7e,0x8, 0x1f,0x77,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34, +0x0, 0x24,0xca,0x39,0x7e,0x18,0x1f,0x53,0x7e,0x8, 0x1f,0xf5,0x12,0x17,0x31,0x1b, +0xfd,0x75,0x68,0x0, 0x22,0x12,0xbb,0xe9,0x12,0x47,0x1b,0x12,0xbb,0x5, 0x12,0xbb, +0x88,0x7e,0x34,0xd, 0xc8,0x2, 0x29,0x9b,0x90,0x60,0x51,0xe4,0x93,0x7c,0xab,0x90, +0x60,0x50,0x12,0xbb,0xde,0xa, 0x3a,0xa, 0xdb,0x2d,0xd3,0x3e,0xd4,0xca,0xc9,0x7e, +0x18,0x20,0x19,0x7e,0x8, 0xd, 0xc8,0x12,0x17,0x31,0x1b,0xfd,0xca,0xd9,0x7e,0x18, +0x25,0xd7,0x7e,0x8, 0x4, 0xfc,0x12,0x17,0x31,0x1b,0xfd,0xca,0xd9,0x7e,0x18,0x1f, +0x77,0x7e,0x8, 0x5, 0x7a,0x12,0x17,0x31,0x1b,0xfd,0x7e,0x34,0x0, 0x24,0xca,0x39, +0x7e,0x18,0x1f,0xf5,0x7e,0x8, 0x1f,0x53,0x12,0x17,0x31,0x1b,0xfd,0x22,0xe4,0x93, +0x7c,0x9b,0xac,0x9a,0x7d,0xc4,0x3e,0xc4,0x22,0x7e,0xa3,0x31,0x8f,0x7e,0x73,0x2f, +0xa5,0x6c,0x66,0x80,0x27,0x7e,0x30,0x2, 0xac,0x36,0x9, 0x51,0x2e,0x1b,0x9, 0x41, +0x2e,0x1c,0x7c,0x15,0xac,0x1a,0xa, 0x14,0x2d,0x1, 0x3e,0x4, 0x2e,0x4, 0xd, 0xc8, +0xb, 0x8, 0x10,0x2e,0x14,0x27,0x10,0x1b,0x8, 0x10,0xb, 0x60,0xbc,0x76,0x38,0xd5, +0x22,0x7e,0x8, 0x1f,0x34,0x7e,0x34,0x0, 0x1f,0xe4,0x2, 0x17,0x56,0x7e,0x8, 0x1f, +0x53,0x7e,0x34,0x0, 0x24,0xe4,0x2, 0x17,0x56,0x74,0x1, 0x7a,0xb3,0x32,0x22,0x7a, +0xb3,0x32,0x3e,0x22,0x7e,0x18,0x5, 0xf8,0x7a,0x1f,0x6, 0xf4,0x22,0xa, 0x4a,0x7f, +0x10,0x2d,0x34,0x7a,0x1b,0xb0,0x22,0x9, 0x75,0x2d,0x56,0x7a,0x73,0x32,0x40,0x22, +0x9, 0x75,0x2d,0x57,0x7a,0x73,0x32,0x41,0x22,0x9, 0x75,0x2d,0x55,0x7a,0x73,0x32, +0x35,0x22,0x7e,0x8, 0x39,0xf0,0x7e,0x34,0x0, 0x6, 0x74,0xff,0x2, 0x17,0x56,0x74, +0x2, 0xac,0xbf,0x9, 0xd5,0x2e,0x1b,0x9, 0xe5,0x2e,0x1c,0x22,0xa, 0x47,0x7f,0x70, +0x2d,0xf4,0x7e,0x7b,0x60,0xbc,0x6b,0x22,0x2e,0x14,0x35,0x69,0x6d,0x0, 0x7e,0x18, +0x37,0x99,0x22,0x2e,0x14,0x34,0x89,0x6d,0x0, 0x7e,0x18,0x34,0x0, 0x22,0x7a,0x37, +0x31,0x70,0x7e,0x34,0x61,0x59,0x22,0x7e,0x34,0x61,0x43,0x7e,0x24,0x0, 0xff,0x22, +0x90,0x60,0xaa,0xe4,0x93,0xbe,0xb0,0x1, 0x22,0x9, 0x75,0x2d,0x54,0x7a,0x73,0x32, +0x30,0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x2d,0x54,0x22,0x7e,0x8, 0x0, 0x25,0x7e, +0x18,0x0, 0x24,0x22,0xa, 0x2b,0x1b,0x24,0xa, 0x3d,0xbd,0x32,0x22,0x7e,0x73,0x3b, +0xee,0x7a,0x73,0x32,0x41,0x22,0x7e,0xb3,0x3c,0x11,0x7e,0x34,0x0, 0x4, 0x22,0x5e, +0x54,0x0, 0xf, 0x1b,0x1a,0x50,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x10,0x22,0x7e, +0x30,0x2, 0xac,0x3e,0x2d,0x31,0x22,0x7e,0x73,0x31,0x23,0xbe,0x70,0x0, 0x22,0x90, +0x60,0xa7,0xe4,0x93,0x7c,0xab,0x22,0xff,0xbd,0x28,0x42,0xd7,0xa2,0x5d,0x10,0x3b, diff --git a/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V08_D01_20170809_app.i b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V08_D01_20170809_app.i new file mode 100644 index 0000000000000..425ca819dd8df --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V08_D01_20170809_app.i @@ -0,0 +1,3279 @@ +0x2, 0x1f,0xd2,0x2, 0xc0,0x36,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x42,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0xc0,0xa, 0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x80,0x7e,0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x32,0x2, 0x80,0x9a,0x2, 0x2a,0x27,0x22,0x32,0x2, 0x0, 0x4a,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x3f,0x65,0xff,0xff,0x2, 0x0, 0x5a,0xa2,0x8, +0x22,0xff,0xff,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xd, 0x7e,0xf, 0x33,0xcf, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x33,0xdf,0x7e,0x73,0x33,0xdf,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xc, 0x80,0x2, 0xc2,0xc, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x6b,0xcb,0x7e,0x1f,0x33,0xcf,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x33,0xcf,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x33,0xd3,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x33,0xdb,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x33,0xd9,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x39,0xee,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x64,0x30,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x1e, +0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0xe2,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0xb2,0x61,0x3f,0x7e,0x34,0x1d,0x96,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x1d,0xc6,0x61,0x3f,0x7e,0x34,0x1e,0xa, 0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d, +0xf1,0x61,0x3f,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x1e,0x69,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x1e,0x6a,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x4, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x4, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xcf,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x33, +0xcf,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x33,0xcf,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x20,0xe8,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x39,0xf2,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x39,0xf2,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x39,0xf2,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x39,0xee,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x33,0xc7,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x39, +0xee,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x33,0xc7,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x39,0xee,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x39,0xee,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x39,0xee,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x33,0xcf,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x33,0xcf,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x1e,0xb9,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x33,0xcf,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x39,0xf2,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xf2,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x39,0xf2,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0x2, 0x45,0xd2,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x39,0xf2, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x39,0xf2, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x39,0xf2,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39,0xea,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39, +0xea,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x39,0xea,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x39,0xea,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x33,0xc7,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x33,0xc7,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x33,0xc7,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x33,0xc7,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x33,0xcf,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x33,0xcf,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x33, +0xcf,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x33,0xcf,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x33,0xcf,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x33,0xcf,0x69,0x40,0x0, 0x22,0x30,0x4, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x33,0xcf,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x33,0xcf,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x33, +0xcf,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x33,0xcf, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x33,0xcf,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x33,0xcf,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x33,0xcf,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x33,0xcf,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1e,0xb9,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x1e,0xb9,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xf2, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x39,0xea,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x39,0xea,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x39,0xea,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1c,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x39,0xf2, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x39,0xf2,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x39, +0xf2,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x33,0xcf,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x33,0xcf,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x33,0xcf,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x33,0xcf, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x33,0xcf,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x33,0xcf,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x39,0xf2,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x39,0xf2,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x39,0xf2,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x39,0xf2,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xee,0x79,0x30, +0x0, 0xe, 0xc2,0x1b,0xe4,0x7a,0xb3,0x39,0xe9,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x33,0xc7,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xc7,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x39, +0xee,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x39, +0xee,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x39,0xf2,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x39,0xf2,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x39,0xf2,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x39, +0xf2,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x39,0xf2,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1c,0x7e,0xf, 0x39,0xf2,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x1f,0x58,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x1e,0x12,0x1f,0x5, 0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x33,0xcf,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1b,0x7e,0xf, 0x39,0xee,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x39,0xe9,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x39,0xee,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x6b,0xcb,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x33,0xc7,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x33,0xc7,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xcf,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xd, 0xe4,0x7a,0xb3,0x33,0xdf,0x7e,0x1f,0x33,0xc7, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xea,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xea,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x39,0xea,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x33,0xcf,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x33,0xcf,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x39,0xea,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x39,0xea,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x39,0xf2,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x20,0x99,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x20,0x9a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x33,0xc7,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x33,0xc7,0x1b,0x1a,0x10,0x7e, +0x1f,0x33,0xc7,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x33,0xcf,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x39,0xee,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x33,0xc7,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x33,0xc7,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x33, +0xcf,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x33,0xcf,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x4, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x33,0xcf,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x33,0xc7,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x1f,0x7, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x1f,0x7, 0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x39,0xfc,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x6, 0xc2,0x7, 0x75,0x1d,0x0, 0xc2,0xe, 0xc2,0xf, 0xc2,0x11,0x75,0x1e, +0x0, 0x75,0x1f,0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x1b,0x0, 0x75,0x1c,0x0, 0xc2,0x13, +0x75,0x5e,0x0, 0xc2,0x15,0x75,0x5f,0x0, 0xc2,0x16,0xc2,0x17,0xc2,0x18,0x75,0x60, +0x0, 0xc2,0xa, 0x75,0x61,0x64,0xc2,0x19,0xc2,0x1a,0x75,0x62,0x0, 0xd2,0x0, 0xd2, +0x1, 0xd2,0x2, 0xd2,0x1b,0xc2,0xc, 0xd2,0xd, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x21, +0x2a,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44, +0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2, +0x80,0xdf,0x2, 0x38,0x35,0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd, +0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, +0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, +0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94, +0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31, +0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11, +0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, +0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d, +0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44, +0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0x32,0x1, 0x19,0x1, 0x0, 0x2, +0xf8,0x4, 0xe7,0x5, 0xce,0x6, 0xc2,0x7, 0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff, +0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, +0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x34,0x8c,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x39,0xf8,0x1, 0x0, 0x1, 0x25,0xf6,0x1, 0x0, 0x1, 0x38,0xaf, +0x0, 0x0, 0x2, 0x39,0x1, 0x0, 0x0, 0x0, 0x2, 0x39,0x3, 0x0, 0x0, 0x0, 0x1, 0x39, +0x5, 0x0, 0x0, 0x1, 0x3, 0x9a,0xff,0x0, 0x1, 0x39,0xf9,0x0, 0x0, 0x1, 0x39,0xfa, +0x0, 0x0, 0x2, 0x36,0x92,0x0, 0x0, 0x0, 0x1, 0x36,0xb5,0x0, 0x0, 0x1, 0x37,0x2e, +0x0, 0x0, 0x1, 0x37,0x2f,0x0, 0x0, 0x1, 0x37,0x30,0x0, 0x0, 0x3c,0x33,0x4c,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x33,0xc4,0x0, +0x0, 0x1, 0x33,0xc5,0x0, 0x0, 0x1, 0x33,0xc6,0x0, 0x0, 0x1, 0x37,0xd2,0x1, 0x0, +0x2, 0x37,0xd5,0x0, 0x0, 0x0, 0x1, 0x0, 0x63,0x0, 0x0, 0x1, 0x0, 0x64,0x0, 0x0, +0x1, 0x0, 0x65,0x0, 0x0, 0x1, 0x37,0xd9,0x1, 0x0, 0x1, 0x38,0x53,0x0, 0x0, 0x1, +0x39,0xfb,0x0, 0x0, 0x6, 0x34,0x49,0x3f,0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, 0x34, +0x4f,0x24,0x0, 0x1, 0x33,0xfb,0x0, 0x0, 0x1, 0x33,0xfc,0x0, 0x0, 0x1, 0x33,0xfd, +0x0, 0x0, 0x1, 0x33,0xfe,0x0, 0x0, 0x1, 0x33,0xff,0x0, 0x0, 0x1, 0x2f,0xa9,0x0, +0x0, 0x1, 0x33,0x46,0x0, 0x0, 0x1, 0x2, 0x87,0x0, 0x0, 0x2, 0x2, 0xa8,0x0, 0x0, +0x0, 0x4, 0x38,0x54,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xfa,0x0, 0x0, 0x1, 0x3, +0xfb,0x0, 0x0, 0x2, 0x3, 0xfc,0x0, 0x0, 0x0, 0x1, 0x3, 0xfe,0x64,0x0, 0x1, 0x3, +0xff,0x0, 0x0, 0x1, 0x39,0xfc,0x0, 0x0, 0x1, 0x39,0xf6,0x0, 0x0, 0x1, 0x39,0xf7, +0x0, 0x0, 0x2, 0x2b,0xb9,0x2b,0xbf,0x0, 0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8, +0x0, 0x0, 0x1, 0x39,0xd4,0x0, 0x0, 0x1, 0x39,0x52,0xff,0x0, 0x1, 0x39,0x53,0x0, +0x0, 0x1, 0x39,0x54,0x0, 0x0, 0x1, 0x39,0x55,0x40,0x0, 0x1, 0x39,0x56,0x40,0x0, +0x4, 0x39,0xea,0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x39,0xee,0x0, 0x0, 0x64,0x0, 0x0, +0x4, 0x33,0xc7,0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x33,0xcb,0x0, 0x0, 0x68,0xc0,0x0, +0x4, 0x33,0xcf,0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x33,0xe0,0x0, 0x0, 0x40,0x0, 0x0, +0x4, 0x39,0xf2,0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x3, 0xe8,0x0, 0xc, 0x1, 0xf4,0x3, +0x20,0x0, 0xa, 0x1, 0x4a,0x2, 0xbc,0x0, 0x9, 0x0, 0xc8,0x1, 0xf4,0x0, 0x6, 0x0, +0x3c,0x1, 0x2c,0x0, 0x6, 0x0, 0x3c,0x0, 0x64,0x0, 0x6, 0x0, 0x3c,0x0, 0x50,0x0, +0x6, 0x0, 0x0, 0x0, 0xe, 0x1c,0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, +0x0, 0x0, 0x1e,0x12,0x49,0x9b,0x12,0x5e,0xe1,0x12,0x38,0xae,0x12,0x28,0x86,0x2, +0x23,0x12,0x12,0x23,0x23,0x7e,0xb3,0x2b,0xf, 0x12,0xa5,0xf9,0x74,0x1, 0x7a,0xb3, +0x37,0xdd,0x22,0x12,0xa7,0x7a,0x74,0x1, 0x7a,0xb3,0x37,0xd9,0x22,0x7e,0x34,0x60, +0xa3,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x62,0xd9,0x12,0x38,0x57,0x12,0x49,0x9b, +0x12,0x5e,0xda,0x12,0xcc,0x30,0x12,0x38,0xae,0x12,0x28,0x86,0x12,0x5e,0xc5,0x2, +0x23,0x12,0x7e,0x34,0x61,0x4f,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x7a,0x37,0x2a, +0x5a,0x7e,0x34,0x61,0x51,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x7a,0x37,0x2a,0x5c, +0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x22,0x7e,0x34,0x61,0x55, +0x12,0x23,0x74,0x7a,0x37,0x28,0x95,0x7e,0x34,0x61,0xc0,0x12,0x23,0x74,0x7a,0x37, +0x28,0x99,0x7e,0x34,0x61,0xbe,0x12,0x23,0x74,0x7a,0x37,0x28,0x97,0x7e,0x34,0x62, +0x18,0x12,0x23,0x74,0x7a,0x37,0x28,0x9b,0x7e,0x34,0x61,0xc2,0x12,0x23,0x74,0x7a, +0x37,0x28,0x9d,0x7e,0x34,0x61,0xc4,0x12,0x23,0x74,0x7a,0x37,0x28,0x9f,0x7e,0x34, +0x61,0xc6,0x12,0x23,0x74,0x12,0x87,0xda,0x12,0x23,0x74,0x7a,0x37,0x28,0xa3,0x90, +0x61,0xca,0xe4,0x93,0x7a,0xb3,0x28,0xa5,0xe4,0x7a,0xb3,0x28,0xa8,0x12,0xcc,0x7b, +0x3e,0x34,0x7e,0x8, 0x25,0xf7,0xe4,0x2, 0x20,0xe8,0x12,0x25,0xa2,0x7e,0xb3,0x37, +0xe4,0xb4,0x1, 0x16,0x7e,0x34,0x62,0x3a,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5a,0x7e, +0x34,0x62,0x3c,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5c,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x37,0x7e,0x34,0x62,0x44,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x46, +0x12,0x23,0x74,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x62,0x48,0x12,0x23,0x74,0x7a,0x37, +0x2a,0x4f,0x7e,0x34,0x62,0x4a,0x12,0x23,0x74,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62, +0x4c,0x12,0x23,0x74,0x7a,0x37,0x2a,0x53,0x7e,0xb3,0x2a,0x2, 0x70,0x21,0x7e,0x27, +0x2a,0x5a,0x7d,0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12,0x25,0x12,0xbe, +0x34,0x0, 0x28,0x28,0x4, 0x7e,0x34,0x0, 0x28,0x2d,0x32,0x7a,0x37,0x2a,0x5a,0x22, +0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69,0x22,0x0, 0x2, +0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34,0x0, 0x20,0x7e,0x8, 0x0, +0x24,0x7e,0x24,0x0, 0x6, 0x12,0x64,0x30,0x7e,0x34,0x61,0x4f,0x12,0x23,0x74,0x1e, +0x34,0x1e,0x34,0x7a,0x73,0x3, 0x9b,0x7e,0x34,0x61,0x51,0x12,0x23,0x74,0xe, 0x34, +0xe, 0x34,0x7a,0x73,0x3, 0x9c,0x7e,0x34,0x61,0x55,0x12,0x23,0x74,0x12,0x25,0x12, +0x7a,0x73,0x3, 0x9d,0x7e,0x34,0x61,0x59,0x12,0x23,0x74,0x12,0x25,0x12,0x7a,0x73, +0x3, 0x9e,0x7e,0x34,0x61,0x5b,0x12,0x23,0x74,0x12,0x25,0x12,0x7a,0x73,0x3, 0x9f, +0x7e,0x34,0x61,0x5d,0x12,0x23,0x74,0x12,0x25,0x12,0x7a,0x73,0x3, 0xa0,0x7e,0x34, +0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x3, 0xa1, +0x12,0x20,0xc3,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x3, 0xcc,0xe5,0x28,0x7a,0xb3,0x3, +0xbb,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x22,0x90,0x60,0x99,0xe4,0x93, +0x7a,0xb3,0x2a,0x4d,0x90,0x60,0x9e,0xe4,0x93,0x7a,0xb3,0x2a,0x4e,0x7e,0x34,0x61, +0x55,0x12,0x23,0x74,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12,0x23,0x74,0x7a, +0x37,0x2a,0x51,0x7e,0x14,0x61,0x5b,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x7a,0x27, +0x2a,0x53,0x7a,0x37,0x2a,0x55,0x90,0x60,0x9d,0xe4,0x93,0x7a,0xb3,0x2a,0x59,0x12, +0x23,0x52,0x12,0xcc,0x66,0x7e,0x34,0x62,0x18,0x12,0x23,0x74,0x7a,0x37,0x2a,0x60, +0x90,0x60,0x9f,0xe4,0x93,0x7a,0xb3,0x2a,0x64,0x90,0x60,0xa0,0xe4,0x93,0x7a,0xb3, +0x2a,0x65,0x7e,0x34,0x60,0xa1,0x12,0x23,0x74,0x7a,0x37,0x2a,0x66,0x7e,0x34,0x61, +0x5d,0x12,0x23,0x74,0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3,0x2a,0x6b,0x7a,0xb3,0x16, +0x92,0x22,0x12,0x23,0x52,0x12,0xcc,0x66,0x7e,0x34,0x61,0x55,0x12,0x23,0x74,0x7a, +0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12,0x23,0x74,0x7a,0x37,0x2a,0x51,0x7e,0x34, +0x61,0x5b,0x12,0x23,0x74,0x7a,0x37,0x2a,0x53,0x22,0x7e,0x34,0x62,0x4e,0x12,0x23, +0x74,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x50,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5c, +0x7e,0x34,0x62,0x52,0x12,0x23,0x74,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x62,0x54,0x12, +0x23,0x74,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62,0x56,0x12,0x23,0x74,0x7a,0x37,0x2a, +0x53,0x22,0xca,0xf8,0x7e,0xf3,0x38,0xb4,0xbe,0xf0,0x5, 0x78,0xb, 0x74,0x1, 0x7a, +0xb3,0x38,0xb4,0x12,0x0, 0x9, 0x80,0x52,0xbe,0xf0,0x4, 0x78,0x13,0x12,0xcc,0x19, +0x12,0x23,0x74,0x12,0x26,0x77,0xe4,0x7a,0xb3,0x2b,0x2, 0x12,0x6a,0x92,0x80,0x3a, +0xbe,0xf0,0x6, 0x78,0x19,0x12,0xcc,0x19,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x55, +0xcf,0xe4,0x7a,0xb3,0x2b,0x1e,0x12,0x5f,0x1f,0x12,0xcc,0xc2,0x80,0x1c,0xbe,0xf0, +0x7, 0x78,0x1d,0x12,0xcc,0x19,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x6f,0xca,0x50, +0xfb,0x12,0x87,0x5c,0x12,0x5e,0xea,0x12,0x28,0x86,0x74,0x2, 0x7a,0xb3,0x38,0xb4, +0xda,0xf8,0x22,0x7e,0x34,0x3, 0xe8,0x6d,0x22,0x7a,0x27,0x34,0x38,0x7a,0x37,0x34, +0x3a,0x22,0x7e,0xb3,0x3, 0xc0,0x14,0x68,0x5d,0x14,0x78,0x2, 0xe1,0x29,0x14,0x68, +0x6d,0x24,0x3, 0x68,0x2, 0xe1,0x21,0x12,0xcc,0xdc,0x38,0x8, 0x30,0x12,0xf, 0x12, +0x8f,0xa0,0x68,0xa, 0x12,0x59,0xa8,0xe4,0x7a,0xb3,0x39,0x99,0x80,0x7b,0x7e,0xb3, +0x3, 0xa1,0x30,0xe0,0x74,0x7e,0x73,0x3, 0xa2,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad, +0x32,0x7e,0xb3,0x3, 0xeb,0xb4,0x1, 0xb, 0x7e,0x34,0x62,0x6a,0x12,0x23,0x74,0x2e, +0x34,0x4, 0x0, 0xbe,0x37,0x39,0x97,0x50,0x50,0x12,0x59,0xa8,0x12,0x5e,0xc, 0xe4, +0x7a,0xb3,0x39,0x9b,0x80,0x43,0x12,0xcc,0xdc,0x28,0x39,0xe4,0x7a,0xb3,0x3, 0xc0, +0x7e,0xb3,0x39,0x99,0xb4,0x1, 0x3, 0x12,0x5e,0xc, 0xd2,0x1a,0x80,0x26,0x74,0xff, +0x7a,0xb3,0x3, 0x9a,0x7e,0x34,0x60,0xa5,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x66, +0xa5,0x12,0x23,0x2d,0xe4,0x7a,0xb3,0x3, 0xc0,0x7a,0xb3,0x3, 0xff,0xd2,0x1a,0x80, +0x8, 0x12,0x5e,0xc, 0xe4,0x7a,0xb3,0x3, 0xff,0x12,0x65,0xc2,0x2, 0x27,0x2f,0xca, +0x3b,0x7e,0xb3,0x3, 0xc0,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x28,0x78,0x6c,0xcc,0x6c, +0xdd,0x7e,0xb3,0x3, 0xeb,0xb4,0x1, 0xc, 0x90,0x61,0x62,0xe4,0x93,0x7c,0xeb,0x90, +0x61,0x64,0x80,0xa, 0x90,0x61,0x61,0xe4,0x93,0x7c,0xeb,0x90,0x61,0x63,0xe4,0x93, +0x7c,0xfb,0x12,0x8b,0x56,0x7d,0xf3,0x12,0x6f,0xca,0x50,0xfb,0x74,0x1, 0x7a,0xb3, +0x39,0x9a,0x12,0x48,0x34,0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x67,0x6e, +0x12,0xcc,0xb1,0x7e,0xe7,0x2b,0xd, 0x7a,0xe5,0x25,0x7e,0xb3,0x2a,0xfa,0xf5,0x24, +0x74,0x4, 0x7a,0xb3,0x2a,0xfa,0x7e,0xe7,0x2b,0xd, 0x5e,0xe4,0x0, 0x3f,0x7a,0xe7, +0x2b,0xd, 0x7e,0xb3,0x2a,0xfa,0x12,0xc3,0x5d,0x7c,0x7b,0x74,0x8, 0xac,0x7b,0x7e, +0x24,0x0, 0x4, 0x12,0x1e,0xb9,0x7d,0x23,0x7d,0x3f,0x12,0x25,0x12,0xad,0x32,0x7a, +0x37,0x2b,0x7, 0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0x8f,0xbf,0x2, 0x28,0x58, +0x12,0x26,0x73,0x30,0xf, 0x3, 0x2, 0x28,0x5f,0x7c,0xbe,0x12,0x90,0x42,0x12,0x69, +0xb5,0x80,0xf, 0x80,0x7, 0x12,0x66,0x35,0xe4,0x12,0x66,0x3c,0x20,0x93,0xf6,0x12, +0x65,0x8d,0x30,0x1b,0xf7,0x30,0x1a,0xf4,0xd2,0x4, 0x12,0x65,0x7c,0xe4,0x12,0x13, +0xde,0xb, 0xc0,0x12,0x89,0x26,0x12,0x90,0x4c,0x7e,0xa3,0x39,0x99,0x4c,0xaa,0x78, +0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x9a,0x4c,0xaa,0x68,0xb, 0x7e,0xb3,0x3, 0xeb,0x70, +0x5, 0xe4,0x7a,0xb3,0x39,0x99,0x12,0x28,0x7b,0x78,0x18,0x7e,0xb3,0x39,0x99,0x60, +0x12,0xe4,0x7a,0xb3,0x39,0x99,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a,0x3, 0x7e,0xd0, +0x1, 0x80,0x1c,0x12,0x28,0x7b,0x68,0x10,0x7e,0xb3,0x39,0x99,0x70,0xa, 0x7e,0xd0, +0x1, 0xe4,0x7a,0xb3,0x3, 0xc0,0x80,0x7, 0xbc,0xfc,0x28,0x3, 0x2, 0x27,0xd0,0xe4, +0x7a,0xb3,0x2b,0x4, 0x7e,0x35,0x25,0x7a,0x37,0x2b,0xd, 0xe5,0x24,0x7a,0xb3,0x2a, +0xfa,0x4c,0xdd,0x68,0x3, 0x12,0x28,0x86,0xda,0x3b,0x22,0x7e,0x73,0x39,0xe9,0xa, +0x37,0x5e,0x34,0x0, 0x2, 0x22,0xe4,0x7a,0xb3,0x33,0xe6,0x7a,0xb3,0x33,0xe5,0x12, +0x6a,0xf2,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x33,0xe6,0x22, +0xca,0x3b,0x12,0x6f,0xca,0x50,0xfb,0x7e,0xf3,0x2b,0xf, 0x7c,0xbf,0x12,0xaa,0xd9, +0x12,0xab,0x6a,0x7e,0xb3,0x2b,0x1f,0xf5,0x28,0x7e,0xc3,0x2b,0x20,0x7e,0xb3,0x3, +0xc2,0xb4,0x1, 0xf, 0x12,0xa6,0xff,0x7e,0xb3,0x16,0x91,0x70,0x6, 0x12,0x28,0x86, +0xc3,0x21,0x9c,0x12,0x29,0x9f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, +0x4, 0x7e,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x29,0x9f,0x3e,0x34,0xca,0x39,0x7e,0x18, +0x7, 0x7a,0x7e,0x8, 0x4, 0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x3, 0xc2,0xb4, +0x3, 0x7, 0x12,0xa4,0x32,0x7a,0x37,0x38,0xf7,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12, +0x5e,0xe1,0x12,0xa4,0x1a,0x12,0xae,0x69,0xe4,0x12,0x13,0xde,0x12,0x28,0x86,0x7e, +0x8, 0x4, 0x7e,0x7a,0xd, 0x29,0x7e,0x18,0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0x6b, +0x63,0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29,0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0, +0x12,0x6b,0x63,0x7e,0xd3,0x2b,0x1f,0x7e,0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b, +0x1f,0x7a,0xc3,0x2b,0x20,0x7e,0x34,0x8, 0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d, +0x10,0x12,0x79,0x34,0x7a,0xd3,0x2b,0x1f,0x7a,0xe3,0x2b,0x20,0x7c,0xbf,0x12,0xaa, +0x7f,0x12,0xa2,0xf3,0x7e,0xb3,0x3, 0xff,0x4, 0x7a,0xb3,0x3, 0xff,0x7e,0x73,0x3, +0xff,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64,0x7a,0xb3,0x3, 0xff,0x7e,0xb3,0x16,0x90, +0x60,0x9, 0x7e,0xb3,0x16,0x91,0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e, +0x73,0x2a,0x74,0xa, 0x27,0x7e,0x73,0x2a,0x73,0xa, 0x37,0x2d,0x32,0x22,0x12,0x54, +0xc9,0x7e,0xb3,0x3, 0xc2,0xb4,0x3, 0x69,0x12,0xc1,0xb6,0x12,0x26,0x73,0x12,0x4b, +0x51,0x7e,0xb3,0x38,0xb0,0x30,0xe7,0xe9,0x12,0x28,0xa0,0x12,0x29,0x9f,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, 0xfc,0x12,0x20,0xc3,0x1b,0xfd,0x12, +0x29,0x9f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x7e,0x7e,0x8, 0x5, 0x7a,0x12,0x20, +0xc3,0x1b,0xfd,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x15,0x12,0x6e,0x5f,0x12,0x6f,0xa, +0x12,0x45,0xb9,0x12,0x84,0x67,0x12,0x36,0xfe,0x12,0x2a,0x31,0x12,0x58,0xc4,0x12, +0x54,0xfb,0x12,0xaf,0x58,0x7e,0xb3,0x38,0xb0,0x54,0x7f,0x7a,0xb3,0x38,0xb0,0x80, +0x90,0x12,0x6f,0xd5,0x2, 0x0, 0x46,0xe4,0x7a,0xb3,0x2b,0x2, 0x7a,0xb3,0x2b,0x1e, +0x22,0x12,0x8b,0xc1,0x12,0x2c,0x2b,0x12,0x2c,0x2b,0x12,0x2f,0xde,0x12,0x36,0x67, +0x12,0x2e,0x78,0x12,0x2c,0x2b,0x12,0xb8,0x6b,0x12,0x2c,0x2b,0x12,0x9f,0x65,0x12, +0x2c,0x2b,0x2, 0x2a,0x55,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4, +0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x33,0x88,0x7e,0x8, 0x33,0x4c,0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0xf3,0x28,0x84,0xa, 0xcf,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e, +0x8, 0x1f,0x34,0x12,0x20,0xc3,0x1b,0xfd,0x6c,0x88,0x6c,0xee,0x61,0x29,0x7e,0xc4, +0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99,0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f, +0x34,0xbe,0xb0,0xff,0x68,0x3d,0x7c,0xb9,0x12,0x2e,0x5f,0x60,0x36,0x74,0x2, 0xac, +0xb9,0x9, 0x75,0x1f,0x35,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x33,0x89,0x12, +0x2c,0x73,0x7d,0x13,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, +0xac,0xbe,0x9, 0x75,0x33,0x88,0x12,0x2c,0x73,0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d, +0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9,0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70, +0x2, 0xac,0x7c,0x9, 0xb3,0x1f,0x34,0x9, 0x73,0x1f,0x35,0x12,0x30,0xb6,0xbe,0x37, +0x2a,0x5a,0x48,0x23,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac, +0xbd,0x19,0x55,0x1f,0x70,0x9, 0x53,0x1f,0x35,0x19,0x55,0x1f,0x71,0x74,0xff,0x19, +0xb3,0x1f,0x34,0xb, 0x80,0xb, 0xd0,0xb, 0xe0,0x7e,0x73,0x33,0x48,0xbc,0x7e,0x28, +0x2, 0x41,0x8e,0x7c,0xe8,0x80,0x6d,0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c, +0x7c,0xb9,0x12,0x2e,0x5f,0x60,0x33,0x12,0x2f,0xd4,0xbe,0xb0,0xff,0x68,0x2b,0x9, +0x73,0x1f,0x35,0x12,0xbf,0xcb,0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58, +0x5, 0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0xd, 0x12,0x2f,0xd4, +0xf5,0x24,0x9, 0xc3,0x1f,0x35,0x7d,0xdc,0x7c,0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0, +0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74,0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70, +0x19,0xc5,0x1f,0x71,0x7e,0xa0,0xff,0x7e,0x70,0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34, +0xb, 0xd0,0xb, 0xe0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbe,0x38,0x8a,0x90,0x60,0x9a, +0xe4,0x93,0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f, +0x34,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xfd,0x12,0x95,0x29,0x7e,0x8, 0x33,0x88,0x74, +0xff,0x12,0x20,0xe8,0xbe,0xf0,0x0, 0x28,0x38,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e, +0x18,0x1f,0x34,0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x33,0x88,0x12,0x20,0xc3,0x1b,0xfd,0x6c, +0xee,0x80,0xa, 0x7c,0xbe,0x7e,0x70,0x1, 0x12,0x2e,0xdd,0xb, 0xe0,0xbc,0xfe,0x38, +0xf2,0x7a,0xf3,0x33,0x48,0x7a,0xf3,0x28,0x84,0x90,0x60,0x99,0xe4,0x93,0xbe,0xb3, +0x28,0x84,0x50,0x4, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0xca,0x79,0x6c,0xff,0x6c, +0xee,0x80,0x31,0x7c,0xbe,0x12,0x2e,0x5f,0x60,0x28,0x7e,0x34,0x0, 0x2, 0xca,0x39, +0xac,0x7e,0x2e,0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x26, +0xfa,0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbf,0x7e,0x70,0x1, 0x12,0x2e,0xdd, +0xb, 0xf0,0xb, 0xe0,0x12,0x47,0xe5,0x38,0xca,0x7a,0xf3,0x28,0x84,0xda,0x79,0x22, +0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x2, 0x21,0x1a,0xca,0x79,0x7f,0x70,0x7e,0xb4, +0xff,0xff,0x6c,0xee,0xc2,0x4, 0xc2,0x5, 0x29,0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc, +0x76,0x78,0xe, 0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2, +0x5, 0x6c,0xff,0x12,0x2e,0x52,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xa1, +0x34,0x7f,0x6, 0x7e,0x7b,0xb0,0x12,0x2f,0x7f,0x50,0x2d,0x7f,0x6, 0x29,0xb7,0x0, +0x2, 0x12,0x2f,0x7f,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0x2f, +0x4a,0x50,0x15,0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x2f,0x4a,0x50,0x8, +0x7c,0xef,0xd2,0x4, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70, +0x12,0x2c,0x73,0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12, +0x2c,0x73,0x2d,0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x2c, +0x73,0x2d,0xa3,0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x2c,0x73, +0x2d,0xa3,0xbd,0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, +0xd2,0x4, 0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0x81,0xa3,0x20,0x4, 0xb, +0x20,0x5, 0x8, 0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x4, 0x20,0x4, 0x2, 0xa1,0xf5, +0x74,0x6, 0xac,0xbe,0x12,0x2e,0x56,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23,0x54, +0x1f,0xbe,0xb0,0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e,0x60, +0x8, 0x5e,0x60,0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x5, 0x11,0x29, +0xb6,0x0, 0x4, 0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b,0xb0, +0x29,0x67,0x0, 0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x3, +0x80,0x4, 0x29,0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29,0x76, +0x0, 0x2, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, 0x2, +0x39,0x76,0x0, 0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50,0x6, +0x29,0x76,0x0, 0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e,0x7b, +0x60,0x7e,0x6b,0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b,0x70, +0x7a,0x6b,0x70,0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x2, 0xeb,0x30, +0xe1,0x7, 0xb, 0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x39,0x74,0x1, +0x39,0xb7,0x0, 0x4, 0x12,0x2e,0x52,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f,0x17,0x7f, +0x6, 0x12,0x20,0xc3,0x1b,0xfd,0x7f,0x16,0x12,0x2e,0x4a,0x44,0x1, 0x7a,0x1b,0xb0, +0x7f,0x16,0x12,0x2e,0x4a,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x5, 0xa, 0x7f,0x16,0x12, +0x2e,0x4a,0x44,0x4, 0x7a,0x1b,0xb0,0xda,0x79,0x22,0x2e,0x34,0x0, 0x5, 0x7e,0x1b, +0xb0,0x22,0x74,0x6, 0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x2, 0xe6,0x6d,0xcc,0x22,0x7c, +0x7b,0x12,0xc5,0x67,0x9, 0xa2,0x27,0x72,0x7c,0xb7,0x54,0x7, 0xa, 0x3b,0x2e,0x34, +0x0, 0x5e,0x12,0x6f,0xee,0x5c,0xba,0x22,0x6c,0x0, 0x6c,0x11,0x80,0x16,0x7c,0xb1, +0x12,0x2e,0x5f,0x60,0xd, 0x12,0x2f,0x1c,0x12,0x2f,0x2d,0x40,0x5, 0x7e,0x0, 0x1, +0x80,0xa, 0xb, 0x10,0x7e,0x73,0x28,0x84,0xbc,0x71,0x38,0xe2,0x7c,0xb0,0x6c,0x77, +0x12,0xa0,0x78,0xbe,0x0, 0x1, 0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, 0x12,0xa0,0x78, +0xb4,0x1, 0x24,0x6c,0x11,0x80,0x18,0x7c,0xb1,0x12,0x2e,0x5f,0x60,0xf, 0x12,0x2f, +0x1c,0x12,0x2f,0x2d,0x50,0x7, 0x7c,0xb1,0x6c,0x77,0x12,0x2e,0xdd,0xb, 0x10,0x7e, +0x3, 0x28,0x84,0xbc,0x1, 0x38,0xe0,0x22,0x7c,0xb3,0x7e,0x70,0x1, 0x7c,0x67,0x7c, +0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e,0x24,0x0, +0x5e,0x12,0x6c,0xb9,0x7c,0x7b,0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24,0x27,0x72, +0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a,0x2e, +0x24,0x27,0x72,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0x74,0x2, 0xac,0xb1, +0x9, 0x25,0x26,0xfa,0x9, 0x35,0x26,0xfb,0x7c,0xb2,0x7c,0x73,0x22,0x7c,0xa7,0x7c, +0x7b,0x90,0x60,0xaa,0xe4,0x93,0x60,0x2, 0x7c,0xa7,0x90,0x60,0xab,0xe4,0x93,0xbc, +0xba,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x70,0x1, 0x7c,0x87,0x7c,0x9b,0x29,0xa0, +0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, 0x78,0x7, 0x29,0xa0, +0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, 0x16,0xbd,0x1, 0x48, +0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3,0x22,0xc3,0x22,0x7e, +0x70,0x1, 0x2, 0x2f,0x4a,0xca,0x3b,0x12,0xcc,0x9f,0x75,0x5b,0x0, 0x7e,0xa1,0x5b, +0x74,0x6, 0xa4,0x12,0xba,0x59,0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc,0x12,0x2f,0x7f, +0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x2f,0x47,0x50,0x1c,0x7f,0x7, 0x7c,0xbd,0x6c, +0x77,0x12,0x2f,0x4a,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12,0x2f,0x4a,0x50, +0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x5b,0xe5,0x5b,0xbe,0xb0,0x1e,0x40,0xbd, +0xe4,0xda,0x3b,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3,0x1f,0x34,0x22,0x12,0xa0, +0xb3,0x12,0x9b,0x2d,0x12,0x9a,0x7a,0x2, 0x2f,0xea,0xca,0x3b,0x12,0x2c,0x2b,0x7e, +0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0xd2,0x60,0x9, 0xe4,0x7a,0xb3,0x37,0xd4, +0x7a,0xb3,0x37,0x59,0x7e,0xb3,0x37,0xd2,0x70,0x6f,0x6c,0x99,0x80,0x63,0x74,0x2, +0xac,0xb9,0x9, 0x85,0x26,0xfa,0x9, 0xf5,0x26,0xfb,0x7c,0xb9,0x12,0x9f,0x11,0x40, +0x4e,0x6c,0xee,0x80,0x42,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x37,0x5a,0x9, 0xc5,0x37, +0x5b,0xa, 0x28,0xa, 0x3d,0x12,0x30,0x9c,0x78,0x2b,0xa, 0x2f,0xa, 0x3c,0x12,0x30, +0x9c,0x78,0x22,0x7c,0xb9,0x12,0x30,0xa4,0x7e,0x14,0x62,0x31,0x7e,0x4, 0x0, 0xff, +0xb, 0xa, 0x20,0xbd,0x32,0x58,0xe, 0x7c,0xb9,0x6c,0x77,0x12,0x2e,0xdd,0x7c,0xb8, +0x7c,0x7f,0x12,0x9b,0xe2,0xb, 0xe0,0x7e,0x73,0x37,0xd4,0xbc,0x7e,0x38,0xb6,0xb, +0x90,0x7e,0x73,0x28,0x84,0xbc,0x79,0x38,0x95,0x7e,0x73,0x37,0x59,0x7a,0x73,0x37, +0xd4,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x37,0x96,0x7e,0x8, 0x37,0x5a,0x12, +0x20,0xc3,0x1b,0xfd,0xe4,0x7a,0xb3,0x37,0xd2,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21, +0x1a,0x4d,0x33,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7a,0x12,0x9e,0xf5,0x2, 0x30, +0xb6,0xe5,0x26,0x7e,0x71,0x25,0x12,0xbf,0xcb,0xb, 0x1a,0x30,0x22,0xca,0x3b,0x6d, +0xee,0x7e,0xc3,0x2a,0x6e,0x7e,0xd3,0x2a,0x6d,0x7e,0xb3,0x3, 0xeb,0xb4,0x1, 0x3, +0xe4,0x21,0xf3,0x7e,0xb3,0x28,0x84,0x70,0x2, 0x21,0x62,0x7e,0xb3,0x2a,0x3, 0x60, +0x2, 0x80,0x7f,0x7e,0xa3,0x26,0xfa,0x7e,0x73,0x26,0xfb,0x7a,0x71,0x24,0x6c,0xee, +0x6d,0xff,0x6c,0xff,0xa, 0x47,0x80,0x20,0x12,0x32,0x9, 0xbe,0x34,0x0, 0x96,0x8, +0x1d,0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x31,0xf9,0x12,0x36, +0x5e,0x58,0x3, 0x12,0x31,0xf6,0x1b,0x44,0xbe,0x44,0x0, 0x0, 0x58,0xda,0xe5,0x24, +0xa, 0x4b,0x80,0x1e,0x12,0x32,0x9, 0xbe,0x34,0x0, 0x96,0x8, 0x21,0xb, 0xe0,0xbe, +0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x31,0xf9,0x12,0x36,0x5e,0x58,0x3, 0x12, +0x31,0xf6,0x7d,0x24,0xb, 0x24,0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xd6,0xbe,0xe0, +0x3, 0x50,0x2, 0x80,0xd, 0xa, 0x2f,0x7d,0x3f,0x12,0x1e,0xb9,0xbe,0x34,0x0, 0x28, +0x8, 0x7, 0xe4,0x7a,0xb3,0x37,0x2f,0x21,0xf3,0x6d,0xdd,0xbe,0xa0,0x0, 0x28,0x8, +0x7c,0xba,0x14,0x12,0x32,0x3, 0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, 0xca,0xbd,0xc3, +0x58,0x8, 0x7c,0xba,0x4, 0x12,0x32,0x3, 0x2d,0xd3,0x7e,0x70,0x8, 0x80,0x2a,0x7e, +0x50,0x2, 0xac,0x57,0x7d,0xc2,0x2e,0xc4,0x20,0xfa,0x7d,0x1c,0x7a,0x31,0x82,0x7a, +0x21,0x83,0xe4,0x93,0x1a,0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x20,0xfb, +0x7d,0x2c,0x12,0x6c,0xb9,0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, +0xce,0x7c,0xba,0x12,0x32,0x3, 0x12,0x21,0x1a,0xbe,0x34,0xa, 0xf0,0x8, 0x4, 0x2e, +0xe4,0x0, 0x28,0xbe,0xe4,0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x37, +0x2f,0xa, 0x3b,0xbd,0x3e,0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x37,0x2f,0x7e, +0xb3,0x37,0x2f,0xda,0x3b,0x22,0x7c,0xba,0x4, 0x7c,0x79,0x12,0x30,0xb6,0x2d,0xf3, +0xb, 0xf0,0x22,0x7e,0x71,0x24,0x2, 0x30,0xb6,0x7c,0xba,0x7c,0x79,0x2, 0x30,0xb6, +0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, +0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, +0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d, +0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0x61,0x75,0x75,0x2d,0x0, +0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18,0x1f,0x70,0x7a, +0x1d,0x29,0x74,0xff,0x7e,0x34,0x1f,0x71,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x7e, +0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d,0x29, +0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12,0x2e,0x4a,0x44,0x1, 0x7a,0x1b,0xb0,0x75, +0x24,0x0, 0x80,0x6c,0x12,0xcc,0x24,0x9, 0x93,0x26,0xfb,0xe5,0x24,0x12,0x3e,0xdb, +0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, 0x39, +0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x32,0x9, 0xbe,0x35,0x2e,0x8, 0x6, 0x12,0x32, +0x9, 0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a,0x1b, +0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, 0x2, +0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, 0x7e, +0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, 0x24, +0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e,0xd, 0x29,0x12, +0x2c,0x7a,0xe5,0x2d,0xa, 0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e,0x35, +0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55,0x25,0x12,0x36,0x56,0x19,0xa3,0x2, 0xaa, +0x7e,0x55,0x27,0x12,0x36,0x56,0x19,0xa3,0x2, 0xab,0x7e,0x37,0x28,0x8a,0xbe,0x35, +0x2e,0x78,0xe, 0x7e,0x35,0x25,0x7a,0x73,0x28,0x8c,0x7e,0x35,0x27,0x7a,0x73,0x28, +0x8d,0x7e,0x37,0x2, 0xa8,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27,0x12, +0x30,0xb6,0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x2, 0xa8,0x1b,0x38, +0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x41,0x4d,0x12,0xb7,0xf8,0x7c,0xbf, +0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x2, 0x30,0xb6,0xca,0x3b,0x7f,0x70,0x7c,0xe7, +0x7c,0xdb,0x7e,0xc0,0x4, 0x7e,0xb3,0x2a,0x6d,0xf5,0x28,0x7e,0xb3,0x2a,0x6e,0xf5, +0x27,0x7e,0x34,0x62,0x10,0x12,0x83,0x38,0x6c,0xff,0x12,0xbf,0xc7,0x7f,0x51,0xe5, +0x28,0xa, 0x3b,0x1b,0x34,0xa, 0xcd,0xbd,0xc3,0x58,0x14,0xe5,0x27,0xa, 0x3b,0x1b, +0x34,0xa, 0xce,0xbd,0xc3,0x58,0x8, 0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e, +0xf0,0x10,0xb, 0x5a,0x30,0x7e,0x14,0x62,0x10,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20, +0xbd,0x32,0x8, 0xc, 0x7e,0x27,0x28,0x8a,0xbe,0x24,0x3, 0x20,0x8, 0x2, 0x81,0xe7, +0xb, 0xa, 0xc0,0x1e,0xc4,0xbd,0x3c,0x8, 0xc, 0x7e,0xc7,0x28,0x8a,0xbe,0xc4,0x3, +0x20,0x58,0x2, 0x81,0xe7,0x6c,0xaa,0x7c,0x8d,0x80,0x1e,0x7c,0x9e,0xbe,0x80,0x0, +0x48,0x13,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0xb, 0x12,0x33,0x83,0xbd,0x3d,0x58, +0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a, +0xc8,0xbd,0xc3,0x18,0xd6,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0x81,0xe7,0x6c,0xaa, +0x7c,0x8d,0x80,0x1e,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x13,0x7e,0xb3,0x2a,0x6d,0xbc, +0xb8,0x8, 0xb, 0x12,0x33,0x83,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0, +0xb, 0x80,0x1a,0x2c,0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd6,0xbc,0xca, +0x18,0x5, 0x4e,0xf0,0x2, 0x80,0x70,0x6c,0xaa,0x7c,0x9e,0x80,0x1e,0x7c,0x8d,0xbe, +0x90,0x0, 0x48,0x13,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0xb, 0x12,0x33,0x83,0xbd, +0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d, +0x32,0x1a,0xc9,0xbd,0xc3,0x18,0xd6,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x37, +0x6c,0xaa,0x7c,0x9e,0x80,0x1e,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x13,0x7e,0xb3,0x2a, +0x6e,0xbc,0xb9,0x8, 0xb, 0x12,0x33,0x83,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, +0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a,0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd6, +0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, 0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd, +0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7,0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, +0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe,0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, +0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7,0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0xca,0x3b, +0x7c,0xc7,0x7c,0xfb,0x7f,0x40,0x6d,0x33,0x7a,0x35,0x24,0x7e,0xa3,0x2a,0x6d,0x7e, +0x73,0x2a,0x6e,0x4c,0xcc,0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc, +0xbc,0x78,0x6, 0xa, 0x6c,0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, +0x80,0xb, 0x7c,0xba,0x14,0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e, +0x34,0x0, 0x6, 0xe4,0x12,0x20,0xe8,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b,0x34,0x7a, +0x4b,0x70,0x7e,0x73,0x2a,0x6e,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec, +0x80,0x1f,0x75,0x26,0x0, 0x7c,0xdf,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70, +0xa, 0x12,0x36,0x4b,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xee,0xe5,0x26,0x60,0x7, 0x1b, +0xe0,0xbe,0xe0,0x0, 0x58,0xdc,0x7c,0xec,0x80,0x26,0x75,0x26,0x0, 0x1a,0x3f,0xb, +0x34,0x7c,0xd7,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70,0xd, 0x12,0x36,0x4b, +0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xeb,0xe5,0x26,0x60,0x7, 0x1b,0xe0, +0xbe,0xe0,0x0, 0x58,0xd5,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x1f,0x75,0x26,0x0, +0x7c,0xdf,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70,0xa, 0x12,0x36,0x4b,0x1b, +0xd0,0xbe,0xd0,0x0, 0x58,0xee,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x2a,0x6e, +0xbc,0x7e,0x18,0xd9,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x24,0x75,0x26,0x0, 0x1a, +0x6f,0xb, 0x64,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70,0xd, 0x12,0x36,0x4b, +0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xeb,0xe5,0x26,0x60,0xa, 0xb, 0xe0, +0x7e,0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xd4,0x7e,0x35,0x24,0x7d,0x23,0x39,0x54,0x0, +0x5, 0xda,0x3b,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0x22,0x5, 0x26,0x7e,0x35,0x24, +0xb, 0x34,0x7a,0x35,0x24,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0xa, 0x2d, +0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0xca,0x79,0x6c,0x88,0x80,0x6e,0x74,0x2, 0xac, +0xb8,0x9, 0xf5,0x26,0xfa,0x9, 0x75,0x26,0xfb,0x7a,0x71,0x24,0x7c,0xbf,0x12,0xa3, +0x84,0x50,0x56,0x6c,0xee,0x80,0x4d,0xbc,0xe8,0x68,0x47,0x12,0xcc,0x71,0x12,0x9e, +0xec,0x6c,0x99,0x90,0x60,0xaa,0xe4,0x93,0x70,0x18,0x7e,0xb3,0x2a,0x70,0x14,0xbe, +0xb1,0x26,0x78,0xe, 0xa, 0x2f,0xe5,0x25,0xa, 0x3b,0x12,0x37,0xb, 0x18,0x3, 0x7e, +0x90,0x1, 0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe,0x12,0x30,0xa4,0x7d,0xf3,0x7c,0xb8, +0x12,0x30,0xa4,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe,0x80,0x2, 0x7c,0xb8,0x6c,0x77,0x12, +0x2e,0xdd,0xb, 0xe0,0x12,0x47,0xe5,0x38,0xae,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc, +0x78,0x38,0x8a,0xda,0x79,0x22,0x7c,0xba,0x7c,0x7d,0x2, 0x30,0xb6,0x7c,0xbd,0x7c, +0x7e,0x2, 0x30,0xb6,0x7c,0xbf,0x12,0x30,0xa4,0x74,0x2, 0xac,0xbf,0x22,0x12,0x37, +0x15,0x12,0x30,0xbd,0x7a,0xb3,0x2a,0xc, 0x22,0x1a,0x3b,0x9d,0x32,0x12,0x21,0x1a, +0xbe,0x34,0x0, 0x1, 0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x36,0x94,0x6c,0x33, +0x80,0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10,0x1, 0x6c,0x0, +0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93,0x26,0xfb,0xa, +0x29,0xa, 0x32,0x12,0x37,0xb, 0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74, +0x2, 0x7a,0xb3,0x36,0x94,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc, +0xa3,0x38,0xbf,0x2, 0x37,0x66,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c,0x22,0x80,0x45, +0x74,0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e,0xa0,0x1, 0x6c, +0x99,0x80,0x2c,0xbc,0x92,0x68,0x26,0x7e,0x70,0x2, 0xac,0x79,0x9, 0x83,0x26,0xfa, +0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, 0x31,0x12,0x37,0xb, 0x18,0xb, 0xa, 0x2f,0xa, +0x30,0x12,0x37,0xb, 0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc, +0x39,0x38,0xd0,0xb, 0x20,0xbc,0x32,0x38,0xb7,0x7e,0xb3,0x37,0x2e,0xbe,0xb0,0x0, +0x28,0x12,0x14,0x7a,0xb3,0x37,0x2e,0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c, +0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x3, 0xa6,0x70,0x58,0x7e,0xb3,0x33,0xfe,0x70,0x52, +0x7e,0xb3,0x37,0xe4,0x70,0x4c,0x7e,0x37,0x39,0x11,0xbe,0x34,0x0, 0x14,0x50,0x42, +0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x28,0x84,0xbe,0xb0, +0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x26,0x85,0xbe,0xb0,0x3, 0x50, +0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x26,0xf6,0xbe,0xb0, +0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7,0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3, +0x37,0x2e,0xda,0xf8,0x22,0x12,0x62,0xd9,0x12,0x24,0x70,0x12,0x38,0x57,0x12,0x23, +0x3, 0x7e,0xb3,0x3, 0xc2,0x24,0xfd,0x68,0x9, 0xb, 0xb1,0x78,0xf4,0x12,0x3c,0x27, +0x80,0xef,0x12,0x29,0xae,0x80,0xea,0x12,0x70,0x4e,0x12,0x73,0x39,0x12,0x0, 0xa, +0x12,0xcc,0x3b,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8,0x7e,0xf, 0x6, 0xf8,0x7e, +0x1f,0x6, 0xf4,0x12,0x7f,0xfa,0x7e,0x18,0x8, 0xa, 0x7a,0x1f,0x13,0x86,0x7e,0x18, +0xd, 0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, 0x13,0x8a,0x7e,0x1f,0x13,0x86,0x12,0x78, +0x89,0x12,0x78,0x3d,0x12,0x25,0x1b,0x12,0x77,0xf3,0x12,0x38,0xf7,0x2, 0x38,0xa0, +0xe4,0x7a,0xb3,0x33,0xe4,0x7a,0xb3,0x33,0xe5,0x7a,0xb3,0x33,0xe6,0x22,0x12,0x38, +0xa0,0x12,0x38,0xe3,0x2, 0x38,0xb7,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x38,0xc0, +0x7d,0x43,0x7e,0xa3,0x33,0xe4,0xbe,0xa0,0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a, +0x59,0x43,0x33,0xe7,0x59,0x23,0x33,0xe9,0x7c,0xba,0x4, 0x7a,0xb3,0x33,0xe4,0xc3, +0x22,0xd3,0x22,0x6d,0x33,0x7e,0x24,0x6, 0xfc,0x12,0x38,0xc0,0x7e,0x34,0x0, 0x1, +0x7e,0x24,0x7, 0x7a,0x2, 0x38,0xc0,0x12,0x78,0x31,0x7e,0x24,0x0, 0x3, 0xad,0x32, +0x7e,0x8, 0x28,0xae,0x74,0xff,0x12,0x20,0xe8,0x12,0x9f,0x59,0x7e,0x8, 0x29,0xbc, +0x12,0x39,0x1f,0x7e,0x8, 0x2a,0x2, 0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x20,0xe8,0x6c, +0xaa,0x80,0x20,0x74,0x3, 0x12,0xa2,0x9a,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, +0x12,0x3b,0xeb,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, +0x28,0xb, 0xa0,0x12,0x39,0x49,0x38,0xdb,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba, +0x22,0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x80,0x19,0x7e,0x70,0xff,0x12,0x3c, +0x6, 0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19,0xb4,0x1f,0x46,0x19,0xb4, +0x1f,0x50,0xb, 0xa0,0x12,0x39,0x49,0x38,0xe2,0x7e,0x73,0x2a,0x2, 0xa5,0xbf,0x0, +0x23,0x7e,0xb3,0x39,0xf9,0x70,0x2, 0x61,0x60,0x6c,0xaa,0x80,0x10,0x7e,0x44,0x7f, +0xff,0x12,0x3c,0x10,0x79,0x40,0x0, 0x14,0x12,0x3b,0xfd,0xb, 0xa0,0x12,0x39,0x49, +0x38,0xeb,0x61,0x60,0x7e,0xb3,0x39,0xf9,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38,0x6c, +0xaa,0x80,0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x28,0xae,0x12,0x3c,0x10,0x79, +0x30,0x0, 0x14,0x49,0x34,0x28,0xb0,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74, +0x1, 0xa, 0x3a,0x19,0xb3,0x1f,0x34,0x19,0xa4,0x28,0xb2,0xb, 0xa0,0x7e,0xb3,0x2a, +0x2, 0xbc,0xba,0x38,0xce,0x61,0x60,0x6c,0xaa,0x80,0x17,0x12,0x3b,0xeb,0x3e,0x34, +0x59,0x43,0x15,0x4e,0x59,0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15,0x78, +0xb, 0xa0,0x12,0x39,0x49,0x38,0xe4,0x6c,0xaa,0x80,0x3d,0x6c,0xff,0x80,0x32,0x7e, +0x70,0x2, 0xac,0x7f,0x7f,0x6, 0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f,0xff, +0x68,0x1d,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x14,0x12,0x3b,0xf5,0x59,0x32, +0x15,0x4e,0x69,0x30,0x0, 0x28,0x59,0x32,0x15,0x50,0x12,0x3c,0x1a,0x80,0x7, 0xb, +0xf0,0x12,0x3b,0xe3,0x38,0xc9,0xb, 0xa0,0x7e,0xb3,0x39,0xf9,0xbc,0xba,0x38,0xbb, +0x6c,0xaa,0x80,0x24,0xa, 0x3a,0x9, 0xb3,0x1f,0x46,0xb4,0xff,0x19,0x6c,0xff,0x80, +0x10,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, 0x12,0x3c,0x1a,0x80,0x7, 0xb, +0xf0,0x12,0x3b,0xe3,0x38,0xeb,0xb, 0xa0,0x12,0x39,0x49,0x38,0xd7,0x6c,0xaa,0x80, +0x1a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x28,0xae,0x12,0x3b,0xf5,0x59,0x42,0x15, +0x76,0x49,0x33,0x28,0xb0,0x59,0x32,0x15,0x78,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc, +0xba,0x38,0xde,0x7e,0x34,0x15,0x4e,0x7a,0x37,0x1f,0x40,0x7e,0x34,0x15,0x76,0x7a, +0x37,0x1f,0x42,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x44,0x7e,0x73,0x39,0xf9,0x7a, +0x73,0x1f,0x3e,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x1f,0x3f,0x7e,0x8, 0x1f,0x3e,0x12, +0x4, 0xad,0x6c,0xaa,0x80,0x59,0x7e,0x70,0xff,0x6c,0xff,0x80,0x19,0x7e,0x50,0x2, +0xac,0x5f,0x49,0x12,0x15,0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, 0x73, +0x1f,0x46,0x80,0x7, 0xb, 0xf0,0x12,0x3b,0xe3,0x38,0xe2,0xbe,0x70,0xff,0x68,0x2d, +0x12,0x3c,0x6, 0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34,0x7e,0x90,0x9, 0xac,0x9a, +0x49,0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20,0x0, +0x14,0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12,0x3b,0xfd,0xb, 0xa0,0x7e, +0x63,0x2a,0x2, 0xbc,0x6a,0x38,0x9f,0x6c,0xaa,0x80,0x20,0xa, 0x3a,0x9, 0xb3,0x1f, +0x34,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x3b,0xeb,0x7f,0x6, 0x2d,0x13,0x79,0x40,0x0, +0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x12,0x39,0x49,0x38,0xdb, +0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x39,0xf9,0x6c,0xaa,0x80,0x68,0xa, 0x3a,0x9, 0xb3, +0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x3b,0xdc,0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, 0x74, +0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x3b,0xdc,0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, 0x6, +0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a,0x1b,0xb0,0x80, +0x27,0x12,0x3b,0xdc,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14,0x74, +0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1,0x28, +0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x3b,0xdc,0x7e,0x1b,0xb0,0x39,0xb1, +0x0, 0xa, 0xb, 0xa0,0x12,0x39,0x49,0x38,0x93,0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d, +0x7d,0x2c,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x22,0x7e,0x44,0x7f,0xff,0x7e, +0x70,0x2, 0xac,0x7a,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x22,0x7f,0x6, 0x2d, +0x12,0x79,0x40,0x0, 0x28,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x28,0xb2,0x22, +0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0xa, 0x3a,0x19,0xf3,0x1f,0x46, +0x74,0x1, 0x19,0xb4,0x1f,0x50,0x22,0x12,0x5e,0xb2,0x12,0x80,0x6e,0x7e,0xb3,0x3, +0xc2,0xb4,0x1, 0x6b,0x12,0xc1,0xb6,0x7e,0x34,0x60,0xa5,0x12,0x23,0x74,0x12,0x26, +0x77,0x12,0x8f,0xfd,0x12,0x81,0x86,0x12,0x28,0xa0,0x50,0xde,0x12,0x6e,0x5f,0x12, +0x6f,0xa, 0x7e,0xb3,0x3, 0xbf,0xb4,0x1, 0x4, 0xe4,0x12,0x3c,0xb1,0x12,0x45,0xb9, +0x12,0x3e,0xe5,0x40,0xc5,0x12,0x84,0x67,0x12,0x3e,0xe5,0x40,0xbd,0x12,0x36,0xfe, +0x12,0x2a,0x31,0x12,0x0, 0x66,0x12,0x45,0xeb,0x12,0x87,0xfe,0x12,0x91,0x36,0x12, +0x39,0x51,0x12,0x94,0x0, 0x12,0x3e,0xfd,0x12,0x96,0xe8,0x12,0x83,0x40,0x12,0xc7, +0x76,0x12,0x3c,0xb9,0x12,0x62,0xab,0x12,0x8b,0x36,0x12,0x59,0x4e,0x80,0x8b,0x12, +0x6f,0xd5,0x2, 0x3c,0xa5,0x7e,0xb3,0x3, 0xbf,0xb4,0x1, 0x4, 0xe4,0x2, 0x3c,0xb1, +0x22,0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff, +0x12,0x3e,0xd4,0x75,0x28,0x3, 0x6c,0xee,0x7e,0x48,0x29,0xbc,0x7e,0xb3,0x2a,0xb, +0x70,0xe, 0x7e,0xb3,0x2a,0x7, 0x70,0x8, 0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0xc1,0xab, +0x30,0x10,0x6, 0x7e,0x68,0x35,0xe4,0x80,0x4, 0x7e,0x68,0x35,0xa6,0x7f,0x6, 0x12, +0xcc,0x8c,0x7e,0x73,0x2a,0x4, 0x7a,0x6b,0x70,0x6c,0xdd,0xc1,0x5c,0x74,0x9, 0xac, +0xbd,0x9, 0xc5,0x29,0xc, 0x7c,0xbc,0x54,0xf, 0x12,0x3e,0xdb,0xf5,0x28,0x7c,0xbc, +0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, 0xc1,0x5a,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, +0xc1,0x5a,0x7e,0x8, 0x0, 0x28,0x7c,0xbc,0x12,0x97,0x41,0x50,0x2, 0xc1,0x5a,0x74, +0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xd, 0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29, +0xe, 0xc4,0x54,0xf0,0xf5,0x26,0x7e,0x73,0x2a,0x4d,0xbc,0x7c,0x28,0x54,0x7e,0xb3, +0x2a,0x9, 0x70,0x2a,0x75,0x29,0xf, 0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x35, +0x92,0x6d,0x22,0x74,0x1, 0x12,0x81,0xf0,0x75,0x29,0x20,0x7e,0x8, 0x0, 0x26,0xa, +0x3c,0x2e,0x34,0x35,0x9c,0x6d,0x22,0x74,0x10,0x12,0x81,0xf0,0x80,0xe, 0xa, 0x3c, +0x9, 0xb3,0x35,0x92,0xf5,0x25,0x9, 0xb3,0x35,0x9c,0xf5,0x26,0xa, 0x3c,0x12,0x3e, +0xdd,0xb4,0x1, 0xe, 0xe4,0xa, 0x3c,0x19,0xb3,0x35,0x92,0x19,0xb3,0x35,0x9c,0x12, +0x3e,0xd4,0x7e,0xb3,0x2a,0x64,0xb4,0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd, +0x9, 0xb5,0x29,0xc, 0xbe,0xb0,0xff,0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, 0xac, +0x9d,0x49,0xb4,0x29,0x8, 0x49,0xa4,0x29,0xa, 0xe5,0x28,0xb4,0x1, 0x2c,0x75,0x27, +0x0, 0x80,0x1d,0x7e,0x71,0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x36,0x26,0x54,0xf, +0xbc,0xbc,0x78,0xa, 0x49,0xb3,0x36,0x22,0x49,0xa3,0x36,0x24,0x80,0xc, 0x5, 0x27, +0x90,0x60,0x99,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd9,0x5e,0xb4,0xf, 0xff,0x5e,0xa4, +0xf, 0xff,0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x2d,0xa5, +0xbe,0x70,0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x24,0xb, 0xf0, +0xe5,0x28,0xa, 0x5b,0x12,0xc2,0x45,0x2d,0xb5,0x80,0x4, 0x2e,0xb4,0xc0,0x0, 0x7e, +0x70,0x6, 0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, 0x7f,0x6, 0x2d,0x13, +0x79,0xa0,0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0,0x0, 0x6, 0xe5,0x26, +0x2d,0x3d,0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0,0x7e,0x73,0x2a,0x4d, +0xbc,0x7d,0x28,0x2, 0x81,0xfd,0xe5,0x24,0x39,0xb6,0x0, 0x1, 0x7e,0xb3,0x3, 0xeb, +0xb4,0x1, 0x9, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x17,0x80,0xd, 0xbe,0xf0,0x0, 0x38, +0x6, 0x7e,0xb3,0x2a,0x8, 0x60,0xa, 0xb2,0x10,0x12,0x80,0xa1,0x74,0x1, 0x12,0x3c, +0xb1,0x7e,0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x39,0x1f,0xe4,0x7a,0xb3,0x2a, +0xb, 0x7a,0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4,0x12,0x3c,0xb1,0x12, +0x94,0x58,0xca,0x59,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x36,0x22,0x12,0x20,0xc3,0x1b, +0xfd,0x4c,0xff,0x78,0xc, 0x12,0x78,0x31,0x7e,0x8, 0x36,0x22,0x74,0xff,0x12,0x20, +0xe8,0xda,0x3b,0x22,0x75,0x25,0x0, 0x75,0x26,0x0, 0x22,0xa, 0x3b,0x2d,0x39,0x7d, +0x28,0x7e,0x1b,0xb0,0x22,0xc2,0x3, 0x7e,0xb3,0x16,0x91,0x60,0x6, 0x7e,0xb3,0x16, +0x90,0x70,0x7, 0x12,0xba,0x25,0x28,0x2, 0xd2,0x3, 0xa2,0x3, 0x22,0xca,0xf8,0x7e, +0xa3,0x2a,0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, 0xbe,0xb0,0x0, 0x28,0x13, +0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, 0x7a, +0xb3,0x2a,0xb, 0x12,0x94,0x58,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x8, +0x12,0x20,0xc3,0x1b,0xfd,0x90,0x61,0x35,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x23,0x6c, +0xff,0x80,0x1a,0x12,0x96,0xa8,0x12,0x82,0x32,0x74,0x9, 0xac,0xbf,0x59,0x35,0x29, +0x8, 0x49,0x35,0x28,0xb0,0x12,0x5b,0x81,0x12,0x83,0xf0,0xb, 0xf0,0x12,0x3b,0xe3, +0x38,0xe1,0xda,0xf8,0x22,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x2a,0x6f,0xf5,0x27,0x7e, +0xb3,0x2a,0x70,0xf5,0x28,0x75,0x2b,0x0, 0x7e,0xb3,0x16,0x91,0xbe,0xb0,0x1, 0x68, +0x11,0x60,0x3, 0x2, 0x40,0xa5,0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x2, 0x80,0x3, 0x2, +0x40,0xa5,0x6c,0xee,0x2, 0x40,0x99,0x12,0xcc,0x4d,0x75,0x25,0x2, 0x75,0x26,0x2, +0x7c,0xbe,0x12,0x6c,0xe4,0xd2,0x3, 0x12,0x6e,0x25,0x4c,0xdd,0x68,0x7, 0xe5,0x27, +0x12,0xcc,0x44,0x48,0x3, 0x75,0x25,0x1, 0x4c,0xcc,0x68,0xc, 0xe5,0x28,0xa, 0x2b, +0x1b,0x24,0xa, 0x3c,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, 0x75,0x24,0x0, 0x80,0x30, +0xe5,0x24,0xbc,0xbe,0x68,0x28,0x12,0xcc,0x24,0x7a,0xa1,0x29,0x9, 0xb3,0x26,0xfb, +0xf5,0x2a,0xa, 0x2a,0xa, 0x3d,0x12,0xcc,0x95,0x18,0x13,0xe5,0x2a,0xa, 0x2b,0xa, +0x3c,0x12,0xcc,0x95,0x18,0x8, 0x75,0x25,0x1, 0x75,0x26,0x1, 0x80,0x7, 0x5, 0x24, +0x12,0x9e,0xe4,0x38,0xcb,0x7c,0xbd,0x7c,0x7c,0x12,0x2f,0x2d,0x50,0x8, 0x12,0x40, +0xbb,0x12,0x3e,0xd4,0x80,0x1b,0x12,0x0, 0x6e,0x50,0x16,0x7e,0x73,0x33,0x4a,0xbc, +0x7d,0x78,0xe, 0x7e,0x73,0x33,0x4b,0xbc,0x7c,0x78,0x6, 0x75,0x25,0x3, 0x75,0x26, +0x3, 0x4c,0xdd,0x78,0x2, 0x80,0x7, 0xe5,0x27,0x14,0xbc,0xbd,0x78,0xd, 0x12,0x40, +0xa8,0xb, 0xa, 0x30,0x9e,0x34,0x0, 0x32,0x1b,0xa, 0x30,0xe5,0x28,0x14,0xbc,0xbc, +0x78,0x2, 0x80,0x4, 0x4c,0xcc,0x78,0xd, 0x12,0x40,0xa8,0xb, 0xa, 0x30,0x9e,0x34, +0x0, 0x3c,0x1b,0xa, 0x30,0xe5,0x25,0x7e,0x71,0x26,0x7c,0x6e,0x7c,0x5f,0x7e,0x41, +0x2b,0x12,0x40,0xe9,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x16,0x7e,0x70,0x9, 0xac, +0x7e,0x7d,0x13,0x2e,0x14,0x27,0x76,0x6d,0x0, 0x2e,0x34,0x27,0x78,0x6d,0x22,0x12, +0x81,0x49,0x12,0x40,0xbb,0xb, 0xf0,0xb, 0xe0,0x12,0x47,0xe5,0x28,0x3, 0x2, 0x3f, +0x97,0x7a,0xf3,0x28,0x84,0xda,0x3b,0x22,0x7e,0x73,0x2a,0x6e,0xac,0x7d,0xa, 0x2c, +0x2d,0x32,0x3e,0x34,0x7e,0xf, 0x13,0x8a,0x2d,0x13,0x22,0x12,0x6f,0xb0,0x60,0x28, +0x6c,0x22,0x80,0x1c,0x7c,0xb2,0x12,0x6c,0xc2,0x50,0x13,0x7c,0xb2,0x12,0x6d,0xf2, +0x7d,0x3, 0x12,0x6f,0xa8,0x49,0x55,0x39,0xdf,0x7d,0x40,0x12,0xba,0x4d,0xb, 0x20, +0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xdc,0x22,0xca,0x3b,0x7a,0x41,0x2c,0x12,0xcc, +0x9f,0x74,0x9, 0xac,0xbf,0x7d,0x95,0x2e,0x94,0x27,0x76,0x6d,0x88,0x7e,0xe7,0x2a, +0x66,0xe4,0x39,0xb4,0x0, 0x6, 0x12,0xcc,0x71,0xf5,0x37,0x9, 0xb3,0x26,0xfb,0xf5, +0x38,0x7e,0x73,0x2a,0x6e,0x7c,0x6d,0x7e,0x8, 0x0, 0x3b,0x12,0x43,0x33,0xf5,0x39, +0xe5,0x37,0x7e,0x73,0x2a,0x6d,0x7c,0x6c,0x7e,0x8, 0x0, 0x3a,0x12,0x43,0x33,0x7c, +0xab,0xe5,0x3a,0x7e,0x71,0x3b,0x12,0xbf,0xcb,0x7d,0xf3,0x7a,0xf5,0x43,0x7e,0xf4, +0x15,0x9e,0x7a,0xf5,0x45,0x85,0x3a,0x3d,0x85,0x3b,0x3e,0x7a,0xa1,0x3f,0x85,0x39, +0x40,0x7e,0xb3,0x2a,0x59,0xf5,0x41,0x75,0x42,0x0, 0xe5,0x2c,0xb4,0x1, 0x8, 0xe5, +0x41,0x1e,0xb0,0x1e,0xb0,0xf5,0x41,0x7e,0x8, 0x0, 0x3d,0x12,0x47,0xf4,0x7d,0x23, +0x6d,0x33,0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x15,0xa2,0x6d,0x22, +0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x2d,0x7e,0x37,0x15, +0xa6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8,0x2f,0x10,0x7a,0x1d,0x31,0x7f,0x65, +0xa, 0x4c,0xe5,0x37,0xa, 0x5b,0x9d,0x54,0xf5,0x35,0x41,0x83,0xa, 0x4d,0xe5,0x38, +0xa, 0x5b,0x9d,0x54,0xf5,0x36,0x41,0x6d,0xe5,0x35,0xbe,0xb0,0x0, 0x58,0x2, 0x41, +0x6b,0x7e,0x73,0x2a,0x6d,0xbe,0x71,0x35,0x18,0x2, 0x41,0x6b,0xe5,0x36,0xbe,0xb0, +0x0, 0x58,0x2, 0x41,0x6b,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x36,0x18,0x2, 0x41,0x6b, +0xe5,0x35,0x7e,0x71,0x36,0x12,0x30,0xb6,0x7e,0x53,0x2a,0x59,0xa, 0x25,0x7d,0xf3, +0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x73,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e,0x34, +0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5,0x37,0xa, 0x2b,0xe5,0x35,0x12, +0x37,0x9, 0x18,0xb, 0xe5,0x38,0xa, 0x2b,0xe5,0x36,0x12,0x37,0x9, 0x8, 0x4c,0xe5, +0x35,0x7e,0x71,0x36,0x7c,0x6e,0x12,0xba,0x66,0xf5,0x3c,0xb4,0x2, 0x6, 0x7d,0x3f, +0xe, 0x34,0x9d,0xf3,0xe5,0x3c,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3c,0xb4,0x1, 0x2b, +0x12,0x43,0x13,0xe5,0x35,0x12,0x43,0x1a,0x7e,0x1d,0x2d,0x9f,0x10,0x7a,0x1d,0x2d, +0x12,0x43,0x13,0xe5,0x36,0x12,0x43,0x1a,0x7e,0x1d,0x31,0x9f,0x10,0x7a,0x1d,0x31, +0x12,0x43,0x13,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61,0x5, 0x36,0xa, 0x2d,0xe5, +0x38,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x36,0x1a,0x3b,0xbd,0x32,0x18,0x2, 0x21, +0xb8,0x5, 0x35,0xa, 0x2c,0xe5,0x37,0xa, 0x3b,0x2d,0x32,0x1a,0x37,0xe5,0x35,0x1a, +0xfb,0xbd,0xf3,0x18,0x2, 0x21,0xac,0xbe,0x58,0x0, 0x0, 0x78,0x2, 0xb, 0x5c,0xbe, +0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2d,0x7f,0x5, 0x12,0x43,0x24,0x1b, +0x4a,0x30,0x7e,0x1d,0x31,0x7f,0x6, 0x12,0x43,0x24,0x79,0x34,0x0, 0x2, 0x7e,0xb3, +0x2a,0x65,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80,0x0, 0x14,0x78, +0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d,0x39,0x74,0x0, +0x5, 0x74,0x9, 0xac,0xbe,0x9, 0x75,0x27,0x7c,0x39,0x74,0x0, 0x6, 0xbe,0x70,0xf, +0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0x7e,0xa1,0x37,0x7e,0x70,0x9, 0xac,0x7f, +0x19,0xa3,0x27,0x7d,0x7e,0xa1,0x38,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x27,0x7e, +0xda,0x3b,0x22,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x22,0x1a,0x1b,0x1a,0x2, 0x12,0x1e, +0xeb,0x7f,0x1, 0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x1f,0x7, 0x2e,0x18, +0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e, +0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d, +0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28, +0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f, +0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, +0xb0,0x7c,0xba,0xda,0xf8,0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0,0x34,0x38,0x2, 0x81, +0x97,0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0xa1,0xb6,0xbe,0xa0,0x36,0x68, +0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0x8, +0x2e,0x37,0x34,0x8a,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, 0xa1,0xb6,0x75,0x1a, +0x36,0xa1,0xb6,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78,0x1b,0x7e,0xf3,0x38, +0xd4,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd4,0xbe,0xa0,0x39,0x78,0x3, 0x75,0x1a,0x38, +0xa, 0x3f,0x9, 0xb3,0x2b,0x21,0xa1,0xb6,0xbe,0xa0,0x3a,0x68,0x5, 0xbe,0xa0,0x3b, +0x78,0x1b,0x7e,0xf3,0x38,0xd6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd6,0xbe,0xa0,0x3b, +0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44,0xa1,0xb6,0xbe,0xa0,0xfb, +0x78,0x6, 0x7e,0xb3,0x2b,0x12,0xa1,0xb6,0xbe,0xa0,0x5e,0x78,0x26,0x7e,0xf, 0x33, +0xc7,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, +0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c,0xa7,0x4c,0xba,0x44, +0x80,0xa1,0xb6,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78,0x1b,0x7e,0xf3,0x38, +0xd8,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd8,0xbe,0xa0,0x3d,0x78,0x3, 0x75,0x1a,0x3c, +0xa, 0x3f,0x9, 0xb3,0x2a,0x7a,0xa1,0xb6,0xbe,0xa0,0x3e,0x68,0x5, 0xbe,0xa0,0x3f, +0x78,0x1b,0x7e,0xf3,0x38,0xda,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xda,0xbe,0xa0,0x3f, +0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d,0xa1,0xb6,0xbe,0xa0,0x40, +0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x38,0xb0,0xa1,0xb6,0xbe, +0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x38,0xf5,0x7c,0xbf,0x4, +0x7a,0xb3,0x38,0xf5,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1a,0x4e,0xa, 0x3f,0x2e,0x37, +0x34,0x88,0x7e,0x39,0xb0,0xa1,0xb6,0xbe,0xa0,0x51,0x68,0x5, 0xbe,0xa0,0x52,0x78, +0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e,0xb3,0x39,0x0, 0xa, +0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x39,0x0, 0xbe,0xa0,0x52, +0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0xa1,0xb6,0xbe,0xa0,0x5c,0x68,0x5, 0xbe,0xa0, +0x5d,0x78,0x1a,0x7e,0xf3,0x38,0xc9,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc9,0xbe,0xa0, +0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0xae,0xd8,0xa1,0xb6,0xbe,0xa0,0x60, +0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x33,0xdc,0xa1,0xb6,0xbe, +0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x7e,0xbe,0xa0,0xf4,0x68,0x5, 0xbe,0xa0,0xf5, +0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, 0x9, 0xb3,0x34,0x90, +0xbe,0xa0,0xf5,0x78,0x61,0x75,0x1a,0xf4,0x80,0x5c,0xbe,0xa0,0xf0,0x68,0x5, 0xbe, +0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80,0x49,0xbe,0xa0,0xf2, +0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14,0x7e,0x1f,0x34,0x8c, +0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56,0x80,0x28,0x7d,0x53, +0x80,0x24,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x1b,0xbe,0xa0,0xf7,0x78,0xd, +0x7e,0x34,0x62,0x4e,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x50,0x80,0x9, 0xbe,0xa0,0xfd, +0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x12,0x47,0x85,0x12,0x7, 0xfb,0x12, +0x45,0xda,0x90,0x60,0xa7,0xe4,0x93,0x60,0x8, 0x30,0x14,0x5, 0x12,0x40,0xbb,0xc2, +0x14,0x22,0x7e,0x73,0x2a,0x6b,0x2e,0x70,0xff,0x22,0x12,0x45,0xd2,0x40,0xb, 0x12, +0x23,0xea,0xe4,0x7a,0xb3,0x39,0xf6,0x2, 0x47,0x8b,0x22,0xca,0x3b,0x7e,0x73,0x3, +0xdf,0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e,0x33,0x3, 0xe1,0xa, 0x13,0x6d,0x0, +0x7a,0xd, 0x2a,0x7e,0x33,0x3, 0xe0,0xa, 0x93,0x6d,0x88,0x7e,0x33,0x3, 0xe2,0xa, +0x73,0x6d,0x66,0x7e,0x14,0x61,0x37,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x40,0x12,0x46, +0xb1,0x7a,0x1d,0x26,0x12,0x87,0xe3,0xb, 0x1a,0x50,0x7e,0x1d,0x2a,0x7d,0x15,0x12, +0x46,0xb3,0x7a,0x1d,0x2a,0x7f,0x14,0x12,0x46,0xb1,0x7f,0x41,0x7f,0x13,0x7d,0x15, +0x12,0x1e,0xfc,0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12,0x45,0xd2,0x50,0x60,0x7e,0xb3, +0x16,0x91,0xb4,0x1, 0x59,0x75,0x2e,0x0, 0x80,0x4b,0x7e,0xa1,0x2e,0x74,0x9, 0xa4, +0x49,0x35,0x27,0x76,0x12,0x82,0x32,0x7a,0x35,0x24,0x7e,0xa1,0x2e,0x74,0x9, 0xa4, +0x49,0x35,0x27,0x78,0x12,0x5b,0x81,0x7d,0xa3,0x7e,0x35,0x24,0x6d,0x22,0x7e,0xd, +0x26,0xbf,0x10,0x40,0x17,0x7d,0x5a,0x6d,0x44,0x7e,0xd, 0x2a,0xbf,0x20,0x40,0xc, +0xbf,0x14,0x38,0x8, 0x7d,0x3a,0x6d,0x22,0xbf,0x13,0x28,0x7, 0xe5,0x2e,0x6c,0x77, +0x12,0x2e,0xdd,0x5, 0x2e,0x7e,0x73,0x28,0x84,0xbe,0x71,0x2e,0x38,0xac,0xda,0x3b, +0x22,0x7d,0x14,0x12,0x1e,0xfc,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x22,0xca,0x79,0x7c, +0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c,0xb4,0x12,0x97,0x95,0x7d,0x3, 0x7e,0xb3, +0x33,0x49,0xb4,0x1, 0x1a,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb5,0xbe,0x73,0x33, +0x4a,0x78,0xc, 0x9, 0x75,0x28,0xb6,0xbe,0x73,0x33,0x4b,0x78,0x2, 0x1e,0x4, 0x74, +0x9, 0xac,0xbf,0x12,0x96,0xb1,0x12,0x47,0x7d,0x7d,0x30,0xad,0x31,0x12,0x46,0xb6, +0x7d,0x13,0x5d,0x1e,0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x29,0x62,0x74,0x9, 0xac, +0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x29,0x62,0x7d, +0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34,0x29,0x62,0x9d,0xf1,0x1b,0x38, +0xf0,0x74,0x9, 0xac,0xbf,0x12,0x47,0x71,0x7d,0x30,0xad,0x31,0x12,0x46,0xb6,0x7d, +0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49,0x32,0x29,0x64,0x74,0x9, 0xac,0xbe, +0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d,0x2, 0x2e,0x4, 0x29,0x64,0x2d,0x13, +0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x29,0x64,0x9d,0x31,0x1b,0x28,0x30,0xda,0x79, +0x22,0x49,0x25,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xb0,0x9d,0x32,0x12, +0x21,0x1a,0x7d,0x13,0x22,0x12,0x47,0xd3,0x2, 0x47,0x8b,0xe4,0x7a,0xb3,0x28,0x93, +0x12,0xc4,0x29,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, 0x7e,0x73,0x28,0x84,0x7a,0x73, +0x28,0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8,0x12,0xcc,0x3b,0x12,0xc5,0x6e, +0x12,0x71,0xc8,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18,0x7e,0x73,0x26,0x83,0x7a,0x73, +0x26,0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26,0xf5,0x7e,0x73,0x26,0x84,0x7a,0x73, +0x26,0xf4,0x22,0x12,0x25,0xa2,0x2, 0x47,0xd9,0x12,0x45,0xd2,0x50,0x3, 0x2, 0x25, +0xca,0x22,0x2, 0x46,0xbd,0x7e,0x73,0x28,0x84,0xbc,0x7e,0x22,0x12,0x45,0xd2,0xd2, +0x18,0x2, 0x2a,0x27,0x12,0xc, 0x29,0x7e,0x37,0x15,0x9e,0x22,0x12,0xcc,0xcb,0xb4, +0x1, 0x14,0xca,0x39,0x7e,0x18,0x38,0xf0,0x7e,0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b, +0xfd,0x12,0x4a,0x95,0x80,0x12,0xca,0x39,0x7e,0x18,0x38,0xf0,0x7e,0x8, 0x2b,0x70, +0x12,0x20,0xc3,0x1b,0xfd,0x12,0x4a,0xb3,0x2, 0x48,0x2b,0x7a,0x1f,0x2a,0xfc,0x7a, +0xf, 0x2a,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x14,0x12,0x4a,0xb3,0x12,0x48,0x2b, +0x7e,0x18,0x6, 0x76,0x7a,0x1f,0x6, 0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x10,0xb4,0x1, +0x11,0x12,0x4a,0x95,0x12,0x48,0x2b,0x12,0xcc,0x3b,0x7e,0x18,0x4, 0x0, 0x7a,0x1f, +0x6, 0xf8,0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12,0x48,0x34,0x12,0x48,0x7b,0xe4, +0x12,0x0, 0x1e,0x74,0x1, 0x12,0x48,0x34,0x2, 0x48,0x7b,0xca,0x3b,0x7e,0xd3,0x2a, +0x73,0x7e,0xc3,0x2a,0x74,0x7e,0x8, 0x1f,0x44,0x12,0x6c,0x36,0x7e,0x8, 0x1f,0x8a, +0x7e,0x34,0x0, 0x46,0x12,0x20,0xe8,0x7e,0x8, 0x1f,0xd0,0x7e,0x34,0x0, 0xa, 0xe4, +0x12,0x20,0xe8,0x7e,0x8, 0x1f,0xda,0x7e,0x34,0x0, 0xa, 0x12,0x20,0xe8,0x7e,0xf3, +0x2a,0xfc,0x7e,0x18,0x2a,0xdc,0x7a,0x1d,0x24,0x7e,0x18,0x1f,0xd0,0x7a,0x1d,0x28, +0x7c,0xbd,0x7c,0x7c,0x7e,0x8, 0x2a,0xb9,0x12,0x49,0xd1,0x6c,0xee,0x80,0x2b,0xa, +0x3e,0x9, 0xa3,0x2a,0xdc,0xa, 0x3a,0x2e,0x34,0x20,0x7d,0x12,0x6f,0xee,0x7c,0xab, +0xbe,0xa0,0x1c,0x50,0x13,0xa, 0x3e,0x12,0x49,0x93,0xa, 0x4a,0x19,0xb4,0x1f,0x44, +0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f,0x8a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee, +0x80,0x24,0xa, 0x3e,0x9, 0xa3,0x2a,0xb9,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, +0x3c,0x2d,0x32,0x12,0x49,0x93,0xa, 0x4a,0x19,0xb4,0x1f,0x60,0x7e,0xb3,0x2a,0xfb, +0x19,0xb4,0x1f,0xa6,0xb, 0xe0,0xbc,0xde,0x38,0xd8,0x7e,0xb3,0x2a,0xfd,0x7e,0x8, +0x1f,0xe4,0x60,0x9, 0x7e,0x18,0x1f,0xd0,0x12,0xc1,0xeb,0x80,0x3, 0x12,0xc3,0x3, +0x6c,0xee,0x7e,0x18,0x1f,0xe4,0x7a,0x1f,0x1f,0x34,0x74,0x2, 0xac,0xbe,0x49,0x35, +0x1f,0xd0,0x7a,0x37,0x1f,0x38,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xda,0x7a,0x37, +0x1f,0x3a,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x44,0x6d,0x22,0x7a,0x1f,0x1f, +0x3c,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x8a,0x7a,0x1f,0x1f,0x40,0x7e,0x8, +0x1f,0x34,0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2, +0xda,0x3b,0x22,0x2e,0x37,0x2a,0xfe,0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x3, +0xc2,0x12,0x4f,0xfd,0x12,0x13,0xf5,0x12,0xc2,0x77,0xe4,0x12,0xa, 0x66,0x7e,0x24, +0x3, 0xd4,0x12,0x4f,0xed,0x74,0x1, 0x12,0x48,0x34,0x12,0x4f,0xf4,0x7e,0x34,0xd0, +0xc, 0x12,0x1, 0xe, 0x12,0x48,0x63,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13, +0x1, 0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80,0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4, +0x7e,0x7b,0x60,0xa, 0x46,0x2e,0x44,0x20,0x7d,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4, +0x93,0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, +0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, +0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, +0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80, +0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12, +0x4a,0x8e,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f, +0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60,0xe, 0x12,0x4a,0x8e,0x60,0x5, 0x3e,0x44,0x14, +0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0x4a, +0x8e,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, +0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44, +0x0, 0x1, 0x7c,0xb6,0x22,0x7e,0x1f,0x25,0xf2,0x7e,0xf, 0x25,0xee,0x22,0x7a,0xb3, +0x2b,0x0, 0x70,0x5, 0x12,0x4a,0xb3,0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x4a,0x95,0x12, +0x48,0x2b,0x22,0x7e,0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x22,0x12,0xcc,0xcb,0xb4, +0x1, 0x17,0xca,0x39,0x7e,0x18,0x25,0xee,0x7e,0x8, 0x38,0xf0,0x12,0x20,0xc3,0x1b, +0xfd,0x12,0xcc,0xb9,0x12,0x4a,0x95,0x80,0x1a,0xca,0x39,0x7e,0x18,0x2b,0x70,0x7e, +0x8, 0x38,0xf0,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x37,0x2b,0x76,0x7a,0x37,0x34,0x88, +0x12,0x4a,0xb3,0x2, 0x48,0x2b,0xe5,0xd, 0x60,0x56,0xe5,0xd, 0x30,0xe0,0xa, 0x53, +0xd, 0xfe,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0xe5,0xd, 0x30,0xe1,0x14,0x53,0xd, +0xfd,0x7e,0xb3,0x38,0xf4,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12,0x6b,0xbb,0x12, +0x6c,0x3f,0xe5,0xd, 0x30,0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a,0xb3,0x38,0xf5,0x7e, +0xb3,0x38,0xf4,0x70,0xa, 0x74,0x1, 0x12,0x0, 0x1e,0x12,0x4a,0xb3,0x80,0x7, 0xe4, +0x12,0x0, 0x1e,0x12,0x4a,0x95,0x12,0x48,0x2b,0x7e,0xb3,0x2a,0xfc,0x2, 0x68,0x88, +0x22,0x30,0x6, 0x3b,0xc2,0x6, 0x12,0x26,0x2, 0x7e,0x73,0x38,0xb5,0x7a,0x73,0x2a, +0x4d,0x7e,0x73,0x38,0xb6,0x7a,0x73,0x2b,0x1d,0x7e,0x73,0x38,0xb6,0x7a,0x73,0x2b, +0x1, 0x7e,0xb3,0x38,0xb7,0x60,0x18,0x7e,0x34,0x0, 0x2, 0x12,0x4c,0xba,0x7e,0x34, +0x0, 0x1, 0x12,0x4c,0xba,0x6d,0x33,0x12,0x4c,0xba,0xe4,0x7a,0xb3,0x38,0xb7,0x12, +0x4a,0xf6,0x2, 0x4b,0x95,0xe5,0xc, 0x70,0x2, 0x81,0xb9,0xe5,0xc, 0x30,0xe0,0x10, +0x53,0xc, 0xfe,0x12,0x75,0x24,0x12,0x78,0x40,0x7e,0x8, 0x2a,0x6d,0x12,0x9, 0xa1, +0xe5,0xc, 0x30,0xe1,0x6, 0x53,0xc, 0xfd,0x12,0xc3,0x14,0xe5,0xc, 0x30,0xe2,0x32, +0x53,0xc, 0xfb,0x7e,0xb3,0x2b,0x12,0x60,0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x6, 0xba, +0x80,0xb, 0x7e,0xb3,0x2b,0x65,0x7e,0x73,0x2b,0x64,0x12,0xb, 0xad,0x7e,0x73,0x2b, +0x12,0x2e,0x70,0xff,0x92,0x4, 0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x2a,0x77,0x12, +0xb, 0x1e,0xe5,0xc, 0x30,0xe3,0x4c,0x53,0xc, 0xf7,0x7e,0x73,0x38,0xe2,0x7a,0x73, +0x2b,0xf, 0x12,0xaa,0x5d,0x7a,0xb3,0x2f,0xa9,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, +0x20,0x7e,0x73,0x2f,0xa9,0x7a,0x73,0x38,0xba,0x12,0x57,0xef,0x7e,0x8, 0x2a,0x6d, +0x12,0xd, 0x72,0x7e,0x73,0x38,0xe3,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b, +0x62,0xd2,0xe, 0x30,0xe, 0x7, 0x12,0x4f,0xfb,0xe4,0x12,0xa, 0x66,0x12,0x23,0x23, +0x12,0xa5,0xf5,0xe5,0xc, 0x30,0xe4,0xf, 0x53,0xc, 0xef,0x7e,0x43,0x38,0xe4,0x7e, +0x50,0xa, 0xac,0x45,0x12,0x4f,0xed,0xe5,0xc, 0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e, +0x73,0x38,0xd0,0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x38,0xd0,0xa9,0xd5, +0xcb,0x74,0xe, 0x12,0x4f,0x53,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63,0x38,0xd0,0xa, +0x26,0x2e,0x24,0x0, 0x3, 0x12,0x95,0x7, 0x7c,0x65,0x4c,0x76,0x74,0xe, 0x12,0x4e, +0xc7,0x12,0x4f,0x53,0x12,0x4f,0x5b,0x7e,0x73,0x38,0xd3,0x7a,0x73,0x2b,0x14,0x7e, +0x73,0x38,0xd2,0x7a,0x73,0x2b,0x1f,0x12,0xcc,0xc2,0xe5,0xc, 0x30,0xe5,0xa, 0x53, +0xc, 0xdf,0x7e,0xb3,0x38,0xba,0x2, 0x55,0x39,0x22,0xca,0xd8,0xca,0x79,0x7d,0xd3, +0x90,0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90,0x60,0x51,0xe4,0x93,0x7c,0x8b,0xa, 0x38, +0xa, 0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c,0x7c,0xe7,0x12,0x26,0x73,0xa9,0xd0,0xc4, +0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x4f,0x53,0x7c,0x8b,0x74,0x7, 0x7e,0x70,0xf, 0x12, +0x4f,0x58,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x33,0xcb,0x79,0x51,0x0, 0x6, 0x7e,0x54, +0x0, 0x80,0x7e,0x1f,0x33,0xcb,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f, +0x33,0xcb,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78,0xb, 0x7e,0x1f,0x33,0xcb, +0x12,0x4e,0xbf,0x44,0x1, 0x80,0x20,0x7e,0x1f,0x33,0xcb,0x12,0x4e,0xbf,0x44,0x8, +0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x33,0xcb,0x78,0x7, 0x12,0x4e,0xbf,0x54,0xfb, +0x80,0x5, 0x12,0x4e,0xbf,0x44,0x4, 0x12,0x4f,0xc2,0x69,0xe1,0x0, 0x84,0x69,0x51, +0x0, 0x90,0x7d,0xf5,0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3, +0x3, 0xcc,0xbe,0xb0,0x6, 0x40,0x3, 0xb4,0xff,0x1d,0x7e,0x1f,0x33,0xc7,0x2e,0x34, +0x0, 0x84,0xb, 0x1a,0x50,0x54,0xe6,0x12,0x4f,0xc2,0x2e,0x34,0x0, 0x84,0xb, 0x1a, +0x50,0x4e,0x54,0x1, 0xa4,0x80,0x1b,0x7e,0x1f,0x33,0xc7,0x2e,0x34,0x0, 0x84,0xb, +0x1a,0x50,0x5e,0x54,0xfe,0xe6,0x12,0x4f,0xc2,0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50, +0x44,0xa4,0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x2d,0x7e,0x1f,0x33,0xcb,0x12, +0x4e,0xbf,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xcb,0x12,0x4e,0xbf, +0x44,0x50,0x1b,0x1a,0x50,0x7e,0x34,0x0, 0x2, 0x12,0x4f,0xa3,0x12,0x58,0xa1,0x12, +0x4f,0xca,0x7a,0x37,0x34,0x90,0xc1,0x7b,0x6c,0xdd,0xc1,0x75,0x4c,0xdd,0x78,0x4, +0x6c,0x99,0x80,0x2b,0xbc,0xfd,0x40,0x12,0xa, 0xcd,0x9, 0x9c,0x2a,0xb8,0xbe,0x90, +0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, 0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3, +0x9, 0x9c,0x2a,0xdb,0xbe,0x90,0x1c,0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x7e, +0x1f,0x33,0xcb,0x12,0x4e,0xbf,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0xa, 0xc9,0x3e, +0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x7e,0x1f,0x33,0xcb,0x12,0x4e,0xbf,0x4d,0x5c, +0x1b,0x1a,0x50,0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34, +0x0, 0x2, 0x80,0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x4f,0xa3,0x12,0x58,0xa1,0xbe,0xd4, +0x0, 0x1, 0x78,0x10,0x12,0x58,0xa1,0x12,0x4f,0xca,0x74,0x2, 0xac,0xbd,0x59,0x35, +0x34,0x92,0x80,0xf, 0x12,0x4f,0xca,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59, +0x32,0x34,0x92,0xb, 0xd0,0xbc,0xed,0x28,0x2, 0xa1,0xdc,0xa9,0xd5,0xcb,0x74,0x7, +0x7c,0x78,0x12,0x4f,0x58,0xa9,0xc0,0xc4,0x7e,0x1f,0x33,0xc7,0x79,0xe1,0x0, 0x84, +0x7e,0x1f,0x33,0xc7,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x33,0xcb,0x79,0x30, +0x0, 0x6, 0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x33,0xcb,0x79,0x30, +0x0, 0x10,0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x2e, +0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xca,0x79,0xa9, +0xd5,0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x4e,0xc7,0x74,0xf, 0x12,0x4f,0x53,0x7c, +0xfb,0x74,0xf, 0x7c,0x7f,0x5e,0x70,0xfe,0x12,0x4e,0xc7,0x74,0xc, 0x12,0x4f,0x53, +0x7c,0xfb,0x54,0x7f,0x68,0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x4e,0xc7,0x90,0x61, +0x18,0xe4,0x93,0x7c,0xab,0xbe,0xa0,0x7, 0x38,0xb, 0x12,0x4f,0x90,0x7c,0xb7,0xa, +0x7b,0xb, 0x75,0x80,0x16,0x90,0x61,0x17,0xe4,0x93,0xb4,0x1, 0xe, 0xbe,0xa0,0x7, +0x28,0x9, 0x12,0x4f,0x90,0xa, 0x77,0x2e,0x74,0x0, 0x7, 0x74,0xe, 0x7c,0x7f,0x12, +0x4e,0xc7,0x74,0x7, 0x12,0x4f,0x53,0x7c,0xfb,0x5e,0xf0,0xfb,0x90,0x60,0x2, 0xe4, +0x93,0xa, 0x3b,0x3e,0x34,0x3e,0x34,0x4c,0xf7,0x74,0x7, 0x7c,0x7f,0x12,0x4f,0x58, +0xda,0x79,0x22,0xf5,0xfd,0xe5,0xfe,0x22,0x12,0x4e,0xc7,0x75,0xfd,0xff,0xa9,0xc5, +0xcb,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x12,0x12,0x64,0x30,0xe5, +0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, 0x7e,0x71,0x27,0x12,0x4e,0xc7,0x74, +0xb, 0x7e,0x71,0x2f,0x12,0x4e,0xc7,0x74,0xc, 0x7e,0x71,0x30,0x12,0x4f,0x58,0x22, +0xa, 0x3a,0x2e,0x34,0x0, 0x3, 0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x7e, +0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e,0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x67, +0x6e,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, 0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78, +0xe6,0x22,0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xc7,0x22,0x7e,0xf, 0x33,0xcb,0x69,0x30, +0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74,0x7, +0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x7d,0x32,0x74, +0xfa,0x2, 0x12,0xd0,0x7e,0x8, 0x2a,0x6d,0x2, 0x0, 0x2e,0xc2,0xe, 0x7e,0x8, 0x2a, +0x6d,0x12,0x3, 0x8b,0x7e,0x8, 0x2a,0x6d,0x74,0x3, 0x2, 0x11,0x7a,0xca,0xf8,0x7c, +0x6b,0xa5,0xbe,0x0, 0x9, 0x7c,0xb7,0x12,0x53,0x63,0xd2,0x6, 0x41,0xae,0xa5,0xbe, +0x1, 0x3d,0x7a,0x73,0x38,0xb1,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, +0xd2,0x7, 0x41,0xae,0xa5,0xbf,0xaa,0x5, 0x12,0x54,0xc0,0x80,0x1e,0xa5,0xbf,0xab, +0xa, 0x7e,0x34,0x5, 0x7a,0x7a,0x37,0x34,0x8a,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80, +0x2, 0x41,0xae,0x7e,0x34,0x4, 0xfc,0x7a,0x37,0x34,0x8a,0x6d,0x33,0x21,0x1e,0xbe, +0x60,0x4, 0x40,0x25,0xbe,0x60,0x8, 0x38,0x20,0xd2,0x6, 0xa, 0x26,0x19,0x72,0x38, +0xb0,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, 0x41,0xae,0xa5,0xbe,0x8, 0x2, +0x80,0x2, 0x41,0xae,0x12,0x54,0xba,0x41,0xae,0xa5,0xbe,0xa, 0x9, 0x43,0xc, 0x20, +0x7a,0x73,0x38,0xba,0x41,0xae,0xa5,0xbe,0xb, 0xd, 0xd2,0x6, 0xa, 0x26,0x19,0x72, +0x38,0xb0,0x12,0x54,0xbd,0x41,0xae,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c,0x38, +0x2, 0x41,0x43,0xbe,0x60,0x1e,0x40,0x10,0xbe,0x60,0x23,0x38,0xb, 0xa, 0x26,0x19, +0x72,0x38,0xb0,0x43,0xc, 0x40,0x41,0xae,0xbe,0x60,0x15,0x40,0x1d,0xbe,0x60,0x18, +0x38,0x18,0xa, 0x26,0x19,0x72,0x38,0xb0,0xd2,0x6, 0xa5,0xbe,0x15,0x2, 0x80,0x2, +0x41,0xae,0x74,0x7, 0x7a,0xb3,0x38,0xb4,0x41,0xae,0xa5,0xbe,0x19,0x7, 0xe4,0x7a, +0xb3,0x38,0xc9,0x41,0xae,0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0x41, +0x43,0xa5,0xbe,0x2d,0x1e,0xa, 0x26,0x19,0x72,0x38,0xb0,0x20,0x7, 0x2, 0x41,0xae, +0x7e,0x63,0x38,0xdc,0x7c,0x46,0x6c,0x55,0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35, +0x8, 0x41,0xae,0xbe,0x60,0x2f,0x40,0xa, 0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, +0x41,0x43,0xa5,0xbe,0x34,0xf, 0x43,0xc, 0x10,0xbe,0x70,0x64,0x38,0x2, 0x41,0x43, +0x7e,0x70,0x64,0x41,0x43,0xbe,0x60,0x38,0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, +0x1, 0x7e,0xf3,0x38,0xd5,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd5,0xa, 0x2f,0x19,0x72, +0x2b,0x21,0xa5,0xbe,0x39,0x2, 0x80,0x2, 0x41,0xae,0x75,0x1a,0x38,0x41,0xae,0xbe, +0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21,0x43,0xc, 0x2, 0x7e,0xf3,0x38,0xd7,0x7c, +0xbf,0x4, 0x7a,0xb3,0x38,0xd7,0xa, 0x2f,0x19,0x72,0x2b,0x44,0xa5,0xbe,0x3b,0x2, +0x80,0x2, 0x41,0xae,0x75,0x1a,0x3a,0x41,0xae,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, +0x7a,0x73,0x2b,0x12,0x41,0xae,0xa5,0xbe,0x50,0x6, 0x7a,0x73,0x39,0x0, 0x41,0xae, +0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xd9, +0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd9,0xa, 0x2f,0x19,0x72,0x2a,0x7a,0xa5,0xbe,0x3d, +0x2, 0x80,0x2, 0x41,0xae,0x75,0x1a,0x3c,0x41,0xae,0xbe,0x60,0x3e,0x68,0x4, 0xa5, +0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xdb,0x7c,0xbf,0x4, 0x7a,0xb3,0x38, +0xdb,0xa, 0x2f,0x19,0x72,0x2a,0x9d,0xa5,0xbe,0x3f,0x2, 0x80,0x2, 0x41,0xae,0x75, +0x1a,0x3e,0x41,0xae,0xbe,0x60,0x40,0x40,0x10,0xbe,0x60,0x42,0x38,0xb, 0xa, 0x26, +0x19,0x72,0x38,0xb0,0x75,0xd, 0x1, 0x80,0xd, 0xa5,0xbe,0x43,0xe, 0xa, 0x26,0x19, +0x72,0x38,0xb0,0x75,0xd, 0x2, 0x12,0x47,0xfc,0x41,0xae,0xa5,0xbe,0x44,0xb, 0xa, +0x26,0x19,0x72,0x38,0xb0,0x12,0x4a,0xbc,0x80,0x74,0xbe,0x60,0x45,0x68,0x4, 0xa5, +0xbe,0x46,0x8, 0xa, 0x26,0x19,0x72,0x38,0xb0,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, +0xa5,0xbe,0x4f,0x20,0x43,0xd, 0x4, 0x7e,0xf3,0x38,0xf6,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xf6,0xa, 0x2f,0x2e,0x27,0x34,0x88,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75, +0x1a,0x4e,0x80,0x3a,0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0, +0x40,0x25,0xbe,0x60,0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7, +0xa5,0xbe,0xf3,0x1a,0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x34,0x8c, +0x2d,0x30,0x1b,0x1a,0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8, +0x22,0x7c,0x6b,0x12,0x53,0x10,0x78,0x5, 0x7c,0xb6,0x2, 0x53,0x18,0xb4,0x4, 0x5, +0x7c,0xb6,0x2, 0x50,0xd, 0x22,0x30,0x90,0x19,0xc2,0x90,0xe5,0x18,0x70,0x9, 0x75, +0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80,0x11,0x7e,0x71,0x91,0xe5,0x1a,0x12,0x52,0xb1, +0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x1a,0xe5,0x1a,0x12,0x52,0xf1,0xf5,0x91, +0x22,0x7c,0x7b,0x6c,0xaa,0x12,0x53,0x10,0x78,0x9, 0x7c,0xb7,0x12,0x53,0xf1,0x7c, +0xab,0x80,0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x43,0x86,0x7c,0xab,0x7c,0xba,0x22, +0x7e,0xb3,0x38,0xb0,0xc4,0x54,0x7, 0x22,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, +0x7c,0xba,0x12,0x53,0x63,0x80,0x2c,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, +0x7c,0xb3,0x7c,0x7a,0x12,0x80,0xc0,0x80,0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30, +0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x81,0x58,0xa5,0xbb,0x8f,0x3, +0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, 0x53,0x8e,0x74,0x1, 0x7a,0xb3, +0x39,0xf8,0x22,0x7a,0xb3,0x38,0xb0,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, 0xb4, +0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3,0x3, +0xc2,0x22,0x74,0x1, 0x7a,0xb3,0x3, 0xc2,0xe4,0x7a,0xb3,0x38,0xb0,0x22,0x24,0xab, +0x68,0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, +0x80,0x2d,0x7e,0xb3,0x39,0xf8,0xb4,0x5, 0x2a,0x12,0x4f,0x9f,0x12,0xc0,0x9b,0x2, +0x53,0xda,0x7e,0xb3,0x39,0xf8,0xb4,0x5, 0x1a,0x12,0x4f,0x9f,0x75,0xe9,0xff,0x22, +0x7e,0xb3,0x39,0xf8,0xb4,0x5, 0xc, 0x12,0x4f,0x9f,0x2, 0x53,0xd4,0x74,0x1, 0x7a, +0xb3,0x39,0xf8,0x22,0x75,0xe7,0x6b,0x2, 0x53,0xda,0xe4,0x7e,0x34,0xd7,0xfc,0x7e, +0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff, +0x22,0x70,0x5, 0x7e,0xb3,0x38,0xb0,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x1d,0x0, +0x30,0x10,0x6, 0x7e,0x18,0x35,0xa6,0x80,0x4, 0x7e,0x18,0x35,0xe4,0x7a,0x1d,0x14, +0x80,0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1d,0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d, +0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4, +0xd3,0x8, 0x6d,0x33,0x7a,0x37,0x39,0x1, 0x80,0x2, 0x15,0x1a,0x2, 0x80,0x21,0xbe, +0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x54,0x88,0xbe,0xb0,0x80,0x40,0xc, 0xbe, +0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x3, 0x1b,0x22,0xb4,0xfc,0x5, 0x7e,0xb3, +0x3, 0xc2,0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e,0xb3,0x28,0xa8,0x60,0x3, 0x4e,0xa0, +0x1, 0x7e,0xb3,0x37,0xe4,0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba,0x22,0xb4,0xfe,0x5, +0x7e,0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x39,0x6, +0x7e,0x73,0x39,0x6, 0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x6c,0xb9,0x7c,0xab,0x7c, +0xb7,0x4, 0x7a,0xb3,0x39,0x6, 0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x39,0x6, 0x6d,0x33, +0x7a,0x37,0x39,0x3, 0x75,0x1a,0xeb,0x7c,0xba,0x22,0xb2,0x86,0x22,0xb2,0x82,0x22, +0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x34,0x8a,0x22,0x12,0x54,0xc0,0x12,0xcc,0xb9,0x6d, +0x33,0x7a,0x35,0xa, 0x12,0x55,0x18,0x12,0x54,0xf2,0x74,0x50,0x7a,0xb3,0x38,0xe4, +0x7e,0x24,0x3, 0x20,0x12,0x4f,0xed,0xe4,0x12,0xcc,0x32,0x6d,0x33,0x7a,0x37,0x3, +0xfc,0x22,0x7e,0x73,0x2b,0x62,0x7a,0x73,0x38,0xe3,0x22,0xa2,0xc, 0xe4,0x33,0x7a, +0xb3,0x38,0xde,0x7e,0x73,0x38,0xe2,0xbe,0x73,0x2b,0xf, 0x68,0xa, 0xe5,0xc, 0x70, +0x6, 0x12,0x55,0x18,0x12,0x54,0xf2,0x22,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xe2, +0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xd2,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xd1, +0x7e,0x73,0x2b,0x14,0x7a,0x73,0x38,0xd3,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90, +0x61,0xcb,0xe4,0x93,0x7c,0xab,0xbe,0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff, +0x80,0xb, 0x12,0x55,0xaa,0x38,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38, +0xf1,0x80,0x1a,0xbe,0xd0,0x81,0x78,0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x55, +0xaa,0x40,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38, +0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0xa6,0xc9,0x12,0x55,0x30,0x7e,0x73,0x2b,0x1f,0x7a, +0x73,0x38,0xd2,0x12,0x55,0xc6,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xe2,0x12,0x54, +0xf2,0x7a,0xd3,0x38,0xba,0xda,0x79,0xda,0xd8,0x22,0x7e,0x90,0x5, 0xac,0x9f,0x9, +0xb4,0x26,0x33,0xbc,0xbe,0x22,0x30,0x3, 0x3, 0x12,0x55,0x30,0xa2,0x4, 0x92,0x5, +0x12,0x7c,0xdb,0x2, 0x55,0xc6,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xd1,0x22,0x74, +0x40,0x7a,0xb3,0x2b,0x20,0x12,0xae,0xc7,0x50,0x9, 0xd2,0x3, 0xd2,0x4, 0x12,0x55, +0xb6,0x80,0x1c,0x74,0x1, 0x12,0x56,0xd, 0x7e,0x43,0x38,0xcf,0x7e,0x50,0x64,0xac, +0x45,0x12,0x88,0x52,0x7a,0xb3,0x2b,0x1f,0x7e,0xf, 0x33,0xe0,0x12,0x56,0x93,0x12, +0x55,0xc6,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xd2,0x2, 0x55,0x30,0xca,0x3b,0x7c, +0xdb,0xe4,0x7a,0xb3,0x2b,0x14,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0x7e,0xc0,0xa, +0x12,0x7c,0xcc,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x1f,0x33,0xe0,0x12, +0x88,0xc6,0x7d,0x73,0xbe,0x74,0xff,0xff,0x78,0xc, 0x12,0x56,0x8a,0xb, 0xa, 0x30, +0x2e,0x34,0x0, 0x3, 0x80,0x1e,0xbe,0x74,0x80,0x0, 0x28,0xa, 0x12,0x56,0x8a,0xb, +0xa, 0x30,0xb, 0x35,0x80,0xe, 0xbe,0x74,0x40,0x0, 0x28,0xf, 0x12,0x56,0x8a,0xb, +0xa, 0x30,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xb5,0xbe,0xd0,0x1, 0x78,0x9, +0x7e,0x1f,0x33,0xe0,0x12,0x88,0x71,0x7d,0x73,0x7e,0x1f,0x33,0xcf,0x69,0x31,0x0, +0x1a,0x7a,0x73,0x2b,0x14,0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x33,0xcf,0x2e,0x14, +0x0, 0x1a,0x22,0x12,0x56,0x9d,0xb, 0x34,0x7a,0x73,0x2b,0x20,0x22,0xca,0x79,0x7f, +0x10,0x9f,0x0, 0x12,0x57,0xf7,0x4c,0xaa,0x78,0x6, 0x7e,0x34,0x0, 0x40,0x80,0x6c, +0x6c,0x99,0x80,0x38,0xa, 0xe9,0x2e,0xe4,0x60,0xac,0x7d,0x7e,0x7a,0xf1,0x82,0x7a, +0xe1,0x83,0xe4,0x93,0x7c,0x8b,0x90,0x60,0xaa,0xe4,0x93,0x70,0xe, 0x7e,0xf3,0x2a, +0x6e,0xac,0xf8,0x7e,0xb3,0x2a,0x70,0xa, 0xfb,0x2d,0xf7,0x7d,0xef,0x3e,0xe4,0x7f, +0x61,0x2d,0xde,0xb, 0x6a,0xd0,0x6d,0xcc,0x2f,0x6, 0xb, 0x90,0xbc,0xa9,0x38,0xc4, +0xbe,0x8, 0x0, 0x0, 0x78,0x2, 0xb, 0xc, 0xa, 0x5a,0x6d,0x44,0x7f,0x10,0x7f,0x2, +0x12,0x1f,0x7, 0x7f,0x1, 0xb, 0xc, 0x7e,0x34,0xc4,0x0, 0x7e,0x24,0x0, 0x9, 0x12, +0x1f,0x7, 0xbe,0x34,0x0, 0xfa,0x28,0x4, 0x7e,0x34,0x0, 0xfa,0xda,0x79,0x22,0x7e, +0xb, 0x70,0x7a,0x73,0x2b,0xf, 0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62,0x29,0x70, +0x0, 0x1, 0x7a,0x73,0x2b,0x14,0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20,0x12,0x57, +0xef,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0xd2,0x3, 0xc2,0x4, 0x2, 0x55,0xb6,0xca, +0xf8,0x6c,0xff,0x80,0x34,0x7e,0x73,0x2f,0xa9,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, +0xac,0x3f,0x12,0x57,0xcb,0xca,0x39,0x7e,0x30,0x38,0xac,0x3f,0x12,0x57,0xe4,0x12, +0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12, +0x57,0xd9,0x12,0x20,0xc3,0x1b,0xfd,0xb, 0xf0,0x90,0x61,0xcb,0xe4,0x93,0xbc,0xbf, +0x38,0xc3,0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x5, 0xac,0x23,0x12,0x57,0xcb,0xca,0x39, +0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x38,0xac,0x23,0x12,0x57,0xe4,0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x8c,0xac,0x23, +0x12,0x57,0xd9,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8,0x22,0x2e,0x14,0x26,0x33,0x6d, +0x0, 0x12,0x57,0x1f,0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x30,0x8a,0x6d,0x0, 0x7e, +0x18,0x32,0xba,0x22,0x2e,0x14,0x2f,0xaa,0x6d,0x0, 0x7e,0x18,0x34,0x0, 0x22,0x12, +0x57,0xff,0x7a,0x37,0x2b,0x1b,0x22,0x90,0x60,0xa7,0xe4,0x93,0x7c,0xab,0x22,0x7e, +0x23,0x2b,0xf, 0x7e,0x33,0x38,0xe1,0x7e,0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x0, 0xac,0x23,0x2d,0x10,0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, +0x7e,0x63,0x2b,0x10,0xbe,0x14,0xf, 0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c,0xbe,0x14, +0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x21,0xbe,0x14,0x3, 0x84,0x40,0x16,0x90,0x61,0x1b, +0xe4,0x93,0x7c,0x7b,0xbe,0x70,0x1, 0x28,0x4, 0x74,0x1, 0x80,0xb, 0x7a,0x73,0x2b, +0x10,0x80,0x9, 0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x7e,0x73,0x2b,0x10, +0xbc,0x76,0x68,0x2, 0xd2,0xe, 0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17, +0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e,0x1f,0x33,0xc7,0x69,0x51,0x0, 0x86, +0x54,0x1f,0xa, 0x1, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, +0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x1f, +0x58,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x4, 0x7e,0xf, 0x33, +0xcb,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, 0x79, +0x30,0x0, 0x12,0x22,0xca,0xd8,0xca,0x79,0x7e,0x73,0x2a,0x6e,0x7e,0xf3,0x2a,0x6d, +0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x20,0xe8,0x7e,0xb3, +0x38,0xcb,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xcc,0xbe,0x70,0x0, 0x28,0x5b,0x6c,0xdd, +0x80,0x3c,0x12,0x26,0x73,0x12,0x28,0xa0,0x6d,0x33,0x80,0x28,0x7e,0x35,0x24,0x3e, +0x34,0x49,0x33,0xd, 0xc8,0x12,0x21,0x1a,0x7a,0x35,0x26,0x7e,0x35,0x24,0x7d,0x13, +0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26,0x58,0x7, 0x7e,0x25,0x26,0x59,0x21, +0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75,0x24,0x38,0xd0,0xb, 0xd0,0x7e,0x73, +0x38,0xcc,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34, +0x7e,0x8, 0xd, 0xc8,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x7e,0x8, +0x39,0x7, 0x12,0x59,0x85,0x7e,0x8, 0x39,0xf, 0x12,0x59,0x85,0x12,0x59,0x9a,0x12, +0x59,0xa1,0x2, 0x59,0x65,0x7e,0x37,0x39,0x7, 0xbe,0x34,0x0, 0x0, 0x28,0x15,0x7e, +0x73,0x3, 0xff,0xbe,0x70,0x5, 0x50,0xc, 0x7e,0xb3,0x3, 0xeb,0x70,0x6, 0x12,0x59, +0xa8,0x12,0x5e,0xc, 0x22,0xb, 0xa, 0x30,0xe5,0x62,0xa, 0x2b,0xbd,0x32,0x28,0x4, +0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x8, 0x2b,0xb7,0x2, 0x59, +0x85,0x7e,0x8, 0x39,0xdd,0x2, 0x59,0x85,0x6d,0x33,0x7a,0x37,0x39,0x97,0x22,0xca, +0xf8,0x7e,0xa3,0x2a,0x2, 0x7e,0xb3,0x2a,0x3, 0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0, +0x1, 0x38,0x1c,0x7e,0x47,0x28,0x86,0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e, +0xf3,0x2f,0x80,0x4c,0xff,0x68,0x17,0x7e,0x47,0x2b,0xb7,0x4d,0x44,0x78,0xf, 0x12, +0x59,0xa8,0x74,0x1, 0x7a,0xb3,0x39,0x99,0x7a,0xb3,0x3, 0xc0,0x80,0x35,0x4c,0xaa, +0x78,0x36,0xb4,0x1, 0x33,0x7e,0x37,0x2b,0xb7,0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f, +0x80,0xb4,0x3, 0x1f,0x7e,0x37,0x2b,0xb7,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, +0x7a,0xb3,0x2f,0x80,0x7e,0x37,0x2f,0x98,0x7e,0x27,0x2f,0x9a,0x12,0x5a,0xc0,0x41, +0xb9,0x80,0x0, 0x12,0xc8,0x97,0x41,0xb9,0x7e,0xc7,0x29,0x8, 0x7e,0xd7,0x29,0xa, +0x4c,0xff,0x78,0x19,0x70,0x57,0xbe,0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12, +0xc8,0x32,0x12,0x5a,0xbc,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x40,0xbe,0xf0,0x1, +0x78,0x2e,0x7e,0x27,0x2f,0x88,0x9e,0x27,0x2f,0x90,0x7e,0x14,0x62,0x90,0x12,0x5b, +0x79,0xbd,0x23,0x38,0x13,0x7e,0x27,0x2f,0x96,0x9e,0x27,0x2f,0x8e,0x7e,0x14,0x62, +0x92,0x12,0x5b,0x79,0xbd,0x23,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, +0xbe,0xf0,0x3, 0x78,0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f, +0x80,0x60,0x26,0x7d,0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12, +0x5d,0x78,0xa, 0x2b,0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x5a, +0xbc,0x7a,0xc7,0x2b,0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d, +0x7d,0x42,0x7d,0x13,0x7d,0x24,0x12,0x5e,0xfe,0x7d,0x31,0x12,0xc7,0xc6,0x2, 0x5a, +0xd1,0x7e,0x3, 0x2f,0xa8,0xbe,0x0, 0xf0,0x50,0x2, 0x61,0x6a,0x61,0x5f,0x6c,0x99, +0x7e,0xb3,0x2f,0x7f,0xbe,0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f, +0x2b,0xbf,0x7a,0x1f,0x1f,0x34,0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49, +0x35,0x2b,0xbf,0x49,0x25,0x2b,0xc1,0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12, +0x5d,0x78,0x7c,0x1b,0x7e,0x3, 0x2f,0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70, +0x4, 0xac,0x78,0x2e,0x34,0x2b,0xbf,0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1f,0x8c, +0x7e,0x34,0x1f,0x34,0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12, +0x1f,0x8c,0xb, 0x80,0x7e,0x3, 0x2f,0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54, +0x7c,0xb, 0x7a,0x3, 0x2f,0xa8,0x7e,0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xb, 0x7e, +0x3, 0x2f,0xa8,0xbe,0x0, 0xec,0x40,0x2, 0x41,0xde,0x22,0x7d,0x34,0x9e,0x34,0x0, +0x40,0x7d,0x2e,0x9d,0x23,0x7e,0x14,0x61,0x49,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30, +0x22,0x7d,0xe3,0x9f,0x11,0x7e,0x14,0x61,0x43,0x12,0x5e,0xaa,0x90,0x61,0x35,0xe4, +0x93,0x70,0x3, 0x7d,0x3e,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83, +0x2a,0x6f,0x80,0x4, 0x7e,0x83,0x2a,0x70,0x12,0x5f,0xf3,0xbe,0xe4,0x0, 0x3f,0x38, +0x1e,0x7e,0x24,0x0, 0x3f,0x9d,0x2e,0x7e,0x14,0x61,0x47,0x12,0x5b,0x79,0x12,0x5c, +0xbe,0x90,0x61,0x45,0x12,0x5c,0xb5,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0x12, +0x57,0xf7,0xbe,0xa0,0x0, 0x28,0x3a,0x7d,0x14,0x9e,0x14,0x0, 0x3f,0xbd,0x1e,0x38, +0x17,0x12,0x5d,0x66,0x2d,0x10,0xbd,0x1e,0x40,0xe, 0x12,0x5b,0x6b,0x12,0x5c,0xa8, +0x48,0x36,0x7f,0x10,0x1b,0x1c,0x80,0x30,0x12,0x5d,0x66,0x2d,0x10,0xbd,0x1e,0x50, +0x31,0x7d,0x34,0x9e,0x34,0x0, 0x20,0x12,0x5b,0x71,0x12,0x5c,0xbe,0x7d,0x1f,0x80, +0x1d,0x4c,0xaa,0x78,0x1d,0x12,0x5d,0x5f,0xbd,0x5e,0x38,0x16,0x12,0x5b,0x6b,0x12, +0x5c,0xa8,0x48,0x4, 0x7f,0x10,0x1b,0x1c,0xa, 0xb, 0x7d,0x1f,0x9d,0x10,0x6d,0x0, +0x2f,0x10,0xbe,0xe4,0x0, 0x3f,0x28,0x6f,0x12,0x5d,0x5f,0xbd,0x5e,0x28,0x68,0x7d, +0xd4,0xb, 0xd4,0x1e,0xd4,0x7d,0x5d,0x1b,0x54,0xbd,0x5e,0x40,0xc, 0x7d,0x35,0x9d, +0x3e,0x6d,0x22,0x7e,0x14,0x61,0x4b,0x80,0xa, 0x7d,0x3e,0x9d,0x3d,0x6d,0x22,0x7e, +0x14,0x61,0x4d,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10,0x12,0x1e,0xfc,0x12,0x5c,0xc2, +0xbd,0x5e,0x7d,0x1f,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d,0x0, 0x9f,0x1, 0x7f,0x10, +0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0x90,0x61,0x45,0x12,0x5c,0xb5,0x58,0x4, +0x7f,0x10,0x80,0x13,0x90,0x61,0x46,0xe4,0x93,0xa, 0xb, 0x7d,0x1f,0x9d,0x10,0x6d, +0x0, 0xbf,0x10,0x8, 0x2, 0x7f,0x10,0x22,0xad,0x32,0x6d,0x22,0x7c,0x76,0x7c,0x65, +0x1a,0x24,0x90,0x61,0x46,0xe4,0x93,0xa, 0x1b,0x6d,0x0, 0xbf,0x10,0x22,0xad,0x32, +0x6d,0x22,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x7e,0x73,0x37,0xdc,0x7a,0x73,0x38, +0x52,0x7e,0x27,0x33,0xdd,0x7e,0x14,0x61,0xce,0x12,0x5b,0x79,0x1e,0x34,0xbd,0x32, +0x50,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xdc,0x7e,0x14,0x61,0xce,0x12,0x5b,0x79,0xbd, +0x32,0x50,0x8, 0xe4,0x7a,0xb3,0x37,0xda,0x12,0x5e,0x13,0x7e,0x37,0x37,0xe2,0xbd, +0x32,0x50,0x4, 0x7a,0x27,0x37,0xe2,0x12,0x5f,0xeb,0x38,0xa, 0x12,0x5f,0xe3,0x38, +0x5, 0x12,0x5f,0xdb,0x28,0x3d,0x12,0x5e,0x1a,0x7e,0x14,0x61,0xce,0x12,0x5b,0x79, +0x1e,0x34,0x1e,0x34,0xbd,0x32,0x28,0x21,0x7e,0xb3,0x37,0xda,0x4, 0x7a,0xb3,0x37, +0xda,0x7e,0x73,0x37,0xda,0xbe,0x70,0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x37,0xda, +0x12,0xa7,0x57,0x7a,0xb3,0x38,0x4f,0x80,0x5, 0xe4,0x7a,0xb3,0x37,0xda,0x7d,0x32, +0x2, 0xa8,0x1c,0x2, 0x5d,0x56,0x12,0x5e,0x71,0xe4,0x7a,0xb3,0x37,0xe8,0x22,0x7d, +0x54,0x9e,0x54,0x0, 0x3f,0x22,0x7d,0x4, 0x9e,0x4, 0x0, 0x1f,0x7e,0xd4,0x60,0xd1, +0x7e,0xc4,0x0, 0xff,0xb, 0x6a,0x10,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x21, +0x1a,0x7c,0xa7,0x12,0x5f,0xc4,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22, +0x7d,0x13,0x7e,0x54,0x62,0x5e,0x12,0x5d,0xbf,0x50,0x21,0x7e,0x54,0x62,0x60,0x12, +0x5d,0xbf,0x28,0x18,0x7e,0x14,0x62,0x62,0x12,0x5b,0x79,0xbd,0x32,0x50,0xd, 0x7e, +0x14,0x62,0x64,0x12,0x5b,0x79,0xbd,0x32,0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22,0x7e, +0x44,0x0, 0xff,0xb, 0x2a,0x30,0xbd,0x31,0x22,0x12,0x5c,0xc9,0x2, 0x5d,0xcf,0x7e, +0xb3,0x37,0xdc,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xe4,0x7e,0xb3,0x38,0x52,0x70, +0x3, 0x12,0x5e,0x7b,0x7e,0xb3,0x37,0xe4,0xb4,0x1, 0xc, 0x74,0x3, 0x12,0x5e,0x3, +0x12,0x23,0x74,0x3e,0x34,0x80,0x7, 0xe4,0x12,0x5e,0x3, 0x12,0x23,0x74,0x7a,0x37, +0x2a,0x62,0x22,0x7a,0xb3,0x36,0xa0,0x7e,0x34,0x61,0x5d,0x22,0x74,0x1, 0x7a,0xb3, +0x3, 0xc0,0x22,0x74,0x2, 0x7a,0xb3,0x37,0xdc,0x22,0x7e,0xb3,0x37,0xe8,0xb4,0x1, +0x3, 0x2, 0x5e,0x13,0x7e,0xb3,0x38,0x4e,0x4, 0x7a,0xb3,0x38,0x4e,0x7e,0xb3,0x37, +0xdc,0xb4,0x2, 0x18,0x7e,0xb3,0x38,0x4d,0x4, 0x7a,0xb3,0x38,0x4d,0xb4,0x1, 0x6, +0x74,0x1, 0x7a,0xb3,0x38,0x4e,0x74,0x1, 0x7a,0xb3,0x37,0xdc,0x7e,0x73,0x38,0x4d, +0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xe8,0x12,0x5e,0x13,0x12,0x5e, +0x7b,0x12,0x5e,0x71,0x7e,0x73,0x38,0x4e,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0x5e,0x71, +0x22,0xe4,0x7a,0xb3,0x38,0x4e,0x7a,0xb3,0x38,0x4d,0x22,0xe4,0x7a,0xb3,0x37,0xda, +0x6c,0xaa,0x80,0xd, 0x6d,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37,0xf1,0xb, +0xa0,0x12,0x5f,0xcb,0x38,0xee,0xe4,0x7a,0xb3,0x37,0xdb,0x6d,0x33,0x7a,0x37,0x37, +0xe2,0x7a,0x37,0x37,0xd7,0x22,0x7e,0x14,0x62,0x94,0x7e,0x4, 0x0, 0xff,0xb, 0xa, +0xf0,0x22,0x12,0xcc,0x30,0x12,0x59,0xa8,0x7a,0x37,0x3, 0xfc,0x12,0x5e,0xda,0x12, +0x28,0x86,0x2, 0x5e,0xc5,0x7e,0x70,0xa, 0x12,0x0, 0x6e,0x50,0x3, 0x7e,0x70,0x19, +0x7a,0x73,0x36,0x7c,0xe4,0x7a,0xb3,0x36,0x7d,0x22,0x7e,0x34,0xd, 0xac,0x12,0x26, +0x77,0x12,0x6a,0x92,0x12,0x5f,0x1f,0x2, 0x5e,0xea,0x30,0x11,0x10,0x12,0xae,0xc7, +0x50,0x3, 0x12,0x57,0x4f,0x12,0x78,0xac,0x12,0x5f,0x45,0xc2,0x11,0x22,0x7e,0xa3, +0x2f,0xa8,0xbe,0xa0,0xf0,0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0x5f, +0xd3,0x59,0x25,0x2b,0xc1,0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e, +0xb3,0x2b,0x1e,0x70,0x1f,0x12,0x26,0x73,0x12,0x6f,0xca,0x50,0xfb,0x12,0x78,0xac, +0x12,0x87,0x5c,0x20,0x11,0x3, 0x12,0x5f,0x45,0x74,0x2, 0x7a,0xb3,0x2b,0x1e,0xe4, +0x7a,0xb3,0x16,0x91,0x22,0xca,0x3b,0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e, +0xf3,0x2b,0x62,0x12,0xaa,0x61,0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12, +0xcc,0xa8,0xf5,0x29,0x7e,0x73,0x2b,0xf, 0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, +0xac,0x7d,0xa, 0x2c,0x12,0x6f,0xe8,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, +0x7e,0x14,0x2, 0xe0,0xad,0x10,0x2e,0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e, +0x70,0x1d,0xac,0x7e,0x2e,0x34,0x38,0x58,0x6d,0x22,0x7a,0x1f,0x38,0x54,0x7c,0xbc, +0x12,0x7b,0xc8,0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f, +0x68,0x6, 0x7a,0xf3,0x2b,0x62,0xd2,0xe, 0xd2,0x3, 0x7e,0xb3,0x1f,0x33,0x12,0xa6, +0xa8,0xda,0x3b,0x22,0x7d,0x31,0x9d,0x30,0x2, 0x21,0x1a,0x90,0x61,0xcb,0xe4,0x93, +0xbc,0xba,0x22,0x7e,0xa3,0x2f,0xa8,0x74,0x4, 0xa4,0x22,0x7e,0x73,0x26,0xf5,0xbe, +0x70,0x0, 0x22,0x7e,0x73,0x26,0xf4,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x28,0x92,0xbe, +0x70,0x0, 0x22,0x7e,0x90,0x40,0xac,0x89,0x1b,0x44,0x22,0x2, 0x62,0xc1,0xff,0xff, +0x70,0x8f,0x0, 0xff,0xd0,0x2f,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x31,0x37,0x32,0x1, 0xd2,0x0, 0x31,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x8, 0xf7,0x44,0x32,0x5f,0x42,0x69,0x65,0x6c,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0xf, 0xe, 0xd, +0xc, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xb, 0xa, 0x9, 0x8, 0x18,0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x6, 0xb, 0x0, +0x0, 0x0, 0x64,0x0, 0xfa,0x1, 0x2c,0x2, 0xbc,0x2, 0xee,0x4, 0x1a,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x22,0x1, 0xf4,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x0, 0x4, 0x35,0x28,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x53,0x40,0xe, 0x19,0x27,0x13,0xd, 0x6, 0x80,0x13,0xd, 0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x46,0x45,0x2, 0x4e,0x2, 0x4e,0x1, +0x38,0x1, 0x3b,0x7, 0x80,0x46,0x48,0x2, 0xe, 0x2, 0xe, 0x1, 0x43,0x1, 0x43,0x0, +0xa0,0x0, 0x8c,0x0, 0x8c,0x0, 0xc8,0x0, 0x64,0x0, 0xb4,0x0, 0xb4,0xa, 0x0, 0x0, +0xdc,0x6, 0xa, 0x14,0x28,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0x8, 0x1, 0xd0,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x22,0x3, 0x35,0x53,0x28, +0x10,0x3, 0x32,0x52,0x28,0x19,0x3, 0x33,0x51,0x28,0x43,0x2, 0x3b,0x5c,0x28,0x22, +0x3, 0x35,0x53,0x28,0x22,0x3, 0x35,0x53,0x28,0x22,0x3, 0x35,0x53,0x28,0x22,0x3, +0x35,0x53,0x28,0x4, 0x5, 0xd, 0xe, 0xf, 0x10,0x11,0x4, 0x0, 0x96,0x1, 0x90,0x28, +0x1, 0x2c,0x1, 0x5e,0x0, 0xc8,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, 0x90, +0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, 0x50, +0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x8, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x32,0x1, 0xf4,0x1, 0xf4,0x2, 0x58,0x0, 0xc8, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0x7e,0x73,0x28,0x93,0x7a, +0x73,0x28,0x94,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, 0xe4,0x7a,0xb3,0x2a,0x6, +0x22,0x7e,0x37,0x34,0x38,0xb, 0x34,0x7a,0x37,0x34,0x38,0x7e,0x37,0x34,0x3a,0xbe, +0x37,0x34,0x38,0x28,0x3, 0x2, 0xc0,0x87,0x22,0xe4,0x12,0x65,0x42,0x12,0xc1,0x51, +0x12,0x26,0x73,0x12,0xc1,0xaf,0x12,0x4e,0xcd,0x12,0xc0,0x91,0x12,0xc1,0x68,0x12, +0x0, 0x49,0x12,0xc1,0x74,0x12,0x64,0xcd,0x12,0xc1,0x84,0xd2,0xaf,0x12,0xc0,0xe3, +0x12,0x63,0x27,0x12,0x4f,0x62,0x12,0x67,0x34,0x7e,0x8, 0x34,0x3c,0x12,0x65,0x1c, +0x90,0x60,0x50,0xe4,0x93,0xca,0xb8,0x90,0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24, +0xff,0xff,0xda,0xb8,0x2, 0x12,0x34,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3, +0x13,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0x64,0xbd,0xe4,0x12,0x63,0x4a,0x2, 0x63, +0x41,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x39,0xfc,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x2, +0x12,0x63,0xc8,0x4c,0xff,0x78,0x5, 0x5e,0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74, +0x2, 0x12,0x63,0x6b,0xda,0xf8,0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, +0x14,0x7c,0x73,0x7d,0x52,0x7c,0xab,0x7e,0xb3,0x39,0xfc,0xb4,0xa5,0x42,0x12,0x64, +0x68,0x75,0xb5,0x1, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36, +0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a, +0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4, +0x22,0x74,0x4, 0x7d,0x30,0x2, 0x63,0x6b,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3, +0x39,0xfc,0xb4,0xa5,0x52,0x12,0x64,0x68,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6, +0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22, +0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x64,0xbd,0x74,0x2, 0x12,0x63,0xc8,0x7d,0xf3, +0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x64,0x61,0x7a,0x45,0x36,0x7d,0x30, +0x6d,0x22,0x7f,0x6, 0x12,0x64,0x79,0x5e,0xf4,0xff,0xfd,0x12,0x64,0x61,0x2, 0x63, +0x41,0x74,0x2, 0x7d,0x3f,0x2, 0x63,0x6b,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74, +0x6, 0x12,0x63,0xc8,0x7d,0x3, 0x6c,0x11,0x22,0x12,0x64,0x87,0x7e,0x35,0x36,0x12, +0xc1,0xcf,0xa9,0xd2,0xb4,0xd3,0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, +0x44,0xf5,0x39,0x7f,0x21,0xf5,0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x64,0xb2,0xe5, +0x3a,0x12,0x64,0xb2,0xe5,0x39,0x12,0x64,0xb2,0xe5,0x38,0x12,0x64,0xb2,0xe4,0x2, +0x64,0xb2,0xf5,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xa9,0xd5,0xca, +0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x39,0xfc,0x22,0xe4,0x7a,0xb3, +0x38,0xb0,0x7e,0x8, 0x35,0xa6,0x12,0xcc,0x8c,0x7e,0x8, 0x35,0xe4,0x7e,0x34,0x0, +0x3e,0x12,0x20,0xe8,0x7e,0x18,0x35,0xa6,0x7a,0x1d,0x14,0x12,0x64,0xfe,0x2, 0x64, +0xf1,0x75,0x18,0x0, 0x75,0x1a,0x0, 0x7e,0xb3,0x38,0xb0,0xf5,0x91,0x22,0x2, 0x65, +0x1, 0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2, +0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0xd2,0xc9,0x75,0xf2, +0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80, +0xb4,0x80,0xf9,0xe5,0xf6,0x12,0xa2,0x9a,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xed,0xc2, +0xc9,0x22,0xa9,0xc4,0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x67,0xa2, +0xa9,0xd0,0xce,0xa9,0xc0,0xc9,0xd2,0x5, 0x12,0x65,0x73,0xa9,0xc2,0xea,0x75,0xc1, +0x6, 0x75,0xc2,0xc, 0xd2,0x3, 0x12,0x67,0x29,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9, +0xc2,0xe1,0x22,0xa9,0xd0,0xce,0xa2,0x5, 0xa9,0x91,0xc9,0x22,0x30,0x4, 0x6, 0x12, +0x66,0xf2,0x2, 0x13,0x96,0x12,0x67,0x89,0xc2,0x5, 0x2, 0x65,0x73,0x30,0x1b,0x5, +0xc2,0x4, 0x12,0x65,0x7c,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1a,0x3, 0x20,0x1b, +0x14,0x12,0x66,0x35,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x66,0x3c,0xa9, +0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x4, 0x2, 0x65,0x7c,0xd2,0x4, 0x2, +0x65,0x7c,0x74,0x1, 0x12,0x65,0xe1,0x20,0x1a,0x6, 0x12,0x65,0xea,0x12,0x65,0xbd, +0x7e,0xb3,0x33,0xe6,0xb4,0x1, 0x6, 0x12,0x66,0x83,0x12,0x65,0xbd,0xe4,0x2, 0x65, +0xe1,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x67,0xa2,0x22,0xd2,0x3, 0x80,0x12,0x30,0x3, +0xc, 0x12,0x66,0x9d,0x68,0x7, 0xc2,0x3, 0xc2,0x4, 0x12,0x65,0x7c,0x12,0x66,0x4, +0x30,0x1a,0xeb,0x22,0x80,0x1d,0x12,0x66,0x35,0x12,0x66,0x9d,0x68,0x5, 0xc2,0x4, +0x12,0x65,0x7c,0x7e,0xb3,0x33,0xe6,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1a,0x15,0xe4, +0x12,0x66,0x3c,0x20,0x93,0xe0,0x12,0x66,0x35,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x74, +0x2, 0x2, 0x66,0x3c,0x22,0x74,0x81,0x7a,0xb3,0x3, 0xfa,0x22,0x7c,0xab,0x7e,0xb3, +0x3, 0xfa,0xb4,0x81,0x38,0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0, +0x1, 0x78,0xf, 0xc2,0xaf,0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf, +0x80,0x15,0xbe,0xa0,0x2, 0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9, +0xd7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3, +0x3, 0xfa,0x22,0x74,0xc8,0x7a,0xb3,0x3, 0xfe,0xc2,0x1a,0x80,0xa, 0x12,0x66,0x4, +0x30,0x1a,0x4, 0x75,0xe9,0xff,0x22,0x12,0x66,0x9d,0x68,0xf1,0x22,0x7e,0xb3,0x33, +0xe6,0xbe,0xb0,0x1, 0x22,0x12,0x66,0x35,0x12,0x67,0x90,0x75,0xcd,0x0, 0xa9,0xd6, +0xeb,0xa9,0xd7,0xcd,0xc2,0xce,0x12,0x75,0xba,0x12,0x66,0xfa,0x74,0x1, 0x12,0x66, +0x3c,0xa9,0xc6,0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x66, +0xd1,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x4e,0xc7,0x7a,0x61,0xfc,0x12,0x4f, +0x5b,0x12,0x67,0x34,0xd2,0x3, 0x12,0x67,0x29,0x12,0x66,0xf2,0x12,0x13,0xde,0x2, +0x13,0x96,0xd2,0x5, 0x12,0x65,0x73,0x74,0x1, 0x22,0x12,0x67,0x89,0xc2,0x3, 0x12, +0x67,0x99,0xc2,0x5, 0x12,0x65,0x73,0xc2,0x3, 0x12,0x67,0x29,0xa9,0xd5,0xcb,0x74, +0xf, 0x12,0x4f,0x53,0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77,0x12,0x4e,0xc7,0xe5,0xfc, +0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, 0x4f,0x5b,0xa2,0x3, 0xa9,0x97,0xc1,0xa2,0x3, +0xa9,0x97,0xc2,0x22,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x3, 0x12,0x67, +0x99,0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75, +0x9c,0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x67,0x6e, +0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0x7c,0xab, +0x80,0xe, 0x7e,0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7, +0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xea,0x22,0xe4,0x12,0x13,0xde,0x2, 0x13,0x96, +0x12,0x66,0x9d,0x68,0xfb,0x20,0x93,0xfd,0x22,0xa9,0xd0,0xce,0xa2,0x3, 0xa9,0x95, +0xc9,0x22,0xa, 0x5b,0x2e,0x54,0x0, 0x8, 0xf5,0xcc,0x22,0x7c,0x96,0x7c,0xa7,0x12, +0x48,0x34,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, 0x12,0x67,0x6e,0x7c,0xb9,0x12,0x0, +0x1e,0x2, 0x67,0xc4,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a,0xfa,0x74,0x1, +0x7a,0xb3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0xcc,0xb1,0x12,0x29, +0x9f,0x7e,0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x20,0xe8,0x7e,0xd0,0x7, 0x12,0x26,0x73, +0x6c,0xcc,0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78, +0xfb,0x7c,0x67,0x12,0x69,0xa, 0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x69,0x14, +0xa, 0x3c,0xbd,0x32,0x48,0xde,0x12,0x69,0xa4,0x30,0x1b,0xfd,0x12,0x6a,0xda,0x7e, +0xb3,0x2a,0x73,0x7c,0x7e,0x12,0x10,0xee,0x74,0x2, 0x12,0x0, 0x1e,0x6c,0xcc,0x80, +0x29,0x74,0x2, 0xac,0xbc,0x49,0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e, +0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff, +0x12,0x69,0xa, 0x5c,0x7b,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x69,0x14,0xa, 0x3c,0xbd, +0x32,0x48,0xce,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0x83,0x12,0x69,0x23,0x74,0x2, 0x12, +0x6b,0xbb,0x12,0x68,0x88,0x74,0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x2a,0xfa,0x7e,0x8, +0x2a,0x6d,0x12,0x5, 0xb4,0xda,0x3b,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x24,0xf2, +0x12,0x6c,0x36,0x7e,0xa3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x6c,0xee,0x80,0x1d,0xa, +0x2e,0x9, 0x62,0x2a,0xdc,0xa, 0x26,0x12,0x6c,0xb5,0x7c,0x6b,0xbe,0x60,0x1c,0x50, +0x9, 0xa, 0x2e,0x12,0x69,0x0, 0x19,0xb2,0x24,0xf2,0xb, 0xe0,0xbc,0x7e,0x38,0xdf, +0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, 0x62,0x2a,0xb9,0xbe,0x60,0x23,0x50,0xd, 0xa, +0x1e,0xa, 0x27,0x2d,0x21,0x12,0x69,0x0, 0x19,0xb2,0x25,0xe, 0xb, 0xe0,0xbc,0xae, +0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x24,0xf2,0x6d,0x0, 0x7c, +0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22, +0x2e,0x27,0x2a,0xfe,0x7e,0x29,0xb0,0xa, 0x26,0x22,0xa, 0x2c,0x2e,0x27,0x2a,0xfe, +0x7e,0x29,0x70,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73,0xa, 0x25, +0x2d,0x23,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a,0xb3,0x2a,0xfa, +0x12,0x29,0x9f,0x7c,0xe7,0x80,0x60,0x12,0x26,0x73,0x12,0x69,0xa4,0x30,0x1b,0xfd, +0x12,0x6a,0xda,0x12,0x6a,0xe4,0x12,0x0, 0x1e,0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, +0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17, +0x2a,0xfe,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18, +0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x49,0x93,0xbe,0xb0,0xff,0x68,0x8, +0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x69,0x14,0xa, 0x3d,0xbd, +0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x98,0xda, +0x79,0xda,0xd8,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x68,0x88, +0x74,0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x69,0xc7, +0x7e,0xb3,0x2a,0xfc,0x2, 0xe, 0x94,0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x2a, +0xdc,0x2e,0x34,0x20,0x7d,0x12,0x6f,0xee,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac, +0x5a,0x7e,0xf, 0x33,0xc7,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x2a, +0x74,0xbc,0x6a,0x38,0xd6,0x22,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0,0x1, 0x28,0x2, 0xe4, +0x22,0x12,0x6f,0xdb,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x7a,0xd7,0x2b,0xd, 0x7e, +0x73,0x2a,0xfa,0xa, 0x37,0x3e,0x34,0x3e,0x34,0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, +0x12,0x69,0xb5,0x74,0x1, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40, +0x7f,0x15,0x12,0x7f,0xfa,0x12,0x4f,0xf4,0x7e,0xe0,0x1, 0x12,0x69,0xb5,0x30,0x1b, +0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x6a,0xe4,0x12,0x0, 0x1e,0x6c,0xdd, +0x80,0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, 0xac, +0xbd,0x7f,0x5, 0x2d,0x15,0x12,0x6f,0xc1,0xb, 0xd0,0x7e,0x73,0x2a,0x74,0xa, 0x7, +0x7e,0x63,0x2a,0x73,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b,0xe0, +0x78,0xb9,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12,0x6b,0x29,0xda,0x79,0xda, +0xd8,0x22,0x7e,0xb3,0x2b,0x2, 0x70,0x41,0x12,0x6f,0xca,0x50,0xfb,0xe4,0x6c,0x77, +0x6c,0x66,0x12,0x67,0xab,0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x2b, +0x72,0x12,0x6a,0x26,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x67,0xab,0x7e, +0x8, 0x7, 0x7a,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x25,0xf0,0x12,0x6a,0x26,0x74,0x2, +0x7a,0xb3,0x2b,0x2, 0xe4,0x7a,0xb3,0x16,0x90,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e, +0x8, 0x6, 0xfc,0x22,0x7e,0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x74, +0x2, 0x22,0x12,0x6c,0x2d,0x38,0x2, 0xe4,0x22,0x12,0x6b,0xc3,0x49,0x55,0x33,0xe7, +0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x69,0xf6,0x2, 0x6b,0xb, 0xb4,0x3, 0x5, 0x12,0x6b, +0x1b,0x80,0x2, 0xe4,0x22,0x12,0x7c,0xd0,0x74,0x1, 0x22,0x12,0x6f,0xb8,0xe4,0x12, +0x0, 0xe, 0x7e,0x8, 0x2a,0x6d,0x2, 0xd, 0x72,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f, +0x70,0x12,0xc3,0x5d,0x7c,0xeb,0x6c,0xdd,0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67, +0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e, +0x6d,0x0, 0x12,0x1f,0x7, 0x1b,0x6a,0x30,0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79, +0xda,0xd8,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40,0x7e,0xa3,0x2a,0x74,0xa, 0x3a,0x7e, +0xa3,0x2a,0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, 0x29,0x7c,0x7f,0x12,0x6b,0x29,0xa, +0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f,0x4, 0x12,0x20,0xc3,0x1b,0xfd,0x7e, +0xb3,0x2b,0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f, +0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d,0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b, +0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda,0x79,0x22,0x12,0x0, 0x1e,0x7e,0xb3, +0x2a,0xfc,0x22,0x7e,0xa3,0x33,0xe5,0x74,0x4, 0xa4,0x22,0x30,0x1b,0x8, 0x74,0x5, +0x7e,0x70,0x99,0x12,0x13,0x2c,0x7e,0xb3,0x33,0xe6,0xb4,0x1, 0x4f,0x12,0x6b,0xc3, +0x49,0x35,0x33,0xe7,0x49,0x15,0x33,0xe9,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a, +0xbe,0x70,0x0, 0x40,0x15,0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e, +0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x7e,0xb3,0x33,0xe5,0x4, 0x7a, +0xb3,0x33,0xe5,0x12,0x6c,0x2d,0x28,0xe, 0x12,0x6a,0xf2,0xb4,0x1, 0x4, 0x74,0x1, +0x80,0x6, 0x74,0x3, 0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x33,0xe6,0x22,0x7e,0x73,0x33, +0xe4,0xbe,0x73,0x33,0xe5,0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x20,0xe8,0xca, +0x79,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12,0x6c,0x36,0x7e,0xa3,0x2a,0x73,0x7e,0x63, +0x2a,0x74,0x6c,0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x2a,0xdc,0xbe,0x70,0x1c,0x50, +0x11,0xa, 0x27,0x12,0x6c,0xb5,0x7c,0x7b,0x7e,0xb3,0x2a,0xfb,0xa, 0x27,0x19,0xb2, +0x1f,0x34,0xb, 0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73, +0x2a,0xb9,0xbe,0x70,0x23,0x50,0xa, 0x7e,0x63,0x2a,0xfb,0xa, 0x27,0x19,0x62,0x1f, +0x50,0xb, 0xe0,0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14, +0x1f,0x34,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe,0xe0,0x5, +0x40,0xe7,0xda,0x79,0x22,0x2e,0x24,0x20,0x7d,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4, +0x93,0x22,0x7c,0xab,0x6c,0x77,0x80,0x11,0xa, 0x27,0x2e,0x24,0x60,0xac,0x12,0x6c, +0xb9,0xbc,0xba,0x78,0x2, 0xd3,0x22,0xb, 0x70,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xb7, +0x38,0xe6,0xc3,0x22,0xca,0x3b,0x7c,0x5b,0x7e,0x43,0x28,0x84,0xbe,0x40,0x1, 0x28, +0x2, 0xa1,0xdf,0x7e,0xa3,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x75,0x9, 0xd3,0x26,0xfa, +0x9, 0xc3,0x26,0xfb,0x7c,0xbd,0x7c,0x7c,0x12,0xbf,0xcb,0x7f,0x1, 0x90,0x60,0xaa, +0xe4,0x93,0x70,0x12,0x7c,0xfc,0x7c,0x9d,0x7e,0x83,0x2a,0x70,0x7e,0xe3,0x2a,0x6f, +0xa, 0xca,0x6d,0xbb,0x9d,0xbc,0xa, 0xa8,0x1b,0xa5,0xa, 0x5f,0xbd,0x5a,0x58,0x2, +0xa1,0xdf,0xa, 0x59,0x1b,0x54,0xbe,0x54,0x0, 0x0, 0x48,0x4e,0x7c,0xb9,0x14,0x12, +0x6c,0xc2,0x50,0x46,0x7c,0xb9,0x14,0x12,0x6d,0xe2,0xb, 0x1a,0xe0,0x7d,0x3b,0x12, +0x6e,0x17,0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, +0x7d,0x5a,0x12,0x6e,0xf, 0x7c,0xb8,0x24,0xfe,0xbc,0xbf,0x78,0x1d,0x90,0x60,0xaa, +0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f,0x12,0x6d,0xe9,0xb, 0x1a,0x30, +0xbd,0x3a,0x8, 0x6, 0x12,0x6d,0xeb,0x1b,0x1a,0xa0,0xa, 0xa9,0xb, 0xa4,0xa, 0x5e, +0xbd,0xa5,0x58,0x4b,0x7c,0xb9,0x4, 0x12,0x6c,0xc2,0x50,0x43,0x7c,0xb9,0x4, 0x12, +0x6d,0xe2,0xb, 0x1a,0xe0,0x7d,0x3c,0x12,0x6e,0x17,0x8, 0x11,0x9d,0xae,0xbe,0xa4, +0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a,0x12,0x6e,0xf, 0x7c,0xb8,0x24, +0xfe,0xbc,0xbf,0x78,0x1a,0x90,0x60,0xaa,0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4, +0x7d,0x5f,0x12,0x6d,0xe9,0xb, 0x1a,0x50,0xbd,0x5a,0x8, 0x3, 0x1b,0x1a,0xa0,0xda, +0x3b,0x22,0x12,0x6d,0xf2,0x7d,0xd3,0x7d,0x5d,0x3e,0x54,0x7e,0x1f,0x13,0x8a,0x2d, +0x35,0x22,0x7c,0x5b,0x7e,0x43,0x2a,0x6e,0x90,0x60,0xab,0xe4,0x93,0x7c,0xab,0x90, +0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7c,0x75,0xac,0x74,0xa, 0x2a,0x2d,0x32,0x22,0x2d, +0x31,0x7d,0x20,0x1b,0x1a,0x50,0x22,0x3e,0x34,0x7f,0x40,0x2d,0x93,0xb, 0x4a,0xa0, +0xbe,0xe4,0x0, 0x0, 0x22,0x12,0x6f,0xb0,0x60,0x34,0x6c,0x22,0x80,0x28,0x7c,0xb2, +0x12,0x6c,0xc2,0x50,0x1f,0x7c,0xb2,0x12,0x6d,0xf2,0x3e,0x34,0x7e,0x7f,0x13,0x8a, +0x2d,0xf3,0xb, 0x7a,0x30,0x12,0x6f,0xa8,0x59,0x35,0x39,0xdf,0x30,0x3, 0x5, 0x6d, +0x33,0x1b,0x7a,0x30,0xb, 0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xd0,0x22,0x90, +0x60,0xa7,0xe4,0x93,0x60,0x2b,0x6c,0x33,0x80,0x1f,0x7c,0xb3,0x12,0x6c,0xc2,0x40, +0x16,0x7c,0xb3,0x12,0x6d,0xf2,0x7d,0x43,0x6d,0x55,0x7d,0x4, 0x3e,0x4, 0x7e,0x1f, +0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50,0xb, 0x30,0x7e,0x23,0x2a,0x75,0xbc,0x23,0x38, +0xd9,0x22,0x7e,0x63,0x2a,0x6e,0x90,0x60,0xa7,0xe4,0x93,0x60,0x6c,0xc2,0x14,0x6c, +0x33,0x80,0x56,0x90,0x60,0xaa,0xe4,0x93,0x70,0x13,0x7c,0x96,0xac,0x93,0x90,0x60, +0xab,0xe4,0x93,0xa, 0x5b,0x1b,0x54,0x2d,0x45,0x7d,0xd4,0xb, 0xd4,0x7d,0x54,0x3e, +0x54,0x7e,0x7f,0x13,0x8a,0x2d,0xf5,0xb, 0x7a,0x50,0xbe,0x57,0x2a,0x5a,0x8, 0x27, +0x7c,0xb3,0x12,0x6c,0xc2,0x50,0x20,0x7d,0x5d,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x7f, +0x57,0x2d,0xb5,0xb, 0x5a,0xc0,0x7d,0x54,0x3e,0x54,0x2d,0xf5,0xb, 0x7a,0x50,0xbd, +0x5c,0x8, 0x4, 0xd2,0x14,0x80,0xa, 0xb, 0x30,0x7e,0x73,0x2a,0x75,0xbc,0x73,0x38, +0xa2,0x30,0x14,0x5, 0xd2,0x3, 0x2, 0x6e,0x25,0x22,0x7e,0x37,0x2a,0x4f,0x1e,0x34, +0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, 0x12,0x6f,0x4c,0x7e,0x37, +0x28,0x99,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a,0x7e,0x18,0x4, 0x7e,0x12, +0x6f,0x4c,0x12,0x6f,0x79,0x12,0x6e,0x92,0x2, 0x6f,0x3b,0xe4,0x7a,0xb3,0x39,0xf7, +0x7e,0xb3,0x28,0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x39,0xf7,0x22,0xca,0x3b,0x7f,0x31, +0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24,0x7f,0x13,0x12,0x8a, +0x4f,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x6f,0xa0,0x7e,0xd, 0x24,0x2d,0x15,0x7f, +0x13,0x2d,0x35,0x12,0x7a,0x90,0xda,0x3b,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e, +0xe3,0x2a,0x6f,0x7e,0xd3,0x2a,0x70,0x6c,0xcc,0x80,0xe, 0x7c,0x7c,0xac,0x7f,0x12, +0x40,0xb2,0x7c,0xbd,0x12,0xa0,0xca,0xb, 0xc0,0xbc,0xec,0x38,0xee,0xda,0x3b,0x22, +0x7e,0xa3,0x2a,0x74,0x74,0x2, 0xa4,0x22,0x7c,0xa3,0xb, 0x30,0x74,0x2, 0xa4,0x22, +0x6c,0x33,0x90,0x60,0xa7,0xe4,0x93,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, +0x1e,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0xb3,0x33,0xe6,0xb4,0x1, +0x2, 0xc3,0x22,0xd3,0x22,0x12,0x6f,0xca,0x50,0xfb,0x22,0x7c,0xab,0x12,0x4a,0x9e, +0x7c,0xba,0x12,0x13,0xc7,0x2, 0x0, 0x1e,0x2d,0x32,0x2e,0x34,0x21,0xa, 0x7a,0x71, +0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61, +0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x70,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34, +0x2a,0xe, 0x7a,0x37,0x2b,0x76,0xe4,0x7a,0xb3,0x2b,0x74,0x7a,0xb3,0x2b,0x75,0x7e, +0x34,0x0, 0x4, 0xca,0x39,0x12,0x70,0x45,0x7e,0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0x34,0x2b,0x78,0x7a,0x37,0x25,0xf4,0xe4,0x7a,0xb3,0x25,0xf2,0x74,0x1, +0x7a,0xb3,0x25,0xf3,0x22,0x7e,0x34,0x61,0x29,0x7e,0x24,0x0, 0xff,0x22,0xe4,0x7a, +0xb3,0x38,0xb0,0x7a,0xb3,0x38,0xb1,0x90,0x60,0x50,0x93,0x7a,0xb3,0x38,0xb2,0x90, +0x60,0x51,0xe4,0x93,0x7a,0xb3,0x38,0xb3,0xe4,0x7a,0xb3,0x38,0xb4,0x90,0x60,0x99, +0x93,0x7a,0xb3,0x38,0xb5,0xe4,0x7a,0xb3,0x38,0xb6,0x7a,0xb3,0x38,0xb7,0x90,0x61, +0xca,0x93,0x7a,0xb3,0x38,0xb9,0x7e,0x34,0x61,0x4f,0x12,0x23,0x74,0x1e,0x34,0x1e, +0x34,0x7a,0x73,0x38,0xbd,0x7e,0x34,0x61,0x55,0x12,0x23,0x74,0x1e,0x34,0x1e,0x34, +0x7a,0x73,0x38,0xbe,0x74,0x64,0x7a,0xb3,0x38,0xcf,0x90,0x61,0x18,0xe4,0x93,0x7a, +0xb3,0x38,0xd0,0x90,0x61,0x17,0xe4,0x93,0x7a,0xb3,0x38,0xbc,0x90,0x61,0x19,0xe4, +0x93,0x7a,0xb3,0x38,0xd2,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x38,0xd1,0x90,0x61, +0x1d,0xe4,0x93,0x7a,0xb3,0x38,0xd3,0x90,0x61,0x25,0xe4,0x93,0x7a,0xb3,0x38,0xce, +0xe4,0x7a,0xb3,0x38,0xc9,0x74,0xc8,0x7a,0xb3,0x38,0xc7,0x74,0x1e,0x7a,0xb3,0x38, +0xc8,0x74,0x1, 0x7a,0xb3,0x38,0xc6,0x74,0xc, 0x7a,0xb3,0x38,0xc5,0x74,0x1, 0x7a, +0xb3,0x38,0xca,0xe4,0x7a,0xb3,0x38,0xcb,0x7a,0xb3,0x38,0xcc,0x7e,0x8, 0x38,0xd4, +0x7e,0x34,0x0, 0x2c,0x12,0x20,0xe8,0x7e,0x34,0x60,0xd6,0x12,0x23,0x74,0xa, 0x36, +0x7a,0x73,0x38,0xdf,0x7e,0x34,0x60,0xd6,0x12,0x23,0x74,0x7a,0x73,0x38,0xe0,0x90, +0x60,0xd4,0x93,0x7a,0xb3,0x38,0xe1,0x90,0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x38,0xe2, +0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x70,0x45,0x7e,0x8, 0x38,0xf0,0x12,0x20,0xc3, +0x1b,0xfd,0x74,0x5, 0x7a,0xb3,0x38,0xfd,0x74,0x1, 0x7a,0xb3,0x38,0xf4,0x7e,0x34, +0x0, 0x28,0xca,0x39,0x7e,0x34,0x61,0xdb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33, +0x12,0x20,0xc3,0x1b,0xfd,0x22,0x6d,0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2, +0x2a,0xdc,0x54,0x1, 0x78,0x5, 0x4e,0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0, +0x7e,0x53,0x2a,0x74,0xbc,0x5a,0x38,0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2, +0x2a,0xb9,0xbe,0xb0,0xd, 0x38,0x5, 0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38, +0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e,0x60,0x50,0xb, 0xa0,0x12,0x71,0xc1,0x38,0xdc, +0x22,0x7e,0xb3,0x2a,0x73,0xbc,0xba,0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab, +0x7d,0x8b,0x6d,0x22,0x7d,0x32,0x7d,0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, +0xfc,0x7e,0x8, 0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3, +0x26,0xf6,0x7a,0xb3,0x26,0xf8,0x7a,0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa, +0x80,0x5f,0x12,0x73,0x2f,0xb, 0x6a,0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3, +0x8, 0x2, 0x7d,0x3c,0x2d,0x71,0x7d,0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d, +0x9d,0x7e,0x67,0x2a,0x53,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, +0x24,0x12,0x73,0x1c,0xb, 0x3a,0xd0,0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x26,0xf7,0x4, +0x7a,0xb3,0x26,0xf7,0x80,0x19,0x12,0x73,0x25,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff, +0xb, 0xd4,0xbd,0xcd,0x58,0x9, 0x7e,0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, +0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x99,0x7a,0xa7,0x7, 0xfe,0x7a,0x37,0x8, +0x2, 0xe5,0x24,0x7a,0xb3,0x8, 0x9, 0x7a,0x97,0x8, 0x6, 0x12,0x6f,0xa0,0x2d,0xf5, +0x6c,0xaa,0x80,0x50,0x12,0x73,0x2f,0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d, +0xbd,0xd2,0x8, 0x2, 0x7d,0x2d,0x7e,0x67,0x2a,0x51,0x7e,0x74,0x0, 0x3, 0xad,0x76, +0xbd,0xd7,0x8, 0x2, 0xb, 0x90,0x12,0x73,0x1c,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, +0x7e,0xb3,0x26,0xf6,0x4, 0x7a,0xb3,0x26,0xf6,0x80,0x17,0x12,0x73,0x25,0xb, 0x3a, +0xd0,0x6d,0x99,0x9d,0x9c,0xbd,0xd9,0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3, +0x26,0xf8,0xb, 0xa0,0x12,0x71,0xc1,0x38,0xab,0x7a,0x87,0x7, 0xfc,0x7a,0x27,0x8, +0x0, 0x7a,0x93,0x8, 0x8, 0x12,0x6f,0xa0,0x2d,0x15,0x6c,0xaa,0x80,0xe, 0x12,0x75, +0xc3,0xb, 0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x71,0xc1,0x38, +0xed,0x7a,0xb7,0x8, 0x4, 0xbd,0x8a,0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0xf8,0xbd, +0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b,0x22,0x7e,0x74,0x62,0x16, +0x7e,0x64,0x0, 0xff,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x2d,0x7f,0x7d,0x6e,0x22,0x7e, +0xf0,0x2, 0xac,0xfa,0x7f,0x67,0x2d,0xd7,0x22,0xca,0xd8,0xca,0x79,0x90,0x60,0x50, +0xe4,0x93,0x7c,0xdb,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e,0x73,0x2a,0x74,0xbc, +0x7e,0x28,0x4, 0x7c,0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3,0x2a,0x6d,0x7a,0xe3,0x2a, +0x6e,0x7a,0xd3,0x2a,0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xd3,0x2a,0x73,0x7a,0xe3,0x2a, +0x74,0x90,0x60,0xa8,0xe4,0x93,0x7c,0xab,0x7a,0xa3,0x2a,0x77,0x90,0x60,0xa9,0xe4, +0x93,0xa, 0x2b,0xa, 0x3d,0x9d,0x32,0x7c,0xb7,0x7a,0xb3,0x2a,0x6f,0xa, 0x2a,0xa, +0x3e,0x9d,0x32,0x7a,0x73,0x2a,0x70,0x90,0x60,0x91,0xe4,0x93,0x7a,0xb3,0x2a,0x78, +0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x2a,0x79,0xa, 0x3d,0xca,0x39,0x7e,0x34,0x60, +0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x7a,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f, +0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x9d,0x12,0x20, +0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e,0x34,0x60,0xd8,0x7e,0x24,0x0, +0xff,0x7e,0x8, 0x2b,0x21,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x75,0x24,0x12,0x78,0x40, +0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7a,0xd3,0x2a,0x75,0x7a,0xe3,0x2a,0x76,0x12, +0x6f,0xf7,0x74,0x1, 0x12,0x48,0x34,0xe4,0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x2, +0x12,0x71,0x76,0x7a,0x37,0x2b,0xd, 0x74,0x3, 0x7a,0xb3,0x2b,0x3, 0xe4,0x7a,0xb3, +0x2b,0x4, 0x74,0x2, 0x7a,0xb3,0x2b,0x5, 0x7e,0x34,0x61,0x5b,0x12,0x23,0x74,0x7a, +0x37,0x2b,0x7, 0x74,0x4, 0x7a,0xb3,0x2b,0x6, 0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x2b, +0x9, 0x7e,0x34,0x20,0x5f,0x7a,0x37,0x2b,0xb, 0x90,0x61,0x1a,0xe4,0x93,0x7a,0xb3, +0x2b,0x62,0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x90,0x61,0x1c,0xe4,0x93, +0x7a,0xb3,0x2b,0x11,0x74,0x4, 0x7a,0xb3,0x2b,0x13,0x90,0x60,0xd5,0xe4,0x93,0x7a, +0xb3,0x2b,0xf, 0x12,0x57,0xef,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3,0x2b,0x1e,0x7e, +0x34,0x61,0x22,0x12,0x23,0x74,0x7a,0x37,0x2b,0x19,0x90,0x60,0xd3,0x93,0x7a,0xb3, +0x2b,0x12,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x2b,0x20,0x90,0x61,0x19,0xe4,0x93, +0x7a,0xb3,0x2b,0x1f,0x7e,0x34,0x61,0x1e,0x12,0x23,0x74,0x7a,0x37,0x2b,0x15,0x7e, +0x34,0x61,0x20,0x12,0x23,0x74,0x7a,0x37,0x2b,0x17,0x90,0x61,0x1d,0xe4,0x93,0x7a, +0xb3,0x2b,0x14,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a,0x74,0x1, 0x7a,0xb3,0x2b, +0x67,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b,0x66,0x7e,0x34, +0x4, 0x6d,0x7a,0x37,0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74,0x2, 0x7a,0xb3, +0x2b,0x64,0xe4,0x7a,0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60,0xe4,0x7a,0xb3, +0x2b,0x61,0x7e,0x34,0x20,0x65,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca,0x39,0x7e,0x34, +0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x20,0xc3,0x1b,0xfd,0xda, +0x79,0xda,0xd8,0x22,0x12,0x75,0xba,0x12,0x75,0x86,0x90,0x60,0x50,0xe4,0x93,0xa, +0x3b,0x7d,0x13,0x2e,0x14,0x2a,0x7a,0x6d,0x0, 0x9, 0xb3,0x2a,0x79,0x12,0x75,0x6d, +0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2b,0x21,0x6d,0x0, 0x9, 0xb3,0x2b,0x20,0x12,0x75, +0x6d,0xa, 0x1b,0x2e,0x14,0x2a,0x7c,0x12,0x75,0x7a,0xe5,0x25,0x12,0x75,0x71,0xa, +0x1b,0x2e,0x14,0x2b,0x23,0x12,0x75,0x7a,0xe5,0x24,0x2, 0x20,0xe8,0x7e,0x34,0x0, +0x2, 0x12,0x20,0xe8,0x90,0x60,0x50,0xe4,0x93,0x22,0x6d,0x0, 0x90,0x60,0x91,0xe4, +0x93,0xa, 0x3b,0x1b,0x35,0x22,0x6c,0xaa,0x6c,0x99,0x80,0xc, 0xa, 0xf9,0x9, 0xbf, +0x2a,0x7a,0xbc,0xba,0x68,0x7, 0xb, 0x90,0x12,0x75,0xb2,0x38,0xef,0x12,0x75,0xb2, +0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, 0xa0,0x74,0x6e,0x7a,0x1b, +0xb0,0x22,0x90,0x60,0x50,0xe4,0x93,0xbc,0xb9,0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18, +0x0, 0x24,0x22,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0x22,0xca,0x79,0x6c, +0xaa,0x12,0x75,0xc3,0xb, 0x7a,0xf0,0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39, +0x57,0x7f,0x71,0x2d,0xf4,0xb, 0x7a,0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0x77, +0xb, 0xa0,0xbe,0xa0,0x20,0x40,0xda,0x7e,0x8, 0x39,0x57,0x7e,0x18,0x39,0x77,0x74, +0x20,0x12,0xbc,0xc0,0xda,0x79,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x39, +0x53,0xbe,0x70,0x20,0x40,0x52,0x7e,0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74, +0x5, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0x33,0x39,0x53,0xa, 0x13,0x6d,0x0, 0x12,0x1f, +0x7, 0x7c,0xe7,0xbe,0xe0,0x2, 0x50,0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, +0x3e,0x1b,0x34,0x7c,0xc7,0x7f,0x5, 0x7c,0xbd,0x12,0x76,0x71,0x7f,0x6, 0x7c,0xbd, +0x7c,0x7c,0x12,0x76,0x71,0xb, 0xf0,0x7e,0x73,0x39,0x53,0xbc,0x7f,0x50,0xbc,0x7f, +0x5, 0x7f,0x16,0x12,0x75,0xcd,0x80,0x6, 0x74,0x7e,0x7a,0xb3,0x39,0x52,0xda,0x3b, +0x22,0x7c,0x97,0x7c,0xab,0x7f,0x10,0x7e,0x30,0x2, 0xac,0x3a,0x2d,0x13,0x7d,0x2, +0xb, 0xa, 0x10,0x7e,0x10,0x2, 0xac,0x19,0x7f,0x71,0x2d,0xf0,0xb, 0x7a,0x0, 0x7c, +0x21,0xa5,0xba,0x0, 0x14,0xa, 0x3, 0x1b,0x7a,0x0, 0xbc,0x9a,0x68,0x24,0x6d,0x44, +0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x40,0x22,0xbc,0x9a,0x68,0x15,0xa, 0x2, 0xa, +0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a,0x10,0x6d,0x11,0x74,0x2, 0xa4,0x2d,0x35,0x1b, +0x1a,0x10,0x22,0xca,0xf8,0x7e,0x45,0x24,0x7c,0xb9,0x7a,0xb3,0x39,0x53,0x74,0xff, +0x7a,0xb3,0x39,0x52,0x6d,0x55,0x80,0x19,0x7d,0xf5,0x3e,0xf4,0x12,0x77,0xaf,0x7d, +0xe5,0x3e,0xe4,0x59,0xfe,0x1f,0x34,0x69,0xf6,0x0, 0x2, 0x59,0xfe,0x21,0x14,0xb, +0x54,0xbd,0x45,0x38,0xe3,0x7e,0x33,0x39,0x53,0xbe,0x30,0x4, 0x38,0x2, 0xe1,0x85, +0x69,0xf1,0x0, 0x1c,0x69,0x11,0x0, 0x1e,0xbd,0x1f,0x18,0x19,0x4d,0x11,0x78,0x4, +0x7e,0x14,0x0, 0x1, 0x7d,0x3f,0x7d,0x21,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x40,0x7a, +0xb3,0x39,0x56,0x80,0x43,0x4d,0xff,0x78,0x4, 0x7e,0xf4,0x0, 0x1, 0x7d,0x31,0x7d, +0x2f,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x80,0x7a,0xb3,0x39,0x56,0x7d,0xf, 0x2d,0xf, +0xbd,0x1, 0x8, 0x24,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x39,0x56,0xa, 0x37,0x6d,0x22, +0x12,0x1e,0xeb,0x7d,0x5f,0x1a,0x4a,0x1a,0x48,0x7d,0x1f,0x1a,0x2, 0x1a,0x0, 0x2f, +0x2, 0x12,0x1f,0x7, 0x7a,0x73,0x39,0x56,0xbe,0xf0,0x5, 0x58,0x14,0x12,0x77,0xa4, +0x12,0xc9,0xf6,0x12,0x77,0xa4,0x12,0xca,0xa1,0x12,0x77,0xa4,0x12,0x76,0x7, 0x80, +0xa, 0x74,0x7d,0x80,0x2, 0x74,0x7f,0x7a,0xb3,0x39,0x52,0xe4,0x7a,0xb3,0x39,0x53, +0x7e,0x73,0x34,0x4f,0xbe,0x73,0x39,0x52,0x48,0x6, 0x7e,0xb3,0x39,0x54,0x80,0x1, +0xe4,0xda,0xf8,0x22,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x21,0x14,0x22,0x7d,0xf4,0x3e, +0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0,0x22,0x12,0x77,0xea,0x7a,0x37,0x2f,0x9c, +0x12,0x77,0xe1,0x7a,0x37,0x2f,0x9e,0x12,0x8e,0x3, 0x60,0x1, 0x22,0x7e,0x73,0x2f, +0xa8,0xa, 0x37,0x7a,0x35,0x24,0x7e,0x8, 0x2b,0xbf,0x7e,0x18,0x2f,0x80,0x2, 0x76, +0xc3,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37, +0x2f,0x90,0x22,0x7e,0x8, 0x26,0x5b,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x20,0xe8,0x90, +0x60,0x9c,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0x8c,0x74,0xff,0x12,0x20,0xe8, +0x90,0x60,0x9c,0xe4,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0xb4,0x74,0xff,0x12, +0x20,0xe8,0x90,0x60,0x9a,0x12,0x78,0x34,0x7e,0x8, 0x27,0x76,0x74,0xff,0x2, 0x20, +0xe8,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x9, 0xac,0x7b,0x22,0x2, 0x23,0x7c, +0xca,0xf8,0x7e,0x73,0x2a,0x78,0xa, 0x47,0x7e,0x73,0x2a,0x71,0xa, 0x57,0x2d,0x54, +0x7e,0xa3,0x2a,0x73,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x2a,0x72,0x7e,0xa3, +0x2a,0x74,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xb9,0x7e, +0x18,0x2a,0x7a,0x12,0xd, 0xd9,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xdc,0x7e,0x18,0x2a, +0x9d,0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7f,0x60,0x7e,0xa3,0x2a,0x6d,0x7e, +0xb3,0x2a,0x6e,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d,0x3f,0xe4,0x12,0x20,0xe8, +0x7f,0x6, 0x7d,0x3f,0x12,0x20,0xe8,0x7a,0xb3,0x16,0x91,0x22,0x7e,0xf, 0x13,0x8a, +0x7e,0x18,0x8, 0xa, 0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30,0x12,0x7c,0xbb,0x7a,0x55, +0x31,0x7e,0xb3,0x2b,0x1d,0xf5,0x2e,0xe4,0x7a,0xb3,0x2b,0x1d,0x7f,0x3, 0x7e,0x1d, +0x29,0x12,0x78,0x89,0x12,0x6f,0xb8,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0x75,0x2d, +0x0, 0x12,0x7c,0xcc,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x7f,0xcf,0x7e,0x14,0x40,0x0, +0x7d,0x21,0x7d,0x7, 0x12,0x79,0x34,0x12,0x7b,0x7e,0x6d,0x33,0x80,0x19,0x7e,0x35, +0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13,0x12, +0x6f,0xc1,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35,0x2f, +0x38,0xdc,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3,0x2b, +0x1d,0xda,0x3b,0x22,0x7e,0xb3,0x2a,0x6d,0xca,0x3b,0x7c,0xdb,0x7a,0x5, 0x38,0x7d, +0x71,0x7a,0x25,0x36,0x7a,0x35,0x34,0x12,0xae,0xc7,0x40,0x2, 0x21,0xd0,0x6c,0xcc, +0x80,0x14,0x7e,0x73,0x2a,0x6e,0x12,0x7a,0x56,0x12,0x7a,0x5f,0x12,0x7a,0x4d,0x7e, +0x34,0x34,0x0, 0x12,0x7a,0x71,0x12,0x7a,0x89,0x38,0xe7,0x6c,0xcc,0x80,0x5b,0x7e, +0xa3,0x2a,0x6e,0x7c,0x7a,0x12,0x7a,0x56,0x75,0x3a,0x0, 0x80,0x27,0x7e,0xb3,0x38, +0xc5,0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac,0x7c,0x49,0x43,0x32,0xba,0x80, +0x6, 0xac,0x7c,0x49,0x43,0x32,0xbc,0x7e,0x71,0x3a,0x74,0x2, 0xac,0x7b,0x59,0x43, +0x34,0x50,0x5, 0x3a,0x7e,0xb3,0x2a,0x70,0xbe,0xb1,0x3a,0x38,0xd0,0x12,0x7f,0x97, +0x68,0xb, 0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34,0x4e,0x12,0x7a,0x5f, +0x12,0x7a,0x4d,0x7e,0x34,0x34,0x50,0x12,0x7a,0x71,0xbc,0xdc,0x38,0xa1,0x80,0x2c, +0x7a,0xd3,0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x25,0xb7,0xe4,0x7a,0xb3,0x25, +0xb9,0x74,0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0x77,0x25,0xba,0x7a,0x77,0x25,0xbe,0x7e, +0x8, 0x25,0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12,0x80, +0xfc,0x7e,0x35,0x38,0x7a,0x37,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x7a,0x4d, +0x7a,0xd3,0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9,0x7a, +0x77,0x25,0xba,0x7e,0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x25,0xb9,0x7e, +0x35,0x34,0x7a,0x37,0x25,0xba,0x7e,0x35,0x36,0x7a,0x37,0x25,0xbc,0x6d,0x33,0x7a, +0x37,0x25,0xc0,0x7e,0x8, 0x25,0xb6,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x7e,0x73,0x2a, +0x6e,0x7a,0x73,0x25,0xb7,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3,0x22,0x74, +0xc, 0x7a,0xb3,0x25,0xb8,0x74,0x1, 0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9, +0x22,0x7a,0x37,0x25,0xba,0x7d,0x3f,0x7a,0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e, +0x8, 0x25,0xb6,0x12,0x7, 0x9b,0xb, 0xc0,0x22,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x22, +0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x22,0xf3,0x7e,0x4, 0x0, 0xff,0x69,0x30, +0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x3e,0x34, +0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc3,0x1b,0xfd,0x6c,0xdd,0x12,0x7f,0xd7, +0x7a,0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4f,0x12,0x7b,0x6e,0x40,0x48,0x12,0x7b,0x64, +0x50,0x43,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x10,0x7d,0x3f,0x12, +0x21,0x1a,0x7d,0x3, 0x7d,0x31,0x12,0x21,0x1a,0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe, +0x15,0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, +0x8, 0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34, +0x4, 0x7a,0xb3,0x1f,0x34,0xb, 0xc0,0x12,0x7a,0x89,0x38,0xac,0x7e,0x73,0x1f,0x34, +0x4c,0x77,0x68,0x34,0x12,0x8b,0x1e,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, 0x5, +0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e, +0x6c,0xcc,0x80,0xf, 0x12,0x7b,0x6e,0x40,0x8, 0x12,0x7b,0x64,0x50,0x3, 0x12,0x8b, +0x9, 0xb, 0xc0,0x12,0x7a,0x89,0x38,0xec,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x2, 0x41, +0xbd,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc,0xab,0x22,0xa, 0xec, +0x9, 0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0x7e,0xa3, +0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4,0x12,0x20,0xe8,0x90,0x60, +0x93,0x93,0xa, 0x3b,0x7e,0xb3,0x2a,0x71,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xad,0x32, +0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12,0xab,0xa3,0xb, 0xa, 0x0, +0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18,0x20,0x2d,0x20,0x1b,0x18, +0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c,0xcb,0x7e, +0xb3,0x2b,0x1d,0xf5,0x32,0x7e,0xb3,0x2b,0xf, 0xf5,0x33,0x7e,0xd3,0x2b,0x14,0x7e, +0xe3,0x2b,0x1f,0x7e,0xf3,0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x34, +0x0, 0x7e,0x8, 0x24,0xf2,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39, +0x7e,0x18,0x32,0xba,0x7e,0x8, 0x25,0x2a,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbc,0x12, +0xa7,0xac,0x74,0x1, 0x7a,0xb3,0x2b,0x1d,0x74,0x5, 0xac,0xbc,0x12,0x7f,0xf1,0x74, +0x5, 0xac,0xbc,0x12,0x7f,0xdf,0x74,0x5, 0xac,0xbc,0x12,0x7f,0xe8,0x74,0x5, 0xac, +0xbc,0x9, 0x75,0x26,0x37,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2, +0xe, 0xc2,0x3, 0x12,0xcc,0xa8,0x12,0xa6,0xa8,0x12,0x7c,0xc5,0x30,0xd, 0xfd,0x74, +0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x13,0x86,0x7d,0x25, +0x7e,0x4, 0xd, 0xc8,0x12,0x79,0x34,0x12,0x7c,0xbb,0x7a,0x55,0x34,0x7e,0xd, 0x2e, +0x7e,0x18,0xd, 0xc8,0x12,0xa1,0xe9,0x12,0xa2,0xa4,0xe5,0x32,0x7a,0xb3,0x2b,0x1d, +0xe5,0x33,0x7a,0xb3,0x2b,0xf, 0x7a,0xd3,0x2b,0x14,0x7a,0xe3,0x2b,0x1f,0x7a,0xf3, +0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x24,0xf2,0x7e,0x8, 0x34,0x0, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x25,0x2a,0x7e, +0x8, 0x32,0xba,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x3b,0x22,0x7e,0xa3,0x2a,0x6e,0x7e, +0xb3,0x2a,0x6d,0xa4,0x22,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, +0x74,0x1, 0x7e,0x70,0x99,0x12,0x13,0x2c,0x2, 0x0, 0x4e,0xca,0x3b,0x7e,0x34,0xff, +0xff,0x7a,0x35,0x34,0x7e,0xb3,0x38,0xc5,0xf5,0x29,0x7e,0xb3,0x2a,0x6d,0xf5,0x2a, +0x7e,0xb3,0x2a,0x6e,0xf5,0x2b,0x7e,0xb3,0x2a,0x70,0xf5,0x2c,0x7e,0xb3,0x2a,0x6f, +0xf5,0x2d,0x7e,0x34,0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30, +0x12,0x7c,0xc5,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12, +0x7f,0xc7,0x6c,0xff,0x80,0x35,0x12,0x7f,0x5b,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b, +0xac,0x1e,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31, +0xb, 0x1a,0x10,0x12,0x7f,0x62,0xe5,0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x7f, +0x71,0x74,0x2, 0xac,0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38, +0xc5,0x12,0x7f,0x97,0x68,0xe, 0x7e,0x34,0x10,0x0, 0x7e,0xa1,0x2b,0x74,0x2, 0xa4, +0x59,0x35,0x33,0xfe,0x6c,0xff,0x80,0x78,0x12,0x7f,0x5b,0x6c,0xee,0x80,0x14,0x12, +0x7f,0xa0,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x13, +0x12,0x7f,0x62,0xe5,0x29,0xbc,0xbe,0x38,0xe6,0xe5,0x29,0x12,0x7f,0x71,0x74,0x4, +0xac,0xbf,0x59,0x35,0x32,0xba,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x35,0x12,0x7f,0x5b, +0x7e,0xe1,0x29,0x80,0x14,0x12,0x7f,0xa0,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60, +0x80,0x14,0x78,0xf4,0x7d,0x13,0x12,0x7f,0x62,0xe5,0x2c,0xbc,0xbe,0x38,0xe6,0xe5, +0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x7f,0x75, +0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x32,0xbc,0xb, 0xf0, +0xe5,0x2d,0xbc,0xbf,0x38,0x82,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0xcc, +0x12,0x1f,0x7, 0x6c,0xff,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, +0x5f,0xad,0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e, +0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59, +0x25,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d, +0x0, 0x7e,0x18,0x0, 0x28,0x12,0x1f,0x7, 0x6c,0xff,0x80,0x5c,0x74,0x4, 0xac,0xbf, +0x49,0x25,0x32,0xba,0xa, 0x1f,0xad,0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2, +0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d, +0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25,0x32,0xba,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26, +0x74,0x4, 0xac,0xbf,0x49,0x25,0x32,0xbc,0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, +0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, +0xac,0xbf,0x59,0x25,0x32,0xbc,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73, +0x38,0xc7,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, +0x64,0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0xe3,0x7a,0xe5,0x34,0x7e,0x73,0x38,0xc8,0xa, +0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7d,0x1f,0x12,0x1f,0x5, 0x7d, +0x63,0x6c,0xff,0x80,0x20,0x74,0x2, 0xac,0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34, +0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x34,0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59, +0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74, +0x4, 0xac,0xbf,0x49,0x45,0x32,0xba,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59, +0x35,0x32,0xba,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x32,0xba,0x49,0x45,0x32, +0xbc,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x32,0xbc,0x80,0x8, 0xbd, +0x46,0x50,0x4, 0x59,0x65,0x32,0xbc,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30, +0x5, 0x6, 0x7e,0xd, 0x30,0x12,0x56,0x93,0xda,0x3b,0x22,0x9f,0x11,0x7a,0x1f,0x24, +0xf4,0x22,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x2f,0x10,0x7a,0x1f,0x24,0xf4,0xb, 0xe0, +0x22,0xa, 0x1b,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x12,0x1f,0x7, 0x7a,0x1f,0x24,0xf4, +0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d,0x22,0x60,0x5, 0x2f,0x11,0x14, +0x78,0xfb,0xb, 0x14,0x2, 0x1f,0x5, 0x90,0x60,0xaa,0xe4,0x93,0xbe,0xb0,0x1, 0x22, +0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d, +0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24,0xf2,0x74,0x2, 0xac,0xbe,0x49,0x35, +0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x20,0xe8,0x12, +0x0, 0xe, 0x7e,0x1f,0x13,0x86,0x22,0x7e,0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22,0x9, +0x75,0x26,0x35,0x7a,0x73,0x2b,0x1f,0x22,0x9, 0x75,0x26,0x36,0x7a,0x73,0x2b,0x20, +0x22,0x9, 0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22,0x7f,0x70,0x7e,0x33,0x2a,0x74, +0xa, 0x43,0x7e,0x33,0x2a,0x73,0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a, +0xb3,0x16,0x90,0x7f,0x1, 0xa, 0x3a,0x12,0x20,0xe8,0x7f,0x7, 0xa, 0x3a,0x2, 0x20, +0xe8,0x7e,0xa3,0x2f,0xa8,0x7e,0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x39,0x1, +0x40,0x39,0x7e,0x37,0x39,0x1, 0xb, 0x34,0x7a,0x37,0x39,0x1, 0xbe,0x34,0x0, 0x1, +0x78,0x5, 0x7e,0xb3,0x3, 0xee,0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba,0x22, +0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x34,0x49,0x22,0x9e, +0x34,0x0, 0x3, 0x2e,0x37,0x2b,0xb9,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x7e,0xa3, +0x38,0xaf,0x7c,0xba,0x4, 0x7a,0xb3,0x38,0xaf,0x7a,0xa3,0x3, 0xac,0x22,0xca,0x7b, +0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82,0x12,0x52,0xc6,0xd0,0x82,0xd0, +0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32,0xa9,0xc0,0x93,0x75,0x18,0x0, +0x32,0x7e,0xb3,0x39,0x5, 0x4, 0x7a,0xb3,0x39,0x5, 0xe5,0x19,0xb4,0x1, 0x8, 0xe4, +0x7a,0xb3,0x39,0x5, 0x75,0x19,0x0, 0x7e,0x73,0x39,0x5, 0x7a,0x73,0x3, 0xaa,0x22, +0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x39,0x3, 0x4d,0x22,0x78,0xe, +0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x39,0x3, 0x15,0x1a,0x7e,0x27, +0x39,0x3, 0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, 0x2, +0x80,0x2, 0x6d,0x33,0x7a,0x37,0x39,0x3, 0x75,0x1a,0xea,0x22,0x7d,0xf3,0x6d,0xee, +0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x6d,0xf2,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f, +0x57,0x2d,0xbc,0xb, 0x5a,0x10,0x1a,0x2, 0x1a,0x0, 0x7e,0x83,0x2b,0x20,0xa, 0x98, +0x6d,0x88,0x7f,0x10,0x7f,0x4, 0x12,0x1e,0xeb,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e, +0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90, +0x7e,0x83,0x2a,0x75,0xbc,0x89,0x38,0xbc,0x22,0x7f,0x20,0xb, 0x2a,0x10,0xb, 0x1a, +0x0, 0x1b,0x2a,0x0, 0x1b,0x1a,0x10,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e, +0x60,0xfd,0x68,0x21,0x1b,0x61,0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b,0x61,0x68,0x15, +0x1b,0x60,0x68,0x11,0x2e,0x60,0xa, 0x78,0x4, 0x7a,0x73,0x3, 0x9a,0xa, 0x2b,0x19, +0x72,0x3, 0x9b,0xd2,0xf, 0x22,0x7e,0x24,0x3, 0x9b,0x30,0xf, 0x62,0xc2,0xf, 0x9, +0x72,0x0, 0x2, 0xa, 0x37,0x12,0x4f,0x96,0x7a,0x37,0x2a,0x4f,0x9, 0x72,0x0, 0x3, +0xa, 0x37,0x12,0x4f,0x96,0x7a,0x37,0x2a,0x51,0x9, 0x72,0x0, 0x4, 0xa, 0x37,0x12, +0x4f,0x96,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a, +0x37,0x2a,0x5a,0x9, 0x72,0x0, 0x1, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a,0x37,0x2a, +0x5c,0x9, 0x72,0x0, 0x5, 0xa, 0x37,0x12,0x4f,0x96,0x7a,0x37,0x2a,0x62,0x9, 0x72, +0x0, 0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a,0x73,0x2a,0x6b,0x2, 0x47,0xec,0x22, +0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b, +0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80,0xa, 0x38,0x9d,0x32,0x12,0x21,0x1a,0xe5,0x29, +0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba, +0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, +0x70,0x22,0x7d,0xc3,0x7e,0x34,0x61,0x37,0x12,0x83,0x38,0x90,0x61,0x35,0xe4,0x93, +0x70,0x3, 0x7d,0x3c,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x2a, +0x70,0x80,0x4, 0x7e,0x83,0x2a,0x6f,0x12,0x5f,0xf3,0xbe,0xc4,0x0, 0x3f,0x38,0x20, +0x7e,0xe4,0x0, 0x3f,0x9d,0xec,0x7e,0x34,0x61,0x3b,0x12,0x83,0x26,0x7c,0x65,0x7f, +0x71,0x12,0x83,0x15,0xbf,0x71,0x40,0x2, 0x7f,0x71,0x9f,0x17,0x7f,0x71,0x61,0x12, +0x12,0x5d,0x5f,0xbd,0x5c,0x38,0x25,0x7d,0xec,0x9d,0xe5,0x7e,0x34,0x61,0x3d,0x12, +0x83,0x26,0x7c,0x65,0x7f,0x71,0x90,0x61,0x3a,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40, +0x4, 0x7f,0x71,0x1b,0x7c,0x12,0x83,0x1d,0x2f,0x71,0x80,0x66,0x7d,0xb4,0xb, 0xb4, +0x1e,0xb4,0x7d,0x5b,0x1b,0x54,0xbd,0x5c,0x40,0xc, 0x7d,0xf5,0x9d,0xfc,0x6d,0xee, +0x7e,0x34,0x61,0x3f,0x80,0xa, 0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x34,0x61,0x41, +0x12,0x84,0x5f,0x7f,0x17,0x12,0x1e,0xfc,0x7f,0x71,0x12,0x46,0xb6,0x7f,0x71,0xbd, +0x5c,0x7d,0x3d,0x40,0xc, 0x1e,0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80, +0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71,0x12,0x83,0x15,0x6d,0x22,0xbf,0x71,0x50,0x4, +0x7f,0x71,0x80,0xe, 0x90,0x61,0x3a,0xe4,0x93,0x12,0x83,0x1d,0xbf,0x71,0x28,0x2, +0x7f,0x71,0x7d,0x3f,0x22,0x90,0x61,0x39,0xe4,0x93,0xa, 0x3b,0x22,0xa, 0x2b,0x7d, +0x3d,0x9d,0x32,0x6d,0x22,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xad,0xfe,0x6d, +0xee,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x22, +0xca,0xd8,0xca,0x79,0x12,0x87,0xe3,0xb, 0x1a,0x40,0x90,0x61,0x35,0xe4,0x93,0x70, +0x2, 0x61,0xeb,0x90,0x60,0xa7,0xe4,0x93,0x70,0x2, 0x61,0xeb,0x6c,0xff,0x61,0xe4, +0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x29,0xc, 0x5e,0xe0,0xf, 0x49,0xc3,0x29,0xa, +0x7e,0x14,0x60,0xd1,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x2d,0x24,0xbd,0xc2,0x40, +0x42,0x49,0xd3,0x29,0x8, 0x7d,0x3d,0x12,0x84,0x24,0x7c,0xdb,0x90,0x60,0xa7,0xe4, +0x93,0xbc,0xbd,0x38,0xe, 0x7d,0x34,0x1b,0x34,0x12,0x83,0xf0,0x7c,0xbe,0x12,0x83, +0xf9,0x80,0x3f,0x7e,0x70,0x2, 0xac,0x7d,0x2e,0x34,0x60,0xc5,0x12,0x83,0x38,0x74, +0x9, 0xac,0xbf,0x59,0xd5,0x29,0x8, 0x7e,0x34,0x60,0xcf,0x12,0x23,0x74,0x12,0x83, +0xf0,0x80,0x1f,0xbd,0xc4,0x40,0x1b,0x7d,0x54,0x2e,0x54,0x0, 0xa, 0xbd,0xc5,0x40, +0x5, 0x7c,0xbe,0x12,0x83,0xf9,0x7d,0xc4,0x1b,0xc4,0x74,0x9, 0xac,0xbf,0x59,0xc5, +0x29,0xa, 0xb, 0xf0,0x12,0x3b,0xe3,0x28,0x2, 0x61,0x60,0xda,0x79,0xda,0xd8,0x22, +0x74,0x9, 0xac,0xbf,0x59,0x35,0x29,0xa, 0x22,0x7c,0xab,0x7e,0x8, 0x29,0xbc,0x12, +0x39,0x49,0x28,0x1f,0xa, 0x3a,0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0,0xb4,0x2, 0x4, +0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x31,0x7d,0x20,0x39, +0xb1,0x0, 0xa, 0x22,0x6c,0xaa,0x80,0x23,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e, +0xf4,0x60,0xb1,0x12,0x84,0x57,0xbd,0x23,0x38,0xf, 0x2e,0x14,0x60,0xb3,0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x23,0x50,0xb, 0xb, 0xa0,0x90,0x60,0xa7,0xe4,0x93, +0xbc,0xba,0x38,0xd4,0x7c,0xba,0x22,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0x22,0x7e, +0x24,0x0, 0xff,0xb, 0x1a,0x10,0x22,0x12,0x9d,0xc3,0x12,0x84,0xc4,0x12,0x86,0xd7, +0x12,0x86,0x4e,0x7e,0xb3,0x3, 0xc0,0xb4,0x1, 0x1e,0x7e,0x34,0x61,0xc6,0x12,0x84, +0x5f,0x7e,0x24,0x0, 0x5, 0xad,0x12,0x7a,0x17,0x28,0xa1,0x7e,0x14,0x61,0xc8,0x12, +0x5b,0x79,0xad,0x32,0x7a,0x37,0x28,0xa3,0x7e,0xb3,0x39,0xfa,0x60,0x7, 0x14,0x7a, +0xb3,0x39,0xfa,0x80,0x6, 0x7e,0xb3,0x28,0xac,0x60,0x9, 0x12,0x87,0x53,0x12,0x87, +0x70,0x12,0xbf,0xe1,0x7e,0xb3,0x28,0xad,0x60,0x9, 0x12,0xc3,0xa4,0x12,0xa3,0x33, +0x2, 0xab,0xb9,0x22,0x7e,0x90,0x1, 0x7e,0x94,0x61,0xc6,0x7e,0x84,0x0, 0xff,0xb, +0x4a,0x30,0x7a,0x37,0x28,0xa1,0x7e,0xb4,0x61,0xc8,0x7e,0xa4,0x0, 0xff,0xb, 0x5a, +0x30,0x7a,0x37,0x28,0xa3,0x12,0x87,0x67,0xb, 0x1a,0x20,0x7e,0x14,0x61,0x4f,0x7e, +0x4, 0x0, 0xff,0xb, 0xa, 0xd0,0xe4,0x7a,0xb3,0x28,0xac,0x12,0x86,0x2e,0x7e,0x34, +0xff,0xfa,0xad,0x32,0x12,0x9a,0x73,0x7d,0xc3,0xe, 0x34,0x7e,0x27,0x7, 0xfe,0xbd, +0x2c,0x58,0x1c,0x7e,0xc7,0x7, 0xfc,0xbd,0xc3,0x58,0x14,0x6d,0xcc,0x9e,0xc7,0x2a, +0x5a,0xbe,0xc7,0x28,0x8e,0x8, 0x8, 0x12,0xa3,0x9a,0x60,0x3, 0x12,0xa5,0x3b,0x12, +0xa5,0x4a,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12,0x87,0xc9,0x68,0x6, 0x7e,0xb3, +0x33,0xfe,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x6f,0x12,0x86,0x35,0x28,0x5, +0xe4,0x7a,0xb3,0x28,0xad,0x30,0x12,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0xa5,0x88, +0x50,0xa, 0x12,0x86,0x2e,0x12,0x86,0x6b,0x7c,0x9b,0x80,0x17,0x7e,0xb3,0x26,0x84, +0x70,0x11,0x7e,0xb3,0x26,0x85,0x70,0xb, 0x12,0x86,0x35,0x28,0x6, 0x7e,0x90,0x3, +0x12,0x86,0x2e,0x7e,0xc7,0x7, 0xfa,0xbe,0xc4,0x5, 0xdc,0x8, 0x17,0x12,0x86,0x35, +0x28,0x12,0x6d,0xcc,0x9d,0xcd,0xbe,0xc7,0x28,0x8e,0x58,0x8, 0x12,0x86,0x40,0xe4, +0x7a,0xb3,0x28,0xad,0xa, 0x29,0xb, 0x4a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa1,0xa, +0x29,0xb, 0x5a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa3,0x12,0x86,0x3d,0x50,0xd, 0xe4, +0x7a,0xb3,0x28,0xad,0x12,0x87,0xc1,0x28,0x3, 0x12,0x86,0x40,0x7e,0xc7,0x28,0x8a, +0xbd,0xcd,0x8, 0x1f,0x7e,0x24,0x0, 0x2, 0x7d,0x3d,0x12,0x1e,0xb9,0x6e,0x34,0xff, +0xff,0xb, 0x34,0xbe,0x37,0x28,0x8e,0x58,0xa, 0x12,0x86,0x3d,0x50,0x5, 0xe4,0x7a, +0xb3,0x28,0xad,0x12,0x99,0x34,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0xa4, +0xa2,0x7e,0xb3,0x0, 0x63,0xbe,0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x0, 0x63,0x70, +0x1c,0xe4,0x7a,0xb3,0x28,0xad,0x74,0x1, 0x7a,0xb3,0x28,0xac,0xe4,0x7a,0xb3,0x16, +0x91,0x7a,0xb3,0x16,0x90,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x26,0x83,0x22,0x74,0x1, +0x7a,0xb3,0x28,0xad,0x22,0x7e,0x83,0x28,0x84,0xbe,0x80,0x0, 0x22,0xa2,0x15,0x22, +0xe4,0x7a,0xb3,0x0, 0x63,0x7a,0xb3,0x28,0xac,0x74,0x2, 0x2, 0x2a,0x28,0x12,0xad, +0xa3,0x60,0x17,0x12,0x86,0x2e,0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1, +0x7e,0x37,0x28,0xa3,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0x7e,0xa0,0x1, 0x7e,0x47, +0x7, 0xf8,0x12,0x87,0x67,0xb, 0x1a,0x0, 0x7e,0x34,0xff,0xfa,0xad,0x30,0x7e,0x14, +0x0, 0x2, 0x12,0x86,0xcf,0x8, 0x12,0x7e,0xb3,0x28,0xac,0x60,0x7, 0xe4,0x7a,0xb3, +0x28,0xad,0x80,0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x12, +0x86,0xcf,0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x23,0x7e,0x34,0xff,0xfc,0xad,0x30,0x12, +0x86,0xcf,0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x13,0x7e,0x34,0xff,0xfd,0xad,0x30,0x12, +0x86,0xcf,0x8, 0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7d, +0x21,0x12,0x1e,0xb9,0xbd,0x34,0x22,0xc2,0x3, 0x12,0x45,0xd2,0x50,0x4b,0x6c,0xaa, +0x80,0x39,0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26,0xfb,0xbe, +0x70,0x0, 0x28,0x25,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27,0xbd,0x21, +0x58,0x17,0xbe,0x60,0x0, 0x28,0x12,0x7e,0xb3,0x2a,0x70,0x1e,0xb0,0xa, 0x1b,0xa, +0x26,0xbd,0x21,0x58,0x4, 0xd2,0x3, 0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc, +0xba,0x38,0xbf,0x20,0x3, 0x3, 0x12,0x86,0x2e,0x30,0x18,0x23,0x5, 0x60,0xe5,0x60, +0xbe,0xb0,0x50,0x50,0x16,0x7e,0x34,0x61,0xc6,0x12,0x23,0x74,0x3e,0x34,0x12,0x87, +0xda,0x12,0x23,0x74,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0xc2,0x18,0x80,0x0, 0x75, +0x60,0x0, 0x22,0x12,0xa4,0xfc,0x12,0x87,0x8d,0x2, 0x87,0x5c,0x12,0xae,0xc7,0x50, +0x3, 0xd2,0x11,0x22,0xc2,0x11,0x22,0x7e,0x34,0x61,0x55,0x7e,0x24,0x0, 0xff,0x22, +0x12,0xa7,0xe1,0x6d,0x33,0x7a,0x37,0x38,0x50,0x6c,0xaa,0x80,0x5, 0x12,0xac,0x7, +0xb, 0xa0,0x12,0x5f,0xcb,0x38,0xf6,0xe4,0x7a,0xb3,0x37,0xe5,0x22,0x7e,0x8, 0x24, +0xf2,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x20,0xe8,0x12,0x87,0xf5,0x12,0x87,0xec,0xa9, +0xd1,0xcb,0x12,0x7f,0xcf,0x7a,0x37,0x24,0xf6,0x7e,0x1f,0x33,0xe0,0x7a,0x37,0x24, +0xf8,0x7e,0x1f,0x13,0x86,0x7a,0x37,0x24,0xfa,0x6d,0x33,0x12,0x87,0xd1,0x2, 0xd, +0x7, 0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0x7e,0xb3,0x28,0xa8,0xbe,0xb0,0x1, +0x22,0x7a,0x37,0x24,0xfc,0x7e,0x8, 0x24,0xf2,0x22,0x7a,0x37,0x28,0xa1,0x7e,0x34, +0x61,0xc8,0x22,0x7e,0x34,0x61,0x43,0x7e,0x24,0x0, 0xff,0x22,0x7e,0x73,0x2a,0x6d, +0x7a,0x73,0x24,0xf2,0x22,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x2, 0x88, +0x1, 0xca,0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c,0xee,0x80,0x35,0x7c,0xbe,0x12, +0x30,0xa4,0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0x2e,0x5f,0x60,0x23,0x7e,0xc4,0x0, +0x9, 0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x27,0x76,0x6d,0x22,0x7e,0x30, +0x9, 0xac,0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0xb, 0xf0, +0xb, 0xe0,0x12,0x47,0xe5,0x38,0xc6,0x7a,0x73,0x28,0x93,0x7a,0xf3,0x2a,0x2, 0xda, +0x79,0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0xb, +0x14,0x12,0x1f,0x5, 0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28,0x4, 0x7e,0x54,0x0, 0x40, +0x22,0xca,0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f,0x3a,0x7e,0x34,0x15,0x9e,0x7a, +0x37,0x1f,0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3,0x1f,0x35,0x7e,0x73,0x2a,0x6f, +0x7a,0x73,0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3,0x1f,0x38,0x7a,0xb3,0x1f,0x39, +0x7e,0x8, 0x1f,0x34,0x12,0x47,0xf4,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15, +0xa0,0x2f,0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12,0x1f,0x7, 0xa, 0x1f,0x6d,0x0, +0x12,0x1f,0x7, 0xda,0xf8,0x22,0x7a,0x37,0x1f,0x38,0x7e,0x34,0x15,0xa8,0x7a,0x37, +0x1f,0x3c,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a,0x7e,0x73,0x2a,0x6f,0x7a,0x73, +0x1f,0x35,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34,0x7e,0x37,0x2a,0x5c,0x7a,0x37, +0x1f,0x3e,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40,0x7e,0x37,0x2a,0x60,0x7a,0x37, +0x1f,0x42,0x74,0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3,0x1f,0x37,0x7e,0x8, 0x1f,0x34, +0x7e,0x18,0x1f,0x44,0x12,0x8, 0x0, 0x7e,0x37,0x1f,0x4e,0x7e,0x27,0x1f,0x4a,0xbd, +0x23,0x28,0x2, 0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, 0x1f,0x34,0x12,0x7f,0xc7,0x7e, +0x1f,0x39,0xea,0x7a,0x1d,0x27,0x7e,0xb3,0x2a,0x74,0xf5,0x2e,0x7e,0xb3,0x39,0x9a, +0xb4,0x1, 0x6, 0x7e,0x38,0x39,0x9c,0x80,0x4, 0x7e,0x38,0x5, 0xf8,0x6d,0x33,0x7a, +0x35,0x2b,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39,0x9b,0x70,0xe, 0x7e,0xb3,0x39, +0x99,0x70,0x8, 0x74,0x1, 0x7a,0xb3,0x39,0x9b,0x21,0xee,0x7e,0xb3,0x39,0x9b,0x70, +0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x9b,0x7e,0xb3,0x39,0x9a,0xb4,0x1, 0x14,0x75,0x2d, +0x0, 0x80,0x6, 0x12,0x8a,0x30,0x12,0x8a,0x3e,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xf3, +0x80,0x18,0x75,0x2d,0x0, 0x80,0xc, 0x12,0x8a,0x30,0x3e,0x24,0x3e,0x24,0x1e,0x24, +0x12,0x8a,0x3e,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e,0x34,0x61,0x5b,0x12,0x23, +0x74,0x7a,0x35,0x2f,0x7e,0x18,0x1f,0x34,0x7f,0x1, 0x12,0x8a,0x4f,0x75,0x2d,0x0, +0x80,0x10,0x12,0x8a,0x23,0xbe,0x35,0x2b,0x8, 0x6, 0x12,0x8a,0x23,0x7a,0x35,0x2b, +0x5, 0x2d,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xe9,0x12,0x8a,0x1b,0x40,0x25,0x7e,0xb3, +0x39,0x9a,0xb4,0x1, 0x1e,0x5, 0x1e,0xe5,0x1e,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x1e, +0x0, 0xe5,0x2e,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, 0x12,0x20, +0xc3,0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x8a,0x1b,0x50,0xb, 0x74,0x2, 0x7a, +0xb3,0x39,0xe9,0xe4,0x7a,0xb3,0x39,0x9b,0xda,0x3b,0x22,0x7e,0x37,0x2b,0x7, 0xbe, +0x35,0x2b,0x22,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x49,0x35,0x1f,0x34,0x2, 0x21,0x1a, +0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7e,0xd, +0x27,0x2d,0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35,0x1f,0x34,0x5, 0x2d,0x22,0xca, +0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x2a,0x6e,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f, +0x16,0x7f,0x5, 0x12,0x20,0xc3,0x1b,0xfd,0x6c,0xdd,0x12,0x7f,0xd7,0x7a,0xb3,0x1f, +0x6c,0x6c,0xcc,0x80,0x4a,0x12,0x8a,0xf8,0x78,0x43,0x74,0x2, 0xac,0xbc,0x7f,0x16, +0x2d,0x35,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x21,0x1a,0x7d,0x13,0x7d,0x3e,0x12,0x21, +0x1a,0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f,0x8, 0x5, 0x7e,0xe5,0x2f,0x80, +0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, 0x7d,0xe3,0x7d,0x3e,0x1a,0x26, +0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x6c,0x4, 0x7a,0xb3,0x1f,0x6c,0xb, 0xc0,0x7e, +0x73,0x2a,0x70,0xbc,0x7c,0x38,0xae,0x7e,0x73,0x1f,0x6c,0x4c,0x77,0x68,0x1d,0x12, +0x8b,0x1e,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80,0xa, 0x12,0x8a,0xf8,0x78,0x3, 0x12, +0x8b,0x9, 0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xee,0xb, 0xd0,0xbe,0xd0, +0x2, 0x50,0x2, 0x41,0x6a,0xda,0x3b,0x22,0xa, 0xec,0x9, 0x7e,0x2a,0xdc,0xa, 0x37, +0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d, +0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b,0x1a,0xe0,0x22,0xa, 0x17, +0x6d,0x0, 0x7f,0x14,0x12,0x1f,0x58,0x7d,0x73,0x12,0x21,0x1a,0x7d,0xe3,0x7d,0x3f, +0x12,0x21,0x1a,0xbd,0x3e,0x22,0x12,0x26,0x82,0x7e,0x73,0x3, 0x9a,0xbe,0x70,0xff, +0x68,0x13,0xbe,0x73,0x3, 0xc0,0x68,0xd, 0x7a,0x73,0x3, 0xc0,0x74,0xff,0x7a,0xb3, +0x3, 0x9a,0x2, 0x26,0x82,0x22,0x7e,0x34,0x61,0x57,0x7e,0x24,0x0, 0xff,0xb, 0x1a, +0x20,0x12,0x8b,0x71,0x50,0x8, 0x7e,0x27,0x2a,0x4f,0x1e,0x24,0x1e,0x24,0x7d,0x32, +0x22,0xc2,0x3, 0x12,0x8b,0x99,0x68,0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17,0x7e, +0xb3,0x37,0xe4,0x70,0x11,0x12,0x45,0xd2,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe,0x34, +0x1, 0x90,0x58,0x2, 0xd2,0x3, 0xa2,0x3, 0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, +0x22,0x7c,0xab,0x7e,0xb3,0x33,0xfe,0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70,0x11,0x12, +0x8f,0xa0,0x68,0xc, 0x12,0x8b,0x99,0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x2e,0xdd, +0x22,0xca,0xd8,0xca,0x79,0xc2,0x3, 0x6d,0x88,0x7a,0x87,0x39,0x50,0xe4,0x7a,0xb3, +0x1f,0x58,0xe5,0x1f,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x1f,0x7e,0xb3,0x28,0x84,0x60, +0xc, 0x12,0x87,0x67,0xb, 0x1a,0x80,0xbe,0x87,0x7, 0xfa,0x28,0xa, 0xc2,0x12,0x6d, +0x88,0x7a,0x87,0x39,0x11,0x81,0xf2,0x12,0x90,0xab,0x60,0x12,0x7e,0x34,0x62,0x14, +0x12,0x8d,0xfb,0x7a,0x87,0x39,0x7, 0x12,0x8d,0x5c,0x7a,0x87,0x39,0x11,0x7e,0x87, +0x39,0x7, 0x4d,0x88,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x77, +0xe4,0xa, 0x3f,0x19,0xb3,0x1f,0x34,0x12,0x8d,0x76,0x7e,0x8, 0x1f,0x52,0x7c,0xbd, +0x7c,0x7e,0x12,0x35,0x1e,0x7d,0x93,0x7e,0x87,0x39,0x11,0xbd,0x89,0x50,0x4, 0x7a, +0x97,0x39,0x11,0x7e,0x87,0x39,0x50,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x50,0xe5, +0x1f,0xbe,0xb0,0x5, 0x38,0x1f,0x7e,0x8, 0x39,0x13,0x12,0x8d,0x83,0x50,0x7, 0x12, +0x8d,0x6d,0xd2,0x3, 0x80,0x2f,0x7e,0x8, 0x39,0x13,0x7e,0x18,0x1f,0x52,0x12,0x8d, +0xc9,0x50,0x22,0x80,0x10,0x12,0x8d,0x5c,0xbd,0x89,0x38,0x19,0x7e,0x8, 0x1f,0x52, +0x12,0x90,0x5c,0x50,0x10,0x12,0x8d,0x6d,0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52, +0x12,0x8f,0xd7,0xd2,0x3, 0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38,0x81,0x30, +0x3, 0x36,0x6c,0xff,0x80,0x1c,0x12,0x8d,0x76,0x7e,0x8, 0x1f,0x58,0x12,0x8d,0x83, +0x40,0x9, 0xa, 0x3f,0x9, 0xb3,0x1f,0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x8b,0xa1, +0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38,0xdc,0x75,0x1f,0x0, 0x7e,0x34,0x62, +0x14,0x12,0x23,0x74,0x7a,0x37,0x39,0x7, 0x7e,0x63,0x1f,0x58,0x7e,0x70,0x6, 0xac, +0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1f,0x58,0x7e,0x8, 0x39,0x13,0x12,0x20,0xc3, +0x1b,0xfd,0x7e,0x37,0x39,0x7, 0x4d,0x33,0x78,0x39,0x90,0x62,0xf, 0xe4,0x93,0xa, +0x3b,0xbe,0x37,0x39,0x11,0x38,0x43,0x7c,0x7b,0x1e,0x70,0xa, 0x37,0xbe,0x37,0x39, +0x50,0x38,0x37,0x90,0x60,0x51,0x12,0x8d,0x64,0x7e,0x73,0x26,0xf7,0xa, 0x37,0xbd, +0x32,0x8, 0x27,0x90,0x60,0x50,0x12,0x8d,0x64,0x7e,0x73,0x26,0xf6,0xa, 0x37,0xbd, +0x32,0x8, 0x17,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12,0x8b,0xa1,0xb, 0xf0,0x7e,0x73, +0x28,0x84,0xbc,0x7f,0x38,0xf1,0xd2,0x3, 0x80,0x6, 0x6d,0x33,0x7a,0x37,0x39,0x11, +0xa2,0x3, 0x92,0x12,0x12,0x8f,0xa8,0xda,0x79,0xda,0xd8,0x22,0x90,0x62,0xf, 0xe4, +0x93,0xa, 0x8b,0x22,0xe4,0x93,0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, +0x8f,0x19,0xb8,0x1f,0x34,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5, +0x26,0xfb,0x22,0x7c,0xbd,0x7c,0x7e,0x7c,0x6b,0xc2,0x4, 0x6c,0xaa,0x80,0x30,0x7e, +0x50,0x6, 0xac,0x5a,0x7f,0x70,0x2d,0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6, +0x40,0x1b,0x7e,0x7b,0xb0,0xbc,0xb6,0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40, +0xc, 0x29,0xb7,0x0, 0x1, 0xbc,0xb7,0x38,0x4, 0xd2,0x4, 0x80,0x9, 0xb, 0xa0,0x7e, +0xb, 0xb0,0xbc,0xba,0x38,0xc9,0xa2,0x4, 0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90, +0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x8d, +0x87,0x50,0x2, 0xd3,0x22,0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, +0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79,0x50,0xd9,0xc3,0x22,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x80,0x22,0xca,0xf8,0x6c,0xff,0x7e,0xb7,0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e, +0x97,0x2f,0x84,0x7e,0xd7,0x2f,0x86,0x7e,0xa7,0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4, +0x7e,0x73,0x2f,0xa8,0x1b,0x70,0x7d,0x2b,0x7d,0x1c,0x12,0x8f,0x4b,0x70,0x2, 0xe1, +0x32,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0xa, 0x28,0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27, +0x2f,0xa0,0x7e,0x17,0x2f,0xa2,0x12,0x8f,0x4b,0x70,0x2, 0xe1,0x32,0x7e,0x73,0x2f, +0xa8,0xbe,0x70,0x14,0x28,0x13,0xe4,0x7e,0x70,0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17, +0x2f,0xa6,0x12,0x8f,0x4b,0x70,0x2, 0xe1,0x32,0x7e,0x34,0x62,0x78,0x12,0x8f,0x37, +0x28,0x4a,0x7e,0x34,0x62,0x76,0x12,0x8f,0x41,0x50,0x41,0x7e,0xb3,0x2f,0x81,0x70, +0x3b,0x7e,0x34,0x62,0x7c,0x12,0x23,0x74,0x12,0x5e,0xa6,0x7d,0x8f,0x9d,0x83,0xbe, +0x87,0x2f,0x82,0x50,0x27,0x7e,0x34,0x62,0x7a,0x12,0x8d,0xfb,0x9d,0xf8,0xbe,0xf7, +0x2f,0x82,0x28,0x18,0x7d,0xfc,0x3e,0xf4,0xbd,0xfb,0x40,0x2, 0xe1,0x32,0xbd,0xa9, +0x50,0x5, 0x7e,0xf0,0x20,0x80,0x7b,0x7e,0xf0,0x21,0x80,0x76,0x7e,0x34,0x62,0x80, +0x12,0x8f,0x41,0x28,0x6d,0x7e,0x34,0x62,0x7e,0x12,0x8f,0x37,0x50,0x64,0x7e,0xb3, +0x2f,0x81,0x70,0x5e,0x7e,0x34,0x62,0x84,0x12,0x23,0x74,0x12,0x5e,0xa6,0x7d,0xaf, +0x9d,0xa3,0xbe,0xa7,0x2f,0x82,0x50,0x4a,0x7e,0x34,0x62,0x82,0x7e,0x24,0x0, 0xff, +0xb, 0x1a,0xa0,0x9d,0xfa,0xbe,0xf7,0x2f,0x82,0x28,0x37,0x7d,0xfb,0x3e,0xf4,0xbd, +0xfc,0x50,0x2f,0xbd,0xed,0x50,0x5, 0x7e,0xf0,0x22,0x80,0x26,0x12,0x5f,0xd3,0x49, +0x35,0x2b,0xbb,0x49,0x15,0x2b,0xbd,0x49,0x25,0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d, +0x10,0xbe,0x14,0x0, 0x20,0x18,0x8, 0x9d,0x32,0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e, +0xf0,0x23,0x7c,0xbf,0xda,0xf8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xbd,0xfc, +0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xbd,0xfb,0x22,0x7d,0x41,0x7d,0x2, 0x7c, +0x37,0x7c,0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35,0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74, +0x4, 0xac,0xb3,0x49,0x25,0x2b,0xbf,0x49,0x55,0x2b,0xc1,0x12,0x47,0x7d,0x7d,0x3f, +0x9d,0x35,0x12,0x21,0x1a,0x9d,0x34,0x12,0x21,0x1a,0x7e,0x54,0x62,0x70,0x7e,0x44, +0x0, 0xff,0xb, 0x2a,0x20,0xbd,0x32,0x50,0x15,0x12,0x5f,0xc4,0x7e,0x14,0x62,0x70, +0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x32,0x50,0x3, 0x74,0x1, 0x22,0xe4,0x22, +0x7e,0xb3,0x3, 0xeb,0xbe,0xb0,0x1, 0x22,0x30,0x12,0x13,0x12,0x87,0xc9,0x68,0x6, +0x7e,0xb3,0x33,0xfe,0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x39,0xf, 0x22,0x12, +0x8b,0x71,0x50,0x12,0x7e,0x37,0x2b,0x7, 0xbe,0x34,0x1, 0x2c,0x28,0x8, 0x7e,0x34, +0x1, 0x2c,0x7a,0x37,0x2b,0x7, 0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe,0xa0,0xa, 0x50, +0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d,0x15,0xb, 0x14, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22,0x7e,0xb3,0x3, +0xc0,0x70,0x2e,0x7e,0x73,0x3, 0xa3,0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77,0x7e,0xb3, +0x3, 0xeb,0xb4,0x1, 0x3, 0x7e,0x70,0x6, 0xa, 0x37,0x2e,0x34,0xf, 0xf0,0x12,0x6f, +0xee,0x7c,0xab,0xe5,0x62,0xa, 0x3b,0x2e,0x37,0x39,0x97,0x7a,0x37,0x39,0x97,0x80, +0xc, 0x7e,0xa3,0x3, 0xa4,0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, +0x90,0x42,0x75,0x62,0x0, 0x7a,0xb3,0x3, 0xfe,0xc2,0x1a,0x22,0x7e,0xb3,0x39,0x9a, +0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x9a,0x22,0x7f,0x20,0xc2,0x4, +0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x21,0x1a,0x7c,0x27, +0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x21,0x1a,0x7c, +0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x21,0x1a,0x7c,0x67,0x7c,0x72,0xbc,0x32, +0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e,0x37, +0x39,0x7, 0x4d,0x33,0x68,0x2, 0xd2,0x4, 0xa2,0x4, 0x22,0x6c,0xaa,0x7e,0x63,0x2a, +0x6e,0x7e,0x73,0x2a,0x6d,0xac,0x76,0x7d,0x13,0x1e,0x14,0x7e,0x27,0x28,0x88,0x2e, +0x27,0x28,0x86,0xbd,0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34,0xbe,0x37,0x28,0x86,0x50, +0x29,0x90,0x60,0x51,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26,0xf7,0xa, 0x3b, +0xbd,0x32,0x8, 0x16,0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26, +0xf6,0xa, 0x3b,0xbd,0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7e,0xa3,0x2a, +0x3, 0xbe,0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, +0xbe,0xb3,0x37,0x30,0x28,0x14,0x7e,0xb3,0x37,0x30,0x4, 0x7a,0xb3,0x37,0x30,0x7a, +0xa3,0x2a,0x2, 0x80,0x5, 0xe4,0x7a,0xb3,0x37,0x30,0x7e,0xb3,0x2a,0x2, 0x70,0x5, +0xe4,0x7a,0xb3,0x2a,0xb, 0x22,0x12,0x91,0x3c,0x2, 0x90,0xfd,0x7e,0xb3,0x2a,0x2, +0x70,0x2d,0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x28,0x24,0x7e,0xb3,0x36,0xb5,0x70, +0x18,0x12,0x91,0x79,0x7e,0x73,0x2a,0x3, 0x7a,0x73,0x2a,0x2, 0x74,0x1, 0x7a,0xb3, +0x2a,0x9, 0x7e,0xb3,0x36,0xb5,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x36,0xb5,0x22,0xe4, +0x7a,0xb3,0x36,0xb5,0x7a,0xb3,0x2a,0x9, 0x22,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e, +0x18,0x33,0x4c,0x7e,0x8, 0x33,0x88,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x73,0x28,0x94, +0x7a,0x73,0x33,0x48,0x7a,0x73,0x28,0x93,0x22,0xca,0x3b,0x6d,0x11,0x7d,0x1, 0x7e, +0xe3,0x2a,0x2, 0x4c,0xee,0x78,0x23,0x6c,0xff,0x80,0x1a,0x74,0x2, 0xac,0xbf,0x12, +0x93,0x6a,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x36,0xba,0x74,0x2, 0xa, 0x3f,0x19, +0xb3,0x37,0x24,0xb, 0xf0,0x12,0x3b,0xe3,0x38,0xe1,0x12,0x94,0x63,0x7e,0x24,0x0, +0x14,0xad,0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c,0xff,0x61,0x43,0x74,0x9, 0xac, +0xbf,0x9, 0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0x12,0x93,0x84,0x38,0x2, 0x61,0x41,0xa, +0x1d,0x9, 0xb1,0x29,0xbc,0xbe,0xb0,0x1, 0x78,0x2, 0x61,0x27,0x75,0x24,0x0, 0x61, +0x19,0x7e,0x31,0x24,0x74,0x9, 0xac,0x3b,0x9, 0xc1,0x36,0xba,0xbc,0xcd,0x68,0x2, +0x61,0x17,0x7e,0xa3,0x2a,0x70,0x74,0x40,0xa4,0x9e,0x54,0x0, 0x20,0x7e,0x34,0x60, +0xd1,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0x2d,0xf5,0x49,0x21,0x36,0xb8,0xbd,0x2f, +0x28,0x9, 0x12,0x93,0x7b,0xbd,0x3f,0x38,0x2, 0x41,0xc3,0x12,0x93,0x7b,0x9d,0x32, +0x12,0x21,0x1a,0x7d,0x3, 0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49,0x25,0x36,0xb6,0x12, +0x96,0xa8,0x9d,0x32,0x12,0x21,0x1a,0x2d,0x3, 0xa, 0x1c,0x9, 0xa1,0x37,0x24,0xbe, +0xa0,0x0, 0x28,0x17,0x7e,0x30,0x2, 0xac,0x3c,0x59,0x1, 0x37,0x10,0xa, 0x1c,0x2e, +0x14,0x37,0x24,0x7c,0xba,0x14,0x7a,0x19,0xb0,0x61,0x41,0x74,0x2, 0xac,0xbc,0x49, +0x15,0x37,0x10,0xbe,0x14,0x0, 0x32,0x28,0x8, 0x7d,0xe1,0x2d,0xe4,0xbd,0xe0,0x40, +0x20,0xbe,0x14,0x0, 0x32,0x28,0x8, 0xbe,0x4, 0x0, 0x32,0x28,0x2, 0x80,0x72,0x7d, +0xe1,0x2e,0xe4,0x0, 0x32,0xbd,0xe0,0x50,0x8, 0xbe,0x14,0x0, 0x32,0x28,0x2, 0x80, +0x60,0xbe,0x4, 0x0, 0xa0,0x28,0x56,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0x70,0x4, 0x74, +0x3, 0x80,0x2, 0x74,0x1, 0xa, 0x1d,0x19,0xb1,0x29,0xbc,0x74,0x3, 0xa, 0x1c,0x19, +0xb1,0x29,0xc6,0xbe,0xe0,0x0, 0x28,0x69,0x1b,0xe0,0x7e,0x70,0x9, 0xac,0x7f,0x2e, +0x34,0x28,0xae,0x7e,0x14,0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0x7e,0x70,0x9, 0xac, +0x7e,0x12,0x96,0x98,0xac,0x3f,0x12,0x93,0x72,0x7e,0x34,0x1f,0x34,0x7e,0x30,0x9, +0xac,0x3e,0x12,0x93,0x72,0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74,0x2, 0xac, +0xbc,0x59,0x5, 0x37,0x10,0x80,0x2a,0x5, 0x24,0x90,0x60,0x99,0xe4,0x93,0xbe,0xb1, +0x24,0x28,0x2, 0x41,0x1, 0x80,0x1a,0x6d,0x11,0x74,0x2, 0xac,0xbd,0x12,0x93,0x6a, +0x7e,0x30,0x9, 0xac,0x3d,0x19,0xa1,0x36,0xba,0x74,0x2, 0xa, 0x1d,0x19,0xb1,0x37, +0x24,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x21,0xdd,0xe4,0x7a,0xb3,0x16,0x92,0x90,0x60, +0x99,0x12,0x94,0x5c,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x36,0xb6,0x12,0x20, +0xc3,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, 0xda,0x3b,0x22,0x59,0x15,0x37,0x10,0x7e,0xa0, +0xff,0x22,0x2e,0x14,0x28,0xae,0x74,0x9, 0x2, 0x1f,0x8c,0x74,0x9, 0xac,0xbf,0x49, +0x35,0x28,0xb0,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbd,0x22,0xca,0x3b,0x7c,0xfb, +0x6c,0xee,0x80,0x65,0x6c,0xdd,0x80,0x16,0x74,0x9, 0xac,0xbd,0x9, 0x65,0x29,0x66, +0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb2,0xbc,0x67,0x68,0x7, 0xb, 0xd0,0x12,0x93, +0x84,0x38,0xe5,0x12,0x93,0x84,0x28,0x45,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x29,0x66, +0x12,0x47,0x71,0x74,0x9, 0xac,0xbd,0x12,0x96,0xb1,0x9d,0x32,0x12,0x21,0x1a,0x2d, +0x31,0x7a,0x35,0x24,0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, 0x6d,0x33,0x74, +0x2, 0xac,0xbc,0x59,0x35,0x36,0x7e,0x59,0x35,0x36,0xa1,0x7e,0x35,0x24,0x7c,0xbd, +0x7c,0x5e,0x7c,0x4c,0x12,0x47,0xe2,0xb, 0xe0,0xbc,0xfe,0x38,0x97,0xda,0x3b,0x22, +0x7e,0xb3,0x3, 0xeb,0x70,0x3, 0x12,0x91,0x99,0x2, 0x94,0xc, 0xca,0x79,0x7e,0xf3, +0x2a,0x2, 0x7e,0xe3,0x2a,0x3, 0x7c,0xbf,0x7c,0x7e,0x12,0x94,0x9b,0x7c,0xbf,0x12, +0x95,0x35,0x4c,0xee,0x78,0x14,0x12,0x94,0x58,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e, +0x8, 0x29,0x62,0x12,0x20,0xc3,0x1b,0xfd,0x80,0xb, 0x7e,0xb3,0x2a,0x9, 0x70,0x5, +0x7c,0xbf,0x12,0x93,0x8c,0x7c,0xbf,0x12,0x96,0xee,0xbe,0xf0,0x0, 0x28,0x6, 0x74, +0x1, 0x7a,0xb3,0x2a,0xb, 0xda,0x79,0x22,0x90,0x60,0x99,0xe4,0x93,0x7c,0xab,0x74, +0x9, 0xa4,0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x73,0x2a,0x2, 0x78,0x13,0x12,0x96,0xa0, +0x40,0xe, 0x7e,0x37,0x36,0x92,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, +0x7e,0x37,0x36,0x92,0x1e,0x34,0x7a,0x37,0x36,0x92,0x7e,0xb3,0x2a,0x2, 0x70,0x6, +0x6d,0x33,0x7a,0x37,0x36,0x92,0x7e,0x37,0x36,0x92,0x22,0x7c,0x67,0x7c,0x7b,0xa5, +0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0xe4,0x7a, +0xb3,0x2a,0x9, 0x7a,0xb3,0x2a,0xa, 0x2, 0x95,0x10,0xa5,0xbe,0x0, 0x1d,0x6c,0xaa, +0x80,0xe, 0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62,0x29,0x66,0xb, 0xa0, +0x12,0x39,0x49,0x38,0xed,0x74,0x1, 0x7a,0xb3,0x2a,0x6, 0x6c,0xaa,0x80,0x20,0x7e, +0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0x95,0x4, 0x1b,0x18,0x20,0x7e,0x30, +0x9, 0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0x95,0x4, 0x1b,0x18,0x20,0xb, 0xa0,0xbc, +0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22, +0x12,0x95,0x29,0x7e,0x8, 0x36,0xa1,0xe4,0x12,0x20,0xe8,0x90,0x60,0x99,0x12,0x95, +0x2d,0x7e,0x8, 0x36,0x7e,0xe4,0x2, 0x20,0xe8,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b, +0x74,0x2, 0xac,0x7b,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x60,0x99,0xe4,0x93, +0x7c,0xfb,0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1f, +0x38,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x34,0x74,0x9, 0xac, +0xb1,0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d, +0x12,0x96,0x8e,0x7c,0x7d,0x7c,0x6f,0x12,0x96,0x8e,0x6c,0x0, 0x80,0x39,0x6c,0xee, +0x80,0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38,0x74,0x9, 0xac,0xb0,0x9, 0x75, +0x28,0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x15, +0x7e,0x70,0x9, 0xac,0x70,0x12,0x96,0x98,0xac,0x31,0x2e,0x14,0x1f,0x34,0x74,0x9, +0x12,0x1f,0x8c,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf,0xca, +0x59,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x79, +0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0xc1,0x76,0x7c,0x57,0xc1, +0x6e,0x7e,0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66,0x7c,0x98,0x7e,0xd0,0x9, 0xac, +0xd5,0x9, 0xb6,0x28,0xb2,0xbc,0xb9,0x78,0x73,0xbe,0x90,0xff,0x68,0x6e,0x12,0x96, +0x86,0x2d,0xf7,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x29,0xbc,0x7e,0xf0,0x9, +0x70,0xc, 0xac,0xf5,0x7d,0x97,0x2e,0x94,0x28,0xae,0x6d,0x88,0x80,0xa, 0xac,0xf6, +0x7d,0x97,0x2e,0x94,0x29,0x62,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x96,0x86,0x2d,0xf7, +0x1b,0x7a,0xd0,0x69,0xf4,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7, +0x79,0xf6,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb3,0x12,0x96,0x86, +0x2d,0xf7,0x39,0x87,0x0, 0x5, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb4,0x12, +0x96,0x86,0x2d,0xf7,0x39,0x87,0x0, 0x6, 0xb, 0xa0,0x80,0x8, 0xb, 0x50,0xbc,0x45, +0x28,0x2, 0xa1,0xe1,0xb, 0x60,0x90,0x60,0x99,0xe4,0x93,0xbc,0xb6,0x28,0x2, 0xa1, +0xdd,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x70,0x22,0x7e,0x8, +0x1f,0x34,0x12,0x95,0xd3,0x7c,0x1b,0x22,0x2e,0x34,0x28,0xae,0x7e,0x30,0x9, 0x22, +0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, 0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xae, +0x22,0x49,0x25,0x29,0x62,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xae,0x22,0x7e,0xb3, +0x2a,0x9, 0x70,0x23,0x7e,0xb3,0x36,0x94,0xb4,0x2, 0x9, 0x12,0x96,0xa0,0x28,0x4, +0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x36,0x9f,0x7e,0x73,0x36,0xa0,0xbe,0x73,0x36, +0x9f,0x28,0x4, 0x7a,0x73,0x36,0x9f,0x22,0x12,0x97,0xe5,0x2, 0x96,0xbe,0x6c,0xaa, +0x80,0x49,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x62,0x12,0x25,0x12,0x59,0x32, +0x28,0xae,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x64,0x12,0x25,0x12,0x59,0x32, +0x28,0xb0,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x66,0x19,0xb4,0x28,0xb2,0x7e, +0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x67,0x19,0xb4,0x28,0xb3,0x7e,0x90,0x9, 0xac, +0x9a,0x9, 0xb4,0x29,0x68,0x19,0xb4,0x28,0xb4,0xb, 0xa0,0x12,0x39,0x49,0x38,0xb2, +0x22,0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x36, +0x95,0xbe,0x73,0x36,0x9f,0x50,0xe, 0x7d,0x24,0x2e,0x24,0x36,0x95,0x7c,0xb7,0x4, +0x7a,0x29,0xb0,0xd3,0x22,0xbe,0x73,0x36,0x9f,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, +0xe4,0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4,0x36,0x95,0x80,0x17,0xa, 0x3a,0x9, 0xb3, +0x36,0x95,0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x36,0x95,0xd3,0x22,0xe4,0x19, +0xb3,0x36,0x95,0xc3,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x2a,0x62,0xbd, +0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c, +0x77,0x12,0x1f,0x5, 0xbe,0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10,0x74,0x2, +0xac,0xbf,0x49,0x25,0x36,0xa1,0xbd,0x2f,0x28,0x6, 0x49,0x35,0x36,0x7e,0x80,0x4, +0x59,0x35,0x36,0x7e,0x59,0xf5,0x36,0xa1,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34, +0x1, 0x0, 0xda,0xf8,0x22,0xca,0x79,0x7e,0xa3,0x2a,0x2, 0x7e,0x8, 0x29,0xbc,0x7e, +0x90,0xa, 0x12,0x0, 0x6e,0x50,0x3, 0x7e,0x90,0x19,0x4c,0xaa,0x78,0x5, 0x12,0x5e, +0xc5,0x21,0x17,0x6c,0x88,0x21,0xc, 0x7e,0x70,0x9, 0xac,0x78,0x9, 0xf3,0x29,0xc, +0xbe,0xf0,0xff,0x78,0x2, 0x21,0xa, 0xa, 0x2f,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0xe0, +0xbe,0xe0,0x2, 0x68,0x2, 0x1, 0xed,0x7e,0x50,0x4, 0xac,0x5f,0x49,0x22,0x37,0x31, +0x49,0x33,0x29,0x8, 0x12,0x99,0x2c,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x23,0x37,0x33, +0x12,0x99,0x22,0x9d,0x32,0x12,0x21,0x1a,0x7d,0xe3,0x7e,0xb3,0x36,0x7c,0xa, 0x3b, +0xbd,0x3f,0x28,0x54,0xbd,0x3e,0x28,0x50,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x37, +0x31,0x7e,0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0x8, 0x7e,0x70,0x4, 0xac,0x7f,0x49, +0x33,0x37,0x33,0x7e,0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0xa, 0xbe,0xa0,0x0, 0x28, +0x2, 0x1b,0xa0,0x4c,0xaa,0x68,0x2, 0x21,0xa, 0x7e,0xb3,0x36,0x7d,0x4, 0x7a,0xb3, +0x36,0x7d,0xbe,0xb0,0x32,0x40,0x73,0xe4,0x7a,0xb3,0x36,0x7d,0x12,0x99,0x1a,0x50, +0x69,0x4, 0x7a,0xb3,0x36,0x7c,0x80,0x62,0x7e,0x70,0x9, 0xac,0x78,0x49,0xd3,0x29, +0x8, 0x7e,0x50,0x4, 0xac,0x5f,0x59,0xd2,0x37,0x31,0x49,0x33,0x29,0xa, 0x59,0x32, +0x37,0x33,0x12,0x0, 0x6e,0x50,0x7, 0x12,0x99,0x1a,0x28,0x1a,0x80,0x13,0x7e,0x73, +0x36,0x7c,0xbc,0x79,0x40,0x4, 0x74,0x1, 0x80,0x8, 0xbe,0x70,0x1, 0x28,0x7, 0x7c, +0xb7,0x14,0x7a,0xb3,0x36,0x7c,0xe4,0x7a,0xb3,0x36,0x7d,0x80,0x1d,0x4c,0xee,0x78, +0x19,0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x5f,0x59, +0x32,0x37,0x31,0x12,0x99,0x22,0x59,0x32,0x37,0x33,0xb, 0x80,0x90,0x60,0x99,0xe4, +0x93,0xbc,0xb8,0x28,0x2, 0x1, 0x7, 0xda,0x79,0x22,0x7e,0xb3,0x36,0x7c,0xbe,0xb0, +0x1, 0x22,0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x29,0xa, 0x22,0x9d,0x32,0x12,0x21, +0x1a,0x7d,0xf3,0x22,0xca,0x3b,0x12,0x9a,0x1a,0x38,0x2, 0x21,0xf7,0x7e,0xc3,0x0, +0x66,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x0, 0x66,0xe4,0x7a,0xb3,0x0, 0x68,0x6c,0xaa, +0x80,0x26,0x12,0x9a,0x2, 0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3,0x26,0xfa,0x9, 0xe3, +0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12, +0x36,0xed,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xd2, +0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80,0x31,0x12,0x9a,0x2, 0x7e,0x49,0xd0,0x9, 0xe4, +0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1b,0x12,0x36,0xed,0x7d, +0x23,0x49,0x34,0x0, 0x2, 0x12,0x99,0x2c,0xbe,0xf4,0x0, 0x23,0x8, 0x9, 0x74,0x5, +0x19,0xb4,0x0, 0x8, 0x75,0x5f,0x1, 0xb, 0xa0,0xbc,0xfa,0x38,0xcb,0x4c,0xff,0x78, +0x2, 0x80,0x26,0x7e,0x73,0x0, 0x68,0xbe,0x70,0x4, 0x40,0x22,0x6c,0xaa,0x80,0xe, +0x12,0x9a,0x2, 0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, 0xb, 0xa0,0xbc,0xfa, +0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x5f,0x0, 0x12,0x9a,0xc, 0x80,0xf, 0x7c,0xb7, +0x4, 0x7a,0xb3,0x0, 0x68,0x80,0x6, 0x12,0x9a,0xc, 0x75,0x5f,0x0, 0xe5,0x5f,0xda, +0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x0, 0x69,0x22,0xe4,0x7a,0xb3,0x0, +0x67,0x7a,0xb3,0x0, 0x66,0x7a,0xb3,0x0, 0x68,0x22,0x7e,0xb3,0x28,0x84,0xbe,0xb0, +0x0, 0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12,0x9a,0x1a,0x28,0x35,0x6d,0x22, +0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x9a,0x73,0xbe,0x37,0x7, 0xfa,0x8, +0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, 0x70,0x17,0x7e,0xb3,0x3, 0xc2, +0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x5e,0xe5,0x5e,0xbe,0xb0,0x10,0x28,0x5, 0xd2,0x13, +0x75,0x5e,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x5e,0x0, 0x22,0xe5,0x2a,0xa, 0x2b,0xa, +0x3e,0x2d,0x32,0x7e,0x24,0x0, 0x2, 0x2, 0x1e,0xb9,0xca,0xd8,0xca,0x79,0x7e,0x34, +0x62,0x2d,0x12,0x9b,0x25,0x12,0x9f,0x33,0x50,0x2, 0x61,0x20,0x7e,0x34,0x62,0x31, +0x12,0x23,0x74,0x7a,0x35,0x2a,0x90,0x62,0x2c,0xe4,0x93,0x70,0x2, 0x61,0x20,0x7e, +0xb3,0x28,0xa8,0xb4,0x1, 0x7, 0x7e,0x34,0x62,0x2f,0x12,0x9b,0x25,0x7e,0x37,0x28, +0x8a,0xbe,0x34,0x4, 0x4c,0x8, 0x69,0x6c,0xdd,0x80,0x5d,0xc2,0x3, 0x7c,0xbd,0x12, +0x30,0xa4,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xbe,0xfc,0x7a,0x35,0x24, +0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x35,0x26,0x3e,0x34,0x3e,0x34,0x12,0x9a,0x73, +0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e,0x35,0x28,0xbe,0x35, +0x24,0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35,0x26,0x8, 0x2, 0xd2,0x3, 0x7c,0xbd,0x12, +0x9f,0x11,0x50,0x2, 0xc2,0x3, 0x30,0x3, 0xd, 0x7c,0xbd,0x12,0x9e,0xfe,0xac,0x7d, +0x12,0x9e,0xf5,0x12,0x9b,0xe2,0xb, 0xd0,0x7e,0x73,0x28,0x84,0xbc,0x7d,0x38,0x9b, +0xda,0x79,0xda,0xd8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x70,0x22,0xca,0x3b,0x7e, +0xb3,0x2a,0x74,0xf5,0x27,0x12,0x86,0x3d,0x50,0x2, 0x61,0xd3,0x6d,0x33,0x9e,0x37, +0x2a,0x4f,0x3e,0x34,0xbe,0x37,0x7, 0xf8,0x8, 0x2, 0x61,0xd3,0x7e,0xb3,0x16,0x92, +0x60,0x2, 0x61,0xd3,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x69,0x7e,0x77,0x2a,0x51,0x7e, +0x67,0x2a,0x53,0x75,0x24,0x0, 0x80,0x57,0xe5,0x24,0x12,0x2e,0x5f,0x60,0x4e,0x12, +0x9b,0xd6,0x12,0x9e,0xec,0x7e,0xb3,0x2a,0x3, 0xb4,0x1, 0xe, 0x90,0x60,0xab,0xe4, +0x93,0xbe,0xb1,0x26,0x78,0x4, 0xe, 0x64,0xe, 0x74,0x7e,0xa1,0x26,0x74,0x2, 0xa4, +0x49,0x35,0x4, 0xfc,0xbd,0x36,0x48,0x14,0xe5,0x25,0xa, 0x2b,0xe5,0x27,0xa, 0x3b, +0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xfc,0xbd,0x37,0x58,0x11,0xe5,0x24,0x6c,0x77, +0x12,0x2e,0xdd,0x12,0x9b,0xd6,0x9, 0x73,0x26,0xfb,0x12,0x9b,0xe2,0x5, 0x24,0x12, +0x9e,0xe4,0x38,0xa4,0x7e,0xb3,0x2a,0x68,0x70,0x9, 0x7e,0xb3,0x2a,0x6b,0x70,0x3, +0x12,0x9a,0x22,0xda,0x3b,0x22,0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b,0x9, 0xb3,0x26, +0xfa,0x22,0x7c,0x6b,0x7e,0xa3,0x37,0x59,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x37, +0x96,0x19,0x72,0x37,0x97,0x7c,0xba,0x4, 0x7a,0xb3,0x37,0x59,0x22,0xca,0xd8,0xca, +0x79,0xc2,0x3, 0x6c,0xdd,0x7e,0x57,0x28,0x99,0x7d,0xf5,0x7e,0xe7,0x28,0x97,0x7e, +0x37,0x39,0xf, 0x4d,0x33,0x68,0x4, 0x7d,0xf5,0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x2a, +0x6e,0x7c,0x8a,0x7e,0xb3,0x28,0xa5,0x14,0x68,0x21,0x14,0x68,0x14,0x24,0xc2,0x68, +0x8, 0x24,0xfb,0x68,0x16,0x24,0x45,0x78,0x10,0x7c,0xfa,0x7e,0x83,0x2a,0x6d,0x80, +0xa, 0x7e,0x73,0x2a,0x6d,0x2c,0x87,0x80,0x2, 0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c, +0xb9,0x12,0x30,0xa4,0xbe,0x34,0x2, 0x58,0x8, 0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33, +0x28,0x84,0xbc,0x39,0x38,0xe9,0xbe,0xd0,0x3, 0x40,0x2, 0xa1,0xbe,0x7e,0xa3,0x28, +0x85,0xbe,0xa0,0x0, 0x38,0xb, 0xbe,0x30,0x0, 0x28,0x37,0x7e,0xb3,0x26,0x83,0x70, +0x31,0x6c,0x99,0x80,0x29,0xa, 0x29,0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, +0x7a,0xbd,0x2f,0x8, 0x17,0x49,0x3, 0x4, 0xfc,0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d, +0x3e,0x12,0x9a,0x73,0xbd,0x3, 0x8, 0x4, 0xd2,0x3, 0x80,0x6, 0xb, 0x90,0xbc,0x89, +0x38,0xd3,0x6d,0xee,0x9e,0xe7,0x2a,0x4f,0xbe,0xe7,0x7, 0xf8,0x8, 0x2, 0xc2,0x3, +0x30,0x3, 0x20,0x7e,0xb3,0x33,0xfe,0x4, 0x7a,0xb3,0x33,0xfe,0x7e,0x23,0x33,0xfe, +0xbe,0x20,0xa, 0x28,0x1d,0x74,0xa, 0x7a,0xb3,0x33,0xfe,0x74,0x1, 0x7a,0xb3,0x28, +0xa8,0x80,0xf, 0x7e,0x23,0x33,0xfe,0xbe,0x20,0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23, +0x33,0xfe,0x6c,0xee,0xbe,0x30,0x0, 0x38,0x5, 0xbe,0xa0,0x0, 0x28,0x69,0x7e,0xb3, +0x28,0xa7,0xb4,0x1, 0x9, 0x7e,0xb3,0x28,0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3, +0x28,0xa8,0xb4,0x1, 0x52,0x6c,0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3, +0x26,0xfa,0x9, 0xd3,0x26,0xfb,0x12,0x36,0xe6,0xbe,0x34,0x0, 0x96,0x8, 0x5, 0x7e, +0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x28,0x84,0xbc,0xb9,0x38,0xdb,0x6c,0x99, +0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x27,0x36,0x9, 0xd3,0x27,0x37,0x12, +0x36,0xe6,0xbe,0x34,0xff,0x6a,0x58,0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e, +0xb3,0x28,0x85,0xbc,0xb9,0x38,0xdb,0x6c,0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d, +0x5e,0x3e,0x54,0x49,0x55,0x5, 0x7a,0xbd,0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, +0xb, 0x90,0xbc,0x89,0x38,0xe5,0x4c,0xee,0x78,0x25,0x7e,0xb3,0x33,0xff,0x4, 0x7a, +0xb3,0x33,0xff,0x7e,0x73,0x33,0xff,0xbe,0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3, +0x33,0xff,0x7e,0xb3,0x28,0xa8,0x60,0x2, 0xd2,0x17,0x12,0x9f,0x7, 0x80,0xf, 0x7e, +0x73,0x33,0xff,0xbe,0x70,0x0, 0x28,0x6, 0x1e,0x70,0x7a,0x73,0x33,0xff,0xda,0x79, +0xda,0xd8,0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28,0x99,0xe4, +0x7a,0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x4c,0x7e,0x73,0x28, +0x85,0xbe,0x70,0x0, 0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, +0xd2,0x27,0x36,0x9, 0xe2,0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xfc, +0x6d,0x22,0x9e,0x27,0x2a,0x53,0xbd,0x12,0x58,0x19,0x12,0x9e,0xdb,0x49,0x12,0x4, +0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28, +0xa6,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7,0x7e,0xb3, +0x26,0x83,0x70,0x40,0x12,0x87,0xc1,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, +0xac,0x5f,0x9, 0xd2,0x26,0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x9e,0xdb,0x49,0x2, 0x5, +0x7a,0x6d,0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20, +0x5, 0x7a,0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, 0xb, 0xf0, +0xbc,0x7f,0x38,0xc9,0x12,0x9b,0xfd,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37,0x28,0x88, +0x2e,0x37,0x28,0x86,0xbe,0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9, +0x74,0x1, 0x7a,0xb3,0x28,0xaa,0x6c,0xff,0x80,0x1f,0x12,0x36,0xf4,0x49,0x25,0x25, +0xf7,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x21,0x1a,0xbe,0x37,0x28,0x9d,0x8, 0x7, +0xe4,0x7a,0xb3,0x28,0xaa,0x80,0xa, 0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38, +0xd9,0x6c,0xff,0x80,0x9, 0x12,0x36,0xf4,0x59,0x35,0x25,0xf7,0xb, 0xf0,0x7e,0x73, +0x28,0x84,0xbc,0x7f,0x38,0xef,0xda,0x79,0xda,0xd8,0x22,0xa, 0x1d,0xa, 0x2a,0x2d, +0x21,0x3e,0x24,0x22,0x7e,0x73,0x28,0x84,0xbe,0x71,0x24,0x22,0xf5,0x25,0x9, 0xb3, +0x26,0xfb,0xf5,0x26,0x22,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x22,0x6c,0x77, +0x12,0x2e,0xdd,0x7e,0x70,0x2, 0x22,0xe4,0x7a,0xb3,0x28,0xa8,0x7a,0xb3,0x33,0xfe, +0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x26,0xfa,0x9, 0x65,0x26,0xfb,0x7e, +0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x28,0x8d,0xbc,0x76,0x78,0x2, 0xd3, +0x22,0xc3,0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12,0x30,0xa4,0xbe,0x34, +0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38,0xe9, +0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0x7e,0x8, 0x36,0x94,0x7e,0x34,0x0, +0xd, 0xe4,0x2, 0x20,0xe8,0xca,0xf8,0x6d,0xcc,0x7e,0xd4,0x0, 0x8, 0x7e,0xa3,0x28, +0x84,0x4c,0xaa,0x78,0x17,0x7a,0xc5,0x1b,0xc2,0x8, 0xc2,0x9, 0x7e,0x8, 0x33,0x49, +0x7e,0x34,0x0, 0x3, 0x74,0xff,0x12,0x20,0xe8,0x2, 0xa0,0x38,0xbe,0xa0,0x2, 0x28, +0x3, 0x2, 0xa0,0x2e,0xbe,0xa0,0x2, 0x78,0x29,0x7e,0x73,0x26,0xfc,0xa, 0x27,0x7e, +0x73,0x26,0xfa,0x12,0x2c,0x73,0xbe,0x34,0x0, 0x5, 0x58,0x16,0x7e,0x73,0x26,0xfd, +0xa, 0x27,0x7e,0x73,0x26,0xfb,0x12,0x2c,0x73,0xbe,0x34,0x0, 0x5, 0x58,0x3, 0x2, +0xa0,0x53,0x6c,0xff,0x80,0x5e,0x7c,0xbf,0x12,0xbb,0x42,0x1a,0x4b,0x7c,0xbf,0x12, +0x30,0xa4,0x7d,0xc3,0xbe,0xc4,0x2, 0x58,0x58,0x4, 0x7e,0xd4,0x0, 0x7, 0x7d,0x5d, +0x3e,0x54,0xbd,0x54,0x58,0x4, 0xd2,0x9, 0x80,0xa, 0x7d,0x5d,0xe, 0x54,0xbd,0x54, +0x48,0x2, 0xc2,0x9, 0x20,0x9, 0x4, 0xbd,0xd4,0x58,0x10,0x7e,0x34,0x1, 0x90,0x7a, +0x35,0x1b,0x12,0xa0,0x5d,0x7a,0x73,0x33,0x4b,0x80,0x2d,0x7d,0x5d,0xe, 0x54,0xbd, +0x54,0x58,0x9, 0x12,0xa0,0x5d,0x7a,0x73,0x33,0x4b,0x80,0x6, 0x74,0xff,0x7a,0xb3, +0x33,0x49,0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38,0x9a,0x80,0xa, 0x7e,0x35, +0x1b,0x9e,0x34,0x0, 0x5, 0x7a,0x35,0x1b,0x7e,0x35,0x1b,0xbe,0x34,0x0, 0x0, 0x8, +0x12,0x20,0x8, 0x8, 0xd2,0x8, 0x74,0x14,0x7a,0xb3,0x36,0x7c,0x1b,0x34,0x7a,0x35, +0x1b,0x80,0x7, 0x6d,0x33,0x7a,0x35,0x1b,0xc2,0x8, 0xda,0xf8,0x22,0x74,0x1, 0x7a, +0xb3,0x33,0x49,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfa,0x7a,0x73,0x33,0x4a,0x74, +0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfb,0x22,0x7c,0xab,0xa5,0xbf,0x0, 0xc, 0x7e,0xb3, +0x33,0xc4,0x7a,0xb3,0x33,0xc5,0x7a,0xa3,0x33,0xc4,0x7e,0xb3,0x33,0xc5,0x60,0x4, +0x74,0x8, 0x80,0xd, 0x7e,0xb3,0x28,0x84,0x70,0xb, 0x7e,0xb3,0x33,0xc6,0x60,0x5, +0x14,0x7a,0xb3,0x33,0xc6,0x7e,0x73,0x33,0xc6,0xbe,0x70,0x0, 0x28,0x3, 0x74,0x1, +0x22,0xe4,0x22,0xe4,0x7a,0xb3,0x37,0x59,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3, +0x37,0xd2,0x60,0x5, 0xe4,0x7a,0xb3,0x37,0xd4,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb, +0x7f,0x70,0xc2,0x3, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x22,0xf7,0x7e,0x24,0x0, 0xff, +0x7e,0x14,0x1f,0x34,0x74,0xc, 0x12,0x1f,0xad,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c, +0xee,0x80,0x13,0x12,0xa1,0xdb,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, +0x28,0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, +0x7e,0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0x21,0xcc,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, +0xd2,0x3, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1f,0x34,0xbd,0x4d,0x58,0x6, +0x49,0xd5,0x1f,0x36,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, +0x78,0x4, 0x6d,0x33,0x21,0xcc,0xbd,0xd, 0x8, 0x5, 0x30,0x3, 0x2, 0x7d,0xd0,0x9f, +0x55,0x6c,0xee,0x80,0xb, 0x12,0xa1,0xdb,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0, +0xbc,0xfe,0x38,0xf1,0xa, 0x1f,0x12,0xa1,0xd1,0x9f,0x55,0x6c,0xee,0x80,0x1f,0x74, +0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x21,0x1a,0x7d, +0xc3,0xbd,0x1c,0x28,0x7, 0x12,0xa2,0x93,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe, +0x38,0xdd,0x6d,0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0xa1,0xd1,0xbd,0x1d, +0x8, 0x4, 0x7d,0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10, +0x6c,0xee,0x80,0x12,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x0, 0x9d, +0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc,0xfe,0x38,0xea,0x7d,0x31,0xda,0x79,0xda,0xd8, +0x22,0x6d,0x0, 0x7f,0x15,0x12,0x1f,0x58,0x7d,0x13,0x22,0x74,0x2, 0xac,0xbe,0x7f, +0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x21,0x1a,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c, +0xaa,0x7e,0xf0,0x80,0xc2,0x3, 0x6d,0x44,0x80,0x32,0x12,0xa2,0x8a,0x12,0xa1,0xe3, +0xbd,0x3d,0x48,0x26,0x12,0xa2,0x8a,0xb, 0x1a,0x30,0xbe,0x34,0x0, 0x0, 0x8, 0x4, +0xd2,0x3, 0x80,0x9, 0x12,0x21,0x1a,0xbd,0x3d,0x68,0x2, 0xc2,0x3, 0x7d,0x34,0x3e, +0x34,0x2d,0x3f,0x7d,0x2e,0x12,0xa1,0xe3,0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd, +0xc4,0x38,0xc7,0x30,0x3, 0xc, 0x7e,0xf0,0x7f,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, +0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd, +0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34,0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d, +0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e, +0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0x7c,0xb7,0x12,0xa2,0x9c,0xb, 0x44, +0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda,0xf8,0x22,0x7d,0xc4,0x3e,0xc4,0x7f,0x17, +0x2d,0x3c,0x22,0x7d,0x39,0x1a,0x26,0x1a,0x24,0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34, +0x7a,0x1b,0xb0,0x22,0x90,0x60,0x93,0xe4,0x93,0xa, 0xb, 0x7e,0x73,0x2a,0x71,0xa, +0x17,0x2d,0x10,0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0xad,0x13,0x7d,0x21,0x6c,0x33,0x80, +0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f,0x33,0xe0,0x2d,0xf0,0xb, 0x7a,0x0, +0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x13,0x8e,0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, +0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e,0xf, 0x38,0x54,0x7e,0x18,0x25,0xb6, +0x2, 0xa1,0xe9,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x31,0x12,0xa3,0x2c,0x7e,0x1f,0x33, +0xe0,0x7a,0x37,0x24,0xfa,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x24,0xf6,0x12,0x87,0xec, +0x12,0x87,0xf5,0xe4,0x7a,0xb3,0x24,0xf5,0x7e,0x34,0x0, 0x20,0x7a,0x37,0x24,0xfc, +0x7a,0xb3,0x24,0xf4,0x7e,0x8, 0x24,0xf2,0x2, 0xd, 0x7, 0x22,0xa9,0xd1,0xcb,0xe4, +0x2, 0x0, 0xe, 0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d,0xac,0x54,0x7e,0x17,0x28, +0xa1,0x12,0xa3,0x2c,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x33,0xe0, +0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x8, 0xa, 0xb, +0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, +0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd, +0x20,0x38,0xc5,0x22,0x7c,0xab,0x90,0x60,0xab,0xe4,0x93,0xbc,0xb7,0x78,0x9, 0x7c, +0xba,0x12,0x6c,0xc2,0x50,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0x66,0x90,0x60,0xa7,0xe4, +0x93,0xbe,0xb0,0x0, 0x28,0x71,0x90,0x60,0xaa,0xe4,0x93,0x70,0x6a,0x7e,0xb3,0x28, +0xa8,0xb4,0x1, 0x63,0x7e,0x73,0x26,0xf2,0xbe,0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80, +0x4e,0xa, 0x23,0x9, 0x72,0x26,0xe6,0x7e,0xb3,0x2a,0x6e,0x14,0xbc,0x7b,0x78,0x3d, +0x6c,0x22,0x80,0x27,0x7c,0xb2,0x7c,0x73,0x12,0xa3,0x84,0x50,0x1c,0xa, 0x22,0x7e, +0x73,0x2a,0x6e,0xa, 0x7, 0x2d,0x2, 0x3e,0x4, 0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e, +0x7, 0x2a,0x4f,0xbd,0x20,0x58,0x2, 0xb, 0x60,0xb, 0x20,0x7e,0x73,0x2a,0x6d,0xbc, +0x72,0x38,0xd1,0xbe,0x60,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e, +0x73,0x26,0xf2,0xbc,0x73,0x38,0xaa,0x74,0x1, 0x22,0x12,0xa4,0x32,0x7e,0x14,0x62, +0xd, 0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x32,0x28,0x3, 0xd2,0x15,0x22,0xc2, +0x15,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e,0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac, +0x1a,0x7e,0x7f,0x39,0xea,0x2d,0xf0,0x69,0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d, +0x32,0x12,0x21,0x1a,0xbd,0x31,0x28,0x16,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x39, +0xea,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69,0x30,0x0, 0x80,0x12,0x47,0x7d,0x7e,0x10, +0x2, 0xac,0x1a,0x7e,0x1f,0x39,0xea,0x2d,0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f, +0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69,0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78, +0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x9d,0x7d, +0x31,0x22,0x7e,0x60,0x4, 0x7e,0x27,0x3, 0xfc,0xbe,0x24,0x3, 0xe8,0x28,0x3, 0x7e, +0x60,0x8, 0x7e,0xb3,0x28,0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x0, 0x64,0xbc,0x76,0x50, +0xf, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x86,0x40,0x7e,0xb3,0x0, 0x64,0x4, 0x80,0x4, +0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x64,0x7e,0xb3,0x28,0xad,0xb4,0x1, 0x17,0x7e, +0xa3,0x0, 0x65,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad,0x7c,0xba,0x4, +0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x65,0x22,0x6c,0xaa,0x80,0x26, +0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, 0x2d,0x31,0x59, +0x32,0x5, 0xf8,0x30,0x1, 0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, 0x76,0x2d,0x31, +0x59,0x32,0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0x3b,0x7e,0xb3,0x2a,0x73, +0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0x74,0x2, 0x7a,0xb3,0x0, +0x63,0x74,0x1, 0x7a,0xb3,0x28,0xac,0x2, 0x2a,0x27,0xd2,0x3, 0x6c,0xaa,0x6c,0x77, +0x80,0x1f,0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c,0x65,0x7e,0x50, +0x2, 0xac,0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, 0xb, 0xa0,0xb, +0x70,0x7e,0xb3,0x2a,0x6d,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24,0xa, 0x3a,0xbd, +0x32,0x8, 0x2, 0xc2,0x3, 0xa2,0x3, 0x22,0x7e,0x63,0x2a,0x6f,0x7e,0xa3,0x2a,0x70, +0x7e,0x70,0x1, 0x80,0x25,0xa, 0x17,0x7e,0xb3,0x2a,0x6e,0xa, 0x2b,0x2d,0x21,0x3e, +0x24,0x49,0x12,0x4, 0xfc,0x7e,0xf4,0x61,0x59,0x12,0x84,0x57,0x6e,0x24,0xff,0xff, +0xb, 0x24,0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b,0x14,0xa, 0x27, +0xbd,0x21,0x48,0xd1,0x7e,0x70,0x2, 0x80,0x20,0x7e,0x50,0x2, 0xac,0x57,0x49,0x12, +0x4, 0xfc,0x7e,0xf4,0x61,0x5b,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, 0x6d,0x22,0x9d, +0x20,0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27,0xbd, +0x21,0x48,0xd6,0xc3,0x22,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c,0xeb,0x6c,0xff,0x7e, +0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xc0,0x7e,0x73,0x38,0xe1,0xa, 0xb7, +0x7e,0xb3,0x2b,0x10,0xf5,0x35,0x12,0xa7,0x46,0xbe,0xd0,0x4, 0x38,0x5, 0xe4,0x7a, +0xb3,0x37,0xe5,0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d,0xac,0x75,0x34,0x0, 0x7e,0xa3, +0x37,0xe5,0xbc,0xad,0x40,0x2, 0x80,0x19,0xbe,0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4, +0x9, 0x75,0x26,0x33,0xbc,0x7e,0x78,0xe, 0x7c,0xbd,0x14,0xbe,0xb3,0x37,0xe5,0x78, +0x5, 0xe4,0x7a,0xb3,0x37,0xe5,0x7e,0xc3,0x37,0xe5,0x80,0x41,0x7e,0xb3,0x37,0xe5, +0x4, 0x7a,0xb3,0x37,0xe5,0x7e,0x90,0x5, 0xac,0x9c,0x9, 0xa4,0x26,0x33,0xbc,0xae, +0x68,0x29,0xe5,0x34,0xa, 0xdb,0x19,0xcd,0x37,0xe9,0xa, 0x9a,0xad,0x9b,0x2d,0x9c, +0x7e,0xa1,0x34,0x7c,0xba,0x4, 0xf5,0x34,0x7c,0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31, +0x35,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x6, 0xb, 0xc0,0xbc,0xdc,0x38, +0xbb,0x7a,0xf3,0x37,0xe6,0xda,0x3b,0x22,0x7a,0xb3,0x2b,0xf, 0x12,0x57,0xef,0x30, +0xe, 0xa, 0x12,0x4f,0xfb,0x30,0x3, 0x4, 0xe4,0x12,0xa, 0x66,0x30,0x3, 0x9, 0x12, +0xa7,0x7a,0x12,0xa5,0xf5,0x2, 0x87,0x70,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac, +0xbf,0x12,0xa7,0x4e,0x12,0x7f,0xf1,0x12,0x7f,0xdf,0x12,0x7f,0xe8,0x7a,0xf3,0x2f, +0xa9,0x7c,0xbf,0x12,0xa7,0xac,0x12,0x57,0xef,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x26, +0x37,0x12,0xa7,0x61,0x12,0x23,0x15,0xe4,0x7a,0xb3,0x16,0x91,0xda,0xf8,0x22,0x7e, +0xb3,0x37,0xd9,0x60,0x6, 0x14,0x7a,0xb3,0x37,0xd9,0x22,0x12,0xa7,0xe1,0x90,0x61, +0xcb,0xe4,0x93,0xbe,0xb0,0x4, 0x28,0x3, 0x12,0xa5,0xf5,0x7e,0xb3,0x3, 0xa6,0x70, +0xe, 0x7e,0xb3,0x39,0xfb,0xb4,0x1, 0x7, 0xe4,0x12,0xa6,0xc9,0x12,0xa7,0x57,0x12, +0x5d,0xc9,0x12,0xa9,0x2b,0x7e,0xa3,0x3, 0xa6,0x7a,0xa3,0x39,0xfb,0xbe,0xb0,0xff, +0x68,0x3, 0x2, 0xa6,0xc9,0x22,0x90,0x61,0xcb,0xe4,0x93,0x7c,0xdb,0x22,0x9, 0x75, +0x26,0x33,0x7a,0x73,0x2b,0xf, 0x22,0xe4,0x7a,0xb3,0x37,0xdc,0x7a,0xb3,0x37,0xe4, +0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab,0x68,0x6, 0x7a,0xb3,0x2b,0x62,0xd2,0xe, 0x30, +0xe, 0x7, 0x12,0x4f,0xfb,0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x37,0xed,0x7e,0x34, +0x0, 0x60,0xe4,0x12,0x20,0xe8,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac, +0x7a,0x59,0x43,0x37,0xef,0x59,0x43,0x37,0xf7,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8, +0x7e,0x8, 0x37,0xdb,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe8,0xca,0xf8,0x7c,0xfb, +0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x2f,0xaa,0x6d,0x22,0x7e,0x8, +0x34,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0xac,0x7f,0x2e, +0x34,0x30,0x8a,0x6d,0x22,0x7e,0x8, 0x32,0xba,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8, +0x22,0x7e,0x37,0x33,0xd9,0x12,0x25,0x12,0x7a,0x37,0x38,0x50,0x6c,0xaa,0x80,0x23, +0x12,0x5f,0xcb,0x28,0x26,0xa, 0x4a,0x9, 0x64,0x37,0xe9,0xbc,0x6b,0x50,0x12,0x7e, +0x50,0x2, 0xac,0x5a,0x49,0x42,0x33,0xd3,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x37, +0xf3,0xb, 0xa0,0x7e,0xb3,0x37,0xe6,0xbc,0xba,0x38,0xd5,0x22,0x7d,0x23,0x7e,0x14, +0x61,0xce,0x12,0x5b,0x79,0x7e,0x14,0x0, 0x5, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50, +0xd, 0x7e,0x33,0x38,0x4f,0xbe,0x30,0x8, 0x50,0x45,0x74,0x8, 0x80,0x3d,0x7d,0x13, +0x3e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x38,0x4f,0xbe,0x30,0x6, 0x50,0x30,0x74, +0x6, 0x80,0x28,0x7e,0x14,0x0, 0x3, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e, +0x33,0x38,0x4f,0xbe,0x30,0x4, 0x50,0x17,0x74,0x4, 0x80,0xf, 0xbd,0x32,0x50,0xf, +0x7e,0x73,0x38,0x4f,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a,0xb3,0x38,0x4f,0x7e, +0xb3,0x38,0x4f,0xbe,0xb0,0x0, 0x28,0x1b,0x14,0x7a,0xb3,0x38,0x4f,0x74,0x1, 0x7a, +0xb3,0x16,0x92,0x90,0x62,0x3, 0xe4,0x93,0xbe,0xb3,0x38,0x4f,0x50,0x5, 0xe4,0x7a, +0xb3,0x16,0x91,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a,0x12,0xa9, +0x1d,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0xab,0xac,0x7d,0x23,0x7e,0x70,0xc, +0xac,0x72,0x59,0x23,0x37,0xf5,0x49,0x3, 0x37,0xf5,0x49,0x23,0x37,0xf1,0xbd,0x20, +0x50,0x4, 0x59,0x3, 0x37,0xf1,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa,0x6c,0x22, +0x80,0x18,0x12,0xa9,0x1d,0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, 0x37,0xf1, +0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4,0x7e,0x37, +0x37,0xd7,0xbe,0x37,0x38,0x50,0x50,0x8, 0x7e,0x37,0x38,0x50,0x7a,0x37,0x37,0xd7, +0x12,0xaa,0x53,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e,0x10,0x5, +0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, 0x22,0xca,0xd8,0xca,0x79,0x7e, +0xe0,0xff,0x12,0xac,0x40,0x7e,0xb3,0x37,0xde,0xb4,0x1, 0x8, 0x12,0x87,0x53,0xe4, +0x7a,0xb3,0x37,0xde,0x7e,0xb3,0x37,0xdd,0x60,0x4, 0x74,0xff,0x41,0x4e,0x7e,0xb3, +0x37,0xdc,0xb4,0x2, 0x2, 0x80,0x2, 0x41,0x42,0x12,0x5f,0xeb,0x38,0xc, 0x12,0x5f, +0xe3,0x38,0x7, 0x12,0x5f,0xdb,0x38,0x2, 0x41,0x42,0x12,0xa7,0x46,0xa, 0x3d,0x1b, +0x34,0xbe,0x34,0x0, 0x3, 0x48,0x4, 0x74,0x3, 0x80,0x3, 0x7c,0xbd,0x14,0x12,0xa8, +0xa4,0x7c,0xfb,0x7e,0xb3,0x37,0xdb,0x4, 0x7a,0xb3,0x37,0xdb,0x90,0x61,0xcb,0xe4, +0x93,0x14,0x12,0xa8,0xa4,0x7c,0xab,0xbe,0xa0,0xff,0x68,0x2c,0xbe,0xf0,0xff,0x68, +0x25,0x7e,0x30,0xc, 0xac,0x3f,0x49,0x21,0x37,0xf1,0x7e,0xf4,0x61,0xd2,0x7e,0xe4, +0x0, 0xff,0xb, 0x7a,0x30,0xbd,0x23,0x28,0xf, 0x12,0xaa,0x53,0x3e,0x34,0xbd,0x23, +0x28,0x6, 0x7c,0xfa,0x80,0x2, 0x7c,0xfa,0xbe,0xf0,0xff,0x78,0x11,0xe4,0x7a,0xb3, +0x37,0xdb,0x7a,0xb3,0x37,0xdc,0x7a,0xb3,0x37,0xe8,0x74,0xff,0x80,0x70,0x90,0x61, +0xda,0xe4,0x93,0xbe,0xb3,0x37,0xdb,0x50,0x59,0x74,0xc, 0xac,0xbf,0x49,0x25,0x37, +0xf1,0x7e,0x14,0x61,0xd2,0x12,0x5b,0x79,0xbd,0x23,0x50,0x3d,0x7e,0x34,0x61,0xd6, +0x12,0x23,0x74,0xbe,0x37,0x37,0xd7,0x40,0xd, 0x7e,0x34,0x61,0xd8,0x12,0x23,0x74, +0xbe,0x37,0x37,0xe2,0x50,0x23,0x74,0x5, 0xac,0xbf,0x9, 0x75,0x26,0x33,0xbe,0x73, +0x2b,0xf, 0x68,0x15,0x7c,0xef,0xbe,0xe0,0x4, 0x50,0x8, 0x12,0xaa,0x5d,0xbe,0xb0, +0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xde,0xe4,0x7a,0xb3,0x37,0xe8,0x7a,0xb3, +0x37,0xdc,0xbe,0xe0,0xff,0x68,0x5, 0xe4,0x7a,0xb3,0x37,0xdb,0x7c,0xbe,0xda,0x79, +0xda,0xd8,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x37,0xf1,0x22,0x7e,0xb3,0x2b, +0xf, 0x7c,0xab,0x6c,0x77,0x7e,0x50,0x5, 0xac,0x57,0x9, 0x62,0x26,0x33,0xbc,0x6a, +0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0x7c, +0x2b,0x7e,0xb3,0x1f,0x33,0xbc,0x2b,0x68,0x4f,0x12,0xaa,0x61,0x7c,0x3b,0x7c,0xb2, +0x12,0xaa,0x61,0x7c,0xab,0xbe,0x30,0xff,0x68,0x3e,0xbe,0xa0,0xff,0x68,0x39,0x7e, +0x70,0x4, 0xac,0x73,0xa, 0x2a,0x12,0x6f,0xe8,0xbe,0xb0,0x2, 0x38,0x2a,0xa, 0x2b, +0x7e,0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30,0x19,0x3, 0x2, +0xaa,0xe8,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0xf, 0x12,0x7c,0xbb,0x7a,0x55,0x29,0x7e, +0x8, 0xd, 0xc8,0x74,0x1, 0x2, 0xab,0x19,0x22,0x7c,0xab,0x12,0xab,0x62,0xd2,0x19, +0x7c,0xba,0x12,0xaa,0x7f,0xc2,0x19,0x22,0x7c,0x7b,0x90,0x60,0x93,0xe4,0x93,0xa, +0x1b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2d,0x1, 0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xad, +0x10,0x7d,0x21,0x12,0xab,0xa3,0xa, 0x26,0x7a,0x25,0x29,0x74,0x1d,0xac,0x7b,0x2e, +0x34,0x38,0x58,0x6d,0x22,0xe4,0x2, 0xab,0x19,0x7c,0xab,0x6d,0x44,0x80,0x29,0x4c, +0xaa,0x68,0x11,0x12,0xab,0x50,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x77,0xad, +0x2d,0xfe,0x80,0xf, 0x12,0xab,0x50,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x77, +0xad,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e,0xf5,0x29,0xbd,0xf4,0x38,0xd0,0x22, +0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b, +0xb0,0x22,0xa9,0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x12,0xab,0x62,0x7e,0x34,0xd, +0xc8,0x7e,0xb3,0x2a,0x6d,0x12,0xac,0x15,0x12,0xab,0x86,0x7a,0x37,0x33,0xdd,0x74, +0x1, 0x7a,0xb3,0x16,0x91,0x22,0x6d,0x33,0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0,0x0, +0x28,0x3, 0x2, 0xad,0x8, 0x90,0x60,0x92,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, +0xac,0x6f,0x22,0x3e,0x24,0x7e,0xf, 0x33,0xe0,0x2d,0x12,0x22,0x49,0x23,0x37,0xf7, +0x49,0x33,0x37,0xf3,0x9d,0x32,0x2, 0x21,0x1a,0x6c,0xaa,0x80,0x44,0x7e,0x70,0xc, +0xac,0x7a,0x12,0xab,0xac,0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0xac,0x7, 0x80,0x2f, +0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0xf7,0x49,0x12,0x37,0xf3,0xbd,0x13,0x28, +0xf, 0x7d,0x2, 0x2e,0x4, 0x37,0xf7,0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, +0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24,0x37,0xf7,0x1b,0x35,0x1b,0x28,0x30,0xb, +0xa0,0x12,0x5f,0xcb,0x38,0xb7,0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0xf3, +0x59,0x32,0x37,0xf7,0x22,0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e,0x7a,0x53,0x24, +0xf3,0x7a,0x37,0x24,0xfa,0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24,0xf5,0x7e,0x34, +0x40,0x0, 0x7a,0x37,0x24,0xf6,0x7e,0x34,0x0, 0x20,0x12,0x87,0xd1,0x2, 0xd, 0x7, +0x7e,0xb3,0x37,0xdd,0xb4,0x1, 0x27,0x7e,0xb3,0x38,0x53,0x4, 0x7a,0xb3,0x38,0x53, +0x7e,0x73,0x38,0x53,0xbe,0x70,0x3, 0x40,0x15,0x12,0x87,0x70,0x7e,0x73,0x38,0x53, +0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3,0x38,0x53,0x7a,0xb3,0x37,0xdd,0x22,0xca, +0xf8,0x6d,0xee,0x7d,0xfe,0x7e,0x83,0x2a,0x6e,0xa, 0xd8,0x90,0x60,0x94,0xe4,0x93, +0xb4,0xff,0x2f,0x7e,0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x18,0x7e,0x70,0x2, 0xac,0x7a, +0x49,0x23,0x13,0xfe,0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0,0x9d,0xc2,0x59,0xc3,0x13, +0xc6,0xb, 0xa0,0xbc,0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4,0x93,0x7c,0x9b,0x6d,0xdd, +0x80,0x11,0x7e,0x8, 0x13,0xfe,0x90,0x60,0x92,0xe4,0x93,0xa, 0xcb,0x1b,0xc4,0x7d, +0x3c,0x7c,0x97,0x6c,0xff,0x80,0x38,0x6c,0xaa,0x80,0x28,0xa, 0x3a,0x7d,0x23,0x2d, +0x2e,0x3e,0x24,0x49,0xc2,0x13,0xfe,0x2d,0x3d,0x3e,0x34,0x2d,0x31,0x7d,0x20,0xb, +0x1a,0xb0,0x7d,0x3c,0x9d,0x3b,0x12,0x21,0x1a,0x7d,0xa3,0xbd,0xfa,0x58,0x2, 0x7d, +0xfa,0xb, 0xa0,0xbc,0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec,0x2d,0xdc,0xb, 0xf0,0xbc, +0x9f,0x38,0xc4,0x7d,0x3f,0xda,0xf8,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x2a,0x6e, +0x90,0x60,0x93,0xe4,0x93,0xa, 0xfb,0x7e,0xb3,0x2a,0x6d,0xa, 0xeb,0x2d,0xef,0xa, +0xff,0xad,0xfe,0xa, 0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e, +0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x33, +0xe0,0x2d,0x3d,0xb, 0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, +0x5a,0x30,0x9d,0x3d,0x59,0x32,0x13,0xc6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, +0x7d,0x5e,0x3e,0x54,0x7e,0xf, 0x33,0xe0,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea, +0x2d,0xef,0x3e,0xe4,0x7e,0x1f,0x33,0xe0,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, +0xac,0x7a,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x21,0x1a, +0x7d,0xc3,0xbd,0x4c,0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34, +0xda,0xf8,0x22,0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c,0x22,0x80, +0x37,0x7e,0xb3,0x2a,0x6e,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e,0x44,0x7e, +0x7f,0x13,0x8a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, 0xbe,0x44, +0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44,0xfd,0xa8, +0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x2a,0x6e,0xbc,0x92,0x38,0xc1, +0xb, 0x31,0x7e,0xb3,0x2a,0x6d,0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, 0xad,0x53, +0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12,0x25,0x14,0xbd,0x12,0x50,0x22,0xbd, +0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x33,0xfb,0x7e,0xb3,0x33,0xfc,0xbe,0xb0,0x5, 0x50, +0x7, 0x4, 0x7a,0xb3,0x33,0xfc,0x80,0x3c,0xe4,0x7a,0xb3,0x33,0xfc,0x74,0x1, 0x80, +0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x33,0xfc,0x7e,0xb3, +0x33,0xfb,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x33,0xfb,0x80,0x16,0xe4,0x7a, +0xb3,0x33,0xfb,0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x33,0xfb,0x7a,0xb3,0x33,0xfc, +0x7a,0xb3,0x33,0xfd,0x7e,0xb3,0x33,0xfd,0x22,0x7e,0xa3,0x2f,0xa9,0xbe,0xa0,0xff, +0x68,0x4c,0xbe,0xa3,0x33,0x46,0x68,0x46,0x74,0x5, 0xa4,0x12,0xa7,0x4e,0x12,0xae, +0xbf,0x12,0x7f,0xf1,0x12,0xae,0xbf,0x12,0x7f,0xe8,0x12,0xae,0xc7,0x50,0x9, 0x7e, +0xb3,0x2f,0xa9,0x12,0xa7,0xac,0x80,0x6, 0x12,0xae,0xbf,0x12,0x7f,0xdf,0x12,0x57, +0xef,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0x7e,0x73,0x2b,0x14,0xa, 0x37,0x7e,0xf, +0x33,0xcf,0x79,0x30,0x0, 0x1a,0x7e,0x73,0x2f,0xa9,0x7a,0x73,0x33,0x46,0x22,0x7e, +0xa3,0x2f,0xa9,0x74,0x5, 0xa4,0x22,0x7e,0xb3,0x3, 0xc2,0xb4,0x3, 0x8, 0x7e,0xb3, +0x38,0xc6,0x70,0x2, 0xc3,0x22,0xd3,0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e, +0xb3,0x2a,0x6e,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51, +0x7e,0x13,0x2a,0x6e,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x2a,0x6d,0xa, 0x10,0xa, 0x21, +0x2d,0x12,0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23, +0x32,0xba,0x80,0x2d,0x7e,0x3, 0x2a,0x6d,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42, +0xa, 0x3a,0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58, +0xe, 0x9d,0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x32,0xbc,0x80,0x2, 0xe4, +0x22,0x7e,0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e, +0x60,0x80,0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0xae, +0xd8,0xa, 0x1b,0x7e,0x63,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac, +0x1f,0x2d,0x3, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x12,0xaf,0x97,0x9d,0x35,0x1b,0x1a, +0x10,0xb, 0xf0,0x12,0xaf,0x97,0x7e,0x73,0x2a,0x6e,0xa, 0x27,0x2d,0x25,0xa, 0x3f, +0xbd,0x32,0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x2a,0x6d,0x74,0x2, 0xa4,0x22,0xca, +0x3b,0x7c,0xcb,0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x43,0x7e, +0xb3,0x2a,0x70,0xf5,0x44,0x75,0x45,0x28,0x7e,0xb3,0x28,0x84,0xf5,0x2b,0xe4,0x7a, +0xb3,0x2, 0x89,0x7a,0xb3,0x2, 0x85,0x7a,0xb3,0x2, 0x86,0x7e,0x8, 0x2, 0x8a,0x12, +0xcc,0x7b,0xe4,0x12,0x20,0xe8,0x12,0xcc,0x7b,0x3e,0x34,0x7e,0x8, 0x2, 0xaa,0xe4, +0x12,0x20,0xe8,0xe5,0x2b,0xbe,0xb0,0x2, 0x50,0x3, 0x2, 0xb6,0xf4,0x75,0x2c,0x0, +0x2, 0xb6,0xea,0x7e,0x71,0x2c,0x12,0x9b,0xd9,0xf5,0x24,0x9, 0xb3,0x26,0xfb,0xf5, +0x25,0xe5,0x2c,0x60,0xa, 0xe5,0x2c,0xa, 0x3b,0x9, 0xb3,0x2, 0x8a,0x70,0x10,0xe5, +0x2c,0xa, 0x5b,0xb, 0x54,0x7c,0xab,0xe5,0x2c,0xa, 0x3b,0x19,0xa3,0x2, 0x8a,0xe5, +0x2b,0x14,0xbe,0xb1,0x2c,0x78,0x2, 0xc1,0xf4,0xe5,0x2c,0xa, 0x5b,0xb, 0x54,0xf5, +0x2d,0xc1,0xdf,0x7e,0x71,0x2d,0x12,0xcc,0x27,0x7a,0xa1,0x26,0x9, 0xb3,0x26,0xfb, +0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0xb7,0xb0,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5, +0x25,0x12,0xb7,0xb0,0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, 0xc1,0xdd,0xe5, +0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xc1,0xdd,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26, +0x7e,0x51,0x27,0x12,0x2f,0x85,0x7a,0xb3,0x2, 0x88,0x85,0x25,0x5b,0x85,0x26,0x5c, +0x85,0x27,0x5d,0x7e,0x8, 0x0, 0x33,0x7e,0x18,0x0, 0x35,0xe5,0x24,0x12,0xba,0xbc, +0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x75,0x32,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x30, +0xb6,0x7a,0x35,0x37,0xe5,0x26,0x12,0xb7,0x5a,0x7a,0x35,0x39,0x7e,0x35,0x37,0xbe, +0x35,0x39,0x8, 0x7, 0x7e,0x35,0x39,0x7d,0x83,0x80,0x3, 0x7e,0x85,0x37,0x7a,0x85, +0x3b,0xe, 0x84,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x21,0xe5,0x29,0xbe,0xb0,0x1, 0x38, +0x1a,0x7c,0xbc,0x30,0xe1,0x15,0x12,0x30,0xb1,0x7d,0x43,0x12,0xb7,0x58,0x2d,0x34, +0xbd,0x38,0x18,0x2, 0x81,0x98,0x75,0x32,0x1, 0x81,0x98,0xe5,0x28,0xbe,0xb0,0x1, +0x38,0x9, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x2, 0x81,0x98,0xe5,0x28,0xbe,0xb0,0x5, +0x40,0x2, 0x81,0x98,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0x81,0x98,0x7c,0xbc,0x20, +0xe0,0x2, 0x81,0x98,0x6d,0x33,0x7d,0x93,0x75,0x52,0x0, 0x7a,0x35,0x53,0x75,0x55, +0x0, 0xc2,0x4, 0xc2,0x5, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x6, 0xe5,0x24,0x7c,0xeb, +0x80,0x3, 0x7e,0xe1,0x26,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, +0xe5,0x26,0xf5,0x2a,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x6, 0xe5,0x25,0x7c,0xfb,0x80, +0x3, 0x7e,0xf1,0x27,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x6, 0xe5,0x25,0x7c,0xdb,0x80, +0x3, 0x7e,0xd1,0x27,0xe5,0x43,0xa, 0xb, 0x1b,0x4, 0xe5,0x2a,0xa, 0x1b,0xbd,0x10, +0xe5,0x2a,0x58,0x6, 0xa, 0x5b,0xb, 0x54,0x80,0x0, 0xf5,0x4e,0xbe,0xe0,0x0, 0x28, +0x6, 0xa, 0x5e,0x1b,0x54,0x80,0x2, 0x7c,0xbe,0xf5,0x4f,0xe5,0x44,0x12,0xcc,0x44, +0x58,0x6, 0xa, 0x5d,0xb, 0x54,0x80,0x2, 0x7c,0xbd,0xf5,0x50,0xbe,0xf0,0x0, 0x28, +0x6, 0xa, 0x5f,0x1b,0x54,0x80,0x2, 0x7c,0xbf,0xf5,0x51,0xe5,0x2a,0xbc,0xbe,0x78, +0x1c,0xd2,0x4, 0x4c,0xee,0x68,0x7, 0xe5,0x43,0x14,0xbc,0xbe,0x78,0x2, 0xd2,0x5, +0xbe,0xe0,0x0, 0x28,0x2, 0x1b,0xe0,0xbd,0x10,0x58,0x2, 0x5, 0x2a,0xbc,0xdf,0x78, +0x1c,0xd2,0x4, 0x4c,0xff,0x68,0x7, 0xe5,0x44,0x14,0xbc,0xbf,0x78,0x2, 0xd2,0x5, +0xbe,0xf0,0x0, 0x28,0x2, 0x1b,0xf0,0xbd,0x32,0x58,0x2, 0xb, 0xd0,0x75,0x30,0x0, +0x75,0x31,0x0, 0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f,0xa, 0x2b,0x9, 0x72,0x26,0x5b, +0xbe,0x71,0x4e,0x38,0x7, 0xbe,0x71,0x4f,0x40,0x2, 0x5, 0x30,0x5, 0x2f,0x7e,0x73, +0x26,0x84,0xbe,0x71,0x2f,0x38,0xe1,0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f,0xa, 0x2b, +0x9, 0x72,0x26,0x6f,0xbe,0x71,0x50,0x38,0x7, 0xbe,0x71,0x51,0x40,0x2, 0x5, 0x31, +0x5, 0x2f,0x7e,0x73,0x26,0x85,0xbe,0x71,0x2f,0x38,0xe1,0x7a,0xe1,0x3f,0x80,0x4f, +0x7a,0xf1,0x40,0x80,0x43,0xe5,0x3f,0x7e,0x71,0x40,0x12,0x30,0xb6,0x7a,0x35,0x41, +0xbe,0xe1,0x3f,0x68,0x11,0xe5,0x2a,0xbe,0xb1,0x3f,0x68,0xa, 0xbe,0xf1,0x40,0x68, +0x5, 0xbe,0xd1,0x40,0x78,0x9, 0x7e,0x35,0x41,0x2d,0x93,0x5, 0x52,0x80,0x17,0x5, +0x55,0x7e,0x35,0x41,0x2e,0x35,0x53,0x7a,0x35,0x53,0x7e,0x35,0x35,0xbe,0x35,0x41, +0x58,0x2, 0x5, 0x3d,0x5, 0x3e,0x5, 0x40,0xbe,0xd1,0x40,0x50,0xb8,0x5, 0x3f,0xe5, +0x2a,0xbe,0xb1,0x3f,0x50,0xaa,0xe5,0x2a,0x12,0xb7,0x82,0x7c,0xbe,0x12,0xb7,0x7a, +0x12,0xb7,0x82,0xe5,0x2a,0x12,0xb7,0x7a,0x7e,0x85,0x39,0x2e,0x85,0x37,0x30,0x4, +0x9, 0x20,0x5, 0x6, 0x9d,0x98,0x15,0x52,0x15,0x52,0xe5,0x52,0xbe,0xb0,0x4, 0x28, +0x6, 0xe5,0x52,0x24,0xfc,0xf5,0x52,0xbe,0x94,0x0, 0x0, 0x58,0x2, 0x6d,0x99,0x75, +0x45,0x22,0xe5,0x43,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, 0xe5, +0x24,0x60,0x4, 0xe5,0x26,0x70,0xa, 0x12,0xb7,0x72,0x28,0x39,0x75,0x45,0x2c,0x80, +0x34,0x30,0x8, 0x31,0x7e,0xb3,0x33,0x49,0xb4,0x1, 0x2a,0x7e,0x73,0x33,0x4a,0xbe, +0x71,0x2a,0x38,0x21,0xbc,0x7e,0x40,0x1d,0x7e,0x73,0x33,0x4b,0xbc,0x7d,0x38,0x15, +0xbc,0x7f,0x40,0x11,0xe5,0x45,0xa, 0x3b,0x7e,0x24,0x0, 0x3, 0x12,0x1e,0xb9,0x7c, +0xb7,0x25,0x45,0xf5,0x45,0x7e,0x15,0x53,0x1a,0x2, 0x1a,0x0, 0x12,0xa2,0x93,0x2f, +0x10,0xe5,0x45,0xa, 0x1b,0x6d,0x0, 0x12,0x1e,0xeb,0x7f,0x71,0x7a,0x7d,0x46,0x7d, +0x18,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x33,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0xe5, +0x55,0xa, 0xdb,0x6d,0xcc,0xe5,0x52,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1e,0xeb, +0x7a,0x1d,0x4a,0xbf,0x71,0x8, 0x3, 0x75,0x32,0x2, 0x7e,0xa1,0x31,0xe5,0x30,0xa4, +0xbe,0x54,0x0, 0x1, 0x68,0x2, 0x81,0xf, 0x12,0xb7,0x72,0x38,0x2, 0x81,0xf, 0x12, +0xb7,0xba,0xbe,0x24,0x0, 0x5, 0x48,0x2, 0x81,0xf, 0xa, 0x5f,0xa, 0x2d,0x9d,0x25, +0xbe,0x24,0x0, 0x5, 0x58,0x79,0x12,0xb7,0xc5,0x48,0x17,0x12,0xb7,0x21,0xbd,0x23, +0x48,0x10,0x12,0xb6,0xf7,0x48,0xb, 0x74,0x2, 0xac,0xbd,0x12,0xb7,0x15,0x48,0x2, +0x80,0x5a,0xa, 0x2f,0xa, 0x3d,0x9d,0x32,0xbe,0x34,0x0, 0x2, 0x58,0x32,0x12,0x9a, +0x6b,0x7d,0x3, 0x3e,0x4, 0x12,0xb7,0x68,0x2d,0x10,0x12,0xb7,0x9c,0x12,0xb7,0x68, +0x7e,0x70,0x2, 0xac,0x7e,0x12,0xb7,0x4c,0xbd,0x23,0x48,0x14,0x12,0x9a,0x6b,0x7d, +0x3, 0x3e,0x4, 0x7e,0x23,0x2a,0x6e,0x12,0xb7,0x2c,0xbd,0x23,0x48,0x2, 0x80,0x1c, +0xa, 0x2e,0xe5,0x2a,0xa, 0x3b,0x9d,0x32,0xbe,0x34,0x0, 0x2, 0x58,0x11,0x12,0xb6, +0xf7,0x48,0xc, 0x74,0x2, 0xac,0xbd,0x12,0xb7,0x15,0x48,0x3, 0x75,0x32,0x2, 0x12, +0xb7,0x60,0x28,0x5a,0x12,0xb7,0xba,0xbe,0x24,0x0, 0x2, 0x48,0xf, 0x12,0xb7,0xc5, +0x58,0xa, 0x12,0xb7,0x21,0xbd,0x23,0x58,0x3, 0x75,0x32,0x0, 0xa, 0x2f,0xa, 0x3d, +0x7d,0x13,0x9d,0x12,0xbe,0x14,0x0, 0x2, 0x48,0x34,0x12,0x9a,0x71,0x7d,0x23,0x3e, +0x24,0x7e,0x7f,0x6, 0xf8,0x7f,0x7, 0x2d,0x12,0xb, 0xa, 0x10,0x74,0x2, 0xac,0xbf, +0x2d,0x5f,0x7d,0x4e,0xb, 0x2a,0x20,0xbd,0x12,0x58,0x13,0x7d,0x13,0x3e,0x14,0x12, +0xb7,0x9c,0x74,0x2, 0xac,0xbd,0x12,0xb7,0x15,0x58,0x3, 0x75,0x32,0x0, 0x7e,0x73, +0x2, 0x88,0xbe,0x70,0x2, 0x50,0x21,0x12,0xb7,0x58,0xbe,0x34,0x0, 0x0, 0x58,0x18, +0x12,0x30,0xb1,0xbe,0x34,0x0, 0x0, 0x58,0xf, 0x12,0xb7,0x60,0x28,0xa, 0xe5,0x32, +0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x4c,0xcc,0x78,0x2, 0xc1,0x7a,0x7e,0xb3, +0x26,0x84,0xb4,0x2, 0x2, 0x80,0x2, 0xa1,0x5f,0x7e,0xb3,0x26,0x85,0xb4,0x1, 0x2, +0x80,0x2, 0xa1,0x5f,0x7e,0x73,0x2a,0x70,0xa, 0x27,0x1b,0x24,0x7e,0x73,0x26,0x6f, +0xa, 0x37,0xbd,0x32,0x48,0x2, 0xa1,0x5f,0x7e,0x73,0x26,0x5c,0xa, 0x27,0x7e,0x73, +0x26,0x5b,0x12,0xb7,0x93,0xf5,0x56,0x12,0xb7,0xa6,0x58,0x58,0x85,0x56,0x59,0x7e, +0x83,0x2a,0x6e,0x7e,0x90,0x2, 0xac,0x89,0x7e,0xa1,0x59,0x74,0x2, 0xa4,0x2d,0x54, +0x7e,0x7f,0x6, 0xf8,0x7f,0x17,0x2d,0x35,0x7f,0x1, 0x1b,0x15,0xb, 0xa, 0x0, 0x7e, +0x31,0x56,0x74,0x2, 0xac,0x3b,0x2d,0x14,0x7f,0x27,0x2d,0x51,0xb, 0x2a,0x10,0xbd, +0x10,0x8, 0x8, 0xe5,0x59,0xa, 0x5b,0x1b,0x54,0xf5,0x56,0x69,0x21,0x0, 0x2, 0x12, +0xb7,0x68,0x7e,0x71,0x56,0x12,0xb7,0x48,0xbd,0x32,0x8, 0x8, 0xe5,0x59,0xa, 0x5b, +0xb, 0x54,0xf5,0x56,0xe5,0x2a,0xbe,0xb1,0x56,0x28,0x5, 0xbe,0xe1,0x56,0x28,0x9, +0xe5,0x32,0x70,0x1b,0x75,0x32,0x2, 0x80,0x16,0xbe,0xe1,0x56,0x38,0x11,0xe5,0x2a, +0xbe,0xb1,0x56,0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e, +0xb3,0x26,0x84,0xb4,0x1, 0x2, 0x80,0x2, 0xa1,0xfc,0x7e,0xb3,0x26,0x85,0xb4,0x2, +0x2, 0x80,0x2, 0xa1,0xfc,0x7e,0x73,0x26,0x70,0xa, 0x27,0x7e,0x73,0x26,0x6f,0x12, +0xb7,0x93,0xf5,0x57,0x12,0xb7,0xa6,0x58,0x4c,0x85,0x57,0x5a,0x7e,0xa1,0x5a,0x74, +0x2, 0xa4,0x7e,0xf, 0x6, 0xf8,0x7f,0x10,0x2d,0x35,0x7f,0x21,0x1b,0x55,0xb, 0x2a, +0x40,0x7e,0xa1,0x57,0x74,0x2, 0xa4,0x7f,0x70,0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x54, +0x8, 0x8, 0xe5,0x5a,0xa, 0x5b,0x1b,0x54,0xf5,0x57,0x69,0x21,0x0, 0x2, 0x7e,0xa1, +0x57,0x74,0x2, 0xa4,0x2d,0x15,0xb, 0xa, 0x30,0xbd,0x32,0x8, 0x8, 0xe5,0x5a,0xa, +0x5b,0xb, 0x54,0xf5,0x57,0xbe,0xd1,0x57,0x28,0x5, 0xbe,0xf1,0x57,0x28,0x9, 0xe5, +0x32,0x70,0x19,0x75,0x32,0x2, 0x80,0x14,0xbe,0xf1,0x57,0x38,0xf, 0xbe,0xd1,0x57, +0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e,0x73,0x28,0x84, +0xa5,0xbf,0x2, 0x21,0x7e,0x63,0x2, 0x88,0xbe,0x60,0x2, 0x50,0x18,0x7e,0x63,0x2a, +0x3, 0xbe,0x60,0x1, 0x28,0xf, 0xbe,0x73,0x26,0x84,0x28,0x6, 0xbe,0x73,0x26,0x85, +0x38,0x3, 0x75,0x32,0x0, 0x7e,0xb3,0x26,0x83,0xb4,0x1, 0x4e,0x7e,0xb3,0x2, 0x88, +0x70,0x3e,0x12,0xb7,0x60,0x28,0x39,0x12,0xb7,0x58,0xbe,0x34,0xff,0x38,0x58,0xb, +0x12,0x30,0xb1,0xbe,0x34,0xff,0x38,0x58,0x2, 0x80,0x20,0x7e,0xb3,0x2a,0x3, 0xb4, +0x2, 0x28,0x7e,0x73,0x28,0x84,0xbe,0x70,0x5, 0x50,0x1f,0x7e,0x73,0x28,0x85,0xbe, +0x70,0x1, 0x50,0x16,0xe5,0x32,0xbe,0xb0,0x1, 0x28,0xf, 0x75,0x32,0x0, 0x80,0xa, +0x7e,0xb3,0x2a,0x3, 0xb4,0x1, 0x3, 0x75,0x32,0x2, 0xe5,0x32,0xbe,0xb0,0x0, 0x28, +0x5c,0xe5,0x32,0xa, 0x3b,0x2e,0x34,0x2, 0x84,0x7e,0x39,0xb0,0x4, 0x7a,0x39,0xb0, +0xe5,0x2d,0xa, 0x3b,0x9, 0xa3,0x2, 0x8a,0x4c,0xaa,0x78,0x9, 0x12,0xb7,0x8a,0x19, +0xb3,0x2, 0x8a,0x80,0x38,0x12,0xb7,0x8a,0xf5,0x58,0xbc,0xba,0x28,0x3, 0x7a,0xa1, +0x58,0x75,0x2e,0x0, 0x80,0x20,0x9, 0x13,0x2, 0x8a,0xe5,0x2e,0xa, 0x1b,0x9, 0x1, +0x2, 0x8a,0xbc,0x1, 0x68,0x8, 0x9, 0x12,0x2, 0x8a,0xbc,0x1, 0x78,0x6, 0xe5,0x58, +0x19,0xb1,0x2, 0x8a,0x5, 0x2e,0xe5,0x2b,0xbe,0xb1,0x2e,0x38,0xd9,0x5, 0x2d,0xe5, +0x2b,0xbe,0xb1,0x2d,0x28,0x2, 0x1, 0x33,0x5, 0x2c,0xe5,0x2b,0xbe,0xb1,0x2c,0x28, +0x3, 0x2, 0xaf,0xf3,0xda,0x3b,0x22,0xa, 0x2d,0xa, 0x3f,0x2d,0x32,0x7e,0x24,0x0, +0x2, 0x12,0x1e,0xb9,0x7d,0x13,0x3e,0x14,0x7e,0x1f,0x6, 0xf8,0x2d,0x31,0xb, 0x1a, +0x20,0x74,0x2, 0xac,0xbf,0x7e,0xf, 0x6, 0xf8,0x2d,0x15,0xb, 0xa, 0x30,0xbd,0x23, +0x22,0x7d,0x34,0x7d,0x20,0x12,0x1e,0xb9,0x7d,0x3, 0x3e,0x4, 0x7e,0x30,0x2, 0xac, +0x23,0x2d,0x10,0x7e,0x1f,0x6, 0xf8,0x2d,0x31,0xb, 0x1a,0x20,0x7e,0x23,0x2a,0x6e, +0x7e,0x30,0x2, 0xac,0x23,0x7e,0x71,0x2a,0x74,0x2, 0xac,0x7b,0x2d,0x31,0x7e,0xf, +0x6, 0xf8,0x2d,0x13,0xb, 0xa, 0x30,0x22,0xe5,0x24,0x7e,0x71,0x27,0x2, 0x30,0xb6, +0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x1, 0x22,0x7e,0x23,0x2a,0x6e,0x7e,0x30,0x2, 0xac, +0x23,0x22,0x7e,0x73,0x2, 0x88,0xbe,0x70,0x5, 0x22,0x7c,0x7d,0x12,0x30,0xb6,0x9d, +0x93,0x22,0x7c,0x7f,0x12,0x30,0xb6,0x9d,0x93,0x22,0xe5,0x2c,0xa, 0x2b,0x9, 0xb2, +0x2, 0x8a,0x22,0xa, 0x37,0x7d,0x53,0x2d,0x52,0xe, 0x54,0x22,0x7e,0x1f,0x6, 0xf8, +0x2d,0x31,0xb, 0x1a,0x20,0x22,0x9d,0x32,0x12,0x21,0x1a,0xbe,0x34,0x0, 0x6, 0x22, +0xa, 0x3b,0x9d,0x32,0x12,0x21,0x1a,0x7c,0xb7,0x22,0xa, 0x3e,0xe5,0x2a,0xa, 0x4b, +0x7d,0x24,0x9d,0x23,0x22,0x2d,0x43,0x7e,0x4, 0x0, 0x2, 0x7d,0x34,0x7d,0x20,0x12, +0x1e,0xb9,0x3e,0x34,0x7e,0x23,0x2a,0x6e,0x74,0x2, 0xac,0xb2,0x2d,0x35,0x7e,0x7f, +0x6, 0xf8,0x2d,0x3f,0x7d,0x2e,0xb, 0x1a,0x30,0x7e,0x50,0x2, 0xac,0x5e,0x2d,0x25, +0x2d,0xf2,0xb, 0x7a,0x50,0xbd,0x35,0x22,0x6c,0xaa,0x12,0xba,0x41,0x29,0x81,0x0, +0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x12,0xb8,0x3c,0x7c,0xb8,0x54,0xfd,0x4c, +0xb9,0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23, +0x54,0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, +0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xc2,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14, +0x0, 0x5, 0x22,0x6c,0xaa,0x12,0xba,0x41,0x12,0xb8,0x3c,0x7e,0xb, 0xb0,0x54,0xfe, +0x12,0xb8,0x39,0x7e,0xb, 0xb0,0x54,0x7, 0x12,0xb8,0x39,0x7e,0xb, 0xb0,0x54,0xfb, +0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xdb,0x22,0xca,0x79,0xc2,0x3, 0x7e, +0xf0,0x3, 0x7e,0xe3,0x2a,0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37,0x2, 0xa8,0x12,0xba, +0x25,0x38,0x2, 0x21,0x3f,0x12,0xb9,0x48,0x92,0xb, 0x12,0xb8,0x43,0x7c,0xbf,0x12, +0xaf,0x9f,0x4c,0xee,0x68,0xe, 0x7e,0xa3,0x2, 0x85,0x4c,0xaa,0x78,0xa, 0x7e,0xb3, +0x2, 0x86,0x70,0x4, 0xd2,0x3, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x61,0xbe, +0xb0,0x8, 0x28,0x4, 0xd2,0x3, 0x80,0x15,0xd2,0x3, 0x7e,0xb3,0x28,0x84,0xbc,0xbe, +0x78,0xb, 0x20,0xb, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x3, 0x20,0x3, 0x5, +0x7c,0xbf,0x12,0xaf,0x9f,0x7e,0x8, 0x2, 0x8a,0x12,0x32,0x10,0x7a,0xb3,0x2, 0x89, +0xbe,0xb3,0x28,0x84,0x50,0x38,0x7e,0x33,0x2, 0x89,0x80,0x24,0x7e,0x70,0x2, 0xac, +0x73,0x9, 0x23,0x2, 0xaa,0x9, 0x13,0x2, 0xab,0x2e,0x37,0x2, 0xa8,0xb, 0x38,0x50, +0x7e,0x93,0x2a,0x6e,0xac,0x92,0xa, 0x31,0x2d,0x43,0x12,0xba,0x4d,0x12,0x2e,0xd8, +0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xd4,0x74,0x1, 0x7a,0xb3,0x2, 0x87,0x7e,0xa3, +0x2, 0x89,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x2, 0xaa,0x7e, +0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0x12,0xb9,0xa4,0xf5,0x61,0x80,0x6, 0x75, +0x61,0x64,0x12,0xba,0x35,0xda,0x79,0x22,0xca,0x3b,0x7e,0xe3,0x28,0x84,0x6c,0xdd, +0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0xba,0x59,0x30,0xe0,0x3d,0x6c,0xcc,0x80,0x2d, +0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x7a,0xb3,0x1f,0x70,0x9, 0xa3,0x26, +0xfb,0x7a,0xa3,0x1f,0x71,0x7f,0x7, 0x12,0x2f,0x47,0x50,0xf, 0x7f,0x7, 0x7e,0xb3, +0x1f,0x71,0x6c,0x77,0x12,0x2f,0x4a,0x50,0x2, 0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38, +0xcf,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb0, +0xc3,0xda,0x3b,0x22,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4e,0xa, 0x31, +0xb, 0x34,0x7c,0x7, 0x80,0x3c,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26,0xfa,0x12, +0xba,0x1d,0x9, 0xb3,0x26,0xfa,0xa, 0x3b,0x12,0xba,0x2d,0x7e,0x70,0x2, 0xac,0x70, +0x9, 0xb3,0x26,0xfb,0x12,0xba,0x1d,0x9, 0xb3,0x26,0xfb,0xa, 0x3b,0x9d,0x32,0x12, +0x21,0x1a,0x7c,0x87,0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28, +0xb, 0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xb0,0x38,0xbc,0xb, 0x10,0x7e,0xb3,0x28,0x84, +0xbc,0xb1,0x38,0xaa,0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22, +0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b,0x7e, +0x70,0x2, 0xac,0x71,0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x1, 0x22,0x9d,0x32,0x12, +0x21,0x1a,0x7c,0x97,0x22,0x7e,0x8, 0x2, 0xe6,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x20, +0xe8,0x7e,0x70,0x6, 0xac,0x7a,0x2e,0x34,0x2, 0xe6,0x6d,0x22,0x22,0x3e,0x44,0x7e, +0x1f,0x13,0x8a,0x2d,0x34,0x1b,0x1a,0x50,0x22,0x7d,0xf5,0x2e,0xf4,0x2, 0xe6,0x6d, +0xee,0x29,0xb7,0x0, 0x5, 0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4,0x6c,0x11,0x80, +0x42,0xbc,0xa1,0x68,0x3c,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x26,0xfb,0xa, 0x20,0xa, +0x33,0x9d,0x32,0x12,0x21,0x1a,0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, 0x74,0x26,0xfa, +0xa, 0x27,0xa, 0x32,0x12,0xba,0x2d,0xbe,0x90,0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18, +0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, 0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, +0x22,0xb, 0x10,0x7e,0x83,0x28,0x84,0xbc,0x81,0x18,0xb6,0x22,0x7c,0x9b,0x7f,0x71, +0x7f,0x60,0x7e,0x34,0x22,0xc9,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x70,0x74,0x2a, +0x12,0x1f,0xad,0x7e,0x58,0x1f,0x70,0x7c,0xb9,0x7e,0x71,0x5b,0x12,0x30,0xb6,0x7d, +0x43,0xe5,0x5c,0x7e,0x71,0x5d,0x12,0x30,0xb6,0x2d,0x34,0xe, 0x34,0x7f,0x5, 0x7e, +0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b,0x6a,0x30, +0x69,0x30,0x0, 0x4, 0x1b,0x7a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78, +0xe1,0x12,0xb7,0x72,0x28,0x2b,0xb, 0x6a,0x20,0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e, +0x24,0x0, 0x10,0x12,0x1e,0xb9,0x1b,0x6a,0x30,0xb, 0x7a,0x30,0x1a,0x26,0x1a,0x24, +0x7e,0x14,0x0, 0xd, 0x12,0x1e,0xfc,0x7e,0x8, 0x0, 0x10,0x12,0x1f,0x58,0x1b,0x7a, +0x30,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x70,0x2, 0x12,0xbe,0xfc,0x7f,0x71,0x7c,0xbf, +0x12,0x30,0xa4,0x12,0xbb,0x60,0x7f,0x17,0x12,0x1f,0x58,0x7c,0xb7,0xda,0xf8,0x22, +0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x22,0xca,0x3b,0x7c,0xfb,0x7f,0x61,0x7f,0x40,0x9f, +0x11,0x7f,0x51,0x7f,0x71,0x7a,0x1d,0x3c,0x7a,0x1d,0x40,0x7a,0x1d,0x44,0xbe,0xf0, +0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80,0x4, 0x7e,0x54,0x2, 0x35,0x7a,0x57,0x23, +0x43,0x6c,0xee,0x80,0x60,0xa, 0x5e,0x7f,0x14,0x12,0xbc,0xb8,0x7a,0x55,0x4a,0xa, +0x5e,0x7f,0x16,0x12,0xbc,0xb8,0x7a,0x55,0x48,0x7e,0x35,0x48,0x12,0xbb,0x60,0x2f, +0x50,0x7e,0x65,0x4a,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x2f,0x70,0x12,0xbb,0x60,0x12, +0xbc,0xae,0x7e,0x1d,0x3c,0x2f,0x10,0x7a,0x1d,0x3c,0x7d,0x16,0x1a,0x2, 0x1a,0x0, +0x7e,0x35,0x4a,0x12,0xbc,0xae,0x7e,0x1d,0x40,0x2f,0x10,0x7a,0x1d,0x40,0x7e,0x15, +0x4a,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x48,0x12,0xbc,0xae,0x7e,0x1d,0x44,0x2f,0x10, +0x7a,0x1d,0x44,0xb, 0xe0,0xbc,0xfe,0x38,0x9c,0xa, 0xdf,0x6d,0xcc,0x7f,0x15,0x7f, +0x6, 0x12,0x1f,0x58,0x7f,0x51,0x7f,0x17,0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x71,0x7e, +0x94,0x0, 0x64,0x7e,0x1d,0x3c,0x7d,0x19,0x12,0x1e,0xfc,0x7e,0x87,0x23,0x43,0x7d, +0x18,0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f,0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x3c,0x7e, +0x1d,0x40,0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x40,0x7e, +0x1d,0x44,0x7d,0x19,0x12,0x1e,0xfc,0x7d,0x18,0x1a,0x2, 0x1a,0x0, 0x12,0x1f,0x58, +0x7a,0x1d,0x44,0x7f,0x15,0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x6d,0x44,0x9f,0x61,0x7f, +0x15,0x7f,0x5, 0x12,0x1e,0xeb,0x7e,0x5d,0x3c,0x9f,0x51,0x7f,0x17,0x7f,0x7, 0x12, +0x1e,0xeb,0x7e,0x7d,0x40,0x9f,0x71,0xbe,0x58,0x0, 0x0, 0x68,0x6, 0xbe,0x78,0x0, +0x0, 0x78,0x6, 0x7e,0x44,0x0, 0x64,0x80,0x18,0x7f,0x16,0x7d,0x19,0x12,0x1e,0xfc, +0x7f,0x5, 0x12,0x1f,0x58,0x7f,0x6, 0x12,0x1e,0xeb,0x7f,0x7, 0x12,0x1f,0x58,0x7d, +0x43,0xbe,0x44,0x0, 0x0, 0x18,0x2, 0x6d,0x44,0x7c,0xb9,0xda,0x3b,0x22,0x1a,0x26, +0x1a,0x24,0x12,0x1e,0xeb,0x7f,0x1, 0x22,0x2d,0x35,0x7e,0x1b,0x70,0xa, 0x57,0x22, +0xca,0x3b,0xf5,0x2a,0x7f,0x31,0x7a,0xd, 0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3, +0x22,0xf7,0x7a,0xb3,0x22,0xf8,0x7e,0x34,0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c, +0x7a,0xb3,0x22,0xf5,0x75,0x2f,0x46,0x75,0x2b,0x0, 0xc1,0xb1,0x12,0xbe,0xec,0x28, +0x1e,0x7e,0x34,0x0, 0x44,0xca,0x39,0x7e,0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34, +0x14,0x6, 0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x22,0xff,0x12,0x20,0xc3,0x1b,0xfd,0x6d, +0x33,0x7a,0x37,0x22,0xf9,0x7a,0x35,0x30,0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a, +0x35,0x34,0x7e,0x34,0x22,0xff,0x7a,0x35,0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38, +0x75,0x2c,0x0, 0x80,0x59,0xe5,0x2c,0xa, 0x3b,0x7e,0xd, 0x26,0x12,0xbe,0xf4,0x2e, +0x35,0x36,0x12,0x2c,0x70,0x7d,0xd3,0x7e,0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a, +0xd7,0x22,0xfb,0xe5,0x2c,0xa, 0x3b,0x7f,0x3, 0x12,0xbe,0xf4,0x2e,0x35,0x38,0x12, +0x2c,0x70,0x7d,0xc3,0x7e,0x35,0x32,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37, +0x22,0xf9,0x2d,0x3d,0x7a,0x37,0x22,0xf9,0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30, +0x2d,0xcd,0x7e,0x35,0x34,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a, +0xbe,0xb1,0x2c,0x38,0xa0,0xe5,0x2a,0xb4,0xa, 0x2a,0x7e,0x37,0x22,0xfb,0xbe,0x34, +0x0, 0x40,0x48,0xb, 0x7e,0x25,0x32,0xbe,0x24,0x0, 0x40,0x48,0x2, 0xc1,0xaf,0xbe, +0x34,0x0, 0x60,0x8, 0x2, 0xc1,0xaf,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x2, +0xc1,0xaf,0x80,0x28,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x20,0x8, 0xb, 0x7e,0x25, +0x32,0xbe,0x24,0x0, 0x20,0x8, 0x2, 0xc1,0xaf,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xc1, +0xaf,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xc1,0xaf,0x7e,0xa3,0x39,0x55, +0x74,0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58,0x2, 0xc1,0xaf,0x7e,0xa3,0x39,0x56,0x74, +0xc, 0xa4,0xbe,0x55,0x30,0x58,0x2, 0xc1,0xaf,0x7e,0x15,0x36,0x6d,0x0, 0x7e,0x1d, +0x26,0xe5,0x2a,0x12,0xbb,0x67,0x7a,0xb3,0x22,0xf4,0x7e,0x15,0x38,0x6d,0x0, 0x7f, +0x13,0xe5,0x2a,0x12,0xbb,0x67,0xf5,0x2d,0x7e,0x73,0x22,0xf5,0xbe,0x73,0x22,0xf4, +0x38,0x7d,0xbe,0x71,0x2d,0x38,0x78,0xe5,0x2d,0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, +0x1a,0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d, +0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4,0xa, 0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1f, +0x7, 0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe,0xb1,0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb, +0x2e,0x35,0x32,0x2e,0x35,0x34,0x7a,0x35,0x3a,0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, +0x64,0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a,0x7a,0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe, +0x35,0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a,0x37,0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22, +0xf7,0x7e,0x73,0x23,0x41,0x7a,0x73,0x22,0xf8,0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, +0x2b,0x12,0xbe,0xec,0x28,0x2, 0x81,0xec,0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40, +0x20,0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, 0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e, +0x73,0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a,0x73,0x39,0x52,0x7a,0xb3,0x39,0x54,0x80, +0x6, 0x74,0x7c,0x7a,0xb3,0x39,0x52,0x7c,0xba,0xda,0x3b,0x22,0x7e,0x73,0x34,0x4f, +0xbe,0x71,0x2b,0x22,0x2d,0x13,0x7e,0xb, 0x50,0xa, 0x25,0x22,0xca,0x79,0x7c,0xa7, +0x7c,0x8b,0x7e,0xb3,0x2a,0x6f,0x7a,0xb3,0x1f,0x34,0x7e,0xb3,0x2a,0x70,0x7a,0xb3, +0x1f,0x35,0x7e,0x70,0x2, 0xac,0x78,0x9, 0x93,0x26,0xfa,0x9, 0x83,0x26,0xfb,0x9f, +0x77,0x1a,0x3a,0x1a,0x79,0x9d,0x73,0xe1,0xb4,0x7a,0xf1,0x2d,0xbe,0xf0,0x0, 0x58, +0xe, 0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x2d,0x7e, +0xb3,0x1f,0x34,0xbc,0xbf,0x18,0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d, +0x32,0x7c,0xb7,0xf5,0x2d,0x1a,0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x2c,0x80, +0x43,0x85,0x2c,0x2e,0xe5,0x2c,0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x2c,0x1a,0x3b,0x1a, +0x28,0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c,0xb7,0xf5,0x2e,0x7e,0xb3,0x1f,0x35,0xbe, +0xb1,0x2c,0x18,0x10,0x1a,0x38,0xe5,0x2c,0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32, +0x7c,0xb7,0xf5,0x2e,0xe5,0x2d,0x7e,0x71,0x2e,0x12,0x30,0xb6,0x1a,0x26,0x1a,0x24, +0x2f,0x71,0x5, 0x2c,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x2c,0x1a,0x3b,0xbd,0x32, +0x8, 0xaf,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18,0x2, +0xe1,0x29,0x7f,0x17,0xda,0x79,0x22,0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x2a,0x6e,0xac, +0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10,0x7e,0x1f,0x13,0x8a,0x2d,0x31, +0x22,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32, +0x13,0x8e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, +0xa0,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x38,0xdc,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b, +0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x5f, +0xfb,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda, +0x5b,0xda,0x6b,0xda,0x7b,0x32,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9, +0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x62,0x7e,0x73, +0x3, 0xfe,0xbe,0x71,0x62,0x38,0x2, 0xd2,0x1a,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9, +0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9, +0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5, +0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf, +0x22,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8,0x7e, +0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b, +0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79,0x30,0x0, 0x6, 0x79,0x20, +0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20, +0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20, +0x0, 0xc, 0x22,0xa9,0xd5,0xcb,0x74,0x10,0x12,0x4f,0x53,0x7c,0x7b,0x12,0x4f,0x5b, +0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x33,0xc7, +0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, 0x33,0xc7,0x79,0x20,0x0, 0x82, +0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x33,0xc7,0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c,0x77, +0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x33,0xc7,0x79,0x30,0x0, 0x86,0x7e,0x34,0x29,0x90, +0x7e,0xf, 0x33,0xc7,0x79,0x30,0x0, 0x8a,0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x33,0xc7, +0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, 0x33,0xc7,0x79,0x30,0x0, 0x8e, +0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb,0xa9, +0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2,0x9c, +0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, 0xd2, +0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8,0x0, +0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8,0xa9, +0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22,0xa9, +0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3, 0xfc,0xb, 0x34,0x7a,0x37,0x3, 0xfc, +0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3, 0xfc,0x22,0x6d, +0x22,0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a, +0xb, 0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22,0x7f,0x71,0x69,0x37,0x0, +0x2, 0x7d,0x53,0x12,0xc2,0x45,0xb, 0x7a,0x20,0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27, +0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35, +0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, 0x7d,0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e, +0x54,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69, +0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12,0x25,0x12,0x1e,0x34,0x1e,0x34,0x2d,0x32, +0x79,0x30,0x0, 0x6, 0x22,0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x22,0x7c,0xab,0x9f, +0x11,0x30,0x3, 0x22,0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b, +0xb0,0x7e,0x78,0x0, 0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e, +0xb, 0x90,0xbc,0xa9,0x38,0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c,0xfb, +0x7e,0x8, 0x1f,0x34,0x12,0xc3,0x3, 0x7e,0x8, 0x1f,0x3c,0x12,0xc3,0xb, 0xd2,0x3, +0x7e,0x8, 0x2a,0xdc,0x7c,0xbf,0x12,0xc2,0x4d,0x7e,0x8, 0x1f,0x34,0x7a,0xf, 0x1f, +0x58,0x7f,0x1, 0x7a,0x17,0x1f,0x5c,0x7d,0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18,0x1f, +0x3c,0x7a,0x1f,0x1f,0x64,0x6c,0x77,0x80,0xe, 0x12,0xc3,0x53,0x50,0x7, 0x12,0xc3, +0x4a,0x19,0x51,0x1f,0x3c,0xb, 0x70,0xbc,0xf7,0x38,0xee,0x12,0xc2,0xf0,0xe4,0x12, +0xc2,0xf8,0xe4,0x12,0xc, 0x9b,0x6d,0x33,0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f,0x5e, +0x12,0xc2,0xf0,0x74,0x1, 0x12,0xc2,0xf8,0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22, +0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, +0x1f,0x58,0x22,0x7e,0x34,0x0, 0x8, 0xe4,0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x1c,0x74, +0x3f,0x2, 0x20,0xe8,0x7e,0x8, 0x1f,0x34,0x12,0xc3,0xb, 0x6c,0x77,0x80,0xe, 0x12, +0xc3,0x53,0x50,0x7, 0x12,0xc3,0x4a,0x19,0x51,0x1f,0x34,0xb, 0x70,0x7e,0x53,0x2a, +0x6e,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x11,0x38, +0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x34,0x2, 0x11,0x38,0xa, 0x27,0x9, 0x52,0x2b,0x44, +0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x2a,0xdc,0xbe,0x60,0x1c,0x22,0x7c,0x7b,0xa5, +0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe, +0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0, +0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, +0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78, +0xfb,0x7c,0xb9,0x22,0x7e,0x27,0x28,0xa3,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64, +0x30,0x0, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, 0x0, +0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59, +0xf4,0x5, 0xf8,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, +0xf8,0x30,0x2, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, 0x4, +0x7e,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3, +0x59,0xf4,0x6, 0x76,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, +0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0xb, 0x7e,0xb3,0x2a,0x73,0xa, 0x4b, +0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33, +0x19,0xb3,0x27,0x72,0xb, 0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0xc5,0x67,0xb, 0x24, +0xa, 0x33,0xbd,0x32,0x48,0xe7,0xe4,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x28,0x85,0x6d, +0x33,0x7a,0x37,0x28,0x86,0x7a,0x37,0x28,0x88,0x7a,0x37,0x28,0x8a,0x7a,0x37,0x28, +0x8e,0x7e,0xd4,0x1f,0x36,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x13,0x8a,0x7a, +0x37,0x1f,0x76,0x7d,0x3d,0x7a,0x37,0x1f,0x7a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f, +0x78,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x1f,0x73,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x1f, +0x72,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x7c,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f, +0x7e,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x80,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1f, +0x74,0x7e,0x73,0x39,0xf7,0x7a,0x73,0x1f,0x75,0x7e,0x8, 0x1f,0x72,0x7e,0x18,0x1f, +0x82,0x12,0x8, 0x0, 0x7e,0x73,0x1f,0x82,0x7a,0x73,0x28,0x84,0x7e,0x73,0x1f,0x83, +0x7a,0x73,0x28,0x85,0x7e,0x37,0x1f,0x84,0x7a,0x37,0x28,0x86,0x7e,0x37,0x1f,0x86, +0x7a,0x37,0x28,0x88,0x7e,0x37,0x1f,0x8c,0x7a,0x37,0x28,0x8a,0x7e,0x37,0x1f,0x8e, +0x7d,0x23,0x7a,0x53,0x28,0x8c,0xa, 0x36,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x1f,0x88, +0x7a,0x37,0x28,0x8e,0x7e,0x37,0x1f,0x8a,0x7d,0x23,0x7a,0x53,0x28,0x90,0xa, 0x36, +0x7a,0x73,0x28,0x91,0x6c,0x33,0x80,0x1b,0x12,0x2e,0xd8,0x74,0x2, 0xac,0xb3,0x49, +0x45,0x15,0x9e,0xa, 0x38,0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29,0x19,0x25,0x26, +0xfb,0xb, 0x30,0x7e,0x23,0x28,0x84,0xbc,0x23,0x38,0xdd,0x6c,0x33,0x80,0x1b,0x74, +0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25, +0x27,0x36,0x7c,0x29,0x19,0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28,0x85,0xbc,0x23, +0x38,0xdd,0x22,0x7c,0xa5,0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x7e,0x8, +0x26,0x86,0x7e,0x34,0x0, 0x3, 0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x26,0x89,0x7e,0x34, +0x0, 0x3, 0x12,0x20,0xe8,0x7a,0xb3,0x26,0x83,0x7a,0xb3,0x26,0x84,0x7a,0xb3,0x26, +0x85,0x7a,0xb3,0x26,0xf0,0x7a,0xb3,0x26,0xf1,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26, +0x6f,0x12,0xc6,0xd1,0x6c,0x55,0x12,0xc6,0x34,0x7a,0xb3,0x26,0x85,0x7e,0x18,0x26, +0x5b,0x12,0xc6,0xe1,0x6c,0x55,0x12,0xc6,0x34,0x7a,0xb3,0x26,0x84,0x6c,0x77,0x80, +0x14,0x12,0xc6,0xbd,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12,0xc5,0x63,0x2e,0x24, +0x26,0x86,0x12,0xc6,0xc6,0x7e,0x63,0x26,0x84,0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80, +0x14,0x12,0xc6,0xbd,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12,0xc5,0x63,0x2e,0x24, +0x26,0x89,0x12,0xc6,0xc6,0x7e,0xa3,0x26,0x85,0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x26, +0x84,0xa4,0x7a,0xb3,0x26,0x83,0x7e,0x18,0x26,0xe6,0x12,0xc6,0xd1,0x7e,0x50,0x1, +0x12,0xc6,0x34,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0xdc,0x12,0xc6,0xe1,0x7e,0x50, +0x1, 0x12,0xc6,0x34,0x7c,0xab,0x7a,0xa3,0x26,0xf1,0x7e,0xb3,0x26,0xf2,0xa4,0x7a, +0xb3,0x26,0xf0,0x22,0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff, +0x80,0x70,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55, +0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, +0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78, +0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69, +0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff, +0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x19,0xbd,0xfe,0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24, +0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0x90,0x60,0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, +0xb, 0xf0,0xbc,0x4f,0x38,0x8c,0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0xb7,0x54, +0x7, 0x7e,0x24,0x0, 0x1, 0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70, +0x22,0x7a,0x1d,0x24,0x7e,0xf, 0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a,0x53, +0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0xf8,0x2d, +0x15,0x7e,0xb3,0x2a,0x6d,0x7e,0x37,0x2a,0x51,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54, +0x0, 0x20,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60, +0xf0,0xa5,0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e, +0x24,0x14,0x78,0xfb,0x7e,0x73,0x34,0x49,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x3, 0xec, +0x80,0x36,0xa5,0xbe,0x30,0x18,0x12,0xc7,0x6d,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb, +0x7e,0x53,0x34,0x4a,0xa, 0x45,0x5d,0x43,0x7e,0x73,0x3, 0xed,0x80,0x1a,0x12,0xc7, +0x6d,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x34,0x49,0xa, 0x4b, +0x5d,0x43,0xa, 0x5a,0x9, 0x75,0x3, 0xee,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54, +0xf, 0x7e,0x34,0x0, 0x1, 0x22,0x7e,0xb3,0x3, 0xeb,0x70,0x6, 0x12,0xc7,0xaf,0x2, +0xc7,0xb5,0x12,0x59,0xaf,0x12,0xc7,0xbb,0x50,0xa, 0x12,0x77,0xb9,0x7c,0x3b,0x12, +0xc7,0xaf,0x80,0x5, 0x12,0xc8,0xce,0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12, +0xc6,0xfa,0x60,0xa, 0x7a,0x33,0x3, 0xee,0x74,0x1, 0x7a,0xb3,0x2a,0x8, 0x22,0xe4, +0x7a,0xb3,0x2f,0x80,0x22,0xe4,0x7a,0xb3,0x39,0xd4,0x22,0x7e,0xb3,0x2f,0x80,0xb4, +0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x17,0x2f,0x90,0xbd,0x13,0x28,0xa, 0x7a,0x37, +0x2f,0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e,0x17,0x2f,0x88,0xbd,0x13,0x50,0x8, +0x7a,0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e,0x17,0x2f,0x8e,0xbd,0x12,0x28,0xa, +0x7a,0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80,0x10,0x7e,0x17,0x2f,0x96,0xbd,0x12, +0x50,0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f,0x94,0x7e,0xb3,0x2f,0xa8,0xb4,0xa, +0xf, 0x12,0x77,0xea,0x7a,0x37,0x2f,0xa0,0x12,0x77,0xe1,0x7a,0x37,0x2f,0xa2,0x22, +0xb4,0x14,0xe, 0x12,0x77,0xea,0x7a,0x37,0x2f,0xa4,0x12,0x77,0xe1,0x7a,0x37,0x2f, +0xa6,0x22,0x7d,0xf2,0x7d,0xe3,0x7e,0x8, 0x2f,0x80,0x7e,0x34,0x0, 0x28,0xe4,0x12, +0x20,0xe8,0x7e,0x8, 0x2b,0xbf,0x7e,0x34,0x3, 0xc0,0x12,0x20,0xe8,0x7a,0xb3,0x3, +0xee,0x7e,0x34,0x62,0x94,0x12,0x23,0x74,0x7a,0x37,0x2b,0xb7,0x7a,0xe7,0x2f,0x84, +0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88,0x7a,0xe7,0x2f,0x8c,0x7a,0xe7,0x2f,0x90, +0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a,0x7a,0xf7,0x2f,0x8e,0x7a,0xf7,0x2f,0x92, +0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb,0x7a,0xf7,0x2b,0xbd,0x7a,0xb3,0x2f,0xa8, +0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x74,0xfe,0x7a,0xb3,0x3, 0xee,0xe4,0x7a,0xb3, +0x2f,0x80,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x39,0xd9,0x9e, +0x37,0x39,0xd5,0x12,0x21,0x1a,0xbd,0x31,0x38,0x12,0x7e,0x37,0x39,0xdb,0x9e,0x37, +0x39,0xd7,0x12,0x21,0x1a,0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xd8, +0xca,0x79,0x6c,0xff,0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x2a,0x2, 0x7e,0xe3, +0x2a,0x3, 0x7e,0xb3,0x39,0xd4,0x60,0x11,0x7e,0xc7,0x39,0xdd,0x4d,0xcc,0x78,0x2, +0x21,0xc2,0xbe,0xd0,0x1, 0x28,0x2, 0x21,0xc2,0xbe,0xd0,0x1, 0x78,0x1d,0xbe,0xb0, +0x4, 0x78,0x2, 0x21,0xc2,0x7e,0xe7,0x29,0x8, 0x7e,0xf7,0x29,0xa, 0x7d,0x3e,0x7d, +0x2f,0x12,0x5d,0x90,0xbe,0xb0,0x1, 0x78,0x2, 0x21,0xc2,0x7e,0xa3,0x39,0xd4,0x7c, +0xba,0x14,0x68,0x29,0x14,0x68,0x54,0x14,0x68,0x23,0x14,0x78,0x2, 0x21,0xbf,0xb, +0xb2,0x68,0x2, 0x21,0xc2,0xbe,0xd0,0x1, 0x68,0x2, 0x21,0xd1,0x4c,0xee,0x68,0x2, +0x21,0xd1,0x74,0x1, 0x7a,0xb3,0x39,0xd4,0x12,0xc9,0xe4,0x80,0x65,0x4c,0xdd,0x78, +0x1d,0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x39,0xd4,0x7e,0x34,0x62,0x6a, +0x80,0x54,0x74,0x4, 0x7a,0xb3,0x39,0xd4,0x7e,0x34,0x62,0x6e,0x80,0x48,0x12,0xc9, +0xed,0x90,0x62,0x5d,0x12,0xc9,0xd8,0x68,0x49,0x80,0x56,0xbe,0xd0,0x1, 0x78,0x51, +0x4c,0xee,0x78,0x4d,0x12,0xc9,0xed,0x7e,0x34,0x62,0x66,0x12,0x23,0x74,0x7e,0x14, +0x62,0x6a,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7,0x39,0xdd,0x40, +0x21,0x90,0x62,0x5c,0x12,0xc9,0xd8,0x68,0x19,0x12,0xc9,0xe4,0x74,0x3, 0x7a,0xb3, +0x39,0xd4,0x7e,0x34,0x62,0x6a,0x12,0x23,0x74,0x7a,0x37,0x39,0xdd,0x80,0x12,0x7e, +0xf0,0x24,0xe4,0x7a,0xb3,0x39,0xd4,0x6d,0x33,0x7a,0x37,0x39,0xdd,0x7c,0xbf,0x80, +0x2, 0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xe4,0x93,0xa, 0x3b,0x12,0xc8,0xa3,0xa, +0xdb,0x4d,0xdd,0x22,0x7a,0xe7,0x39,0xd5,0x7a,0xf7,0x39,0xd7,0x22,0x7a,0xe7,0x39, +0xd9,0x7a,0xf7,0x39,0xdb,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x2f,0x90, +0x7a,0x35,0x2a,0x7e,0x37,0x2f,0x8e,0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c,0x7a,0x35, +0x26,0x7e,0x37,0x2f,0x9e,0x7a,0x35,0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x26, +0x7e,0x14,0x0, 0x2f,0x74,0x9, 0x12,0x1f,0x8c,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d, +0x15,0x7f,0x15,0x2d,0x35,0x12,0xca,0x45,0xb, 0xf0,0x7e,0x73,0x39,0x53,0xbc,0x7f, +0x38,0xda,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34,0x0, 0x0, +0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, +0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35,0x33,0x6d, +0x22,0x7e,0x33,0x39,0x55,0x12,0xca,0x9a,0x7e,0x15,0x2f,0x12,0x1f,0x5, 0x1b,0x6a, +0x30,0xb, 0x7a,0x30,0x9e,0x35,0x35,0x6d,0x22,0x7e,0x33,0x39,0x56,0x12,0xca,0x9a, +0x7e,0x15,0x31,0x12,0x1f,0x5, 0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x1e, +0xeb,0xca,0x3b,0x7f,0x71,0x7e,0x60,0x1, 0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b, +0x7a,0x53,0x22,0xf4,0x7a,0x43,0x23,0xe4,0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x61,0xc2, +0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x60,0x2d,0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf, +0xf5,0x26,0x7f,0x67,0x2d,0xd4,0xb, 0x6a,0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d, +0xad,0x7d,0x7a,0x7c,0x8f,0xbe,0x80,0x0, 0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, +0xa4,0xa, 0x79,0x9d,0x7a,0xbe,0xf0,0x0, 0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe, +0x80,0x2, 0x58,0x7, 0xbe,0xf0,0x2, 0x58,0x2, 0x61,0xc0,0xbe,0x60,0x0, 0x18,0x2, +0x61,0xa8,0xbe,0x70,0xec,0x28,0x2, 0x61,0xcc,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0, +0x8, 0x48,0x61,0xa, 0xa7,0xb, 0xa4,0x7d,0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12, +0xcc,0x10,0x19,0xba,0x22,0xf4,0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0xcc,0x10,0x19, +0xba,0x23,0xe4,0x9, 0xba,0x22,0xf4,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d, +0x6c,0x7c,0xbd,0xa, 0xc7,0x19,0xbc,0x22,0xf3,0x9, 0xbc,0x23,0xe4,0xa, 0xcb,0xa, +0xa4,0x2d,0xac,0x12,0xcc,0x10,0x19,0xba,0x23,0xe3,0x2d,0xdb,0x12,0xcc,0x7, 0x19, +0xbd,0x22,0xf5,0xa, 0xd9,0x12,0xcc,0x5, 0x19,0xbd,0x23,0xe5,0xb, 0xd5,0x7d,0x6d, +0x7c,0x7d,0x80,0x24,0xbe,0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x26, +0xa, 0xcb,0xa, 0xd5,0x12,0xcc,0x5, 0x19,0xbd,0x22,0xf4,0xa, 0xc9,0xa, 0xd4,0x12, +0xcc,0x5, 0x19,0xbd,0x23,0xe4,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x1f,0x7e,0x51,0x26, +0x7c,0x49,0xe5,0x26,0xa, 0xd7,0x19,0xbd,0x22,0xf4,0x19,0x9d,0x23,0xe4,0xb, 0x70, +0xb, 0xa0,0x7e,0xb3,0x39,0x53,0xbc,0xba,0x28,0x2, 0x41,0xc0,0x7a,0x73,0x39,0x53, +0x7e,0xa0,0x1, 0x80,0x25,0xa, 0x3a,0x9, 0xb3,0x22,0xf4,0xa, 0x2b,0x7e,0x70,0x2, +0xac,0x7a,0x7f,0x60,0x2d,0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x23,0xe4,0xa, +0x4b,0x2d,0x3f,0x7d,0x2e,0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x39,0x53,0xbc,0xba, +0x38,0xd3,0xda,0x3b,0x22,0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22, +0xe, 0xa4,0x7d,0x6a,0x7c,0xbd,0xa, 0xa7,0x22,0x74,0x1, 0x7a,0xb3,0x38,0xb4,0x7e, +0x34,0x60,0xa3,0x22,0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b,0x9, 0xa3,0x26,0xfa,0x22, +0x74,0x1, 0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x1d,0x22,0x7e,0x18,0x5, 0xf8,0x7a, +0x1f,0x6, 0xf4,0x22,0xa, 0x2b,0x1b,0x24,0xa, 0x3d,0xbd,0x32,0x22,0x74,0x2, 0xac, +0xbe,0x9, 0xd5,0x26,0xfa,0x9, 0xc5,0x26,0xfb,0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4, +0x7e,0x7b,0x60,0xbc,0x6b,0x22,0x6e,0x34,0xff,0xff,0xb, 0x34,0x7a,0x37,0x2a,0x5e, +0x22,0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x26,0xfa,0x22,0x90,0x60,0x9a,0x93,0xa, +0x3b,0x22,0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x31,0xb, 0xa0,0x22,0x7e,0x34,0x0, 0x3e, +0x74,0xff,0x2, 0x20,0xe8,0x9d,0x32,0x12,0x21,0x1a,0xbe,0x34,0x0, 0x3, 0x22,0x7c, +0xf5,0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33, +0x22,0x6d,0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7e,0x37,0x25,0xf4,0x7a,0x37,0x34, +0x88,0x22,0x7e,0x73,0x38,0xd1,0x7a,0x73,0x2b,0x20,0x22,0x7e,0xb3,0x38,0xf4,0x7e, +0x34,0x0, 0x4, 0x22,0x7d,0x2e,0x12,0x1e,0xb9,0x7d,0xf3,0x22,0x7e,0x73,0x2a,0x2, +0xbe,0x70,0x0, 0x22,0xcc,0xe4,0x33,0x1b,0xcd,0x32,0x8, 0xd0, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V09_D01_20170811_app.i b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V09_D01_20170811_app.i new file mode 100644 index 0000000000000..3db75b9fffcc7 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V09_D01_20170811_app.i @@ -0,0 +1,3279 @@ +0x2, 0x1f,0xd2,0x2, 0xc0,0x36,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x42,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0xc0,0xa, 0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x80,0x7e,0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x32,0x2, 0x80,0x9a,0x2, 0x2a,0x27,0x22,0x32,0x2, 0x0, 0x4a,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x3f,0x65,0xff,0xff,0x2, 0x0, 0x5a,0xa2,0x8, +0x22,0xff,0xff,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xd, 0x7e,0xf, 0x33,0xcf, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x33,0xdf,0x7e,0x73,0x33,0xdf,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xc, 0x80,0x2, 0xc2,0xc, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x6b,0xcb,0x7e,0x1f,0x33,0xcf,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x33,0xcf,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x33,0xd3,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x33,0xdb,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x33,0xd9,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x39,0xee,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x64,0x30,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x1e, +0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0xe2,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0xb2,0x61,0x3f,0x7e,0x34,0x1d,0x96,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x1d,0xc6,0x61,0x3f,0x7e,0x34,0x1e,0xa, 0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d, +0xf1,0x61,0x3f,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x1e,0x69,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x1e,0x6a,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x4, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x4, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xcf,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x33, +0xcf,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x33,0xcf,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x20,0xe8,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x39,0xf2,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x39,0xf2,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x39,0xf2,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x39,0xee,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x33,0xc7,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x39, +0xee,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x33,0xc7,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x39,0xee,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x39,0xee,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x39,0xee,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x33,0xcf,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x33,0xcf,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x1e,0xb9,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x33,0xcf,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x39,0xf2,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xf2,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x39,0xf2,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0x2, 0x45,0xd2,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x39,0xf2,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x39,0xf2, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x39,0xf2, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x39,0xf2,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39,0xea,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39, +0xea,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x39,0xea,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x39,0xea,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x33,0xc7,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x33,0xc7,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x33,0xc7,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x33,0xc7,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x33,0xcf,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x33,0xcf,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x33, +0xcf,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x33,0xcf,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x33,0xcf,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x33,0xcf,0x69,0x40,0x0, 0x22,0x30,0x4, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x33,0xcf,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x33,0xcf,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x33, +0xcf,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x33,0xcf, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x33,0xcf,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x33,0xcf,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x33,0xcf,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x33,0xcf,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1e,0xb9,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x1e,0xb9,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xf2, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x39,0xea,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x39,0xea,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x39,0xea,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1c,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x39,0xf2, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xf2,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x39,0xf2,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x39, +0xf2,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x33,0xcf,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x33,0xcf,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x33,0xcf,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x33,0xcf, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x33,0xcf,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x33,0xcf,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x39,0xf2,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x39,0xf2,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x39,0xf2,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x39,0xf2,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xee,0x79,0x30, +0x0, 0xe, 0xc2,0x1b,0xe4,0x7a,0xb3,0x39,0xe9,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x33,0xc7,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xc7,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x39, +0xee,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x39, +0xee,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x39,0xf2,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x39,0xf2,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x39,0xf2,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x39, +0xf2,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x39,0xf2,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1c,0x7e,0xf, 0x39,0xf2,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x39,0xf2,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x1f,0x58,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x1e,0x12,0x1f,0x5, 0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x33,0xcf,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1b,0x7e,0xf, 0x39,0xee,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x39,0xe9,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x39,0xee,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x6b,0xcb,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x33,0xc7,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x33,0xc7,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xcf,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xd, 0xe4,0x7a,0xb3,0x33,0xdf,0x7e,0x1f,0x33,0xc7, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xea,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xea,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x39,0xea,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x33,0xcf,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x33,0xcf,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x39,0xea,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x39,0xea,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x39,0xf2,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x39,0xf2,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x20,0x99,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x20,0x9a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x33,0xc7,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x33,0xc7,0x1b,0x1a,0x10,0x7e, +0x1f,0x33,0xc7,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x33,0xcf,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x39,0xee,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x33,0xc7,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x33,0xc7,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x33, +0xcf,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x33,0xcf,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x4, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x33,0xcf,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x33,0xc7,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x1f,0x7, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x1f,0x7, 0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x39,0xfc,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x6, 0xc2,0x7, 0x75,0x1d,0x0, 0xc2,0xe, 0xc2,0xf, 0xc2,0x11,0x75,0x1e, +0x0, 0x75,0x1f,0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x1b,0x0, 0x75,0x1c,0x0, 0xc2,0x13, +0x75,0x5e,0x0, 0xc2,0x15,0x75,0x5f,0x0, 0xc2,0x16,0xc2,0x17,0xc2,0x18,0x75,0x60, +0x0, 0xc2,0xa, 0x75,0x61,0x64,0xc2,0x19,0xc2,0x1a,0x75,0x62,0x0, 0xd2,0x0, 0xd2, +0x1, 0xd2,0x2, 0xd2,0x1b,0xc2,0xc, 0xd2,0xd, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x21, +0x2a,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44, +0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2, +0x80,0xdf,0x2, 0x38,0x35,0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd, +0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, +0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, +0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94, +0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31, +0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11, +0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, +0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d, +0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44, +0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0x32,0x1, 0x19,0x1, 0x0, 0x2, +0xf8,0x4, 0xe7,0x5, 0xce,0x6, 0xc2,0x7, 0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff, +0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, +0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x34,0x8c,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x39,0xf8,0x1, 0x0, 0x1, 0x25,0xf6,0x1, 0x0, 0x1, 0x38,0xaf, +0x0, 0x0, 0x2, 0x39,0x1, 0x0, 0x0, 0x0, 0x2, 0x39,0x3, 0x0, 0x0, 0x0, 0x1, 0x39, +0x5, 0x0, 0x0, 0x1, 0x3, 0x9a,0xff,0x0, 0x1, 0x39,0xf9,0x0, 0x0, 0x1, 0x39,0xfa, +0x0, 0x0, 0x2, 0x36,0x92,0x0, 0x0, 0x0, 0x1, 0x36,0xb5,0x0, 0x0, 0x1, 0x37,0x2e, +0x0, 0x0, 0x1, 0x37,0x2f,0x0, 0x0, 0x1, 0x37,0x30,0x0, 0x0, 0x3c,0x33,0x4c,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x33,0xc4,0x0, +0x0, 0x1, 0x33,0xc5,0x0, 0x0, 0x1, 0x33,0xc6,0x0, 0x0, 0x1, 0x37,0xd2,0x1, 0x0, +0x2, 0x37,0xd5,0x0, 0x0, 0x0, 0x1, 0x0, 0x63,0x0, 0x0, 0x1, 0x0, 0x64,0x0, 0x0, +0x1, 0x0, 0x65,0x0, 0x0, 0x1, 0x37,0xd9,0x1, 0x0, 0x1, 0x38,0x53,0x0, 0x0, 0x1, +0x39,0xfb,0x0, 0x0, 0x6, 0x34,0x49,0x3f,0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, 0x34, +0x4f,0x24,0x0, 0x1, 0x33,0xfb,0x0, 0x0, 0x1, 0x33,0xfc,0x0, 0x0, 0x1, 0x33,0xfd, +0x0, 0x0, 0x1, 0x33,0xfe,0x0, 0x0, 0x1, 0x33,0xff,0x0, 0x0, 0x1, 0x2f,0xa9,0x0, +0x0, 0x1, 0x33,0x46,0x0, 0x0, 0x1, 0x2, 0x87,0x0, 0x0, 0x2, 0x2, 0xa8,0x0, 0x0, +0x0, 0x4, 0x38,0x54,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xfa,0x0, 0x0, 0x1, 0x3, +0xfb,0x0, 0x0, 0x2, 0x3, 0xfc,0x0, 0x0, 0x0, 0x1, 0x3, 0xfe,0x64,0x0, 0x1, 0x3, +0xff,0x0, 0x0, 0x1, 0x39,0xfc,0x0, 0x0, 0x1, 0x39,0xf6,0x0, 0x0, 0x1, 0x39,0xf7, +0x0, 0x0, 0x2, 0x2b,0xb9,0x2b,0xbf,0x0, 0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8, +0x0, 0x0, 0x1, 0x39,0xd4,0x0, 0x0, 0x1, 0x39,0x52,0xff,0x0, 0x1, 0x39,0x53,0x0, +0x0, 0x1, 0x39,0x54,0x0, 0x0, 0x1, 0x39,0x55,0x40,0x0, 0x1, 0x39,0x56,0x40,0x0, +0x4, 0x39,0xea,0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x39,0xee,0x0, 0x0, 0x64,0x0, 0x0, +0x4, 0x33,0xc7,0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x33,0xcb,0x0, 0x0, 0x68,0xc0,0x0, +0x4, 0x33,0xcf,0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x33,0xe0,0x0, 0x0, 0x40,0x0, 0x0, +0x4, 0x39,0xf2,0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x3, 0xe8,0x0, 0xc, 0x1, 0xf4,0x3, +0x20,0x0, 0xa, 0x1, 0x4a,0x2, 0xbc,0x0, 0x9, 0x0, 0xc8,0x1, 0xf4,0x0, 0x6, 0x0, +0x3c,0x1, 0x2c,0x0, 0x6, 0x0, 0x3c,0x0, 0x64,0x0, 0x6, 0x0, 0x3c,0x0, 0x50,0x0, +0x6, 0x0, 0x0, 0x0, 0xe, 0x1c,0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, +0x0, 0x0, 0x1e,0x12,0x49,0x9b,0x12,0x5e,0xe1,0x12,0x38,0xae,0x12,0x28,0x86,0x2, +0x23,0x12,0x12,0x23,0x23,0x7e,0xb3,0x2b,0xf, 0x12,0xa5,0xf9,0x74,0x1, 0x7a,0xb3, +0x37,0xdd,0x22,0x12,0xa7,0x7a,0x74,0x1, 0x7a,0xb3,0x37,0xd9,0x22,0x7e,0x34,0x60, +0xa3,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x62,0xd9,0x12,0x38,0x57,0x12,0x49,0x9b, +0x12,0x5e,0xda,0x12,0xcc,0x30,0x12,0x38,0xae,0x12,0x28,0x86,0x12,0x5e,0xc5,0x2, +0x23,0x12,0x7e,0x34,0x61,0x4f,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x7a,0x37,0x2a, +0x5a,0x7e,0x34,0x61,0x51,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x7a,0x37,0x2a,0x5c, +0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x22,0x7e,0x34,0x61,0x55, +0x12,0x23,0x74,0x7a,0x37,0x28,0x95,0x7e,0x34,0x61,0xc0,0x12,0x23,0x74,0x7a,0x37, +0x28,0x99,0x7e,0x34,0x61,0xbe,0x12,0x23,0x74,0x7a,0x37,0x28,0x97,0x7e,0x34,0x62, +0x18,0x12,0x23,0x74,0x7a,0x37,0x28,0x9b,0x7e,0x34,0x61,0xc2,0x12,0x23,0x74,0x7a, +0x37,0x28,0x9d,0x7e,0x34,0x61,0xc4,0x12,0x23,0x74,0x7a,0x37,0x28,0x9f,0x7e,0x34, +0x61,0xc6,0x12,0x23,0x74,0x12,0x87,0xda,0x12,0x23,0x74,0x7a,0x37,0x28,0xa3,0x90, +0x61,0xca,0xe4,0x93,0x7a,0xb3,0x28,0xa5,0xe4,0x7a,0xb3,0x28,0xa8,0x12,0xcc,0x7b, +0x3e,0x34,0x7e,0x8, 0x25,0xf7,0xe4,0x2, 0x20,0xe8,0x12,0x25,0xa2,0x7e,0xb3,0x37, +0xe4,0xb4,0x1, 0x16,0x7e,0x34,0x62,0x3a,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5a,0x7e, +0x34,0x62,0x3c,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5c,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x37,0x7e,0x34,0x62,0x44,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x46, +0x12,0x23,0x74,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x62,0x48,0x12,0x23,0x74,0x7a,0x37, +0x2a,0x4f,0x7e,0x34,0x62,0x4a,0x12,0x23,0x74,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62, +0x4c,0x12,0x23,0x74,0x7a,0x37,0x2a,0x53,0x7e,0xb3,0x2a,0x2, 0x70,0x21,0x7e,0x27, +0x2a,0x5a,0x7d,0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12,0x25,0x12,0xbe, +0x34,0x0, 0x28,0x28,0x4, 0x7e,0x34,0x0, 0x28,0x2d,0x32,0x7a,0x37,0x2a,0x5a,0x22, +0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69,0x22,0x0, 0x2, +0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34,0x0, 0x20,0x7e,0x8, 0x0, +0x24,0x7e,0x24,0x0, 0x6, 0x12,0x64,0x30,0x7e,0x34,0x61,0x4f,0x12,0x23,0x74,0x1e, +0x34,0x1e,0x34,0x7a,0x73,0x3, 0x9b,0x7e,0x34,0x61,0x51,0x12,0x23,0x74,0xe, 0x34, +0xe, 0x34,0x7a,0x73,0x3, 0x9c,0x7e,0x34,0x61,0x55,0x12,0x23,0x74,0x12,0x25,0x12, +0x7a,0x73,0x3, 0x9d,0x7e,0x34,0x61,0x59,0x12,0x23,0x74,0x12,0x25,0x12,0x7a,0x73, +0x3, 0x9e,0x7e,0x34,0x61,0x5b,0x12,0x23,0x74,0x12,0x25,0x12,0x7a,0x73,0x3, 0x9f, +0x7e,0x34,0x61,0x5d,0x12,0x23,0x74,0x12,0x25,0x12,0x7a,0x73,0x3, 0xa0,0x7e,0x34, +0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x3, 0xa1, +0x12,0x20,0xc3,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x3, 0xcc,0xe5,0x28,0x7a,0xb3,0x3, +0xbb,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x22,0x90,0x60,0x99,0xe4,0x93, +0x7a,0xb3,0x2a,0x4d,0x90,0x60,0x9e,0xe4,0x93,0x7a,0xb3,0x2a,0x4e,0x7e,0x34,0x61, +0x55,0x12,0x23,0x74,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12,0x23,0x74,0x7a, +0x37,0x2a,0x51,0x7e,0x14,0x61,0x5b,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x7a,0x27, +0x2a,0x53,0x7a,0x37,0x2a,0x55,0x90,0x60,0x9d,0xe4,0x93,0x7a,0xb3,0x2a,0x59,0x12, +0x23,0x52,0x12,0xcc,0x66,0x7e,0x34,0x62,0x18,0x12,0x23,0x74,0x7a,0x37,0x2a,0x60, +0x90,0x60,0x9f,0xe4,0x93,0x7a,0xb3,0x2a,0x64,0x90,0x60,0xa0,0xe4,0x93,0x7a,0xb3, +0x2a,0x65,0x7e,0x34,0x60,0xa1,0x12,0x23,0x74,0x7a,0x37,0x2a,0x66,0x7e,0x34,0x61, +0x5d,0x12,0x23,0x74,0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3,0x2a,0x6b,0x7a,0xb3,0x16, +0x92,0x22,0x12,0x23,0x52,0x12,0xcc,0x66,0x7e,0x34,0x61,0x55,0x12,0x23,0x74,0x7a, +0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12,0x23,0x74,0x7a,0x37,0x2a,0x51,0x7e,0x34, +0x61,0x5b,0x12,0x23,0x74,0x7a,0x37,0x2a,0x53,0x22,0x7e,0x34,0x62,0x4e,0x12,0x23, +0x74,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x50,0x12,0x23,0x74,0x7a,0x37,0x2a,0x5c, +0x7e,0x34,0x62,0x52,0x12,0x23,0x74,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x62,0x54,0x12, +0x23,0x74,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62,0x56,0x12,0x23,0x74,0x7a,0x37,0x2a, +0x53,0x22,0xca,0xf8,0x7e,0xf3,0x38,0xb4,0xbe,0xf0,0x5, 0x78,0xb, 0x74,0x1, 0x7a, +0xb3,0x38,0xb4,0x12,0x0, 0x9, 0x80,0x52,0xbe,0xf0,0x4, 0x78,0x13,0x12,0xcc,0x19, +0x12,0x23,0x74,0x12,0x26,0x77,0xe4,0x7a,0xb3,0x2b,0x2, 0x12,0x6a,0x92,0x80,0x3a, +0xbe,0xf0,0x6, 0x78,0x19,0x12,0xcc,0x19,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x55, +0xcf,0xe4,0x7a,0xb3,0x2b,0x1e,0x12,0x5f,0x1f,0x12,0xcc,0xc2,0x80,0x1c,0xbe,0xf0, +0x7, 0x78,0x1d,0x12,0xcc,0x19,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x6f,0xca,0x50, +0xfb,0x12,0x87,0x5c,0x12,0x5e,0xea,0x12,0x28,0x86,0x74,0x2, 0x7a,0xb3,0x38,0xb4, +0xda,0xf8,0x22,0x7e,0x34,0x3, 0xe8,0x6d,0x22,0x7a,0x27,0x34,0x38,0x7a,0x37,0x34, +0x3a,0x22,0x7e,0xb3,0x3, 0xc0,0x14,0x68,0x5d,0x14,0x78,0x2, 0xe1,0x29,0x14,0x68, +0x6d,0x24,0x3, 0x68,0x2, 0xe1,0x21,0x12,0xcc,0xdc,0x38,0x8, 0x30,0x12,0xf, 0x12, +0x8f,0xa0,0x68,0xa, 0x12,0x59,0xa8,0xe4,0x7a,0xb3,0x39,0x99,0x80,0x7b,0x7e,0xb3, +0x3, 0xa1,0x30,0xe0,0x74,0x7e,0x73,0x3, 0xa2,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad, +0x32,0x7e,0xb3,0x3, 0xeb,0xb4,0x1, 0xb, 0x7e,0x34,0x62,0x6a,0x12,0x23,0x74,0x2e, +0x34,0x4, 0x0, 0xbe,0x37,0x39,0x97,0x50,0x50,0x12,0x59,0xa8,0x12,0x5e,0xc, 0xe4, +0x7a,0xb3,0x39,0x9b,0x80,0x43,0x12,0xcc,0xdc,0x28,0x39,0xe4,0x7a,0xb3,0x3, 0xc0, +0x7e,0xb3,0x39,0x99,0xb4,0x1, 0x3, 0x12,0x5e,0xc, 0xd2,0x1a,0x80,0x26,0x74,0xff, +0x7a,0xb3,0x3, 0x9a,0x7e,0x34,0x60,0xa5,0x12,0x23,0x74,0x12,0x26,0x77,0x12,0x66, +0xa5,0x12,0x23,0x2d,0xe4,0x7a,0xb3,0x3, 0xc0,0x7a,0xb3,0x3, 0xff,0xd2,0x1a,0x80, +0x8, 0x12,0x5e,0xc, 0xe4,0x7a,0xb3,0x3, 0xff,0x12,0x65,0xc2,0x2, 0x27,0x2f,0xca, +0x3b,0x7e,0xb3,0x3, 0xc0,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x28,0x78,0x6c,0xcc,0x6c, +0xdd,0x7e,0xb3,0x3, 0xeb,0xb4,0x1, 0xc, 0x90,0x61,0x62,0xe4,0x93,0x7c,0xeb,0x90, +0x61,0x64,0x80,0xa, 0x90,0x61,0x61,0xe4,0x93,0x7c,0xeb,0x90,0x61,0x63,0xe4,0x93, +0x7c,0xfb,0x12,0x8b,0x56,0x7d,0xf3,0x12,0x6f,0xca,0x50,0xfb,0x74,0x1, 0x7a,0xb3, +0x39,0x9a,0x12,0x48,0x34,0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x67,0x6e, +0x12,0xcc,0xb1,0x7e,0xe7,0x2b,0xd, 0x7a,0xe5,0x25,0x7e,0xb3,0x2a,0xfa,0xf5,0x24, +0x74,0x4, 0x7a,0xb3,0x2a,0xfa,0x7e,0xe7,0x2b,0xd, 0x5e,0xe4,0x0, 0x3f,0x7a,0xe7, +0x2b,0xd, 0x7e,0xb3,0x2a,0xfa,0x12,0xc3,0x5d,0x7c,0x7b,0x74,0x8, 0xac,0x7b,0x7e, +0x24,0x0, 0x4, 0x12,0x1e,0xb9,0x7d,0x23,0x7d,0x3f,0x12,0x25,0x12,0xad,0x32,0x7a, +0x37,0x2b,0x7, 0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0x8f,0xbf,0x2, 0x28,0x58, +0x12,0x26,0x73,0x30,0xf, 0x3, 0x2, 0x28,0x5f,0x7c,0xbe,0x12,0x90,0x42,0x12,0x69, +0xb5,0x80,0xf, 0x80,0x7, 0x12,0x66,0x35,0xe4,0x12,0x66,0x3c,0x20,0x93,0xf6,0x12, +0x65,0x8d,0x30,0x1b,0xf7,0x30,0x1a,0xf4,0xd2,0x4, 0x12,0x65,0x7c,0xe4,0x12,0x13, +0xde,0xb, 0xc0,0x12,0x89,0x26,0x12,0x90,0x4c,0x7e,0xa3,0x39,0x99,0x4c,0xaa,0x78, +0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x9a,0x4c,0xaa,0x68,0xb, 0x7e,0xb3,0x3, 0xeb,0x70, +0x5, 0xe4,0x7a,0xb3,0x39,0x99,0x12,0x28,0x7b,0x78,0x18,0x7e,0xb3,0x39,0x99,0x60, +0x12,0xe4,0x7a,0xb3,0x39,0x99,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a,0x3, 0x7e,0xd0, +0x1, 0x80,0x1c,0x12,0x28,0x7b,0x68,0x10,0x7e,0xb3,0x39,0x99,0x70,0xa, 0x7e,0xd0, +0x1, 0xe4,0x7a,0xb3,0x3, 0xc0,0x80,0x7, 0xbc,0xfc,0x28,0x3, 0x2, 0x27,0xd0,0xe4, +0x7a,0xb3,0x2b,0x4, 0x7e,0x35,0x25,0x7a,0x37,0x2b,0xd, 0xe5,0x24,0x7a,0xb3,0x2a, +0xfa,0x4c,0xdd,0x68,0x3, 0x12,0x28,0x86,0xda,0x3b,0x22,0x7e,0x73,0x39,0xe9,0xa, +0x37,0x5e,0x34,0x0, 0x2, 0x22,0xe4,0x7a,0xb3,0x33,0xe6,0x7a,0xb3,0x33,0xe5,0x12, +0x6a,0xf2,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x33,0xe6,0x22, +0xca,0x3b,0x12,0x6f,0xca,0x50,0xfb,0x7e,0xf3,0x2b,0xf, 0x7c,0xbf,0x12,0xaa,0xd9, +0x12,0xab,0x6a,0x7e,0xb3,0x2b,0x1f,0xf5,0x28,0x7e,0xc3,0x2b,0x20,0x7e,0xb3,0x3, +0xc2,0xb4,0x1, 0xf, 0x12,0xa6,0xff,0x7e,0xb3,0x16,0x91,0x70,0x6, 0x12,0x28,0x86, +0xc3,0x21,0x9c,0x12,0x29,0x9f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, +0x4, 0x7e,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x29,0x9f,0x3e,0x34,0xca,0x39,0x7e,0x18, +0x7, 0x7a,0x7e,0x8, 0x4, 0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0xb3,0x3, 0xc2,0xb4, +0x3, 0x7, 0x12,0xa4,0x32,0x7a,0x37,0x38,0xf7,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12, +0x5e,0xe1,0x12,0xa4,0x1a,0x12,0xae,0x69,0xe4,0x12,0x13,0xde,0x12,0x28,0x86,0x7e, +0x8, 0x4, 0x7e,0x7a,0xd, 0x29,0x7e,0x18,0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0x6b, +0x63,0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29,0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0, +0x12,0x6b,0x63,0x7e,0xd3,0x2b,0x1f,0x7e,0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b, +0x1f,0x7a,0xc3,0x2b,0x20,0x7e,0x34,0x8, 0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d, +0x10,0x12,0x79,0x34,0x7a,0xd3,0x2b,0x1f,0x7a,0xe3,0x2b,0x20,0x7c,0xbf,0x12,0xaa, +0x7f,0x12,0xa2,0xf3,0x7e,0xb3,0x3, 0xff,0x4, 0x7a,0xb3,0x3, 0xff,0x7e,0x73,0x3, +0xff,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64,0x7a,0xb3,0x3, 0xff,0x7e,0xb3,0x16,0x90, +0x60,0x9, 0x7e,0xb3,0x16,0x91,0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e, +0x73,0x2a,0x74,0xa, 0x27,0x7e,0x73,0x2a,0x73,0xa, 0x37,0x2d,0x32,0x22,0x12,0x54, +0xc9,0x7e,0xb3,0x3, 0xc2,0xb4,0x3, 0x69,0x12,0xc1,0xb6,0x12,0x26,0x73,0x12,0x4b, +0x51,0x7e,0xb3,0x38,0xb0,0x30,0xe7,0xe9,0x12,0x28,0xa0,0x12,0x29,0x9f,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, 0xfc,0x12,0x20,0xc3,0x1b,0xfd,0x12, +0x29,0x9f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x7e,0x7e,0x8, 0x5, 0x7a,0x12,0x20, +0xc3,0x1b,0xfd,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x15,0x12,0x6e,0x5f,0x12,0x6f,0xa, +0x12,0x45,0xb9,0x12,0x84,0x67,0x12,0x36,0xfe,0x12,0x2a,0x31,0x12,0x58,0xc4,0x12, +0x54,0xfb,0x12,0xaf,0x58,0x7e,0xb3,0x38,0xb0,0x54,0x7f,0x7a,0xb3,0x38,0xb0,0x80, +0x90,0x12,0x6f,0xd5,0x2, 0x0, 0x46,0xe4,0x7a,0xb3,0x2b,0x2, 0x7a,0xb3,0x2b,0x1e, +0x22,0x12,0x8b,0xc1,0x12,0x2c,0x2b,0x12,0x2c,0x2b,0x12,0x2f,0xde,0x12,0x36,0x67, +0x12,0x2e,0x78,0x12,0x2c,0x2b,0x12,0xb8,0x6b,0x12,0x2c,0x2b,0x12,0x9f,0x65,0x12, +0x2c,0x2b,0x2, 0x2a,0x55,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4, +0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x33,0x88,0x7e,0x8, 0x33,0x4c,0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0xf3,0x28,0x84,0xa, 0xcf,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e, +0x8, 0x1f,0x34,0x12,0x20,0xc3,0x1b,0xfd,0x6c,0x88,0x6c,0xee,0x61,0x29,0x7e,0xc4, +0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99,0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f, +0x34,0xbe,0xb0,0xff,0x68,0x3d,0x7c,0xb9,0x12,0x2e,0x5f,0x60,0x36,0x74,0x2, 0xac, +0xb9,0x9, 0x75,0x1f,0x35,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x33,0x89,0x12, +0x2c,0x73,0x7d,0x13,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, +0xac,0xbe,0x9, 0x75,0x33,0x88,0x12,0x2c,0x73,0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d, +0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9,0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70, +0x2, 0xac,0x7c,0x9, 0xb3,0x1f,0x34,0x9, 0x73,0x1f,0x35,0x12,0x30,0xb6,0xbe,0x37, +0x2a,0x5a,0x48,0x23,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac, +0xbd,0x19,0x55,0x1f,0x70,0x9, 0x53,0x1f,0x35,0x19,0x55,0x1f,0x71,0x74,0xff,0x19, +0xb3,0x1f,0x34,0xb, 0x80,0xb, 0xd0,0xb, 0xe0,0x7e,0x73,0x33,0x48,0xbc,0x7e,0x28, +0x2, 0x41,0x8e,0x7c,0xe8,0x80,0x6d,0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c, +0x7c,0xb9,0x12,0x2e,0x5f,0x60,0x33,0x12,0x2f,0xd4,0xbe,0xb0,0xff,0x68,0x2b,0x9, +0x73,0x1f,0x35,0x12,0xbf,0xcb,0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58, +0x5, 0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0xd, 0x12,0x2f,0xd4, +0xf5,0x24,0x9, 0xc3,0x1f,0x35,0x7d,0xdc,0x7c,0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0, +0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74,0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70, +0x19,0xc5,0x1f,0x71,0x7e,0xa0,0xff,0x7e,0x70,0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34, +0xb, 0xd0,0xb, 0xe0,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbe,0x38,0x8a,0x90,0x60,0x9a, +0xe4,0x93,0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f, +0x34,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xfd,0x12,0x95,0x29,0x7e,0x8, 0x33,0x88,0x74, +0xff,0x12,0x20,0xe8,0xbe,0xf0,0x0, 0x28,0x38,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e, +0x18,0x1f,0x34,0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x33,0x88,0x12,0x20,0xc3,0x1b,0xfd,0x6c, +0xee,0x80,0xa, 0x7c,0xbe,0x7e,0x70,0x1, 0x12,0x2e,0xdd,0xb, 0xe0,0xbc,0xfe,0x38, +0xf2,0x7a,0xf3,0x33,0x48,0x7a,0xf3,0x28,0x84,0x90,0x60,0x99,0xe4,0x93,0xbe,0xb3, +0x28,0x84,0x50,0x4, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0xca,0x79,0x6c,0xff,0x6c, +0xee,0x80,0x31,0x7c,0xbe,0x12,0x2e,0x5f,0x60,0x28,0x7e,0x34,0x0, 0x2, 0xca,0x39, +0xac,0x7e,0x2e,0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x26, +0xfa,0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbf,0x7e,0x70,0x1, 0x12,0x2e,0xdd, +0xb, 0xf0,0xb, 0xe0,0x12,0x47,0xe5,0x38,0xca,0x7a,0xf3,0x28,0x84,0xda,0x79,0x22, +0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x2, 0x21,0x1a,0xca,0x79,0x7f,0x70,0x7e,0xb4, +0xff,0xff,0x6c,0xee,0xc2,0x4, 0xc2,0x5, 0x29,0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc, +0x76,0x78,0xe, 0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2, +0x5, 0x6c,0xff,0x12,0x2e,0x52,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xa1, +0x34,0x7f,0x6, 0x7e,0x7b,0xb0,0x12,0x2f,0x7f,0x50,0x2d,0x7f,0x6, 0x29,0xb7,0x0, +0x2, 0x12,0x2f,0x7f,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0x2f, +0x4a,0x50,0x15,0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x2f,0x4a,0x50,0x8, +0x7c,0xef,0xd2,0x4, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70, +0x12,0x2c,0x73,0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12, +0x2c,0x73,0x2d,0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x2c, +0x73,0x2d,0xa3,0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x2c,0x73, +0x2d,0xa3,0xbd,0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, +0xd2,0x4, 0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0x81,0xa3,0x20,0x4, 0xb, +0x20,0x5, 0x8, 0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x4, 0x20,0x4, 0x2, 0xa1,0xf5, +0x74,0x6, 0xac,0xbe,0x12,0x2e,0x56,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23,0x54, +0x1f,0xbe,0xb0,0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e,0x60, +0x8, 0x5e,0x60,0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x5, 0x11,0x29, +0xb6,0x0, 0x4, 0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b,0xb0, +0x29,0x67,0x0, 0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x3, +0x80,0x4, 0x29,0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29,0x76, +0x0, 0x2, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, 0x2, +0x39,0x76,0x0, 0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50,0x6, +0x29,0x76,0x0, 0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e,0x7b, +0x60,0x7e,0x6b,0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b,0x70, +0x7a,0x6b,0x70,0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x2, 0xeb,0x30, +0xe1,0x7, 0xb, 0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x39,0x74,0x1, +0x39,0xb7,0x0, 0x4, 0x12,0x2e,0x52,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f,0x17,0x7f, +0x6, 0x12,0x20,0xc3,0x1b,0xfd,0x7f,0x16,0x12,0x2e,0x4a,0x44,0x1, 0x7a,0x1b,0xb0, +0x7f,0x16,0x12,0x2e,0x4a,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x5, 0xa, 0x7f,0x16,0x12, +0x2e,0x4a,0x44,0x4, 0x7a,0x1b,0xb0,0xda,0x79,0x22,0x2e,0x34,0x0, 0x5, 0x7e,0x1b, +0xb0,0x22,0x74,0x6, 0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x2, 0xe6,0x6d,0xcc,0x22,0x7c, +0x7b,0x12,0xc5,0x67,0x9, 0xa2,0x27,0x72,0x7c,0xb7,0x54,0x7, 0xa, 0x3b,0x2e,0x34, +0x0, 0x5e,0x12,0x6f,0xee,0x5c,0xba,0x22,0x6c,0x0, 0x6c,0x11,0x80,0x16,0x7c,0xb1, +0x12,0x2e,0x5f,0x60,0xd, 0x12,0x2f,0x1c,0x12,0x2f,0x2d,0x40,0x5, 0x7e,0x0, 0x1, +0x80,0xa, 0xb, 0x10,0x7e,0x73,0x28,0x84,0xbc,0x71,0x38,0xe2,0x7c,0xb0,0x6c,0x77, +0x12,0xa0,0x78,0xbe,0x0, 0x1, 0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, 0x12,0xa0,0x78, +0xb4,0x1, 0x24,0x6c,0x11,0x80,0x18,0x7c,0xb1,0x12,0x2e,0x5f,0x60,0xf, 0x12,0x2f, +0x1c,0x12,0x2f,0x2d,0x50,0x7, 0x7c,0xb1,0x6c,0x77,0x12,0x2e,0xdd,0xb, 0x10,0x7e, +0x3, 0x28,0x84,0xbc,0x1, 0x38,0xe0,0x22,0x7c,0xb3,0x7e,0x70,0x1, 0x7c,0x67,0x7c, +0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e,0x24,0x0, +0x5e,0x12,0x6c,0xb9,0x7c,0x7b,0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24,0x27,0x72, +0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a,0x2e, +0x24,0x27,0x72,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0x74,0x2, 0xac,0xb1, +0x9, 0x25,0x26,0xfa,0x9, 0x35,0x26,0xfb,0x7c,0xb2,0x7c,0x73,0x22,0x7c,0xa7,0x7c, +0x7b,0x90,0x60,0xaa,0xe4,0x93,0x60,0x2, 0x7c,0xa7,0x90,0x60,0xab,0xe4,0x93,0xbc, +0xba,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x70,0x1, 0x7c,0x87,0x7c,0x9b,0x29,0xa0, +0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, 0x78,0x7, 0x29,0xa0, +0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, 0x16,0xbd,0x1, 0x48, +0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3,0x22,0xc3,0x22,0x7e, +0x70,0x1, 0x2, 0x2f,0x4a,0xca,0x3b,0x12,0xcc,0x9f,0x75,0x5b,0x0, 0x7e,0xa1,0x5b, +0x74,0x6, 0xa4,0x12,0xba,0x59,0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc,0x12,0x2f,0x7f, +0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x2f,0x47,0x50,0x1c,0x7f,0x7, 0x7c,0xbd,0x6c, +0x77,0x12,0x2f,0x4a,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12,0x2f,0x4a,0x50, +0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x5b,0xe5,0x5b,0xbe,0xb0,0x1e,0x40,0xbd, +0xe4,0xda,0x3b,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3,0x1f,0x34,0x22,0x12,0xa0, +0xb3,0x12,0x9b,0x2d,0x12,0x9a,0x7a,0x2, 0x2f,0xea,0xca,0x3b,0x12,0x2c,0x2b,0x7e, +0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0xd2,0x60,0x9, 0xe4,0x7a,0xb3,0x37,0xd4, +0x7a,0xb3,0x37,0x59,0x7e,0xb3,0x37,0xd2,0x70,0x6f,0x6c,0x99,0x80,0x63,0x74,0x2, +0xac,0xb9,0x9, 0x85,0x26,0xfa,0x9, 0xf5,0x26,0xfb,0x7c,0xb9,0x12,0x9f,0x11,0x40, +0x4e,0x6c,0xee,0x80,0x42,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x37,0x5a,0x9, 0xc5,0x37, +0x5b,0xa, 0x28,0xa, 0x3d,0x12,0x30,0x9c,0x78,0x2b,0xa, 0x2f,0xa, 0x3c,0x12,0x30, +0x9c,0x78,0x22,0x7c,0xb9,0x12,0x30,0xa4,0x7e,0x14,0x62,0x31,0x7e,0x4, 0x0, 0xff, +0xb, 0xa, 0x20,0xbd,0x32,0x58,0xe, 0x7c,0xb9,0x6c,0x77,0x12,0x2e,0xdd,0x7c,0xb8, +0x7c,0x7f,0x12,0x9b,0xe2,0xb, 0xe0,0x7e,0x73,0x37,0xd4,0xbc,0x7e,0x38,0xb6,0xb, +0x90,0x7e,0x73,0x28,0x84,0xbc,0x79,0x38,0x95,0x7e,0x73,0x37,0x59,0x7a,0x73,0x37, +0xd4,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x37,0x96,0x7e,0x8, 0x37,0x5a,0x12, +0x20,0xc3,0x1b,0xfd,0xe4,0x7a,0xb3,0x37,0xd2,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21, +0x1a,0x4d,0x33,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7a,0x12,0x9e,0xf5,0x2, 0x30, +0xb6,0xe5,0x26,0x7e,0x71,0x25,0x12,0xbf,0xcb,0xb, 0x1a,0x30,0x22,0xca,0x3b,0x6d, +0xee,0x7e,0xc3,0x2a,0x6e,0x7e,0xd3,0x2a,0x6d,0x7e,0xb3,0x3, 0xeb,0xb4,0x1, 0x3, +0xe4,0x21,0xf3,0x7e,0xb3,0x28,0x84,0x70,0x2, 0x21,0x62,0x7e,0xb3,0x2a,0x3, 0x60, +0x2, 0x80,0x7f,0x7e,0xa3,0x26,0xfa,0x7e,0x73,0x26,0xfb,0x7a,0x71,0x24,0x6c,0xee, +0x6d,0xff,0x6c,0xff,0xa, 0x47,0x80,0x20,0x12,0x32,0x9, 0xbe,0x34,0x0, 0x96,0x8, +0x1d,0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x31,0xf9,0x12,0x36, +0x5e,0x58,0x3, 0x12,0x31,0xf6,0x1b,0x44,0xbe,0x44,0x0, 0x0, 0x58,0xda,0xe5,0x24, +0xa, 0x4b,0x80,0x1e,0x12,0x32,0x9, 0xbe,0x34,0x0, 0x96,0x8, 0x21,0xb, 0xe0,0xbe, +0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x31,0xf9,0x12,0x36,0x5e,0x58,0x3, 0x12, +0x31,0xf6,0x7d,0x24,0xb, 0x24,0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xd6,0xbe,0xe0, +0x3, 0x50,0x2, 0x80,0xd, 0xa, 0x2f,0x7d,0x3f,0x12,0x1e,0xb9,0xbe,0x34,0x0, 0x28, +0x8, 0x7, 0xe4,0x7a,0xb3,0x37,0x2f,0x21,0xf3,0x6d,0xdd,0xbe,0xa0,0x0, 0x28,0x8, +0x7c,0xba,0x14,0x12,0x32,0x3, 0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, 0xca,0xbd,0xc3, +0x58,0x8, 0x7c,0xba,0x4, 0x12,0x32,0x3, 0x2d,0xd3,0x7e,0x70,0x8, 0x80,0x2a,0x7e, +0x50,0x2, 0xac,0x57,0x7d,0xc2,0x2e,0xc4,0x20,0xfa,0x7d,0x1c,0x7a,0x31,0x82,0x7a, +0x21,0x83,0xe4,0x93,0x1a,0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x20,0xfb, +0x7d,0x2c,0x12,0x6c,0xb9,0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, +0xce,0x7c,0xba,0x12,0x32,0x3, 0x12,0x21,0x1a,0xbe,0x34,0xa, 0xf0,0x8, 0x4, 0x2e, +0xe4,0x0, 0x28,0xbe,0xe4,0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x37, +0x2f,0xa, 0x3b,0xbd,0x3e,0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x37,0x2f,0x7e, +0xb3,0x37,0x2f,0xda,0x3b,0x22,0x7c,0xba,0x4, 0x7c,0x79,0x12,0x30,0xb6,0x2d,0xf3, +0xb, 0xf0,0x22,0x7e,0x71,0x24,0x2, 0x30,0xb6,0x7c,0xba,0x7c,0x79,0x2, 0x30,0xb6, +0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, +0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, +0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d, +0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0x61,0x75,0x75,0x2d,0x0, +0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18,0x1f,0x70,0x7a, +0x1d,0x29,0x74,0xff,0x7e,0x34,0x1f,0x71,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x7e, +0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d,0x29, +0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12,0x2e,0x4a,0x44,0x1, 0x7a,0x1b,0xb0,0x75, +0x24,0x0, 0x80,0x6c,0x12,0xcc,0x24,0x9, 0x93,0x26,0xfb,0xe5,0x24,0x12,0x3e,0xdb, +0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, 0x39, +0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x32,0x9, 0xbe,0x35,0x2e,0x8, 0x6, 0x12,0x32, +0x9, 0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a,0x1b, +0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, 0x2, +0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, 0x7e, +0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, 0x24, +0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e,0xd, 0x29,0x12, +0x2c,0x7a,0xe5,0x2d,0xa, 0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e,0x35, +0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55,0x25,0x12,0x36,0x56,0x19,0xa3,0x2, 0xaa, +0x7e,0x55,0x27,0x12,0x36,0x56,0x19,0xa3,0x2, 0xab,0x7e,0x37,0x28,0x8a,0xbe,0x35, +0x2e,0x78,0xe, 0x7e,0x35,0x25,0x7a,0x73,0x28,0x8c,0x7e,0x35,0x27,0x7a,0x73,0x28, +0x8d,0x7e,0x37,0x2, 0xa8,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27,0x12, +0x30,0xb6,0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x2, 0xa8,0x1b,0x38, +0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x41,0x4d,0x12,0xb7,0xf8,0x7c,0xbf, +0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x2, 0x30,0xb6,0xca,0x3b,0x7f,0x70,0x7c,0xe7, +0x7c,0xdb,0x7e,0xc0,0x4, 0x7e,0xb3,0x2a,0x6d,0xf5,0x28,0x7e,0xb3,0x2a,0x6e,0xf5, +0x27,0x7e,0x34,0x62,0x10,0x12,0x83,0x38,0x6c,0xff,0x12,0xbf,0xc7,0x7f,0x51,0xe5, +0x28,0xa, 0x3b,0x1b,0x34,0xa, 0xcd,0xbd,0xc3,0x58,0x14,0xe5,0x27,0xa, 0x3b,0x1b, +0x34,0xa, 0xce,0xbd,0xc3,0x58,0x8, 0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e, +0xf0,0x10,0xb, 0x5a,0x30,0x7e,0x14,0x62,0x10,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20, +0xbd,0x32,0x8, 0xc, 0x7e,0x27,0x28,0x8a,0xbe,0x24,0x3, 0x20,0x8, 0x2, 0x81,0xe7, +0xb, 0xa, 0xc0,0x1e,0xc4,0xbd,0x3c,0x8, 0xc, 0x7e,0xc7,0x28,0x8a,0xbe,0xc4,0x3, +0x20,0x58,0x2, 0x81,0xe7,0x6c,0xaa,0x7c,0x8d,0x80,0x1e,0x7c,0x9e,0xbe,0x80,0x0, +0x48,0x13,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0xb, 0x12,0x33,0x83,0xbd,0x3d,0x58, +0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a, +0xc8,0xbd,0xc3,0x18,0xd6,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0x81,0xe7,0x6c,0xaa, +0x7c,0x8d,0x80,0x1e,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x13,0x7e,0xb3,0x2a,0x6d,0xbc, +0xb8,0x8, 0xb, 0x12,0x33,0x83,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0, +0xb, 0x80,0x1a,0x2c,0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd6,0xbc,0xca, +0x18,0x5, 0x4e,0xf0,0x2, 0x80,0x70,0x6c,0xaa,0x7c,0x9e,0x80,0x1e,0x7c,0x8d,0xbe, +0x90,0x0, 0x48,0x13,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0xb, 0x12,0x33,0x83,0xbd, +0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d, +0x32,0x1a,0xc9,0xbd,0xc3,0x18,0xd6,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x37, +0x6c,0xaa,0x7c,0x9e,0x80,0x1e,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x13,0x7e,0xb3,0x2a, +0x6e,0xbc,0xb9,0x8, 0xb, 0x12,0x33,0x83,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, +0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a,0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd6, +0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, 0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd, +0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7,0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, +0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe,0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, +0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7,0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0xca,0x3b, +0x7c,0xc7,0x7c,0xfb,0x7f,0x40,0x6d,0x33,0x7a,0x35,0x24,0x7e,0xa3,0x2a,0x6d,0x7e, +0x73,0x2a,0x6e,0x4c,0xcc,0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc, +0xbc,0x78,0x6, 0xa, 0x6c,0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, +0x80,0xb, 0x7c,0xba,0x14,0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e, +0x34,0x0, 0x6, 0xe4,0x12,0x20,0xe8,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b,0x34,0x7a, +0x4b,0x70,0x7e,0x73,0x2a,0x6e,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec, +0x80,0x1f,0x75,0x26,0x0, 0x7c,0xdf,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70, +0xa, 0x12,0x36,0x4b,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xee,0xe5,0x26,0x60,0x7, 0x1b, +0xe0,0xbe,0xe0,0x0, 0x58,0xdc,0x7c,0xec,0x80,0x26,0x75,0x26,0x0, 0x1a,0x3f,0xb, +0x34,0x7c,0xd7,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70,0xd, 0x12,0x36,0x4b, +0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xeb,0xe5,0x26,0x60,0x7, 0x1b,0xe0, +0xbe,0xe0,0x0, 0x58,0xd5,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x1f,0x75,0x26,0x0, +0x7c,0xdf,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70,0xa, 0x12,0x36,0x4b,0x1b, +0xd0,0xbe,0xd0,0x0, 0x58,0xee,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x2a,0x6e, +0xbc,0x7e,0x18,0xd9,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x24,0x75,0x26,0x0, 0x1a, +0x6f,0xb, 0x64,0x80,0xd, 0x12,0x36,0x44,0x12,0x33,0x8a,0x70,0xd, 0x12,0x36,0x4b, +0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xeb,0xe5,0x26,0x60,0xa, 0xb, 0xe0, +0x7e,0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xd4,0x7e,0x35,0x24,0x7d,0x23,0x39,0x54,0x0, +0x5, 0xda,0x3b,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0x22,0x5, 0x26,0x7e,0x35,0x24, +0xb, 0x34,0x7a,0x35,0x24,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0xa, 0x2d, +0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0xca,0x79,0x6c,0x88,0x80,0x6e,0x74,0x2, 0xac, +0xb8,0x9, 0xf5,0x26,0xfa,0x9, 0x75,0x26,0xfb,0x7a,0x71,0x24,0x7c,0xbf,0x12,0xa3, +0x84,0x50,0x56,0x6c,0xee,0x80,0x4d,0xbc,0xe8,0x68,0x47,0x12,0xcc,0x71,0x12,0x9e, +0xec,0x6c,0x99,0x90,0x60,0xaa,0xe4,0x93,0x70,0x18,0x7e,0xb3,0x2a,0x70,0x14,0xbe, +0xb1,0x26,0x78,0xe, 0xa, 0x2f,0xe5,0x25,0xa, 0x3b,0x12,0x37,0xb, 0x18,0x3, 0x7e, +0x90,0x1, 0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe,0x12,0x30,0xa4,0x7d,0xf3,0x7c,0xb8, +0x12,0x30,0xa4,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe,0x80,0x2, 0x7c,0xb8,0x6c,0x77,0x12, +0x2e,0xdd,0xb, 0xe0,0x12,0x47,0xe5,0x38,0xae,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc, +0x78,0x38,0x8a,0xda,0x79,0x22,0x7c,0xba,0x7c,0x7d,0x2, 0x30,0xb6,0x7c,0xbd,0x7c, +0x7e,0x2, 0x30,0xb6,0x7c,0xbf,0x12,0x30,0xa4,0x74,0x2, 0xac,0xbf,0x22,0x12,0x37, +0x15,0x12,0x30,0xbd,0x7a,0xb3,0x2a,0xc, 0x22,0x1a,0x3b,0x9d,0x32,0x12,0x21,0x1a, +0xbe,0x34,0x0, 0x1, 0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x36,0x94,0x6c,0x33, +0x80,0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10,0x1, 0x6c,0x0, +0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93,0x26,0xfb,0xa, +0x29,0xa, 0x32,0x12,0x37,0xb, 0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74, +0x2, 0x7a,0xb3,0x36,0x94,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc, +0xa3,0x38,0xbf,0x2, 0x37,0x66,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c,0x22,0x80,0x45, +0x74,0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e,0xa0,0x1, 0x6c, +0x99,0x80,0x2c,0xbc,0x92,0x68,0x26,0x7e,0x70,0x2, 0xac,0x79,0x9, 0x83,0x26,0xfa, +0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, 0x31,0x12,0x37,0xb, 0x18,0xb, 0xa, 0x2f,0xa, +0x30,0x12,0x37,0xb, 0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc, +0x39,0x38,0xd0,0xb, 0x20,0xbc,0x32,0x38,0xb7,0x7e,0xb3,0x37,0x2e,0xbe,0xb0,0x0, +0x28,0x12,0x14,0x7a,0xb3,0x37,0x2e,0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c, +0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x3, 0xa6,0x70,0x58,0x7e,0xb3,0x33,0xfe,0x70,0x52, +0x7e,0xb3,0x37,0xe4,0x70,0x4c,0x7e,0x37,0x39,0x11,0xbe,0x34,0x0, 0x14,0x50,0x42, +0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x28,0x84,0xbe,0xb0, +0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x26,0x85,0xbe,0xb0,0x3, 0x50, +0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x26,0xf6,0xbe,0xb0, +0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7,0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3, +0x37,0x2e,0xda,0xf8,0x22,0x12,0x62,0xd9,0x12,0x24,0x70,0x12,0x38,0x57,0x12,0x23, +0x3, 0x7e,0xb3,0x3, 0xc2,0x24,0xfd,0x68,0x9, 0xb, 0xb1,0x78,0xf4,0x12,0x3c,0x27, +0x80,0xef,0x12,0x29,0xae,0x80,0xea,0x12,0x70,0x4e,0x12,0x73,0x39,0x12,0x0, 0xa, +0x12,0xcc,0x3b,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8,0x7e,0xf, 0x6, 0xf8,0x7e, +0x1f,0x6, 0xf4,0x12,0x7f,0xfa,0x7e,0x18,0x8, 0xa, 0x7a,0x1f,0x13,0x86,0x7e,0x18, +0xd, 0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, 0x13,0x8a,0x7e,0x1f,0x13,0x86,0x12,0x78, +0x89,0x12,0x78,0x3d,0x12,0x25,0x1b,0x12,0x77,0xf3,0x12,0x38,0xf7,0x2, 0x38,0xa0, +0xe4,0x7a,0xb3,0x33,0xe4,0x7a,0xb3,0x33,0xe5,0x7a,0xb3,0x33,0xe6,0x22,0x12,0x38, +0xa0,0x12,0x38,0xe3,0x2, 0x38,0xb7,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x38,0xc0, +0x7d,0x43,0x7e,0xa3,0x33,0xe4,0xbe,0xa0,0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a, +0x59,0x43,0x33,0xe7,0x59,0x23,0x33,0xe9,0x7c,0xba,0x4, 0x7a,0xb3,0x33,0xe4,0xc3, +0x22,0xd3,0x22,0x6d,0x33,0x7e,0x24,0x6, 0xfc,0x12,0x38,0xc0,0x7e,0x34,0x0, 0x1, +0x7e,0x24,0x7, 0x7a,0x2, 0x38,0xc0,0x12,0x78,0x31,0x7e,0x24,0x0, 0x3, 0xad,0x32, +0x7e,0x8, 0x28,0xae,0x74,0xff,0x12,0x20,0xe8,0x12,0x9f,0x59,0x7e,0x8, 0x29,0xbc, +0x12,0x39,0x1f,0x7e,0x8, 0x2a,0x2, 0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x20,0xe8,0x6c, +0xaa,0x80,0x20,0x74,0x3, 0x12,0xa2,0x9a,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, +0x12,0x3b,0xeb,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, +0x28,0xb, 0xa0,0x12,0x39,0x49,0x38,0xdb,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba, +0x22,0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x80,0x19,0x7e,0x70,0xff,0x12,0x3c, +0x6, 0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19,0xb4,0x1f,0x46,0x19,0xb4, +0x1f,0x50,0xb, 0xa0,0x12,0x39,0x49,0x38,0xe2,0x7e,0x73,0x2a,0x2, 0xa5,0xbf,0x0, +0x23,0x7e,0xb3,0x39,0xf9,0x70,0x2, 0x61,0x60,0x6c,0xaa,0x80,0x10,0x7e,0x44,0x7f, +0xff,0x12,0x3c,0x10,0x79,0x40,0x0, 0x14,0x12,0x3b,0xfd,0xb, 0xa0,0x12,0x39,0x49, +0x38,0xeb,0x61,0x60,0x7e,0xb3,0x39,0xf9,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38,0x6c, +0xaa,0x80,0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x28,0xae,0x12,0x3c,0x10,0x79, +0x30,0x0, 0x14,0x49,0x34,0x28,0xb0,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74, +0x1, 0xa, 0x3a,0x19,0xb3,0x1f,0x34,0x19,0xa4,0x28,0xb2,0xb, 0xa0,0x7e,0xb3,0x2a, +0x2, 0xbc,0xba,0x38,0xce,0x61,0x60,0x6c,0xaa,0x80,0x17,0x12,0x3b,0xeb,0x3e,0x34, +0x59,0x43,0x15,0x4e,0x59,0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15,0x78, +0xb, 0xa0,0x12,0x39,0x49,0x38,0xe4,0x6c,0xaa,0x80,0x3d,0x6c,0xff,0x80,0x32,0x7e, +0x70,0x2, 0xac,0x7f,0x7f,0x6, 0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f,0xff, +0x68,0x1d,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x14,0x12,0x3b,0xf5,0x59,0x32, +0x15,0x4e,0x69,0x30,0x0, 0x28,0x59,0x32,0x15,0x50,0x12,0x3c,0x1a,0x80,0x7, 0xb, +0xf0,0x12,0x3b,0xe3,0x38,0xc9,0xb, 0xa0,0x7e,0xb3,0x39,0xf9,0xbc,0xba,0x38,0xbb, +0x6c,0xaa,0x80,0x24,0xa, 0x3a,0x9, 0xb3,0x1f,0x46,0xb4,0xff,0x19,0x6c,0xff,0x80, +0x10,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, 0x12,0x3c,0x1a,0x80,0x7, 0xb, +0xf0,0x12,0x3b,0xe3,0x38,0xeb,0xb, 0xa0,0x12,0x39,0x49,0x38,0xd7,0x6c,0xaa,0x80, +0x1a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x28,0xae,0x12,0x3b,0xf5,0x59,0x42,0x15, +0x76,0x49,0x33,0x28,0xb0,0x59,0x32,0x15,0x78,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc, +0xba,0x38,0xde,0x7e,0x34,0x15,0x4e,0x7a,0x37,0x1f,0x40,0x7e,0x34,0x15,0x76,0x7a, +0x37,0x1f,0x42,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x44,0x7e,0x73,0x39,0xf9,0x7a, +0x73,0x1f,0x3e,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x1f,0x3f,0x7e,0x8, 0x1f,0x3e,0x12, +0x4, 0xad,0x6c,0xaa,0x80,0x59,0x7e,0x70,0xff,0x6c,0xff,0x80,0x19,0x7e,0x50,0x2, +0xac,0x5f,0x49,0x12,0x15,0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, 0x73, +0x1f,0x46,0x80,0x7, 0xb, 0xf0,0x12,0x3b,0xe3,0x38,0xe2,0xbe,0x70,0xff,0x68,0x2d, +0x12,0x3c,0x6, 0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34,0x7e,0x90,0x9, 0xac,0x9a, +0x49,0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20,0x0, +0x14,0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12,0x3b,0xfd,0xb, 0xa0,0x7e, +0x63,0x2a,0x2, 0xbc,0x6a,0x38,0x9f,0x6c,0xaa,0x80,0x20,0xa, 0x3a,0x9, 0xb3,0x1f, +0x34,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x3b,0xeb,0x7f,0x6, 0x2d,0x13,0x79,0x40,0x0, +0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x12,0x39,0x49,0x38,0xdb, +0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x39,0xf9,0x6c,0xaa,0x80,0x68,0xa, 0x3a,0x9, 0xb3, +0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x3b,0xdc,0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, 0x74, +0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x3b,0xdc,0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, 0x6, +0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a,0x1b,0xb0,0x80, +0x27,0x12,0x3b,0xdc,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14,0x74, +0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1,0x28, +0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x3b,0xdc,0x7e,0x1b,0xb0,0x39,0xb1, +0x0, 0xa, 0xb, 0xa0,0x12,0x39,0x49,0x38,0x93,0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d, +0x7d,0x2c,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x22,0x7e,0x44,0x7f,0xff,0x7e, +0x70,0x2, 0xac,0x7a,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x22,0x7f,0x6, 0x2d, +0x12,0x79,0x40,0x0, 0x28,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x28,0xb2,0x22, +0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0xa, 0x3a,0x19,0xf3,0x1f,0x46, +0x74,0x1, 0x19,0xb4,0x1f,0x50,0x22,0x12,0x5e,0xb2,0x12,0x80,0x6e,0x7e,0xb3,0x3, +0xc2,0xb4,0x1, 0x6b,0x12,0xc1,0xb6,0x7e,0x34,0x60,0xa5,0x12,0x23,0x74,0x12,0x26, +0x77,0x12,0x8f,0xfd,0x12,0x81,0x86,0x12,0x28,0xa0,0x50,0xde,0x12,0x6e,0x5f,0x12, +0x6f,0xa, 0x7e,0xb3,0x3, 0xbf,0xb4,0x1, 0x4, 0xe4,0x12,0x3c,0xb1,0x12,0x45,0xb9, +0x12,0x3e,0xe5,0x40,0xc5,0x12,0x84,0x67,0x12,0x3e,0xe5,0x40,0xbd,0x12,0x36,0xfe, +0x12,0x2a,0x31,0x12,0x0, 0x66,0x12,0x45,0xeb,0x12,0x87,0xfe,0x12,0x91,0x36,0x12, +0x39,0x51,0x12,0x94,0x0, 0x12,0x3e,0xfd,0x12,0x96,0xe8,0x12,0x83,0x40,0x12,0xc7, +0x76,0x12,0x3c,0xb9,0x12,0x62,0xab,0x12,0x8b,0x36,0x12,0x59,0x4e,0x80,0x8b,0x12, +0x6f,0xd5,0x2, 0x3c,0xa5,0x7e,0xb3,0x3, 0xbf,0xb4,0x1, 0x4, 0xe4,0x2, 0x3c,0xb1, +0x22,0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff, +0x12,0x3e,0xd4,0x75,0x28,0x3, 0x6c,0xee,0x7e,0x48,0x29,0xbc,0x7e,0xb3,0x2a,0xb, +0x70,0xe, 0x7e,0xb3,0x2a,0x7, 0x70,0x8, 0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0xc1,0xab, +0x30,0x10,0x6, 0x7e,0x68,0x35,0xe4,0x80,0x4, 0x7e,0x68,0x35,0xa6,0x7f,0x6, 0x12, +0xcc,0x8c,0x7e,0x73,0x2a,0x4, 0x7a,0x6b,0x70,0x6c,0xdd,0xc1,0x5c,0x74,0x9, 0xac, +0xbd,0x9, 0xc5,0x29,0xc, 0x7c,0xbc,0x54,0xf, 0x12,0x3e,0xdb,0xf5,0x28,0x7c,0xbc, +0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, 0xc1,0x5a,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, +0xc1,0x5a,0x7e,0x8, 0x0, 0x28,0x7c,0xbc,0x12,0x97,0x41,0x50,0x2, 0xc1,0x5a,0x74, +0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xd, 0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29, +0xe, 0xc4,0x54,0xf0,0xf5,0x26,0x7e,0x73,0x2a,0x4d,0xbc,0x7c,0x28,0x54,0x7e,0xb3, +0x2a,0x9, 0x70,0x2a,0x75,0x29,0xf, 0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x35, +0x92,0x6d,0x22,0x74,0x1, 0x12,0x81,0xf0,0x75,0x29,0x20,0x7e,0x8, 0x0, 0x26,0xa, +0x3c,0x2e,0x34,0x35,0x9c,0x6d,0x22,0x74,0x10,0x12,0x81,0xf0,0x80,0xe, 0xa, 0x3c, +0x9, 0xb3,0x35,0x92,0xf5,0x25,0x9, 0xb3,0x35,0x9c,0xf5,0x26,0xa, 0x3c,0x12,0x3e, +0xdd,0xb4,0x1, 0xe, 0xe4,0xa, 0x3c,0x19,0xb3,0x35,0x92,0x19,0xb3,0x35,0x9c,0x12, +0x3e,0xd4,0x7e,0xb3,0x2a,0x64,0xb4,0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd, +0x9, 0xb5,0x29,0xc, 0xbe,0xb0,0xff,0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, 0xac, +0x9d,0x49,0xb4,0x29,0x8, 0x49,0xa4,0x29,0xa, 0xe5,0x28,0xb4,0x1, 0x2c,0x75,0x27, +0x0, 0x80,0x1d,0x7e,0x71,0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x36,0x26,0x54,0xf, +0xbc,0xbc,0x78,0xa, 0x49,0xb3,0x36,0x22,0x49,0xa3,0x36,0x24,0x80,0xc, 0x5, 0x27, +0x90,0x60,0x99,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd9,0x5e,0xb4,0xf, 0xff,0x5e,0xa4, +0xf, 0xff,0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x2d,0xa5, +0xbe,0x70,0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x24,0xb, 0xf0, +0xe5,0x28,0xa, 0x5b,0x12,0xc2,0x45,0x2d,0xb5,0x80,0x4, 0x2e,0xb4,0xc0,0x0, 0x7e, +0x70,0x6, 0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, 0x7f,0x6, 0x2d,0x13, +0x79,0xa0,0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0,0x0, 0x6, 0xe5,0x26, +0x2d,0x3d,0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0,0x7e,0x73,0x2a,0x4d, +0xbc,0x7d,0x28,0x2, 0x81,0xfd,0xe5,0x24,0x39,0xb6,0x0, 0x1, 0x7e,0xb3,0x3, 0xeb, +0xb4,0x1, 0x9, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x17,0x80,0xd, 0xbe,0xf0,0x0, 0x38, +0x6, 0x7e,0xb3,0x2a,0x8, 0x60,0xa, 0xb2,0x10,0x12,0x80,0xa1,0x74,0x1, 0x12,0x3c, +0xb1,0x7e,0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x39,0x1f,0xe4,0x7a,0xb3,0x2a, +0xb, 0x7a,0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4,0x12,0x3c,0xb1,0x12, +0x94,0x58,0xca,0x59,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x36,0x22,0x12,0x20,0xc3,0x1b, +0xfd,0x4c,0xff,0x78,0xc, 0x12,0x78,0x31,0x7e,0x8, 0x36,0x22,0x74,0xff,0x12,0x20, +0xe8,0xda,0x3b,0x22,0x75,0x25,0x0, 0x75,0x26,0x0, 0x22,0xa, 0x3b,0x2d,0x39,0x7d, +0x28,0x7e,0x1b,0xb0,0x22,0xc2,0x3, 0x7e,0xb3,0x16,0x91,0x60,0x6, 0x7e,0xb3,0x16, +0x90,0x70,0x7, 0x12,0xba,0x25,0x28,0x2, 0xd2,0x3, 0xa2,0x3, 0x22,0xca,0xf8,0x7e, +0xa3,0x2a,0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, 0xbe,0xb0,0x0, 0x28,0x13, +0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, 0x7a, +0xb3,0x2a,0xb, 0x12,0x94,0x58,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x8, +0x12,0x20,0xc3,0x1b,0xfd,0x90,0x61,0x35,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x23,0x6c, +0xff,0x80,0x1a,0x12,0x96,0xa8,0x12,0x82,0x32,0x74,0x9, 0xac,0xbf,0x59,0x35,0x29, +0x8, 0x49,0x35,0x28,0xb0,0x12,0x5b,0x81,0x12,0x83,0xf0,0xb, 0xf0,0x12,0x3b,0xe3, +0x38,0xe1,0xda,0xf8,0x22,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x2a,0x6f,0xf5,0x27,0x7e, +0xb3,0x2a,0x70,0xf5,0x28,0x75,0x2b,0x0, 0x7e,0xb3,0x16,0x91,0xbe,0xb0,0x1, 0x68, +0x11,0x60,0x3, 0x2, 0x40,0xa5,0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x2, 0x80,0x3, 0x2, +0x40,0xa5,0x6c,0xee,0x2, 0x40,0x99,0x12,0xcc,0x4d,0x75,0x25,0x2, 0x75,0x26,0x2, +0x7c,0xbe,0x12,0x6c,0xe4,0xd2,0x3, 0x12,0x6e,0x25,0x4c,0xdd,0x68,0x7, 0xe5,0x27, +0x12,0xcc,0x44,0x48,0x3, 0x75,0x25,0x1, 0x4c,0xcc,0x68,0xc, 0xe5,0x28,0xa, 0x2b, +0x1b,0x24,0xa, 0x3c,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, 0x75,0x24,0x0, 0x80,0x30, +0xe5,0x24,0xbc,0xbe,0x68,0x28,0x12,0xcc,0x24,0x7a,0xa1,0x29,0x9, 0xb3,0x26,0xfb, +0xf5,0x2a,0xa, 0x2a,0xa, 0x3d,0x12,0xcc,0x95,0x18,0x13,0xe5,0x2a,0xa, 0x2b,0xa, +0x3c,0x12,0xcc,0x95,0x18,0x8, 0x75,0x25,0x1, 0x75,0x26,0x1, 0x80,0x7, 0x5, 0x24, +0x12,0x9e,0xe4,0x38,0xcb,0x7c,0xbd,0x7c,0x7c,0x12,0x2f,0x2d,0x50,0x8, 0x12,0x40, +0xbb,0x12,0x3e,0xd4,0x80,0x1b,0x12,0x0, 0x6e,0x50,0x16,0x7e,0x73,0x33,0x4a,0xbc, +0x7d,0x78,0xe, 0x7e,0x73,0x33,0x4b,0xbc,0x7c,0x78,0x6, 0x75,0x25,0x3, 0x75,0x26, +0x3, 0x4c,0xdd,0x78,0x2, 0x80,0x7, 0xe5,0x27,0x14,0xbc,0xbd,0x78,0xd, 0x12,0x40, +0xa8,0xb, 0xa, 0x30,0x9e,0x34,0x0, 0x32,0x1b,0xa, 0x30,0xe5,0x28,0x14,0xbc,0xbc, +0x78,0x2, 0x80,0x4, 0x4c,0xcc,0x78,0xd, 0x12,0x40,0xa8,0xb, 0xa, 0x30,0x9e,0x34, +0x0, 0x3c,0x1b,0xa, 0x30,0xe5,0x25,0x7e,0x71,0x26,0x7c,0x6e,0x7c,0x5f,0x7e,0x41, +0x2b,0x12,0x40,0xe9,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x16,0x7e,0x70,0x9, 0xac, +0x7e,0x7d,0x13,0x2e,0x14,0x27,0x76,0x6d,0x0, 0x2e,0x34,0x27,0x78,0x6d,0x22,0x12, +0x81,0x49,0x12,0x40,0xbb,0xb, 0xf0,0xb, 0xe0,0x12,0x47,0xe5,0x28,0x3, 0x2, 0x3f, +0x97,0x7a,0xf3,0x28,0x84,0xda,0x3b,0x22,0x7e,0x73,0x2a,0x6e,0xac,0x7d,0xa, 0x2c, +0x2d,0x32,0x3e,0x34,0x7e,0xf, 0x13,0x8a,0x2d,0x13,0x22,0x12,0x6f,0xb0,0x60,0x28, +0x6c,0x22,0x80,0x1c,0x7c,0xb2,0x12,0x6c,0xc2,0x50,0x13,0x7c,0xb2,0x12,0x6d,0xf2, +0x7d,0x3, 0x12,0x6f,0xa8,0x49,0x55,0x39,0xdf,0x7d,0x40,0x12,0xba,0x4d,0xb, 0x20, +0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xdc,0x22,0xca,0x3b,0x7a,0x41,0x2c,0x12,0xcc, +0x9f,0x74,0x9, 0xac,0xbf,0x7d,0x95,0x2e,0x94,0x27,0x76,0x6d,0x88,0x7e,0xe7,0x2a, +0x66,0xe4,0x39,0xb4,0x0, 0x6, 0x12,0xcc,0x71,0xf5,0x37,0x9, 0xb3,0x26,0xfb,0xf5, +0x38,0x7e,0x73,0x2a,0x6e,0x7c,0x6d,0x7e,0x8, 0x0, 0x3b,0x12,0x43,0x33,0xf5,0x39, +0xe5,0x37,0x7e,0x73,0x2a,0x6d,0x7c,0x6c,0x7e,0x8, 0x0, 0x3a,0x12,0x43,0x33,0x7c, +0xab,0xe5,0x3a,0x7e,0x71,0x3b,0x12,0xbf,0xcb,0x7d,0xf3,0x7a,0xf5,0x43,0x7e,0xf4, +0x15,0x9e,0x7a,0xf5,0x45,0x85,0x3a,0x3d,0x85,0x3b,0x3e,0x7a,0xa1,0x3f,0x85,0x39, +0x40,0x7e,0xb3,0x2a,0x59,0xf5,0x41,0x75,0x42,0x0, 0xe5,0x2c,0xb4,0x1, 0x8, 0xe5, +0x41,0x1e,0xb0,0x1e,0xb0,0xf5,0x41,0x7e,0x8, 0x0, 0x3d,0x12,0x47,0xf4,0x7d,0x23, +0x6d,0x33,0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x15,0xa2,0x6d,0x22, +0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x2d,0x7e,0x37,0x15, +0xa6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8,0x2f,0x10,0x7a,0x1d,0x31,0x7f,0x65, +0xa, 0x4c,0xe5,0x37,0xa, 0x5b,0x9d,0x54,0xf5,0x35,0x41,0x83,0xa, 0x4d,0xe5,0x38, +0xa, 0x5b,0x9d,0x54,0xf5,0x36,0x41,0x6d,0xe5,0x35,0xbe,0xb0,0x0, 0x58,0x2, 0x41, +0x6b,0x7e,0x73,0x2a,0x6d,0xbe,0x71,0x35,0x18,0x2, 0x41,0x6b,0xe5,0x36,0xbe,0xb0, +0x0, 0x58,0x2, 0x41,0x6b,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x36,0x18,0x2, 0x41,0x6b, +0xe5,0x35,0x7e,0x71,0x36,0x12,0x30,0xb6,0x7e,0x53,0x2a,0x59,0xa, 0x25,0x7d,0xf3, +0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x73,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e,0x34, +0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5,0x37,0xa, 0x2b,0xe5,0x35,0x12, +0x37,0x9, 0x18,0xb, 0xe5,0x38,0xa, 0x2b,0xe5,0x36,0x12,0x37,0x9, 0x8, 0x4c,0xe5, +0x35,0x7e,0x71,0x36,0x7c,0x6e,0x12,0xba,0x66,0xf5,0x3c,0xb4,0x2, 0x6, 0x7d,0x3f, +0xe, 0x34,0x9d,0xf3,0xe5,0x3c,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3c,0xb4,0x1, 0x2b, +0x12,0x43,0x13,0xe5,0x35,0x12,0x43,0x1a,0x7e,0x1d,0x2d,0x9f,0x10,0x7a,0x1d,0x2d, +0x12,0x43,0x13,0xe5,0x36,0x12,0x43,0x1a,0x7e,0x1d,0x31,0x9f,0x10,0x7a,0x1d,0x31, +0x12,0x43,0x13,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61,0x5, 0x36,0xa, 0x2d,0xe5, +0x38,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x36,0x1a,0x3b,0xbd,0x32,0x18,0x2, 0x21, +0xb8,0x5, 0x35,0xa, 0x2c,0xe5,0x37,0xa, 0x3b,0x2d,0x32,0x1a,0x37,0xe5,0x35,0x1a, +0xfb,0xbd,0xf3,0x18,0x2, 0x21,0xac,0xbe,0x58,0x0, 0x0, 0x78,0x2, 0xb, 0x5c,0xbe, +0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2d,0x7f,0x5, 0x12,0x43,0x24,0x1b, +0x4a,0x30,0x7e,0x1d,0x31,0x7f,0x6, 0x12,0x43,0x24,0x79,0x34,0x0, 0x2, 0x7e,0xb3, +0x2a,0x65,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80,0x0, 0x14,0x78, +0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d,0x39,0x74,0x0, +0x5, 0x74,0x9, 0xac,0xbe,0x9, 0x75,0x27,0x7c,0x39,0x74,0x0, 0x6, 0xbe,0x70,0xf, +0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0x7e,0xa1,0x37,0x7e,0x70,0x9, 0xac,0x7f, +0x19,0xa3,0x27,0x7d,0x7e,0xa1,0x38,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x27,0x7e, +0xda,0x3b,0x22,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x22,0x1a,0x1b,0x1a,0x2, 0x12,0x1e, +0xeb,0x7f,0x1, 0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x1f,0x7, 0x2e,0x18, +0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e, +0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d, +0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28, +0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f, +0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, +0xb0,0x7c,0xba,0xda,0xf8,0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0,0x34,0x38,0x2, 0x81, +0x97,0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0xa1,0xb6,0xbe,0xa0,0x36,0x68, +0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0x8, +0x2e,0x37,0x34,0x8a,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, 0xa1,0xb6,0x75,0x1a, +0x36,0xa1,0xb6,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78,0x1b,0x7e,0xf3,0x38, +0xd4,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd4,0xbe,0xa0,0x39,0x78,0x3, 0x75,0x1a,0x38, +0xa, 0x3f,0x9, 0xb3,0x2b,0x21,0xa1,0xb6,0xbe,0xa0,0x3a,0x68,0x5, 0xbe,0xa0,0x3b, +0x78,0x1b,0x7e,0xf3,0x38,0xd6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd6,0xbe,0xa0,0x3b, +0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44,0xa1,0xb6,0xbe,0xa0,0xfb, +0x78,0x6, 0x7e,0xb3,0x2b,0x12,0xa1,0xb6,0xbe,0xa0,0x5e,0x78,0x26,0x7e,0xf, 0x33, +0xc7,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, +0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c,0xa7,0x4c,0xba,0x44, +0x80,0xa1,0xb6,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78,0x1b,0x7e,0xf3,0x38, +0xd8,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd8,0xbe,0xa0,0x3d,0x78,0x3, 0x75,0x1a,0x3c, +0xa, 0x3f,0x9, 0xb3,0x2a,0x7a,0xa1,0xb6,0xbe,0xa0,0x3e,0x68,0x5, 0xbe,0xa0,0x3f, +0x78,0x1b,0x7e,0xf3,0x38,0xda,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xda,0xbe,0xa0,0x3f, +0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d,0xa1,0xb6,0xbe,0xa0,0x40, +0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x38,0xb0,0xa1,0xb6,0xbe, +0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x38,0xf5,0x7c,0xbf,0x4, +0x7a,0xb3,0x38,0xf5,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1a,0x4e,0xa, 0x3f,0x2e,0x37, +0x34,0x88,0x7e,0x39,0xb0,0xa1,0xb6,0xbe,0xa0,0x51,0x68,0x5, 0xbe,0xa0,0x52,0x78, +0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e,0xb3,0x39,0x0, 0xa, +0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x39,0x0, 0xbe,0xa0,0x52, +0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0xa1,0xb6,0xbe,0xa0,0x5c,0x68,0x5, 0xbe,0xa0, +0x5d,0x78,0x1a,0x7e,0xf3,0x38,0xc9,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xc9,0xbe,0xa0, +0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0xae,0xd8,0xa1,0xb6,0xbe,0xa0,0x60, +0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x33,0xdc,0xa1,0xb6,0xbe, +0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x7e,0xbe,0xa0,0xf4,0x68,0x5, 0xbe,0xa0,0xf5, +0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, 0x9, 0xb3,0x34,0x90, +0xbe,0xa0,0xf5,0x78,0x61,0x75,0x1a,0xf4,0x80,0x5c,0xbe,0xa0,0xf0,0x68,0x5, 0xbe, +0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80,0x49,0xbe,0xa0,0xf2, +0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14,0x7e,0x1f,0x34,0x8c, +0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56,0x80,0x28,0x7d,0x53, +0x80,0x24,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x1b,0xbe,0xa0,0xf7,0x78,0xd, +0x7e,0x34,0x62,0x4e,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x50,0x80,0x9, 0xbe,0xa0,0xfd, +0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x12,0x47,0x85,0x12,0x7, 0xfb,0x12, +0x45,0xda,0x90,0x60,0xa7,0xe4,0x93,0x60,0x8, 0x30,0x14,0x5, 0x12,0x40,0xbb,0xc2, +0x14,0x22,0x7e,0x73,0x2a,0x6b,0x2e,0x70,0xff,0x22,0x12,0x45,0xd2,0x40,0xb, 0x12, +0x23,0xea,0xe4,0x7a,0xb3,0x39,0xf6,0x2, 0x47,0x8b,0x22,0xca,0x3b,0x7e,0x73,0x3, +0xdf,0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e,0x33,0x3, 0xe1,0xa, 0x13,0x6d,0x0, +0x7a,0xd, 0x2a,0x7e,0x33,0x3, 0xe0,0xa, 0x93,0x6d,0x88,0x7e,0x33,0x3, 0xe2,0xa, +0x73,0x6d,0x66,0x7e,0x14,0x61,0x37,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x40,0x12,0x46, +0xb1,0x7a,0x1d,0x26,0x12,0x87,0xe3,0xb, 0x1a,0x50,0x7e,0x1d,0x2a,0x7d,0x15,0x12, +0x46,0xb3,0x7a,0x1d,0x2a,0x7f,0x14,0x12,0x46,0xb1,0x7f,0x41,0x7f,0x13,0x7d,0x15, +0x12,0x1e,0xfc,0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12,0x45,0xd2,0x50,0x60,0x7e,0xb3, +0x16,0x91,0xb4,0x1, 0x59,0x75,0x2e,0x0, 0x80,0x4b,0x7e,0xa1,0x2e,0x74,0x9, 0xa4, +0x49,0x35,0x27,0x76,0x12,0x82,0x32,0x7a,0x35,0x24,0x7e,0xa1,0x2e,0x74,0x9, 0xa4, +0x49,0x35,0x27,0x78,0x12,0x5b,0x81,0x7d,0xa3,0x7e,0x35,0x24,0x6d,0x22,0x7e,0xd, +0x26,0xbf,0x10,0x40,0x17,0x7d,0x5a,0x6d,0x44,0x7e,0xd, 0x2a,0xbf,0x20,0x40,0xc, +0xbf,0x14,0x38,0x8, 0x7d,0x3a,0x6d,0x22,0xbf,0x13,0x28,0x7, 0xe5,0x2e,0x6c,0x77, +0x12,0x2e,0xdd,0x5, 0x2e,0x7e,0x73,0x28,0x84,0xbe,0x71,0x2e,0x38,0xac,0xda,0x3b, +0x22,0x7d,0x14,0x12,0x1e,0xfc,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x22,0xca,0x79,0x7c, +0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c,0xb4,0x12,0x97,0x95,0x7d,0x3, 0x7e,0xb3, +0x33,0x49,0xb4,0x1, 0x1a,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb5,0xbe,0x73,0x33, +0x4a,0x78,0xc, 0x9, 0x75,0x28,0xb6,0xbe,0x73,0x33,0x4b,0x78,0x2, 0x1e,0x4, 0x74, +0x9, 0xac,0xbf,0x12,0x96,0xb1,0x12,0x47,0x7d,0x7d,0x30,0xad,0x31,0x12,0x46,0xb6, +0x7d,0x13,0x5d,0x1e,0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x29,0x62,0x74,0x9, 0xac, +0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x29,0x62,0x7d, +0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34,0x29,0x62,0x9d,0xf1,0x1b,0x38, +0xf0,0x74,0x9, 0xac,0xbf,0x12,0x47,0x71,0x7d,0x30,0xad,0x31,0x12,0x46,0xb6,0x7d, +0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49,0x32,0x29,0x64,0x74,0x9, 0xac,0xbe, +0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d,0x2, 0x2e,0x4, 0x29,0x64,0x2d,0x13, +0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x29,0x64,0x9d,0x31,0x1b,0x28,0x30,0xda,0x79, +0x22,0x49,0x25,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xb0,0x9d,0x32,0x12, +0x21,0x1a,0x7d,0x13,0x22,0x12,0x47,0xd3,0x2, 0x47,0x8b,0xe4,0x7a,0xb3,0x28,0x93, +0x12,0xc4,0x29,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, 0x7e,0x73,0x28,0x84,0x7a,0x73, +0x28,0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8,0x12,0xcc,0x3b,0x12,0xc5,0x6e, +0x12,0x71,0xc8,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18,0x7e,0x73,0x26,0x83,0x7a,0x73, +0x26,0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26,0xf5,0x7e,0x73,0x26,0x84,0x7a,0x73, +0x26,0xf4,0x22,0x12,0x25,0xa2,0x2, 0x47,0xd9,0x12,0x45,0xd2,0x50,0x3, 0x2, 0x25, +0xca,0x22,0x2, 0x46,0xbd,0x7e,0x73,0x28,0x84,0xbc,0x7e,0x22,0x12,0x45,0xd2,0xd2, +0x18,0x2, 0x2a,0x27,0x12,0xc, 0x29,0x7e,0x37,0x15,0x9e,0x22,0x12,0xcc,0xcb,0xb4, +0x1, 0x14,0xca,0x39,0x7e,0x18,0x38,0xf0,0x7e,0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b, +0xfd,0x12,0x4a,0x95,0x80,0x12,0xca,0x39,0x7e,0x18,0x38,0xf0,0x7e,0x8, 0x2b,0x70, +0x12,0x20,0xc3,0x1b,0xfd,0x12,0x4a,0xb3,0x2, 0x48,0x2b,0x7a,0x1f,0x2a,0xfc,0x7a, +0xf, 0x2a,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x14,0x12,0x4a,0xb3,0x12,0x48,0x2b, +0x7e,0x18,0x6, 0x76,0x7a,0x1f,0x6, 0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x10,0xb4,0x1, +0x11,0x12,0x4a,0x95,0x12,0x48,0x2b,0x12,0xcc,0x3b,0x7e,0x18,0x4, 0x0, 0x7a,0x1f, +0x6, 0xf8,0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12,0x48,0x34,0x12,0x48,0x7b,0xe4, +0x12,0x0, 0x1e,0x74,0x1, 0x12,0x48,0x34,0x2, 0x48,0x7b,0xca,0x3b,0x7e,0xd3,0x2a, +0x73,0x7e,0xc3,0x2a,0x74,0x7e,0x8, 0x1f,0x44,0x12,0x6c,0x36,0x7e,0x8, 0x1f,0x8a, +0x7e,0x34,0x0, 0x46,0x12,0x20,0xe8,0x7e,0x8, 0x1f,0xd0,0x7e,0x34,0x0, 0xa, 0xe4, +0x12,0x20,0xe8,0x7e,0x8, 0x1f,0xda,0x7e,0x34,0x0, 0xa, 0x12,0x20,0xe8,0x7e,0xf3, +0x2a,0xfc,0x7e,0x18,0x2a,0xdc,0x7a,0x1d,0x24,0x7e,0x18,0x1f,0xd0,0x7a,0x1d,0x28, +0x7c,0xbd,0x7c,0x7c,0x7e,0x8, 0x2a,0xb9,0x12,0x49,0xd1,0x6c,0xee,0x80,0x2b,0xa, +0x3e,0x9, 0xa3,0x2a,0xdc,0xa, 0x3a,0x2e,0x34,0x20,0x7d,0x12,0x6f,0xee,0x7c,0xab, +0xbe,0xa0,0x1c,0x50,0x13,0xa, 0x3e,0x12,0x49,0x93,0xa, 0x4a,0x19,0xb4,0x1f,0x44, +0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f,0x8a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee, +0x80,0x24,0xa, 0x3e,0x9, 0xa3,0x2a,0xb9,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, +0x3c,0x2d,0x32,0x12,0x49,0x93,0xa, 0x4a,0x19,0xb4,0x1f,0x60,0x7e,0xb3,0x2a,0xfb, +0x19,0xb4,0x1f,0xa6,0xb, 0xe0,0xbc,0xde,0x38,0xd8,0x7e,0xb3,0x2a,0xfd,0x7e,0x8, +0x1f,0xe4,0x60,0x9, 0x7e,0x18,0x1f,0xd0,0x12,0xc1,0xeb,0x80,0x3, 0x12,0xc3,0x3, +0x6c,0xee,0x7e,0x18,0x1f,0xe4,0x7a,0x1f,0x1f,0x34,0x74,0x2, 0xac,0xbe,0x49,0x35, +0x1f,0xd0,0x7a,0x37,0x1f,0x38,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xda,0x7a,0x37, +0x1f,0x3a,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x44,0x6d,0x22,0x7a,0x1f,0x1f, +0x3c,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x8a,0x7a,0x1f,0x1f,0x40,0x7e,0x8, +0x1f,0x34,0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2, +0xda,0x3b,0x22,0x2e,0x37,0x2a,0xfe,0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x3, +0xc2,0x12,0x4f,0xfd,0x12,0x13,0xf5,0x12,0xc2,0x77,0xe4,0x12,0xa, 0x66,0x7e,0x24, +0x3, 0xd4,0x12,0x4f,0xed,0x74,0x1, 0x12,0x48,0x34,0x12,0x4f,0xf4,0x7e,0x34,0xd0, +0xc, 0x12,0x1, 0xe, 0x12,0x48,0x63,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13, +0x1, 0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80,0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4, +0x7e,0x7b,0x60,0xa, 0x46,0x2e,0x44,0x20,0x7d,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4, +0x93,0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, +0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, +0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, +0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80, +0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12, +0x4a,0x8e,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f, +0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60,0xe, 0x12,0x4a,0x8e,0x60,0x5, 0x3e,0x44,0x14, +0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0x4a, +0x8e,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, +0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44, +0x0, 0x1, 0x7c,0xb6,0x22,0x7e,0x1f,0x25,0xf2,0x7e,0xf, 0x25,0xee,0x22,0x7a,0xb3, +0x2b,0x0, 0x70,0x5, 0x12,0x4a,0xb3,0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x4a,0x95,0x12, +0x48,0x2b,0x22,0x7e,0x1f,0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x22,0x12,0xcc,0xcb,0xb4, +0x1, 0x17,0xca,0x39,0x7e,0x18,0x25,0xee,0x7e,0x8, 0x38,0xf0,0x12,0x20,0xc3,0x1b, +0xfd,0x12,0xcc,0xb9,0x12,0x4a,0x95,0x80,0x1a,0xca,0x39,0x7e,0x18,0x2b,0x70,0x7e, +0x8, 0x38,0xf0,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x37,0x2b,0x76,0x7a,0x37,0x34,0x88, +0x12,0x4a,0xb3,0x2, 0x48,0x2b,0xe5,0xd, 0x60,0x56,0xe5,0xd, 0x30,0xe0,0xa, 0x53, +0xd, 0xfe,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0xe5,0xd, 0x30,0xe1,0x14,0x53,0xd, +0xfd,0x7e,0xb3,0x38,0xf4,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12,0x6b,0xbb,0x12, +0x6c,0x3f,0xe5,0xd, 0x30,0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a,0xb3,0x38,0xf5,0x7e, +0xb3,0x38,0xf4,0x70,0xa, 0x74,0x1, 0x12,0x0, 0x1e,0x12,0x4a,0xb3,0x80,0x7, 0xe4, +0x12,0x0, 0x1e,0x12,0x4a,0x95,0x12,0x48,0x2b,0x7e,0xb3,0x2a,0xfc,0x2, 0x68,0x88, +0x22,0x30,0x6, 0x3b,0xc2,0x6, 0x12,0x26,0x2, 0x7e,0x73,0x38,0xb5,0x7a,0x73,0x2a, +0x4d,0x7e,0x73,0x38,0xb6,0x7a,0x73,0x2b,0x1d,0x7e,0x73,0x38,0xb6,0x7a,0x73,0x2b, +0x1, 0x7e,0xb3,0x38,0xb7,0x60,0x18,0x7e,0x34,0x0, 0x2, 0x12,0x4c,0xba,0x7e,0x34, +0x0, 0x1, 0x12,0x4c,0xba,0x6d,0x33,0x12,0x4c,0xba,0xe4,0x7a,0xb3,0x38,0xb7,0x12, +0x4a,0xf6,0x2, 0x4b,0x95,0xe5,0xc, 0x70,0x2, 0x81,0xb9,0xe5,0xc, 0x30,0xe0,0x10, +0x53,0xc, 0xfe,0x12,0x75,0x24,0x12,0x78,0x40,0x7e,0x8, 0x2a,0x6d,0x12,0x9, 0xa1, +0xe5,0xc, 0x30,0xe1,0x6, 0x53,0xc, 0xfd,0x12,0xc3,0x14,0xe5,0xc, 0x30,0xe2,0x32, +0x53,0xc, 0xfb,0x7e,0xb3,0x2b,0x12,0x60,0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x6, 0xba, +0x80,0xb, 0x7e,0xb3,0x2b,0x65,0x7e,0x73,0x2b,0x64,0x12,0xb, 0xad,0x7e,0x73,0x2b, +0x12,0x2e,0x70,0xff,0x92,0x4, 0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x2a,0x77,0x12, +0xb, 0x1e,0xe5,0xc, 0x30,0xe3,0x4c,0x53,0xc, 0xf7,0x7e,0x73,0x38,0xe2,0x7a,0x73, +0x2b,0xf, 0x12,0xaa,0x5d,0x7a,0xb3,0x2f,0xa9,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, +0x20,0x7e,0x73,0x2f,0xa9,0x7a,0x73,0x38,0xba,0x12,0x57,0xef,0x7e,0x8, 0x2a,0x6d, +0x12,0xd, 0x72,0x7e,0x73,0x38,0xe3,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b, +0x62,0xd2,0xe, 0x30,0xe, 0x7, 0x12,0x4f,0xfb,0xe4,0x12,0xa, 0x66,0x12,0x23,0x23, +0x12,0xa5,0xf5,0xe5,0xc, 0x30,0xe4,0xf, 0x53,0xc, 0xef,0x7e,0x43,0x38,0xe4,0x7e, +0x50,0xa, 0xac,0x45,0x12,0x4f,0xed,0xe5,0xc, 0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e, +0x73,0x38,0xd0,0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x38,0xd0,0xa9,0xd5, +0xcb,0x74,0xe, 0x12,0x4f,0x53,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63,0x38,0xd0,0xa, +0x26,0x2e,0x24,0x0, 0x3, 0x12,0x95,0x7, 0x7c,0x65,0x4c,0x76,0x74,0xe, 0x12,0x4e, +0xc7,0x12,0x4f,0x53,0x12,0x4f,0x5b,0x7e,0x73,0x38,0xd3,0x7a,0x73,0x2b,0x14,0x7e, +0x73,0x38,0xd2,0x7a,0x73,0x2b,0x1f,0x12,0xcc,0xc2,0xe5,0xc, 0x30,0xe5,0xa, 0x53, +0xc, 0xdf,0x7e,0xb3,0x38,0xba,0x2, 0x55,0x39,0x22,0xca,0xd8,0xca,0x79,0x7d,0xd3, +0x90,0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90,0x60,0x51,0xe4,0x93,0x7c,0x8b,0xa, 0x38, +0xa, 0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c,0x7c,0xe7,0x12,0x26,0x73,0xa9,0xd0,0xc4, +0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x4f,0x53,0x7c,0x8b,0x74,0x7, 0x7e,0x70,0xf, 0x12, +0x4f,0x58,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x33,0xcb,0x79,0x51,0x0, 0x6, 0x7e,0x54, +0x0, 0x80,0x7e,0x1f,0x33,0xcb,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f, +0x33,0xcb,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78,0xb, 0x7e,0x1f,0x33,0xcb, +0x12,0x4e,0xbf,0x44,0x1, 0x80,0x20,0x7e,0x1f,0x33,0xcb,0x12,0x4e,0xbf,0x44,0x8, +0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x33,0xcb,0x78,0x7, 0x12,0x4e,0xbf,0x54,0xfb, +0x80,0x5, 0x12,0x4e,0xbf,0x44,0x4, 0x12,0x4f,0xc2,0x69,0xe1,0x0, 0x84,0x69,0x51, +0x0, 0x90,0x7d,0xf5,0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3, +0x3, 0xcc,0xbe,0xb0,0x6, 0x40,0x3, 0xb4,0xff,0x1d,0x7e,0x1f,0x33,0xc7,0x2e,0x34, +0x0, 0x84,0xb, 0x1a,0x50,0x54,0xe6,0x12,0x4f,0xc2,0x2e,0x34,0x0, 0x84,0xb, 0x1a, +0x50,0x4e,0x54,0x1, 0xa4,0x80,0x1b,0x7e,0x1f,0x33,0xc7,0x2e,0x34,0x0, 0x84,0xb, +0x1a,0x50,0x5e,0x54,0xfe,0xe6,0x12,0x4f,0xc2,0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50, +0x44,0xa4,0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x2d,0x7e,0x1f,0x33,0xcb,0x12, +0x4e,0xbf,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xcb,0x12,0x4e,0xbf, +0x44,0x50,0x1b,0x1a,0x50,0x7e,0x34,0x0, 0x2, 0x12,0x4f,0xa3,0x12,0x58,0xa1,0x12, +0x4f,0xca,0x7a,0x37,0x34,0x90,0xc1,0x7b,0x6c,0xdd,0xc1,0x75,0x4c,0xdd,0x78,0x4, +0x6c,0x99,0x80,0x2b,0xbc,0xfd,0x40,0x12,0xa, 0xcd,0x9, 0x9c,0x2a,0xb8,0xbe,0x90, +0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, 0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3, +0x9, 0x9c,0x2a,0xdb,0xbe,0x90,0x1c,0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x7e, +0x1f,0x33,0xcb,0x12,0x4e,0xbf,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0xa, 0xc9,0x3e, +0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x7e,0x1f,0x33,0xcb,0x12,0x4e,0xbf,0x4d,0x5c, +0x1b,0x1a,0x50,0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34, +0x0, 0x2, 0x80,0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x4f,0xa3,0x12,0x58,0xa1,0xbe,0xd4, +0x0, 0x1, 0x78,0x10,0x12,0x58,0xa1,0x12,0x4f,0xca,0x74,0x2, 0xac,0xbd,0x59,0x35, +0x34,0x92,0x80,0xf, 0x12,0x4f,0xca,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59, +0x32,0x34,0x92,0xb, 0xd0,0xbc,0xed,0x28,0x2, 0xa1,0xdc,0xa9,0xd5,0xcb,0x74,0x7, +0x7c,0x78,0x12,0x4f,0x58,0xa9,0xc0,0xc4,0x7e,0x1f,0x33,0xc7,0x79,0xe1,0x0, 0x84, +0x7e,0x1f,0x33,0xc7,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x33,0xcb,0x79,0x30, +0x0, 0x6, 0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x33,0xcb,0x79,0x30, +0x0, 0x10,0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x2e, +0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xca,0x79,0xa9, +0xd5,0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x4e,0xc7,0x74,0xf, 0x12,0x4f,0x53,0x7c, +0xfb,0x74,0xf, 0x7c,0x7f,0x5e,0x70,0xfe,0x12,0x4e,0xc7,0x74,0xc, 0x12,0x4f,0x53, +0x7c,0xfb,0x54,0x7f,0x68,0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x4e,0xc7,0x90,0x61, +0x18,0xe4,0x93,0x7c,0xab,0xbe,0xa0,0x7, 0x38,0xb, 0x12,0x4f,0x90,0x7c,0xb7,0xa, +0x7b,0xb, 0x75,0x80,0x16,0x90,0x61,0x17,0xe4,0x93,0xb4,0x1, 0xe, 0xbe,0xa0,0x7, +0x28,0x9, 0x12,0x4f,0x90,0xa, 0x77,0x2e,0x74,0x0, 0x7, 0x74,0xe, 0x7c,0x7f,0x12, +0x4e,0xc7,0x74,0x7, 0x12,0x4f,0x53,0x7c,0xfb,0x5e,0xf0,0xfb,0x90,0x60,0x2, 0xe4, +0x93,0xa, 0x3b,0x3e,0x34,0x3e,0x34,0x4c,0xf7,0x74,0x7, 0x7c,0x7f,0x12,0x4f,0x58, +0xda,0x79,0x22,0xf5,0xfd,0xe5,0xfe,0x22,0x12,0x4e,0xc7,0x75,0xfd,0xff,0xa9,0xc5, +0xcb,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x12,0x12,0x64,0x30,0xe5, +0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, 0x7e,0x71,0x27,0x12,0x4e,0xc7,0x74, +0xb, 0x7e,0x71,0x2f,0x12,0x4e,0xc7,0x74,0xc, 0x7e,0x71,0x30,0x12,0x4f,0x58,0x22, +0xa, 0x3a,0x2e,0x34,0x0, 0x3, 0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x7e, +0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e,0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x67, +0x6e,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, 0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78, +0xe6,0x22,0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xc7,0x22,0x7e,0xf, 0x33,0xcb,0x69,0x30, +0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74,0x7, +0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x7d,0x32,0x74, +0xfa,0x2, 0x12,0xd0,0x7e,0x8, 0x2a,0x6d,0x2, 0x0, 0x2e,0xc2,0xe, 0x7e,0x8, 0x2a, +0x6d,0x12,0x3, 0x8b,0x7e,0x8, 0x2a,0x6d,0x74,0x3, 0x2, 0x11,0x7a,0xca,0xf8,0x7c, +0x6b,0xa5,0xbe,0x0, 0x9, 0x7c,0xb7,0x12,0x53,0x63,0xd2,0x6, 0x41,0xae,0xa5,0xbe, +0x1, 0x3d,0x7a,0x73,0x38,0xb1,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, +0xd2,0x7, 0x41,0xae,0xa5,0xbf,0xaa,0x5, 0x12,0x54,0xc0,0x80,0x1e,0xa5,0xbf,0xab, +0xa, 0x7e,0x34,0x5, 0x7a,0x7a,0x37,0x34,0x8a,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80, +0x2, 0x41,0xae,0x7e,0x34,0x4, 0xfc,0x7a,0x37,0x34,0x8a,0x6d,0x33,0x21,0x1e,0xbe, +0x60,0x4, 0x40,0x25,0xbe,0x60,0x8, 0x38,0x20,0xd2,0x6, 0xa, 0x26,0x19,0x72,0x38, +0xb0,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, 0x41,0xae,0xa5,0xbe,0x8, 0x2, +0x80,0x2, 0x41,0xae,0x12,0x54,0xba,0x41,0xae,0xa5,0xbe,0xa, 0x9, 0x43,0xc, 0x20, +0x7a,0x73,0x38,0xba,0x41,0xae,0xa5,0xbe,0xb, 0xd, 0xd2,0x6, 0xa, 0x26,0x19,0x72, +0x38,0xb0,0x12,0x54,0xbd,0x41,0xae,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c,0x38, +0x2, 0x41,0x43,0xbe,0x60,0x1e,0x40,0x10,0xbe,0x60,0x23,0x38,0xb, 0xa, 0x26,0x19, +0x72,0x38,0xb0,0x43,0xc, 0x40,0x41,0xae,0xbe,0x60,0x15,0x40,0x1d,0xbe,0x60,0x18, +0x38,0x18,0xa, 0x26,0x19,0x72,0x38,0xb0,0xd2,0x6, 0xa5,0xbe,0x15,0x2, 0x80,0x2, +0x41,0xae,0x74,0x7, 0x7a,0xb3,0x38,0xb4,0x41,0xae,0xa5,0xbe,0x19,0x7, 0xe4,0x7a, +0xb3,0x38,0xc9,0x41,0xae,0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0x41, +0x43,0xa5,0xbe,0x2d,0x1e,0xa, 0x26,0x19,0x72,0x38,0xb0,0x20,0x7, 0x2, 0x41,0xae, +0x7e,0x63,0x38,0xdc,0x7c,0x46,0x6c,0x55,0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35, +0x8, 0x41,0xae,0xbe,0x60,0x2f,0x40,0xa, 0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, +0x41,0x43,0xa5,0xbe,0x34,0xf, 0x43,0xc, 0x10,0xbe,0x70,0x64,0x38,0x2, 0x41,0x43, +0x7e,0x70,0x64,0x41,0x43,0xbe,0x60,0x38,0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, +0x1, 0x7e,0xf3,0x38,0xd5,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd5,0xa, 0x2f,0x19,0x72, +0x2b,0x21,0xa5,0xbe,0x39,0x2, 0x80,0x2, 0x41,0xae,0x75,0x1a,0x38,0x41,0xae,0xbe, +0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21,0x43,0xc, 0x2, 0x7e,0xf3,0x38,0xd7,0x7c, +0xbf,0x4, 0x7a,0xb3,0x38,0xd7,0xa, 0x2f,0x19,0x72,0x2b,0x44,0xa5,0xbe,0x3b,0x2, +0x80,0x2, 0x41,0xae,0x75,0x1a,0x3a,0x41,0xae,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, +0x7a,0x73,0x2b,0x12,0x41,0xae,0xa5,0xbe,0x50,0x6, 0x7a,0x73,0x39,0x0, 0x41,0xae, +0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xd9, +0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd9,0xa, 0x2f,0x19,0x72,0x2a,0x7a,0xa5,0xbe,0x3d, +0x2, 0x80,0x2, 0x41,0xae,0x75,0x1a,0x3c,0x41,0xae,0xbe,0x60,0x3e,0x68,0x4, 0xa5, +0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xdb,0x7c,0xbf,0x4, 0x7a,0xb3,0x38, +0xdb,0xa, 0x2f,0x19,0x72,0x2a,0x9d,0xa5,0xbe,0x3f,0x2, 0x80,0x2, 0x41,0xae,0x75, +0x1a,0x3e,0x41,0xae,0xbe,0x60,0x40,0x40,0x10,0xbe,0x60,0x42,0x38,0xb, 0xa, 0x26, +0x19,0x72,0x38,0xb0,0x75,0xd, 0x1, 0x80,0xd, 0xa5,0xbe,0x43,0xe, 0xa, 0x26,0x19, +0x72,0x38,0xb0,0x75,0xd, 0x2, 0x12,0x47,0xfc,0x41,0xae,0xa5,0xbe,0x44,0xb, 0xa, +0x26,0x19,0x72,0x38,0xb0,0x12,0x4a,0xbc,0x80,0x74,0xbe,0x60,0x45,0x68,0x4, 0xa5, +0xbe,0x46,0x8, 0xa, 0x26,0x19,0x72,0x38,0xb0,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, +0xa5,0xbe,0x4f,0x20,0x43,0xd, 0x4, 0x7e,0xf3,0x38,0xf6,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xf6,0xa, 0x2f,0x2e,0x27,0x34,0x88,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75, +0x1a,0x4e,0x80,0x3a,0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0, +0x40,0x25,0xbe,0x60,0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7, +0xa5,0xbe,0xf3,0x1a,0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x34,0x8c, +0x2d,0x30,0x1b,0x1a,0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8, +0x22,0x7c,0x6b,0x12,0x53,0x10,0x78,0x5, 0x7c,0xb6,0x2, 0x53,0x18,0xb4,0x4, 0x5, +0x7c,0xb6,0x2, 0x50,0xd, 0x22,0x30,0x90,0x19,0xc2,0x90,0xe5,0x18,0x70,0x9, 0x75, +0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80,0x11,0x7e,0x71,0x91,0xe5,0x1a,0x12,0x52,0xb1, +0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x1a,0xe5,0x1a,0x12,0x52,0xf1,0xf5,0x91, +0x22,0x7c,0x7b,0x6c,0xaa,0x12,0x53,0x10,0x78,0x9, 0x7c,0xb7,0x12,0x53,0xf1,0x7c, +0xab,0x80,0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x43,0x86,0x7c,0xab,0x7c,0xba,0x22, +0x7e,0xb3,0x38,0xb0,0xc4,0x54,0x7, 0x22,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, +0x7c,0xba,0x12,0x53,0x63,0x80,0x2c,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, +0x7c,0xb3,0x7c,0x7a,0x12,0x80,0xc0,0x80,0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30, +0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x81,0x58,0xa5,0xbb,0x8f,0x3, +0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, 0x53,0x8e,0x74,0x1, 0x7a,0xb3, +0x39,0xf8,0x22,0x7a,0xb3,0x38,0xb0,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, 0xb4, +0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3,0x3, +0xc2,0x22,0x74,0x1, 0x7a,0xb3,0x3, 0xc2,0xe4,0x7a,0xb3,0x38,0xb0,0x22,0x24,0xab, +0x68,0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, +0x80,0x2d,0x7e,0xb3,0x39,0xf8,0xb4,0x5, 0x2a,0x12,0x4f,0x9f,0x12,0xc0,0x9b,0x2, +0x53,0xda,0x7e,0xb3,0x39,0xf8,0xb4,0x5, 0x1a,0x12,0x4f,0x9f,0x75,0xe9,0xff,0x22, +0x7e,0xb3,0x39,0xf8,0xb4,0x5, 0xc, 0x12,0x4f,0x9f,0x2, 0x53,0xd4,0x74,0x1, 0x7a, +0xb3,0x39,0xf8,0x22,0x75,0xe7,0x6b,0x2, 0x53,0xda,0xe4,0x7e,0x34,0xd7,0xfc,0x7e, +0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff, +0x22,0x70,0x5, 0x7e,0xb3,0x38,0xb0,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x1d,0x0, +0x30,0x10,0x6, 0x7e,0x18,0x35,0xa6,0x80,0x4, 0x7e,0x18,0x35,0xe4,0x7a,0x1d,0x14, +0x80,0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1d,0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d, +0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4, +0xd3,0x8, 0x6d,0x33,0x7a,0x37,0x39,0x1, 0x80,0x2, 0x15,0x1a,0x2, 0x80,0x21,0xbe, +0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x54,0x88,0xbe,0xb0,0x80,0x40,0xc, 0xbe, +0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x3, 0x1b,0x22,0xb4,0xfc,0x5, 0x7e,0xb3, +0x3, 0xc2,0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e,0xb3,0x28,0xa8,0x60,0x3, 0x4e,0xa0, +0x1, 0x7e,0xb3,0x37,0xe4,0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba,0x22,0xb4,0xfe,0x5, +0x7e,0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x39,0x6, +0x7e,0x73,0x39,0x6, 0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x6c,0xb9,0x7c,0xab,0x7c, +0xb7,0x4, 0x7a,0xb3,0x39,0x6, 0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x39,0x6, 0x6d,0x33, +0x7a,0x37,0x39,0x3, 0x75,0x1a,0xeb,0x7c,0xba,0x22,0xb2,0x86,0x22,0xb2,0x82,0x22, +0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x34,0x8a,0x22,0x12,0x54,0xc0,0x12,0xcc,0xb9,0x6d, +0x33,0x7a,0x35,0xa, 0x12,0x55,0x18,0x12,0x54,0xf2,0x74,0x50,0x7a,0xb3,0x38,0xe4, +0x7e,0x24,0x3, 0x20,0x12,0x4f,0xed,0xe4,0x12,0xcc,0x32,0x6d,0x33,0x7a,0x37,0x3, +0xfc,0x22,0x7e,0x73,0x2b,0x62,0x7a,0x73,0x38,0xe3,0x22,0xa2,0xc, 0xe4,0x33,0x7a, +0xb3,0x38,0xde,0x7e,0x73,0x38,0xe2,0xbe,0x73,0x2b,0xf, 0x68,0xa, 0xe5,0xc, 0x70, +0x6, 0x12,0x55,0x18,0x12,0x54,0xf2,0x22,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xe2, +0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xd2,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xd1, +0x7e,0x73,0x2b,0x14,0x7a,0x73,0x38,0xd3,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90, +0x61,0xcb,0xe4,0x93,0x7c,0xab,0xbe,0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff, +0x80,0xb, 0x12,0x55,0xaa,0x38,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38, +0xf1,0x80,0x1a,0xbe,0xd0,0x81,0x78,0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x55, +0xaa,0x40,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38, +0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0xa6,0xc9,0x12,0x55,0x30,0x7e,0x73,0x2b,0x1f,0x7a, +0x73,0x38,0xd2,0x12,0x55,0xc6,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xe2,0x12,0x54, +0xf2,0x7a,0xd3,0x38,0xba,0xda,0x79,0xda,0xd8,0x22,0x7e,0x90,0x5, 0xac,0x9f,0x9, +0xb4,0x26,0x33,0xbc,0xbe,0x22,0x30,0x3, 0x3, 0x12,0x55,0x30,0xa2,0x4, 0x92,0x5, +0x12,0x7c,0xdb,0x2, 0x55,0xc6,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xd1,0x22,0x74, +0x40,0x7a,0xb3,0x2b,0x20,0x12,0xae,0xc7,0x50,0x9, 0xd2,0x3, 0xd2,0x4, 0x12,0x55, +0xb6,0x80,0x1c,0x74,0x1, 0x12,0x56,0xd, 0x7e,0x43,0x38,0xcf,0x7e,0x50,0x64,0xac, +0x45,0x12,0x88,0x52,0x7a,0xb3,0x2b,0x1f,0x7e,0xf, 0x33,0xe0,0x12,0x56,0x93,0x12, +0x55,0xc6,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xd2,0x2, 0x55,0x30,0xca,0x3b,0x7c, +0xdb,0xe4,0x7a,0xb3,0x2b,0x14,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0x7e,0xc0,0xa, +0x12,0x7c,0xcc,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x1f,0x33,0xe0,0x12, +0x88,0xc6,0x7d,0x73,0xbe,0x74,0xff,0xff,0x78,0xc, 0x12,0x56,0x8a,0xb, 0xa, 0x30, +0x2e,0x34,0x0, 0x3, 0x80,0x1e,0xbe,0x74,0x80,0x0, 0x28,0xa, 0x12,0x56,0x8a,0xb, +0xa, 0x30,0xb, 0x35,0x80,0xe, 0xbe,0x74,0x40,0x0, 0x28,0xf, 0x12,0x56,0x8a,0xb, +0xa, 0x30,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xb5,0xbe,0xd0,0x1, 0x78,0x9, +0x7e,0x1f,0x33,0xe0,0x12,0x88,0x71,0x7d,0x73,0x7e,0x1f,0x33,0xcf,0x69,0x31,0x0, +0x1a,0x7a,0x73,0x2b,0x14,0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x33,0xcf,0x2e,0x14, +0x0, 0x1a,0x22,0x12,0x56,0x9d,0xb, 0x34,0x7a,0x73,0x2b,0x20,0x22,0xca,0x79,0x7f, +0x10,0x9f,0x0, 0x12,0x57,0xf7,0x4c,0xaa,0x78,0x6, 0x7e,0x34,0x0, 0x40,0x80,0x6c, +0x6c,0x99,0x80,0x38,0xa, 0xe9,0x2e,0xe4,0x60,0xac,0x7d,0x7e,0x7a,0xf1,0x82,0x7a, +0xe1,0x83,0xe4,0x93,0x7c,0x8b,0x90,0x60,0xaa,0xe4,0x93,0x70,0xe, 0x7e,0xf3,0x2a, +0x6e,0xac,0xf8,0x7e,0xb3,0x2a,0x70,0xa, 0xfb,0x2d,0xf7,0x7d,0xef,0x3e,0xe4,0x7f, +0x61,0x2d,0xde,0xb, 0x6a,0xd0,0x6d,0xcc,0x2f,0x6, 0xb, 0x90,0xbc,0xa9,0x38,0xc4, +0xbe,0x8, 0x0, 0x0, 0x78,0x2, 0xb, 0xc, 0xa, 0x5a,0x6d,0x44,0x7f,0x10,0x7f,0x2, +0x12,0x1f,0x7, 0x7f,0x1, 0xb, 0xc, 0x7e,0x34,0xc4,0x0, 0x7e,0x24,0x0, 0x9, 0x12, +0x1f,0x7, 0xbe,0x34,0x0, 0xfa,0x28,0x4, 0x7e,0x34,0x0, 0xfa,0xda,0x79,0x22,0x7e, +0xb, 0x70,0x7a,0x73,0x2b,0xf, 0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62,0x29,0x70, +0x0, 0x1, 0x7a,0x73,0x2b,0x14,0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20,0x12,0x57, +0xef,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0xd2,0x3, 0xc2,0x4, 0x2, 0x55,0xb6,0xca, +0xf8,0x6c,0xff,0x80,0x34,0x7e,0x73,0x2f,0xa9,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, +0xac,0x3f,0x12,0x57,0xcb,0xca,0x39,0x7e,0x30,0x38,0xac,0x3f,0x12,0x57,0xe4,0x12, +0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12, +0x57,0xd9,0x12,0x20,0xc3,0x1b,0xfd,0xb, 0xf0,0x90,0x61,0xcb,0xe4,0x93,0xbc,0xbf, +0x38,0xc3,0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x5, 0xac,0x23,0x12,0x57,0xcb,0xca,0x39, +0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x38,0xac,0x23,0x12,0x57,0xe4,0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x8c,0xac,0x23, +0x12,0x57,0xd9,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8,0x22,0x2e,0x14,0x26,0x33,0x6d, +0x0, 0x12,0x57,0x1f,0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x30,0x8a,0x6d,0x0, 0x7e, +0x18,0x32,0xba,0x22,0x2e,0x14,0x2f,0xaa,0x6d,0x0, 0x7e,0x18,0x34,0x0, 0x22,0x12, +0x57,0xff,0x7a,0x37,0x2b,0x1b,0x22,0x90,0x60,0xa7,0xe4,0x93,0x7c,0xab,0x22,0x7e, +0x23,0x2b,0xf, 0x7e,0x33,0x38,0xe1,0x7e,0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x0, 0xac,0x23,0x2d,0x10,0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, +0x7e,0x63,0x2b,0x10,0xbe,0x14,0xf, 0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c,0xbe,0x14, +0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x21,0xbe,0x14,0x3, 0x84,0x40,0x16,0x90,0x61,0x1b, +0xe4,0x93,0x7c,0x7b,0xbe,0x70,0x1, 0x28,0x4, 0x74,0x1, 0x80,0xb, 0x7a,0x73,0x2b, +0x10,0x80,0x9, 0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x7e,0x73,0x2b,0x10, +0xbc,0x76,0x68,0x2, 0xd2,0xe, 0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17, +0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e,0x1f,0x33,0xc7,0x69,0x51,0x0, 0x86, +0x54,0x1f,0xa, 0x1, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, +0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x1f, +0x58,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x4, 0x7e,0xf, 0x33, +0xcb,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, 0x79, +0x30,0x0, 0x12,0x22,0xca,0xd8,0xca,0x79,0x7e,0x73,0x2a,0x6e,0x7e,0xf3,0x2a,0x6d, +0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x20,0xe8,0x7e,0xb3, +0x38,0xcb,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xcc,0xbe,0x70,0x0, 0x28,0x5b,0x6c,0xdd, +0x80,0x3c,0x12,0x26,0x73,0x12,0x28,0xa0,0x6d,0x33,0x80,0x28,0x7e,0x35,0x24,0x3e, +0x34,0x49,0x33,0xd, 0xc8,0x12,0x21,0x1a,0x7a,0x35,0x26,0x7e,0x35,0x24,0x7d,0x13, +0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26,0x58,0x7, 0x7e,0x25,0x26,0x59,0x21, +0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75,0x24,0x38,0xd0,0xb, 0xd0,0x7e,0x73, +0x38,0xcc,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34, +0x7e,0x8, 0xd, 0xc8,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x7e,0x8, +0x39,0x7, 0x12,0x59,0x85,0x7e,0x8, 0x39,0xf, 0x12,0x59,0x85,0x12,0x59,0x9a,0x12, +0x59,0xa1,0x2, 0x59,0x65,0x7e,0x37,0x39,0x7, 0xbe,0x34,0x0, 0x0, 0x28,0x15,0x7e, +0x73,0x3, 0xff,0xbe,0x70,0x5, 0x50,0xc, 0x7e,0xb3,0x3, 0xeb,0x70,0x6, 0x12,0x59, +0xa8,0x12,0x5e,0xc, 0x22,0xb, 0xa, 0x30,0xe5,0x62,0xa, 0x2b,0xbd,0x32,0x28,0x4, +0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x8, 0x2b,0xb7,0x2, 0x59, +0x85,0x7e,0x8, 0x39,0xdd,0x2, 0x59,0x85,0x6d,0x33,0x7a,0x37,0x39,0x97,0x22,0xca, +0xf8,0x7e,0xa3,0x2a,0x2, 0x7e,0xb3,0x2a,0x3, 0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0, +0x1, 0x38,0x1c,0x7e,0x47,0x28,0x86,0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e, +0xf3,0x2f,0x80,0x4c,0xff,0x68,0x17,0x7e,0x47,0x2b,0xb7,0x4d,0x44,0x78,0xf, 0x12, +0x59,0xa8,0x74,0x1, 0x7a,0xb3,0x39,0x99,0x7a,0xb3,0x3, 0xc0,0x80,0x35,0x4c,0xaa, +0x78,0x36,0xb4,0x1, 0x33,0x7e,0x37,0x2b,0xb7,0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f, +0x80,0xb4,0x3, 0x1f,0x7e,0x37,0x2b,0xb7,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, +0x7a,0xb3,0x2f,0x80,0x7e,0x37,0x2f,0x98,0x7e,0x27,0x2f,0x9a,0x12,0x5a,0xc0,0x41, +0xb9,0x80,0x0, 0x12,0xc8,0x97,0x41,0xb9,0x7e,0xc7,0x29,0x8, 0x7e,0xd7,0x29,0xa, +0x4c,0xff,0x78,0x19,0x70,0x57,0xbe,0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12, +0xc8,0x32,0x12,0x5a,0xbc,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x40,0xbe,0xf0,0x1, +0x78,0x2e,0x7e,0x27,0x2f,0x88,0x9e,0x27,0x2f,0x90,0x7e,0x14,0x62,0x90,0x12,0x5b, +0x79,0xbd,0x23,0x38,0x13,0x7e,0x27,0x2f,0x96,0x9e,0x27,0x2f,0x8e,0x7e,0x14,0x62, +0x92,0x12,0x5b,0x79,0xbd,0x23,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, +0xbe,0xf0,0x3, 0x78,0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f, +0x80,0x60,0x26,0x7d,0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12, +0x5d,0x78,0xa, 0x2b,0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x5a, +0xbc,0x7a,0xc7,0x2b,0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d, +0x7d,0x42,0x7d,0x13,0x7d,0x24,0x12,0x5e,0xfe,0x7d,0x31,0x12,0xc7,0xc6,0x2, 0x5a, +0xd1,0x7e,0x3, 0x2f,0xa8,0xbe,0x0, 0xf0,0x50,0x2, 0x61,0x6a,0x61,0x5f,0x6c,0x99, +0x7e,0xb3,0x2f,0x7f,0xbe,0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f, +0x2b,0xbf,0x7a,0x1f,0x1f,0x34,0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49, +0x35,0x2b,0xbf,0x49,0x25,0x2b,0xc1,0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12, +0x5d,0x78,0x7c,0x1b,0x7e,0x3, 0x2f,0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70, +0x4, 0xac,0x78,0x2e,0x34,0x2b,0xbf,0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1f,0x8c, +0x7e,0x34,0x1f,0x34,0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12, +0x1f,0x8c,0xb, 0x80,0x7e,0x3, 0x2f,0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54, +0x7c,0xb, 0x7a,0x3, 0x2f,0xa8,0x7e,0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xb, 0x7e, +0x3, 0x2f,0xa8,0xbe,0x0, 0xec,0x40,0x2, 0x41,0xde,0x22,0x7d,0x34,0x9e,0x34,0x0, +0x40,0x7d,0x2e,0x9d,0x23,0x7e,0x14,0x61,0x49,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30, +0x22,0x7d,0xe3,0x9f,0x11,0x7e,0x14,0x61,0x43,0x12,0x5e,0xaa,0x90,0x61,0x35,0xe4, +0x93,0x70,0x3, 0x7d,0x3e,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83, +0x2a,0x6f,0x80,0x4, 0x7e,0x83,0x2a,0x70,0x12,0x5f,0xf3,0xbe,0xe4,0x0, 0x3f,0x38, +0x1e,0x7e,0x24,0x0, 0x3f,0x9d,0x2e,0x7e,0x14,0x61,0x47,0x12,0x5b,0x79,0x12,0x5c, +0xbe,0x90,0x61,0x45,0x12,0x5c,0xb5,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0x12, +0x57,0xf7,0xbe,0xa0,0x0, 0x28,0x3a,0x7d,0x14,0x9e,0x14,0x0, 0x3f,0xbd,0x1e,0x38, +0x17,0x12,0x5d,0x66,0x2d,0x10,0xbd,0x1e,0x40,0xe, 0x12,0x5b,0x6b,0x12,0x5c,0xa8, +0x48,0x36,0x7f,0x10,0x1b,0x1c,0x80,0x30,0x12,0x5d,0x66,0x2d,0x10,0xbd,0x1e,0x50, +0x31,0x7d,0x34,0x9e,0x34,0x0, 0x20,0x12,0x5b,0x71,0x12,0x5c,0xbe,0x7d,0x1f,0x80, +0x1d,0x4c,0xaa,0x78,0x1d,0x12,0x5d,0x5f,0xbd,0x5e,0x38,0x16,0x12,0x5b,0x6b,0x12, +0x5c,0xa8,0x48,0x4, 0x7f,0x10,0x1b,0x1c,0xa, 0xb, 0x7d,0x1f,0x9d,0x10,0x6d,0x0, +0x2f,0x10,0xbe,0xe4,0x0, 0x3f,0x28,0x6f,0x12,0x5d,0x5f,0xbd,0x5e,0x28,0x68,0x7d, +0xd4,0xb, 0xd4,0x1e,0xd4,0x7d,0x5d,0x1b,0x54,0xbd,0x5e,0x40,0xc, 0x7d,0x35,0x9d, +0x3e,0x6d,0x22,0x7e,0x14,0x61,0x4b,0x80,0xa, 0x7d,0x3e,0x9d,0x3d,0x6d,0x22,0x7e, +0x14,0x61,0x4d,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10,0x12,0x1e,0xfc,0x12,0x5c,0xc2, +0xbd,0x5e,0x7d,0x1f,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d,0x0, 0x9f,0x1, 0x7f,0x10, +0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0x90,0x61,0x45,0x12,0x5c,0xb5,0x58,0x4, +0x7f,0x10,0x80,0x13,0x90,0x61,0x46,0xe4,0x93,0xa, 0xb, 0x7d,0x1f,0x9d,0x10,0x6d, +0x0, 0xbf,0x10,0x8, 0x2, 0x7f,0x10,0x22,0xad,0x32,0x6d,0x22,0x7c,0x76,0x7c,0x65, +0x1a,0x24,0x90,0x61,0x46,0xe4,0x93,0xa, 0x1b,0x6d,0x0, 0xbf,0x10,0x22,0xad,0x32, +0x6d,0x22,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x7e,0x73,0x37,0xdc,0x7a,0x73,0x38, +0x52,0x7e,0x27,0x33,0xdd,0x7e,0x14,0x61,0xce,0x12,0x5b,0x79,0x1e,0x34,0xbd,0x32, +0x50,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xdc,0x7e,0x14,0x61,0xce,0x12,0x5b,0x79,0xbd, +0x32,0x50,0x8, 0xe4,0x7a,0xb3,0x37,0xda,0x12,0x5e,0x13,0x7e,0x37,0x37,0xe2,0xbd, +0x32,0x50,0x4, 0x7a,0x27,0x37,0xe2,0x12,0x5f,0xeb,0x38,0xa, 0x12,0x5f,0xe3,0x38, +0x5, 0x12,0x5f,0xdb,0x28,0x3d,0x12,0x5e,0x1a,0x7e,0x14,0x61,0xce,0x12,0x5b,0x79, +0x1e,0x34,0x1e,0x34,0xbd,0x32,0x28,0x21,0x7e,0xb3,0x37,0xda,0x4, 0x7a,0xb3,0x37, +0xda,0x7e,0x73,0x37,0xda,0xbe,0x70,0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x37,0xda, +0x12,0xa7,0x57,0x7a,0xb3,0x38,0x4f,0x80,0x5, 0xe4,0x7a,0xb3,0x37,0xda,0x7d,0x32, +0x2, 0xa8,0x1c,0x2, 0x5d,0x56,0x12,0x5e,0x71,0xe4,0x7a,0xb3,0x37,0xe8,0x22,0x7d, +0x54,0x9e,0x54,0x0, 0x3f,0x22,0x7d,0x4, 0x9e,0x4, 0x0, 0x1f,0x7e,0xd4,0x60,0xd1, +0x7e,0xc4,0x0, 0xff,0xb, 0x6a,0x10,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x21, +0x1a,0x7c,0xa7,0x12,0x5f,0xc4,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22, +0x7d,0x13,0x7e,0x54,0x62,0x5e,0x12,0x5d,0xbf,0x50,0x21,0x7e,0x54,0x62,0x60,0x12, +0x5d,0xbf,0x28,0x18,0x7e,0x14,0x62,0x62,0x12,0x5b,0x79,0xbd,0x32,0x50,0xd, 0x7e, +0x14,0x62,0x64,0x12,0x5b,0x79,0xbd,0x32,0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22,0x7e, +0x44,0x0, 0xff,0xb, 0x2a,0x30,0xbd,0x31,0x22,0x12,0x5c,0xc9,0x2, 0x5d,0xcf,0x7e, +0xb3,0x37,0xdc,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xe4,0x7e,0xb3,0x38,0x52,0x70, +0x3, 0x12,0x5e,0x7b,0x7e,0xb3,0x37,0xe4,0xb4,0x1, 0xc, 0x74,0x3, 0x12,0x5e,0x3, +0x12,0x23,0x74,0x3e,0x34,0x80,0x7, 0xe4,0x12,0x5e,0x3, 0x12,0x23,0x74,0x7a,0x37, +0x2a,0x62,0x22,0x7a,0xb3,0x36,0xa0,0x7e,0x34,0x61,0x5d,0x22,0x74,0x1, 0x7a,0xb3, +0x3, 0xc0,0x22,0x74,0x2, 0x7a,0xb3,0x37,0xdc,0x22,0x7e,0xb3,0x37,0xe8,0xb4,0x1, +0x3, 0x2, 0x5e,0x13,0x7e,0xb3,0x38,0x4e,0x4, 0x7a,0xb3,0x38,0x4e,0x7e,0xb3,0x37, +0xdc,0xb4,0x2, 0x18,0x7e,0xb3,0x38,0x4d,0x4, 0x7a,0xb3,0x38,0x4d,0xb4,0x1, 0x6, +0x74,0x1, 0x7a,0xb3,0x38,0x4e,0x74,0x1, 0x7a,0xb3,0x37,0xdc,0x7e,0x73,0x38,0x4d, +0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xe8,0x12,0x5e,0x13,0x12,0x5e, +0x7b,0x12,0x5e,0x71,0x7e,0x73,0x38,0x4e,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0x5e,0x71, +0x22,0xe4,0x7a,0xb3,0x38,0x4e,0x7a,0xb3,0x38,0x4d,0x22,0xe4,0x7a,0xb3,0x37,0xda, +0x6c,0xaa,0x80,0xd, 0x6d,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37,0xf1,0xb, +0xa0,0x12,0x5f,0xcb,0x38,0xee,0xe4,0x7a,0xb3,0x37,0xdb,0x6d,0x33,0x7a,0x37,0x37, +0xe2,0x7a,0x37,0x37,0xd7,0x22,0x7e,0x14,0x62,0x94,0x7e,0x4, 0x0, 0xff,0xb, 0xa, +0xf0,0x22,0x12,0xcc,0x30,0x12,0x59,0xa8,0x7a,0x37,0x3, 0xfc,0x12,0x5e,0xda,0x12, +0x28,0x86,0x2, 0x5e,0xc5,0x7e,0x70,0xa, 0x12,0x0, 0x6e,0x50,0x3, 0x7e,0x70,0x19, +0x7a,0x73,0x36,0x7c,0xe4,0x7a,0xb3,0x36,0x7d,0x22,0x7e,0x34,0xd, 0xac,0x12,0x26, +0x77,0x12,0x6a,0x92,0x12,0x5f,0x1f,0x2, 0x5e,0xea,0x30,0x11,0x10,0x12,0xae,0xc7, +0x50,0x3, 0x12,0x57,0x4f,0x12,0x78,0xac,0x12,0x5f,0x45,0xc2,0x11,0x22,0x7e,0xa3, +0x2f,0xa8,0xbe,0xa0,0xf0,0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0x5f, +0xd3,0x59,0x25,0x2b,0xc1,0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e, +0xb3,0x2b,0x1e,0x70,0x1f,0x12,0x26,0x73,0x12,0x6f,0xca,0x50,0xfb,0x12,0x78,0xac, +0x12,0x87,0x5c,0x20,0x11,0x3, 0x12,0x5f,0x45,0x74,0x2, 0x7a,0xb3,0x2b,0x1e,0xe4, +0x7a,0xb3,0x16,0x91,0x22,0xca,0x3b,0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e, +0xf3,0x2b,0x62,0x12,0xaa,0x61,0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12, +0xcc,0xa8,0xf5,0x29,0x7e,0x73,0x2b,0xf, 0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, +0xac,0x7d,0xa, 0x2c,0x12,0x6f,0xe8,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, +0x7e,0x14,0x2, 0xe0,0xad,0x10,0x2e,0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e, +0x70,0x1d,0xac,0x7e,0x2e,0x34,0x38,0x58,0x6d,0x22,0x7a,0x1f,0x38,0x54,0x7c,0xbc, +0x12,0x7b,0xc8,0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f, +0x68,0x6, 0x7a,0xf3,0x2b,0x62,0xd2,0xe, 0xd2,0x3, 0x7e,0xb3,0x1f,0x33,0x12,0xa6, +0xa8,0xda,0x3b,0x22,0x7d,0x31,0x9d,0x30,0x2, 0x21,0x1a,0x90,0x61,0xcb,0xe4,0x93, +0xbc,0xba,0x22,0x7e,0xa3,0x2f,0xa8,0x74,0x4, 0xa4,0x22,0x7e,0x73,0x26,0xf5,0xbe, +0x70,0x0, 0x22,0x7e,0x73,0x26,0xf4,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x28,0x92,0xbe, +0x70,0x0, 0x22,0x7e,0x90,0x40,0xac,0x89,0x1b,0x44,0x22,0x2, 0x62,0xc1,0xff,0xff, +0x70,0x8f,0x0, 0xff,0xd0,0x2f,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x31,0x37,0x32,0x1, 0xd2,0x0, 0x31,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x9, 0xf6,0x44,0x32,0x5f,0x42,0x69,0x65,0x6c,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0xf, 0xe, 0xd, +0xc, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xb, 0xa, 0x9, 0x8, 0x18,0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x6, 0xb, 0x0, +0x0, 0x0, 0x64,0x0, 0xfa,0x1, 0x2c,0x2, 0xbc,0x2, 0xee,0x4, 0x1a,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x1e,0x1, 0xf4,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x0, 0x4, 0x34,0x28,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x52,0x40,0xe, 0x19,0x27,0x13,0xd, 0x6, 0x80,0x13,0xd, 0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x46,0x45,0x2, 0x4e,0x2, 0x4e,0x1, +0x38,0x1, 0x3b,0x7, 0x80,0x46,0x48,0x2, 0xe, 0x2, 0xe, 0x1, 0x43,0x1, 0x43,0x0, +0xa0,0x0, 0x8c,0x0, 0x8c,0x0, 0xc8,0x0, 0x64,0x0, 0xb4,0x0, 0xb4,0xa, 0x0, 0x0, +0xdc,0x6, 0xa, 0x14,0x28,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0x9, 0x1, 0xd0,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x3, 0x34,0x52,0x28, +0x19,0x3, 0x33,0x51,0x28,0x22,0x3, 0x35,0x53,0x28,0x43,0x2, 0x3b,0x5c,0x28,0x1e, +0x3, 0x34,0x52,0x28,0x1e,0x3, 0x34,0x52,0x28,0x1e,0x3, 0x34,0x52,0x28,0x1e,0x3, +0x34,0x52,0x28,0x4, 0x5, 0xd, 0xe, 0xf, 0x10,0x11,0x4, 0x0, 0x96,0x1, 0x90,0x28, +0x1, 0x2c,0x1, 0x5e,0x0, 0xc8,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, 0x90, +0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, 0x50, +0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x8, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x32,0x1, 0xf4,0x1, 0xf4,0x2, 0x58,0x0, 0xc8, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0x7e,0x73,0x28,0x93,0x7a, +0x73,0x28,0x94,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, 0xe4,0x7a,0xb3,0x2a,0x6, +0x22,0x7e,0x37,0x34,0x38,0xb, 0x34,0x7a,0x37,0x34,0x38,0x7e,0x37,0x34,0x3a,0xbe, +0x37,0x34,0x38,0x28,0x3, 0x2, 0xc0,0x87,0x22,0xe4,0x12,0x65,0x42,0x12,0xc1,0x51, +0x12,0x26,0x73,0x12,0xc1,0xaf,0x12,0x4e,0xcd,0x12,0xc0,0x91,0x12,0xc1,0x68,0x12, +0x0, 0x49,0x12,0xc1,0x74,0x12,0x64,0xcd,0x12,0xc1,0x84,0xd2,0xaf,0x12,0xc0,0xe3, +0x12,0x63,0x27,0x12,0x4f,0x62,0x12,0x67,0x34,0x7e,0x8, 0x34,0x3c,0x12,0x65,0x1c, +0x90,0x60,0x50,0xe4,0x93,0xca,0xb8,0x90,0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24, +0xff,0xff,0xda,0xb8,0x2, 0x12,0x34,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3, +0x13,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0x64,0xbd,0xe4,0x12,0x63,0x4a,0x2, 0x63, +0x41,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x39,0xfc,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x2, +0x12,0x63,0xc8,0x4c,0xff,0x78,0x5, 0x5e,0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74, +0x2, 0x12,0x63,0x6b,0xda,0xf8,0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, +0x14,0x7c,0x73,0x7d,0x52,0x7c,0xab,0x7e,0xb3,0x39,0xfc,0xb4,0xa5,0x42,0x12,0x64, +0x68,0x75,0xb5,0x1, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36, +0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a, +0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4, +0x22,0x74,0x4, 0x7d,0x30,0x2, 0x63,0x6b,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3, +0x39,0xfc,0xb4,0xa5,0x52,0x12,0x64,0x68,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6, +0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22, +0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x64,0xbd,0x74,0x2, 0x12,0x63,0xc8,0x7d,0xf3, +0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x64,0x61,0x7a,0x45,0x36,0x7d,0x30, +0x6d,0x22,0x7f,0x6, 0x12,0x64,0x79,0x5e,0xf4,0xff,0xfd,0x12,0x64,0x61,0x2, 0x63, +0x41,0x74,0x2, 0x7d,0x3f,0x2, 0x63,0x6b,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74, +0x6, 0x12,0x63,0xc8,0x7d,0x3, 0x6c,0x11,0x22,0x12,0x64,0x87,0x7e,0x35,0x36,0x12, +0xc1,0xcf,0xa9,0xd2,0xb4,0xd3,0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, +0x44,0xf5,0x39,0x7f,0x21,0xf5,0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x64,0xb2,0xe5, +0x3a,0x12,0x64,0xb2,0xe5,0x39,0x12,0x64,0xb2,0xe5,0x38,0x12,0x64,0xb2,0xe4,0x2, +0x64,0xb2,0xf5,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xa9,0xd5,0xca, +0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x39,0xfc,0x22,0xe4,0x7a,0xb3, +0x38,0xb0,0x7e,0x8, 0x35,0xa6,0x12,0xcc,0x8c,0x7e,0x8, 0x35,0xe4,0x7e,0x34,0x0, +0x3e,0x12,0x20,0xe8,0x7e,0x18,0x35,0xa6,0x7a,0x1d,0x14,0x12,0x64,0xfe,0x2, 0x64, +0xf1,0x75,0x18,0x0, 0x75,0x1a,0x0, 0x7e,0xb3,0x38,0xb0,0xf5,0x91,0x22,0x2, 0x65, +0x1, 0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2, +0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0xd2,0xc9,0x75,0xf2, +0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80, +0xb4,0x80,0xf9,0xe5,0xf6,0x12,0xa2,0x9a,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xed,0xc2, +0xc9,0x22,0xa9,0xc4,0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x67,0xa2, +0xa9,0xd0,0xce,0xa9,0xc0,0xc9,0xd2,0x5, 0x12,0x65,0x73,0xa9,0xc2,0xea,0x75,0xc1, +0x6, 0x75,0xc2,0xc, 0xd2,0x3, 0x12,0x67,0x29,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9, +0xc2,0xe1,0x22,0xa9,0xd0,0xce,0xa2,0x5, 0xa9,0x91,0xc9,0x22,0x30,0x4, 0x6, 0x12, +0x66,0xf2,0x2, 0x13,0x96,0x12,0x67,0x89,0xc2,0x5, 0x2, 0x65,0x73,0x30,0x1b,0x5, +0xc2,0x4, 0x12,0x65,0x7c,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1a,0x3, 0x20,0x1b, +0x14,0x12,0x66,0x35,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x66,0x3c,0xa9, +0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x4, 0x2, 0x65,0x7c,0xd2,0x4, 0x2, +0x65,0x7c,0x74,0x1, 0x12,0x65,0xe1,0x20,0x1a,0x6, 0x12,0x65,0xea,0x12,0x65,0xbd, +0x7e,0xb3,0x33,0xe6,0xb4,0x1, 0x6, 0x12,0x66,0x83,0x12,0x65,0xbd,0xe4,0x2, 0x65, +0xe1,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x67,0xa2,0x22,0xd2,0x3, 0x80,0x12,0x30,0x3, +0xc, 0x12,0x66,0x9d,0x68,0x7, 0xc2,0x3, 0xc2,0x4, 0x12,0x65,0x7c,0x12,0x66,0x4, +0x30,0x1a,0xeb,0x22,0x80,0x1d,0x12,0x66,0x35,0x12,0x66,0x9d,0x68,0x5, 0xc2,0x4, +0x12,0x65,0x7c,0x7e,0xb3,0x33,0xe6,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1a,0x15,0xe4, +0x12,0x66,0x3c,0x20,0x93,0xe0,0x12,0x66,0x35,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x74, +0x2, 0x2, 0x66,0x3c,0x22,0x74,0x81,0x7a,0xb3,0x3, 0xfa,0x22,0x7c,0xab,0x7e,0xb3, +0x3, 0xfa,0xb4,0x81,0x38,0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0, +0x1, 0x78,0xf, 0xc2,0xaf,0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf, +0x80,0x15,0xbe,0xa0,0x2, 0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9, +0xd7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3, +0x3, 0xfa,0x22,0x74,0xc8,0x7a,0xb3,0x3, 0xfe,0xc2,0x1a,0x80,0xa, 0x12,0x66,0x4, +0x30,0x1a,0x4, 0x75,0xe9,0xff,0x22,0x12,0x66,0x9d,0x68,0xf1,0x22,0x7e,0xb3,0x33, +0xe6,0xbe,0xb0,0x1, 0x22,0x12,0x66,0x35,0x12,0x67,0x90,0x75,0xcd,0x0, 0xa9,0xd6, +0xeb,0xa9,0xd7,0xcd,0xc2,0xce,0x12,0x75,0xba,0x12,0x66,0xfa,0x74,0x1, 0x12,0x66, +0x3c,0xa9,0xc6,0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x66, +0xd1,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x4e,0xc7,0x7a,0x61,0xfc,0x12,0x4f, +0x5b,0x12,0x67,0x34,0xd2,0x3, 0x12,0x67,0x29,0x12,0x66,0xf2,0x12,0x13,0xde,0x2, +0x13,0x96,0xd2,0x5, 0x12,0x65,0x73,0x74,0x1, 0x22,0x12,0x67,0x89,0xc2,0x3, 0x12, +0x67,0x99,0xc2,0x5, 0x12,0x65,0x73,0xc2,0x3, 0x12,0x67,0x29,0xa9,0xd5,0xcb,0x74, +0xf, 0x12,0x4f,0x53,0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77,0x12,0x4e,0xc7,0xe5,0xfc, +0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, 0x4f,0x5b,0xa2,0x3, 0xa9,0x97,0xc1,0xa2,0x3, +0xa9,0x97,0xc2,0x22,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x3, 0x12,0x67, +0x99,0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75, +0x9c,0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x67,0x6e, +0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0x7c,0xab, +0x80,0xe, 0x7e,0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7, +0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xea,0x22,0xe4,0x12,0x13,0xde,0x2, 0x13,0x96, +0x12,0x66,0x9d,0x68,0xfb,0x20,0x93,0xfd,0x22,0xa9,0xd0,0xce,0xa2,0x3, 0xa9,0x95, +0xc9,0x22,0xa, 0x5b,0x2e,0x54,0x0, 0x8, 0xf5,0xcc,0x22,0x7c,0x96,0x7c,0xa7,0x12, +0x48,0x34,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, 0x12,0x67,0x6e,0x7c,0xb9,0x12,0x0, +0x1e,0x2, 0x67,0xc4,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a,0xfa,0x74,0x1, +0x7a,0xb3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0xcc,0xb1,0x12,0x29, +0x9f,0x7e,0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x20,0xe8,0x7e,0xd0,0x7, 0x12,0x26,0x73, +0x6c,0xcc,0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78, +0xfb,0x7c,0x67,0x12,0x69,0xa, 0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x69,0x14, +0xa, 0x3c,0xbd,0x32,0x48,0xde,0x12,0x69,0xa4,0x30,0x1b,0xfd,0x12,0x6a,0xda,0x7e, +0xb3,0x2a,0x73,0x7c,0x7e,0x12,0x10,0xee,0x74,0x2, 0x12,0x0, 0x1e,0x6c,0xcc,0x80, +0x29,0x74,0x2, 0xac,0xbc,0x49,0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e, +0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff, +0x12,0x69,0xa, 0x5c,0x7b,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x69,0x14,0xa, 0x3c,0xbd, +0x32,0x48,0xce,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0x83,0x12,0x69,0x23,0x74,0x2, 0x12, +0x6b,0xbb,0x12,0x68,0x88,0x74,0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x2a,0xfa,0x7e,0x8, +0x2a,0x6d,0x12,0x5, 0xb4,0xda,0x3b,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x24,0xf2, +0x12,0x6c,0x36,0x7e,0xa3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x6c,0xee,0x80,0x1d,0xa, +0x2e,0x9, 0x62,0x2a,0xdc,0xa, 0x26,0x12,0x6c,0xb5,0x7c,0x6b,0xbe,0x60,0x1c,0x50, +0x9, 0xa, 0x2e,0x12,0x69,0x0, 0x19,0xb2,0x24,0xf2,0xb, 0xe0,0xbc,0x7e,0x38,0xdf, +0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, 0x62,0x2a,0xb9,0xbe,0x60,0x23,0x50,0xd, 0xa, +0x1e,0xa, 0x27,0x2d,0x21,0x12,0x69,0x0, 0x19,0xb2,0x25,0xe, 0xb, 0xe0,0xbc,0xae, +0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x24,0xf2,0x6d,0x0, 0x7c, +0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22, +0x2e,0x27,0x2a,0xfe,0x7e,0x29,0xb0,0xa, 0x26,0x22,0xa, 0x2c,0x2e,0x27,0x2a,0xfe, +0x7e,0x29,0x70,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73,0xa, 0x25, +0x2d,0x23,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a,0xb3,0x2a,0xfa, +0x12,0x29,0x9f,0x7c,0xe7,0x80,0x60,0x12,0x26,0x73,0x12,0x69,0xa4,0x30,0x1b,0xfd, +0x12,0x6a,0xda,0x12,0x6a,0xe4,0x12,0x0, 0x1e,0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, +0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17, +0x2a,0xfe,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18, +0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x49,0x93,0xbe,0xb0,0xff,0x68,0x8, +0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x69,0x14,0xa, 0x3d,0xbd, +0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x98,0xda, +0x79,0xda,0xd8,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x68,0x88, +0x74,0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x69,0xc7, +0x7e,0xb3,0x2a,0xfc,0x2, 0xe, 0x94,0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x2a, +0xdc,0x2e,0x34,0x20,0x7d,0x12,0x6f,0xee,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac, +0x5a,0x7e,0xf, 0x33,0xc7,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x2a, +0x74,0xbc,0x6a,0x38,0xd6,0x22,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0,0x1, 0x28,0x2, 0xe4, +0x22,0x12,0x6f,0xdb,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x7a,0xd7,0x2b,0xd, 0x7e, +0x73,0x2a,0xfa,0xa, 0x37,0x3e,0x34,0x3e,0x34,0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, +0x12,0x69,0xb5,0x74,0x1, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40, +0x7f,0x15,0x12,0x7f,0xfa,0x12,0x4f,0xf4,0x7e,0xe0,0x1, 0x12,0x69,0xb5,0x30,0x1b, +0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x6a,0xe4,0x12,0x0, 0x1e,0x6c,0xdd, +0x80,0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, 0xac, +0xbd,0x7f,0x5, 0x2d,0x15,0x12,0x6f,0xc1,0xb, 0xd0,0x7e,0x73,0x2a,0x74,0xa, 0x7, +0x7e,0x63,0x2a,0x73,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b,0xe0, +0x78,0xb9,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12,0x6b,0x29,0xda,0x79,0xda, +0xd8,0x22,0x7e,0xb3,0x2b,0x2, 0x70,0x41,0x12,0x6f,0xca,0x50,0xfb,0xe4,0x6c,0x77, +0x6c,0x66,0x12,0x67,0xab,0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x2b, +0x72,0x12,0x6a,0x26,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x67,0xab,0x7e, +0x8, 0x7, 0x7a,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x25,0xf0,0x12,0x6a,0x26,0x74,0x2, +0x7a,0xb3,0x2b,0x2, 0xe4,0x7a,0xb3,0x16,0x90,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e, +0x8, 0x6, 0xfc,0x22,0x7e,0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x74, +0x2, 0x22,0x12,0x6c,0x2d,0x38,0x2, 0xe4,0x22,0x12,0x6b,0xc3,0x49,0x55,0x33,0xe7, +0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x69,0xf6,0x2, 0x6b,0xb, 0xb4,0x3, 0x5, 0x12,0x6b, +0x1b,0x80,0x2, 0xe4,0x22,0x12,0x7c,0xd0,0x74,0x1, 0x22,0x12,0x6f,0xb8,0xe4,0x12, +0x0, 0xe, 0x7e,0x8, 0x2a,0x6d,0x2, 0xd, 0x72,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f, +0x70,0x12,0xc3,0x5d,0x7c,0xeb,0x6c,0xdd,0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67, +0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e, +0x6d,0x0, 0x12,0x1f,0x7, 0x1b,0x6a,0x30,0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79, +0xda,0xd8,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40,0x7e,0xa3,0x2a,0x74,0xa, 0x3a,0x7e, +0xa3,0x2a,0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, 0x29,0x7c,0x7f,0x12,0x6b,0x29,0xa, +0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f,0x4, 0x12,0x20,0xc3,0x1b,0xfd,0x7e, +0xb3,0x2b,0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f, +0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d,0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b, +0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda,0x79,0x22,0x12,0x0, 0x1e,0x7e,0xb3, +0x2a,0xfc,0x22,0x7e,0xa3,0x33,0xe5,0x74,0x4, 0xa4,0x22,0x30,0x1b,0x8, 0x74,0x5, +0x7e,0x70,0x99,0x12,0x13,0x2c,0x7e,0xb3,0x33,0xe6,0xb4,0x1, 0x4f,0x12,0x6b,0xc3, +0x49,0x35,0x33,0xe7,0x49,0x15,0x33,0xe9,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a, +0xbe,0x70,0x0, 0x40,0x15,0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e, +0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x7e,0xb3,0x33,0xe5,0x4, 0x7a, +0xb3,0x33,0xe5,0x12,0x6c,0x2d,0x28,0xe, 0x12,0x6a,0xf2,0xb4,0x1, 0x4, 0x74,0x1, +0x80,0x6, 0x74,0x3, 0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x33,0xe6,0x22,0x7e,0x73,0x33, +0xe4,0xbe,0x73,0x33,0xe5,0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x20,0xe8,0xca, +0x79,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12,0x6c,0x36,0x7e,0xa3,0x2a,0x73,0x7e,0x63, +0x2a,0x74,0x6c,0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x2a,0xdc,0xbe,0x70,0x1c,0x50, +0x11,0xa, 0x27,0x12,0x6c,0xb5,0x7c,0x7b,0x7e,0xb3,0x2a,0xfb,0xa, 0x27,0x19,0xb2, +0x1f,0x34,0xb, 0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73, +0x2a,0xb9,0xbe,0x70,0x23,0x50,0xa, 0x7e,0x63,0x2a,0xfb,0xa, 0x27,0x19,0x62,0x1f, +0x50,0xb, 0xe0,0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14, +0x1f,0x34,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe,0xe0,0x5, +0x40,0xe7,0xda,0x79,0x22,0x2e,0x24,0x20,0x7d,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4, +0x93,0x22,0x7c,0xab,0x6c,0x77,0x80,0x11,0xa, 0x27,0x2e,0x24,0x60,0xac,0x12,0x6c, +0xb9,0xbc,0xba,0x78,0x2, 0xd3,0x22,0xb, 0x70,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xb7, +0x38,0xe6,0xc3,0x22,0xca,0x3b,0x7c,0x5b,0x7e,0x43,0x28,0x84,0xbe,0x40,0x1, 0x28, +0x2, 0xa1,0xdf,0x7e,0xa3,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x75,0x9, 0xd3,0x26,0xfa, +0x9, 0xc3,0x26,0xfb,0x7c,0xbd,0x7c,0x7c,0x12,0xbf,0xcb,0x7f,0x1, 0x90,0x60,0xaa, +0xe4,0x93,0x70,0x12,0x7c,0xfc,0x7c,0x9d,0x7e,0x83,0x2a,0x70,0x7e,0xe3,0x2a,0x6f, +0xa, 0xca,0x6d,0xbb,0x9d,0xbc,0xa, 0xa8,0x1b,0xa5,0xa, 0x5f,0xbd,0x5a,0x58,0x2, +0xa1,0xdf,0xa, 0x59,0x1b,0x54,0xbe,0x54,0x0, 0x0, 0x48,0x4e,0x7c,0xb9,0x14,0x12, +0x6c,0xc2,0x50,0x46,0x7c,0xb9,0x14,0x12,0x6d,0xe2,0xb, 0x1a,0xe0,0x7d,0x3b,0x12, +0x6e,0x17,0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, +0x7d,0x5a,0x12,0x6e,0xf, 0x7c,0xb8,0x24,0xfe,0xbc,0xbf,0x78,0x1d,0x90,0x60,0xaa, +0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f,0x12,0x6d,0xe9,0xb, 0x1a,0x30, +0xbd,0x3a,0x8, 0x6, 0x12,0x6d,0xeb,0x1b,0x1a,0xa0,0xa, 0xa9,0xb, 0xa4,0xa, 0x5e, +0xbd,0xa5,0x58,0x4b,0x7c,0xb9,0x4, 0x12,0x6c,0xc2,0x50,0x43,0x7c,0xb9,0x4, 0x12, +0x6d,0xe2,0xb, 0x1a,0xe0,0x7d,0x3c,0x12,0x6e,0x17,0x8, 0x11,0x9d,0xae,0xbe,0xa4, +0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a,0x12,0x6e,0xf, 0x7c,0xb8,0x24, +0xfe,0xbc,0xbf,0x78,0x1a,0x90,0x60,0xaa,0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4, +0x7d,0x5f,0x12,0x6d,0xe9,0xb, 0x1a,0x50,0xbd,0x5a,0x8, 0x3, 0x1b,0x1a,0xa0,0xda, +0x3b,0x22,0x12,0x6d,0xf2,0x7d,0xd3,0x7d,0x5d,0x3e,0x54,0x7e,0x1f,0x13,0x8a,0x2d, +0x35,0x22,0x7c,0x5b,0x7e,0x43,0x2a,0x6e,0x90,0x60,0xab,0xe4,0x93,0x7c,0xab,0x90, +0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7c,0x75,0xac,0x74,0xa, 0x2a,0x2d,0x32,0x22,0x2d, +0x31,0x7d,0x20,0x1b,0x1a,0x50,0x22,0x3e,0x34,0x7f,0x40,0x2d,0x93,0xb, 0x4a,0xa0, +0xbe,0xe4,0x0, 0x0, 0x22,0x12,0x6f,0xb0,0x60,0x34,0x6c,0x22,0x80,0x28,0x7c,0xb2, +0x12,0x6c,0xc2,0x50,0x1f,0x7c,0xb2,0x12,0x6d,0xf2,0x3e,0x34,0x7e,0x7f,0x13,0x8a, +0x2d,0xf3,0xb, 0x7a,0x30,0x12,0x6f,0xa8,0x59,0x35,0x39,0xdf,0x30,0x3, 0x5, 0x6d, +0x33,0x1b,0x7a,0x30,0xb, 0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xd0,0x22,0x90, +0x60,0xa7,0xe4,0x93,0x60,0x2b,0x6c,0x33,0x80,0x1f,0x7c,0xb3,0x12,0x6c,0xc2,0x40, +0x16,0x7c,0xb3,0x12,0x6d,0xf2,0x7d,0x43,0x6d,0x55,0x7d,0x4, 0x3e,0x4, 0x7e,0x1f, +0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50,0xb, 0x30,0x7e,0x23,0x2a,0x75,0xbc,0x23,0x38, +0xd9,0x22,0x7e,0x63,0x2a,0x6e,0x90,0x60,0xa7,0xe4,0x93,0x60,0x6c,0xc2,0x14,0x6c, +0x33,0x80,0x56,0x90,0x60,0xaa,0xe4,0x93,0x70,0x13,0x7c,0x96,0xac,0x93,0x90,0x60, +0xab,0xe4,0x93,0xa, 0x5b,0x1b,0x54,0x2d,0x45,0x7d,0xd4,0xb, 0xd4,0x7d,0x54,0x3e, +0x54,0x7e,0x7f,0x13,0x8a,0x2d,0xf5,0xb, 0x7a,0x50,0xbe,0x57,0x2a,0x5a,0x8, 0x27, +0x7c,0xb3,0x12,0x6c,0xc2,0x50,0x20,0x7d,0x5d,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x7f, +0x57,0x2d,0xb5,0xb, 0x5a,0xc0,0x7d,0x54,0x3e,0x54,0x2d,0xf5,0xb, 0x7a,0x50,0xbd, +0x5c,0x8, 0x4, 0xd2,0x14,0x80,0xa, 0xb, 0x30,0x7e,0x73,0x2a,0x75,0xbc,0x73,0x38, +0xa2,0x30,0x14,0x5, 0xd2,0x3, 0x2, 0x6e,0x25,0x22,0x7e,0x37,0x2a,0x4f,0x1e,0x34, +0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, 0x12,0x6f,0x4c,0x7e,0x37, +0x28,0x99,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a,0x7e,0x18,0x4, 0x7e,0x12, +0x6f,0x4c,0x12,0x6f,0x79,0x12,0x6e,0x92,0x2, 0x6f,0x3b,0xe4,0x7a,0xb3,0x39,0xf7, +0x7e,0xb3,0x28,0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x39,0xf7,0x22,0xca,0x3b,0x7f,0x31, +0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24,0x7f,0x13,0x12,0x8a, +0x4f,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x6f,0xa0,0x7e,0xd, 0x24,0x2d,0x15,0x7f, +0x13,0x2d,0x35,0x12,0x7a,0x90,0xda,0x3b,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e, +0xe3,0x2a,0x6f,0x7e,0xd3,0x2a,0x70,0x6c,0xcc,0x80,0xe, 0x7c,0x7c,0xac,0x7f,0x12, +0x40,0xb2,0x7c,0xbd,0x12,0xa0,0xca,0xb, 0xc0,0xbc,0xec,0x38,0xee,0xda,0x3b,0x22, +0x7e,0xa3,0x2a,0x74,0x74,0x2, 0xa4,0x22,0x7c,0xa3,0xb, 0x30,0x74,0x2, 0xa4,0x22, +0x6c,0x33,0x90,0x60,0xa7,0xe4,0x93,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, +0x1e,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0xb3,0x33,0xe6,0xb4,0x1, +0x2, 0xc3,0x22,0xd3,0x22,0x12,0x6f,0xca,0x50,0xfb,0x22,0x7c,0xab,0x12,0x4a,0x9e, +0x7c,0xba,0x12,0x13,0xc7,0x2, 0x0, 0x1e,0x2d,0x32,0x2e,0x34,0x21,0xa, 0x7a,0x71, +0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61, +0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x70,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34, +0x2a,0xe, 0x7a,0x37,0x2b,0x76,0xe4,0x7a,0xb3,0x2b,0x74,0x7a,0xb3,0x2b,0x75,0x7e, +0x34,0x0, 0x4, 0xca,0x39,0x12,0x70,0x45,0x7e,0x8, 0x25,0xee,0x12,0x20,0xc3,0x1b, +0xfd,0x7e,0x34,0x2b,0x78,0x7a,0x37,0x25,0xf4,0xe4,0x7a,0xb3,0x25,0xf2,0x74,0x1, +0x7a,0xb3,0x25,0xf3,0x22,0x7e,0x34,0x61,0x29,0x7e,0x24,0x0, 0xff,0x22,0xe4,0x7a, +0xb3,0x38,0xb0,0x7a,0xb3,0x38,0xb1,0x90,0x60,0x50,0x93,0x7a,0xb3,0x38,0xb2,0x90, +0x60,0x51,0xe4,0x93,0x7a,0xb3,0x38,0xb3,0xe4,0x7a,0xb3,0x38,0xb4,0x90,0x60,0x99, +0x93,0x7a,0xb3,0x38,0xb5,0xe4,0x7a,0xb3,0x38,0xb6,0x7a,0xb3,0x38,0xb7,0x90,0x61, +0xca,0x93,0x7a,0xb3,0x38,0xb9,0x7e,0x34,0x61,0x4f,0x12,0x23,0x74,0x1e,0x34,0x1e, +0x34,0x7a,0x73,0x38,0xbd,0x7e,0x34,0x61,0x55,0x12,0x23,0x74,0x1e,0x34,0x1e,0x34, +0x7a,0x73,0x38,0xbe,0x74,0x64,0x7a,0xb3,0x38,0xcf,0x90,0x61,0x18,0xe4,0x93,0x7a, +0xb3,0x38,0xd0,0x90,0x61,0x17,0xe4,0x93,0x7a,0xb3,0x38,0xbc,0x90,0x61,0x19,0xe4, +0x93,0x7a,0xb3,0x38,0xd2,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x38,0xd1,0x90,0x61, +0x1d,0xe4,0x93,0x7a,0xb3,0x38,0xd3,0x90,0x61,0x25,0xe4,0x93,0x7a,0xb3,0x38,0xce, +0xe4,0x7a,0xb3,0x38,0xc9,0x74,0xc8,0x7a,0xb3,0x38,0xc7,0x74,0x1e,0x7a,0xb3,0x38, +0xc8,0x74,0x1, 0x7a,0xb3,0x38,0xc6,0x74,0xc, 0x7a,0xb3,0x38,0xc5,0x74,0x1, 0x7a, +0xb3,0x38,0xca,0xe4,0x7a,0xb3,0x38,0xcb,0x7a,0xb3,0x38,0xcc,0x7e,0x8, 0x38,0xd4, +0x7e,0x34,0x0, 0x2c,0x12,0x20,0xe8,0x7e,0x34,0x60,0xd6,0x12,0x23,0x74,0xa, 0x36, +0x7a,0x73,0x38,0xdf,0x7e,0x34,0x60,0xd6,0x12,0x23,0x74,0x7a,0x73,0x38,0xe0,0x90, +0x60,0xd4,0x93,0x7a,0xb3,0x38,0xe1,0x90,0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x38,0xe2, +0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x70,0x45,0x7e,0x8, 0x38,0xf0,0x12,0x20,0xc3, +0x1b,0xfd,0x74,0x5, 0x7a,0xb3,0x38,0xfd,0x74,0x1, 0x7a,0xb3,0x38,0xf4,0x7e,0x34, +0x0, 0x28,0xca,0x39,0x7e,0x34,0x61,0xdb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33, +0x12,0x20,0xc3,0x1b,0xfd,0x22,0x6d,0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2, +0x2a,0xdc,0x54,0x1, 0x78,0x5, 0x4e,0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0, +0x7e,0x53,0x2a,0x74,0xbc,0x5a,0x38,0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2, +0x2a,0xb9,0xbe,0xb0,0xd, 0x38,0x5, 0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38, +0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e,0x60,0x50,0xb, 0xa0,0x12,0x71,0xc1,0x38,0xdc, +0x22,0x7e,0xb3,0x2a,0x73,0xbc,0xba,0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab, +0x7d,0x8b,0x6d,0x22,0x7d,0x32,0x7d,0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, +0xfc,0x7e,0x8, 0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3, +0x26,0xf6,0x7a,0xb3,0x26,0xf8,0x7a,0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa, +0x80,0x5f,0x12,0x73,0x2f,0xb, 0x6a,0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3, +0x8, 0x2, 0x7d,0x3c,0x2d,0x71,0x7d,0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d, +0x9d,0x7e,0x67,0x2a,0x53,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, +0x24,0x12,0x73,0x1c,0xb, 0x3a,0xd0,0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x26,0xf7,0x4, +0x7a,0xb3,0x26,0xf7,0x80,0x19,0x12,0x73,0x25,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff, +0xb, 0xd4,0xbd,0xcd,0x58,0x9, 0x7e,0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, +0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x99,0x7a,0xa7,0x7, 0xfe,0x7a,0x37,0x8, +0x2, 0xe5,0x24,0x7a,0xb3,0x8, 0x9, 0x7a,0x97,0x8, 0x6, 0x12,0x6f,0xa0,0x2d,0xf5, +0x6c,0xaa,0x80,0x50,0x12,0x73,0x2f,0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d, +0xbd,0xd2,0x8, 0x2, 0x7d,0x2d,0x7e,0x67,0x2a,0x51,0x7e,0x74,0x0, 0x3, 0xad,0x76, +0xbd,0xd7,0x8, 0x2, 0xb, 0x90,0x12,0x73,0x1c,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, +0x7e,0xb3,0x26,0xf6,0x4, 0x7a,0xb3,0x26,0xf6,0x80,0x17,0x12,0x73,0x25,0xb, 0x3a, +0xd0,0x6d,0x99,0x9d,0x9c,0xbd,0xd9,0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3, +0x26,0xf8,0xb, 0xa0,0x12,0x71,0xc1,0x38,0xab,0x7a,0x87,0x7, 0xfc,0x7a,0x27,0x8, +0x0, 0x7a,0x93,0x8, 0x8, 0x12,0x6f,0xa0,0x2d,0x15,0x6c,0xaa,0x80,0xe, 0x12,0x75, +0xc3,0xb, 0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x71,0xc1,0x38, +0xed,0x7a,0xb7,0x8, 0x4, 0xbd,0x8a,0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0xf8,0xbd, +0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b,0x22,0x7e,0x74,0x62,0x16, +0x7e,0x64,0x0, 0xff,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x2d,0x7f,0x7d,0x6e,0x22,0x7e, +0xf0,0x2, 0xac,0xfa,0x7f,0x67,0x2d,0xd7,0x22,0xca,0xd8,0xca,0x79,0x90,0x60,0x50, +0xe4,0x93,0x7c,0xdb,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e,0x73,0x2a,0x74,0xbc, +0x7e,0x28,0x4, 0x7c,0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3,0x2a,0x6d,0x7a,0xe3,0x2a, +0x6e,0x7a,0xd3,0x2a,0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xd3,0x2a,0x73,0x7a,0xe3,0x2a, +0x74,0x90,0x60,0xa8,0xe4,0x93,0x7c,0xab,0x7a,0xa3,0x2a,0x77,0x90,0x60,0xa9,0xe4, +0x93,0xa, 0x2b,0xa, 0x3d,0x9d,0x32,0x7c,0xb7,0x7a,0xb3,0x2a,0x6f,0xa, 0x2a,0xa, +0x3e,0x9d,0x32,0x7a,0x73,0x2a,0x70,0x90,0x60,0x91,0xe4,0x93,0x7a,0xb3,0x2a,0x78, +0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x2a,0x79,0xa, 0x3d,0xca,0x39,0x7e,0x34,0x60, +0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x7a,0x12,0x20,0xc3,0x1b,0xfd,0xa, 0x3f, +0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x9d,0x12,0x20, +0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e,0x34,0x60,0xd8,0x7e,0x24,0x0, +0xff,0x7e,0x8, 0x2b,0x21,0x12,0x20,0xc3,0x1b,0xfd,0x12,0x75,0x24,0x12,0x78,0x40, +0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7a,0xd3,0x2a,0x75,0x7a,0xe3,0x2a,0x76,0x12, +0x6f,0xf7,0x74,0x1, 0x12,0x48,0x34,0xe4,0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x2, +0x12,0x71,0x76,0x7a,0x37,0x2b,0xd, 0x74,0x3, 0x7a,0xb3,0x2b,0x3, 0xe4,0x7a,0xb3, +0x2b,0x4, 0x74,0x2, 0x7a,0xb3,0x2b,0x5, 0x7e,0x34,0x61,0x5b,0x12,0x23,0x74,0x7a, +0x37,0x2b,0x7, 0x74,0x4, 0x7a,0xb3,0x2b,0x6, 0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x2b, +0x9, 0x7e,0x34,0x20,0x5f,0x7a,0x37,0x2b,0xb, 0x90,0x61,0x1a,0xe4,0x93,0x7a,0xb3, +0x2b,0x62,0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x90,0x61,0x1c,0xe4,0x93, +0x7a,0xb3,0x2b,0x11,0x74,0x4, 0x7a,0xb3,0x2b,0x13,0x90,0x60,0xd5,0xe4,0x93,0x7a, +0xb3,0x2b,0xf, 0x12,0x57,0xef,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3,0x2b,0x1e,0x7e, +0x34,0x61,0x22,0x12,0x23,0x74,0x7a,0x37,0x2b,0x19,0x90,0x60,0xd3,0x93,0x7a,0xb3, +0x2b,0x12,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x2b,0x20,0x90,0x61,0x19,0xe4,0x93, +0x7a,0xb3,0x2b,0x1f,0x7e,0x34,0x61,0x1e,0x12,0x23,0x74,0x7a,0x37,0x2b,0x15,0x7e, +0x34,0x61,0x20,0x12,0x23,0x74,0x7a,0x37,0x2b,0x17,0x90,0x61,0x1d,0xe4,0x93,0x7a, +0xb3,0x2b,0x14,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a,0x74,0x1, 0x7a,0xb3,0x2b, +0x67,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b,0x66,0x7e,0x34, +0x4, 0x6d,0x7a,0x37,0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74,0x2, 0x7a,0xb3, +0x2b,0x64,0xe4,0x7a,0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60,0xe4,0x7a,0xb3, +0x2b,0x61,0x7e,0x34,0x20,0x65,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca,0x39,0x7e,0x34, +0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x20,0xc3,0x1b,0xfd,0xda, +0x79,0xda,0xd8,0x22,0x12,0x75,0xba,0x12,0x75,0x86,0x90,0x60,0x50,0xe4,0x93,0xa, +0x3b,0x7d,0x13,0x2e,0x14,0x2a,0x7a,0x6d,0x0, 0x9, 0xb3,0x2a,0x79,0x12,0x75,0x6d, +0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2b,0x21,0x6d,0x0, 0x9, 0xb3,0x2b,0x20,0x12,0x75, +0x6d,0xa, 0x1b,0x2e,0x14,0x2a,0x7c,0x12,0x75,0x7a,0xe5,0x25,0x12,0x75,0x71,0xa, +0x1b,0x2e,0x14,0x2b,0x23,0x12,0x75,0x7a,0xe5,0x24,0x2, 0x20,0xe8,0x7e,0x34,0x0, +0x2, 0x12,0x20,0xe8,0x90,0x60,0x50,0xe4,0x93,0x22,0x6d,0x0, 0x90,0x60,0x91,0xe4, +0x93,0xa, 0x3b,0x1b,0x35,0x22,0x6c,0xaa,0x6c,0x99,0x80,0xc, 0xa, 0xf9,0x9, 0xbf, +0x2a,0x7a,0xbc,0xba,0x68,0x7, 0xb, 0x90,0x12,0x75,0xb2,0x38,0xef,0x12,0x75,0xb2, +0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, 0xa0,0x74,0x6e,0x7a,0x1b, +0xb0,0x22,0x90,0x60,0x50,0xe4,0x93,0xbc,0xb9,0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18, +0x0, 0x24,0x22,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0x22,0xca,0x79,0x6c, +0xaa,0x12,0x75,0xc3,0xb, 0x7a,0xf0,0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39, +0x57,0x7f,0x71,0x2d,0xf4,0xb, 0x7a,0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0x77, +0xb, 0xa0,0xbe,0xa0,0x20,0x40,0xda,0x7e,0x8, 0x39,0x57,0x7e,0x18,0x39,0x77,0x74, +0x20,0x12,0xbc,0xc0,0xda,0x79,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x39, +0x53,0xbe,0x70,0x20,0x40,0x52,0x7e,0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74, +0x5, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0x33,0x39,0x53,0xa, 0x13,0x6d,0x0, 0x12,0x1f, +0x7, 0x7c,0xe7,0xbe,0xe0,0x2, 0x50,0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, +0x3e,0x1b,0x34,0x7c,0xc7,0x7f,0x5, 0x7c,0xbd,0x12,0x76,0x71,0x7f,0x6, 0x7c,0xbd, +0x7c,0x7c,0x12,0x76,0x71,0xb, 0xf0,0x7e,0x73,0x39,0x53,0xbc,0x7f,0x50,0xbc,0x7f, +0x5, 0x7f,0x16,0x12,0x75,0xcd,0x80,0x6, 0x74,0x7e,0x7a,0xb3,0x39,0x52,0xda,0x3b, +0x22,0x7c,0x97,0x7c,0xab,0x7f,0x10,0x7e,0x30,0x2, 0xac,0x3a,0x2d,0x13,0x7d,0x2, +0xb, 0xa, 0x10,0x7e,0x10,0x2, 0xac,0x19,0x7f,0x71,0x2d,0xf0,0xb, 0x7a,0x0, 0x7c, +0x21,0xa5,0xba,0x0, 0x14,0xa, 0x3, 0x1b,0x7a,0x0, 0xbc,0x9a,0x68,0x24,0x6d,0x44, +0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x40,0x22,0xbc,0x9a,0x68,0x15,0xa, 0x2, 0xa, +0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a,0x10,0x6d,0x11,0x74,0x2, 0xa4,0x2d,0x35,0x1b, +0x1a,0x10,0x22,0xca,0xf8,0x7e,0x45,0x24,0x7c,0xb9,0x7a,0xb3,0x39,0x53,0x74,0xff, +0x7a,0xb3,0x39,0x52,0x6d,0x55,0x80,0x19,0x7d,0xf5,0x3e,0xf4,0x12,0x77,0xaf,0x7d, +0xe5,0x3e,0xe4,0x59,0xfe,0x1f,0x34,0x69,0xf6,0x0, 0x2, 0x59,0xfe,0x21,0x14,0xb, +0x54,0xbd,0x45,0x38,0xe3,0x7e,0x33,0x39,0x53,0xbe,0x30,0x4, 0x38,0x2, 0xe1,0x85, +0x69,0xf1,0x0, 0x1c,0x69,0x11,0x0, 0x1e,0xbd,0x1f,0x18,0x19,0x4d,0x11,0x78,0x4, +0x7e,0x14,0x0, 0x1, 0x7d,0x3f,0x7d,0x21,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x40,0x7a, +0xb3,0x39,0x56,0x80,0x43,0x4d,0xff,0x78,0x4, 0x7e,0xf4,0x0, 0x1, 0x7d,0x31,0x7d, +0x2f,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x80,0x7a,0xb3,0x39,0x56,0x7d,0xf, 0x2d,0xf, +0xbd,0x1, 0x8, 0x24,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x39,0x56,0xa, 0x37,0x6d,0x22, +0x12,0x1e,0xeb,0x7d,0x5f,0x1a,0x4a,0x1a,0x48,0x7d,0x1f,0x1a,0x2, 0x1a,0x0, 0x2f, +0x2, 0x12,0x1f,0x7, 0x7a,0x73,0x39,0x56,0xbe,0xf0,0x5, 0x58,0x14,0x12,0x77,0xa4, +0x12,0xc9,0xf6,0x12,0x77,0xa4,0x12,0xca,0xa1,0x12,0x77,0xa4,0x12,0x76,0x7, 0x80, +0xa, 0x74,0x7d,0x80,0x2, 0x74,0x7f,0x7a,0xb3,0x39,0x52,0xe4,0x7a,0xb3,0x39,0x53, +0x7e,0x73,0x34,0x4f,0xbe,0x73,0x39,0x52,0x48,0x6, 0x7e,0xb3,0x39,0x54,0x80,0x1, +0xe4,0xda,0xf8,0x22,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x21,0x14,0x22,0x7d,0xf4,0x3e, +0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0,0x22,0x12,0x77,0xea,0x7a,0x37,0x2f,0x9c, +0x12,0x77,0xe1,0x7a,0x37,0x2f,0x9e,0x12,0x8e,0x3, 0x60,0x1, 0x22,0x7e,0x73,0x2f, +0xa8,0xa, 0x37,0x7a,0x35,0x24,0x7e,0x8, 0x2b,0xbf,0x7e,0x18,0x2f,0x80,0x2, 0x76, +0xc3,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37, +0x2f,0x90,0x22,0x7e,0x8, 0x26,0x5b,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x20,0xe8,0x90, +0x60,0x9c,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0x8c,0x74,0xff,0x12,0x20,0xe8, +0x90,0x60,0x9c,0xe4,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0xb4,0x74,0xff,0x12, +0x20,0xe8,0x90,0x60,0x9a,0x12,0x78,0x34,0x7e,0x8, 0x27,0x76,0x74,0xff,0x2, 0x20, +0xe8,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x9, 0xac,0x7b,0x22,0x2, 0x23,0x7c, +0xca,0xf8,0x7e,0x73,0x2a,0x78,0xa, 0x47,0x7e,0x73,0x2a,0x71,0xa, 0x57,0x2d,0x54, +0x7e,0xa3,0x2a,0x73,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x2a,0x72,0x7e,0xa3, +0x2a,0x74,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xb9,0x7e, +0x18,0x2a,0x7a,0x12,0xd, 0xd9,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xdc,0x7e,0x18,0x2a, +0x9d,0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7f,0x60,0x7e,0xa3,0x2a,0x6d,0x7e, +0xb3,0x2a,0x6e,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d,0x3f,0xe4,0x12,0x20,0xe8, +0x7f,0x6, 0x7d,0x3f,0x12,0x20,0xe8,0x7a,0xb3,0x16,0x91,0x22,0x7e,0xf, 0x13,0x8a, +0x7e,0x18,0x8, 0xa, 0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30,0x12,0x7c,0xbb,0x7a,0x55, +0x31,0x7e,0xb3,0x2b,0x1d,0xf5,0x2e,0xe4,0x7a,0xb3,0x2b,0x1d,0x7f,0x3, 0x7e,0x1d, +0x29,0x12,0x78,0x89,0x12,0x6f,0xb8,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0x75,0x2d, +0x0, 0x12,0x7c,0xcc,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x7f,0xcf,0x7e,0x14,0x40,0x0, +0x7d,0x21,0x7d,0x7, 0x12,0x79,0x34,0x12,0x7b,0x7e,0x6d,0x33,0x80,0x19,0x7e,0x35, +0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13,0x12, +0x6f,0xc1,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35,0x2f, +0x38,0xdc,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3,0x2b, +0x1d,0xda,0x3b,0x22,0x7e,0xb3,0x2a,0x6d,0xca,0x3b,0x7c,0xdb,0x7a,0x5, 0x38,0x7d, +0x71,0x7a,0x25,0x36,0x7a,0x35,0x34,0x12,0xae,0xc7,0x40,0x2, 0x21,0xd0,0x6c,0xcc, +0x80,0x14,0x7e,0x73,0x2a,0x6e,0x12,0x7a,0x56,0x12,0x7a,0x5f,0x12,0x7a,0x4d,0x7e, +0x34,0x34,0x0, 0x12,0x7a,0x71,0x12,0x7a,0x89,0x38,0xe7,0x6c,0xcc,0x80,0x5b,0x7e, +0xa3,0x2a,0x6e,0x7c,0x7a,0x12,0x7a,0x56,0x75,0x3a,0x0, 0x80,0x27,0x7e,0xb3,0x38, +0xc5,0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac,0x7c,0x49,0x43,0x32,0xba,0x80, +0x6, 0xac,0x7c,0x49,0x43,0x32,0xbc,0x7e,0x71,0x3a,0x74,0x2, 0xac,0x7b,0x59,0x43, +0x34,0x50,0x5, 0x3a,0x7e,0xb3,0x2a,0x70,0xbe,0xb1,0x3a,0x38,0xd0,0x12,0x7f,0x97, +0x68,0xb, 0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34,0x4e,0x12,0x7a,0x5f, +0x12,0x7a,0x4d,0x7e,0x34,0x34,0x50,0x12,0x7a,0x71,0xbc,0xdc,0x38,0xa1,0x80,0x2c, +0x7a,0xd3,0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x25,0xb7,0xe4,0x7a,0xb3,0x25, +0xb9,0x74,0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0x77,0x25,0xba,0x7a,0x77,0x25,0xbe,0x7e, +0x8, 0x25,0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12,0x80, +0xfc,0x7e,0x35,0x38,0x7a,0x37,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x7a,0x4d, +0x7a,0xd3,0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9,0x7a, +0x77,0x25,0xba,0x7e,0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x25,0xb9,0x7e, +0x35,0x34,0x7a,0x37,0x25,0xba,0x7e,0x35,0x36,0x7a,0x37,0x25,0xbc,0x6d,0x33,0x7a, +0x37,0x25,0xc0,0x7e,0x8, 0x25,0xb6,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x7e,0x73,0x2a, +0x6e,0x7a,0x73,0x25,0xb7,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3,0x22,0x74, +0xc, 0x7a,0xb3,0x25,0xb8,0x74,0x1, 0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9, +0x22,0x7a,0x37,0x25,0xba,0x7d,0x3f,0x7a,0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e, +0x8, 0x25,0xb6,0x12,0x7, 0x9b,0xb, 0xc0,0x22,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x22, +0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x22,0xf3,0x7e,0x4, 0x0, 0xff,0x69,0x30, +0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x3e,0x34, +0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc3,0x1b,0xfd,0x6c,0xdd,0x12,0x7f,0xd7, +0x7a,0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4f,0x12,0x7b,0x6e,0x40,0x48,0x12,0x7b,0x64, +0x50,0x43,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x10,0x7d,0x3f,0x12, +0x21,0x1a,0x7d,0x3, 0x7d,0x31,0x12,0x21,0x1a,0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe, +0x15,0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, +0x8, 0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34, +0x4, 0x7a,0xb3,0x1f,0x34,0xb, 0xc0,0x12,0x7a,0x89,0x38,0xac,0x7e,0x73,0x1f,0x34, +0x4c,0x77,0x68,0x34,0x12,0x8b,0x1e,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, 0x5, +0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e, +0x6c,0xcc,0x80,0xf, 0x12,0x7b,0x6e,0x40,0x8, 0x12,0x7b,0x64,0x50,0x3, 0x12,0x8b, +0x9, 0xb, 0xc0,0x12,0x7a,0x89,0x38,0xec,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x2, 0x41, +0xbd,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc,0xab,0x22,0xa, 0xec, +0x9, 0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0x7e,0xa3, +0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4,0x12,0x20,0xe8,0x90,0x60, +0x93,0x93,0xa, 0x3b,0x7e,0xb3,0x2a,0x71,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xad,0x32, +0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12,0xab,0xa3,0xb, 0xa, 0x0, +0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18,0x20,0x2d,0x20,0x1b,0x18, +0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c,0xcb,0x7e, +0xb3,0x2b,0x1d,0xf5,0x32,0x7e,0xb3,0x2b,0xf, 0xf5,0x33,0x7e,0xd3,0x2b,0x14,0x7e, +0xe3,0x2b,0x1f,0x7e,0xf3,0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x34, +0x0, 0x7e,0x8, 0x24,0xf2,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39, +0x7e,0x18,0x32,0xba,0x7e,0x8, 0x25,0x2a,0x12,0x20,0xc3,0x1b,0xfd,0x7c,0xbc,0x12, +0xa7,0xac,0x74,0x1, 0x7a,0xb3,0x2b,0x1d,0x74,0x5, 0xac,0xbc,0x12,0x7f,0xf1,0x74, +0x5, 0xac,0xbc,0x12,0x7f,0xdf,0x74,0x5, 0xac,0xbc,0x12,0x7f,0xe8,0x74,0x5, 0xac, +0xbc,0x9, 0x75,0x26,0x37,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2, +0xe, 0xc2,0x3, 0x12,0xcc,0xa8,0x12,0xa6,0xa8,0x12,0x7c,0xc5,0x30,0xd, 0xfd,0x74, +0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x13,0x86,0x7d,0x25, +0x7e,0x4, 0xd, 0xc8,0x12,0x79,0x34,0x12,0x7c,0xbb,0x7a,0x55,0x34,0x7e,0xd, 0x2e, +0x7e,0x18,0xd, 0xc8,0x12,0xa1,0xe9,0x12,0xa2,0xa4,0xe5,0x32,0x7a,0xb3,0x2b,0x1d, +0xe5,0x33,0x7a,0xb3,0x2b,0xf, 0x7a,0xd3,0x2b,0x14,0x7a,0xe3,0x2b,0x1f,0x7a,0xf3, +0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x24,0xf2,0x7e,0x8, 0x34,0x0, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x25,0x2a,0x7e, +0x8, 0x32,0xba,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x3b,0x22,0x7e,0xa3,0x2a,0x6e,0x7e, +0xb3,0x2a,0x6d,0xa4,0x22,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, +0x74,0x1, 0x7e,0x70,0x99,0x12,0x13,0x2c,0x2, 0x0, 0x4e,0xca,0x3b,0x7e,0x34,0xff, +0xff,0x7a,0x35,0x34,0x7e,0xb3,0x38,0xc5,0xf5,0x29,0x7e,0xb3,0x2a,0x6d,0xf5,0x2a, +0x7e,0xb3,0x2a,0x6e,0xf5,0x2b,0x7e,0xb3,0x2a,0x70,0xf5,0x2c,0x7e,0xb3,0x2a,0x6f, +0xf5,0x2d,0x7e,0x34,0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30, +0x12,0x7c,0xc5,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12, +0x7f,0xc7,0x6c,0xff,0x80,0x35,0x12,0x7f,0x5b,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b, +0xac,0x1e,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31, +0xb, 0x1a,0x10,0x12,0x7f,0x62,0xe5,0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x7f, +0x71,0x74,0x2, 0xac,0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38, +0xc5,0x12,0x7f,0x97,0x68,0xe, 0x7e,0x34,0x10,0x0, 0x7e,0xa1,0x2b,0x74,0x2, 0xa4, +0x59,0x35,0x33,0xfe,0x6c,0xff,0x80,0x78,0x12,0x7f,0x5b,0x6c,0xee,0x80,0x14,0x12, +0x7f,0xa0,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x13, +0x12,0x7f,0x62,0xe5,0x29,0xbc,0xbe,0x38,0xe6,0xe5,0x29,0x12,0x7f,0x71,0x74,0x4, +0xac,0xbf,0x59,0x35,0x32,0xba,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x35,0x12,0x7f,0x5b, +0x7e,0xe1,0x29,0x80,0x14,0x12,0x7f,0xa0,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60, +0x80,0x14,0x78,0xf4,0x7d,0x13,0x12,0x7f,0x62,0xe5,0x2c,0xbc,0xbe,0x38,0xe6,0xe5, +0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x7f,0x75, +0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x32,0xbc,0xb, 0xf0, +0xe5,0x2d,0xbc,0xbf,0x38,0x82,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0xcc, +0x12,0x1f,0x7, 0x6c,0xff,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, +0x5f,0xad,0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e, +0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59, +0x25,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d, +0x0, 0x7e,0x18,0x0, 0x28,0x12,0x1f,0x7, 0x6c,0xff,0x80,0x5c,0x74,0x4, 0xac,0xbf, +0x49,0x25,0x32,0xba,0xa, 0x1f,0xad,0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2, +0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d, +0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25,0x32,0xba,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26, +0x74,0x4, 0xac,0xbf,0x49,0x25,0x32,0xbc,0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, +0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, +0xac,0xbf,0x59,0x25,0x32,0xbc,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73, +0x38,0xc7,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, +0x64,0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0xe3,0x7a,0xe5,0x34,0x7e,0x73,0x38,0xc8,0xa, +0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7d,0x1f,0x12,0x1f,0x5, 0x7d, +0x63,0x6c,0xff,0x80,0x20,0x74,0x2, 0xac,0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34, +0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x34,0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59, +0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74, +0x4, 0xac,0xbf,0x49,0x45,0x32,0xba,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59, +0x35,0x32,0xba,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x32,0xba,0x49,0x45,0x32, +0xbc,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x32,0xbc,0x80,0x8, 0xbd, +0x46,0x50,0x4, 0x59,0x65,0x32,0xbc,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30, +0x5, 0x6, 0x7e,0xd, 0x30,0x12,0x56,0x93,0xda,0x3b,0x22,0x9f,0x11,0x7a,0x1f,0x24, +0xf4,0x22,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x2f,0x10,0x7a,0x1f,0x24,0xf4,0xb, 0xe0, +0x22,0xa, 0x1b,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x12,0x1f,0x7, 0x7a,0x1f,0x24,0xf4, +0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d,0x22,0x60,0x5, 0x2f,0x11,0x14, +0x78,0xfb,0xb, 0x14,0x2, 0x1f,0x5, 0x90,0x60,0xaa,0xe4,0x93,0xbe,0xb0,0x1, 0x22, +0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d, +0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24,0xf2,0x74,0x2, 0xac,0xbe,0x49,0x35, +0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x20,0xe8,0x12, +0x0, 0xe, 0x7e,0x1f,0x13,0x86,0x22,0x7e,0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22,0x9, +0x75,0x26,0x35,0x7a,0x73,0x2b,0x1f,0x22,0x9, 0x75,0x26,0x36,0x7a,0x73,0x2b,0x20, +0x22,0x9, 0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22,0x7f,0x70,0x7e,0x33,0x2a,0x74, +0xa, 0x43,0x7e,0x33,0x2a,0x73,0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a, +0xb3,0x16,0x90,0x7f,0x1, 0xa, 0x3a,0x12,0x20,0xe8,0x7f,0x7, 0xa, 0x3a,0x2, 0x20, +0xe8,0x7e,0xa3,0x2f,0xa8,0x7e,0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x39,0x1, +0x40,0x39,0x7e,0x37,0x39,0x1, 0xb, 0x34,0x7a,0x37,0x39,0x1, 0xbe,0x34,0x0, 0x1, +0x78,0x5, 0x7e,0xb3,0x3, 0xee,0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba,0x22, +0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x34,0x49,0x22,0x9e, +0x34,0x0, 0x3, 0x2e,0x37,0x2b,0xb9,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x7e,0xa3, +0x38,0xaf,0x7c,0xba,0x4, 0x7a,0xb3,0x38,0xaf,0x7a,0xa3,0x3, 0xac,0x22,0xca,0x7b, +0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82,0x12,0x52,0xc6,0xd0,0x82,0xd0, +0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32,0xa9,0xc0,0x93,0x75,0x18,0x0, +0x32,0x7e,0xb3,0x39,0x5, 0x4, 0x7a,0xb3,0x39,0x5, 0xe5,0x19,0xb4,0x1, 0x8, 0xe4, +0x7a,0xb3,0x39,0x5, 0x75,0x19,0x0, 0x7e,0x73,0x39,0x5, 0x7a,0x73,0x3, 0xaa,0x22, +0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x39,0x3, 0x4d,0x22,0x78,0xe, +0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x39,0x3, 0x15,0x1a,0x7e,0x27, +0x39,0x3, 0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, 0x2, +0x80,0x2, 0x6d,0x33,0x7a,0x37,0x39,0x3, 0x75,0x1a,0xea,0x22,0x7d,0xf3,0x6d,0xee, +0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x6d,0xf2,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f, +0x57,0x2d,0xbc,0xb, 0x5a,0x10,0x1a,0x2, 0x1a,0x0, 0x7e,0x83,0x2b,0x20,0xa, 0x98, +0x6d,0x88,0x7f,0x10,0x7f,0x4, 0x12,0x1e,0xeb,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e, +0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90, +0x7e,0x83,0x2a,0x75,0xbc,0x89,0x38,0xbc,0x22,0x7f,0x20,0xb, 0x2a,0x10,0xb, 0x1a, +0x0, 0x1b,0x2a,0x0, 0x1b,0x1a,0x10,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e, +0x60,0xfd,0x68,0x21,0x1b,0x61,0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b,0x61,0x68,0x15, +0x1b,0x60,0x68,0x11,0x2e,0x60,0xa, 0x78,0x4, 0x7a,0x73,0x3, 0x9a,0xa, 0x2b,0x19, +0x72,0x3, 0x9b,0xd2,0xf, 0x22,0x7e,0x24,0x3, 0x9b,0x30,0xf, 0x62,0xc2,0xf, 0x9, +0x72,0x0, 0x2, 0xa, 0x37,0x12,0x4f,0x96,0x7a,0x37,0x2a,0x4f,0x9, 0x72,0x0, 0x3, +0xa, 0x37,0x12,0x4f,0x96,0x7a,0x37,0x2a,0x51,0x9, 0x72,0x0, 0x4, 0xa, 0x37,0x12, +0x4f,0x96,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a, +0x37,0x2a,0x5a,0x9, 0x72,0x0, 0x1, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a,0x37,0x2a, +0x5c,0x9, 0x72,0x0, 0x5, 0xa, 0x37,0x12,0x4f,0x96,0x7a,0x37,0x2a,0x62,0x9, 0x72, +0x0, 0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a,0x73,0x2a,0x6b,0x2, 0x47,0xec,0x22, +0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b, +0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80,0xa, 0x38,0x9d,0x32,0x12,0x21,0x1a,0xe5,0x29, +0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba, +0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, +0x70,0x22,0x7d,0xc3,0x7e,0x34,0x61,0x37,0x12,0x83,0x38,0x90,0x61,0x35,0xe4,0x93, +0x70,0x3, 0x7d,0x3c,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x2a, +0x70,0x80,0x4, 0x7e,0x83,0x2a,0x6f,0x12,0x5f,0xf3,0xbe,0xc4,0x0, 0x3f,0x38,0x20, +0x7e,0xe4,0x0, 0x3f,0x9d,0xec,0x7e,0x34,0x61,0x3b,0x12,0x83,0x26,0x7c,0x65,0x7f, +0x71,0x12,0x83,0x15,0xbf,0x71,0x40,0x2, 0x7f,0x71,0x9f,0x17,0x7f,0x71,0x61,0x12, +0x12,0x5d,0x5f,0xbd,0x5c,0x38,0x25,0x7d,0xec,0x9d,0xe5,0x7e,0x34,0x61,0x3d,0x12, +0x83,0x26,0x7c,0x65,0x7f,0x71,0x90,0x61,0x3a,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40, +0x4, 0x7f,0x71,0x1b,0x7c,0x12,0x83,0x1d,0x2f,0x71,0x80,0x66,0x7d,0xb4,0xb, 0xb4, +0x1e,0xb4,0x7d,0x5b,0x1b,0x54,0xbd,0x5c,0x40,0xc, 0x7d,0xf5,0x9d,0xfc,0x6d,0xee, +0x7e,0x34,0x61,0x3f,0x80,0xa, 0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x34,0x61,0x41, +0x12,0x84,0x5f,0x7f,0x17,0x12,0x1e,0xfc,0x7f,0x71,0x12,0x46,0xb6,0x7f,0x71,0xbd, +0x5c,0x7d,0x3d,0x40,0xc, 0x1e,0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80, +0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71,0x12,0x83,0x15,0x6d,0x22,0xbf,0x71,0x50,0x4, +0x7f,0x71,0x80,0xe, 0x90,0x61,0x3a,0xe4,0x93,0x12,0x83,0x1d,0xbf,0x71,0x28,0x2, +0x7f,0x71,0x7d,0x3f,0x22,0x90,0x61,0x39,0xe4,0x93,0xa, 0x3b,0x22,0xa, 0x2b,0x7d, +0x3d,0x9d,0x32,0x6d,0x22,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xad,0xfe,0x6d, +0xee,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x22, +0xca,0xd8,0xca,0x79,0x12,0x87,0xe3,0xb, 0x1a,0x40,0x90,0x61,0x35,0xe4,0x93,0x70, +0x2, 0x61,0xeb,0x90,0x60,0xa7,0xe4,0x93,0x70,0x2, 0x61,0xeb,0x6c,0xff,0x61,0xe4, +0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x29,0xc, 0x5e,0xe0,0xf, 0x49,0xc3,0x29,0xa, +0x7e,0x14,0x60,0xd1,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x2d,0x24,0xbd,0xc2,0x40, +0x42,0x49,0xd3,0x29,0x8, 0x7d,0x3d,0x12,0x84,0x24,0x7c,0xdb,0x90,0x60,0xa7,0xe4, +0x93,0xbc,0xbd,0x38,0xe, 0x7d,0x34,0x1b,0x34,0x12,0x83,0xf0,0x7c,0xbe,0x12,0x83, +0xf9,0x80,0x3f,0x7e,0x70,0x2, 0xac,0x7d,0x2e,0x34,0x60,0xc5,0x12,0x83,0x38,0x74, +0x9, 0xac,0xbf,0x59,0xd5,0x29,0x8, 0x7e,0x34,0x60,0xcf,0x12,0x23,0x74,0x12,0x83, +0xf0,0x80,0x1f,0xbd,0xc4,0x40,0x1b,0x7d,0x54,0x2e,0x54,0x0, 0xa, 0xbd,0xc5,0x40, +0x5, 0x7c,0xbe,0x12,0x83,0xf9,0x7d,0xc4,0x1b,0xc4,0x74,0x9, 0xac,0xbf,0x59,0xc5, +0x29,0xa, 0xb, 0xf0,0x12,0x3b,0xe3,0x28,0x2, 0x61,0x60,0xda,0x79,0xda,0xd8,0x22, +0x74,0x9, 0xac,0xbf,0x59,0x35,0x29,0xa, 0x22,0x7c,0xab,0x7e,0x8, 0x29,0xbc,0x12, +0x39,0x49,0x28,0x1f,0xa, 0x3a,0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0,0xb4,0x2, 0x4, +0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x31,0x7d,0x20,0x39, +0xb1,0x0, 0xa, 0x22,0x6c,0xaa,0x80,0x23,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e, +0xf4,0x60,0xb1,0x12,0x84,0x57,0xbd,0x23,0x38,0xf, 0x2e,0x14,0x60,0xb3,0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x23,0x50,0xb, 0xb, 0xa0,0x90,0x60,0xa7,0xe4,0x93, +0xbc,0xba,0x38,0xd4,0x7c,0xba,0x22,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0x22,0x7e, +0x24,0x0, 0xff,0xb, 0x1a,0x10,0x22,0x12,0x9d,0xc3,0x12,0x84,0xc4,0x12,0x86,0xd7, +0x12,0x86,0x4e,0x7e,0xb3,0x3, 0xc0,0xb4,0x1, 0x1e,0x7e,0x34,0x61,0xc6,0x12,0x84, +0x5f,0x7e,0x24,0x0, 0x5, 0xad,0x12,0x7a,0x17,0x28,0xa1,0x7e,0x14,0x61,0xc8,0x12, +0x5b,0x79,0xad,0x32,0x7a,0x37,0x28,0xa3,0x7e,0xb3,0x39,0xfa,0x60,0x7, 0x14,0x7a, +0xb3,0x39,0xfa,0x80,0x6, 0x7e,0xb3,0x28,0xac,0x60,0x9, 0x12,0x87,0x53,0x12,0x87, +0x70,0x12,0xbf,0xe1,0x7e,0xb3,0x28,0xad,0x60,0x9, 0x12,0xc3,0xa4,0x12,0xa3,0x33, +0x2, 0xab,0xb9,0x22,0x7e,0x90,0x1, 0x7e,0x94,0x61,0xc6,0x7e,0x84,0x0, 0xff,0xb, +0x4a,0x30,0x7a,0x37,0x28,0xa1,0x7e,0xb4,0x61,0xc8,0x7e,0xa4,0x0, 0xff,0xb, 0x5a, +0x30,0x7a,0x37,0x28,0xa3,0x12,0x87,0x67,0xb, 0x1a,0x20,0x7e,0x14,0x61,0x4f,0x7e, +0x4, 0x0, 0xff,0xb, 0xa, 0xd0,0xe4,0x7a,0xb3,0x28,0xac,0x12,0x86,0x2e,0x7e,0x34, +0xff,0xfa,0xad,0x32,0x12,0x9a,0x73,0x7d,0xc3,0xe, 0x34,0x7e,0x27,0x7, 0xfe,0xbd, +0x2c,0x58,0x1c,0x7e,0xc7,0x7, 0xfc,0xbd,0xc3,0x58,0x14,0x6d,0xcc,0x9e,0xc7,0x2a, +0x5a,0xbe,0xc7,0x28,0x8e,0x8, 0x8, 0x12,0xa3,0x9a,0x60,0x3, 0x12,0xa5,0x3b,0x12, +0xa5,0x4a,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12,0x87,0xc9,0x68,0x6, 0x7e,0xb3, +0x33,0xfe,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x6f,0x12,0x86,0x35,0x28,0x5, +0xe4,0x7a,0xb3,0x28,0xad,0x30,0x12,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0xa5,0x88, +0x50,0xa, 0x12,0x86,0x2e,0x12,0x86,0x6b,0x7c,0x9b,0x80,0x17,0x7e,0xb3,0x26,0x84, +0x70,0x11,0x7e,0xb3,0x26,0x85,0x70,0xb, 0x12,0x86,0x35,0x28,0x6, 0x7e,0x90,0x3, +0x12,0x86,0x2e,0x7e,0xc7,0x7, 0xfa,0xbe,0xc4,0x5, 0xdc,0x8, 0x17,0x12,0x86,0x35, +0x28,0x12,0x6d,0xcc,0x9d,0xcd,0xbe,0xc7,0x28,0x8e,0x58,0x8, 0x12,0x86,0x40,0xe4, +0x7a,0xb3,0x28,0xad,0xa, 0x29,0xb, 0x4a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa1,0xa, +0x29,0xb, 0x5a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa3,0x12,0x86,0x3d,0x50,0xd, 0xe4, +0x7a,0xb3,0x28,0xad,0x12,0x87,0xc1,0x28,0x3, 0x12,0x86,0x40,0x7e,0xc7,0x28,0x8a, +0xbd,0xcd,0x8, 0x1f,0x7e,0x24,0x0, 0x2, 0x7d,0x3d,0x12,0x1e,0xb9,0x6e,0x34,0xff, +0xff,0xb, 0x34,0xbe,0x37,0x28,0x8e,0x58,0xa, 0x12,0x86,0x3d,0x50,0x5, 0xe4,0x7a, +0xb3,0x28,0xad,0x12,0x99,0x34,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0xa4, +0xa2,0x7e,0xb3,0x0, 0x63,0xbe,0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x0, 0x63,0x70, +0x1c,0xe4,0x7a,0xb3,0x28,0xad,0x74,0x1, 0x7a,0xb3,0x28,0xac,0xe4,0x7a,0xb3,0x16, +0x91,0x7a,0xb3,0x16,0x90,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x26,0x83,0x22,0x74,0x1, +0x7a,0xb3,0x28,0xad,0x22,0x7e,0x83,0x28,0x84,0xbe,0x80,0x0, 0x22,0xa2,0x15,0x22, +0xe4,0x7a,0xb3,0x0, 0x63,0x7a,0xb3,0x28,0xac,0x74,0x2, 0x2, 0x2a,0x28,0x12,0xad, +0xa3,0x60,0x17,0x12,0x86,0x2e,0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1, +0x7e,0x37,0x28,0xa3,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0x7e,0xa0,0x1, 0x7e,0x47, +0x7, 0xf8,0x12,0x87,0x67,0xb, 0x1a,0x0, 0x7e,0x34,0xff,0xfa,0xad,0x30,0x7e,0x14, +0x0, 0x2, 0x12,0x86,0xcf,0x8, 0x12,0x7e,0xb3,0x28,0xac,0x60,0x7, 0xe4,0x7a,0xb3, +0x28,0xad,0x80,0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x12, +0x86,0xcf,0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x23,0x7e,0x34,0xff,0xfc,0xad,0x30,0x12, +0x86,0xcf,0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x13,0x7e,0x34,0xff,0xfd,0xad,0x30,0x12, +0x86,0xcf,0x8, 0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7d, +0x21,0x12,0x1e,0xb9,0xbd,0x34,0x22,0xc2,0x3, 0x12,0x45,0xd2,0x50,0x4b,0x6c,0xaa, +0x80,0x39,0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26,0xfb,0xbe, +0x70,0x0, 0x28,0x25,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27,0xbd,0x21, +0x58,0x17,0xbe,0x60,0x0, 0x28,0x12,0x7e,0xb3,0x2a,0x70,0x1e,0xb0,0xa, 0x1b,0xa, +0x26,0xbd,0x21,0x58,0x4, 0xd2,0x3, 0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc, +0xba,0x38,0xbf,0x20,0x3, 0x3, 0x12,0x86,0x2e,0x30,0x18,0x23,0x5, 0x60,0xe5,0x60, +0xbe,0xb0,0x50,0x50,0x16,0x7e,0x34,0x61,0xc6,0x12,0x23,0x74,0x3e,0x34,0x12,0x87, +0xda,0x12,0x23,0x74,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0xc2,0x18,0x80,0x0, 0x75, +0x60,0x0, 0x22,0x12,0xa4,0xfc,0x12,0x87,0x8d,0x2, 0x87,0x5c,0x12,0xae,0xc7,0x50, +0x3, 0xd2,0x11,0x22,0xc2,0x11,0x22,0x7e,0x34,0x61,0x55,0x7e,0x24,0x0, 0xff,0x22, +0x12,0xa7,0xe1,0x6d,0x33,0x7a,0x37,0x38,0x50,0x6c,0xaa,0x80,0x5, 0x12,0xac,0x7, +0xb, 0xa0,0x12,0x5f,0xcb,0x38,0xf6,0xe4,0x7a,0xb3,0x37,0xe5,0x22,0x7e,0x8, 0x24, +0xf2,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x20,0xe8,0x12,0x87,0xf5,0x12,0x87,0xec,0xa9, +0xd1,0xcb,0x12,0x7f,0xcf,0x7a,0x37,0x24,0xf6,0x7e,0x1f,0x33,0xe0,0x7a,0x37,0x24, +0xf8,0x7e,0x1f,0x13,0x86,0x7a,0x37,0x24,0xfa,0x6d,0x33,0x12,0x87,0xd1,0x2, 0xd, +0x7, 0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0x7e,0xb3,0x28,0xa8,0xbe,0xb0,0x1, +0x22,0x7a,0x37,0x24,0xfc,0x7e,0x8, 0x24,0xf2,0x22,0x7a,0x37,0x28,0xa1,0x7e,0x34, +0x61,0xc8,0x22,0x7e,0x34,0x61,0x43,0x7e,0x24,0x0, 0xff,0x22,0x7e,0x73,0x2a,0x6d, +0x7a,0x73,0x24,0xf2,0x22,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x2, 0x88, +0x1, 0xca,0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c,0xee,0x80,0x35,0x7c,0xbe,0x12, +0x30,0xa4,0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0x2e,0x5f,0x60,0x23,0x7e,0xc4,0x0, +0x9, 0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x27,0x76,0x6d,0x22,0x7e,0x30, +0x9, 0xac,0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0xb, 0xf0, +0xb, 0xe0,0x12,0x47,0xe5,0x38,0xc6,0x7a,0x73,0x28,0x93,0x7a,0xf3,0x2a,0x2, 0xda, +0x79,0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0xb, +0x14,0x12,0x1f,0x5, 0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28,0x4, 0x7e,0x54,0x0, 0x40, +0x22,0xca,0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f,0x3a,0x7e,0x34,0x15,0x9e,0x7a, +0x37,0x1f,0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3,0x1f,0x35,0x7e,0x73,0x2a,0x6f, +0x7a,0x73,0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3,0x1f,0x38,0x7a,0xb3,0x1f,0x39, +0x7e,0x8, 0x1f,0x34,0x12,0x47,0xf4,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15, +0xa0,0x2f,0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12,0x1f,0x7, 0xa, 0x1f,0x6d,0x0, +0x12,0x1f,0x7, 0xda,0xf8,0x22,0x7a,0x37,0x1f,0x38,0x7e,0x34,0x15,0xa8,0x7a,0x37, +0x1f,0x3c,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a,0x7e,0x73,0x2a,0x6f,0x7a,0x73, +0x1f,0x35,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34,0x7e,0x37,0x2a,0x5c,0x7a,0x37, +0x1f,0x3e,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40,0x7e,0x37,0x2a,0x60,0x7a,0x37, +0x1f,0x42,0x74,0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3,0x1f,0x37,0x7e,0x8, 0x1f,0x34, +0x7e,0x18,0x1f,0x44,0x12,0x8, 0x0, 0x7e,0x37,0x1f,0x4e,0x7e,0x27,0x1f,0x4a,0xbd, +0x23,0x28,0x2, 0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, 0x1f,0x34,0x12,0x7f,0xc7,0x7e, +0x1f,0x39,0xea,0x7a,0x1d,0x27,0x7e,0xb3,0x2a,0x74,0xf5,0x2e,0x7e,0xb3,0x39,0x9a, +0xb4,0x1, 0x6, 0x7e,0x38,0x39,0x9c,0x80,0x4, 0x7e,0x38,0x5, 0xf8,0x6d,0x33,0x7a, +0x35,0x2b,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39,0x9b,0x70,0xe, 0x7e,0xb3,0x39, +0x99,0x70,0x8, 0x74,0x1, 0x7a,0xb3,0x39,0x9b,0x21,0xee,0x7e,0xb3,0x39,0x9b,0x70, +0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x9b,0x7e,0xb3,0x39,0x9a,0xb4,0x1, 0x14,0x75,0x2d, +0x0, 0x80,0x6, 0x12,0x8a,0x30,0x12,0x8a,0x3e,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xf3, +0x80,0x18,0x75,0x2d,0x0, 0x80,0xc, 0x12,0x8a,0x30,0x3e,0x24,0x3e,0x24,0x1e,0x24, +0x12,0x8a,0x3e,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e,0x34,0x61,0x5b,0x12,0x23, +0x74,0x7a,0x35,0x2f,0x7e,0x18,0x1f,0x34,0x7f,0x1, 0x12,0x8a,0x4f,0x75,0x2d,0x0, +0x80,0x10,0x12,0x8a,0x23,0xbe,0x35,0x2b,0x8, 0x6, 0x12,0x8a,0x23,0x7a,0x35,0x2b, +0x5, 0x2d,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xe9,0x12,0x8a,0x1b,0x40,0x25,0x7e,0xb3, +0x39,0x9a,0xb4,0x1, 0x1e,0x5, 0x1e,0xe5,0x1e,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x1e, +0x0, 0xe5,0x2e,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, 0x12,0x20, +0xc3,0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x8a,0x1b,0x50,0xb, 0x74,0x2, 0x7a, +0xb3,0x39,0xe9,0xe4,0x7a,0xb3,0x39,0x9b,0xda,0x3b,0x22,0x7e,0x37,0x2b,0x7, 0xbe, +0x35,0x2b,0x22,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x49,0x35,0x1f,0x34,0x2, 0x21,0x1a, +0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7e,0xd, +0x27,0x2d,0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35,0x1f,0x34,0x5, 0x2d,0x22,0xca, +0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x2a,0x6e,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f, +0x16,0x7f,0x5, 0x12,0x20,0xc3,0x1b,0xfd,0x6c,0xdd,0x12,0x7f,0xd7,0x7a,0xb3,0x1f, +0x6c,0x6c,0xcc,0x80,0x4a,0x12,0x8a,0xf8,0x78,0x43,0x74,0x2, 0xac,0xbc,0x7f,0x16, +0x2d,0x35,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x21,0x1a,0x7d,0x13,0x7d,0x3e,0x12,0x21, +0x1a,0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f,0x8, 0x5, 0x7e,0xe5,0x2f,0x80, +0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, 0x7d,0xe3,0x7d,0x3e,0x1a,0x26, +0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x6c,0x4, 0x7a,0xb3,0x1f,0x6c,0xb, 0xc0,0x7e, +0x73,0x2a,0x70,0xbc,0x7c,0x38,0xae,0x7e,0x73,0x1f,0x6c,0x4c,0x77,0x68,0x1d,0x12, +0x8b,0x1e,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80,0xa, 0x12,0x8a,0xf8,0x78,0x3, 0x12, +0x8b,0x9, 0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xee,0xb, 0xd0,0xbe,0xd0, +0x2, 0x50,0x2, 0x41,0x6a,0xda,0x3b,0x22,0xa, 0xec,0x9, 0x7e,0x2a,0xdc,0xa, 0x37, +0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d, +0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b,0x1a,0xe0,0x22,0xa, 0x17, +0x6d,0x0, 0x7f,0x14,0x12,0x1f,0x58,0x7d,0x73,0x12,0x21,0x1a,0x7d,0xe3,0x7d,0x3f, +0x12,0x21,0x1a,0xbd,0x3e,0x22,0x12,0x26,0x82,0x7e,0x73,0x3, 0x9a,0xbe,0x70,0xff, +0x68,0x13,0xbe,0x73,0x3, 0xc0,0x68,0xd, 0x7a,0x73,0x3, 0xc0,0x74,0xff,0x7a,0xb3, +0x3, 0x9a,0x2, 0x26,0x82,0x22,0x7e,0x34,0x61,0x57,0x7e,0x24,0x0, 0xff,0xb, 0x1a, +0x20,0x12,0x8b,0x71,0x50,0x8, 0x7e,0x27,0x2a,0x4f,0x1e,0x24,0x1e,0x24,0x7d,0x32, +0x22,0xc2,0x3, 0x12,0x8b,0x99,0x68,0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17,0x7e, +0xb3,0x37,0xe4,0x70,0x11,0x12,0x45,0xd2,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe,0x34, +0x1, 0x90,0x58,0x2, 0xd2,0x3, 0xa2,0x3, 0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, +0x22,0x7c,0xab,0x7e,0xb3,0x33,0xfe,0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70,0x11,0x12, +0x8f,0xa0,0x68,0xc, 0x12,0x8b,0x99,0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x2e,0xdd, +0x22,0xca,0xd8,0xca,0x79,0xc2,0x3, 0x6d,0x88,0x7a,0x87,0x39,0x50,0xe4,0x7a,0xb3, +0x1f,0x58,0xe5,0x1f,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x1f,0x7e,0xb3,0x28,0x84,0x60, +0xc, 0x12,0x87,0x67,0xb, 0x1a,0x80,0xbe,0x87,0x7, 0xfa,0x28,0xa, 0xc2,0x12,0x6d, +0x88,0x7a,0x87,0x39,0x11,0x81,0xf2,0x12,0x90,0xab,0x60,0x12,0x7e,0x34,0x62,0x14, +0x12,0x8d,0xfb,0x7a,0x87,0x39,0x7, 0x12,0x8d,0x5c,0x7a,0x87,0x39,0x11,0x7e,0x87, +0x39,0x7, 0x4d,0x88,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x77, +0xe4,0xa, 0x3f,0x19,0xb3,0x1f,0x34,0x12,0x8d,0x76,0x7e,0x8, 0x1f,0x52,0x7c,0xbd, +0x7c,0x7e,0x12,0x35,0x1e,0x7d,0x93,0x7e,0x87,0x39,0x11,0xbd,0x89,0x50,0x4, 0x7a, +0x97,0x39,0x11,0x7e,0x87,0x39,0x50,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x50,0xe5, +0x1f,0xbe,0xb0,0x5, 0x38,0x1f,0x7e,0x8, 0x39,0x13,0x12,0x8d,0x83,0x50,0x7, 0x12, +0x8d,0x6d,0xd2,0x3, 0x80,0x2f,0x7e,0x8, 0x39,0x13,0x7e,0x18,0x1f,0x52,0x12,0x8d, +0xc9,0x50,0x22,0x80,0x10,0x12,0x8d,0x5c,0xbd,0x89,0x38,0x19,0x7e,0x8, 0x1f,0x52, +0x12,0x90,0x5c,0x50,0x10,0x12,0x8d,0x6d,0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52, +0x12,0x8f,0xd7,0xd2,0x3, 0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38,0x81,0x30, +0x3, 0x36,0x6c,0xff,0x80,0x1c,0x12,0x8d,0x76,0x7e,0x8, 0x1f,0x58,0x12,0x8d,0x83, +0x40,0x9, 0xa, 0x3f,0x9, 0xb3,0x1f,0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x8b,0xa1, +0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38,0xdc,0x75,0x1f,0x0, 0x7e,0x34,0x62, +0x14,0x12,0x23,0x74,0x7a,0x37,0x39,0x7, 0x7e,0x63,0x1f,0x58,0x7e,0x70,0x6, 0xac, +0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1f,0x58,0x7e,0x8, 0x39,0x13,0x12,0x20,0xc3, +0x1b,0xfd,0x7e,0x37,0x39,0x7, 0x4d,0x33,0x78,0x39,0x90,0x62,0xf, 0xe4,0x93,0xa, +0x3b,0xbe,0x37,0x39,0x11,0x38,0x43,0x7c,0x7b,0x1e,0x70,0xa, 0x37,0xbe,0x37,0x39, +0x50,0x38,0x37,0x90,0x60,0x51,0x12,0x8d,0x64,0x7e,0x73,0x26,0xf7,0xa, 0x37,0xbd, +0x32,0x8, 0x27,0x90,0x60,0x50,0x12,0x8d,0x64,0x7e,0x73,0x26,0xf6,0xa, 0x37,0xbd, +0x32,0x8, 0x17,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12,0x8b,0xa1,0xb, 0xf0,0x7e,0x73, +0x28,0x84,0xbc,0x7f,0x38,0xf1,0xd2,0x3, 0x80,0x6, 0x6d,0x33,0x7a,0x37,0x39,0x11, +0xa2,0x3, 0x92,0x12,0x12,0x8f,0xa8,0xda,0x79,0xda,0xd8,0x22,0x90,0x62,0xf, 0xe4, +0x93,0xa, 0x8b,0x22,0xe4,0x93,0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, +0x8f,0x19,0xb8,0x1f,0x34,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5, +0x26,0xfb,0x22,0x7c,0xbd,0x7c,0x7e,0x7c,0x6b,0xc2,0x4, 0x6c,0xaa,0x80,0x30,0x7e, +0x50,0x6, 0xac,0x5a,0x7f,0x70,0x2d,0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6, +0x40,0x1b,0x7e,0x7b,0xb0,0xbc,0xb6,0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40, +0xc, 0x29,0xb7,0x0, 0x1, 0xbc,0xb7,0x38,0x4, 0xd2,0x4, 0x80,0x9, 0xb, 0xa0,0x7e, +0xb, 0xb0,0xbc,0xba,0x38,0xc9,0xa2,0x4, 0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90, +0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x8d, +0x87,0x50,0x2, 0xd3,0x22,0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, +0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79,0x50,0xd9,0xc3,0x22,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x80,0x22,0xca,0xf8,0x6c,0xff,0x7e,0xb7,0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e, +0x97,0x2f,0x84,0x7e,0xd7,0x2f,0x86,0x7e,0xa7,0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4, +0x7e,0x73,0x2f,0xa8,0x1b,0x70,0x7d,0x2b,0x7d,0x1c,0x12,0x8f,0x4b,0x70,0x2, 0xe1, +0x32,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0xa, 0x28,0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27, +0x2f,0xa0,0x7e,0x17,0x2f,0xa2,0x12,0x8f,0x4b,0x70,0x2, 0xe1,0x32,0x7e,0x73,0x2f, +0xa8,0xbe,0x70,0x14,0x28,0x13,0xe4,0x7e,0x70,0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17, +0x2f,0xa6,0x12,0x8f,0x4b,0x70,0x2, 0xe1,0x32,0x7e,0x34,0x62,0x78,0x12,0x8f,0x37, +0x28,0x4a,0x7e,0x34,0x62,0x76,0x12,0x8f,0x41,0x50,0x41,0x7e,0xb3,0x2f,0x81,0x70, +0x3b,0x7e,0x34,0x62,0x7c,0x12,0x23,0x74,0x12,0x5e,0xa6,0x7d,0x8f,0x9d,0x83,0xbe, +0x87,0x2f,0x82,0x50,0x27,0x7e,0x34,0x62,0x7a,0x12,0x8d,0xfb,0x9d,0xf8,0xbe,0xf7, +0x2f,0x82,0x28,0x18,0x7d,0xfc,0x3e,0xf4,0xbd,0xfb,0x40,0x2, 0xe1,0x32,0xbd,0xa9, +0x50,0x5, 0x7e,0xf0,0x20,0x80,0x7b,0x7e,0xf0,0x21,0x80,0x76,0x7e,0x34,0x62,0x80, +0x12,0x8f,0x41,0x28,0x6d,0x7e,0x34,0x62,0x7e,0x12,0x8f,0x37,0x50,0x64,0x7e,0xb3, +0x2f,0x81,0x70,0x5e,0x7e,0x34,0x62,0x84,0x12,0x23,0x74,0x12,0x5e,0xa6,0x7d,0xaf, +0x9d,0xa3,0xbe,0xa7,0x2f,0x82,0x50,0x4a,0x7e,0x34,0x62,0x82,0x7e,0x24,0x0, 0xff, +0xb, 0x1a,0xa0,0x9d,0xfa,0xbe,0xf7,0x2f,0x82,0x28,0x37,0x7d,0xfb,0x3e,0xf4,0xbd, +0xfc,0x50,0x2f,0xbd,0xed,0x50,0x5, 0x7e,0xf0,0x22,0x80,0x26,0x12,0x5f,0xd3,0x49, +0x35,0x2b,0xbb,0x49,0x15,0x2b,0xbd,0x49,0x25,0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d, +0x10,0xbe,0x14,0x0, 0x20,0x18,0x8, 0x9d,0x32,0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e, +0xf0,0x23,0x7c,0xbf,0xda,0xf8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xbd,0xfc, +0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xbd,0xfb,0x22,0x7d,0x41,0x7d,0x2, 0x7c, +0x37,0x7c,0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35,0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74, +0x4, 0xac,0xb3,0x49,0x25,0x2b,0xbf,0x49,0x55,0x2b,0xc1,0x12,0x47,0x7d,0x7d,0x3f, +0x9d,0x35,0x12,0x21,0x1a,0x9d,0x34,0x12,0x21,0x1a,0x7e,0x54,0x62,0x70,0x7e,0x44, +0x0, 0xff,0xb, 0x2a,0x20,0xbd,0x32,0x50,0x15,0x12,0x5f,0xc4,0x7e,0x14,0x62,0x70, +0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x32,0x50,0x3, 0x74,0x1, 0x22,0xe4,0x22, +0x7e,0xb3,0x3, 0xeb,0xbe,0xb0,0x1, 0x22,0x30,0x12,0x13,0x12,0x87,0xc9,0x68,0x6, +0x7e,0xb3,0x33,0xfe,0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x39,0xf, 0x22,0x12, +0x8b,0x71,0x50,0x12,0x7e,0x37,0x2b,0x7, 0xbe,0x34,0x1, 0x2c,0x28,0x8, 0x7e,0x34, +0x1, 0x2c,0x7a,0x37,0x2b,0x7, 0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe,0xa0,0xa, 0x50, +0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d,0x15,0xb, 0x14, +0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22,0x7e,0xb3,0x3, +0xc0,0x70,0x2e,0x7e,0x73,0x3, 0xa3,0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77,0x7e,0xb3, +0x3, 0xeb,0xb4,0x1, 0x3, 0x7e,0x70,0x6, 0xa, 0x37,0x2e,0x34,0xf, 0xf0,0x12,0x6f, +0xee,0x7c,0xab,0xe5,0x62,0xa, 0x3b,0x2e,0x37,0x39,0x97,0x7a,0x37,0x39,0x97,0x80, +0xc, 0x7e,0xa3,0x3, 0xa4,0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, +0x90,0x42,0x75,0x62,0x0, 0x7a,0xb3,0x3, 0xfe,0xc2,0x1a,0x22,0x7e,0xb3,0x39,0x9a, +0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x9a,0x22,0x7f,0x20,0xc2,0x4, +0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x21,0x1a,0x7c,0x27, +0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x21,0x1a,0x7c, +0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x21,0x1a,0x7c,0x67,0x7c,0x72,0xbc,0x32, +0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e,0x37, +0x39,0x7, 0x4d,0x33,0x68,0x2, 0xd2,0x4, 0xa2,0x4, 0x22,0x6c,0xaa,0x7e,0x63,0x2a, +0x6e,0x7e,0x73,0x2a,0x6d,0xac,0x76,0x7d,0x13,0x1e,0x14,0x7e,0x27,0x28,0x88,0x2e, +0x27,0x28,0x86,0xbd,0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34,0xbe,0x37,0x28,0x86,0x50, +0x29,0x90,0x60,0x51,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26,0xf7,0xa, 0x3b, +0xbd,0x32,0x8, 0x16,0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26, +0xf6,0xa, 0x3b,0xbd,0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7e,0xa3,0x2a, +0x3, 0xbe,0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, +0xbe,0xb3,0x37,0x30,0x28,0x14,0x7e,0xb3,0x37,0x30,0x4, 0x7a,0xb3,0x37,0x30,0x7a, +0xa3,0x2a,0x2, 0x80,0x5, 0xe4,0x7a,0xb3,0x37,0x30,0x7e,0xb3,0x2a,0x2, 0x70,0x5, +0xe4,0x7a,0xb3,0x2a,0xb, 0x22,0x12,0x91,0x3c,0x2, 0x90,0xfd,0x7e,0xb3,0x2a,0x2, +0x70,0x2d,0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x28,0x24,0x7e,0xb3,0x36,0xb5,0x70, +0x18,0x12,0x91,0x79,0x7e,0x73,0x2a,0x3, 0x7a,0x73,0x2a,0x2, 0x74,0x1, 0x7a,0xb3, +0x2a,0x9, 0x7e,0xb3,0x36,0xb5,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x36,0xb5,0x22,0xe4, +0x7a,0xb3,0x36,0xb5,0x7a,0xb3,0x2a,0x9, 0x22,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e, +0x18,0x33,0x4c,0x7e,0x8, 0x33,0x88,0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x73,0x28,0x94, +0x7a,0x73,0x33,0x48,0x7a,0x73,0x28,0x93,0x22,0xca,0x3b,0x6d,0x11,0x7d,0x1, 0x7e, +0xe3,0x2a,0x2, 0x4c,0xee,0x78,0x23,0x6c,0xff,0x80,0x1a,0x74,0x2, 0xac,0xbf,0x12, +0x93,0x6a,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x36,0xba,0x74,0x2, 0xa, 0x3f,0x19, +0xb3,0x37,0x24,0xb, 0xf0,0x12,0x3b,0xe3,0x38,0xe1,0x12,0x94,0x63,0x7e,0x24,0x0, +0x14,0xad,0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c,0xff,0x61,0x43,0x74,0x9, 0xac, +0xbf,0x9, 0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0x12,0x93,0x84,0x38,0x2, 0x61,0x41,0xa, +0x1d,0x9, 0xb1,0x29,0xbc,0xbe,0xb0,0x1, 0x78,0x2, 0x61,0x27,0x75,0x24,0x0, 0x61, +0x19,0x7e,0x31,0x24,0x74,0x9, 0xac,0x3b,0x9, 0xc1,0x36,0xba,0xbc,0xcd,0x68,0x2, +0x61,0x17,0x7e,0xa3,0x2a,0x70,0x74,0x40,0xa4,0x9e,0x54,0x0, 0x20,0x7e,0x34,0x60, +0xd1,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0x2d,0xf5,0x49,0x21,0x36,0xb8,0xbd,0x2f, +0x28,0x9, 0x12,0x93,0x7b,0xbd,0x3f,0x38,0x2, 0x41,0xc3,0x12,0x93,0x7b,0x9d,0x32, +0x12,0x21,0x1a,0x7d,0x3, 0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49,0x25,0x36,0xb6,0x12, +0x96,0xa8,0x9d,0x32,0x12,0x21,0x1a,0x2d,0x3, 0xa, 0x1c,0x9, 0xa1,0x37,0x24,0xbe, +0xa0,0x0, 0x28,0x17,0x7e,0x30,0x2, 0xac,0x3c,0x59,0x1, 0x37,0x10,0xa, 0x1c,0x2e, +0x14,0x37,0x24,0x7c,0xba,0x14,0x7a,0x19,0xb0,0x61,0x41,0x74,0x2, 0xac,0xbc,0x49, +0x15,0x37,0x10,0xbe,0x14,0x0, 0x32,0x28,0x8, 0x7d,0xe1,0x2d,0xe4,0xbd,0xe0,0x40, +0x20,0xbe,0x14,0x0, 0x32,0x28,0x8, 0xbe,0x4, 0x0, 0x32,0x28,0x2, 0x80,0x72,0x7d, +0xe1,0x2e,0xe4,0x0, 0x32,0xbd,0xe0,0x50,0x8, 0xbe,0x14,0x0, 0x32,0x28,0x2, 0x80, +0x60,0xbe,0x4, 0x0, 0xa0,0x28,0x56,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0x70,0x4, 0x74, +0x3, 0x80,0x2, 0x74,0x1, 0xa, 0x1d,0x19,0xb1,0x29,0xbc,0x74,0x3, 0xa, 0x1c,0x19, +0xb1,0x29,0xc6,0xbe,0xe0,0x0, 0x28,0x69,0x1b,0xe0,0x7e,0x70,0x9, 0xac,0x7f,0x2e, +0x34,0x28,0xae,0x7e,0x14,0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0x7e,0x70,0x9, 0xac, +0x7e,0x12,0x96,0x98,0xac,0x3f,0x12,0x93,0x72,0x7e,0x34,0x1f,0x34,0x7e,0x30,0x9, +0xac,0x3e,0x12,0x93,0x72,0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74,0x2, 0xac, +0xbc,0x59,0x5, 0x37,0x10,0x80,0x2a,0x5, 0x24,0x90,0x60,0x99,0xe4,0x93,0xbe,0xb1, +0x24,0x28,0x2, 0x41,0x1, 0x80,0x1a,0x6d,0x11,0x74,0x2, 0xac,0xbd,0x12,0x93,0x6a, +0x7e,0x30,0x9, 0xac,0x3d,0x19,0xa1,0x36,0xba,0x74,0x2, 0xa, 0x1d,0x19,0xb1,0x37, +0x24,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x21,0xdd,0xe4,0x7a,0xb3,0x16,0x92,0x90,0x60, +0x99,0x12,0x94,0x5c,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x36,0xb6,0x12,0x20, +0xc3,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, 0xda,0x3b,0x22,0x59,0x15,0x37,0x10,0x7e,0xa0, +0xff,0x22,0x2e,0x14,0x28,0xae,0x74,0x9, 0x2, 0x1f,0x8c,0x74,0x9, 0xac,0xbf,0x49, +0x35,0x28,0xb0,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbd,0x22,0xca,0x3b,0x7c,0xfb, +0x6c,0xee,0x80,0x65,0x6c,0xdd,0x80,0x16,0x74,0x9, 0xac,0xbd,0x9, 0x65,0x29,0x66, +0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb2,0xbc,0x67,0x68,0x7, 0xb, 0xd0,0x12,0x93, +0x84,0x38,0xe5,0x12,0x93,0x84,0x28,0x45,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x29,0x66, +0x12,0x47,0x71,0x74,0x9, 0xac,0xbd,0x12,0x96,0xb1,0x9d,0x32,0x12,0x21,0x1a,0x2d, +0x31,0x7a,0x35,0x24,0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, 0x6d,0x33,0x74, +0x2, 0xac,0xbc,0x59,0x35,0x36,0x7e,0x59,0x35,0x36,0xa1,0x7e,0x35,0x24,0x7c,0xbd, +0x7c,0x5e,0x7c,0x4c,0x12,0x47,0xe2,0xb, 0xe0,0xbc,0xfe,0x38,0x97,0xda,0x3b,0x22, +0x7e,0xb3,0x3, 0xeb,0x70,0x3, 0x12,0x91,0x99,0x2, 0x94,0xc, 0xca,0x79,0x7e,0xf3, +0x2a,0x2, 0x7e,0xe3,0x2a,0x3, 0x7c,0xbf,0x7c,0x7e,0x12,0x94,0x9b,0x7c,0xbf,0x12, +0x95,0x35,0x4c,0xee,0x78,0x14,0x12,0x94,0x58,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e, +0x8, 0x29,0x62,0x12,0x20,0xc3,0x1b,0xfd,0x80,0xb, 0x7e,0xb3,0x2a,0x9, 0x70,0x5, +0x7c,0xbf,0x12,0x93,0x8c,0x7c,0xbf,0x12,0x96,0xee,0xbe,0xf0,0x0, 0x28,0x6, 0x74, +0x1, 0x7a,0xb3,0x2a,0xb, 0xda,0x79,0x22,0x90,0x60,0x99,0xe4,0x93,0x7c,0xab,0x74, +0x9, 0xa4,0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x73,0x2a,0x2, 0x78,0x13,0x12,0x96,0xa0, +0x40,0xe, 0x7e,0x37,0x36,0x92,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, +0x7e,0x37,0x36,0x92,0x1e,0x34,0x7a,0x37,0x36,0x92,0x7e,0xb3,0x2a,0x2, 0x70,0x6, +0x6d,0x33,0x7a,0x37,0x36,0x92,0x7e,0x37,0x36,0x92,0x22,0x7c,0x67,0x7c,0x7b,0xa5, +0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0xe4,0x7a, +0xb3,0x2a,0x9, 0x7a,0xb3,0x2a,0xa, 0x2, 0x95,0x10,0xa5,0xbe,0x0, 0x1d,0x6c,0xaa, +0x80,0xe, 0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62,0x29,0x66,0xb, 0xa0, +0x12,0x39,0x49,0x38,0xed,0x74,0x1, 0x7a,0xb3,0x2a,0x6, 0x6c,0xaa,0x80,0x20,0x7e, +0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0x95,0x4, 0x1b,0x18,0x20,0x7e,0x30, +0x9, 0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0x95,0x4, 0x1b,0x18,0x20,0xb, 0xa0,0xbc, +0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22, +0x12,0x95,0x29,0x7e,0x8, 0x36,0xa1,0xe4,0x12,0x20,0xe8,0x90,0x60,0x99,0x12,0x95, +0x2d,0x7e,0x8, 0x36,0x7e,0xe4,0x2, 0x20,0xe8,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b, +0x74,0x2, 0xac,0x7b,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x60,0x99,0xe4,0x93, +0x7c,0xfb,0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1f, +0x38,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x34,0x74,0x9, 0xac, +0xb1,0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d, +0x12,0x96,0x8e,0x7c,0x7d,0x7c,0x6f,0x12,0x96,0x8e,0x6c,0x0, 0x80,0x39,0x6c,0xee, +0x80,0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38,0x74,0x9, 0xac,0xb0,0x9, 0x75, +0x28,0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x15, +0x7e,0x70,0x9, 0xac,0x70,0x12,0x96,0x98,0xac,0x31,0x2e,0x14,0x1f,0x34,0x74,0x9, +0x12,0x1f,0x8c,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf,0xca, +0x59,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12,0x20,0xc3,0x1b,0xfd,0xda,0x79, +0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0xc1,0x76,0x7c,0x57,0xc1, +0x6e,0x7e,0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66,0x7c,0x98,0x7e,0xd0,0x9, 0xac, +0xd5,0x9, 0xb6,0x28,0xb2,0xbc,0xb9,0x78,0x73,0xbe,0x90,0xff,0x68,0x6e,0x12,0x96, +0x86,0x2d,0xf7,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x29,0xbc,0x7e,0xf0,0x9, +0x70,0xc, 0xac,0xf5,0x7d,0x97,0x2e,0x94,0x28,0xae,0x6d,0x88,0x80,0xa, 0xac,0xf6, +0x7d,0x97,0x2e,0x94,0x29,0x62,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x96,0x86,0x2d,0xf7, +0x1b,0x7a,0xd0,0x69,0xf4,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7, +0x79,0xf6,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb3,0x12,0x96,0x86, +0x2d,0xf7,0x39,0x87,0x0, 0x5, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb4,0x12, +0x96,0x86,0x2d,0xf7,0x39,0x87,0x0, 0x6, 0xb, 0xa0,0x80,0x8, 0xb, 0x50,0xbc,0x45, +0x28,0x2, 0xa1,0xe1,0xb, 0x60,0x90,0x60,0x99,0xe4,0x93,0xbc,0xb6,0x28,0x2, 0xa1, +0xdd,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x70,0x22,0x7e,0x8, +0x1f,0x34,0x12,0x95,0xd3,0x7c,0x1b,0x22,0x2e,0x34,0x28,0xae,0x7e,0x30,0x9, 0x22, +0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, 0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28,0xae, +0x22,0x49,0x25,0x29,0x62,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xae,0x22,0x7e,0xb3, +0x2a,0x9, 0x70,0x23,0x7e,0xb3,0x36,0x94,0xb4,0x2, 0x9, 0x12,0x96,0xa0,0x28,0x4, +0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x36,0x9f,0x7e,0x73,0x36,0xa0,0xbe,0x73,0x36, +0x9f,0x28,0x4, 0x7a,0x73,0x36,0x9f,0x22,0x12,0x97,0xe5,0x2, 0x96,0xbe,0x6c,0xaa, +0x80,0x49,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x62,0x12,0x25,0x12,0x59,0x32, +0x28,0xae,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x64,0x12,0x25,0x12,0x59,0x32, +0x28,0xb0,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x66,0x19,0xb4,0x28,0xb2,0x7e, +0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x67,0x19,0xb4,0x28,0xb3,0x7e,0x90,0x9, 0xac, +0x9a,0x9, 0xb4,0x29,0x68,0x19,0xb4,0x28,0xb4,0xb, 0xa0,0x12,0x39,0x49,0x38,0xb2, +0x22,0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x36, +0x95,0xbe,0x73,0x36,0x9f,0x50,0xe, 0x7d,0x24,0x2e,0x24,0x36,0x95,0x7c,0xb7,0x4, +0x7a,0x29,0xb0,0xd3,0x22,0xbe,0x73,0x36,0x9f,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, +0xe4,0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4,0x36,0x95,0x80,0x17,0xa, 0x3a,0x9, 0xb3, +0x36,0x95,0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x36,0x95,0xd3,0x22,0xe4,0x19, +0xb3,0x36,0x95,0xc3,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x2a,0x62,0xbd, +0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c, +0x77,0x12,0x1f,0x5, 0xbe,0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10,0x74,0x2, +0xac,0xbf,0x49,0x25,0x36,0xa1,0xbd,0x2f,0x28,0x6, 0x49,0x35,0x36,0x7e,0x80,0x4, +0x59,0x35,0x36,0x7e,0x59,0xf5,0x36,0xa1,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34, +0x1, 0x0, 0xda,0xf8,0x22,0xca,0x79,0x7e,0xa3,0x2a,0x2, 0x7e,0x8, 0x29,0xbc,0x7e, +0x90,0xa, 0x12,0x0, 0x6e,0x50,0x3, 0x7e,0x90,0x19,0x4c,0xaa,0x78,0x5, 0x12,0x5e, +0xc5,0x21,0x17,0x6c,0x88,0x21,0xc, 0x7e,0x70,0x9, 0xac,0x78,0x9, 0xf3,0x29,0xc, +0xbe,0xf0,0xff,0x78,0x2, 0x21,0xa, 0xa, 0x2f,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0xe0, +0xbe,0xe0,0x2, 0x68,0x2, 0x1, 0xed,0x7e,0x50,0x4, 0xac,0x5f,0x49,0x22,0x37,0x31, +0x49,0x33,0x29,0x8, 0x12,0x99,0x2c,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x23,0x37,0x33, +0x12,0x99,0x22,0x9d,0x32,0x12,0x21,0x1a,0x7d,0xe3,0x7e,0xb3,0x36,0x7c,0xa, 0x3b, +0xbd,0x3f,0x28,0x54,0xbd,0x3e,0x28,0x50,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x37, +0x31,0x7e,0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0x8, 0x7e,0x70,0x4, 0xac,0x7f,0x49, +0x33,0x37,0x33,0x7e,0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0xa, 0xbe,0xa0,0x0, 0x28, +0x2, 0x1b,0xa0,0x4c,0xaa,0x68,0x2, 0x21,0xa, 0x7e,0xb3,0x36,0x7d,0x4, 0x7a,0xb3, +0x36,0x7d,0xbe,0xb0,0x32,0x40,0x73,0xe4,0x7a,0xb3,0x36,0x7d,0x12,0x99,0x1a,0x50, +0x69,0x4, 0x7a,0xb3,0x36,0x7c,0x80,0x62,0x7e,0x70,0x9, 0xac,0x78,0x49,0xd3,0x29, +0x8, 0x7e,0x50,0x4, 0xac,0x5f,0x59,0xd2,0x37,0x31,0x49,0x33,0x29,0xa, 0x59,0x32, +0x37,0x33,0x12,0x0, 0x6e,0x50,0x7, 0x12,0x99,0x1a,0x28,0x1a,0x80,0x13,0x7e,0x73, +0x36,0x7c,0xbc,0x79,0x40,0x4, 0x74,0x1, 0x80,0x8, 0xbe,0x70,0x1, 0x28,0x7, 0x7c, +0xb7,0x14,0x7a,0xb3,0x36,0x7c,0xe4,0x7a,0xb3,0x36,0x7d,0x80,0x1d,0x4c,0xee,0x78, +0x19,0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x5f,0x59, +0x32,0x37,0x31,0x12,0x99,0x22,0x59,0x32,0x37,0x33,0xb, 0x80,0x90,0x60,0x99,0xe4, +0x93,0xbc,0xb8,0x28,0x2, 0x1, 0x7, 0xda,0x79,0x22,0x7e,0xb3,0x36,0x7c,0xbe,0xb0, +0x1, 0x22,0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x29,0xa, 0x22,0x9d,0x32,0x12,0x21, +0x1a,0x7d,0xf3,0x22,0xca,0x3b,0x12,0x9a,0x1a,0x38,0x2, 0x21,0xf7,0x7e,0xc3,0x0, +0x66,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x0, 0x66,0xe4,0x7a,0xb3,0x0, 0x68,0x6c,0xaa, +0x80,0x26,0x12,0x9a,0x2, 0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3,0x26,0xfa,0x9, 0xe3, +0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12, +0x36,0xed,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xd2, +0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80,0x31,0x12,0x9a,0x2, 0x7e,0x49,0xd0,0x9, 0xe4, +0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1b,0x12,0x36,0xed,0x7d, +0x23,0x49,0x34,0x0, 0x2, 0x12,0x99,0x2c,0xbe,0xf4,0x0, 0x23,0x8, 0x9, 0x74,0x5, +0x19,0xb4,0x0, 0x8, 0x75,0x5f,0x1, 0xb, 0xa0,0xbc,0xfa,0x38,0xcb,0x4c,0xff,0x78, +0x2, 0x80,0x26,0x7e,0x73,0x0, 0x68,0xbe,0x70,0x4, 0x40,0x22,0x6c,0xaa,0x80,0xe, +0x12,0x9a,0x2, 0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, 0xb, 0xa0,0xbc,0xfa, +0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x5f,0x0, 0x12,0x9a,0xc, 0x80,0xf, 0x7c,0xb7, +0x4, 0x7a,0xb3,0x0, 0x68,0x80,0x6, 0x12,0x9a,0xc, 0x75,0x5f,0x0, 0xe5,0x5f,0xda, +0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x0, 0x69,0x22,0xe4,0x7a,0xb3,0x0, +0x67,0x7a,0xb3,0x0, 0x66,0x7a,0xb3,0x0, 0x68,0x22,0x7e,0xb3,0x28,0x84,0xbe,0xb0, +0x0, 0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12,0x9a,0x1a,0x28,0x35,0x6d,0x22, +0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x9a,0x73,0xbe,0x37,0x7, 0xfa,0x8, +0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, 0x70,0x17,0x7e,0xb3,0x3, 0xc2, +0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x5e,0xe5,0x5e,0xbe,0xb0,0x10,0x28,0x5, 0xd2,0x13, +0x75,0x5e,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x5e,0x0, 0x22,0xe5,0x2a,0xa, 0x2b,0xa, +0x3e,0x2d,0x32,0x7e,0x24,0x0, 0x2, 0x2, 0x1e,0xb9,0xca,0xd8,0xca,0x79,0x7e,0x34, +0x62,0x2d,0x12,0x9b,0x25,0x12,0x9f,0x33,0x50,0x2, 0x61,0x20,0x7e,0x34,0x62,0x31, +0x12,0x23,0x74,0x7a,0x35,0x2a,0x90,0x62,0x2c,0xe4,0x93,0x70,0x2, 0x61,0x20,0x7e, +0xb3,0x28,0xa8,0xb4,0x1, 0x7, 0x7e,0x34,0x62,0x2f,0x12,0x9b,0x25,0x7e,0x37,0x28, +0x8a,0xbe,0x34,0x4, 0x4c,0x8, 0x69,0x6c,0xdd,0x80,0x5d,0xc2,0x3, 0x7c,0xbd,0x12, +0x30,0xa4,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xbe,0xfc,0x7a,0x35,0x24, +0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x35,0x26,0x3e,0x34,0x3e,0x34,0x12,0x9a,0x73, +0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e,0x35,0x28,0xbe,0x35, +0x24,0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35,0x26,0x8, 0x2, 0xd2,0x3, 0x7c,0xbd,0x12, +0x9f,0x11,0x50,0x2, 0xc2,0x3, 0x30,0x3, 0xd, 0x7c,0xbd,0x12,0x9e,0xfe,0xac,0x7d, +0x12,0x9e,0xf5,0x12,0x9b,0xe2,0xb, 0xd0,0x7e,0x73,0x28,0x84,0xbc,0x7d,0x38,0x9b, +0xda,0x79,0xda,0xd8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x70,0x22,0xca,0x3b,0x7e, +0xb3,0x2a,0x74,0xf5,0x27,0x12,0x86,0x3d,0x50,0x2, 0x61,0xd3,0x6d,0x33,0x9e,0x37, +0x2a,0x4f,0x3e,0x34,0xbe,0x37,0x7, 0xf8,0x8, 0x2, 0x61,0xd3,0x7e,0xb3,0x16,0x92, +0x60,0x2, 0x61,0xd3,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x69,0x7e,0x77,0x2a,0x51,0x7e, +0x67,0x2a,0x53,0x75,0x24,0x0, 0x80,0x57,0xe5,0x24,0x12,0x2e,0x5f,0x60,0x4e,0x12, +0x9b,0xd6,0x12,0x9e,0xec,0x7e,0xb3,0x2a,0x3, 0xb4,0x1, 0xe, 0x90,0x60,0xab,0xe4, +0x93,0xbe,0xb1,0x26,0x78,0x4, 0xe, 0x64,0xe, 0x74,0x7e,0xa1,0x26,0x74,0x2, 0xa4, +0x49,0x35,0x4, 0xfc,0xbd,0x36,0x48,0x14,0xe5,0x25,0xa, 0x2b,0xe5,0x27,0xa, 0x3b, +0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xfc,0xbd,0x37,0x58,0x11,0xe5,0x24,0x6c,0x77, +0x12,0x2e,0xdd,0x12,0x9b,0xd6,0x9, 0x73,0x26,0xfb,0x12,0x9b,0xe2,0x5, 0x24,0x12, +0x9e,0xe4,0x38,0xa4,0x7e,0xb3,0x2a,0x68,0x70,0x9, 0x7e,0xb3,0x2a,0x6b,0x70,0x3, +0x12,0x9a,0x22,0xda,0x3b,0x22,0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b,0x9, 0xb3,0x26, +0xfa,0x22,0x7c,0x6b,0x7e,0xa3,0x37,0x59,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x37, +0x96,0x19,0x72,0x37,0x97,0x7c,0xba,0x4, 0x7a,0xb3,0x37,0x59,0x22,0xca,0xd8,0xca, +0x79,0xc2,0x3, 0x6c,0xdd,0x7e,0x57,0x28,0x99,0x7d,0xf5,0x7e,0xe7,0x28,0x97,0x7e, +0x37,0x39,0xf, 0x4d,0x33,0x68,0x4, 0x7d,0xf5,0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x2a, +0x6e,0x7c,0x8a,0x7e,0xb3,0x28,0xa5,0x14,0x68,0x21,0x14,0x68,0x14,0x24,0xc2,0x68, +0x8, 0x24,0xfb,0x68,0x16,0x24,0x45,0x78,0x10,0x7c,0xfa,0x7e,0x83,0x2a,0x6d,0x80, +0xa, 0x7e,0x73,0x2a,0x6d,0x2c,0x87,0x80,0x2, 0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c, +0xb9,0x12,0x30,0xa4,0xbe,0x34,0x2, 0x58,0x8, 0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33, +0x28,0x84,0xbc,0x39,0x38,0xe9,0xbe,0xd0,0x3, 0x40,0x2, 0xa1,0xbe,0x7e,0xa3,0x28, +0x85,0xbe,0xa0,0x0, 0x38,0xb, 0xbe,0x30,0x0, 0x28,0x37,0x7e,0xb3,0x26,0x83,0x70, +0x31,0x6c,0x99,0x80,0x29,0xa, 0x29,0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, +0x7a,0xbd,0x2f,0x8, 0x17,0x49,0x3, 0x4, 0xfc,0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d, +0x3e,0x12,0x9a,0x73,0xbd,0x3, 0x8, 0x4, 0xd2,0x3, 0x80,0x6, 0xb, 0x90,0xbc,0x89, +0x38,0xd3,0x6d,0xee,0x9e,0xe7,0x2a,0x4f,0xbe,0xe7,0x7, 0xf8,0x8, 0x2, 0xc2,0x3, +0x30,0x3, 0x20,0x7e,0xb3,0x33,0xfe,0x4, 0x7a,0xb3,0x33,0xfe,0x7e,0x23,0x33,0xfe, +0xbe,0x20,0xa, 0x28,0x1d,0x74,0xa, 0x7a,0xb3,0x33,0xfe,0x74,0x1, 0x7a,0xb3,0x28, +0xa8,0x80,0xf, 0x7e,0x23,0x33,0xfe,0xbe,0x20,0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23, +0x33,0xfe,0x6c,0xee,0xbe,0x30,0x0, 0x38,0x5, 0xbe,0xa0,0x0, 0x28,0x69,0x7e,0xb3, +0x28,0xa7,0xb4,0x1, 0x9, 0x7e,0xb3,0x28,0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3, +0x28,0xa8,0xb4,0x1, 0x52,0x6c,0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3, +0x26,0xfa,0x9, 0xd3,0x26,0xfb,0x12,0x36,0xe6,0xbe,0x34,0x0, 0x96,0x8, 0x5, 0x7e, +0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x28,0x84,0xbc,0xb9,0x38,0xdb,0x6c,0x99, +0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x27,0x36,0x9, 0xd3,0x27,0x37,0x12, +0x36,0xe6,0xbe,0x34,0xff,0x6a,0x58,0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e, +0xb3,0x28,0x85,0xbc,0xb9,0x38,0xdb,0x6c,0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d, +0x5e,0x3e,0x54,0x49,0x55,0x5, 0x7a,0xbd,0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, +0xb, 0x90,0xbc,0x89,0x38,0xe5,0x4c,0xee,0x78,0x25,0x7e,0xb3,0x33,0xff,0x4, 0x7a, +0xb3,0x33,0xff,0x7e,0x73,0x33,0xff,0xbe,0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3, +0x33,0xff,0x7e,0xb3,0x28,0xa8,0x60,0x2, 0xd2,0x17,0x12,0x9f,0x7, 0x80,0xf, 0x7e, +0x73,0x33,0xff,0xbe,0x70,0x0, 0x28,0x6, 0x1e,0x70,0x7a,0x73,0x33,0xff,0xda,0x79, +0xda,0xd8,0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28,0x99,0xe4, +0x7a,0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x4c,0x7e,0x73,0x28, +0x85,0xbe,0x70,0x0, 0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, +0xd2,0x27,0x36,0x9, 0xe2,0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xfc, +0x6d,0x22,0x9e,0x27,0x2a,0x53,0xbd,0x12,0x58,0x19,0x12,0x9e,0xdb,0x49,0x12,0x4, +0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28, +0xa6,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7,0x7e,0xb3, +0x26,0x83,0x70,0x40,0x12,0x87,0xc1,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, +0xac,0x5f,0x9, 0xd2,0x26,0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x9e,0xdb,0x49,0x2, 0x5, +0x7a,0x6d,0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20, +0x5, 0x7a,0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, 0xb, 0xf0, +0xbc,0x7f,0x38,0xc9,0x12,0x9b,0xfd,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37,0x28,0x88, +0x2e,0x37,0x28,0x86,0xbe,0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9, +0x74,0x1, 0x7a,0xb3,0x28,0xaa,0x6c,0xff,0x80,0x1f,0x12,0x36,0xf4,0x49,0x25,0x25, +0xf7,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x21,0x1a,0xbe,0x37,0x28,0x9d,0x8, 0x7, +0xe4,0x7a,0xb3,0x28,0xaa,0x80,0xa, 0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38, +0xd9,0x6c,0xff,0x80,0x9, 0x12,0x36,0xf4,0x59,0x35,0x25,0xf7,0xb, 0xf0,0x7e,0x73, +0x28,0x84,0xbc,0x7f,0x38,0xef,0xda,0x79,0xda,0xd8,0x22,0xa, 0x1d,0xa, 0x2a,0x2d, +0x21,0x3e,0x24,0x22,0x7e,0x73,0x28,0x84,0xbe,0x71,0x24,0x22,0xf5,0x25,0x9, 0xb3, +0x26,0xfb,0xf5,0x26,0x22,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x22,0x6c,0x77, +0x12,0x2e,0xdd,0x7e,0x70,0x2, 0x22,0xe4,0x7a,0xb3,0x28,0xa8,0x7a,0xb3,0x33,0xfe, +0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x26,0xfa,0x9, 0x65,0x26,0xfb,0x7e, +0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x28,0x8d,0xbc,0x76,0x78,0x2, 0xd3, +0x22,0xc3,0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12,0x30,0xa4,0xbe,0x34, +0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38,0xe9, +0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0x7e,0x8, 0x36,0x94,0x7e,0x34,0x0, +0xd, 0xe4,0x2, 0x20,0xe8,0xca,0xf8,0x6d,0xcc,0x7e,0xd4,0x0, 0x8, 0x7e,0xa3,0x28, +0x84,0x4c,0xaa,0x78,0x17,0x7a,0xc5,0x1b,0xc2,0x8, 0xc2,0x9, 0x7e,0x8, 0x33,0x49, +0x7e,0x34,0x0, 0x3, 0x74,0xff,0x12,0x20,0xe8,0x2, 0xa0,0x38,0xbe,0xa0,0x2, 0x28, +0x3, 0x2, 0xa0,0x2e,0xbe,0xa0,0x2, 0x78,0x29,0x7e,0x73,0x26,0xfc,0xa, 0x27,0x7e, +0x73,0x26,0xfa,0x12,0x2c,0x73,0xbe,0x34,0x0, 0x5, 0x58,0x16,0x7e,0x73,0x26,0xfd, +0xa, 0x27,0x7e,0x73,0x26,0xfb,0x12,0x2c,0x73,0xbe,0x34,0x0, 0x5, 0x58,0x3, 0x2, +0xa0,0x53,0x6c,0xff,0x80,0x5e,0x7c,0xbf,0x12,0xbb,0x42,0x1a,0x4b,0x7c,0xbf,0x12, +0x30,0xa4,0x7d,0xc3,0xbe,0xc4,0x2, 0x58,0x58,0x4, 0x7e,0xd4,0x0, 0x7, 0x7d,0x5d, +0x3e,0x54,0xbd,0x54,0x58,0x4, 0xd2,0x9, 0x80,0xa, 0x7d,0x5d,0xe, 0x54,0xbd,0x54, +0x48,0x2, 0xc2,0x9, 0x20,0x9, 0x4, 0xbd,0xd4,0x58,0x10,0x7e,0x34,0x1, 0x90,0x7a, +0x35,0x1b,0x12,0xa0,0x5d,0x7a,0x73,0x33,0x4b,0x80,0x2d,0x7d,0x5d,0xe, 0x54,0xbd, +0x54,0x58,0x9, 0x12,0xa0,0x5d,0x7a,0x73,0x33,0x4b,0x80,0x6, 0x74,0xff,0x7a,0xb3, +0x33,0x49,0xb, 0xf0,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x38,0x9a,0x80,0xa, 0x7e,0x35, +0x1b,0x9e,0x34,0x0, 0x5, 0x7a,0x35,0x1b,0x7e,0x35,0x1b,0xbe,0x34,0x0, 0x0, 0x8, +0x12,0x20,0x8, 0x8, 0xd2,0x8, 0x74,0x14,0x7a,0xb3,0x36,0x7c,0x1b,0x34,0x7a,0x35, +0x1b,0x80,0x7, 0x6d,0x33,0x7a,0x35,0x1b,0xc2,0x8, 0xda,0xf8,0x22,0x74,0x1, 0x7a, +0xb3,0x33,0x49,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfa,0x7a,0x73,0x33,0x4a,0x74, +0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfb,0x22,0x7c,0xab,0xa5,0xbf,0x0, 0xc, 0x7e,0xb3, +0x33,0xc4,0x7a,0xb3,0x33,0xc5,0x7a,0xa3,0x33,0xc4,0x7e,0xb3,0x33,0xc5,0x60,0x4, +0x74,0x8, 0x80,0xd, 0x7e,0xb3,0x28,0x84,0x70,0xb, 0x7e,0xb3,0x33,0xc6,0x60,0x5, +0x14,0x7a,0xb3,0x33,0xc6,0x7e,0x73,0x33,0xc6,0xbe,0x70,0x0, 0x28,0x3, 0x74,0x1, +0x22,0xe4,0x22,0xe4,0x7a,0xb3,0x37,0x59,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3, +0x37,0xd2,0x60,0x5, 0xe4,0x7a,0xb3,0x37,0xd4,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb, +0x7f,0x70,0xc2,0x3, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x22,0xf7,0x7e,0x24,0x0, 0xff, +0x7e,0x14,0x1f,0x34,0x74,0xc, 0x12,0x1f,0xad,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c, +0xee,0x80,0x13,0x12,0xa1,0xdb,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, +0x28,0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, +0x7e,0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0x21,0xcc,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, +0xd2,0x3, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1f,0x34,0xbd,0x4d,0x58,0x6, +0x49,0xd5,0x1f,0x36,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, +0x78,0x4, 0x6d,0x33,0x21,0xcc,0xbd,0xd, 0x8, 0x5, 0x30,0x3, 0x2, 0x7d,0xd0,0x9f, +0x55,0x6c,0xee,0x80,0xb, 0x12,0xa1,0xdb,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0, +0xbc,0xfe,0x38,0xf1,0xa, 0x1f,0x12,0xa1,0xd1,0x9f,0x55,0x6c,0xee,0x80,0x1f,0x74, +0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x21,0x1a,0x7d, +0xc3,0xbd,0x1c,0x28,0x7, 0x12,0xa2,0x93,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe, +0x38,0xdd,0x6d,0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0xa1,0xd1,0xbd,0x1d, +0x8, 0x4, 0x7d,0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10, +0x6c,0xee,0x80,0x12,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x0, 0x9d, +0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc,0xfe,0x38,0xea,0x7d,0x31,0xda,0x79,0xda,0xd8, +0x22,0x6d,0x0, 0x7f,0x15,0x12,0x1f,0x58,0x7d,0x13,0x22,0x74,0x2, 0xac,0xbe,0x7f, +0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x21,0x1a,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c, +0xaa,0x7e,0xf0,0x80,0xc2,0x3, 0x6d,0x44,0x80,0x32,0x12,0xa2,0x8a,0x12,0xa1,0xe3, +0xbd,0x3d,0x48,0x26,0x12,0xa2,0x8a,0xb, 0x1a,0x30,0xbe,0x34,0x0, 0x0, 0x8, 0x4, +0xd2,0x3, 0x80,0x9, 0x12,0x21,0x1a,0xbd,0x3d,0x68,0x2, 0xc2,0x3, 0x7d,0x34,0x3e, +0x34,0x2d,0x3f,0x7d,0x2e,0x12,0xa1,0xe3,0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd, +0xc4,0x38,0xc7,0x30,0x3, 0xc, 0x7e,0xf0,0x7f,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, +0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd, +0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34,0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d, +0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e, +0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0x7c,0xb7,0x12,0xa2,0x9c,0xb, 0x44, +0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda,0xf8,0x22,0x7d,0xc4,0x3e,0xc4,0x7f,0x17, +0x2d,0x3c,0x22,0x7d,0x39,0x1a,0x26,0x1a,0x24,0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34, +0x7a,0x1b,0xb0,0x22,0x90,0x60,0x93,0xe4,0x93,0xa, 0xb, 0x7e,0x73,0x2a,0x71,0xa, +0x17,0x2d,0x10,0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0xad,0x13,0x7d,0x21,0x6c,0x33,0x80, +0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f,0x33,0xe0,0x2d,0xf0,0xb, 0x7a,0x0, +0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x13,0x8e,0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, +0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e,0xf, 0x38,0x54,0x7e,0x18,0x25,0xb6, +0x2, 0xa1,0xe9,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x31,0x12,0xa3,0x2c,0x7e,0x1f,0x33, +0xe0,0x7a,0x37,0x24,0xfa,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x24,0xf6,0x12,0x87,0xec, +0x12,0x87,0xf5,0xe4,0x7a,0xb3,0x24,0xf5,0x7e,0x34,0x0, 0x20,0x7a,0x37,0x24,0xfc, +0x7a,0xb3,0x24,0xf4,0x7e,0x8, 0x24,0xf2,0x2, 0xd, 0x7, 0x22,0xa9,0xd1,0xcb,0xe4, +0x2, 0x0, 0xe, 0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d,0xac,0x54,0x7e,0x17,0x28, +0xa1,0x12,0xa3,0x2c,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x33,0xe0, +0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x8, 0xa, 0xb, +0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, +0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd, +0x20,0x38,0xc5,0x22,0x7c,0xab,0x90,0x60,0xab,0xe4,0x93,0xbc,0xb7,0x78,0x9, 0x7c, +0xba,0x12,0x6c,0xc2,0x50,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0x66,0x90,0x60,0xa7,0xe4, +0x93,0xbe,0xb0,0x0, 0x28,0x71,0x90,0x60,0xaa,0xe4,0x93,0x70,0x6a,0x7e,0xb3,0x28, +0xa8,0xb4,0x1, 0x63,0x7e,0x73,0x26,0xf2,0xbe,0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80, +0x4e,0xa, 0x23,0x9, 0x72,0x26,0xe6,0x7e,0xb3,0x2a,0x6e,0x14,0xbc,0x7b,0x78,0x3d, +0x6c,0x22,0x80,0x27,0x7c,0xb2,0x7c,0x73,0x12,0xa3,0x84,0x50,0x1c,0xa, 0x22,0x7e, +0x73,0x2a,0x6e,0xa, 0x7, 0x2d,0x2, 0x3e,0x4, 0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e, +0x7, 0x2a,0x4f,0xbd,0x20,0x58,0x2, 0xb, 0x60,0xb, 0x20,0x7e,0x73,0x2a,0x6d,0xbc, +0x72,0x38,0xd1,0xbe,0x60,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e, +0x73,0x26,0xf2,0xbc,0x73,0x38,0xaa,0x74,0x1, 0x22,0x12,0xa4,0x32,0x7e,0x14,0x62, +0xd, 0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x32,0x28,0x3, 0xd2,0x15,0x22,0xc2, +0x15,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e,0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac, +0x1a,0x7e,0x7f,0x39,0xea,0x2d,0xf0,0x69,0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d, +0x32,0x12,0x21,0x1a,0xbd,0x31,0x28,0x16,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x39, +0xea,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69,0x30,0x0, 0x80,0x12,0x47,0x7d,0x7e,0x10, +0x2, 0xac,0x1a,0x7e,0x1f,0x39,0xea,0x2d,0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f, +0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69,0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78, +0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x9d,0x7d, +0x31,0x22,0x7e,0x60,0x4, 0x7e,0x27,0x3, 0xfc,0xbe,0x24,0x3, 0xe8,0x28,0x3, 0x7e, +0x60,0x8, 0x7e,0xb3,0x28,0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x0, 0x64,0xbc,0x76,0x50, +0xf, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x86,0x40,0x7e,0xb3,0x0, 0x64,0x4, 0x80,0x4, +0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x64,0x7e,0xb3,0x28,0xad,0xb4,0x1, 0x17,0x7e, +0xa3,0x0, 0x65,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad,0x7c,0xba,0x4, +0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x65,0x22,0x6c,0xaa,0x80,0x26, +0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, 0x2d,0x31,0x59, +0x32,0x5, 0xf8,0x30,0x1, 0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, 0x76,0x2d,0x31, +0x59,0x32,0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0x3b,0x7e,0xb3,0x2a,0x73, +0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0x74,0x2, 0x7a,0xb3,0x0, +0x63,0x74,0x1, 0x7a,0xb3,0x28,0xac,0x2, 0x2a,0x27,0xd2,0x3, 0x6c,0xaa,0x6c,0x77, +0x80,0x1f,0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c,0x65,0x7e,0x50, +0x2, 0xac,0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, 0xb, 0xa0,0xb, +0x70,0x7e,0xb3,0x2a,0x6d,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24,0xa, 0x3a,0xbd, +0x32,0x8, 0x2, 0xc2,0x3, 0xa2,0x3, 0x22,0x7e,0x63,0x2a,0x6f,0x7e,0xa3,0x2a,0x70, +0x7e,0x70,0x1, 0x80,0x25,0xa, 0x17,0x7e,0xb3,0x2a,0x6e,0xa, 0x2b,0x2d,0x21,0x3e, +0x24,0x49,0x12,0x4, 0xfc,0x7e,0xf4,0x61,0x59,0x12,0x84,0x57,0x6e,0x24,0xff,0xff, +0xb, 0x24,0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b,0x14,0xa, 0x27, +0xbd,0x21,0x48,0xd1,0x7e,0x70,0x2, 0x80,0x20,0x7e,0x50,0x2, 0xac,0x57,0x49,0x12, +0x4, 0xfc,0x7e,0xf4,0x61,0x5b,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, 0x6d,0x22,0x9d, +0x20,0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27,0xbd, +0x21,0x48,0xd6,0xc3,0x22,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c,0xeb,0x6c,0xff,0x7e, +0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xc0,0x7e,0x73,0x38,0xe1,0xa, 0xb7, +0x7e,0xb3,0x2b,0x10,0xf5,0x35,0x12,0xa7,0x46,0xbe,0xd0,0x4, 0x38,0x5, 0xe4,0x7a, +0xb3,0x37,0xe5,0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d,0xac,0x75,0x34,0x0, 0x7e,0xa3, +0x37,0xe5,0xbc,0xad,0x40,0x2, 0x80,0x19,0xbe,0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4, +0x9, 0x75,0x26,0x33,0xbc,0x7e,0x78,0xe, 0x7c,0xbd,0x14,0xbe,0xb3,0x37,0xe5,0x78, +0x5, 0xe4,0x7a,0xb3,0x37,0xe5,0x7e,0xc3,0x37,0xe5,0x80,0x41,0x7e,0xb3,0x37,0xe5, +0x4, 0x7a,0xb3,0x37,0xe5,0x7e,0x90,0x5, 0xac,0x9c,0x9, 0xa4,0x26,0x33,0xbc,0xae, +0x68,0x29,0xe5,0x34,0xa, 0xdb,0x19,0xcd,0x37,0xe9,0xa, 0x9a,0xad,0x9b,0x2d,0x9c, +0x7e,0xa1,0x34,0x7c,0xba,0x4, 0xf5,0x34,0x7c,0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31, +0x35,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x6, 0xb, 0xc0,0xbc,0xdc,0x38, +0xbb,0x7a,0xf3,0x37,0xe6,0xda,0x3b,0x22,0x7a,0xb3,0x2b,0xf, 0x12,0x57,0xef,0x30, +0xe, 0xa, 0x12,0x4f,0xfb,0x30,0x3, 0x4, 0xe4,0x12,0xa, 0x66,0x30,0x3, 0x9, 0x12, +0xa7,0x7a,0x12,0xa5,0xf5,0x2, 0x87,0x70,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac, +0xbf,0x12,0xa7,0x4e,0x12,0x7f,0xf1,0x12,0x7f,0xdf,0x12,0x7f,0xe8,0x7a,0xf3,0x2f, +0xa9,0x7c,0xbf,0x12,0xa7,0xac,0x12,0x57,0xef,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x26, +0x37,0x12,0xa7,0x61,0x12,0x23,0x15,0xe4,0x7a,0xb3,0x16,0x91,0xda,0xf8,0x22,0x7e, +0xb3,0x37,0xd9,0x60,0x6, 0x14,0x7a,0xb3,0x37,0xd9,0x22,0x12,0xa7,0xe1,0x90,0x61, +0xcb,0xe4,0x93,0xbe,0xb0,0x4, 0x28,0x3, 0x12,0xa5,0xf5,0x7e,0xb3,0x3, 0xa6,0x70, +0xe, 0x7e,0xb3,0x39,0xfb,0xb4,0x1, 0x7, 0xe4,0x12,0xa6,0xc9,0x12,0xa7,0x57,0x12, +0x5d,0xc9,0x12,0xa9,0x2b,0x7e,0xa3,0x3, 0xa6,0x7a,0xa3,0x39,0xfb,0xbe,0xb0,0xff, +0x68,0x3, 0x2, 0xa6,0xc9,0x22,0x90,0x61,0xcb,0xe4,0x93,0x7c,0xdb,0x22,0x9, 0x75, +0x26,0x33,0x7a,0x73,0x2b,0xf, 0x22,0xe4,0x7a,0xb3,0x37,0xdc,0x7a,0xb3,0x37,0xe4, +0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab,0x68,0x6, 0x7a,0xb3,0x2b,0x62,0xd2,0xe, 0x30, +0xe, 0x7, 0x12,0x4f,0xfb,0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x37,0xed,0x7e,0x34, +0x0, 0x60,0xe4,0x12,0x20,0xe8,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac, +0x7a,0x59,0x43,0x37,0xef,0x59,0x43,0x37,0xf7,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8, +0x7e,0x8, 0x37,0xdb,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe8,0xca,0xf8,0x7c,0xfb, +0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x2f,0xaa,0x6d,0x22,0x7e,0x8, +0x34,0x0, 0x12,0x20,0xc3,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0xac,0x7f,0x2e, +0x34,0x30,0x8a,0x6d,0x22,0x7e,0x8, 0x32,0xba,0x12,0x20,0xc3,0x1b,0xfd,0xda,0xf8, +0x22,0x7e,0x37,0x33,0xd9,0x12,0x25,0x12,0x7a,0x37,0x38,0x50,0x6c,0xaa,0x80,0x23, +0x12,0x5f,0xcb,0x28,0x26,0xa, 0x4a,0x9, 0x64,0x37,0xe9,0xbc,0x6b,0x50,0x12,0x7e, +0x50,0x2, 0xac,0x5a,0x49,0x42,0x33,0xd3,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x37, +0xf3,0xb, 0xa0,0x7e,0xb3,0x37,0xe6,0xbc,0xba,0x38,0xd5,0x22,0x7d,0x23,0x7e,0x14, +0x61,0xce,0x12,0x5b,0x79,0x7e,0x14,0x0, 0x5, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50, +0xd, 0x7e,0x33,0x38,0x4f,0xbe,0x30,0x8, 0x50,0x45,0x74,0x8, 0x80,0x3d,0x7d,0x13, +0x3e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x38,0x4f,0xbe,0x30,0x6, 0x50,0x30,0x74, +0x6, 0x80,0x28,0x7e,0x14,0x0, 0x3, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e, +0x33,0x38,0x4f,0xbe,0x30,0x4, 0x50,0x17,0x74,0x4, 0x80,0xf, 0xbd,0x32,0x50,0xf, +0x7e,0x73,0x38,0x4f,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a,0xb3,0x38,0x4f,0x7e, +0xb3,0x38,0x4f,0xbe,0xb0,0x0, 0x28,0x1b,0x14,0x7a,0xb3,0x38,0x4f,0x74,0x1, 0x7a, +0xb3,0x16,0x92,0x90,0x62,0x3, 0xe4,0x93,0xbe,0xb3,0x38,0x4f,0x50,0x5, 0xe4,0x7a, +0xb3,0x16,0x91,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a,0x12,0xa9, +0x1d,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0xab,0xac,0x7d,0x23,0x7e,0x70,0xc, +0xac,0x72,0x59,0x23,0x37,0xf5,0x49,0x3, 0x37,0xf5,0x49,0x23,0x37,0xf1,0xbd,0x20, +0x50,0x4, 0x59,0x3, 0x37,0xf1,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa,0x6c,0x22, +0x80,0x18,0x12,0xa9,0x1d,0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, 0x37,0xf1, +0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4,0x7e,0x37, +0x37,0xd7,0xbe,0x37,0x38,0x50,0x50,0x8, 0x7e,0x37,0x38,0x50,0x7a,0x37,0x37,0xd7, +0x12,0xaa,0x53,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e,0x10,0x5, +0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, 0x22,0xca,0xd8,0xca,0x79,0x7e, +0xe0,0xff,0x12,0xac,0x40,0x7e,0xb3,0x37,0xde,0xb4,0x1, 0x8, 0x12,0x87,0x53,0xe4, +0x7a,0xb3,0x37,0xde,0x7e,0xb3,0x37,0xdd,0x60,0x4, 0x74,0xff,0x41,0x4e,0x7e,0xb3, +0x37,0xdc,0xb4,0x2, 0x2, 0x80,0x2, 0x41,0x42,0x12,0x5f,0xeb,0x38,0xc, 0x12,0x5f, +0xe3,0x38,0x7, 0x12,0x5f,0xdb,0x38,0x2, 0x41,0x42,0x12,0xa7,0x46,0xa, 0x3d,0x1b, +0x34,0xbe,0x34,0x0, 0x3, 0x48,0x4, 0x74,0x3, 0x80,0x3, 0x7c,0xbd,0x14,0x12,0xa8, +0xa4,0x7c,0xfb,0x7e,0xb3,0x37,0xdb,0x4, 0x7a,0xb3,0x37,0xdb,0x90,0x61,0xcb,0xe4, +0x93,0x14,0x12,0xa8,0xa4,0x7c,0xab,0xbe,0xa0,0xff,0x68,0x2c,0xbe,0xf0,0xff,0x68, +0x25,0x7e,0x30,0xc, 0xac,0x3f,0x49,0x21,0x37,0xf1,0x7e,0xf4,0x61,0xd2,0x7e,0xe4, +0x0, 0xff,0xb, 0x7a,0x30,0xbd,0x23,0x28,0xf, 0x12,0xaa,0x53,0x3e,0x34,0xbd,0x23, +0x28,0x6, 0x7c,0xfa,0x80,0x2, 0x7c,0xfa,0xbe,0xf0,0xff,0x78,0x11,0xe4,0x7a,0xb3, +0x37,0xdb,0x7a,0xb3,0x37,0xdc,0x7a,0xb3,0x37,0xe8,0x74,0xff,0x80,0x70,0x90,0x61, +0xda,0xe4,0x93,0xbe,0xb3,0x37,0xdb,0x50,0x59,0x74,0xc, 0xac,0xbf,0x49,0x25,0x37, +0xf1,0x7e,0x14,0x61,0xd2,0x12,0x5b,0x79,0xbd,0x23,0x50,0x3d,0x7e,0x34,0x61,0xd6, +0x12,0x23,0x74,0xbe,0x37,0x37,0xd7,0x40,0xd, 0x7e,0x34,0x61,0xd8,0x12,0x23,0x74, +0xbe,0x37,0x37,0xe2,0x50,0x23,0x74,0x5, 0xac,0xbf,0x9, 0x75,0x26,0x33,0xbe,0x73, +0x2b,0xf, 0x68,0x15,0x7c,0xef,0xbe,0xe0,0x4, 0x50,0x8, 0x12,0xaa,0x5d,0xbe,0xb0, +0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xde,0xe4,0x7a,0xb3,0x37,0xe8,0x7a,0xb3, +0x37,0xdc,0xbe,0xe0,0xff,0x68,0x5, 0xe4,0x7a,0xb3,0x37,0xdb,0x7c,0xbe,0xda,0x79, +0xda,0xd8,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x37,0xf1,0x22,0x7e,0xb3,0x2b, +0xf, 0x7c,0xab,0x6c,0x77,0x7e,0x50,0x5, 0xac,0x57,0x9, 0x62,0x26,0x33,0xbc,0x6a, +0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0x7c, +0x2b,0x7e,0xb3,0x1f,0x33,0xbc,0x2b,0x68,0x4f,0x12,0xaa,0x61,0x7c,0x3b,0x7c,0xb2, +0x12,0xaa,0x61,0x7c,0xab,0xbe,0x30,0xff,0x68,0x3e,0xbe,0xa0,0xff,0x68,0x39,0x7e, +0x70,0x4, 0xac,0x73,0xa, 0x2a,0x12,0x6f,0xe8,0xbe,0xb0,0x2, 0x38,0x2a,0xa, 0x2b, +0x7e,0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30,0x19,0x3, 0x2, +0xaa,0xe8,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0xf, 0x12,0x7c,0xbb,0x7a,0x55,0x29,0x7e, +0x8, 0xd, 0xc8,0x74,0x1, 0x2, 0xab,0x19,0x22,0x7c,0xab,0x12,0xab,0x62,0xd2,0x19, +0x7c,0xba,0x12,0xaa,0x7f,0xc2,0x19,0x22,0x7c,0x7b,0x90,0x60,0x93,0xe4,0x93,0xa, +0x1b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2d,0x1, 0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xad, +0x10,0x7d,0x21,0x12,0xab,0xa3,0xa, 0x26,0x7a,0x25,0x29,0x74,0x1d,0xac,0x7b,0x2e, +0x34,0x38,0x58,0x6d,0x22,0xe4,0x2, 0xab,0x19,0x7c,0xab,0x6d,0x44,0x80,0x29,0x4c, +0xaa,0x68,0x11,0x12,0xab,0x50,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x77,0xad, +0x2d,0xfe,0x80,0xf, 0x12,0xab,0x50,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x77, +0xad,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e,0xf5,0x29,0xbd,0xf4,0x38,0xd0,0x22, +0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b, +0xb0,0x22,0xa9,0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x12,0xab,0x62,0x7e,0x34,0xd, +0xc8,0x7e,0xb3,0x2a,0x6d,0x12,0xac,0x15,0x12,0xab,0x86,0x7a,0x37,0x33,0xdd,0x74, +0x1, 0x7a,0xb3,0x16,0x91,0x22,0x6d,0x33,0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0,0x0, +0x28,0x3, 0x2, 0xad,0x8, 0x90,0x60,0x92,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, +0xac,0x6f,0x22,0x3e,0x24,0x7e,0xf, 0x33,0xe0,0x2d,0x12,0x22,0x49,0x23,0x37,0xf7, +0x49,0x33,0x37,0xf3,0x9d,0x32,0x2, 0x21,0x1a,0x6c,0xaa,0x80,0x44,0x7e,0x70,0xc, +0xac,0x7a,0x12,0xab,0xac,0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0xac,0x7, 0x80,0x2f, +0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0xf7,0x49,0x12,0x37,0xf3,0xbd,0x13,0x28, +0xf, 0x7d,0x2, 0x2e,0x4, 0x37,0xf7,0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, +0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24,0x37,0xf7,0x1b,0x35,0x1b,0x28,0x30,0xb, +0xa0,0x12,0x5f,0xcb,0x38,0xb7,0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0xf3, +0x59,0x32,0x37,0xf7,0x22,0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e,0x7a,0x53,0x24, +0xf3,0x7a,0x37,0x24,0xfa,0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24,0xf5,0x7e,0x34, +0x40,0x0, 0x7a,0x37,0x24,0xf6,0x7e,0x34,0x0, 0x20,0x12,0x87,0xd1,0x2, 0xd, 0x7, +0x7e,0xb3,0x37,0xdd,0xb4,0x1, 0x27,0x7e,0xb3,0x38,0x53,0x4, 0x7a,0xb3,0x38,0x53, +0x7e,0x73,0x38,0x53,0xbe,0x70,0x3, 0x40,0x15,0x12,0x87,0x70,0x7e,0x73,0x38,0x53, +0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3,0x38,0x53,0x7a,0xb3,0x37,0xdd,0x22,0xca, +0xf8,0x6d,0xee,0x7d,0xfe,0x7e,0x83,0x2a,0x6e,0xa, 0xd8,0x90,0x60,0x94,0xe4,0x93, +0xb4,0xff,0x2f,0x7e,0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x18,0x7e,0x70,0x2, 0xac,0x7a, +0x49,0x23,0x13,0xfe,0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0,0x9d,0xc2,0x59,0xc3,0x13, +0xc6,0xb, 0xa0,0xbc,0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4,0x93,0x7c,0x9b,0x6d,0xdd, +0x80,0x11,0x7e,0x8, 0x13,0xfe,0x90,0x60,0x92,0xe4,0x93,0xa, 0xcb,0x1b,0xc4,0x7d, +0x3c,0x7c,0x97,0x6c,0xff,0x80,0x38,0x6c,0xaa,0x80,0x28,0xa, 0x3a,0x7d,0x23,0x2d, +0x2e,0x3e,0x24,0x49,0xc2,0x13,0xfe,0x2d,0x3d,0x3e,0x34,0x2d,0x31,0x7d,0x20,0xb, +0x1a,0xb0,0x7d,0x3c,0x9d,0x3b,0x12,0x21,0x1a,0x7d,0xa3,0xbd,0xfa,0x58,0x2, 0x7d, +0xfa,0xb, 0xa0,0xbc,0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec,0x2d,0xdc,0xb, 0xf0,0xbc, +0x9f,0x38,0xc4,0x7d,0x3f,0xda,0xf8,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x2a,0x6e, +0x90,0x60,0x93,0xe4,0x93,0xa, 0xfb,0x7e,0xb3,0x2a,0x6d,0xa, 0xeb,0x2d,0xef,0xa, +0xff,0xad,0xfe,0xa, 0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e, +0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x33, +0xe0,0x2d,0x3d,0xb, 0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, +0x5a,0x30,0x9d,0x3d,0x59,0x32,0x13,0xc6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, +0x7d,0x5e,0x3e,0x54,0x7e,0xf, 0x33,0xe0,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea, +0x2d,0xef,0x3e,0xe4,0x7e,0x1f,0x33,0xe0,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, +0xac,0x7a,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x21,0x1a, +0x7d,0xc3,0xbd,0x4c,0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34, +0xda,0xf8,0x22,0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c,0x22,0x80, +0x37,0x7e,0xb3,0x2a,0x6e,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e,0x44,0x7e, +0x7f,0x13,0x8a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, 0xbe,0x44, +0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44,0xfd,0xa8, +0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x2a,0x6e,0xbc,0x92,0x38,0xc1, +0xb, 0x31,0x7e,0xb3,0x2a,0x6d,0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, 0xad,0x53, +0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12,0x25,0x14,0xbd,0x12,0x50,0x22,0xbd, +0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x33,0xfb,0x7e,0xb3,0x33,0xfc,0xbe,0xb0,0x5, 0x50, +0x7, 0x4, 0x7a,0xb3,0x33,0xfc,0x80,0x3c,0xe4,0x7a,0xb3,0x33,0xfc,0x74,0x1, 0x80, +0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x33,0xfc,0x7e,0xb3, +0x33,0xfb,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x33,0xfb,0x80,0x16,0xe4,0x7a, +0xb3,0x33,0xfb,0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x33,0xfb,0x7a,0xb3,0x33,0xfc, +0x7a,0xb3,0x33,0xfd,0x7e,0xb3,0x33,0xfd,0x22,0x7e,0xa3,0x2f,0xa9,0xbe,0xa0,0xff, +0x68,0x4c,0xbe,0xa3,0x33,0x46,0x68,0x46,0x74,0x5, 0xa4,0x12,0xa7,0x4e,0x12,0xae, +0xbf,0x12,0x7f,0xf1,0x12,0xae,0xbf,0x12,0x7f,0xe8,0x12,0xae,0xc7,0x50,0x9, 0x7e, +0xb3,0x2f,0xa9,0x12,0xa7,0xac,0x80,0x6, 0x12,0xae,0xbf,0x12,0x7f,0xdf,0x12,0x57, +0xef,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0x7e,0x73,0x2b,0x14,0xa, 0x37,0x7e,0xf, +0x33,0xcf,0x79,0x30,0x0, 0x1a,0x7e,0x73,0x2f,0xa9,0x7a,0x73,0x33,0x46,0x22,0x7e, +0xa3,0x2f,0xa9,0x74,0x5, 0xa4,0x22,0x7e,0xb3,0x3, 0xc2,0xb4,0x3, 0x8, 0x7e,0xb3, +0x38,0xc6,0x70,0x2, 0xc3,0x22,0xd3,0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e, +0xb3,0x2a,0x6e,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51, +0x7e,0x13,0x2a,0x6e,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x2a,0x6d,0xa, 0x10,0xa, 0x21, +0x2d,0x12,0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23, +0x32,0xba,0x80,0x2d,0x7e,0x3, 0x2a,0x6d,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42, +0xa, 0x3a,0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58, +0xe, 0x9d,0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x32,0xbc,0x80,0x2, 0xe4, +0x22,0x7e,0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e, +0x60,0x80,0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0xae, +0xd8,0xa, 0x1b,0x7e,0x63,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac, +0x1f,0x2d,0x3, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x12,0xaf,0x97,0x9d,0x35,0x1b,0x1a, +0x10,0xb, 0xf0,0x12,0xaf,0x97,0x7e,0x73,0x2a,0x6e,0xa, 0x27,0x2d,0x25,0xa, 0x3f, +0xbd,0x32,0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x2a,0x6d,0x74,0x2, 0xa4,0x22,0xca, +0x3b,0x7c,0xcb,0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x43,0x7e, +0xb3,0x2a,0x70,0xf5,0x44,0x75,0x45,0x28,0x7e,0xb3,0x28,0x84,0xf5,0x2b,0xe4,0x7a, +0xb3,0x2, 0x89,0x7a,0xb3,0x2, 0x85,0x7a,0xb3,0x2, 0x86,0x7e,0x8, 0x2, 0x8a,0x12, +0xcc,0x7b,0xe4,0x12,0x20,0xe8,0x12,0xcc,0x7b,0x3e,0x34,0x7e,0x8, 0x2, 0xaa,0xe4, +0x12,0x20,0xe8,0xe5,0x2b,0xbe,0xb0,0x2, 0x50,0x3, 0x2, 0xb6,0xf4,0x75,0x2c,0x0, +0x2, 0xb6,0xea,0x7e,0x71,0x2c,0x12,0x9b,0xd9,0xf5,0x24,0x9, 0xb3,0x26,0xfb,0xf5, +0x25,0xe5,0x2c,0x60,0xa, 0xe5,0x2c,0xa, 0x3b,0x9, 0xb3,0x2, 0x8a,0x70,0x10,0xe5, +0x2c,0xa, 0x5b,0xb, 0x54,0x7c,0xab,0xe5,0x2c,0xa, 0x3b,0x19,0xa3,0x2, 0x8a,0xe5, +0x2b,0x14,0xbe,0xb1,0x2c,0x78,0x2, 0xc1,0xf4,0xe5,0x2c,0xa, 0x5b,0xb, 0x54,0xf5, +0x2d,0xc1,0xdf,0x7e,0x71,0x2d,0x12,0xcc,0x27,0x7a,0xa1,0x26,0x9, 0xb3,0x26,0xfb, +0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0xb7,0xb0,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5, +0x25,0x12,0xb7,0xb0,0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, 0xc1,0xdd,0xe5, +0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xc1,0xdd,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26, +0x7e,0x51,0x27,0x12,0x2f,0x85,0x7a,0xb3,0x2, 0x88,0x85,0x25,0x5b,0x85,0x26,0x5c, +0x85,0x27,0x5d,0x7e,0x8, 0x0, 0x33,0x7e,0x18,0x0, 0x35,0xe5,0x24,0x12,0xba,0xbc, +0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x75,0x32,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x30, +0xb6,0x7a,0x35,0x37,0xe5,0x26,0x12,0xb7,0x5a,0x7a,0x35,0x39,0x7e,0x35,0x37,0xbe, +0x35,0x39,0x8, 0x7, 0x7e,0x35,0x39,0x7d,0x83,0x80,0x3, 0x7e,0x85,0x37,0x7a,0x85, +0x3b,0xe, 0x84,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x21,0xe5,0x29,0xbe,0xb0,0x1, 0x38, +0x1a,0x7c,0xbc,0x30,0xe1,0x15,0x12,0x30,0xb1,0x7d,0x43,0x12,0xb7,0x58,0x2d,0x34, +0xbd,0x38,0x18,0x2, 0x81,0x98,0x75,0x32,0x1, 0x81,0x98,0xe5,0x28,0xbe,0xb0,0x1, +0x38,0x9, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x2, 0x81,0x98,0xe5,0x28,0xbe,0xb0,0x5, +0x40,0x2, 0x81,0x98,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0x81,0x98,0x7c,0xbc,0x20, +0xe0,0x2, 0x81,0x98,0x6d,0x33,0x7d,0x93,0x75,0x52,0x0, 0x7a,0x35,0x53,0x75,0x55, +0x0, 0xc2,0x4, 0xc2,0x5, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x6, 0xe5,0x24,0x7c,0xeb, +0x80,0x3, 0x7e,0xe1,0x26,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, +0xe5,0x26,0xf5,0x2a,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x6, 0xe5,0x25,0x7c,0xfb,0x80, +0x3, 0x7e,0xf1,0x27,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x6, 0xe5,0x25,0x7c,0xdb,0x80, +0x3, 0x7e,0xd1,0x27,0xe5,0x43,0xa, 0xb, 0x1b,0x4, 0xe5,0x2a,0xa, 0x1b,0xbd,0x10, +0xe5,0x2a,0x58,0x6, 0xa, 0x5b,0xb, 0x54,0x80,0x0, 0xf5,0x4e,0xbe,0xe0,0x0, 0x28, +0x6, 0xa, 0x5e,0x1b,0x54,0x80,0x2, 0x7c,0xbe,0xf5,0x4f,0xe5,0x44,0x12,0xcc,0x44, +0x58,0x6, 0xa, 0x5d,0xb, 0x54,0x80,0x2, 0x7c,0xbd,0xf5,0x50,0xbe,0xf0,0x0, 0x28, +0x6, 0xa, 0x5f,0x1b,0x54,0x80,0x2, 0x7c,0xbf,0xf5,0x51,0xe5,0x2a,0xbc,0xbe,0x78, +0x1c,0xd2,0x4, 0x4c,0xee,0x68,0x7, 0xe5,0x43,0x14,0xbc,0xbe,0x78,0x2, 0xd2,0x5, +0xbe,0xe0,0x0, 0x28,0x2, 0x1b,0xe0,0xbd,0x10,0x58,0x2, 0x5, 0x2a,0xbc,0xdf,0x78, +0x1c,0xd2,0x4, 0x4c,0xff,0x68,0x7, 0xe5,0x44,0x14,0xbc,0xbf,0x78,0x2, 0xd2,0x5, +0xbe,0xf0,0x0, 0x28,0x2, 0x1b,0xf0,0xbd,0x32,0x58,0x2, 0xb, 0xd0,0x75,0x30,0x0, +0x75,0x31,0x0, 0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f,0xa, 0x2b,0x9, 0x72,0x26,0x5b, +0xbe,0x71,0x4e,0x38,0x7, 0xbe,0x71,0x4f,0x40,0x2, 0x5, 0x30,0x5, 0x2f,0x7e,0x73, +0x26,0x84,0xbe,0x71,0x2f,0x38,0xe1,0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f,0xa, 0x2b, +0x9, 0x72,0x26,0x6f,0xbe,0x71,0x50,0x38,0x7, 0xbe,0x71,0x51,0x40,0x2, 0x5, 0x31, +0x5, 0x2f,0x7e,0x73,0x26,0x85,0xbe,0x71,0x2f,0x38,0xe1,0x7a,0xe1,0x3f,0x80,0x4f, +0x7a,0xf1,0x40,0x80,0x43,0xe5,0x3f,0x7e,0x71,0x40,0x12,0x30,0xb6,0x7a,0x35,0x41, +0xbe,0xe1,0x3f,0x68,0x11,0xe5,0x2a,0xbe,0xb1,0x3f,0x68,0xa, 0xbe,0xf1,0x40,0x68, +0x5, 0xbe,0xd1,0x40,0x78,0x9, 0x7e,0x35,0x41,0x2d,0x93,0x5, 0x52,0x80,0x17,0x5, +0x55,0x7e,0x35,0x41,0x2e,0x35,0x53,0x7a,0x35,0x53,0x7e,0x35,0x35,0xbe,0x35,0x41, +0x58,0x2, 0x5, 0x3d,0x5, 0x3e,0x5, 0x40,0xbe,0xd1,0x40,0x50,0xb8,0x5, 0x3f,0xe5, +0x2a,0xbe,0xb1,0x3f,0x50,0xaa,0xe5,0x2a,0x12,0xb7,0x82,0x7c,0xbe,0x12,0xb7,0x7a, +0x12,0xb7,0x82,0xe5,0x2a,0x12,0xb7,0x7a,0x7e,0x85,0x39,0x2e,0x85,0x37,0x30,0x4, +0x9, 0x20,0x5, 0x6, 0x9d,0x98,0x15,0x52,0x15,0x52,0xe5,0x52,0xbe,0xb0,0x4, 0x28, +0x6, 0xe5,0x52,0x24,0xfc,0xf5,0x52,0xbe,0x94,0x0, 0x0, 0x58,0x2, 0x6d,0x99,0x75, +0x45,0x22,0xe5,0x43,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, 0xe5, +0x24,0x60,0x4, 0xe5,0x26,0x70,0xa, 0x12,0xb7,0x72,0x28,0x39,0x75,0x45,0x2c,0x80, +0x34,0x30,0x8, 0x31,0x7e,0xb3,0x33,0x49,0xb4,0x1, 0x2a,0x7e,0x73,0x33,0x4a,0xbe, +0x71,0x2a,0x38,0x21,0xbc,0x7e,0x40,0x1d,0x7e,0x73,0x33,0x4b,0xbc,0x7d,0x38,0x15, +0xbc,0x7f,0x40,0x11,0xe5,0x45,0xa, 0x3b,0x7e,0x24,0x0, 0x3, 0x12,0x1e,0xb9,0x7c, +0xb7,0x25,0x45,0xf5,0x45,0x7e,0x15,0x53,0x1a,0x2, 0x1a,0x0, 0x12,0xa2,0x93,0x2f, +0x10,0xe5,0x45,0xa, 0x1b,0x6d,0x0, 0x12,0x1e,0xeb,0x7f,0x71,0x7a,0x7d,0x46,0x7d, +0x18,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x33,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0xe5, +0x55,0xa, 0xdb,0x6d,0xcc,0xe5,0x52,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1e,0xeb, +0x7a,0x1d,0x4a,0xbf,0x71,0x8, 0x3, 0x75,0x32,0x2, 0x7e,0xa1,0x31,0xe5,0x30,0xa4, +0xbe,0x54,0x0, 0x1, 0x68,0x2, 0x81,0xf, 0x12,0xb7,0x72,0x38,0x2, 0x81,0xf, 0x12, +0xb7,0xba,0xbe,0x24,0x0, 0x5, 0x48,0x2, 0x81,0xf, 0xa, 0x5f,0xa, 0x2d,0x9d,0x25, +0xbe,0x24,0x0, 0x5, 0x58,0x79,0x12,0xb7,0xc5,0x48,0x17,0x12,0xb7,0x21,0xbd,0x23, +0x48,0x10,0x12,0xb6,0xf7,0x48,0xb, 0x74,0x2, 0xac,0xbd,0x12,0xb7,0x15,0x48,0x2, +0x80,0x5a,0xa, 0x2f,0xa, 0x3d,0x9d,0x32,0xbe,0x34,0x0, 0x2, 0x58,0x32,0x12,0x9a, +0x6b,0x7d,0x3, 0x3e,0x4, 0x12,0xb7,0x68,0x2d,0x10,0x12,0xb7,0x9c,0x12,0xb7,0x68, +0x7e,0x70,0x2, 0xac,0x7e,0x12,0xb7,0x4c,0xbd,0x23,0x48,0x14,0x12,0x9a,0x6b,0x7d, +0x3, 0x3e,0x4, 0x7e,0x23,0x2a,0x6e,0x12,0xb7,0x2c,0xbd,0x23,0x48,0x2, 0x80,0x1c, +0xa, 0x2e,0xe5,0x2a,0xa, 0x3b,0x9d,0x32,0xbe,0x34,0x0, 0x2, 0x58,0x11,0x12,0xb6, +0xf7,0x48,0xc, 0x74,0x2, 0xac,0xbd,0x12,0xb7,0x15,0x48,0x3, 0x75,0x32,0x2, 0x12, +0xb7,0x60,0x28,0x5a,0x12,0xb7,0xba,0xbe,0x24,0x0, 0x2, 0x48,0xf, 0x12,0xb7,0xc5, +0x58,0xa, 0x12,0xb7,0x21,0xbd,0x23,0x58,0x3, 0x75,0x32,0x0, 0xa, 0x2f,0xa, 0x3d, +0x7d,0x13,0x9d,0x12,0xbe,0x14,0x0, 0x2, 0x48,0x34,0x12,0x9a,0x71,0x7d,0x23,0x3e, +0x24,0x7e,0x7f,0x6, 0xf8,0x7f,0x7, 0x2d,0x12,0xb, 0xa, 0x10,0x74,0x2, 0xac,0xbf, +0x2d,0x5f,0x7d,0x4e,0xb, 0x2a,0x20,0xbd,0x12,0x58,0x13,0x7d,0x13,0x3e,0x14,0x12, +0xb7,0x9c,0x74,0x2, 0xac,0xbd,0x12,0xb7,0x15,0x58,0x3, 0x75,0x32,0x0, 0x7e,0x73, +0x2, 0x88,0xbe,0x70,0x2, 0x50,0x21,0x12,0xb7,0x58,0xbe,0x34,0x0, 0x0, 0x58,0x18, +0x12,0x30,0xb1,0xbe,0x34,0x0, 0x0, 0x58,0xf, 0x12,0xb7,0x60,0x28,0xa, 0xe5,0x32, +0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x4c,0xcc,0x78,0x2, 0xc1,0x7a,0x7e,0xb3, +0x26,0x84,0xb4,0x2, 0x2, 0x80,0x2, 0xa1,0x5f,0x7e,0xb3,0x26,0x85,0xb4,0x1, 0x2, +0x80,0x2, 0xa1,0x5f,0x7e,0x73,0x2a,0x70,0xa, 0x27,0x1b,0x24,0x7e,0x73,0x26,0x6f, +0xa, 0x37,0xbd,0x32,0x48,0x2, 0xa1,0x5f,0x7e,0x73,0x26,0x5c,0xa, 0x27,0x7e,0x73, +0x26,0x5b,0x12,0xb7,0x93,0xf5,0x56,0x12,0xb7,0xa6,0x58,0x58,0x85,0x56,0x59,0x7e, +0x83,0x2a,0x6e,0x7e,0x90,0x2, 0xac,0x89,0x7e,0xa1,0x59,0x74,0x2, 0xa4,0x2d,0x54, +0x7e,0x7f,0x6, 0xf8,0x7f,0x17,0x2d,0x35,0x7f,0x1, 0x1b,0x15,0xb, 0xa, 0x0, 0x7e, +0x31,0x56,0x74,0x2, 0xac,0x3b,0x2d,0x14,0x7f,0x27,0x2d,0x51,0xb, 0x2a,0x10,0xbd, +0x10,0x8, 0x8, 0xe5,0x59,0xa, 0x5b,0x1b,0x54,0xf5,0x56,0x69,0x21,0x0, 0x2, 0x12, +0xb7,0x68,0x7e,0x71,0x56,0x12,0xb7,0x48,0xbd,0x32,0x8, 0x8, 0xe5,0x59,0xa, 0x5b, +0xb, 0x54,0xf5,0x56,0xe5,0x2a,0xbe,0xb1,0x56,0x28,0x5, 0xbe,0xe1,0x56,0x28,0x9, +0xe5,0x32,0x70,0x1b,0x75,0x32,0x2, 0x80,0x16,0xbe,0xe1,0x56,0x38,0x11,0xe5,0x2a, +0xbe,0xb1,0x56,0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e, +0xb3,0x26,0x84,0xb4,0x1, 0x2, 0x80,0x2, 0xa1,0xfc,0x7e,0xb3,0x26,0x85,0xb4,0x2, +0x2, 0x80,0x2, 0xa1,0xfc,0x7e,0x73,0x26,0x70,0xa, 0x27,0x7e,0x73,0x26,0x6f,0x12, +0xb7,0x93,0xf5,0x57,0x12,0xb7,0xa6,0x58,0x4c,0x85,0x57,0x5a,0x7e,0xa1,0x5a,0x74, +0x2, 0xa4,0x7e,0xf, 0x6, 0xf8,0x7f,0x10,0x2d,0x35,0x7f,0x21,0x1b,0x55,0xb, 0x2a, +0x40,0x7e,0xa1,0x57,0x74,0x2, 0xa4,0x7f,0x70,0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x54, +0x8, 0x8, 0xe5,0x5a,0xa, 0x5b,0x1b,0x54,0xf5,0x57,0x69,0x21,0x0, 0x2, 0x7e,0xa1, +0x57,0x74,0x2, 0xa4,0x2d,0x15,0xb, 0xa, 0x30,0xbd,0x32,0x8, 0x8, 0xe5,0x5a,0xa, +0x5b,0xb, 0x54,0xf5,0x57,0xbe,0xd1,0x57,0x28,0x5, 0xbe,0xf1,0x57,0x28,0x9, 0xe5, +0x32,0x70,0x19,0x75,0x32,0x2, 0x80,0x14,0xbe,0xf1,0x57,0x38,0xf, 0xbe,0xd1,0x57, +0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e,0x73,0x28,0x84, +0xa5,0xbf,0x2, 0x21,0x7e,0x63,0x2, 0x88,0xbe,0x60,0x2, 0x50,0x18,0x7e,0x63,0x2a, +0x3, 0xbe,0x60,0x1, 0x28,0xf, 0xbe,0x73,0x26,0x84,0x28,0x6, 0xbe,0x73,0x26,0x85, +0x38,0x3, 0x75,0x32,0x0, 0x7e,0xb3,0x26,0x83,0xb4,0x1, 0x4e,0x7e,0xb3,0x2, 0x88, +0x70,0x3e,0x12,0xb7,0x60,0x28,0x39,0x12,0xb7,0x58,0xbe,0x34,0xff,0x38,0x58,0xb, +0x12,0x30,0xb1,0xbe,0x34,0xff,0x38,0x58,0x2, 0x80,0x20,0x7e,0xb3,0x2a,0x3, 0xb4, +0x2, 0x28,0x7e,0x73,0x28,0x84,0xbe,0x70,0x5, 0x50,0x1f,0x7e,0x73,0x28,0x85,0xbe, +0x70,0x1, 0x50,0x16,0xe5,0x32,0xbe,0xb0,0x1, 0x28,0xf, 0x75,0x32,0x0, 0x80,0xa, +0x7e,0xb3,0x2a,0x3, 0xb4,0x1, 0x3, 0x75,0x32,0x2, 0xe5,0x32,0xbe,0xb0,0x0, 0x28, +0x5c,0xe5,0x32,0xa, 0x3b,0x2e,0x34,0x2, 0x84,0x7e,0x39,0xb0,0x4, 0x7a,0x39,0xb0, +0xe5,0x2d,0xa, 0x3b,0x9, 0xa3,0x2, 0x8a,0x4c,0xaa,0x78,0x9, 0x12,0xb7,0x8a,0x19, +0xb3,0x2, 0x8a,0x80,0x38,0x12,0xb7,0x8a,0xf5,0x58,0xbc,0xba,0x28,0x3, 0x7a,0xa1, +0x58,0x75,0x2e,0x0, 0x80,0x20,0x9, 0x13,0x2, 0x8a,0xe5,0x2e,0xa, 0x1b,0x9, 0x1, +0x2, 0x8a,0xbc,0x1, 0x68,0x8, 0x9, 0x12,0x2, 0x8a,0xbc,0x1, 0x78,0x6, 0xe5,0x58, +0x19,0xb1,0x2, 0x8a,0x5, 0x2e,0xe5,0x2b,0xbe,0xb1,0x2e,0x38,0xd9,0x5, 0x2d,0xe5, +0x2b,0xbe,0xb1,0x2d,0x28,0x2, 0x1, 0x33,0x5, 0x2c,0xe5,0x2b,0xbe,0xb1,0x2c,0x28, +0x3, 0x2, 0xaf,0xf3,0xda,0x3b,0x22,0xa, 0x2d,0xa, 0x3f,0x2d,0x32,0x7e,0x24,0x0, +0x2, 0x12,0x1e,0xb9,0x7d,0x13,0x3e,0x14,0x7e,0x1f,0x6, 0xf8,0x2d,0x31,0xb, 0x1a, +0x20,0x74,0x2, 0xac,0xbf,0x7e,0xf, 0x6, 0xf8,0x2d,0x15,0xb, 0xa, 0x30,0xbd,0x23, +0x22,0x7d,0x34,0x7d,0x20,0x12,0x1e,0xb9,0x7d,0x3, 0x3e,0x4, 0x7e,0x30,0x2, 0xac, +0x23,0x2d,0x10,0x7e,0x1f,0x6, 0xf8,0x2d,0x31,0xb, 0x1a,0x20,0x7e,0x23,0x2a,0x6e, +0x7e,0x30,0x2, 0xac,0x23,0x7e,0x71,0x2a,0x74,0x2, 0xac,0x7b,0x2d,0x31,0x7e,0xf, +0x6, 0xf8,0x2d,0x13,0xb, 0xa, 0x30,0x22,0xe5,0x24,0x7e,0x71,0x27,0x2, 0x30,0xb6, +0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x1, 0x22,0x7e,0x23,0x2a,0x6e,0x7e,0x30,0x2, 0xac, +0x23,0x22,0x7e,0x73,0x2, 0x88,0xbe,0x70,0x5, 0x22,0x7c,0x7d,0x12,0x30,0xb6,0x9d, +0x93,0x22,0x7c,0x7f,0x12,0x30,0xb6,0x9d,0x93,0x22,0xe5,0x2c,0xa, 0x2b,0x9, 0xb2, +0x2, 0x8a,0x22,0xa, 0x37,0x7d,0x53,0x2d,0x52,0xe, 0x54,0x22,0x7e,0x1f,0x6, 0xf8, +0x2d,0x31,0xb, 0x1a,0x20,0x22,0x9d,0x32,0x12,0x21,0x1a,0xbe,0x34,0x0, 0x6, 0x22, +0xa, 0x3b,0x9d,0x32,0x12,0x21,0x1a,0x7c,0xb7,0x22,0xa, 0x3e,0xe5,0x2a,0xa, 0x4b, +0x7d,0x24,0x9d,0x23,0x22,0x2d,0x43,0x7e,0x4, 0x0, 0x2, 0x7d,0x34,0x7d,0x20,0x12, +0x1e,0xb9,0x3e,0x34,0x7e,0x23,0x2a,0x6e,0x74,0x2, 0xac,0xb2,0x2d,0x35,0x7e,0x7f, +0x6, 0xf8,0x2d,0x3f,0x7d,0x2e,0xb, 0x1a,0x30,0x7e,0x50,0x2, 0xac,0x5e,0x2d,0x25, +0x2d,0xf2,0xb, 0x7a,0x50,0xbd,0x35,0x22,0x6c,0xaa,0x12,0xba,0x41,0x29,0x81,0x0, +0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x12,0xb8,0x3c,0x7c,0xb8,0x54,0xfd,0x4c, +0xb9,0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23, +0x54,0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, +0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xc2,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14, +0x0, 0x5, 0x22,0x6c,0xaa,0x12,0xba,0x41,0x12,0xb8,0x3c,0x7e,0xb, 0xb0,0x54,0xfe, +0x12,0xb8,0x39,0x7e,0xb, 0xb0,0x54,0x7, 0x12,0xb8,0x39,0x7e,0xb, 0xb0,0x54,0xfb, +0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xdb,0x22,0xca,0x79,0xc2,0x3, 0x7e, +0xf0,0x3, 0x7e,0xe3,0x2a,0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37,0x2, 0xa8,0x12,0xba, +0x25,0x38,0x2, 0x21,0x3f,0x12,0xb9,0x48,0x92,0xb, 0x12,0xb8,0x43,0x7c,0xbf,0x12, +0xaf,0x9f,0x4c,0xee,0x68,0xe, 0x7e,0xa3,0x2, 0x85,0x4c,0xaa,0x78,0xa, 0x7e,0xb3, +0x2, 0x86,0x70,0x4, 0xd2,0x3, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x61,0xbe, +0xb0,0x8, 0x28,0x4, 0xd2,0x3, 0x80,0x15,0xd2,0x3, 0x7e,0xb3,0x28,0x84,0xbc,0xbe, +0x78,0xb, 0x20,0xb, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x3, 0x20,0x3, 0x5, +0x7c,0xbf,0x12,0xaf,0x9f,0x7e,0x8, 0x2, 0x8a,0x12,0x32,0x10,0x7a,0xb3,0x2, 0x89, +0xbe,0xb3,0x28,0x84,0x50,0x38,0x7e,0x33,0x2, 0x89,0x80,0x24,0x7e,0x70,0x2, 0xac, +0x73,0x9, 0x23,0x2, 0xaa,0x9, 0x13,0x2, 0xab,0x2e,0x37,0x2, 0xa8,0xb, 0x38,0x50, +0x7e,0x93,0x2a,0x6e,0xac,0x92,0xa, 0x31,0x2d,0x43,0x12,0xba,0x4d,0x12,0x2e,0xd8, +0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xd4,0x74,0x1, 0x7a,0xb3,0x2, 0x87,0x7e,0xa3, +0x2, 0x89,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x2, 0xaa,0x7e, +0x8, 0x26,0xfa,0x12,0x20,0xc3,0x1b,0xfd,0x12,0xb9,0xa4,0xf5,0x61,0x80,0x6, 0x75, +0x61,0x64,0x12,0xba,0x35,0xda,0x79,0x22,0xca,0x3b,0x7e,0xe3,0x28,0x84,0x6c,0xdd, +0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0xba,0x59,0x30,0xe0,0x3d,0x6c,0xcc,0x80,0x2d, +0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x7a,0xb3,0x1f,0x70,0x9, 0xa3,0x26, +0xfb,0x7a,0xa3,0x1f,0x71,0x7f,0x7, 0x12,0x2f,0x47,0x50,0xf, 0x7f,0x7, 0x7e,0xb3, +0x1f,0x71,0x6c,0x77,0x12,0x2f,0x4a,0x50,0x2, 0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38, +0xcf,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb0, +0xc3,0xda,0x3b,0x22,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4e,0xa, 0x31, +0xb, 0x34,0x7c,0x7, 0x80,0x3c,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26,0xfa,0x12, +0xba,0x1d,0x9, 0xb3,0x26,0xfa,0xa, 0x3b,0x12,0xba,0x2d,0x7e,0x70,0x2, 0xac,0x70, +0x9, 0xb3,0x26,0xfb,0x12,0xba,0x1d,0x9, 0xb3,0x26,0xfb,0xa, 0x3b,0x9d,0x32,0x12, +0x21,0x1a,0x7c,0x87,0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28, +0xb, 0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xb0,0x38,0xbc,0xb, 0x10,0x7e,0xb3,0x28,0x84, +0xbc,0xb1,0x38,0xaa,0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22, +0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b,0x7e, +0x70,0x2, 0xac,0x71,0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x1, 0x22,0x9d,0x32,0x12, +0x21,0x1a,0x7c,0x97,0x22,0x7e,0x8, 0x2, 0xe6,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x20, +0xe8,0x7e,0x70,0x6, 0xac,0x7a,0x2e,0x34,0x2, 0xe6,0x6d,0x22,0x22,0x3e,0x44,0x7e, +0x1f,0x13,0x8a,0x2d,0x34,0x1b,0x1a,0x50,0x22,0x7d,0xf5,0x2e,0xf4,0x2, 0xe6,0x6d, +0xee,0x29,0xb7,0x0, 0x5, 0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4,0x6c,0x11,0x80, +0x42,0xbc,0xa1,0x68,0x3c,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x26,0xfb,0xa, 0x20,0xa, +0x33,0x9d,0x32,0x12,0x21,0x1a,0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, 0x74,0x26,0xfa, +0xa, 0x27,0xa, 0x32,0x12,0xba,0x2d,0xbe,0x90,0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18, +0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, 0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, +0x22,0xb, 0x10,0x7e,0x83,0x28,0x84,0xbc,0x81,0x18,0xb6,0x22,0x7c,0x9b,0x7f,0x71, +0x7f,0x60,0x7e,0x34,0x22,0xc9,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x70,0x74,0x2a, +0x12,0x1f,0xad,0x7e,0x58,0x1f,0x70,0x7c,0xb9,0x7e,0x71,0x5b,0x12,0x30,0xb6,0x7d, +0x43,0xe5,0x5c,0x7e,0x71,0x5d,0x12,0x30,0xb6,0x2d,0x34,0xe, 0x34,0x7f,0x5, 0x7e, +0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b,0x6a,0x30, +0x69,0x30,0x0, 0x4, 0x1b,0x7a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78, +0xe1,0x12,0xb7,0x72,0x28,0x2b,0xb, 0x6a,0x20,0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e, +0x24,0x0, 0x10,0x12,0x1e,0xb9,0x1b,0x6a,0x30,0xb, 0x7a,0x30,0x1a,0x26,0x1a,0x24, +0x7e,0x14,0x0, 0xd, 0x12,0x1e,0xfc,0x7e,0x8, 0x0, 0x10,0x12,0x1f,0x58,0x1b,0x7a, +0x30,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x70,0x2, 0x12,0xbe,0xfc,0x7f,0x71,0x7c,0xbf, +0x12,0x30,0xa4,0x12,0xbb,0x60,0x7f,0x17,0x12,0x1f,0x58,0x7c,0xb7,0xda,0xf8,0x22, +0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x22,0xca,0x3b,0x7c,0xfb,0x7f,0x61,0x7f,0x40,0x9f, +0x11,0x7f,0x51,0x7f,0x71,0x7a,0x1d,0x3c,0x7a,0x1d,0x40,0x7a,0x1d,0x44,0xbe,0xf0, +0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80,0x4, 0x7e,0x54,0x2, 0x35,0x7a,0x57,0x23, +0x43,0x6c,0xee,0x80,0x60,0xa, 0x5e,0x7f,0x14,0x12,0xbc,0xb8,0x7a,0x55,0x4a,0xa, +0x5e,0x7f,0x16,0x12,0xbc,0xb8,0x7a,0x55,0x48,0x7e,0x35,0x48,0x12,0xbb,0x60,0x2f, +0x50,0x7e,0x65,0x4a,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x2f,0x70,0x12,0xbb,0x60,0x12, +0xbc,0xae,0x7e,0x1d,0x3c,0x2f,0x10,0x7a,0x1d,0x3c,0x7d,0x16,0x1a,0x2, 0x1a,0x0, +0x7e,0x35,0x4a,0x12,0xbc,0xae,0x7e,0x1d,0x40,0x2f,0x10,0x7a,0x1d,0x40,0x7e,0x15, +0x4a,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x48,0x12,0xbc,0xae,0x7e,0x1d,0x44,0x2f,0x10, +0x7a,0x1d,0x44,0xb, 0xe0,0xbc,0xfe,0x38,0x9c,0xa, 0xdf,0x6d,0xcc,0x7f,0x15,0x7f, +0x6, 0x12,0x1f,0x58,0x7f,0x51,0x7f,0x17,0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x71,0x7e, +0x94,0x0, 0x64,0x7e,0x1d,0x3c,0x7d,0x19,0x12,0x1e,0xfc,0x7e,0x87,0x23,0x43,0x7d, +0x18,0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f,0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x3c,0x7e, +0x1d,0x40,0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x40,0x7e, +0x1d,0x44,0x7d,0x19,0x12,0x1e,0xfc,0x7d,0x18,0x1a,0x2, 0x1a,0x0, 0x12,0x1f,0x58, +0x7a,0x1d,0x44,0x7f,0x15,0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x6d,0x44,0x9f,0x61,0x7f, +0x15,0x7f,0x5, 0x12,0x1e,0xeb,0x7e,0x5d,0x3c,0x9f,0x51,0x7f,0x17,0x7f,0x7, 0x12, +0x1e,0xeb,0x7e,0x7d,0x40,0x9f,0x71,0xbe,0x58,0x0, 0x0, 0x68,0x6, 0xbe,0x78,0x0, +0x0, 0x78,0x6, 0x7e,0x44,0x0, 0x64,0x80,0x18,0x7f,0x16,0x7d,0x19,0x12,0x1e,0xfc, +0x7f,0x5, 0x12,0x1f,0x58,0x7f,0x6, 0x12,0x1e,0xeb,0x7f,0x7, 0x12,0x1f,0x58,0x7d, +0x43,0xbe,0x44,0x0, 0x0, 0x18,0x2, 0x6d,0x44,0x7c,0xb9,0xda,0x3b,0x22,0x1a,0x26, +0x1a,0x24,0x12,0x1e,0xeb,0x7f,0x1, 0x22,0x2d,0x35,0x7e,0x1b,0x70,0xa, 0x57,0x22, +0xca,0x3b,0xf5,0x2a,0x7f,0x31,0x7a,0xd, 0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3, +0x22,0xf7,0x7a,0xb3,0x22,0xf8,0x7e,0x34,0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c, +0x7a,0xb3,0x22,0xf5,0x75,0x2f,0x46,0x75,0x2b,0x0, 0xc1,0xb1,0x12,0xbe,0xec,0x28, +0x1e,0x7e,0x34,0x0, 0x44,0xca,0x39,0x7e,0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34, +0x14,0x6, 0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x22,0xff,0x12,0x20,0xc3,0x1b,0xfd,0x6d, +0x33,0x7a,0x37,0x22,0xf9,0x7a,0x35,0x30,0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a, +0x35,0x34,0x7e,0x34,0x22,0xff,0x7a,0x35,0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38, +0x75,0x2c,0x0, 0x80,0x59,0xe5,0x2c,0xa, 0x3b,0x7e,0xd, 0x26,0x12,0xbe,0xf4,0x2e, +0x35,0x36,0x12,0x2c,0x70,0x7d,0xd3,0x7e,0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a, +0xd7,0x22,0xfb,0xe5,0x2c,0xa, 0x3b,0x7f,0x3, 0x12,0xbe,0xf4,0x2e,0x35,0x38,0x12, +0x2c,0x70,0x7d,0xc3,0x7e,0x35,0x32,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37, +0x22,0xf9,0x2d,0x3d,0x7a,0x37,0x22,0xf9,0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30, +0x2d,0xcd,0x7e,0x35,0x34,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a, +0xbe,0xb1,0x2c,0x38,0xa0,0xe5,0x2a,0xb4,0xa, 0x2a,0x7e,0x37,0x22,0xfb,0xbe,0x34, +0x0, 0x40,0x48,0xb, 0x7e,0x25,0x32,0xbe,0x24,0x0, 0x40,0x48,0x2, 0xc1,0xaf,0xbe, +0x34,0x0, 0x60,0x8, 0x2, 0xc1,0xaf,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x2, +0xc1,0xaf,0x80,0x28,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x20,0x8, 0xb, 0x7e,0x25, +0x32,0xbe,0x24,0x0, 0x20,0x8, 0x2, 0xc1,0xaf,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xc1, +0xaf,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xc1,0xaf,0x7e,0xa3,0x39,0x55, +0x74,0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58,0x2, 0xc1,0xaf,0x7e,0xa3,0x39,0x56,0x74, +0xc, 0xa4,0xbe,0x55,0x30,0x58,0x2, 0xc1,0xaf,0x7e,0x15,0x36,0x6d,0x0, 0x7e,0x1d, +0x26,0xe5,0x2a,0x12,0xbb,0x67,0x7a,0xb3,0x22,0xf4,0x7e,0x15,0x38,0x6d,0x0, 0x7f, +0x13,0xe5,0x2a,0x12,0xbb,0x67,0xf5,0x2d,0x7e,0x73,0x22,0xf5,0xbe,0x73,0x22,0xf4, +0x38,0x7d,0xbe,0x71,0x2d,0x38,0x78,0xe5,0x2d,0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, +0x1a,0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d, +0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4,0xa, 0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1f, +0x7, 0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe,0xb1,0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb, +0x2e,0x35,0x32,0x2e,0x35,0x34,0x7a,0x35,0x3a,0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, +0x64,0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a,0x7a,0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe, +0x35,0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a,0x37,0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22, +0xf7,0x7e,0x73,0x23,0x41,0x7a,0x73,0x22,0xf8,0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, +0x2b,0x12,0xbe,0xec,0x28,0x2, 0x81,0xec,0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40, +0x20,0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, 0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e, +0x73,0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a,0x73,0x39,0x52,0x7a,0xb3,0x39,0x54,0x80, +0x6, 0x74,0x7c,0x7a,0xb3,0x39,0x52,0x7c,0xba,0xda,0x3b,0x22,0x7e,0x73,0x34,0x4f, +0xbe,0x71,0x2b,0x22,0x2d,0x13,0x7e,0xb, 0x50,0xa, 0x25,0x22,0xca,0x79,0x7c,0xa7, +0x7c,0x8b,0x7e,0xb3,0x2a,0x6f,0x7a,0xb3,0x1f,0x34,0x7e,0xb3,0x2a,0x70,0x7a,0xb3, +0x1f,0x35,0x7e,0x70,0x2, 0xac,0x78,0x9, 0x93,0x26,0xfa,0x9, 0x83,0x26,0xfb,0x9f, +0x77,0x1a,0x3a,0x1a,0x79,0x9d,0x73,0xe1,0xb4,0x7a,0xf1,0x2d,0xbe,0xf0,0x0, 0x58, +0xe, 0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x2d,0x7e, +0xb3,0x1f,0x34,0xbc,0xbf,0x18,0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d, +0x32,0x7c,0xb7,0xf5,0x2d,0x1a,0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x2c,0x80, +0x43,0x85,0x2c,0x2e,0xe5,0x2c,0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x2c,0x1a,0x3b,0x1a, +0x28,0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c,0xb7,0xf5,0x2e,0x7e,0xb3,0x1f,0x35,0xbe, +0xb1,0x2c,0x18,0x10,0x1a,0x38,0xe5,0x2c,0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32, +0x7c,0xb7,0xf5,0x2e,0xe5,0x2d,0x7e,0x71,0x2e,0x12,0x30,0xb6,0x1a,0x26,0x1a,0x24, +0x2f,0x71,0x5, 0x2c,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x2c,0x1a,0x3b,0xbd,0x32, +0x8, 0xaf,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18,0x2, +0xe1,0x29,0x7f,0x17,0xda,0x79,0x22,0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x2a,0x6e,0xac, +0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10,0x7e,0x1f,0x13,0x8a,0x2d,0x31, +0x22,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32, +0x13,0x8e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, +0xa0,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x38,0xdc,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b, +0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x5f, +0xfb,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda, +0x5b,0xda,0x6b,0xda,0x7b,0x32,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9, +0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x62,0x7e,0x73, +0x3, 0xfe,0xbe,0x71,0x62,0x38,0x2, 0xd2,0x1a,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9, +0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9, +0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5, +0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf, +0x22,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8,0x7e, +0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b, +0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79,0x30,0x0, 0x6, 0x79,0x20, +0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20, +0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20, +0x0, 0xc, 0x22,0xa9,0xd5,0xcb,0x74,0x10,0x12,0x4f,0x53,0x7c,0x7b,0x12,0x4f,0x5b, +0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x33,0xc7, +0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, 0x33,0xc7,0x79,0x20,0x0, 0x82, +0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x33,0xc7,0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c,0x77, +0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x33,0xc7,0x79,0x30,0x0, 0x86,0x7e,0x34,0x29,0x90, +0x7e,0xf, 0x33,0xc7,0x79,0x30,0x0, 0x8a,0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x33,0xc7, +0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, 0x33,0xc7,0x79,0x30,0x0, 0x8e, +0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb,0xa9, +0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2,0x9c, +0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, 0xd2, +0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8,0x0, +0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8,0xa9, +0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22,0xa9, +0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3, 0xfc,0xb, 0x34,0x7a,0x37,0x3, 0xfc, +0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3, 0xfc,0x22,0x6d, +0x22,0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a, +0xb, 0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22,0x7f,0x71,0x69,0x37,0x0, +0x2, 0x7d,0x53,0x12,0xc2,0x45,0xb, 0x7a,0x20,0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27, +0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35, +0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, 0x7d,0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e, +0x54,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69, +0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12,0x25,0x12,0x1e,0x34,0x1e,0x34,0x2d,0x32, +0x79,0x30,0x0, 0x6, 0x22,0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x22,0x7c,0xab,0x9f, +0x11,0x30,0x3, 0x22,0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b, +0xb0,0x7e,0x78,0x0, 0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e, +0xb, 0x90,0xbc,0xa9,0x38,0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c,0xfb, +0x7e,0x8, 0x1f,0x34,0x12,0xc3,0x3, 0x7e,0x8, 0x1f,0x3c,0x12,0xc3,0xb, 0xd2,0x3, +0x7e,0x8, 0x2a,0xdc,0x7c,0xbf,0x12,0xc2,0x4d,0x7e,0x8, 0x1f,0x34,0x7a,0xf, 0x1f, +0x58,0x7f,0x1, 0x7a,0x17,0x1f,0x5c,0x7d,0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18,0x1f, +0x3c,0x7a,0x1f,0x1f,0x64,0x6c,0x77,0x80,0xe, 0x12,0xc3,0x53,0x50,0x7, 0x12,0xc3, +0x4a,0x19,0x51,0x1f,0x3c,0xb, 0x70,0xbc,0xf7,0x38,0xee,0x12,0xc2,0xf0,0xe4,0x12, +0xc2,0xf8,0xe4,0x12,0xc, 0x9b,0x6d,0x33,0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f,0x5e, +0x12,0xc2,0xf0,0x74,0x1, 0x12,0xc2,0xf8,0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22, +0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, +0x1f,0x58,0x22,0x7e,0x34,0x0, 0x8, 0xe4,0x2, 0x20,0xe8,0x7e,0x34,0x0, 0x1c,0x74, +0x3f,0x2, 0x20,0xe8,0x7e,0x8, 0x1f,0x34,0x12,0xc3,0xb, 0x6c,0x77,0x80,0xe, 0x12, +0xc3,0x53,0x50,0x7, 0x12,0xc3,0x4a,0x19,0x51,0x1f,0x34,0xb, 0x70,0x7e,0x53,0x2a, +0x6e,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x11,0x38, +0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x34,0x2, 0x11,0x38,0xa, 0x27,0x9, 0x52,0x2b,0x44, +0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x2a,0xdc,0xbe,0x60,0x1c,0x22,0x7c,0x7b,0xa5, +0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe, +0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0, +0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, +0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78, +0xfb,0x7c,0xb9,0x22,0x7e,0x27,0x28,0xa3,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64, +0x30,0x0, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, 0x0, +0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59, +0xf4,0x5, 0xf8,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, +0xf8,0x30,0x2, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, 0x4, +0x7e,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3, +0x59,0xf4,0x6, 0x76,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, +0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0xb, 0x7e,0xb3,0x2a,0x73,0xa, 0x4b, +0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33, +0x19,0xb3,0x27,0x72,0xb, 0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0xc5,0x67,0xb, 0x24, +0xa, 0x33,0xbd,0x32,0x48,0xe7,0xe4,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x28,0x85,0x6d, +0x33,0x7a,0x37,0x28,0x86,0x7a,0x37,0x28,0x88,0x7a,0x37,0x28,0x8a,0x7a,0x37,0x28, +0x8e,0x7e,0xd4,0x1f,0x36,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x13,0x8a,0x7a, +0x37,0x1f,0x76,0x7d,0x3d,0x7a,0x37,0x1f,0x7a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f, +0x78,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x1f,0x73,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x1f, +0x72,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x7c,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f, +0x7e,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x80,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1f, +0x74,0x7e,0x73,0x39,0xf7,0x7a,0x73,0x1f,0x75,0x7e,0x8, 0x1f,0x72,0x7e,0x18,0x1f, +0x82,0x12,0x8, 0x0, 0x7e,0x73,0x1f,0x82,0x7a,0x73,0x28,0x84,0x7e,0x73,0x1f,0x83, +0x7a,0x73,0x28,0x85,0x7e,0x37,0x1f,0x84,0x7a,0x37,0x28,0x86,0x7e,0x37,0x1f,0x86, +0x7a,0x37,0x28,0x88,0x7e,0x37,0x1f,0x8c,0x7a,0x37,0x28,0x8a,0x7e,0x37,0x1f,0x8e, +0x7d,0x23,0x7a,0x53,0x28,0x8c,0xa, 0x36,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x1f,0x88, +0x7a,0x37,0x28,0x8e,0x7e,0x37,0x1f,0x8a,0x7d,0x23,0x7a,0x53,0x28,0x90,0xa, 0x36, +0x7a,0x73,0x28,0x91,0x6c,0x33,0x80,0x1b,0x12,0x2e,0xd8,0x74,0x2, 0xac,0xb3,0x49, +0x45,0x15,0x9e,0xa, 0x38,0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29,0x19,0x25,0x26, +0xfb,0xb, 0x30,0x7e,0x23,0x28,0x84,0xbc,0x23,0x38,0xdd,0x6c,0x33,0x80,0x1b,0x74, +0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25, +0x27,0x36,0x7c,0x29,0x19,0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28,0x85,0xbc,0x23, +0x38,0xdd,0x22,0x7c,0xa5,0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x7e,0x8, +0x26,0x86,0x7e,0x34,0x0, 0x3, 0xe4,0x12,0x20,0xe8,0x7e,0x8, 0x26,0x89,0x7e,0x34, +0x0, 0x3, 0x12,0x20,0xe8,0x7a,0xb3,0x26,0x83,0x7a,0xb3,0x26,0x84,0x7a,0xb3,0x26, +0x85,0x7a,0xb3,0x26,0xf0,0x7a,0xb3,0x26,0xf1,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26, +0x6f,0x12,0xc6,0xd1,0x6c,0x55,0x12,0xc6,0x34,0x7a,0xb3,0x26,0x85,0x7e,0x18,0x26, +0x5b,0x12,0xc6,0xe1,0x6c,0x55,0x12,0xc6,0x34,0x7a,0xb3,0x26,0x84,0x6c,0x77,0x80, +0x14,0x12,0xc6,0xbd,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12,0xc5,0x63,0x2e,0x24, +0x26,0x86,0x12,0xc6,0xc6,0x7e,0x63,0x26,0x84,0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80, +0x14,0x12,0xc6,0xbd,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12,0xc5,0x63,0x2e,0x24, +0x26,0x89,0x12,0xc6,0xc6,0x7e,0xa3,0x26,0x85,0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x26, +0x84,0xa4,0x7a,0xb3,0x26,0x83,0x7e,0x18,0x26,0xe6,0x12,0xc6,0xd1,0x7e,0x50,0x1, +0x12,0xc6,0x34,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0xdc,0x12,0xc6,0xe1,0x7e,0x50, +0x1, 0x12,0xc6,0x34,0x7c,0xab,0x7a,0xa3,0x26,0xf1,0x7e,0xb3,0x26,0xf2,0xa4,0x7a, +0xb3,0x26,0xf0,0x22,0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff, +0x80,0x70,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55, +0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, +0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78, +0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69, +0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff, +0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x19,0xbd,0xfe,0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24, +0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0x90,0x60,0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, +0xb, 0xf0,0xbc,0x4f,0x38,0x8c,0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0xb7,0x54, +0x7, 0x7e,0x24,0x0, 0x1, 0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70, +0x22,0x7a,0x1d,0x24,0x7e,0xf, 0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a,0x53, +0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0xf8,0x2d, +0x15,0x7e,0xb3,0x2a,0x6d,0x7e,0x37,0x2a,0x51,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54, +0x0, 0x20,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60, +0xf0,0xa5,0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e, +0x24,0x14,0x78,0xfb,0x7e,0x73,0x34,0x49,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x3, 0xec, +0x80,0x36,0xa5,0xbe,0x30,0x18,0x12,0xc7,0x6d,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb, +0x7e,0x53,0x34,0x4a,0xa, 0x45,0x5d,0x43,0x7e,0x73,0x3, 0xed,0x80,0x1a,0x12,0xc7, +0x6d,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x34,0x49,0xa, 0x4b, +0x5d,0x43,0xa, 0x5a,0x9, 0x75,0x3, 0xee,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54, +0xf, 0x7e,0x34,0x0, 0x1, 0x22,0x7e,0xb3,0x3, 0xeb,0x70,0x6, 0x12,0xc7,0xaf,0x2, +0xc7,0xb5,0x12,0x59,0xaf,0x12,0xc7,0xbb,0x50,0xa, 0x12,0x77,0xb9,0x7c,0x3b,0x12, +0xc7,0xaf,0x80,0x5, 0x12,0xc8,0xce,0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12, +0xc6,0xfa,0x60,0xa, 0x7a,0x33,0x3, 0xee,0x74,0x1, 0x7a,0xb3,0x2a,0x8, 0x22,0xe4, +0x7a,0xb3,0x2f,0x80,0x22,0xe4,0x7a,0xb3,0x39,0xd4,0x22,0x7e,0xb3,0x2f,0x80,0xb4, +0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x17,0x2f,0x90,0xbd,0x13,0x28,0xa, 0x7a,0x37, +0x2f,0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e,0x17,0x2f,0x88,0xbd,0x13,0x50,0x8, +0x7a,0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e,0x17,0x2f,0x8e,0xbd,0x12,0x28,0xa, +0x7a,0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80,0x10,0x7e,0x17,0x2f,0x96,0xbd,0x12, +0x50,0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f,0x94,0x7e,0xb3,0x2f,0xa8,0xb4,0xa, +0xf, 0x12,0x77,0xea,0x7a,0x37,0x2f,0xa0,0x12,0x77,0xe1,0x7a,0x37,0x2f,0xa2,0x22, +0xb4,0x14,0xe, 0x12,0x77,0xea,0x7a,0x37,0x2f,0xa4,0x12,0x77,0xe1,0x7a,0x37,0x2f, +0xa6,0x22,0x7d,0xf2,0x7d,0xe3,0x7e,0x8, 0x2f,0x80,0x7e,0x34,0x0, 0x28,0xe4,0x12, +0x20,0xe8,0x7e,0x8, 0x2b,0xbf,0x7e,0x34,0x3, 0xc0,0x12,0x20,0xe8,0x7a,0xb3,0x3, +0xee,0x7e,0x34,0x62,0x94,0x12,0x23,0x74,0x7a,0x37,0x2b,0xb7,0x7a,0xe7,0x2f,0x84, +0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88,0x7a,0xe7,0x2f,0x8c,0x7a,0xe7,0x2f,0x90, +0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a,0x7a,0xf7,0x2f,0x8e,0x7a,0xf7,0x2f,0x92, +0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb,0x7a,0xf7,0x2b,0xbd,0x7a,0xb3,0x2f,0xa8, +0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x74,0xfe,0x7a,0xb3,0x3, 0xee,0xe4,0x7a,0xb3, +0x2f,0x80,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x39,0xd9,0x9e, +0x37,0x39,0xd5,0x12,0x21,0x1a,0xbd,0x31,0x38,0x12,0x7e,0x37,0x39,0xdb,0x9e,0x37, +0x39,0xd7,0x12,0x21,0x1a,0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xd8, +0xca,0x79,0x6c,0xff,0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x2a,0x2, 0x7e,0xe3, +0x2a,0x3, 0x7e,0xb3,0x39,0xd4,0x60,0x11,0x7e,0xc7,0x39,0xdd,0x4d,0xcc,0x78,0x2, +0x21,0xc2,0xbe,0xd0,0x1, 0x28,0x2, 0x21,0xc2,0xbe,0xd0,0x1, 0x78,0x1d,0xbe,0xb0, +0x4, 0x78,0x2, 0x21,0xc2,0x7e,0xe7,0x29,0x8, 0x7e,0xf7,0x29,0xa, 0x7d,0x3e,0x7d, +0x2f,0x12,0x5d,0x90,0xbe,0xb0,0x1, 0x78,0x2, 0x21,0xc2,0x7e,0xa3,0x39,0xd4,0x7c, +0xba,0x14,0x68,0x29,0x14,0x68,0x54,0x14,0x68,0x23,0x14,0x78,0x2, 0x21,0xbf,0xb, +0xb2,0x68,0x2, 0x21,0xc2,0xbe,0xd0,0x1, 0x68,0x2, 0x21,0xd1,0x4c,0xee,0x68,0x2, +0x21,0xd1,0x74,0x1, 0x7a,0xb3,0x39,0xd4,0x12,0xc9,0xe4,0x80,0x65,0x4c,0xdd,0x78, +0x1d,0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x39,0xd4,0x7e,0x34,0x62,0x6a, +0x80,0x54,0x74,0x4, 0x7a,0xb3,0x39,0xd4,0x7e,0x34,0x62,0x6e,0x80,0x48,0x12,0xc9, +0xed,0x90,0x62,0x5d,0x12,0xc9,0xd8,0x68,0x49,0x80,0x56,0xbe,0xd0,0x1, 0x78,0x51, +0x4c,0xee,0x78,0x4d,0x12,0xc9,0xed,0x7e,0x34,0x62,0x66,0x12,0x23,0x74,0x7e,0x14, +0x62,0x6a,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7,0x39,0xdd,0x40, +0x21,0x90,0x62,0x5c,0x12,0xc9,0xd8,0x68,0x19,0x12,0xc9,0xe4,0x74,0x3, 0x7a,0xb3, +0x39,0xd4,0x7e,0x34,0x62,0x6a,0x12,0x23,0x74,0x7a,0x37,0x39,0xdd,0x80,0x12,0x7e, +0xf0,0x24,0xe4,0x7a,0xb3,0x39,0xd4,0x6d,0x33,0x7a,0x37,0x39,0xdd,0x7c,0xbf,0x80, +0x2, 0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xe4,0x93,0xa, 0x3b,0x12,0xc8,0xa3,0xa, +0xdb,0x4d,0xdd,0x22,0x7a,0xe7,0x39,0xd5,0x7a,0xf7,0x39,0xd7,0x22,0x7a,0xe7,0x39, +0xd9,0x7a,0xf7,0x39,0xdb,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x2f,0x90, +0x7a,0x35,0x2a,0x7e,0x37,0x2f,0x8e,0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c,0x7a,0x35, +0x26,0x7e,0x37,0x2f,0x9e,0x7a,0x35,0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x26, +0x7e,0x14,0x0, 0x2f,0x74,0x9, 0x12,0x1f,0x8c,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d, +0x15,0x7f,0x15,0x2d,0x35,0x12,0xca,0x45,0xb, 0xf0,0x7e,0x73,0x39,0x53,0xbc,0x7f, +0x38,0xda,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34,0x0, 0x0, +0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, +0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35,0x33,0x6d, +0x22,0x7e,0x33,0x39,0x55,0x12,0xca,0x9a,0x7e,0x15,0x2f,0x12,0x1f,0x5, 0x1b,0x6a, +0x30,0xb, 0x7a,0x30,0x9e,0x35,0x35,0x6d,0x22,0x7e,0x33,0x39,0x56,0x12,0xca,0x9a, +0x7e,0x15,0x31,0x12,0x1f,0x5, 0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x1e, +0xeb,0xca,0x3b,0x7f,0x71,0x7e,0x60,0x1, 0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b, +0x7a,0x53,0x22,0xf4,0x7a,0x43,0x23,0xe4,0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x61,0xc2, +0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x60,0x2d,0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf, +0xf5,0x26,0x7f,0x67,0x2d,0xd4,0xb, 0x6a,0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d, +0xad,0x7d,0x7a,0x7c,0x8f,0xbe,0x80,0x0, 0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, +0xa4,0xa, 0x79,0x9d,0x7a,0xbe,0xf0,0x0, 0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe, +0x80,0x2, 0x58,0x7, 0xbe,0xf0,0x2, 0x58,0x2, 0x61,0xc0,0xbe,0x60,0x0, 0x18,0x2, +0x61,0xa8,0xbe,0x70,0xec,0x28,0x2, 0x61,0xcc,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0, +0x8, 0x48,0x61,0xa, 0xa7,0xb, 0xa4,0x7d,0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12, +0xcc,0x10,0x19,0xba,0x22,0xf4,0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0xcc,0x10,0x19, +0xba,0x23,0xe4,0x9, 0xba,0x22,0xf4,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d, +0x6c,0x7c,0xbd,0xa, 0xc7,0x19,0xbc,0x22,0xf3,0x9, 0xbc,0x23,0xe4,0xa, 0xcb,0xa, +0xa4,0x2d,0xac,0x12,0xcc,0x10,0x19,0xba,0x23,0xe3,0x2d,0xdb,0x12,0xcc,0x7, 0x19, +0xbd,0x22,0xf5,0xa, 0xd9,0x12,0xcc,0x5, 0x19,0xbd,0x23,0xe5,0xb, 0xd5,0x7d,0x6d, +0x7c,0x7d,0x80,0x24,0xbe,0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x26, +0xa, 0xcb,0xa, 0xd5,0x12,0xcc,0x5, 0x19,0xbd,0x22,0xf4,0xa, 0xc9,0xa, 0xd4,0x12, +0xcc,0x5, 0x19,0xbd,0x23,0xe4,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x1f,0x7e,0x51,0x26, +0x7c,0x49,0xe5,0x26,0xa, 0xd7,0x19,0xbd,0x22,0xf4,0x19,0x9d,0x23,0xe4,0xb, 0x70, +0xb, 0xa0,0x7e,0xb3,0x39,0x53,0xbc,0xba,0x28,0x2, 0x41,0xc0,0x7a,0x73,0x39,0x53, +0x7e,0xa0,0x1, 0x80,0x25,0xa, 0x3a,0x9, 0xb3,0x22,0xf4,0xa, 0x2b,0x7e,0x70,0x2, +0xac,0x7a,0x7f,0x60,0x2d,0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x23,0xe4,0xa, +0x4b,0x2d,0x3f,0x7d,0x2e,0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x39,0x53,0xbc,0xba, +0x38,0xd3,0xda,0x3b,0x22,0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22, +0xe, 0xa4,0x7d,0x6a,0x7c,0xbd,0xa, 0xa7,0x22,0x74,0x1, 0x7a,0xb3,0x38,0xb4,0x7e, +0x34,0x60,0xa3,0x22,0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b,0x9, 0xa3,0x26,0xfa,0x22, +0x74,0x1, 0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x1d,0x22,0x7e,0x18,0x5, 0xf8,0x7a, +0x1f,0x6, 0xf4,0x22,0xa, 0x2b,0x1b,0x24,0xa, 0x3d,0xbd,0x32,0x22,0x74,0x2, 0xac, +0xbe,0x9, 0xd5,0x26,0xfa,0x9, 0xc5,0x26,0xfb,0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4, +0x7e,0x7b,0x60,0xbc,0x6b,0x22,0x6e,0x34,0xff,0xff,0xb, 0x34,0x7a,0x37,0x2a,0x5e, +0x22,0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x26,0xfa,0x22,0x90,0x60,0x9a,0x93,0xa, +0x3b,0x22,0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x31,0xb, 0xa0,0x22,0x7e,0x34,0x0, 0x3e, +0x74,0xff,0x2, 0x20,0xe8,0x9d,0x32,0x12,0x21,0x1a,0xbe,0x34,0x0, 0x3, 0x22,0x7c, +0xf5,0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33, +0x22,0x6d,0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7e,0x37,0x25,0xf4,0x7a,0x37,0x34, +0x88,0x22,0x7e,0x73,0x38,0xd1,0x7a,0x73,0x2b,0x20,0x22,0x7e,0xb3,0x38,0xf4,0x7e, +0x34,0x0, 0x4, 0x22,0x7d,0x2e,0x12,0x1e,0xb9,0x7d,0xf3,0x22,0x7e,0x73,0x2a,0x2, +0xbe,0x70,0x0, 0x22,0xcc,0xe4,0x33,0x1b,0xa4,0x5b,0x9, 0xd0, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b_Black_V0A_D01_20170712_app.i b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b_Black_V0A_D01_20170712_app.i new file mode 100644 index 0000000000000..7902ed4025434 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_BIEL0X3b_Black_V0A_D01_20170712_app.i @@ -0,0 +1,3227 @@ +0x2, 0x1f,0xd2,0x2, 0xb9,0xc6,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x5a,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x68,0x21,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x74,0x8, 0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x75,0x3f,0xf5,0xfd,0xe5,0xfe,0x22,0x2, 0x0, 0x69,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x33,0x6e,0x32,0x32,0x2, 0x0, 0x6a,0x2, 0x3a, +0xf3,0xff,0xff,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xf, 0x7e,0xf, 0x39,0xb2, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x39,0xc2,0x7e,0x73,0x39,0xc2,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xe, 0x80,0x2, 0xc2,0xe, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x75,0xf7,0x7e,0x1f,0x39,0xb2,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x39,0xb2,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x39,0xb6,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x39,0xbe,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x39,0xbc,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x39,0xe1,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0xbc,0x3e,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x1e, +0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0xe2,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0xb2,0x61,0x3f,0x7e,0x34,0x1d,0x96,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x1d,0xc6,0x61,0x3f,0x7e,0x34,0x1e,0xa, 0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d, +0xf1,0x61,0x3f,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x1e,0x69,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x1e,0x6a,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x39,0xb2,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xb2,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x39, +0xb2,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x39,0xb2,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x20,0xeb,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x33,0xfc,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x39,0xe1,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x39,0xaa,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x39, +0xe1,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x39,0xaa,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x39,0xe1,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x39,0xe1,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x39,0xe1,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x39,0xb2,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x39,0xb2,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x1e,0xb9,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x39,0xb2,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x33,0xfc,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x33,0xfc,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xb2,0x86,0x22,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x33,0xfc,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x33,0xfc, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x33,0xfc, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x33,0xfc,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39,0xdd,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39, +0xdd,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x39,0xdd,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x39,0xdd,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x39,0xaa,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x39,0xaa,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xaa,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xaa,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x39,0xb2,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x39,0xb2,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x39, +0xb2,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x39,0xb2,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x39,0xb2,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x39,0xb2,0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x39,0xb2,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x39,0xb2,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x39, +0xb2,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x39,0xb2, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x39,0xb2,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x39,0xb2,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x39,0xb2,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x39,0xb2,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1e,0xb9,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x1e,0xb9,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x39,0xdd,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x39,0xdd,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x39,0xdd,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1e,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x33,0xfc, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x33,0xfc,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x33, +0xfc,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x39,0xb2,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x39,0xb2,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x39,0xb2,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x39,0xb2, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x39,0xb2,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x39,0xb2,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x33,0xfc,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x33,0xfc,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x33,0xfc,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x33,0xfc,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xe1,0x79,0x30, +0x0, 0xe, 0xc2,0x1d,0xe4,0x7a,0xb3,0x39,0xdc,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x39,0xaa,0x1b,0x1a,0x10,0x7e,0xf, 0x39,0xaa,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x39, +0xe1,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x39, +0xe1,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x33,0xfc,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x33,0xfc,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x33,0xfc,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x33, +0xfc,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x33,0xfc,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1e,0x7e,0xf, 0x33,0xfc,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x33,0xfc,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x1f,0x58,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x1e,0x12,0x1f,0x5, 0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x39,0xb2,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1d,0x7e,0xf, 0x39,0xe1,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x39,0xdc,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x39,0xe1,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x75,0xf7,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x39,0xaa,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x39,0xaa,0x1b,0x1a,0x10,0x7e,0xf, 0x39,0xb2,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xf, 0xe4,0x7a,0xb3,0x39,0xc2,0x7e,0x1f,0x39,0xaa, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xdd,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xdd,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x39,0xdd,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x39,0xb2,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x39,0xb2,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x39,0xdd,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x39,0xdd,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x33,0xfc,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x33,0xfc,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x20,0x9c,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x20,0x9d,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x39,0xaa,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x39,0xaa,0x1b,0x1a,0x10,0x7e, +0x1f,0x39,0xaa,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x39,0xb2,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x39,0xe1,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x39,0xaa,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x39,0xaa,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x39, +0xb2,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x39,0xb2,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x39,0xb2,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x39,0xaa,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x1f,0x7, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x1f,0x7, 0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x39,0xfa,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x1f,0x0, 0xc2,0x10,0xc2,0x11,0xc2,0x13,0x75,0x5a, +0x0, 0x75,0x5b,0x0, 0xc2,0xa, 0xc2,0xb, 0x75,0x1b,0x0, 0x75,0x1c,0x0, 0xc2,0x15, +0x75,0x5c,0x0, 0xc2,0x17,0x75,0x5d,0x0, 0xc2,0x18,0xc2,0x19,0xc2,0x1a,0x75,0x5e, +0x0, 0xc2,0xc, 0x75,0x1d,0x0, 0x75,0x1e,0x64,0xc2,0x1b,0xc2,0x1c,0x75,0x5f,0x0, +0xd2,0x5, 0xd2,0x6, 0xd2,0x7, 0xd2,0x1d,0xc2,0xe, 0xd2,0xf, 0x7e,0x4, 0x0, 0xff, +0x7e,0x14,0x21,0x2d,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, +0xe, 0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b, +0x44,0x78,0xf2,0x80,0xdf,0x2, 0x2c,0x8e,0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, +0x0, 0x10,0xfd,0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45, +0x0, 0xe, 0x1, 0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15, +0x8, 0x16,0x9, 0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21, +0xa9,0x20,0x94,0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19, +0x38,0x18,0x31,0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11, +0x13,0x10,0x11,0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a, +0x2b,0xf0,0xb, 0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef, +0xff,0xfc,0x4d,0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80, +0x7, 0x1b,0x44,0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78,0xf5,0x22,0x32,0x1, 0x19, +0x1, 0x0, 0x2, 0xf8,0x4, 0xe7,0x5, 0xce,0x6, 0xc2,0x7, 0xb5,0x8, 0xff,0x0, 0x1, +0x2, 0x0, 0xff,0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe, +0x24,0x0, 0x0, 0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x32, +0xe5,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x34,0x4f,0x1, 0x0, 0x1, 0x25,0xf6,0x1, 0x0, +0x1, 0x38,0x85,0x0, 0x0, 0x2, 0x38,0xd7,0x0, 0x0, 0x0, 0x2, 0x38,0xd9,0x0, 0x0, +0x0, 0x1, 0x38,0xdb,0x0, 0x0, 0x1, 0x37,0xca,0xff,0x0, 0x1, 0x39,0xf7,0x0, 0x0, +0x1, 0x39,0xf8,0x0, 0x0, 0x2, 0x35,0x88,0x0, 0x0, 0x0, 0x1, 0x35,0xab,0x0, 0x0, +0x1, 0x36,0x24,0x0, 0x0, 0x1, 0x36,0x25,0x0, 0x0, 0x1, 0x36,0x26,0x0, 0x0, 0x3c, +0x36,0x54,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, +0x36,0xcc,0x0, 0x0, 0x1, 0x36,0xcd,0x0, 0x0, 0x1, 0x36,0xce,0x0, 0x0, 0x1, 0x37, +0x48,0x1, 0x0, 0x2, 0x37,0x4b,0x0, 0x0, 0x0, 0x1, 0x2f,0xa9,0x0, 0x0, 0x1, 0x2f, +0xaa,0x0, 0x0, 0x1, 0x2f,0xab,0x0, 0x0, 0x1, 0x37,0x4f,0x1, 0x0, 0x1, 0x37,0xc9, +0x0, 0x0, 0x1, 0x39,0xf9,0x0, 0x0, 0x6, 0x39,0xe5,0x3f,0x1f,0x50,0x11,0x20,0x10, +0x0, 0x1, 0x39,0xeb,0x24,0x0, 0x1, 0x39,0xf2,0x0, 0x0, 0x1, 0x39,0xf3,0x0, 0x0, +0x1, 0x39,0xf4,0x0, 0x0, 0x1, 0x39,0xf5,0x0, 0x0, 0x1, 0x39,0xf6,0x0, 0x0, 0x1, +0x0, 0x60,0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x31,0xcd,0x0, 0x0, 0x2, 0x31, +0xee,0x0, 0x0, 0x0, 0x1, 0x32,0x2c,0x0, 0x0, 0x4, 0x38,0x2a,0x0, 0x0, 0x0, 0x0, +0x0, 0x1, 0x39,0xec,0x0, 0x0, 0x1, 0x39,0xed,0x0, 0x0, 0x2, 0x39,0xee,0x0, 0x0, +0x0, 0x1, 0x39,0xf0,0x64,0x0, 0x1, 0x39,0xf1,0x0, 0x0, 0x1, 0x39,0xfa,0x0, 0x0, +0x1, 0x3, 0xfe,0x0, 0x0, 0x1, 0x3, 0xff,0x0, 0x0, 0x2, 0x2b,0xb9,0x2b,0xbf,0x0, +0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8,0x0, 0x0, 0x1, 0x39,0xc7,0x0, 0x0, 0x1, +0x39,0x28,0xff,0x0, 0x1, 0x39,0x29,0x0, 0x0, 0x1, 0x39,0x2a,0x0, 0x0, 0x1, 0x39, +0x2b,0x40,0x0, 0x1, 0x39,0x2c,0x40,0x0, 0x4, 0x39,0xdd,0x0, 0x0, 0x50,0x0, 0x0, +0x4, 0x39,0xe1,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x39,0xaa,0x0, 0x0, 0x6c,0x0, 0x0, +0x4, 0x39,0xae,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x39,0xb2,0x0, 0x0, 0x68,0x0, 0x0, +0x4, 0x39,0xc3,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x33,0xfc,0x0, 0x0, 0x60,0x0, 0x0, +0x0, 0x3, 0xe8,0x0, 0xc, 0x1, 0xf4,0x3, 0x20,0x0, 0xa, 0x1, 0x4a,0x2, 0xbc,0x0, +0x9, 0x0, 0xc8,0x1, 0xf4,0x0, 0x6, 0x0, 0x3c,0x1, 0x2c,0x0, 0x6, 0x0, 0x3c,0x0, +0x64,0x0, 0x6, 0x0, 0x3c,0x0, 0x50,0x0, 0x6, 0x0, 0x0, 0x0, 0xe, 0x1c,0x23,0x5, +0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, 0x0, 0x0, 0x1e,0x12,0x41,0x91,0x12,0x66, +0x9f,0x12,0x23,0x24,0x12,0x4d,0x96,0x12,0x9e,0x16,0x2, 0x23,0x1d,0x74,0x1, 0x7a, +0xb3,0x37,0x53,0x22,0x12,0x6b,0x65,0x12,0x23,0x59,0x2, 0x23,0x2d,0x7e,0x34,0x0, +0x3, 0x6d,0x22,0x2, 0x23,0x36,0x7d,0x43,0x7e,0xa3,0x34,0x38,0xbe,0xa0,0x5, 0x50, +0x16,0x7e,0x70,0x4, 0xac,0x7a,0x59,0x43,0x34,0x3b,0x59,0x23,0x34,0x3d,0x7c,0xba, +0x4, 0x7a,0xb3,0x34,0x38,0xc3,0x22,0xd3,0x22,0x6d,0x33,0x7e,0x24,0x6, 0xfc,0x12, +0x23,0x36,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x7, 0x7a,0x2, 0x23,0x36,0x7e,0x34,0x60, +0xa3,0x12,0x23,0xb7,0x12,0x26,0xba,0x12,0x2f,0x97,0x12,0x6b,0x1c,0x12,0x41,0x91, +0x12,0x66,0x98,0x12,0xc8,0xc9,0x12,0x23,0x24,0x12,0x4d,0x96,0x12,0x65,0x9, 0x12, +0x9e,0x16,0x2, 0x23,0x1d,0x7e,0x34,0x61,0x4f,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30, +0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x61,0x51,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x7a, +0x37,0x2a,0x5c,0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x22,0x7e, +0x34,0x61,0x55,0x12,0x23,0xb7,0x7a,0x37,0x28,0x95,0x7e,0x34,0x61,0xc0,0x12,0x23, +0xb7,0x7a,0x37,0x28,0x99,0x7e,0x34,0x61,0xbe,0x12,0x23,0xb7,0x7a,0x37,0x28,0x97, +0x7e,0x34,0x62,0x18,0x12,0x23,0xb7,0x7a,0x37,0x28,0x9b,0x7e,0x34,0x61,0xc2,0x12, +0x23,0xb7,0x7a,0x37,0x28,0x9d,0x7e,0x34,0x61,0xc4,0x12,0x23,0xb7,0x7a,0x37,0x28, +0x9f,0x7e,0x34,0x61,0xc6,0x12,0x23,0xb7,0x12,0x9f,0xc8,0x12,0x23,0xb7,0x7a,0x37, +0x28,0xa3,0x90,0x61,0xca,0xe4,0x93,0x7a,0xb3,0x28,0xa5,0xe4,0x7a,0xb3,0x28,0xa8, +0x12,0x8f,0x61,0x3e,0x34,0x7e,0x8, 0x25,0xf7,0xe4,0x2, 0x20,0xeb,0x12,0x25,0xe5, +0x7e,0xb3,0x37,0x5a,0xb4,0x1, 0x16,0x7e,0x34,0x62,0x3a,0x12,0x23,0xb7,0x7a,0x37, +0x2a,0x5a,0x7e,0x34,0x62,0x3c,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x5c,0x7e,0xb3,0x28, +0xa8,0xb4,0x1, 0x37,0x7e,0x34,0x62,0x44,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x5a,0x7e, +0x34,0x62,0x46,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x62,0x48,0x12,0x23, +0xb7,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x62,0x4a,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x51, +0x7e,0x34,0x62,0x4c,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x53,0x7e,0xb3,0x2a,0x2, 0x70, +0x21,0x7e,0x27,0x2a,0x5a,0x7d,0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12, +0x25,0x55,0xbe,0x34,0x0, 0x28,0x28,0x4, 0x7e,0x34,0x0, 0x28,0x2d,0x32,0x7a,0x37, +0x2a,0x5a,0x22,0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69, +0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34,0x0, 0x20, +0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x6, 0x12,0xbc,0x3e,0x7e,0x34,0x61,0x4f,0x12, +0x23,0xb7,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x37,0xcb,0x7e,0x34,0x61,0x51,0x12,0x23, +0xb7,0xe, 0x34,0xe, 0x34,0x7a,0x73,0x37,0xcc,0x7e,0x34,0x61,0x55,0x12,0x23,0xb7, +0x12,0x25,0x55,0x7a,0x73,0x37,0xcd,0x7e,0x34,0x61,0x59,0x12,0x23,0xb7,0x12,0x25, +0x55,0x7a,0x73,0x37,0xce,0x7e,0x34,0x61,0x5b,0x12,0x23,0xb7,0x12,0x25,0x55,0x7a, +0x73,0x37,0xcf,0x7e,0x34,0x61,0x5d,0x12,0x23,0xb7,0x12,0x25,0x55,0x7a,0x73,0x37, +0xd0,0x7e,0x34,0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24,0x0, 0xff,0x7e, +0x8, 0x37,0xd1,0x12,0x20,0xc6,0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x37,0xfc,0xe5,0x28, +0x7a,0xb3,0x37,0xeb,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x22,0x90,0x60, +0x99,0xe4,0x93,0x7a,0xb3,0x2a,0x4d,0x90,0x60,0x9e,0xe4,0x93,0x7a,0xb3,0x2a,0x4e, +0x7e,0x34,0x61,0x55,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12, +0x23,0xb7,0x7a,0x37,0x2a,0x51,0x7e,0x14,0x61,0x5b,0x7e,0x4, 0x0, 0xff,0xb, 0xa, +0x20,0x7a,0x27,0x2a,0x53,0x7a,0x37,0x2a,0x55,0x90,0x60,0x9d,0xe4,0x93,0x7a,0xb3, +0x2a,0x59,0x12,0x23,0x95,0x12,0xc9,0xf, 0x7e,0x34,0x62,0x18,0x12,0x23,0xb7,0x7a, +0x37,0x2a,0x60,0x90,0x60,0x9f,0xe4,0x93,0x7a,0xb3,0x2a,0x64,0x90,0x60,0xa0,0xe4, +0x93,0x7a,0xb3,0x2a,0x65,0x7e,0x34,0x60,0xa1,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x66, +0x7e,0x34,0x61,0x5d,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3,0x2a,0x6b, +0x7a,0xb3,0x16,0x92,0x22,0x12,0x23,0x95,0x12,0xc9,0xf, 0x7e,0x34,0x61,0x55,0x12, +0x23,0xb7,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12,0x23,0xb7,0x7a,0x37,0x2a, +0x51,0x7e,0x34,0x61,0x5b,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x53,0x22,0x7e,0x34,0x62, +0x4e,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x50,0x12,0x23,0xb7,0x7a, +0x37,0x2a,0x5c,0x7e,0x34,0x62,0x52,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x4f,0x7e,0x34, +0x62,0x54,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62,0x56,0x12,0x23,0xb7, +0x7a,0x37,0x2a,0x53,0x22,0xca,0xf8,0x7e,0xf3,0x38,0x8a,0xbe,0xf0,0x5, 0x78,0xb, +0x74,0x1, 0x7a,0xb3,0x38,0x8a,0x12,0x0, 0xa, 0x80,0x52,0xbe,0xf0,0x4, 0x78,0x13, +0x12,0xc8,0xbe,0x12,0x23,0xb7,0x12,0x26,0xba,0xe4,0x7a,0xb3,0x2b,0x2, 0x12,0x70, +0xd3,0x80,0x3a,0xbe,0xf0,0x6, 0x78,0x19,0x12,0xc8,0xbe,0x12,0x23,0xb7,0x12,0x26, +0xba,0x12,0x49,0x16,0xe4,0x7a,0xb3,0x2b,0x1e,0x12,0x66,0xdd,0x12,0xc9,0x79,0x80, +0x1c,0xbe,0xf0,0x7, 0x78,0x1d,0x12,0xc8,0xbe,0x12,0x23,0xb7,0x12,0x26,0xba,0x12, +0x67,0xf1,0x50,0xfb,0x12,0x67,0x82,0x12,0x66,0xa8,0x12,0x4d,0x96,0x74,0x2, 0x7a, +0xb3,0x38,0x8a,0xda,0xf8,0x22,0x7e,0x34,0x3, 0xe8,0x6d,0x22,0x7a,0x27,0x33,0xeb, +0x7a,0x37,0x33,0xed,0x22,0x7e,0xb3,0x37,0xf0,0x14,0x68,0x5d,0x14,0x78,0x2, 0xe1, +0x6c,0x14,0x68,0x6d,0x24,0x3, 0x68,0x2, 0xe1,0x64,0x12,0xc9,0x93,0x38,0x8, 0x30, +0x14,0xf, 0x12,0x7f,0xbc,0x68,0xa, 0x12,0x63,0x14,0xe4,0x7a,0xb3,0x39,0x6f,0x80, +0x7b,0x7e,0xb3,0x37,0xd1,0x30,0xe0,0x74,0x7e,0x73,0x37,0xd2,0xa, 0x27,0x7e,0x34, +0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x38,0x1b,0xb4,0x1, 0xb, 0x7e,0x34,0x62,0x6a,0x12, +0x23,0xb7,0x2e,0x34,0x4, 0x0, 0xbe,0x37,0x39,0x6d,0x50,0x50,0x12,0x63,0x14,0x12, +0x64,0xef,0xe4,0x7a,0xb3,0x39,0x71,0x80,0x43,0x12,0xc9,0x93,0x28,0x39,0xe4,0x7a, +0xb3,0x37,0xf0,0x7e,0xb3,0x39,0x6f,0xb4,0x1, 0x3, 0x12,0x64,0xef,0xd2,0x1c,0x80, +0x26,0x74,0xff,0x7a,0xb3,0x37,0xca,0x7e,0x34,0x60,0xa5,0x12,0x23,0xb7,0x12,0x26, +0xba,0x12,0x29,0xa9,0x12,0x23,0x6d,0xe4,0x7a,0xb3,0x37,0xf0,0x7a,0xb3,0x39,0xf1, +0xd2,0x1c,0x80,0x8, 0x12,0x64,0xef,0xe4,0x7a,0xb3,0x39,0xf1,0x12,0x84,0x44,0x2, +0x27,0x72,0xca,0x3b,0x7e,0xb3,0x37,0xf0,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x28,0xb8, +0x6c,0xcc,0x6c,0xdd,0x7e,0xb3,0x38,0x1b,0xb4,0x1, 0xc, 0x90,0x61,0x62,0xe4,0x93, +0x7c,0xeb,0x90,0x61,0x64,0x80,0xa, 0x90,0x61,0x61,0xe4,0x93,0x7c,0xeb,0x90,0x61, +0x63,0xe4,0x93,0x7c,0xfb,0x12,0x84,0xe7,0x7d,0xf3,0x12,0x67,0xf1,0x50,0xfb,0x74, +0x1, 0x7a,0xb3,0x39,0x70,0x12,0x40,0x2a,0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74,0xa, +0x12,0x71,0x34,0x12,0xc9,0x5f,0x7e,0xe7,0x2b,0xd, 0x7a,0xe5,0x25,0x7e,0xb3,0x2a, +0xfa,0xf5,0x24,0x74,0x4, 0x7a,0xb3,0x2a,0xfa,0x7e,0xe7,0x2b,0xd, 0x5e,0xe4,0x0, +0x3f,0x7a,0xe7,0x2b,0xd, 0x7e,0xb3,0x2a,0xfa,0x12,0x71,0xec,0x7c,0x7b,0x74,0x8, +0xac,0x7b,0x7e,0x24,0x0, 0x4, 0x12,0x1e,0xb9,0x7d,0x23,0x7d,0x3f,0x12,0x25,0x55, +0xad,0x32,0x7a,0x37,0x2b,0x7, 0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0x87,0xfa, +0x1, 0x99,0x12,0x26,0xb6,0x30,0x11,0x2, 0x1, 0x9f,0x7c,0xbe,0x12,0x85,0x47,0x12, +0x47,0xa5,0x80,0xf, 0x80,0x7, 0x12,0x29,0x10,0xe4,0x12,0x29,0x48,0x20,0x93,0xf6, +0x12,0x28,0xe0,0x30,0x1d,0xf7,0x30,0x1c,0xf4,0xd2,0x1, 0x12,0x28,0xc6,0xe4,0x12, +0x13,0xde,0xb, 0xc0,0x12,0x81,0x1c,0x12,0x88,0x12,0x7e,0xa3,0x39,0x6f,0x4c,0xaa, +0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x70,0x4c,0xaa,0x68,0xb, 0x7e,0xb3,0x38,0x1b, +0x70,0x5, 0xe4,0x7a,0xb3,0x39,0x6f,0x12,0x28,0xbb,0x78,0x18,0x7e,0xb3,0x39,0x6f, +0x60,0x12,0xe4,0x7a,0xb3,0x39,0x6f,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a,0x3, 0x7e, +0xd0,0x1, 0x80,0x1b,0x12,0x28,0xbb,0x68,0x10,0x7e,0xb3,0x39,0x6f,0x70,0xa, 0x7e, +0xd0,0x1, 0xe4,0x7a,0xb3,0x37,0xf0,0x80,0x6, 0xbc,0xfc,0x28,0x2, 0x1, 0x12,0xe4, +0x7a,0xb3,0x2b,0x4, 0x7e,0x35,0x25,0x7a,0x37,0x2b,0xd, 0xe5,0x24,0x7a,0xb3,0x2a, +0xfa,0x4c,0xdd,0x68,0x3, 0x12,0x4d,0x96,0xda,0x3b,0x22,0x7e,0x73,0x39,0xdc,0xa, +0x37,0x5e,0x34,0x0, 0x2, 0x22,0x30,0x1, 0x6, 0x12,0x2f,0xe5,0x2, 0x13,0x96,0x12, +0x2f,0xf4,0xc2,0x2, 0x2, 0x28,0xd7,0xa9,0xd0,0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22, +0x30,0x1d,0x5, 0xc2,0x1, 0x12,0x28,0xc6,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1c, +0x3, 0x20,0x1d,0x14,0x12,0x29,0x10,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12, +0x29,0x48,0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x1, 0x2, 0x28,0xc6, +0x74,0x81,0x7a,0xb3,0x39,0xec,0x22,0x80,0x1d,0x12,0x29,0x10,0x12,0x84,0x71,0x68, +0x5, 0xc2,0x1, 0x12,0x28,0xc6,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20, +0x1c,0x15,0xe4,0x12,0x29,0x48,0x20,0x93,0xe0,0x12,0x29,0x10,0xa9,0xd1,0xcd,0xa9, +0xc5,0xea,0x74,0x2, 0x2, 0x29,0x48,0x22,0x7c,0xab,0x7e,0xb3,0x39,0xec,0xb4,0x81, +0x38,0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2, +0xaf,0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0, +0x2, 0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1, +0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x39,0xec,0x22,0xd2, +0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12,0x84,0x71,0x68,0x7, 0xc2,0x0, 0xc2,0x1, 0x12, +0x28,0xc6,0x12,0x29,0x17,0x30,0x1c,0xeb,0x22,0x12,0x29,0x10,0x12,0x84,0x79,0x75, +0xcd,0x0, 0xa9,0xd6,0xeb,0xa9,0xd7,0xcd,0xc2,0xce,0x12,0x6e,0xe5,0x12,0x2c,0xde, +0x74,0x1, 0x12,0x29,0x48,0xa9,0xc6,0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25,0x7e, +0x71,0x24,0x2, 0x29,0xd5,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x29,0xf6,0x7a, +0x61,0xfc,0x12,0x2c,0x78,0x12,0x71,0x4f,0xd2,0x0, 0x12,0x84,0xbc,0x12,0x2f,0xe5, +0x12,0x13,0xde,0x2, 0x13,0x96,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xca,0x79,0xa9,0xd5, +0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x29,0xf6,0x74,0xf, 0x12,0x0, 0x46,0x7c,0xfb, +0x74,0xf, 0x7c,0x7f,0x5e,0x70,0xfe,0x12,0x29,0xf6,0x74,0xc, 0x12,0x0, 0x46,0x7c, +0xfb,0x54,0x7f,0x68,0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x29,0xf6,0x90,0x61,0x18, +0xe4,0x93,0x7c,0xab,0xbe,0xa0,0x7, 0x38,0xb, 0x12,0x2d,0xd, 0x7c,0xb7,0xa, 0x7b, +0xb, 0x75,0x80,0x16,0x90,0x61,0x17,0xe4,0x93,0xb4,0x1, 0xe, 0xbe,0xa0,0x7, 0x28, +0x9, 0x12,0x2d,0xd, 0xa, 0x77,0x2e,0x74,0x0, 0x7, 0x74,0xe, 0x7c,0x7f,0x12,0x29, +0xf6,0x74,0x7, 0x12,0x0, 0x46,0x7c,0xfb,0x5e,0xf0,0xfb,0x90,0x60,0x2, 0xe4,0x93, +0xa, 0x3b,0x3e,0x34,0x3e,0x34,0x4c,0xf7,0x74,0x7, 0x7c,0x7f,0x12,0x2c,0x75,0xda, +0x79,0x22,0xca,0xd8,0xca,0x79,0x7d,0xd3,0x90,0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90, +0x60,0x51,0xe4,0x93,0x7c,0x8b,0xa, 0x38,0xa, 0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c, +0x7c,0xe7,0x12,0x26,0xb6,0xa9,0xd0,0xc4,0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x0, 0x46, +0x7c,0x8b,0x74,0x7, 0x7e,0x70,0xf, 0x12,0x2c,0x75,0x7e,0x54,0x0, 0x78,0x7e,0x1f, +0x39,0xae,0x79,0x51,0x0, 0x6, 0x7e,0x54,0x0, 0x80,0x7e,0x1f,0x39,0xae,0x79,0x51, +0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f,0x39,0xae,0x79,0x51,0x0, 0x10,0xbe,0xd4, +0x0, 0x2, 0x78,0xb, 0x7e,0x1f,0x39,0xae,0x12,0x2c,0x6d,0x44,0x1, 0x80,0x20,0x7e, +0x1f,0x39,0xae,0x12,0x2c,0x6d,0x44,0x8, 0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x39, +0xae,0x78,0x7, 0x12,0x2c,0x6d,0x54,0xfb,0x80,0x5, 0x12,0x2c,0x6d,0x44,0x4, 0x1b, +0x1a,0x50,0x7e,0x1f,0x39,0xaa,0x69,0xe1,0x0, 0x84,0x69,0x51,0x0, 0x90,0x7d,0xf5, +0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3,0x37,0xfc,0xbe,0xb0, +0x6, 0x40,0x3, 0xb4,0xff,0xe, 0x12,0x2c,0x82,0x54,0xe6,0x12,0x2c,0x7f,0x4e,0x54, +0x1, 0xa4,0x80,0xc, 0x12,0x2c,0x82,0x5e,0x54,0xfe,0xe6,0x12,0x2c,0x7f,0x44,0xa4, +0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x2d,0x7e,0x1f,0x39,0xae,0x12,0x2c,0x6d, +0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0x7e,0x1f,0x39,0xae,0x12,0x2c,0x6d,0x44,0x50, +0x1b,0x1a,0x50,0x7e,0x34,0x0, 0x2, 0x12,0x2d,0xca,0x12,0x2d,0xa3,0x12,0x2d,0x80, +0x7a,0x37,0x32,0xe9,0x81,0x29,0x6c,0xdd,0x81,0x23,0x4c,0xdd,0x78,0x4, 0x6c,0x99, +0x80,0x2b,0xbc,0xfd,0x40,0x12,0xa, 0xcd,0x9, 0x9c,0x2a,0xb8,0xbe,0x90,0x23,0x40, +0x3, 0x7e,0x90,0x22,0xb, 0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3,0x9, 0x9c, +0x2a,0xdb,0xbe,0x90,0x1c,0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x7e,0x1f,0x39, +0xae,0x12,0x2c,0x6d,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0xa, 0xc9,0x3e,0xc4,0x3e, +0xc4,0x3e,0xc4,0x3e,0xc4,0x7e,0x1f,0x39,0xae,0x12,0x2c,0x6d,0x4d,0x5c,0x1b,0x1a, +0x50,0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, +0x80,0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x2d,0xca,0x12,0x2d,0xa3,0xbe,0xd4,0x0, 0x1, +0x78,0x10,0x12,0x2d,0xa3,0x12,0x2d,0x80,0x74,0x2, 0xac,0xbd,0x59,0x35,0x32,0xeb, +0x80,0xf, 0x12,0x2d,0x80,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59,0x32,0x32, +0xeb,0xb, 0xd0,0xbc,0xed,0x28,0x2, 0x61,0x8a,0xa9,0xd5,0xcb,0x74,0x7, 0x7c,0x78, +0x12,0x2c,0x75,0xa9,0xc0,0xc4,0x7e,0x1f,0x39,0xaa,0x79,0xe1,0x0, 0x84,0x7e,0x1f, +0x39,0xaa,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x39,0xae,0x79,0x30,0x0, 0x6, +0x7e,0xf, 0x39,0xae,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x39,0xae,0x79,0x30,0x0, 0x10, +0x7e,0xf, 0x39,0xae,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x2e,0x34,0x0, +0xe, 0xb, 0x1a,0x50,0x22,0x12,0x29,0xf6,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0x1b, +0x1a,0x50,0x7e,0x1f,0x39,0xaa,0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50,0x22,0x12,0x2f, +0x97,0x12,0x24,0xb3,0x12,0x6b,0x1c,0x12,0x23,0xb, 0x7e,0xb3,0x37,0xf2,0x24,0xfd, +0x68,0x9, 0xb, 0xb1,0x78,0xf4,0x12,0x51,0x39,0x80,0xef,0x12,0x32,0xf5,0x80,0xea, +0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x12,0x12,0xbc,0x3e,0xe5,0x34,0x20, +0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, 0x7e,0x71,0x27,0x12,0x29,0xf6,0x74,0xb, 0x7e, +0x71,0x2f,0x12,0x29,0xf6,0x74,0xc, 0x7e,0x71,0x30,0x12,0x2c,0x75,0x22,0x12,0x2f, +0xf4,0xc2,0x0, 0x12,0x71,0xca,0xc2,0x2, 0x12,0x28,0xd7,0xc2,0x0, 0x12,0x84,0xbc, +0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x0, 0x46,0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77,0x12, +0x29,0xf6,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, 0x2c,0x78,0xa, 0x3a,0x2e, +0x34,0x0, 0x3, 0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x7e,0x24,0x37,0xcb, +0x30,0x11,0x5c,0xc2,0x11,0x9, 0x72,0x0, 0x2, 0xa, 0x37,0x12,0x2d,0x13,0x7a,0x37, +0x2a,0x4f,0x9, 0x72,0x0, 0x3, 0xa, 0x37,0x12,0x2d,0x13,0x7a,0x37,0x2a,0x51,0x9, +0x72,0x0, 0x4, 0xa, 0x37,0x12,0x2d,0x13,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0x12, +0x2f,0xed,0x7a,0x37,0x2a,0x5a,0x9, 0x72,0x0, 0x1, 0x12,0x2f,0xed,0x7a,0x37,0x2a, +0x5c,0x9, 0x72,0x0, 0x5, 0xa, 0x37,0x12,0x2d,0x13,0x7a,0x37,0x2a,0x62,0x9, 0x72, +0x0, 0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a,0x73,0x2a,0x6b,0x2, 0x5f,0xe0,0x22, +0x7e,0xf, 0x39,0xae,0x69,0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, +0x6d,0x0, 0x2f,0x10,0x74,0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14, +0x78,0xf4,0x22,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xae,0x79,0x30,0x0, 0x4, 0x7e, +0xf, 0x39,0xae,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, +0x1, 0x79,0x30,0x0, 0x12,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e,0x30, +0x4, 0x80,0x5, 0x74,0xfa,0x12,0x71,0x34,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, 0xf3, +0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x30,0x8, 0x3b,0xc2,0x8, 0x12,0x26, +0x45,0x7e,0x73,0x38,0x8b,0x7a,0x73,0x2a,0x4d,0x7e,0x73,0x38,0x8c,0x7a,0x73,0x2b, +0x1d,0x7e,0x73,0x38,0x8c,0x7a,0x73,0x2b,0x1, 0x7e,0xb3,0x38,0x8d,0x60,0x18,0x7e, +0x34,0x0, 0x2, 0x12,0x2a,0x82,0x7e,0x34,0x0, 0x1, 0x12,0x2a,0x82,0x6d,0x33,0x12, +0x2a,0x82,0xe4,0x7a,0xb3,0x38,0x8d,0x12,0x45,0x7a,0x2, 0x2e,0x2d,0xe5,0xc, 0x70, +0x2, 0xe1,0x50,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, 0xfe,0x12,0x6a,0x86,0x12,0x6f, +0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x9, 0xa1,0xe5,0xc, 0x30,0xe1,0x6, 0x53,0xc, 0xfd, +0x12,0xbe,0xac,0xe5,0xc, 0x30,0xe2,0x32,0x53,0xc, 0xfb,0x7e,0xb3,0x2b,0x12,0x60, +0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x6, 0xba,0x80,0xb, 0x7e,0xb3,0x2b,0x65,0x7e,0x73, +0x2b,0x64,0x12,0xb, 0xad,0x7e,0x73,0x2b,0x12,0x2e,0x70,0xff,0x92,0x1, 0x90,0x60, +0x51,0xe4,0x93,0x9e,0xb3,0x2a,0x77,0x12,0xb, 0x1e,0xe5,0xc, 0x30,0xe3,0x4b,0x53, +0xc, 0xf7,0x7e,0x73,0x38,0xb8,0x7a,0x73,0x2b,0xf, 0x12,0x67,0xa7,0x7a,0xb3,0x0, +0x60,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e,0x73,0x0, 0x60,0x7a,0x73,0x38, +0x90,0x12,0x4f,0x61,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72,0x7e,0x73,0x38,0xb9,0xbe, +0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10, +0x12,0xac,0xf5,0xe4,0x12,0xa, 0x66,0x12,0x9e,0x16,0xe5,0xc, 0x30,0xe4,0xf, 0x53, +0xc, 0xef,0x7e,0x43,0x38,0xba,0x7e,0x50,0xa, 0xac,0x45,0x12,0x48,0x32,0xe5,0xc, +0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e,0x73,0x38,0xa6,0xbe,0x70,0x7, 0x28,0x6, 0x74, +0x7, 0x7a,0xb3,0x38,0xa6,0xa9,0xd5,0xcb,0x74,0xe, 0x12,0x0, 0x46,0x7c,0x7b,0x5e, +0x70,0xf, 0x7e,0x63,0x38,0xa6,0xa, 0x26,0x2e,0x24,0x0, 0x3, 0x12,0x93,0x26,0x7c, +0x65,0x4c,0x76,0x74,0xe, 0x12,0x29,0xf6,0x12,0x0, 0x46,0x12,0x2c,0x78,0x7e,0x73, +0x38,0xa9,0x7a,0x73,0x2b,0x14,0x7e,0x73,0x38,0xa8,0x7a,0x73,0x2b,0x1f,0x12,0xc9, +0x79,0xe5,0xc, 0x30,0xe5,0xa, 0x53,0xc, 0xdf,0x7e,0xb3,0x38,0x90,0x2, 0x48,0x80, +0x22,0x24,0xab,0x68,0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78, +0x2f,0x74,0x5, 0x80,0x2d,0x7e,0xb3,0x34,0x4f,0xb4,0x5, 0x2a,0x12,0x2d,0xc6,0x12, +0xba,0x21,0x2, 0xbb,0x3b,0x7e,0xb3,0x34,0x4f,0xb4,0x5, 0x1a,0x12,0x2d,0xc6,0x75, +0xe9,0xff,0x22,0x7e,0xb3,0x34,0x4f,0xb4,0x5, 0xc, 0x12,0x2d,0xc6,0x2, 0xbb,0x35, +0x74,0x1, 0x7a,0xb3,0x34,0x4f,0x22,0xe4,0x12,0x84,0x8b,0x12,0xba,0xd7,0x12,0x26, +0xb6,0x12,0xbb,0x52,0x12,0x29,0xfc,0x12,0xba,0x17,0x12,0xba,0xee,0x12,0x0, 0x9, +0x12,0xba,0xfa,0x12,0x75,0x65,0x12,0xbb,0xa, 0xd2,0xaf,0x12,0xba,0x69,0x12,0xbc, +0xc6,0x12,0x2c,0xb0,0x12,0x71,0x4f,0x7e,0x8, 0x33,0xef,0x12,0xa3,0xf5,0x90,0x60, +0x50,0xe4,0x93,0xca,0xb8,0x90,0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24,0xff,0xff, +0xda,0xb8,0x2, 0x12,0x34,0xd2,0x2, 0x12,0x28,0xd7,0x74,0x1, 0x22,0xa, 0x37,0x3e, +0x34,0x3e,0x34,0x22,0xe4,0x12,0x13,0xde,0x2, 0x13,0x96,0xca,0xf8,0x7c,0xab,0xbe, +0xa0,0x34,0x38,0x2, 0x21,0xc, 0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0x41, +0x2b,0xbe,0xa0,0x36,0x68,0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23, +0xb, 0x24,0x7a,0x25,0x8, 0x2e,0x37,0x32,0xe3,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68, +0x2, 0x41,0x2b,0x75,0x1a,0x36,0x41,0x2b,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39, +0x78,0x1b,0x7e,0xf3,0x38,0xaa,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xaa,0xbe,0xa0,0x39, +0x78,0x3, 0x75,0x1a,0x38,0xa, 0x3f,0x9, 0xb3,0x2b,0x21,0x41,0x2b,0xbe,0xa0,0x3a, +0x68,0x5, 0xbe,0xa0,0x3b,0x78,0x1b,0x7e,0xf3,0x38,0xac,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xac,0xbe,0xa0,0x3b,0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44, +0x41,0x2b,0xbe,0xa0,0xfb,0x78,0x6, 0x7e,0xb3,0x2b,0x12,0x41,0x2b,0xbe,0xa0,0x5e, +0x78,0x26,0x7e,0xf, 0x39,0xaa,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x5e,0x54,0x0, 0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, +0x7c,0xa7,0x4c,0xba,0x44,0x80,0x41,0x2b,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d, +0x78,0x1b,0x7e,0xf3,0x38,0xae,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xae,0xbe,0xa0,0x3d, +0x78,0x3, 0x75,0x1a,0x3c,0xa, 0x3f,0x9, 0xb3,0x2a,0x7a,0x41,0x2b,0xbe,0xa0,0x3e, +0x68,0x5, 0xbe,0xa0,0x3f,0x78,0x1b,0x7e,0xf3,0x38,0xb0,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xb0,0xbe,0xa0,0x3f,0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d, +0x41,0x2b,0xbe,0xa0,0x40,0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3, +0x38,0x86,0x41,0x2b,0xbe,0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3, +0x38,0xcb,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xcb,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1a, +0x4e,0xa, 0x3f,0x2e,0x37,0x32,0xe1,0x7e,0x39,0xb0,0x41,0x2b,0xbe,0xa0,0x51,0x68, +0x5, 0xbe,0xa0,0x52,0x78,0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff, +0x7e,0xb3,0x38,0xd6,0xa, 0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3, +0x38,0xd6,0xbe,0xa0,0x52,0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0x41,0x2b,0xbe,0xa0, +0x5c,0x68,0x5, 0xbe,0xa0,0x5d,0x78,0x1a,0x7e,0xf3,0x38,0x9f,0x7c,0xbf,0x4, 0x7a, +0xb3,0x38,0x9f,0xbe,0xa0,0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0x32,0x2e, +0x41,0x2b,0xbe,0xa0,0x60,0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3, +0x33,0x8f,0x41,0x2b,0xbe,0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x7e,0xbe,0xa0,0xf4, +0x68,0x5, 0xbe,0xa0,0xf5,0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25, +0xa, 0x9, 0xb3,0x32,0xe9,0xbe,0xa0,0xf5,0x78,0x61,0x75,0x1a,0xf4,0x80,0x5c,0xbe, +0xa0,0xf0,0x68,0x5, 0xbe,0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7, +0x80,0x49,0xbe,0xa0,0xf2,0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e, +0x14,0x7e,0x1f,0x32,0xe5,0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, +0x56,0x80,0x28,0x7d,0x53,0x80,0x24,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x1b, +0xbe,0xa0,0xf7,0x78,0xd, 0x7e,0x34,0x62,0x4e,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x50, +0x80,0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7c,0xab, +0xbe,0xa0,0x0, 0x40,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4, +0x49,0x25,0x34,0x0, 0x80,0x51,0x7e,0x13,0x2a,0x6e,0xbc,0x1a,0x38,0x1c,0x7e,0x3, +0x2a,0x6d,0xa, 0x10,0xa, 0x21,0x2d,0x12,0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32, +0x3e,0x34,0x3e,0x34,0x49,0x23,0x3, 0x71,0x80,0x2d,0x7e,0x3, 0x2a,0x6d,0xa, 0x20, +0xa, 0x11,0x7d,0x41,0x2d,0x42,0xa, 0x3a,0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac, +0x1, 0x2d,0x1, 0xbd,0x30,0x58,0xe, 0x9d,0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49, +0x23,0x3, 0x73,0x80,0x2, 0xe4,0x22,0x7e,0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e, +0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8, +0x80,0x38,0x7c,0xbf,0x12,0x32,0x2e,0xa, 0x1b,0x7e,0x63,0x2a,0x6e,0x7e,0x70,0x2, +0xac,0x67,0x7e,0x10,0x2, 0xac,0x1f,0x2d,0x3, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x12, +0x32,0xed,0x9d,0x35,0x1b,0x1a,0x10,0xb, 0xf0,0x12,0x32,0xed,0x7e,0x73,0x2a,0x6e, +0xa, 0x27,0x2d,0x25,0xa, 0x3f,0xbd,0x32,0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x2a, +0x6d,0x74,0x2, 0xa4,0x22,0x12,0x48,0x9, 0x7e,0xb3,0x37,0xf2,0xb4,0x3, 0x69,0x12, +0xbb,0x59,0x12,0x26,0xb6,0x12,0x2d,0xe9,0x7e,0xb3,0x38,0x86,0x30,0xe7,0xe9,0x12, +0x4d,0xb0,0x12,0x37,0x30,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, +0xfc,0x12,0x20,0xc6,0x1b,0xfd,0x12,0x37,0x30,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, +0x7e,0x7e,0x8, 0x5, 0x7a,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, +0x15,0x12,0xa7,0xc8,0x12,0x5f,0x6a,0x12,0x5b,0xa7,0x12,0x9c,0x17,0x12,0x37,0x25, +0x12,0x33,0x78,0x12,0x50,0x9b,0x12,0x48,0x42,0x12,0x32,0xae,0x7e,0xb3,0x38,0x86, +0x54,0x7f,0x7a,0xb3,0x38,0x86,0x80,0x90,0x12,0xbe,0xf5,0x2, 0x0, 0x66,0xe4,0x7a, +0xb3,0x2b,0x2, 0x7a,0xb3,0x2b,0x1e,0x22,0x12,0x7c,0x1f,0x12,0x35,0x6f,0x12,0x35, +0x6f,0x12,0x37,0xde,0x12,0x38,0xab,0x12,0x37,0x58,0x12,0x35,0x6f,0x12,0x89,0xb5, +0x12,0x35,0x6f,0x12,0x97,0x2a,0x12,0x35,0x6f,0x2, 0x33,0x9c,0xca,0x3b,0x75,0x24, +0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x36,0x90,0x7e, +0x8, 0x36,0x54,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0xf3,0x28,0x84,0xa, 0xcf,0x3e,0xc4, +0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e,0x8, 0x1f,0x34,0x12,0x20,0xc6,0x1b,0xfd,0x6c, +0x88,0x6c,0xee,0x81,0x70,0x7e,0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99,0x80,0x4c, +0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f,0x34,0xbe,0xb0,0xff,0x68,0x3d,0x7c,0xb9,0x12, +0x37,0x3f,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x35,0xa, 0x27,0x74,0x2, +0xac,0xbe,0x9, 0x75,0x36,0x91,0x12,0x37,0xb, 0x7d,0x13,0x74,0x2, 0xac,0xb9,0x9, +0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x36,0x90,0x12,0x37,0xb, +0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9,0x38,0xb0, +0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x1f,0x34,0x9, 0x73, +0x1f,0x35,0x12,0x35,0xb5,0xbe,0x37,0x2a,0x5a,0x48,0x23,0x7e,0x70,0x2, 0xac,0x7c, +0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac,0xbd,0x19,0x55,0x1f,0x70,0x9, 0x53,0x1f,0x35, +0x19,0x55,0x1f,0x71,0x74,0xff,0x19,0xb3,0x1f,0x34,0xb, 0x80,0xb, 0xd0,0xb, 0xe0, +0x7e,0x73,0x36,0x50,0xbc,0x7e,0x28,0x2, 0x61,0xd5,0x7c,0xe8,0x80,0x6d,0x6d,0xdd, +0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x37,0x3f,0x60,0x33,0x12,0x37, +0xc9,0xbe,0xb0,0xff,0x68,0x2b,0x9, 0x73,0x1f,0x35,0x12,0x5f,0x2c,0x7f,0x71,0xb, +0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, 0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0, +0xbd,0xcd,0x8, 0xd, 0x12,0x37,0xc9,0xf5,0x24,0x9, 0xc3,0x1f,0x35,0x7d,0xdc,0x7c, +0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0,0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74, +0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70,0x19,0xc5,0x1f,0x71,0x7e,0xa0,0xff,0x7e,0x70, +0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34,0xb, 0xd0,0xb, 0xe0,0x90,0x60,0x99,0xe4,0x93, +0xbc,0xbe,0x38,0x8a,0x90,0x60,0x9a,0xe4,0x93,0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59, +0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f,0x34,0x12,0x20,0xc6,0x1b,0xfd,0x7c,0xfd,0x12, +0x93,0x48,0x7e,0x8, 0x36,0x90,0x74,0xff,0x12,0x20,0xeb,0xbe,0xf0,0x0, 0x28,0x35, +0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x26,0xfa,0x12,0x20, +0xc6,0x1b,0xfd,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x36, +0x90,0x12,0x20,0xc6,0x1b,0xfd,0x6c,0xee,0x80,0x7, 0x7c,0xbe,0x12,0x39,0x2c,0xb, +0xe0,0xbc,0xfe,0x38,0xf5,0x7a,0xf3,0x36,0x50,0x7a,0xf3,0x28,0x84,0x90,0x60,0x99, +0xe4,0x93,0xbe,0xb3,0x28,0x84,0x50,0x4, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0xca, +0x79,0x6c,0xff,0x6c,0xee,0x80,0x2e,0x7c,0xbe,0x12,0x37,0x3f,0x60,0x25,0x7e,0x34, +0x0, 0x2, 0xca,0x39,0xac,0x7e,0x2e,0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac, +0x3f,0x2e,0x14,0x26,0xfa,0x6d,0x0, 0x12,0x20,0xc6,0x1b,0xfd,0x7c,0xbf,0x12,0x39, +0x2c,0xb, 0xf0,0xb, 0xe0,0x12,0x5f,0xd9,0x38,0xcd,0x7a,0xf3,0x28,0x84,0xda,0x79, +0x22,0x7c,0xba,0x7c,0x79,0x12,0x5f,0x2c,0xb, 0x1a,0x30,0x22,0xca,0x3b,0x6d,0xee, +0x7e,0xc3,0x2a,0x6e,0x7e,0xd3,0x2a,0x6d,0x7e,0xb3,0x38,0x1b,0xb4,0x1, 0x3, 0xe4, +0xc1,0xf2,0x7e,0xb3,0x28,0x84,0x70,0x2, 0xc1,0x61,0x7e,0xb3,0x2a,0x3, 0x60,0x2, +0x80,0x7f,0x7e,0xa3,0x26,0xfa,0x7e,0x73,0x26,0xfb,0x7a,0x71,0x24,0x6c,0xee,0x6d, +0xff,0x6c,0xff,0xa, 0x47,0x80,0x20,0x12,0x35,0xb1,0xbe,0x34,0x0, 0x96,0x8, 0x1d, +0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x36,0xf8,0x12,0x37,0x12, +0x58,0x3, 0x12,0x36,0xf5,0x1b,0x44,0xbe,0x44,0x0, 0x0, 0x58,0xda,0xe5,0x24,0xa, +0x4b,0x80,0x1e,0x12,0x35,0xb1,0xbe,0x34,0x0, 0x96,0x8, 0x21,0xb, 0xe0,0xbe,0xa0, +0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x36,0xf8,0x12,0x37,0x12,0x58,0x3, 0x12,0x36, +0xf5,0x7d,0x24,0xb, 0x24,0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xd6,0xbe,0xe0,0x3, +0x50,0x2, 0x80,0xd, 0xa, 0x2f,0x7d,0x3f,0x12,0x1e,0xb9,0xbe,0x34,0x0, 0x28,0x8, +0x7, 0xe4,0x7a,0xb3,0x36,0x25,0xc1,0xf2,0x6d,0xdd,0xbe,0xa0,0x0, 0x28,0x8, 0x7c, +0xba,0x14,0x12,0x37,0x2, 0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, 0xca,0xbd,0xc3,0x58, +0x8, 0x7c,0xba,0x4, 0x12,0x37,0x2, 0x2d,0xd3,0x7e,0x70,0x8, 0x80,0x2a,0x7e,0x50, +0x2, 0xac,0x57,0x7d,0xc2,0x2e,0xc4,0x20,0xfd,0x7d,0x1c,0x7a,0x31,0x82,0x7a,0x21, +0x83,0xe4,0x93,0x1a,0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x20,0xfe,0x7d, +0x2c,0x12,0x73,0xff,0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xce, +0x7c,0xba,0x12,0x37,0x2, 0x12,0x21,0x1d,0xbe,0x34,0xa, 0xf0,0x8, 0x4, 0x2e,0xe4, +0x0, 0x28,0xbe,0xe4,0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x36,0x25, +0xa, 0x3b,0xbd,0x3e,0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x36,0x25,0x7e,0xb3, +0x36,0x25,0xda,0x3b,0x22,0x7c,0xba,0x4, 0x7c,0x79,0x12,0x35,0xb5,0x2d,0xf3,0xb, +0xf0,0x22,0x7e,0x71,0x24,0x2, 0x35,0xb5,0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x2, +0x21,0x1d,0xa, 0x2d,0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0x7c,0xb8,0x7c,0x79,0x12, +0x35,0xb5,0xbd,0x3d,0x22,0x12,0x96,0x35,0x12,0x35,0xbc,0x7a,0xb3,0x2a,0xc, 0x22, +0x7e,0x73,0x2a,0x74,0xa, 0x27,0x7e,0x73,0x2a,0x73,0xa, 0x37,0x2d,0x32,0x22,0x7c, +0x7b,0x12,0x37,0xd7,0x9, 0xa2,0x27,0x72,0x7c,0xb7,0x54,0x7, 0xa, 0x3b,0x2e,0x34, +0x0, 0x5e,0x12,0x85,0x57,0x5c,0xba,0x22,0x6c,0x0, 0x6c,0x11,0x80,0x16,0x7c,0xb1, +0x12,0x37,0x3f,0x60,0xd, 0x12,0x37,0xb8,0x12,0xa7,0xae,0x40,0x5, 0x7e,0x0, 0x1, +0x80,0xa, 0xb, 0x10,0x7e,0x73,0x28,0x84,0xbc,0x71,0x38,0xe2,0x7c,0xb0,0x6c,0x77, +0x12,0x98,0x15,0xbe,0x0, 0x1, 0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, 0x12,0x98,0x15, +0xb4,0x1, 0x24,0x6c,0x11,0x80,0x18,0x7c,0xb1,0x12,0x37,0x3f,0x60,0xf, 0x12,0x37, +0xb8,0x12,0xa7,0xae,0x50,0x7, 0x7c,0xb1,0x6c,0x77,0x12,0x39,0x2f,0xb, 0x10,0x7e, +0x3, 0x28,0x84,0xbc,0x1, 0x38,0xe0,0x22,0x74,0x2, 0xac,0xb1,0x9, 0x25,0x26,0xfa, +0x9, 0x35,0x26,0xfb,0x7c,0xb2,0x7c,0x73,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3, +0x1f,0x34,0x22,0x7c,0xa5,0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x12,0x98, +0x50,0x12,0x98,0x67,0x12,0x39,0x6e,0x2, 0x37,0xea,0xca,0x3b,0x12,0x35,0x6f,0x7e, +0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0x48,0x60,0x9, 0xe4,0x7a,0xb3,0x37,0x4a, +0x7a,0xb3,0x36,0xcf,0x7e,0xb3,0x37,0x48,0x70,0x69,0x6c,0x99,0x80,0x5d,0x74,0x2, +0xac,0xb9,0x9, 0x85,0x26,0xfa,0x9, 0xf5,0x26,0xfb,0x7c,0xb9,0x12,0xb9,0x31,0x40, +0x48,0x6c,0xee,0x80,0x3c,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x36,0xd0,0x9, 0xc5,0x36, +0xd1,0xa, 0x28,0xa, 0x3d,0x12,0x38,0x96,0x78,0x25,0xa, 0x2f,0xa, 0x3c,0x12,0x38, +0x96,0x78,0x1c,0x7c,0xb9,0x12,0x38,0x9e,0x7e,0x14,0x62,0x31,0x12,0x3f,0xcd,0x58, +0xe, 0x7c,0xb9,0x6c,0x77,0x12,0x39,0x2f,0x7c,0xb8,0x7c,0x7f,0x12,0x3f,0xd7,0xb, +0xe0,0x7e,0x73,0x37,0x4a,0xbc,0x7e,0x38,0xbc,0xb, 0x90,0x7e,0x73,0x28,0x84,0xbc, +0x79,0x38,0x9b,0x7e,0x73,0x36,0xcf,0x7a,0x73,0x37,0x4a,0xa, 0x37,0x3e,0x34,0xca, +0x39,0x7e,0x18,0x37,0xc, 0x7e,0x8, 0x36,0xd0,0x12,0x20,0xc6,0x1b,0xfd,0xe4,0x7a, +0xb3,0x37,0x48,0xda,0x3b,0x22,0x9d,0x32,0x12,0x21,0x1d,0x4d,0x33,0x22,0x7c,0xab, +0x7e,0x70,0x2, 0xac,0x7a,0x12,0x3f,0xb1,0x2, 0x35,0xb5,0xca,0x79,0x6c,0x88,0x80, +0x70,0x74,0x2, 0xac,0xb8,0x9, 0xf5,0x26,0xfa,0x9, 0x75,0x26,0xfb,0x7a,0x71,0x24, +0x7c,0xbf,0x12,0xa7,0x98,0x50,0x58,0x6c,0xee,0x80,0x4f,0xbc,0xe8,0x68,0x49,0x7e, +0x70,0x2, 0xac,0x7e,0x12,0x9f,0xe8,0x6c,0x99,0x90,0x60,0xaa,0xe4,0x93,0x70,0x18, +0x7e,0xb3,0x2a,0x70,0x14,0xbe,0xb1,0x26,0x78,0xe, 0xa, 0x2f,0xe5,0x25,0xa, 0x3b, +0x12,0x5a,0xe6,0x18,0x3, 0x7e,0x90,0x1, 0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe,0x12, +0x38,0x9e,0x7d,0xf3,0x7c,0xb8,0x12,0x38,0x9e,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe,0x80, +0x2, 0x7c,0xb8,0x6c,0x77,0x12,0x39,0x2f,0xb, 0xe0,0x12,0x5f,0xd9,0x38,0xac,0xb, +0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38,0x88,0xda,0x79,0x22,0x7e,0x70,0x1, 0x7c, +0x67,0x7c,0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e, +0x24,0x0, 0x5e,0x12,0x73,0xff,0x7c,0x7b,0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24, +0x27,0x72,0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, +0x2a,0x2e,0x24,0x27,0x72,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0xca,0xd8, +0xca,0x79,0x7e,0x34,0x62,0x2d,0x12,0x3a,0x19,0x12,0x9f,0xf5,0x50,0x2, 0x41,0x14, +0x7e,0x34,0x62,0x31,0x12,0x23,0xb7,0x7a,0x35,0x2a,0x90,0x62,0x2c,0xe4,0x93,0x70, +0x2, 0x41,0x14,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x7, 0x7e,0x34,0x62,0x2f,0x12,0x3a, +0x19,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x4, 0x4c,0x8, 0x69,0x6c,0xdd,0x80,0x5d,0xc2, +0x0, 0x7c,0xbd,0x12,0x38,0x9e,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xb8, +0x66,0x7a,0x35,0x24,0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x35,0x26,0x3e,0x34,0x3e, +0x34,0x12,0x9f,0x51,0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e, +0x35,0x28,0xbe,0x35,0x24,0x8, 0xa, 0x7e,0x35,0x2a,0xbe,0x35,0x26,0x8, 0x2, 0xd2, +0x0, 0x7c,0xbd,0x12,0xb9,0x31,0x50,0x2, 0xc2,0x0, 0x30,0x0, 0xd, 0x7c,0xbd,0x12, +0x3f,0xba,0xac,0x7d,0x12,0x3f,0xb1,0x12,0x3f,0xd7,0xb, 0xd0,0x7e,0x73,0x28,0x84, +0xbc,0x7d,0x38,0x9b,0xda,0x79,0xda,0xd8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x70, +0x22,0xca,0x3b,0x7e,0x73,0x38,0xf, 0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e,0x33, +0x38,0x11,0xa, 0x13,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x33,0x38,0x10,0xa, 0x93,0x6d, +0x88,0x7e,0x33,0x38,0x12,0xa, 0x73,0x6d,0x66,0x7e,0x14,0x61,0x37,0x7e,0x4, 0x0, +0xff,0xb, 0xa, 0x40,0x12,0x3a,0xe7,0x7a,0x1d,0x26,0x12,0xa7,0x8f,0xb, 0x1a,0x50, +0x7e,0x1d,0x2a,0x7d,0x15,0x12,0x3a,0xe9,0x7a,0x1d,0x2a,0x7f,0x14,0x12,0x3a,0xe7, +0x7f,0x41,0x7f,0x13,0x7d,0x15,0x12,0x1e,0xfc,0x7c,0xf6,0x7c,0xe5,0xa, 0x64,0x12, +0x5b,0xc3,0x50,0x60,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x59,0x75,0x2e,0x0, 0x80,0x4b, +0x7e,0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x76,0x12,0x78,0x64,0x7a,0x35,0x24, +0x7e,0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x78,0x12,0x3d,0x5e,0x7d,0xa3,0x7e, +0x35,0x24,0x6d,0x22,0x7e,0xd, 0x26,0xbf,0x10,0x40,0x17,0x7d,0x5a,0x6d,0x44,0x7e, +0xd, 0x2a,0xbf,0x20,0x40,0xc, 0xbf,0x14,0x38,0x8, 0x7d,0x3a,0x6d,0x22,0xbf,0x13, +0x28,0x7, 0xe5,0x2e,0x6c,0x77,0x12,0x39,0x2f,0x5, 0x2e,0x7e,0x73,0x28,0x84,0xbe, +0x71,0x2e,0x38,0xac,0xda,0x3b,0x22,0x7d,0x14,0x12,0x1e,0xfc,0x7c,0x76,0x7c,0x65, +0xa, 0x24,0x22,0xca,0x79,0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c,0xb4,0x12, +0x96,0xda,0x7d,0x3, 0x7e,0xb3,0x36,0x51,0xb4,0x1, 0x1a,0x74,0x9, 0xac,0xbe,0x9, +0x75,0x28,0xb5,0xbe,0x73,0x36,0x52,0x78,0xc, 0x9, 0x75,0x28,0xb6,0xbe,0x73,0x36, +0x53,0x78,0x2, 0x1e,0x4, 0x74,0x9, 0xac,0xbf,0x12,0x94,0xce,0x12,0x3b,0xb3,0x7d, +0x30,0xad,0x31,0x12,0x3a,0xec,0x7d,0x13,0x5d,0x1e,0x7e,0x70,0x9, 0xac,0x7f,0x49, +0xf3,0x29,0x62,0x74,0x9, 0xac,0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f,0x28,0xf, 0x7d, +0x53,0x2e,0x54,0x29,0x62,0x7d,0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34, +0x29,0x62,0x9d,0xf1,0x1b,0x38,0xf0,0x74,0x9, 0xac,0xbf,0x12,0x3b,0xa7,0x7d,0x30, +0xad,0x31,0x12,0x3a,0xec,0x7d,0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49,0x32, +0x29,0x64,0x74,0x9, 0xac,0xbe,0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d,0x2, +0x2e,0x4, 0x29,0x64,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x29,0x64,0x9d, +0x31,0x1b,0x28,0x30,0xda,0x79,0x22,0x49,0x25,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49, +0x35,0x28,0xb0,0x9d,0x32,0x12,0x21,0x1d,0x7d,0x13,0x22,0x7d,0x41,0x7d,0x2, 0x7c, +0x37,0x7c,0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35,0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74, +0x4, 0xac,0xb3,0x49,0x25,0x2b,0xbf,0x49,0x55,0x2b,0xc1,0x12,0x3b,0xb3,0x7d,0x3f, +0x9d,0x35,0x12,0x21,0x1d,0x9d,0x34,0x12,0x21,0x1d,0x7e,0x54,0x62,0x70,0x7e,0x44, +0x0, 0xff,0xb, 0x2a,0x20,0xbd,0x32,0x50,0xf, 0x12,0x67,0xc9,0x7e,0x14,0x62,0x70, +0x12,0x3f,0xcd,0x50,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xf8,0x6c,0xff,0x7e,0xb7, +0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e,0x97,0x2f,0x84,0x7e,0xd7,0x2f,0x86,0x7e,0xa7, +0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4,0x7e,0x73,0x2f,0xa8,0x1b,0x70,0x7d,0x2b,0x7d, +0x1c,0x12,0x3b,0xbb,0x70,0x2, 0xa1,0x39,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0xa, 0x28, +0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27,0x2f,0xa0,0x7e,0x17,0x2f,0xa2,0x12,0x3b,0xbb, +0x70,0x2, 0xa1,0x39,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0x14,0x28,0x13,0xe4,0x7e,0x70, +0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17,0x2f,0xa6,0x12,0x3b,0xbb,0x70,0x2, 0xa1,0x39, +0x7e,0x34,0x62,0x78,0x12,0x3d,0x3e,0x28,0x4a,0x7e,0x34,0x62,0x76,0x12,0x3d,0x48, +0x50,0x41,0x7e,0xb3,0x2f,0x81,0x70,0x3b,0x7e,0x34,0x62,0x7c,0x12,0x23,0xb7,0x12, +0x3d,0x52,0x7d,0x8f,0x9d,0x83,0xbe,0x87,0x2f,0x82,0x50,0x27,0x7e,0x34,0x62,0x7a, +0x12,0x7f,0x9c,0x9d,0xf8,0xbe,0xf7,0x2f,0x82,0x28,0x18,0x7d,0xfc,0x3e,0xf4,0xbd, +0xfb,0x40,0x2, 0xa1,0x39,0xbd,0xa9,0x50,0x5, 0x7e,0xf0,0x20,0x80,0x7b,0x7e,0xf0, +0x21,0x80,0x76,0x7e,0x34,0x62,0x80,0x12,0x3d,0x48,0x28,0x6d,0x7e,0x34,0x62,0x7e, +0x12,0x3d,0x3e,0x50,0x64,0x7e,0xb3,0x2f,0x81,0x70,0x5e,0x7e,0x34,0x62,0x84,0x12, +0x23,0xb7,0x12,0x3d,0x52,0x7d,0xaf,0x9d,0xa3,0xbe,0xa7,0x2f,0x82,0x50,0x4a,0x7e, +0x34,0x62,0x82,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xa0,0x9d,0xfa,0xbe,0xf7,0x2f,0x82, +0x28,0x37,0x7d,0xfb,0x3e,0xf4,0xbd,0xfc,0x50,0x2f,0xbd,0xed,0x50,0x5, 0x7e,0xf0, +0x22,0x80,0x26,0x12,0x67,0xd0,0x49,0x35,0x2b,0xbb,0x49,0x15,0x2b,0xbd,0x49,0x25, +0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d,0x10,0xbe,0x14,0x0, 0x20,0x18,0x8, 0x9d,0x32, +0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e,0xf0,0x23,0x7c,0xbf,0xda,0xf8,0x22,0x7e,0x24, +0x0, 0xff,0xb, 0x1a,0xf0,0xbd,0xfc,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xbd, +0xfb,0x22,0x7e,0x14,0x62,0x94,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xf0,0x22,0x7d,0xe3, +0x9f,0x11,0x7e,0x14,0x61,0x43,0x12,0x3d,0x56,0x90,0x61,0x35,0xe4,0x93,0x70,0x3, +0x7d,0x3e,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x2a,0x6f,0x80, +0x4, 0x7e,0x83,0x2a,0x70,0x12,0x7f,0xc4,0xbe,0xe4,0x0, 0x3f,0x38,0x1e,0x7e,0x24, +0x0, 0x3f,0x9d,0x2e,0x7e,0x14,0x61,0x47,0x12,0x3e,0x8b,0x12,0x3e,0xa9,0x90,0x61, +0x45,0x12,0x3e,0xa0,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0x12,0xc9,0x9b,0xbe, +0xa0,0x0, 0x28,0x32,0x7d,0x14,0x9e,0x14,0x0, 0x3f,0xbd,0x1e,0x38,0x13,0x12,0x3f, +0x51,0x40,0xe, 0x12,0x3e,0x7d,0x12,0x3e,0x93,0x48,0x32,0x7f,0x10,0x1b,0x1c,0x80, +0x2c,0x12,0x3f,0x51,0x50,0x31,0x7d,0x34,0x9e,0x34,0x0, 0x20,0x12,0x3e,0x83,0x12, +0x3e,0xa9,0x7d,0x1f,0x80,0x1d,0x4c,0xaa,0x78,0x1d,0x12,0x3f,0x4a,0xbd,0x5e,0x38, +0x16,0x12,0x3e,0x7d,0x12,0x3e,0x93,0x48,0x4, 0x7f,0x10,0x1b,0x1c,0xa, 0xb, 0x7d, +0x1f,0x9d,0x10,0x6d,0x0, 0x2f,0x10,0xbe,0xe4,0x0, 0x3f,0x28,0x6f,0x12,0x3f,0x4a, +0xbd,0x5e,0x28,0x68,0x7d,0xd4,0xb, 0xd4,0x1e,0xd4,0x7d,0x5d,0x1b,0x54,0xbd,0x5e, +0x40,0xc, 0x7d,0x35,0x9d,0x3e,0x6d,0x22,0x7e,0x14,0x61,0x4b,0x80,0xa, 0x7d,0x3e, +0x9d,0x3d,0x6d,0x22,0x7e,0x14,0x61,0x4d,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10,0x12, +0x1e,0xfc,0x12,0x3e,0xad,0xbd,0x5e,0x7d,0x1f,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d, +0x0, 0x9f,0x1, 0x7f,0x10,0x80,0x6, 0x1e,0x14,0x6d,0x0, 0x2f,0x10,0x90,0x61,0x45, +0x12,0x3e,0xa0,0x58,0x4, 0x7f,0x10,0x80,0x13,0x90,0x61,0x46,0xe4,0x93,0xa, 0xb, +0x7d,0x1f,0x9d,0x10,0x6d,0x0, 0xbf,0x10,0x8, 0x2, 0x7f,0x10,0x22,0x7d,0x34,0x9e, +0x34,0x0, 0x40,0x7d,0x2e,0x9d,0x23,0x7e,0x14,0x61,0x49,0x7e,0x4, 0x0, 0xff,0xb, +0xa, 0x30,0x22,0xad,0x32,0x6d,0x22,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x90,0x61,0x46, +0xe4,0x93,0xa, 0x1b,0x6d,0x0, 0xbf,0x10,0x22,0xad,0x32,0x6d,0x22,0x7c,0x76,0x7c, +0x65,0x1a,0x24,0x22,0x7e,0x73,0x37,0x52,0x7a,0x73,0x37,0xc8,0x7e,0x27,0x39,0xc0, +0x7e,0x14,0x61,0xce,0x12,0x3e,0x8b,0x1e,0x34,0xbd,0x32,0x50,0x6, 0x74,0x1, 0x7a, +0xb3,0x37,0x52,0x7e,0x14,0x61,0xce,0x12,0x3e,0x8b,0xbd,0x32,0x50,0x8, 0xe4,0x7a, +0xb3,0x37,0x50,0x12,0x3f,0xaa,0x7e,0x37,0x37,0x58,0xbd,0x32,0x50,0x4, 0x7a,0x27, +0x37,0x58,0x12,0xac,0xa3,0x38,0xa, 0x12,0xac,0x9b,0x38,0x5, 0x12,0xac,0x93,0x28, +0x3d,0x12,0xa9,0xd0,0x7e,0x14,0x61,0xce,0x12,0x3e,0x8b,0x1e,0x34,0x1e,0x34,0xbd, +0x32,0x28,0x21,0x7e,0xb3,0x37,0x50,0x4, 0x7a,0xb3,0x37,0x50,0x7e,0x73,0x37,0x50, +0xbe,0x70,0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x37,0x50,0x12,0x9f,0xd1,0x7a,0xb3, +0x37,0xc5,0x80,0x5, 0xe4,0x7a,0xb3,0x37,0x50,0x7d,0x32,0x2, 0xaa,0x52,0x2, 0x3f, +0x41,0x12,0x3f,0xc3,0xe4,0x7a,0xb3,0x37,0x5e,0x22,0x7d,0x54,0x9e,0x54,0x0, 0x3f, +0x22,0x7d,0x4, 0x9e,0x4, 0x0, 0x1f,0x7e,0xd4,0x60,0xd1,0x7e,0xc4,0x0, 0xff,0xb, +0x6a,0x10,0x2d,0x10,0xbd,0x1e,0x22,0x12,0x3e,0xb4,0x2, 0x3f,0x6d,0x7e,0xb3,0x37, +0x52,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0x5a,0x7e,0xb3,0x37,0xc8,0x70,0x3, 0x12, +0xaa,0x27,0x7e,0xb3,0x37,0x5a,0xb4,0x1, 0xc, 0x74,0x3, 0x12,0x3f,0xa1,0x12,0x23, +0xb7,0x3e,0x34,0x80,0x7, 0xe4,0x12,0x3f,0xa1,0x12,0x23,0xb7,0x7a,0x37,0x2a,0x62, +0x22,0x7a,0xb3,0x35,0x96,0x7e,0x34,0x61,0x5d,0x22,0x74,0x2, 0x7a,0xb3,0x37,0x52, +0x22,0x9, 0xb3,0x26,0xfa,0x9, 0x73,0x26,0xfb,0x22,0x6c,0x77,0x12,0x39,0x2f,0x7e, +0x70,0x2, 0x22,0xe4,0x7a,0xb3,0x37,0xc4,0x7a,0xb3,0x37,0xc3,0x22,0x7e,0x4, 0x0, +0xff,0xb, 0xa, 0x20,0xbd,0x32,0x22,0x7c,0x6b,0x7e,0xa3,0x36,0xcf,0x7e,0x50,0x2, +0xac,0x5a,0x19,0x62,0x37,0xc, 0x19,0x72,0x37,0xd, 0x7c,0xba,0x4, 0x7a,0xb3,0x36, +0xcf,0x22,0x12,0xc9,0x82,0xb4,0x1, 0x14,0xca,0x39,0x7e,0x18,0x38,0xc6,0x7e,0x8, +0x25,0xee,0x12,0x20,0xc6,0x1b,0xfd,0x12,0x42,0x8b,0x80,0x12,0xca,0x39,0x7e,0x18, +0x38,0xc6,0x7e,0x8, 0x2b,0x70,0x12,0x20,0xc6,0x1b,0xfd,0x12,0x42,0xa9,0x2, 0x40, +0x21,0x7a,0x1f,0x2a,0xfc,0x7a,0xf, 0x2a,0xf8,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x14, +0x12,0x42,0xa9,0x12,0x40,0x21,0x7e,0x18,0x6, 0x76,0x7a,0x1f,0x6, 0xf4,0x7e,0x18, +0x4, 0x7e,0x80,0x10,0xb4,0x1, 0x11,0x12,0x42,0x8b,0x12,0x40,0x21,0x12,0x6e,0xdc, +0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8,0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12, +0x40,0x2a,0x12,0x40,0x71,0xe4,0x12,0x0, 0x1e,0x74,0x1, 0x12,0x40,0x2a,0x2, 0x40, +0x71,0xca,0x3b,0x7e,0xd3,0x2a,0x73,0x7e,0xc3,0x2a,0x74,0x7e,0x8, 0x1f,0x44,0x12, +0x47,0xfd,0x7e,0x8, 0x1f,0x8a,0x7e,0x34,0x0, 0x46,0x12,0x20,0xeb,0x7e,0x8, 0x1f, +0xd0,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x20,0xeb,0x7e,0x8, 0x1f,0xda,0x7e,0x34,0x0, +0xa, 0x12,0x20,0xeb,0x7e,0xf3,0x2a,0xfc,0x7e,0x18,0x2a,0xdc,0x7a,0x1d,0x24,0x7e, +0x18,0x1f,0xd0,0x7a,0x1d,0x28,0x7c,0xbd,0x7c,0x7c,0x7e,0x8, 0x2a,0xb9,0x12,0x41, +0xc7,0x6c,0xee,0x80,0x2b,0xa, 0x3e,0x9, 0xa3,0x2a,0xdc,0xa, 0x3a,0x2e,0x34,0x20, +0x80,0x12,0x85,0x57,0x7c,0xab,0xbe,0xa0,0x1c,0x50,0x13,0xa, 0x3e,0x12,0x41,0x89, +0xa, 0x4a,0x19,0xb4,0x1f,0x44,0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f,0x8a,0xb, 0xe0, +0xbc,0xce,0x38,0xd1,0x6c,0xee,0x80,0x24,0xa, 0x3e,0x9, 0xa3,0x2a,0xb9,0xbe,0xa0, +0x23,0x50,0x17,0xa, 0x2e,0xa, 0x3c,0x2d,0x32,0x12,0x41,0x89,0xa, 0x4a,0x19,0xb4, +0x1f,0x60,0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f,0xa6,0xb, 0xe0,0xbc,0xde,0x38,0xd8, +0x7e,0xb3,0x2a,0xfd,0x7e,0x8, 0x1f,0xe4,0x60,0x9, 0x7e,0x18,0x1f,0xd0,0x12,0xbd, +0x83,0x80,0x3, 0x12,0xbe,0x9b,0x6c,0xee,0x7e,0x18,0x1f,0xe4,0x7a,0x1f,0x1f,0x34, +0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xd0,0x7a,0x37,0x1f,0x38,0x74,0x2, 0xac,0xbe, +0x49,0x35,0x1f,0xda,0x7a,0x37,0x1f,0x3a,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f, +0x44,0x6d,0x22,0x7a,0x1f,0x1f,0x3c,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1f,0x8a, +0x7a,0x1f,0x1f,0x40,0x7e,0x8, 0x1f,0x34,0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1,0xb, +0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b,0x22,0x2e,0x37,0x2a,0xfe,0x7e,0x39,0xb0, +0x22,0x74,0x1, 0x7a,0xb3,0x37,0xf2,0x12,0xac,0xf5,0x12,0x13,0xf5,0x12,0xbe,0xf, +0xe4,0x12,0xa, 0x66,0x7e,0x24,0x3, 0xd4,0x12,0x48,0x32,0x74,0x1, 0x12,0x40,0x2a, +0x12,0x71,0xc3,0x7e,0x34,0xd0,0xc, 0x12,0x1, 0xe, 0x12,0x40,0x59,0x7e,0x34,0x0, +0x1, 0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80,0x50,0xa, +0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e,0x7b,0x60,0xa, 0x46,0x2e,0x44,0x20,0x80,0x7a, +0x91,0x82,0x7a,0x81,0x83,0xe4,0x93,0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12,0x7e,0xd4, +0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x80,0x15, +0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb, +0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0x70,0xbc, +0x57,0x38,0xac,0x6c,0x77,0x80,0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0x60, +0xbe,0x60,0xd, 0x38,0x11,0x12,0x42,0x84,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e, +0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60,0xe, 0x12,0x42, +0x84,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x6, 0x80, +0x14,0x9e,0x60,0x1c,0x12,0x42,0x84,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d, +0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, 0x70,0xbc, +0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, 0x1, 0x7c,0xb6,0x22,0x7e,0x1f,0x25,0xf2,0x7e, +0xf, 0x25,0xee,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x5, 0x12,0x42,0xa9,0x80,0x6, 0xb4, +0x1, 0x6, 0x12,0x42,0x8b,0x12,0x40,0x21,0x22,0x7e,0x1f,0x2b,0x74,0x7e,0xf, 0x2b, +0x70,0x22,0x12,0xc9,0x82,0xb4,0x1, 0x17,0xca,0x39,0x7e,0x18,0x25,0xee,0x7e,0x8, +0x38,0xc6,0x12,0x20,0xc6,0x1b,0xfd,0x12,0xc9,0x67,0x12,0x42,0x8b,0x80,0x1a,0xca, +0x39,0x7e,0x18,0x2b,0x70,0x7e,0x8, 0x38,0xc6,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x37, +0x2b,0x76,0x7a,0x37,0x32,0xe1,0x12,0x42,0xa9,0x2, 0x40,0x21,0xca,0xf8,0x7c,0x6b, +0xa5,0xbe,0x0, 0x9, 0x7c,0xb7,0x12,0x74,0x24,0xd2,0x8, 0xa1,0x6e,0xa5,0xbe,0x1, +0x3d,0x7a,0x73,0x38,0x87,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, 0xd2, +0x9, 0xa1,0x6e,0xa5,0xbf,0xaa,0x5, 0x12,0xc9,0x70,0x80,0x1e,0xa5,0xbf,0xab,0xa, +0x7e,0x34,0x5, 0x7a,0x7a,0x37,0x32,0xe3,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80,0x2, +0xa1,0x6e,0x7e,0x34,0x4, 0xfc,0x7a,0x37,0x32,0xe3,0x6d,0x33,0x61,0xea,0xbe,0x60, +0x4, 0x40,0x20,0xbe,0x60,0x8, 0x38,0x1b,0x12,0x45,0x71,0xa5,0xbe,0x7, 0x7, 0x6d, +0x33,0x7a,0x35,0xa, 0xa1,0x6e,0xa5,0xbe,0x8, 0x2, 0x80,0x2, 0xa1,0x6e,0x12,0x7, +0xfb,0xa1,0x6e,0xa5,0xbe,0xa, 0x9, 0x43,0xc, 0x20,0x7a,0x73,0x38,0x90,0xa1,0x6e, +0xa5,0xbe,0xb, 0x8, 0x12,0x45,0x71,0x12,0x48,0x6, 0xa1,0x6e,0xbe,0x60,0x1b,0x40, +0x7, 0xbe,0x60,0x1c,0x38,0x2, 0xa1,0x6, 0xbe,0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23, +0x38,0x8, 0x12,0x45,0x73,0x43,0xc, 0x40,0xa1,0x6e,0xbe,0x60,0x15,0x40,0x1a,0xbe, +0x60,0x18,0x38,0x15,0x12,0x45,0x73,0xd2,0x8, 0xa5,0xbe,0x15,0x2, 0x80,0x2, 0xa1, +0x6e,0x74,0x7, 0x7a,0xb3,0x38,0x8a,0xa1,0x6e,0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3, +0x38,0x9f,0xa1,0x6e,0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0xa1,0x6, +0xa5,0xbe,0x2d,0x1b,0x12,0x45,0x73,0x20,0x9, 0x2, 0xa1,0x6e,0x7e,0x63,0x38,0xb2, +0x7c,0x46,0x6c,0x55,0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35,0x8, 0xa1,0x6e,0xbe, +0x60,0x2f,0x40,0xa, 0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, 0xa1,0x6, 0xa5,0xbe, +0x34,0xf, 0x43,0xc, 0x10,0xbe,0x70,0x64,0x38,0x2, 0xa1,0x6, 0x7e,0x70,0x64,0xa1, +0x6, 0xbe,0x60,0x38,0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38, +0xab,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xab,0xa, 0x2f,0x19,0x72,0x2b,0x21,0xa5,0xbe, +0x39,0x2, 0x80,0x2, 0xa1,0x6e,0x75,0x1a,0x38,0xa1,0x6e,0xbe,0x60,0x3a,0x68,0x4, +0xa5,0xbe,0x3b,0x21,0x43,0xc, 0x2, 0x7e,0xf3,0x38,0xad,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xad,0xa, 0x2f,0x19,0x72,0x2b,0x44,0xa5,0xbe,0x3b,0x2, 0x80,0x2, 0xa1,0x6e, +0x75,0x1a,0x3a,0xa1,0x6e,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, 0x7a,0x73,0x2b,0x12, +0xa1,0x6e,0xa5,0xbe,0x50,0x6, 0x7a,0x73,0x38,0xd6,0xa1,0x6e,0xbe,0x60,0x3c,0x68, +0x4, 0xa5,0xbe,0x3d,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xaf,0x7c,0xbf,0x4, 0x7a, +0xb3,0x38,0xaf,0xa, 0x2f,0x19,0x72,0x2a,0x7a,0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0xa1, +0x6e,0x75,0x1a,0x3c,0xa1,0x6e,0xbe,0x60,0x3e,0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43, +0xc, 0x1, 0x7e,0xf3,0x38,0xb1,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xb1,0xa, 0x2f,0x19, +0x72,0x2a,0x9d,0xa5,0xbe,0x3f,0x2, 0x80,0x2, 0xa1,0x6e,0x75,0x1a,0x3e,0xa1,0x6e, +0xbe,0x60,0x40,0x40,0xd, 0xbe,0x60,0x42,0x38,0x8, 0x12,0x45,0x73,0x75,0xd, 0x1, +0x80,0xa, 0xa5,0xbe,0x43,0xb, 0x12,0x45,0x73,0x75,0xd, 0x2, 0x12,0x3f,0xf2,0x80, +0x7d,0xa5,0xbe,0x44,0x8, 0x12,0x45,0x73,0x12,0x42,0xb2,0x80,0x71,0xbe,0x60,0x45, +0x68,0x4, 0xa5,0xbe,0x46,0x5, 0x12,0x45,0x73,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, +0xa5,0xbe,0x4f,0x20,0x43,0xd, 0x4, 0x7e,0xf3,0x38,0xcc,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xcc,0xa, 0x2f,0x2e,0x27,0x32,0xe1,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75, +0x1a,0x4e,0x80,0x3a,0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0, +0x40,0x25,0xbe,0x60,0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7, +0xa5,0xbe,0xf3,0x1a,0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x32,0xe5, +0x2d,0x30,0x1b,0x1a,0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8, +0x22,0xd2,0x8, 0xa, 0x26,0x19,0x72,0x38,0x86,0x22,0xe5,0xd, 0x60,0x56,0xe5,0xd, +0x30,0xe0,0xa, 0x53,0xd, 0xfe,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0xe5,0xd, 0x30, +0xe1,0x14,0x53,0xd, 0xfd,0x7e,0xb3,0x38,0xca,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4, +0x12,0x47,0xf5,0x12,0x74,0xb9,0xe5,0xd, 0x30,0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a, +0xb3,0x38,0xcb,0x7e,0xb3,0x38,0xca,0x70,0xa, 0x74,0x1, 0x12,0x0, 0x1e,0x12,0x42, +0xa9,0x80,0x7, 0xe4,0x12,0x0, 0x1e,0x12,0x42,0x8b,0x12,0x40,0x21,0x7e,0xb3,0x2a, +0xfc,0x2, 0x45,0xd5,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x24,0xf2,0x12,0x47,0xfd, +0x7e,0xa3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x6c,0xee,0x80,0x1d,0xa, 0x2e,0x9, 0x62, +0x2a,0xdc,0xa, 0x26,0x12,0x73,0xfb,0x7c,0x6b,0xbe,0x60,0x1c,0x50,0x9, 0xa, 0x2e, +0x12,0x46,0x4d,0x19,0xb2,0x24,0xf2,0xb, 0xe0,0xbc,0x7e,0x38,0xdf,0x6c,0xee,0x80, +0x1a,0xa, 0x2e,0x9, 0x62,0x2a,0xb9,0xbe,0x60,0x23,0x50,0xd, 0xa, 0x1e,0xa, 0x27, +0x2d,0x21,0x12,0x46,0x4d,0x19,0xb2,0x25,0xe, 0xb, 0xe0,0xbc,0xae,0x38,0xe2,0x6c, +0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x24,0xf2,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e, +0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x2e,0x27,0x2a, +0xfe,0x7e,0x29,0xb0,0xa, 0x26,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, +0x7a,0xb3,0x2a,0xfa,0x12,0x37,0x30,0x7c,0xe7,0x80,0x5d,0x12,0x26,0xb6,0x12,0x47, +0x94,0x30,0x1d,0xfd,0x12,0xc9,0x24,0x12,0x71,0xdc,0x6c,0xdd,0x80,0x3d,0x7e,0x50, +0x2, 0xac,0x5d,0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e, +0x17,0x2a,0xfe,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80, +0x18,0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x41,0x89,0xbe,0xb0,0xff,0x68, +0x8, 0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x47,0xe6,0xa, 0x3d, +0xbd,0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x9b, +0xda,0x79,0xda,0xd8,0x22,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a,0xfa,0x74, +0x1, 0x7a,0xb3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0xc9,0x5f,0x12, +0x37,0x30,0x7e,0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x20,0xeb,0x7e,0xd0,0x7, 0x12,0x26, +0xb6,0x6c,0xcc,0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14, +0x78,0xfb,0x7c,0x67,0x12,0xc9,0x2e,0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x47, +0xe6,0xa, 0x3c,0xbd,0x32,0x48,0xde,0x12,0x47,0x94,0x30,0x1d,0xfd,0x12,0xc9,0x24, +0x7e,0xb3,0x2a,0x73,0x7c,0x7e,0x12,0x71,0xe4,0x6c,0xcc,0x80,0x29,0x74,0x2, 0xac, +0xbc,0x49,0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e,0x34,0x0, 0x1, 0x7c, +0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff,0x12,0xc9,0x2e,0x5c, +0x7b,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x47,0xe6,0xa, 0x3c,0xbd,0x32,0x48,0xce,0x1b, +0xd0,0xbe,0xd0,0x0, 0x58,0x88,0x12,0x46,0x57,0x74,0x2, 0x12,0x47,0xf5,0x12,0x45, +0xd5,0x74,0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x5, +0xb4,0xda,0x3b,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x45,0xd5, +0x74,0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x47,0xb7, +0x7e,0xb3,0x2a,0xfc,0x2, 0xe, 0x94,0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x2a, +0xdc,0x2e,0x34,0x20,0x80,0x12,0x85,0x57,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac, +0x5a,0x7e,0xf, 0x39,0xaa,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x2a, +0x74,0xbc,0x6a,0x38,0xd6,0x22,0x7e,0x73,0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73, +0xa, 0x25,0x2d,0x23,0x22,0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x22,0x7e,0x34,0x0, +0x46,0x74,0x3f,0x2, 0x20,0xeb,0xb2,0x82,0x22,0x12,0xc9,0x70,0x12,0xc9,0x67,0x6d, +0x33,0x7a,0x35,0xa, 0x12,0x48,0x5f,0x12,0x48,0x39,0x74,0x50,0x7a,0xb3,0x38,0xba, +0x7e,0x24,0x3, 0x20,0x12,0x48,0x32,0xe4,0x12,0xc8,0xcb,0x6d,0x33,0x7a,0x37,0x39, +0xee,0x22,0x7d,0x32,0x74,0xfa,0x2, 0x12,0xd0,0x7e,0x73,0x2b,0x62,0x7a,0x73,0x38, +0xb9,0x22,0xa2,0xe, 0xe4,0x33,0x7a,0xb3,0x38,0xb4,0x7e,0x73,0x38,0xb8,0xbe,0x73, +0x2b,0xf, 0x68,0xa, 0xe5,0xc, 0x70,0x6, 0x12,0x48,0x5f,0x12,0x48,0x39,0x22,0x7e, +0x73,0x2b,0xf, 0x7a,0x73,0x38,0xb8,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xa8,0x7e, +0x73,0x2b,0x20,0x7a,0x73,0x38,0xa7,0x7e,0x73,0x2b,0x14,0x7a,0x73,0x38,0xa9,0x22, +0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x61,0xcb,0xe4,0x93,0x7c,0xab,0xbe,0xd0,0x80, +0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff,0x80,0xb, 0x12,0x48,0xf1,0x38,0x4, 0x7c,0xeb, +0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0x80,0x1a,0xbe,0xd0,0x81,0x78,0x15,0x6c, +0xee,0x6c,0xff,0x80,0xb, 0x12,0x48,0xf1,0x40,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0, +0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38,0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0x4f,0x95,0x12, +0x48,0x77,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xa8,0x12,0x49,0xd, 0x7e,0x73,0x2b, +0xf, 0x7a,0x73,0x38,0xb8,0x12,0x48,0x39,0x7a,0xd3,0x38,0x90,0xda,0x79,0xda,0xd8, +0x22,0x7e,0x90,0x5, 0xac,0x9f,0x9, 0xb4,0x26,0x33,0xbc,0xbe,0x22,0x30,0x0, 0x3, +0x12,0x48,0x77,0xa2,0x1, 0x92,0x2, 0x12,0x49,0xda,0x2, 0x49,0xd, 0x7e,0x73,0x2b, +0x20,0x7a,0x73,0x38,0xa7,0x22,0x74,0x40,0x7a,0xb3,0x2b,0x20,0x12,0x67,0x96,0x50, +0x9, 0xd2,0x0, 0xd2,0x1, 0x12,0x48,0xfd,0x80,0x1c,0x74,0x1, 0x12,0x49,0x54,0x7e, +0x43,0x38,0xa5,0x7e,0x50,0x64,0xac,0x45,0x12,0x80,0x48,0x7a,0xb3,0x2b,0x1f,0x7e, +0xf, 0x39,0xc3,0x12,0x4c,0x96,0x12,0x49,0xd, 0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38, +0xa8,0x2, 0x48,0x77,0xca,0x3b,0x7c,0xdb,0xe4,0x7a,0xb3,0x2b,0x14,0x7e,0x8, 0x2a, +0x6d,0x12,0xd, 0x72,0x7e,0xc0,0xa, 0x12,0x4d,0x50,0x30,0xf, 0xfd,0x74,0x1, 0x12, +0x0, 0xe, 0x7e,0x1f,0x39,0xc3,0x12,0x80,0xbc,0x7d,0x73,0xbe,0x74,0xff,0xff,0x78, +0xc, 0x12,0x49,0xd1,0xb, 0xa, 0x30,0x2e,0x34,0x0, 0x3, 0x80,0x1e,0xbe,0x74,0x80, +0x0, 0x28,0xa, 0x12,0x49,0xd1,0xb, 0xa, 0x30,0xb, 0x35,0x80,0xe, 0xbe,0x74,0x40, +0x0, 0x28,0xf, 0x12,0x49,0xd1,0xb, 0xa, 0x30,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0, +0x78,0xb5,0xbe,0xd0,0x1, 0x78,0x9, 0x7e,0x1f,0x39,0xc3,0x12,0x80,0x67,0x7d,0x73, +0x7e,0x1f,0x39,0xb2,0x69,0x31,0x0, 0x1a,0x7a,0x73,0x2b,0x14,0x7d,0x37,0xda,0x3b, +0x22,0x7e,0xf, 0x39,0xb2,0x2e,0x14,0x0, 0x1a,0x22,0xca,0x3b,0x7e,0x34,0xff,0xff, +0x7a,0x35,0x34,0x7e,0xb3,0x38,0x9b,0xf5,0x29,0x7e,0xb3,0x2a,0x6d,0xf5,0x2a,0x7e, +0xb3,0x2a,0x6e,0xf5,0x2b,0x7e,0xb3,0x2a,0x70,0xf5,0x2c,0x7e,0xb3,0x2a,0x6f,0xf5, +0x2d,0x7e,0x34,0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30,0x12, +0x4d,0x49,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x82, +0xff,0x6c,0xff,0x80,0x35,0x12,0x4c,0x5a,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b,0xac, +0x1e,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, +0x1a,0x10,0x12,0x4c,0x61,0xe5,0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x4c,0x70, +0x74,0x2, 0xac,0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xc5, +0x12,0x77,0xbd,0x68,0xe, 0x7e,0x34,0x10,0x0, 0x7e,0xa1,0x2b,0x74,0x2, 0xa4,0x59, +0x35,0x33,0xfe,0x6c,0xff,0x80,0x78,0x12,0x4c,0x5a,0x6c,0xee,0x80,0x14,0x12,0x4d, +0x22,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x13,0x12, +0x4c,0x61,0xe5,0x29,0xbc,0xbe,0x38,0xe6,0xe5,0x29,0x12,0x4c,0x70,0x74,0x4, 0xac, +0xbf,0x59,0x35,0x3, 0x71,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x35,0x12,0x4c,0x5a,0x7e, +0xe1,0x29,0x80,0x14,0x12,0x4d,0x22,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80, +0x14,0x78,0xf4,0x7d,0x13,0x12,0x4c,0x61,0xe5,0x2c,0xbc,0xbe,0x38,0xe6,0xe5,0x29, +0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x4c,0x74,0x80, +0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x3, 0x73,0xb, 0xf0,0xe5, +0x2d,0xbc,0xbf,0x38,0x82,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0xcc,0x12, +0x1f,0x7, 0x6c,0xff,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, 0x5f, +0xad,0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, +0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59,0x25, +0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d,0x0, +0x7e,0x18,0x0, 0x28,0x12,0x1f,0x7, 0x6c,0xff,0x80,0x5c,0x74,0x4, 0xac,0xbf,0x49, +0x25,0x3, 0x71,0xa, 0x1f,0xad,0x13,0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74, +0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, 0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f, +0x74,0x4, 0xac,0xbf,0x59,0x25,0x3, 0x71,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26,0x74, +0x4, 0xac,0xbf,0x49,0x25,0x3, 0x73,0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e, +0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac, +0xbf,0x59,0x25,0x3, 0x73,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73,0x38, +0x9d,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64, +0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0xe3,0x7a,0xe5,0x34,0x7e,0x73,0x38,0x9e,0xa, 0x37, +0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0x63, +0x6c,0xff,0x80,0x20,0x74,0x2, 0xac,0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34,0x28, +0x9, 0x7e,0x35,0x34,0x59,0x35,0x34,0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65, +0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74,0x4, +0xac,0xbf,0x49,0x45,0x3, 0x71,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35, +0x3, 0x71,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x3, 0x71,0x49,0x45,0x3, 0x73, +0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x3, 0x73,0x80,0x8, 0xbd,0x46, +0x50,0x4, 0x59,0x65,0x3, 0x73,0xb, 0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30,0x2, +0x6, 0x7e,0xd, 0x30,0x12,0x4c,0x96,0xda,0x3b,0x22,0x9f,0x11,0x7a,0x1f,0x24,0xf4, +0x22,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x2f,0x10,0x7a,0x1f,0x24,0xf4,0xb, 0xe0,0x22, +0xa, 0x1b,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x12,0x1f,0x7, 0x7a,0x1f,0x24,0xf4,0x7e, +0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d,0x22,0x60,0x5, 0x2f,0x11,0x14,0x78, +0xfb,0xb, 0x14,0x2, 0x1f,0x5, 0x12,0x4c,0xa0,0xb, 0x34,0x7a,0x73,0x2b,0x20,0x22, +0xca,0x79,0x7f,0x10,0x9f,0x0, 0x12,0xc9,0x9b,0x4c,0xaa,0x78,0x6, 0x7e,0x34,0x0, +0x40,0x80,0x6c,0x6c,0x99,0x80,0x38,0xa, 0xe9,0x2e,0xe4,0x60,0xac,0x7d,0x7e,0x7a, +0xf1,0x82,0x7a,0xe1,0x83,0xe4,0x93,0x7c,0x8b,0x90,0x60,0xaa,0xe4,0x93,0x70,0xe, +0x7e,0xf3,0x2a,0x6e,0xac,0xf8,0x7e,0xb3,0x2a,0x70,0xa, 0xfb,0x2d,0xf7,0x7d,0xef, +0x3e,0xe4,0x7f,0x61,0x2d,0xde,0xb, 0x6a,0xd0,0x6d,0xcc,0x2f,0x6, 0xb, 0x90,0xbc, +0xa9,0x38,0xc4,0xbe,0x8, 0x0, 0x0, 0x78,0x2, 0xb, 0xc, 0xa, 0x5a,0x6d,0x44,0x7f, +0x10,0x7f,0x2, 0x12,0x1f,0x7, 0x7f,0x1, 0xb, 0xc, 0x7e,0x34,0xc4,0x0, 0x7e,0x24, +0x0, 0x9, 0x12,0x1f,0x7, 0xbe,0x34,0x0, 0xfa,0x28,0x4, 0x7e,0x34,0x0, 0xfa,0xda, +0x79,0x22,0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x10, +0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24,0xf2,0x74,0x2, 0xac,0xbe, +0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0x7e,0x8, 0x2a,0x6d,0x12,0xd, 0x72, +0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x12,0x13,0x2c,0x2, 0x0, 0x4e,0xb4, +0x3, 0x5, 0x12,0x4d,0x6f,0x80,0x2, 0xe4,0x22,0x12,0x4d,0x54,0x74,0x1, 0x22,0x12, +0x6f,0xf1,0xe4,0x12,0x0, 0xe, 0x7e,0x8, 0x2a,0x6d,0x2, 0xd, 0x72,0x12,0x76,0x61, +0x38,0x2, 0xe4,0x22,0x12,0x76,0x59,0x49,0x55,0x34,0x3b,0xbe,0xb0,0x2, 0x38,0x3, +0x2, 0x75,0xca,0x2, 0x4d,0x5f,0xe4,0x7a,0xb3,0x34,0x3a,0x7a,0xb3,0x34,0x39,0x12, +0x4d,0x7d,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x34,0x3a,0x22, +0xca,0x3b,0x12,0x67,0xf1,0x50,0xfb,0x7e,0xf3,0x2b,0xf, 0x7c,0xbf,0x12,0x85,0xba, +0x12,0xa5,0x3, 0x7e,0xb3,0x2b,0x1f,0xf5,0x28,0x7e,0xc3,0x2b,0x20,0x7e,0xb3,0x37, +0xf2,0xb4,0x1, 0xf, 0x12,0x9d,0xcf,0x7e,0xb3,0x16,0x91,0x70,0x6, 0x12,0x4d,0x96, +0xc3,0xc1,0xac,0x12,0x37,0x30,0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, +0x4, 0x7e,0x12,0x20,0xc6,0x1b,0xfd,0x12,0x37,0x30,0x3e,0x34,0xca,0x39,0x7e,0x18, +0x7, 0x7a,0x7e,0x8, 0x4, 0x0, 0x12,0x20,0xc6,0x1b,0xfd,0x7e,0xb3,0x37,0xf2,0xb4, +0x3, 0x7, 0x12,0xa8,0xd, 0x7a,0x37,0x38,0xcd,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12, +0x66,0x9f,0x12,0xa7,0xfb,0x12,0x4e,0xaf,0xe4,0x12,0x13,0xde,0x12,0x4d,0x96,0x7e, +0x8, 0x4, 0x7e,0x7a,0xd, 0x29,0x7e,0x18,0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0x4f, +0x9, 0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29,0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0, +0x12,0x4f,0x9, 0x7e,0xd3,0x2b,0x1f,0x7e,0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b, +0x1f,0x7a,0xc3,0x2b,0x20,0x7e,0x34,0x8, 0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d, +0x10,0x12,0x76,0x6a,0x7a,0xd3,0x2b,0x1f,0x7a,0xe3,0x2b,0x20,0x7c,0xbf,0x12,0x85, +0x60,0x12,0xa4,0x50,0x7e,0xb3,0x39,0xf1,0x4, 0x7a,0xb3,0x39,0xf1,0x7e,0x73,0x39, +0xf1,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64,0x7a,0xb3,0x39,0xf1,0x7e,0xb3,0x16,0x90, +0x60,0x9, 0x7e,0xb3,0x16,0x91,0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e, +0xa3,0x0, 0x60,0xbe,0xa0,0xff,0x68,0x48,0xbe,0xa3,0x3, 0xfd,0x68,0x42,0x74,0x5, +0xa4,0x12,0x4f,0xf0,0x12,0x4f,0x1, 0x12,0x4f,0xe7,0x12,0x4f,0x1, 0x12,0x4f,0xde, +0x12,0x67,0x96,0x50,0x9, 0x7e,0xb3,0x0, 0x60,0x12,0xa4,0x1b,0x80,0x6, 0x12,0x4f, +0x1, 0x12,0x4f,0xd5,0x12,0x4f,0x61,0x12,0x4f,0xce,0x7e,0x73,0x2b,0x14,0xa, 0x37, +0x7e,0xf, 0x39,0xb2,0x79,0x30,0x0, 0x1a,0x7e,0x73,0x0, 0x60,0x7a,0x73,0x3, 0xfd, +0x22,0x7e,0xa3,0x0, 0x60,0x74,0x5, 0xa4,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40,0x7e, +0xa3,0x2a,0x74,0xa, 0x3a,0x7e,0xa3,0x2a,0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, 0x29, +0x7c,0x7f,0x12,0x71,0x89,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f,0x4, +0x12,0x20,0xc6,0x1b,0xfd,0x7e,0xb3,0x2b,0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80,0x1a, +0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d,0x13, +0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda,0x79, +0x22,0x12,0x4f,0xf9,0x7a,0x37,0x2b,0x1b,0x22,0x7e,0xb, 0x70,0x7a,0x73,0x2b,0xf, +0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62,0x29,0x70,0x0, 0x1, 0x7a,0x73,0x2b,0x14, +0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20,0x12,0x4f,0x61,0x12,0x4f,0xce,0xd2,0x0, +0xc2,0x1, 0x2, 0x48,0xfd,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac,0xbf,0x12,0x4f,0xf0, +0x12,0x4f,0xe7,0x12,0x4f,0xd5,0x12,0x4f,0xde,0x7a,0xf3,0x0, 0x60,0x7c,0xbf,0x12, +0xa4,0x1b,0x12,0x4f,0x61,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x26,0x37,0x12,0xac,0xda, +0x12,0x9e,0x19,0x12,0x23,0x1d,0xe4,0x7a,0xb3,0x16,0x91,0xda,0xf8,0x22,0x7e,0x8, +0x2a,0x6d,0x2, 0x3, 0x8b,0x9, 0x75,0x26,0x35,0x7a,0x73,0x2b,0x1f,0x22,0x9, 0x75, +0x26,0x36,0x7a,0x73,0x2b,0x20,0x22,0x9, 0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22, +0x9, 0x75,0x26,0x33,0x7a,0x73,0x2b,0xf, 0x22,0x7e,0x23,0x2b,0xf, 0x7e,0x33,0x38, +0xb7,0x7e,0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x0, 0xac,0x23,0x2d,0x10, +0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x2b,0x10,0xbe,0x14, +0xf, 0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80, +0x21,0xbe,0x14,0x3, 0x84,0x40,0x16,0x90,0x61,0x1b,0xe4,0x93,0x7c,0x7b,0xbe,0x70, +0x1, 0x28,0x4, 0x74,0x1, 0x80,0xb, 0x7a,0x73,0x2b,0x10,0x80,0x9, 0x90,0x61,0x1b, +0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x7e,0x73,0x2b,0x10,0xbc,0x76,0x68,0x2, 0xd2,0x10, +0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e, +0x10,0x7, 0x7e,0x1f,0x39,0xaa,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x3e,0x4, +0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, +0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x1f,0x58,0xca,0xd8,0xca,0x79,0x7e, +0x73,0x2a,0x6e,0x7e,0xf3,0x2a,0x6d,0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f, +0x34,0xe4,0x12,0x20,0xeb,0x7e,0xb3,0x38,0xa1,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xa2, +0xbe,0x70,0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12,0x26,0xb6,0x12,0x4d,0xb0,0x6d, +0x33,0x80,0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33,0xd, 0xc8,0x12,0x21,0x1d,0x7a, +0x35,0x26,0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26, +0x58,0x7, 0x7e,0x25,0x26,0x59,0x21,0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75, +0x24,0x38,0xd0,0xb, 0xd0,0x7e,0x73,0x38,0xa2,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e, +0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0xd, 0xc8,0x12,0x20,0xc6,0x1b,0xfd, +0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3,0x37,0xef,0xb4,0x1, 0x4, 0xe4,0x2, 0x51,0x31, +0x22,0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0x12,0x64,0xf6,0x12,0x75,0x2f,0x7e, +0xb3,0x37,0xf2,0xb4,0x1, 0x6b,0x12,0xbb,0x59,0x7e,0x34,0x60,0xa5,0x12,0x23,0xb7, +0x12,0x26,0xba,0x12,0x85,0x2, 0x12,0x2d,0x1c,0x12,0x4d,0xb0,0x50,0xde,0x12,0xa7, +0xc8,0x12,0x5f,0x6a,0x7e,0xb3,0x37,0xef,0xb4,0x1, 0x4, 0xe4,0x12,0x51,0x31,0x12, +0x5b,0xa7,0x12,0x56,0xca,0x40,0xc5,0x12,0x9c,0x17,0x12,0x56,0xca,0x40,0xbd,0x12, +0x37,0x25,0x12,0x33,0x78,0x12,0x57,0x4a,0x12,0x3a,0x21,0x12,0x7f,0xf4,0x12,0x89, +0x22,0x12,0x53,0xd2,0x12,0x94,0xc2,0x12,0x56,0xe2,0x12,0x66,0x68,0x12,0xa6,0x9b, +0x12,0xc1,0x3b,0x12,0x51,0xb7,0x12,0x62,0xf7,0x12,0x84,0xc7,0x12,0x62,0xab,0x80, +0x8b,0x12,0xbe,0xf5,0x2, 0x51,0x25,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff,0x12,0x56, +0x74,0x75,0x28,0x3, 0x6c,0xee,0x7e,0x48,0x29,0xbc,0x7e,0xb3,0x2a,0xb, 0x70,0xe, +0x7e,0xb3,0x2a,0x7, 0x70,0x8, 0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0x61,0xa9,0x30,0x12, +0x6, 0x7e,0x68,0x34,0xda,0x80,0x4, 0x7e,0x68,0x34,0x9c,0x7f,0x6, 0x12,0x75,0xb4, +0x7e,0x73,0x2a,0x4, 0x7a,0x6b,0x70,0x6c,0xdd,0x61,0x5a,0x74,0x9, 0xac,0xbd,0x9, +0xc5,0x29,0xc, 0x7c,0xbc,0x54,0xf, 0x12,0x56,0xc0,0xf5,0x28,0x7c,0xbc,0x54,0xf0, +0xbe,0xb0,0x0, 0x28,0x2, 0x61,0x58,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, 0x61,0x58, +0x7e,0x8, 0x0, 0x28,0x7c,0xbc,0x12,0x96,0x86,0x50,0x2, 0x61,0x58,0x74,0x9, 0xac, +0xbd,0x9, 0xb5,0x29,0xd, 0xf5,0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xe, 0xc4, +0x54,0xf0,0xf5,0x26,0x7e,0x73,0x2a,0x4d,0xbc,0x7c,0x28,0x54,0x7e,0xb3,0x2a,0x9, +0x70,0x2a,0x75,0x29,0xf, 0x7e,0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x34,0x88,0x6d, +0x22,0x74,0x1, 0x12,0x78,0x22,0x75,0x29,0x20,0x7e,0x8, 0x0, 0x26,0xa, 0x3c,0x2e, +0x34,0x34,0x92,0x6d,0x22,0x74,0x10,0x12,0x78,0x22,0x80,0xe, 0xa, 0x3c,0x9, 0xb3, +0x34,0x88,0xf5,0x25,0x9, 0xb3,0x34,0x92,0xf5,0x26,0xa, 0x3c,0x12,0x56,0xc2,0xb4, +0x1, 0xe, 0xe4,0xa, 0x3c,0x19,0xb3,0x34,0x88,0x19,0xb3,0x34,0x92,0x12,0x56,0x74, +0x7e,0xb3,0x2a,0x64,0xb4,0xff,0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd,0x9, 0xb5, +0x29,0xc, 0xbe,0xb0,0xff,0x68,0x3, 0x75,0x25,0x1, 0x7e,0x90,0x9, 0xac,0x9d,0x49, +0xb4,0x29,0x8, 0x49,0xa4,0x29,0xa, 0xe5,0x28,0xb4,0x1, 0x2c,0x75,0x27,0x0, 0x80, +0x1d,0x7e,0x71,0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x35,0x1c,0x54,0xf, 0xbc,0xbc, +0x78,0xa, 0x49,0xb3,0x35,0x18,0x49,0xa3,0x35,0x1a,0x80,0xc, 0x5, 0x27,0x90,0x60, +0x99,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd9,0x5e,0xb4,0xf, 0xff,0x5e,0xa4,0xf, 0xff, +0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x2d,0xa5,0xbe,0x70, +0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x24,0xb, 0xf0,0xe5,0x28, +0xa, 0x5b,0x12,0xbd,0xdd,0x2d,0xb5,0x80,0x4, 0x2e,0xb4,0xc0,0x0, 0x7e,0x70,0x6, +0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, 0x2, 0x7f,0x6, 0x2d,0x13,0x79,0xa0, +0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39,0xb0,0x0, 0x6, 0xe5,0x26,0x2d,0x3d, +0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, 0xd0,0x7e,0x73,0x2a,0x4d,0xbc,0x7d, +0x28,0x2, 0x21,0xfb,0xe5,0x24,0x39,0xb6,0x0, 0x1, 0x7e,0xb3,0x38,0x1b,0xb4,0x1, +0x9, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x17,0x80,0xd, 0xbe,0xf0,0x0, 0x38,0x6, 0x7e, +0xb3,0x2a,0x8, 0x60,0xa, 0xb2,0x12,0x12,0x75,0x46,0x74,0x1, 0x12,0x51,0x31,0x7e, +0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x56,0x96,0xe4,0x7a,0xb3,0x2a,0xb, 0x7a, +0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4,0x12,0x51,0x31,0x12,0x92,0xaf, +0xca,0x59,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x35,0x18,0x12,0x20,0xc6,0x1b,0xfd,0x4c, +0xff,0x78,0xc, 0x12,0x6b,0xd9,0x7e,0x8, 0x35,0x18,0x74,0xff,0x12,0x20,0xeb,0xda, +0x3b,0x22,0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x80,0x19,0x7e,0x70,0xff,0x12, +0xc9,0x38,0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19,0xb4,0x1f,0x46,0x19, +0xb4,0x1f,0x50,0xb, 0xa0,0x12,0x56,0x5d,0x38,0xe2,0x7e,0x73,0x2a,0x2, 0xa5,0xbf, +0x0, 0x23,0x7e,0xb3,0x39,0xf7,0x70,0x2, 0xa1,0xe1,0x6c,0xaa,0x80,0x10,0x7e,0x44, +0x7f,0xff,0x12,0xc9,0x42,0x79,0x40,0x0, 0x14,0x12,0x56,0x83,0xb, 0xa0,0x12,0x56, +0x5d,0x38,0xeb,0xa1,0xe1,0x7e,0xb3,0x39,0xf7,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38, +0x6c,0xaa,0x80,0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x28,0xae,0x12,0xc9,0x42, +0x79,0x30,0x0, 0x14,0x49,0x34,0x28,0xb0,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28, +0x74,0x1, 0xa, 0x3a,0x19,0xb3,0x1f,0x34,0x19,0xa4,0x28,0xb2,0xb, 0xa0,0x7e,0xb3, +0x2a,0x2, 0xbc,0xba,0x38,0xce,0xa1,0xe1,0x6c,0xaa,0x80,0x17,0x12,0x56,0x8c,0x3e, +0x34,0x59,0x43,0x15,0x4e,0x59,0x43,0x15,0x50,0x59,0x43,0x15,0x76,0x59,0x43,0x15, +0x78,0xb, 0xa0,0x12,0x56,0x5d,0x38,0xe4,0x6c,0xaa,0x80,0x3d,0x6c,0xff,0x80,0x32, +0x7e,0x70,0x2, 0xac,0x7f,0x7f,0x6, 0x2d,0x13,0x69,0x30,0x0, 0x14,0xbe,0x34,0x7f, +0xff,0x68,0x1d,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x14,0x12,0x56,0x7b,0x59, +0x32,0x15,0x4e,0x69,0x30,0x0, 0x28,0x59,0x32,0x15,0x50,0x12,0xc8,0xea,0x80,0x7, +0xb, 0xf0,0x12,0x56,0x6c,0x38,0xc9,0xb, 0xa0,0x7e,0xb3,0x39,0xf7,0xbc,0xba,0x38, +0xbb,0x6c,0xaa,0x80,0x24,0xa, 0x3a,0x9, 0xb3,0x1f,0x46,0xb4,0xff,0x19,0x6c,0xff, +0x80,0x10,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, 0x12,0xc8,0xea,0x80,0x7, +0xb, 0xf0,0x12,0x56,0x6c,0x38,0xeb,0xb, 0xa0,0x12,0x56,0x5d,0x38,0xd7,0x6c,0xaa, +0x80,0x1a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x28,0xae,0x12,0x56,0x7b,0x59,0x42, +0x15,0x76,0x49,0x33,0x28,0xb0,0x59,0x32,0x15,0x78,0xb, 0xa0,0x7e,0xb3,0x2a,0x2, +0xbc,0xba,0x38,0xde,0x7e,0x34,0x15,0x4e,0x7a,0x37,0x1f,0x40,0x7e,0x34,0x15,0x76, +0x7a,0x37,0x1f,0x42,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x44,0x7e,0x73,0x39,0xf7, +0x7a,0x73,0x1f,0x3e,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x1f,0x3f,0x7e,0x8, 0x1f,0x3e, +0x12,0x4, 0xad,0x6c,0xaa,0x80,0x59,0x7e,0x70,0xff,0x6c,0xff,0x80,0x19,0x7e,0x50, +0x2, 0xac,0x5f,0x49,0x12,0x15,0x9e,0xa, 0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, +0x73,0x1f,0x46,0x80,0x7, 0xb, 0xf0,0x12,0x56,0x6c,0x38,0xe2,0xbe,0x70,0xff,0x68, +0x2d,0x12,0xc9,0x38,0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34,0x7e,0x90,0x9, 0xac, +0x9a,0x49,0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20, +0x0, 0x14,0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12,0x56,0x83,0xb, 0xa0, +0x7e,0x63,0x2a,0x2, 0xbc,0x6a,0x38,0x9f,0x6c,0xaa,0x80,0x20,0xa, 0x3a,0x9, 0xb3, +0x1f,0x34,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x56,0x8c,0x7f,0x6, 0x2d,0x13,0x79,0x40, +0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x12,0x56,0x5d,0x38, +0xdb,0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x39,0xf7,0x6c,0xaa,0x80,0x68,0xa, 0x3a,0x9, +0xb3,0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x56,0x65,0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, +0x74,0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x56,0x65,0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, +0x6, 0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74,0x2, 0x7a,0x1b,0xb0, +0x80,0x27,0x12,0x56,0x65,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14, +0x74,0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1, +0x28,0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x56,0x65,0x7e,0x1b,0xb0,0x39, +0xb1,0x0, 0xa, 0xb, 0xa0,0x12,0x56,0x5d,0x38,0x93,0xda,0xf8,0x22,0x90,0x60,0x99, +0xe4,0x93,0xbc,0xba,0x22,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c,0x22,0x90,0x60,0x99,0xe4, +0x93,0xbc,0xbf,0x22,0x75,0x25,0x0, 0x75,0x26,0x0, 0x22,0x7e,0x50,0x2, 0xac,0x5a, +0x3e,0x24,0x22,0x7f,0x6, 0x2d,0x12,0x79,0x40,0x0, 0x28,0x22,0x7e,0x44,0x7f,0xff, +0x7e,0x70,0x2, 0xac,0x7a,0x22,0x6c,0xaa,0x80,0x20,0x74,0x3, 0x12,0xa3,0xeb,0x7f, +0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, 0x12,0x56,0x8c,0x7f,0x70,0x2d,0xf3,0x79,0x47, +0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x12,0x56,0x5d,0x38,0xdb,0x22, +0xa, 0x3b,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0x22,0xc2,0x0, 0x7e,0xb3,0x16,0x91, +0x60,0x6, 0x7e,0xb3,0x16,0x90,0x70,0x7, 0x12,0x8f,0x74,0x28,0x2, 0xd2,0x0, 0xa2, +0x0, 0x22,0xca,0xf8,0x7e,0xa3,0x2a,0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, +0xbe,0xb0,0x0, 0x28,0x13,0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, +0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x2a,0xb, 0x12,0x92,0xaf,0xca,0x59,0x7e,0x18,0x28, +0xae,0x7e,0x8, 0x29,0x8, 0x12,0x20,0xc6,0x1b,0xfd,0x90,0x61,0x35,0xe4,0x93,0xbe, +0xb0,0x0, 0x28,0x23,0x6c,0xff,0x80,0x1a,0x12,0x94,0xb9,0x12,0x78,0x64,0x74,0x9, +0xac,0xbf,0x59,0x35,0x29,0x8, 0x49,0x35,0x28,0xb0,0x12,0x3d,0x5e,0x12,0xa7,0x4b, +0xb, 0xf0,0x12,0x56,0x6c,0x38,0xe1,0xda,0xf8,0x22,0x2, 0x57,0x4d,0xca,0x3b,0x6c, +0xff,0x7e,0xb3,0x2a,0x6f,0xf5,0x27,0x7e,0xb3,0x2a,0x70,0xf5,0x28,0x75,0x2b,0x0, +0x7e,0xb3,0x16,0x91,0xbe,0xb0,0x1, 0x68,0x11,0x60,0x3, 0x2, 0x58,0x8d,0x7e,0xb3, +0x28,0x84,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x58,0x8d,0x6c,0xee,0x2, 0x58,0x81,0x12, +0xc8,0xdd,0x75,0x25,0x2, 0x75,0x26,0x2, 0x7c,0xbe,0x12,0x5d,0xe2,0xd2,0x0, 0x12, +0xa0,0x93,0x4c,0xdd,0x68,0x7, 0xe5,0x27,0x12,0xc9,0x56,0x48,0x3, 0x75,0x25,0x1, +0x4c,0xcc,0x68,0xc, 0xe5,0x28,0xa, 0x2b,0x1b,0x24,0xa, 0x3c,0xbd,0x32,0x48,0x3, +0x75,0x26,0x1, 0x75,0x24,0x0, 0x80,0x30,0xe5,0x24,0xbc,0xbe,0x68,0x28,0x12,0x8f, +0xf0,0x7a,0xa1,0x29,0x9, 0xb3,0x26,0xfb,0xf5,0x2a,0xa, 0x2a,0xa, 0x3d,0x12,0xc9, +0x4c,0x18,0x13,0xe5,0x2a,0xa, 0x2b,0xa, 0x3c,0x12,0xc9,0x4c,0x18,0x8, 0x75,0x25, +0x1, 0x75,0x26,0x1, 0x80,0x7, 0x5, 0x24,0x12,0x9f,0xc0,0x38,0xcb,0x7c,0xbd,0x7c, +0x7c,0x12,0xa7,0xae,0x50,0x8, 0x12,0x5b,0x79,0x12,0x56,0x74,0x80,0x1b,0x12,0x65, +0x1e,0x50,0x16,0x7e,0x73,0x36,0x52,0xbc,0x7d,0x78,0xe, 0x7e,0x73,0x36,0x53,0xbc, +0x7c,0x78,0x6, 0x75,0x25,0x3, 0x75,0x26,0x3, 0x4c,0xdd,0x78,0x2, 0x80,0x7, 0xe5, +0x27,0x14,0xbc,0xbd,0x78,0xd, 0x12,0x58,0x90,0xb, 0xa, 0x30,0x9e,0x34,0x0, 0x32, +0x1b,0xa, 0x30,0xe5,0x28,0x14,0xbc,0xbc,0x78,0x2, 0x80,0x4, 0x4c,0xcc,0x78,0xd, +0x12,0x58,0x90,0xb, 0xa, 0x30,0x9e,0x34,0x0, 0x3c,0x1b,0xa, 0x30,0xe5,0x25,0x7e, +0x71,0x26,0x7c,0x6e,0x7c,0x5f,0x7e,0x41,0x2b,0x12,0x58,0xa3,0x90,0x61,0x36,0xe4, +0x93,0xb4,0x1, 0x16,0x7e,0x70,0x9, 0xac,0x7e,0x7d,0x13,0x2e,0x14,0x27,0x76,0x6d, +0x0, 0x2e,0x34,0x27,0x78,0x6d,0x22,0x12,0x78,0x13,0x12,0x5b,0x79,0xb, 0xf0,0xb, +0xe0,0x12,0x5f,0xd9,0x28,0x3, 0x2, 0x57,0x7f,0x7a,0xf3,0x28,0x84,0xda,0x3b,0x22, +0x7e,0x73,0x2a,0x6e,0xac,0x7d,0xa, 0x2c,0x2d,0x32,0x3e,0x34,0x7e,0xf, 0x13,0x8a, +0x2d,0x13,0x22,0xca,0x3b,0x7a,0x41,0x2c,0x12,0xb4,0xf0,0x74,0x9, 0xac,0xbf,0x7d, +0x95,0x2e,0x94,0x27,0x76,0x6d,0x88,0x7e,0xe7,0x2a,0x66,0xe4,0x39,0xb4,0x0, 0x6, +0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x26,0xfa,0xf5,0x37,0x9, 0xb3,0x26,0xfb,0xf5, +0x38,0x7e,0x73,0x2a,0x6e,0x7c,0x6d,0x7e,0x8, 0x0, 0x3b,0x12,0x5a,0xff,0xf5,0x39, +0xe5,0x37,0x7e,0x73,0x2a,0x6d,0x7c,0x6c,0x7e,0x8, 0x0, 0x3a,0x12,0x5a,0xff,0x7c, +0xab,0xe5,0x3a,0x7e,0x71,0x3b,0x12,0x5f,0x2c,0x7d,0xf3,0x7a,0xf5,0x43,0x7e,0xf4, +0x15,0x9e,0x7a,0xf5,0x45,0x85,0x3a,0x3d,0x85,0x3b,0x3e,0x7a,0xa1,0x3f,0x85,0x39, +0x40,0x7e,0xb3,0x2a,0x59,0xf5,0x41,0x75,0x42,0x0, 0xe5,0x2c,0xb4,0x1, 0x8, 0xe5, +0x41,0x1e,0xb0,0x1e,0xb0,0xf5,0x41,0x7e,0x8, 0x0, 0x3d,0x12,0x5f,0xf0,0x7d,0x23, +0x6d,0x33,0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x15,0xa2,0x6d,0x22, +0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x2d,0x7e,0x37,0x15, +0xa6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8,0x2f,0x10,0x7a,0x1d,0x31,0x7f,0x65, +0xa, 0x4c,0xe5,0x37,0xa, 0x5b,0x9d,0x54,0xf5,0x35,0x41,0x43,0xa, 0x4d,0xe5,0x38, +0xa, 0x5b,0x9d,0x54,0xf5,0x36,0x41,0x2d,0xe5,0x35,0xbe,0xb0,0x0, 0x58,0x2, 0x41, +0x2b,0x7e,0x73,0x2a,0x6d,0xbe,0x71,0x35,0x18,0x2, 0x41,0x2b,0xe5,0x36,0xbe,0xb0, +0x0, 0x58,0x2, 0x41,0x2b,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x36,0x18,0x2, 0x41,0x2b, +0xe5,0x35,0x7e,0x71,0x36,0x12,0x35,0xb5,0x7e,0x53,0x2a,0x59,0xa, 0x25,0x7d,0xf3, +0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x73,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e,0x34, +0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5,0x37,0xa, 0x2b,0xe5,0x35,0x12, +0x5a,0xe4,0x18,0xb, 0xe5,0x38,0xa, 0x2b,0xe5,0x36,0x12,0x5a,0xe4,0x8, 0x4c,0xe5, +0x35,0x7e,0x71,0x36,0x7c,0x6e,0x12,0xbd,0x29,0xf5,0x3c,0xb4,0x2, 0x6, 0x7d,0x3f, +0xe, 0x34,0x9d,0xf3,0xe5,0x3c,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3c,0xb4,0x1, 0x2b, +0x12,0x5a,0xd3,0xe5,0x35,0x12,0x5a,0xda,0x7e,0x1d,0x2d,0x9f,0x10,0x7a,0x1d,0x2d, +0x12,0x5a,0xd3,0xe5,0x36,0x12,0x5a,0xda,0x7e,0x1d,0x31,0x9f,0x10,0x7a,0x1d,0x31, +0x12,0x5a,0xd3,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61,0x5, 0x36,0xa, 0x2d,0xe5, +0x38,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x36,0x1a,0x3b,0xbd,0x32,0x18,0x2, 0x21, +0x78,0x5, 0x35,0xa, 0x2c,0xe5,0x37,0xa, 0x3b,0x2d,0x32,0x1a,0x37,0xe5,0x35,0x1a, +0xfb,0xbd,0xf3,0x18,0x2, 0x21,0x6c,0xbe,0x58,0x0, 0x0, 0x78,0x2, 0xb, 0x5c,0xbe, +0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2d,0x7f,0x5, 0x12,0x5a,0xf0,0x1b, +0x4a,0x30,0x7e,0x1d,0x31,0x7f,0x6, 0x12,0x5a,0xf0,0x79,0x34,0x0, 0x2, 0x7e,0xb3, +0x2a,0x65,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80,0x0, 0x14,0x78, +0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d,0x39,0x74,0x0, +0x5, 0x74,0x9, 0xac,0xbe,0x9, 0x75,0x27,0x7c,0x39,0x74,0x0, 0x6, 0xbe,0x70,0xf, +0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0x7e,0xa1,0x37,0x7e,0x70,0x9, 0xac,0x7f, +0x19,0xa3,0x27,0x7d,0x7e,0xa1,0x38,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x27,0x7e, +0xda,0x3b,0x22,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x22,0x1a,0x1b,0x1a,0x2, 0x12,0x1e, +0xeb,0x7f,0x1, 0x22,0x1a,0x3b,0x9d,0x32,0x12,0x21,0x1d,0xbe,0x34,0x0, 0x1, 0x22, +0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0x12,0x1f,0x7, 0x2e,0x18,0x0, 0x20,0x22,0xca, +0xf8,0x7c,0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c, +0xb7,0xbc,0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd, +0x3f,0x18,0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, +0x5f,0x2d,0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53, +0xa, 0x39,0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda, +0xf8,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e,0xe3,0x2a,0x6f,0x7e,0xd3,0x2a,0x70, +0x6c,0xcc,0x80,0xe, 0x7c,0x7c,0xac,0x7f,0x12,0x58,0x9a,0x7c,0xbd,0x12,0xa0,0xdd, +0xb, 0xc0,0xbc,0xec,0x38,0xee,0xda,0x3b,0x22,0x12,0xa0,0xd5,0x60,0x28,0x6c,0x22, +0x80,0x1c,0x7c,0xb2,0x12,0x5e,0xf0,0x50,0x13,0x7c,0xb2,0x12,0x5d,0xc5,0x7d,0x3, +0x12,0xa0,0xcd,0x49,0x55,0x39,0xd2,0x7d,0x40,0x12,0xc9,0x3, 0xb, 0x20,0x7e,0x73, +0x2a,0x75,0xbc,0x72,0x38,0xdc,0x22,0x12,0x5b,0xdc,0x12,0x5b,0xc0,0x12,0x5b,0xcb, +0x90,0x60,0xa7,0xe4,0x93,0x60,0x8, 0x30,0x16,0x5, 0x12,0x5b,0x79,0xc2,0x16,0x22, +0x2, 0x5b,0xc3,0x7e,0x73,0x2a,0x6b,0x2e,0x70,0xff,0x22,0x12,0x5b,0xc3,0x40,0xb, +0x12,0x24,0x2d,0xe4,0x7a,0xb3,0x3, 0xfe,0x2, 0x5b,0xe2,0x22,0x12,0x5d,0xb6,0x2, +0x5b,0xe2,0xe4,0x7a,0xb3,0x28,0x93,0x12,0xbf,0x80,0x7e,0xb3,0x16,0x91,0xb4,0x1, +0x8, 0x7e,0x73,0x28,0x84,0x7a,0x73,0x28,0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, +0xf8,0x12,0x6e,0xdc,0x12,0x5c,0x2a,0x12,0x6c,0x37,0x7e,0xb3,0x16,0x90,0xb4,0x1, +0x18,0x7e,0x73,0x26,0x83,0x7a,0x73,0x26,0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26, +0xf5,0x7e,0x73,0x26,0x84,0x7a,0x73,0x26,0xf4,0x22,0x7e,0x8, 0x26,0x86,0x7e,0x34, +0x0, 0x3, 0xe4,0x12,0x20,0xeb,0x7e,0x8, 0x26,0x89,0x7e,0x34,0x0, 0x3, 0x12,0x20, +0xeb,0x7a,0xb3,0x26,0x83,0x7a,0xb3,0x26,0x84,0x7a,0xb3,0x26,0x85,0x7a,0xb3,0x26, +0xf0,0x7a,0xb3,0x26,0xf1,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0x6f,0x12,0x5d,0x8d, +0x6c,0x55,0x12,0x5c,0xf0,0x7a,0xb3,0x26,0x85,0x7e,0x18,0x26,0x5b,0x12,0x5d,0x9d, +0x6c,0x55,0x12,0x5c,0xf0,0x7a,0xb3,0x26,0x84,0x6c,0x77,0x80,0x14,0x12,0x5d,0x79, +0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12,0x37,0xd3,0x2e,0x24,0x26,0x86,0x12,0x5d, +0x82,0x7e,0x63,0x26,0x84,0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0x5d,0x79, +0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12,0x37,0xd3,0x2e,0x24,0x26,0x89,0x12,0x5d, +0x82,0x7e,0xa3,0x26,0x85,0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x26,0x84,0xa4,0x7a,0xb3, +0x26,0x83,0x7e,0x18,0x26,0xe6,0x12,0x5d,0x8d,0x7e,0x50,0x1, 0x12,0x5c,0xf0,0x7a, +0xb3,0x26,0xf2,0x7e,0x18,0x26,0xdc,0x12,0x5d,0x9d,0x7e,0x50,0x1, 0x12,0x5c,0xf0, +0x7c,0xab,0x7a,0xa3,0x26,0xf1,0x7e,0xb3,0x26,0xf2,0xa4,0x7a,0xb3,0x26,0xf0,0x22, +0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff,0x80,0x70,0x7e,0xd0, +0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4, +0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0, +0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, +0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c, +0x55,0x68,0xc, 0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd, +0x4e,0x58,0x19,0xbd,0xfe,0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b, +0xf0,0xb, 0xa0,0x90,0x60,0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, 0xb, 0xf0,0xbc,0x4f, +0x38,0x8c,0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0xb7,0x54,0x7, 0x7e,0x24,0x0, +0x1, 0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70,0x22,0x7a,0x1d,0x24, +0x7e,0xf, 0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a,0x53,0x22,0x7a,0x1d,0x24, +0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0xf8,0x2d,0x15,0x7e,0xb3,0x2a, +0x6d,0x7e,0x37,0x2a,0x51,0x22,0x12,0x25,0xe5,0x2, 0x5d,0xbc,0x12,0x5b,0xc3,0x50, +0x3, 0x2, 0x26,0xd, 0x22,0x7c,0x5b,0x7e,0x43,0x2a,0x6e,0x90,0x60,0xab,0xe4,0x93, +0x7c,0xab,0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7c,0x75,0xac,0x74,0xa, 0x2a,0x2d, +0x32,0x22,0xca,0x3b,0x7c,0x5b,0x7e,0x43,0x28,0x84,0xbe,0x40,0x1, 0x28,0x2, 0xc1, +0xdd,0x7e,0xa3,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x75,0x9, 0xd3,0x26,0xfa,0x9, 0xc3, +0x26,0xfb,0x7c,0xbd,0x7c,0x7c,0x12,0x5f,0x2c,0x7f,0x1, 0x90,0x60,0xaa,0xe4,0x93, +0x70,0x12,0x7c,0xfc,0x7c,0x9d,0x7e,0x83,0x2a,0x70,0x7e,0xe3,0x2a,0x6f,0xa, 0xca, +0x6d,0xbb,0x9d,0xbc,0xa, 0xa8,0x1b,0xa5,0xa, 0x5f,0xbd,0x5a,0x58,0x2, 0xc1,0xdd, +0xa, 0x59,0x1b,0x54,0xbe,0x54,0x0, 0x0, 0x48,0x4e,0x7c,0xb9,0x14,0x12,0x5e,0xf0, +0x50,0x46,0x7c,0xb9,0x14,0x12,0x5e,0xe0,0xb, 0x1a,0xe0,0x7d,0x3b,0x12,0x5f,0x1a, +0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a, +0x12,0x5f,0x12,0x7c,0xb8,0x24,0xfe,0xbc,0xbf,0x78,0x1d,0x90,0x60,0xaa,0xe4,0x93, +0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f,0x12,0x5e,0xe7,0xb, 0x1a,0x30,0xbd,0x3a, +0x8, 0x6, 0x12,0x5e,0xe9,0x1b,0x1a,0xa0,0xa, 0xa9,0xb, 0xa4,0xa, 0x5e,0xbd,0xa5, +0x58,0x4b,0x7c,0xb9,0x4, 0x12,0x5e,0xf0,0x50,0x43,0x7c,0xb9,0x4, 0x12,0x5e,0xe0, +0xb, 0x1a,0xe0,0x7d,0x3c,0x12,0x5f,0x1a,0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, +0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a,0x12,0x5f,0x12,0x7c,0xb8,0x24,0xfe,0xbc, +0xbf,0x78,0x1a,0x90,0x60,0xaa,0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f, +0x12,0x5e,0xe7,0xb, 0x1a,0x50,0xbd,0x5a,0x8, 0x3, 0x1b,0x1a,0xa0,0xda,0x3b,0x22, +0x12,0x5d,0xc5,0x7d,0xd3,0x7d,0x5d,0x3e,0x54,0x7e,0x1f,0x13,0x8a,0x2d,0x35,0x22, +0x7c,0xab,0x6c,0x77,0x80,0x11,0xa, 0x27,0x2e,0x24,0x60,0xac,0x12,0x73,0xff,0xbc, +0xba,0x78,0x2, 0xd3,0x22,0xb, 0x70,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xb7,0x38,0xe6, +0xc3,0x22,0x2d,0x31,0x7d,0x20,0x1b,0x1a,0x50,0x22,0x3e,0x34,0x7f,0x40,0x2d,0x93, +0xb, 0x4a,0xa0,0xbe,0xe4,0x0, 0x0, 0x22,0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x2a,0x6e, +0xac,0x1b,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10,0x7e,0x1f,0x13,0x8a,0x2d, +0x31,0x22,0xc2,0x0, 0x12,0x7f,0xb4,0x68,0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17, +0x7e,0xb3,0x37,0x5a,0x70,0x11,0x12,0x5b,0xc3,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe, +0x34,0x1, 0x90,0x58,0x2, 0xd2,0x0, 0xa2,0x0, 0x22,0x7e,0x37,0x2a,0x4f,0x1e,0x34, +0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, 0x12,0x5f,0xac,0x7e,0x37, +0x28,0x99,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a,0x7e,0x18,0x4, 0x7e,0x12, +0x5f,0xac,0x12,0x5b,0x52,0x12,0xa0,0x1b,0x2, 0x5f,0x9b,0xe4,0x7a,0xb3,0x3, 0xff, +0x7e,0xb3,0x28,0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xff,0x22,0xca,0x3b,0x7f,0x31, +0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24,0x7f,0x13,0x12,0x82, +0x45,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x5f,0xe8,0x7e,0xd, 0x24,0x2d,0x15,0x7f, +0x13,0x2d,0x35,0x12,0x83,0xf, 0xda,0x3b,0x22,0x7e,0x73,0x28,0x84,0xbc,0x7e,0x22, +0x12,0x5b,0xc3,0xd2,0x1a,0x2, 0x33,0x6e,0x7e,0xa3,0x2a,0x74,0x74,0x2, 0xa4,0x22, +0x12,0xc, 0x29,0x7e,0x37,0x15,0x9e,0x22,0x7e,0x8, 0x2b,0xb7,0x2, 0x62,0xe2,0xff, +0x70,0x8f,0x0, 0xff,0x3b,0xc4,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x31,0x36,0x32,0x1, 0xd2,0x0, 0x31,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xa, 0xf5,0x44,0x32,0x5f,0x42,0x69,0x65,0x6c,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0xf, 0xe, 0xd, +0xc, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0xb, 0xa, 0x9, 0x8, 0x18,0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x6, 0xb, 0x0, +0x0, 0x0, 0x64,0x0, 0xfa,0x1, 0x2c,0x2, 0xbc,0x2, 0xee,0x4, 0x1a,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x1e,0x1, 0xf4,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x0, 0x4, 0x3e,0x28,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x5a,0x40,0xe, 0x19,0x27,0x13,0xd, 0x6, 0x80,0x13,0xd, 0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x46,0x45,0x2, 0x4e,0x2, 0x4e,0x1, +0x38,0x1, 0x3b,0x7, 0x80,0x46,0x48,0x2, 0xe, 0x2, 0xe, 0x1, 0x43,0x1, 0x43,0x0, +0xa0,0x0, 0x8c,0x0, 0x8c,0x0, 0xc8,0x0, 0x64,0x0, 0xb4,0x0, 0xb4,0xa, 0x0, 0x0, +0xdc,0x6, 0xa, 0x14,0x28,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0xa, 0x1, 0x3b,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x3, 0x3e,0x5a,0x28, +0x24,0x3, 0x41,0x5c,0x28,0x2b,0x3, 0x43,0x5d,0x28,0x33,0x3, 0x47,0x5f,0x28,0x1e, +0x3, 0x3e,0x5a,0x28,0x1e,0x3, 0x3e,0x5a,0x28,0x1e,0x3, 0x3e,0x5a,0x28,0x1e,0x3, +0x3e,0x5a,0x28,0x4, 0x5, 0xd, 0xe, 0xf, 0x10,0x11,0x4, 0x0, 0x96,0x1, 0x90,0x28, +0x1, 0x2c,0x1, 0x5e,0x0, 0xc8,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, 0x90, +0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, 0x50, +0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x8, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x32,0x1, 0xf4,0x1, 0xf4,0x2, 0x58,0x0, 0xc8, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0x7e,0x8, 0x38,0xdd,0x12, +0x62,0xe2,0x7e,0x8, 0x38,0xe5,0x12,0x62,0xe2,0x12,0x5f,0xf8,0x12,0x63,0xd, 0x2, +0x62,0xc2,0x7e,0x37,0x38,0xdd,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x7e,0x73,0x39,0xf1, +0xbe,0x70,0x5, 0x50,0xc, 0x7e,0xb3,0x38,0x1b,0x70,0x6, 0x12,0x63,0x14,0x12,0x64, +0xef,0x22,0xb, 0xa, 0x30,0xe5,0x5f,0xa, 0x2b,0xbd,0x32,0x28,0x4, 0x9d,0x32,0x80, +0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x73,0x28,0x93,0x7a,0x73,0x28,0x94,0x7e, +0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, 0xe4,0x7a,0xb3,0x2a,0x6, 0x22,0x7e,0x8, 0x39, +0xd0,0x2, 0x62,0xe2,0x6d,0x33,0x7a,0x37,0x39,0x6d,0x22,0xca,0xf8,0x7e,0xa3,0x2a, +0x2, 0x7e,0xb3,0x2a,0x3, 0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0,0x1, 0x38,0x1c,0x7e, +0x47,0x28,0x86,0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x2f,0x80,0x4c, +0xff,0x68,0x17,0x7e,0x47,0x2b,0xb7,0x4d,0x44,0x78,0xf, 0x12,0x63,0x14,0x74,0x1, +0x7a,0xb3,0x39,0x6f,0x7a,0xb3,0x37,0xf0,0x80,0x35,0x4c,0xaa,0x78,0x36,0xb4,0x1, +0x33,0x7e,0x37,0x2b,0xb7,0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f,0x80,0xb4,0x3, 0x1f, +0x7e,0x37,0x2b,0xb7,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a,0xb3,0x2f,0x80, +0x7e,0x37,0x2f,0x98,0x7e,0x27,0x2f,0x9a,0x12,0x64,0x2c,0x81,0x25,0x80,0x0, 0x12, +0xc3,0x7c,0x81,0x25,0x7e,0xc7,0x29,0x8, 0x7e,0xd7,0x29,0xa, 0x4c,0xff,0x78,0x19, +0x70,0x57,0xbe,0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12,0xc3,0x17,0x12,0x64, +0x28,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x40,0xbe,0xf0,0x1, 0x78,0x2e,0x7e,0x27, +0x2f,0x88,0x9e,0x27,0x2f,0x90,0x7e,0x14,0x62,0x90,0x12,0x3e,0x8b,0xbd,0x23,0x38, +0x13,0x7e,0x27,0x2f,0x96,0x9e,0x27,0x2f,0x8e,0x7e,0x14,0x62,0x92,0x12,0x3e,0x8b, +0xbd,0x23,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, 0xbe,0xf0,0x3, 0x78, +0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f,0x80,0x60,0x26,0x7d, +0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12,0x64,0xd7,0xa, 0x2b, +0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x64,0x28,0x7a,0xc7,0x2b, +0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42,0x7d,0x13, +0x7d,0x24,0x12,0x66,0xbc,0x7d,0x31,0x12,0x87,0x6a,0x2, 0x64,0x3d,0x7e,0x3, 0x2f, +0xa8,0xbe,0x0, 0xf0,0x50,0x2, 0x81,0xd6,0x81,0xcb,0x6c,0x99,0x7e,0xb3,0x2f,0x7f, +0xbe,0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f,0x2b,0xbf,0x7a,0x1f, +0x1f,0x34,0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2b,0xbf,0x49, +0x25,0x2b,0xc1,0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12,0x64,0xd7,0x7c,0x1b, +0x7e,0x3, 0x2f,0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70,0x4, 0xac,0x78,0x2e, +0x34,0x2b,0xbf,0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1f,0x8c,0x7e,0x34,0x1f,0x34, +0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12,0x1f,0x8c,0xb, 0x80, +0x7e,0x3, 0x2f,0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54,0x7c,0xb, 0x7a,0x3, +0x2f,0xa8,0x7e,0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xb, 0x7e,0x3, 0x2f,0xa8,0xbe, +0x0, 0xec,0x40,0x2, 0x81,0x4a,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x21,0x1d, +0x7c,0xa7,0x12,0x67,0xc9,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22,0x74, +0x1, 0x7a,0xb3,0x37,0xf0,0x22,0x12,0xc8,0xc9,0x12,0x63,0x14,0x7a,0x37,0x39,0xee, +0x12,0x66,0x98,0x12,0x4d,0x96,0x2, 0x65,0x9, 0x7e,0x70,0xa, 0x12,0x65,0x1e,0x50, +0x3, 0x7e,0x70,0x19,0x7a,0x73,0x35,0x72,0xe4,0x7a,0xb3,0x35,0x73,0x22,0xa2,0xa, +0x22,0xca,0x79,0x7e,0xa3,0x2a,0x2, 0x7e,0x8, 0x29,0xbc,0x7e,0x90,0xa, 0x12,0x65, +0x1e,0x50,0x3, 0x7e,0x90,0x19,0x4c,0xaa,0x78,0x5, 0x12,0x65,0x9, 0xc1,0x53,0x6c, +0x88,0xc1,0x48,0x7e,0x70,0x9, 0xac,0x78,0x9, 0xf3,0x29,0xc, 0xbe,0xf0,0xff,0x78, +0x2, 0xc1,0x46,0xa, 0x2f,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0xe0,0xbe,0xe0,0x2, 0x68, +0x2, 0xc1,0x29,0x7e,0x50,0x4, 0xac,0x5f,0x49,0x22,0x36,0x27,0x49,0x33,0x29,0x8, +0x12,0x67,0xd8,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x23,0x36,0x29,0x12,0x66,0x5e,0x9d, +0x32,0x12,0x21,0x1d,0x7d,0xe3,0x7e,0xb3,0x35,0x72,0xa, 0x3b,0xbd,0x3f,0x28,0x54, +0xbd,0x3e,0x28,0x50,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x36,0x27,0x7e,0x50,0x9, +0xac,0x58,0x59,0x32,0x29,0x8, 0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x36,0x29,0x7e, +0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0xa, 0xbe,0xa0,0x0, 0x28,0x2, 0x1b,0xa0,0x4c, +0xaa,0x68,0x2, 0xc1,0x46,0x7e,0xb3,0x35,0x73,0x4, 0x7a,0xb3,0x35,0x73,0xbe,0xb0, +0x32,0x40,0x73,0xe4,0x7a,0xb3,0x35,0x73,0x12,0x66,0x56,0x50,0x69,0x4, 0x7a,0xb3, +0x35,0x72,0x80,0x62,0x7e,0x70,0x9, 0xac,0x78,0x49,0xd3,0x29,0x8, 0x7e,0x50,0x4, +0xac,0x5f,0x59,0xd2,0x36,0x27,0x49,0x33,0x29,0xa, 0x59,0x32,0x36,0x29,0x12,0x65, +0x1e,0x50,0x7, 0x12,0x66,0x56,0x28,0x1a,0x80,0x13,0x7e,0x73,0x35,0x72,0xbc,0x79, +0x40,0x4, 0x74,0x2, 0x80,0x8, 0xbe,0x70,0x1, 0x28,0x7, 0x7c,0xb7,0x14,0x7a,0xb3, +0x35,0x72,0xe4,0x7a,0xb3,0x35,0x73,0x80,0x1d,0x4c,0xee,0x78,0x19,0x7e,0x70,0x9, +0xac,0x78,0x49,0x33,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x5f,0x59,0x32,0x36,0x27,0x12, +0x66,0x5e,0x59,0x32,0x36,0x29,0xb, 0x80,0x90,0x60,0x99,0xe4,0x93,0xbc,0xb8,0x28, +0x2, 0xa1,0x43,0xda,0x79,0x22,0x7e,0xb3,0x35,0x72,0xbe,0xb0,0x2, 0x22,0x7e,0x70, +0x9, 0xac,0x78,0x49,0x33,0x29,0xa, 0x22,0x12,0x65,0x21,0x2, 0x66,0x6e,0x7e,0xb3, +0x2a,0x9, 0x70,0x23,0x7e,0xb3,0x35,0x8a,0xb4,0x2, 0x9, 0x12,0x67,0xe0,0x28,0x4, +0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x35,0x95,0x7e,0x73,0x35,0x96,0xbe,0x73,0x35, +0x95,0x28,0x4, 0x7a,0x73,0x35,0x95,0x22,0x7e,0x34,0xd, 0xac,0x12,0x26,0xba,0x12, +0x70,0xd3,0x12,0x66,0xdd,0x2, 0x66,0xa8,0x30,0x13,0x10,0x12,0x67,0x96,0x50,0x3, +0x12,0xb0,0x22,0x12,0x6f,0x61,0x12,0x67,0x3, 0xc2,0x13,0x22,0x7e,0xa3,0x2f,0xa8, +0xbe,0xa0,0xf0,0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0x67,0xd0,0x59, +0x25,0x2b,0xc1,0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e,0xb3,0x2b, +0x1e,0x70,0x1f,0x12,0x26,0xb6,0x12,0x67,0xf1,0x50,0xfb,0x12,0x6f,0x61,0x12,0x67, +0x82,0x20,0x13,0x3, 0x12,0x67,0x3, 0x74,0x2, 0x7a,0xb3,0x2b,0x1e,0xe4,0x7a,0xb3, +0x16,0x91,0x22,0xca,0x3b,0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e,0xf3,0x2b, +0x62,0x12,0x67,0xab,0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12,0x67,0xe8, +0xf5,0x29,0x7e,0x73,0x2b,0xf, 0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, 0xac,0x7d, +0xa, 0x2c,0x12,0x85,0x51,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14, +0x2, 0xe0,0xad,0x10,0x2e,0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x1d, +0xac,0x7e,0x2e,0x34,0x38,0x2e,0x6d,0x22,0x7a,0x1f,0x38,0x2a,0x7c,0xbc,0x12,0xa2, +0xa9,0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f,0x68,0x6, +0x7a,0xf3,0x2b,0x62,0xd2,0x10,0xd2,0x0, 0x7e,0xb3,0x1f,0x33,0x12,0x9d,0xd, 0xda, +0x3b,0x22,0x12,0x67,0x96,0x50,0x3, 0xd2,0x13,0x22,0xc2,0x13,0x22,0x12,0xa8,0xd7, +0x12,0xa4,0x92,0x2, 0x67,0x82,0x7e,0xb3,0x37,0xf2,0xb4,0x3, 0x8, 0x7e,0xb3,0x38, +0x9c,0x70,0x2, 0xc3,0x22,0xd3,0x22,0x7e,0xb3,0x2b,0xf, 0x7c,0xab,0x6c,0x77,0x7e, +0x50,0x5, 0xac,0x57,0x9, 0x62,0x26,0x33,0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22,0xb, +0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0x7d,0x31,0x9d,0x30,0x2, 0x21,0x1d, +0x7e,0xa3,0x2f,0xa8,0x74,0x4, 0xa4,0x22,0x9d,0x32,0x12,0x21,0x1d,0x7d,0xf3,0x22, +0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, 0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33, +0x22,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x7e,0x37,0x33,0xeb, +0xb, 0x34,0x7a,0x37,0x33,0xeb,0x7e,0x37,0x33,0xed,0xbe,0x37,0x33,0xeb,0x28,0x3, +0x2, 0x68,0x14,0x22,0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0x2, 0x67, +0xfc,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0, +0xd0,0xc0,0x83,0xc0,0x82,0x12,0x68,0x1e,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, +0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7e,0x34,0x0, +0x4, 0xca,0x39,0x7e,0x34,0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x70,0x12, +0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x2a,0xe, 0x7a,0x37,0x2b,0x76,0xe4,0x7a,0xb3,0x2b, +0x74,0x7a,0xb3,0x2b,0x75,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x6e,0xd0,0x7e,0x8, +0x25,0xee,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x2b,0x78,0x7a,0x37,0x25,0xf4,0xe4, +0x7a,0xb3,0x25,0xf2,0x74,0x1, 0x7a,0xb3,0x25,0xf3,0x22,0xca,0xd8,0xca,0x79,0x90, +0x60,0x50,0xe4,0x93,0x7c,0xdb,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e,0x73,0x2a, +0x74,0xbc,0x7e,0x28,0x4, 0x7c,0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3,0x2a,0x6d,0x7a, +0xe3,0x2a,0x6e,0x7a,0xd3,0x2a,0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xd3,0x2a,0x73,0x7a, +0xe3,0x2a,0x74,0x90,0x60,0xa8,0xe4,0x93,0x7c,0xab,0x7a,0xa3,0x2a,0x77,0x90,0x60, +0xa9,0xe4,0x93,0xa, 0x2b,0xa, 0x3d,0x9d,0x32,0x7c,0xb7,0x7a,0xb3,0x2a,0x6f,0xa, +0x2a,0xa, 0x3e,0x9d,0x32,0x7a,0x73,0x2a,0x70,0x90,0x60,0x91,0xe4,0x93,0x7a,0xb3, +0x2a,0x78,0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x2a,0x79,0xa, 0x3d,0xca,0x39,0x7e, +0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x7a,0x12,0x20,0xc6,0x1b,0xfd, +0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x9d, +0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e,0x34,0x60,0xd8,0x7e, +0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x21,0x12,0x20,0xc6,0x1b,0xfd,0x12,0x6a,0x86,0x12, +0x6f,0xfa,0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7a,0xd3,0x2a,0x75,0x7a,0xe3,0x2a, +0x76,0x12,0x68,0x4d,0x74,0x1, 0x12,0x40,0x2a,0xe4,0x7a,0xb3,0x2b,0x1, 0x7a,0xb3, +0x2b,0x2, 0x12,0x6b,0xe5,0x7a,0x37,0x2b,0xd, 0x74,0x3, 0x7a,0xb3,0x2b,0x3, 0xe4, +0x7a,0xb3,0x2b,0x4, 0x74,0x2, 0x7a,0xb3,0x2b,0x5, 0x7e,0x34,0x61,0x5b,0x12,0x23, +0xb7,0x7a,0x37,0x2b,0x7, 0x74,0x4, 0x7a,0xb3,0x2b,0x6, 0x7e,0x34,0x0, 0xf, 0x7a, +0x37,0x2b,0x9, 0x7e,0x34,0x20,0x5f,0x7a,0x37,0x2b,0xb, 0x90,0x61,0x1a,0xe4,0x93, +0x7a,0xb3,0x2b,0x62,0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x90,0x61,0x1c, +0xe4,0x93,0x7a,0xb3,0x2b,0x11,0x74,0x4, 0x7a,0xb3,0x2b,0x13,0x90,0x60,0xd5,0xe4, +0x93,0x7a,0xb3,0x2b,0xf, 0x12,0x4f,0x61,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3,0x2b, +0x1e,0x7e,0x34,0x61,0x22,0x12,0x23,0xb7,0x7a,0x37,0x2b,0x19,0x90,0x60,0xd3,0x93, +0x7a,0xb3,0x2b,0x12,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x2b,0x20,0x90,0x61,0x19, +0xe4,0x93,0x7a,0xb3,0x2b,0x1f,0x7e,0x34,0x61,0x1e,0x12,0x23,0xb7,0x7a,0x37,0x2b, +0x15,0x7e,0x34,0x61,0x20,0x12,0x23,0xb7,0x7a,0x37,0x2b,0x17,0x90,0x61,0x1d,0xe4, +0x93,0x7a,0xb3,0x2b,0x14,0x7e,0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a,0x74,0x1, 0x7a, +0xb3,0x2b,0x67,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b,0x66, +0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74,0x2, +0x7a,0xb3,0x2b,0x64,0xe4,0x7a,0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60,0xe4, +0x7a,0xb3,0x2b,0x61,0x7e,0x34,0x20,0x68,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca,0x39, +0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x20,0xc6,0x1b, +0xfd,0xda,0x79,0xda,0xd8,0x22,0x12,0x6e,0xe5,0x12,0x6a,0xe8,0x90,0x60,0x50,0xe4, +0x93,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2a,0x7a,0x6d,0x0, 0x9, 0xb3,0x2a,0x79,0x12, +0x6a,0xcf,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2b,0x21,0x6d,0x0, 0x9, 0xb3,0x2b,0x20, +0x12,0x6a,0xcf,0xa, 0x1b,0x2e,0x14,0x2a,0x7c,0x12,0x6a,0xdc,0xe5,0x25,0x12,0x6a, +0xd3,0xa, 0x1b,0x2e,0x14,0x2b,0x23,0x12,0x6a,0xdc,0xe5,0x24,0x2, 0x20,0xeb,0x7e, +0x34,0x0, 0x2, 0x12,0x20,0xeb,0x90,0x60,0x50,0xe4,0x93,0x22,0x6d,0x0, 0x90,0x60, +0x91,0xe4,0x93,0xa, 0x3b,0x1b,0x35,0x22,0x6c,0xaa,0x6c,0x99,0x80,0xc, 0xa, 0xf9, +0x9, 0xbf,0x2a,0x7a,0xbc,0xba,0x68,0x7, 0xb, 0x90,0x12,0x6b,0x14,0x38,0xef,0x12, +0x6b,0x14,0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, 0xa0,0x74,0x6e, +0x7a,0x1b,0xb0,0x22,0x90,0x60,0x50,0xe4,0x93,0xbc,0xb9,0x22,0x12,0x6d,0xa8,0x12, +0x68,0x9b,0x12,0x0, 0x42,0x12,0x6e,0xdc,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8, +0x7e,0xf, 0x6, 0xf8,0x7e,0x1f,0x6, 0xf4,0x12,0x70,0x43,0x7e,0x18,0x8, 0xa, 0x7a, +0x1f,0x13,0x86,0x7e,0x18,0xd, 0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, 0x13,0x8a,0x7e, +0x1f,0x13,0x86,0x12,0x6f,0x3e,0x12,0x6e,0xd9,0x12,0x25,0x5e,0x12,0x6b,0x9b,0x12, +0x6b,0x73,0x2, 0x6b,0x65,0xe4,0x7a,0xb3,0x34,0x38,0x7a,0xb3,0x34,0x39,0x7a,0xb3, +0x34,0x3a,0x22,0x12,0x6b,0xd9,0x7e,0x24,0x0, 0x3, 0xad,0x32,0x7e,0x8, 0x28,0xae, +0x74,0xff,0x12,0x20,0xeb,0x12,0x6f,0x32,0x7e,0x8, 0x29,0xbc,0x12,0x56,0x96,0x7e, +0x8, 0x2a,0x2, 0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x20,0xeb,0x7e,0x8, 0x26,0x5b,0x7e, +0x34,0x2, 0x3a,0xe4,0x12,0x20,0xeb,0x90,0x60,0x9c,0x93,0xa, 0x3b,0x3e,0x34,0x7e, +0x8, 0x26,0x8c,0x74,0xff,0x12,0x20,0xeb,0x90,0x60,0x9c,0xe4,0x93,0xa, 0x3b,0x3e, +0x34,0x7e,0x8, 0x26,0xb4,0x74,0xff,0x12,0x20,0xeb,0x90,0x60,0x9a,0x12,0x6b,0xdc, +0x7e,0x8, 0x27,0x76,0x74,0xff,0x2, 0x20,0xeb,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b, +0x74,0x9, 0xac,0x7b,0x22,0x6d,0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2,0x2a, +0xdc,0x54,0x1, 0x78,0x5, 0x4e,0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0,0x7e, +0x53,0x2a,0x74,0xbc,0x5a,0x38,0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2,0x2a, +0xb9,0xbe,0xb0,0xd, 0x38,0x5, 0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38,0x5, +0x4e,0x60,0x8, 0x80,0x3, 0x4e,0x60,0x50,0xb, 0xa0,0x12,0x6c,0x30,0x38,0xdc,0x22, +0x7e,0xb3,0x2a,0x73,0xbc,0xba,0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab,0x7d, +0x8b,0x6d,0x22,0x7d,0x32,0x7d,0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, 0xfc, +0x7e,0x8, 0x5, 0x7a,0xe4,0x7a,0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3,0x26, +0xf6,0x7a,0xb3,0x26,0xf8,0x7a,0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa,0x80, +0x5f,0x12,0x6d,0x9e,0xb, 0x6a,0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3,0x8, +0x2, 0x7d,0x3c,0x2d,0x71,0x7d,0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d,0x9d, +0x7e,0x67,0x2a,0x53,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, 0x24, +0x12,0x6d,0x8b,0xb, 0x3a,0xd0,0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x26,0xf7,0x4, 0x7a, +0xb3,0x26,0xf7,0x80,0x19,0x12,0x6d,0x94,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff,0xb, +0xd4,0xbd,0xcd,0x58,0x9, 0x7e,0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, 0xa0, +0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x99,0x7a,0xa7,0x7, 0xfe,0x7a,0x37,0x8, 0x2, +0xe5,0x24,0x7a,0xb3,0x8, 0x9, 0x7a,0x97,0x8, 0x6, 0x12,0x5f,0xe8,0x2d,0xf5,0x6c, +0xaa,0x80,0x50,0x12,0x6d,0x9e,0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d,0xbd, +0xd2,0x8, 0x2, 0x7d,0x2d,0x7e,0x67,0x2a,0x51,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd, +0xd7,0x8, 0x2, 0xb, 0x90,0x12,0x6d,0x8b,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, 0x7e, +0xb3,0x26,0xf6,0x4, 0x7a,0xb3,0x26,0xf6,0x80,0x17,0x12,0x6d,0x94,0xb, 0x3a,0xd0, +0x6d,0x99,0x9d,0x9c,0xbd,0xd9,0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3,0x26, +0xf8,0xb, 0xa0,0x12,0x6c,0x30,0x38,0xab,0x7a,0x87,0x7, 0xfc,0x7a,0x27,0x8, 0x0, +0x7a,0x93,0x8, 0x8, 0x12,0x5f,0xe8,0x2d,0x15,0x6c,0xaa,0x80,0xe, 0x12,0x6e,0xee, +0xb, 0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x6c,0x30,0x38,0xed, +0x7a,0xb7,0x8, 0x4, 0xbd,0x8a,0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0xf8,0xbd,0x32, +0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xfa,0xda,0x3b,0x22,0x7e,0x74,0x62,0x16,0x7e, +0x64,0x0, 0xff,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x2d,0x7f,0x7d,0x6e,0x22,0x7e,0xf0, +0x2, 0xac,0xfa,0x7f,0x67,0x2d,0xd7,0x22,0xe4,0x7a,0xb3,0x38,0x86,0x7a,0xb3,0x38, +0x87,0x90,0x60,0x50,0x93,0x7a,0xb3,0x38,0x88,0x90,0x60,0x51,0xe4,0x93,0x7a,0xb3, +0x38,0x89,0xe4,0x7a,0xb3,0x38,0x8a,0x90,0x60,0x99,0x93,0x7a,0xb3,0x38,0x8b,0xe4, +0x7a,0xb3,0x38,0x8c,0x7a,0xb3,0x38,0x8d,0x90,0x61,0xca,0x93,0x7a,0xb3,0x38,0x8f, +0x7e,0x34,0x61,0x4f,0x12,0x23,0xb7,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x38,0x93,0x7e, +0x34,0x61,0x55,0x12,0x23,0xb7,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x38,0x94,0x74,0x64, +0x7a,0xb3,0x38,0xa5,0x90,0x61,0x18,0xe4,0x93,0x7a,0xb3,0x38,0xa6,0x90,0x61,0x17, +0xe4,0x93,0x7a,0xb3,0x38,0x92,0x90,0x61,0x19,0xe4,0x93,0x7a,0xb3,0x38,0xa8,0x90, +0x61,0x24,0xe4,0x93,0x7a,0xb3,0x38,0xa7,0x90,0x61,0x1d,0xe4,0x93,0x7a,0xb3,0x38, +0xa9,0x90,0x61,0x25,0xe4,0x93,0x7a,0xb3,0x38,0xa4,0xe4,0x7a,0xb3,0x38,0x9f,0x74, +0xc8,0x7a,0xb3,0x38,0x9d,0x74,0x1e,0x7a,0xb3,0x38,0x9e,0x74,0x1, 0x7a,0xb3,0x38, +0x9c,0x74,0xc, 0x7a,0xb3,0x38,0x9b,0x74,0x1, 0x7a,0xb3,0x38,0xa0,0xe4,0x7a,0xb3, +0x38,0xa1,0x7a,0xb3,0x38,0xa2,0x7e,0x8, 0x38,0xaa,0x7e,0x34,0x0, 0x2c,0x12,0x20, +0xeb,0x7e,0x34,0x60,0xd6,0x12,0x23,0xb7,0xa, 0x36,0x7a,0x73,0x38,0xb5,0x7e,0x34, +0x60,0xd6,0x12,0x23,0xb7,0x7a,0x73,0x38,0xb6,0x90,0x60,0xd4,0x93,0x7a,0xb3,0x38, +0xb7,0x90,0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x38,0xb8,0x7e,0x34,0x0, 0x4, 0xca,0x39, +0x12,0x6e,0xd0,0x7e,0x8, 0x38,0xc6,0x12,0x20,0xc6,0x1b,0xfd,0x74,0x5, 0x7a,0xb3, +0x38,0xd3,0x74,0x1, 0x7a,0xb3,0x38,0xca,0x7e,0x34,0x0, 0x28,0xca,0x39,0x7e,0x34, +0x61,0xdb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33,0x12,0x20,0xc6,0x1b,0xfd,0x22, +0x7e,0x34,0x61,0x29,0x7e,0x24,0x0, 0xff,0x22,0x2, 0x23,0xbf,0x7e,0x18,0x5, 0xf8, +0x7a,0x1f,0x6, 0xf4,0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18,0x0, 0x24,0x22,0x7e,0x90, +0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0x22,0xca,0x79,0x6c,0xaa,0x12,0x6e,0xee,0xb, +0x7a,0xf0,0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39,0x2d,0x7f,0x71,0x2d,0xf4, +0xb, 0x7a,0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0x4d,0xb, 0xa0,0xbe,0xa0,0x20, +0x40,0xda,0x7e,0x8, 0x39,0x2d,0x7e,0x18,0x39,0x4d,0x74,0x20,0x12,0xc3,0x88,0xda, +0x79,0x22,0x7e,0x8, 0x35,0x8a,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xeb,0x7f,0x60, +0x7e,0xa3,0x2a,0x6d,0x7e,0xb3,0x2a,0x6e,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d, +0x3f,0xe4,0x12,0x20,0xeb,0x7f,0x6, 0x7d,0x3f,0x12,0x20,0xeb,0x7a,0xb3,0x16,0x91, +0x22,0x7e,0xf, 0x13,0x8a,0x7e,0x18,0x8, 0xa, 0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30, +0x12,0x87,0xf0,0x7a,0x55,0x31,0x7e,0xb3,0x2b,0x1d,0xf5,0x2e,0xe4,0x7a,0xb3,0x2b, +0x1d,0x7f,0x3, 0x7e,0x1d,0x29,0x12,0x6f,0x3e,0x12,0x6f,0xf1,0x7e,0x8, 0x2a,0x6d, +0x12,0xd, 0x72,0x75,0x2d,0x0, 0x12,0x4d,0x50,0x30,0xf, 0xfd,0x74,0x1, 0x12,0x6f, +0xe9,0x7e,0x14,0x40,0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x76,0x6a,0x12,0xb9,0x53,0x6d, +0x33,0x80,0x19,0x7e,0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e, +0xd, 0x29,0x2d,0x13,0x12,0x71,0xd3,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e, +0x35,0x31,0xbe,0x35,0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb6, +0xe5,0x2e,0x7a,0xb3,0x2b,0x1d,0xda,0x3b,0x22,0x12,0x0, 0xe, 0x7e,0x1f,0x13,0x86, +0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, 0x1e,0xca,0xf8,0x7e,0x73,0x2a,0x78, +0xa, 0x47,0x7e,0x73,0x2a,0x71,0xa, 0x57,0x2d,0x54,0x7e,0xa3,0x2a,0x73,0xbc,0xab, +0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x2a,0x72,0x7e,0xa3,0x2a,0x74,0xbc,0xaf,0x28,0x2, +0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xb9,0x7e,0x18,0x2a,0x7a,0x12,0xd, 0xd9, +0x75,0x25,0x15,0x7e,0x8, 0x2a,0xdc,0x7e,0x18,0x2a,0x9d,0x7c,0xbf,0x12,0xf, 0x9c, +0xda,0xf8,0x22,0x7f,0x70,0x7e,0x33,0x2a,0x74,0xa, 0x43,0x7e,0x33,0x2a,0x73,0xa, +0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x16,0x90,0x7f,0x1, 0xa, 0x3a, +0x12,0x20,0xeb,0x7f,0x7, 0xa, 0x3a,0x2, 0x20,0xeb,0xca,0xd8,0xca,0x79,0x7c,0xfb, +0x7f,0x51,0x7f,0x40,0x7f,0x15,0x12,0x70,0x43,0x12,0x71,0xc3,0x7e,0xe0,0x1, 0x12, +0x47,0xa5,0x30,0x1d,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x71,0xdc,0x6c, +0xdd,0x80,0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, +0xac,0xbd,0x7f,0x5, 0x2d,0x15,0x12,0x71,0xd3,0xb, 0xd0,0x7e,0x73,0x2a,0x74,0xa, +0x7, 0x7e,0x63,0x2a,0x73,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b, +0xe0,0x78,0xbc,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12,0x71,0x89,0xda,0x79, +0xda,0xd8,0x22,0x7e,0xb3,0x2b,0x2, 0x70,0x41,0x12,0x67,0xf1,0x50,0xfb,0xe4,0x6c, +0x77,0x6c,0x66,0x12,0x71,0x1b,0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3, +0x2b,0x72,0x12,0x70,0x6a,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x71,0x1b, +0x7e,0x8, 0x7, 0x7a,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x25,0xf0,0x12,0x70,0x6a,0x74, +0x2, 0x7a,0xb3,0x2b,0x2, 0xe4,0x7a,0xb3,0x16,0x90,0x22,0x7c,0x96,0x7c,0xa7,0x12, +0x40,0x2a,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, 0x12,0x71,0x34,0x7c,0xb9,0x12,0x0, +0x1e,0x2, 0x46,0xd5,0x7c,0xab,0x80,0xe, 0x7e,0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67, +0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xea,0x22,0xca, +0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x0, 0x12,0x71,0xca,0xa9,0xd0,0xcb,0xc2, +0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x20,0xa9,0xd0,0x9e, +0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x71,0x34,0xa9,0xd0,0x9e,0xa9,0xd7, +0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f, +0x70,0x12,0x71,0xec,0x7c,0xeb,0x6c,0xdd,0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67, +0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e, +0x6d,0x0, 0x12,0x1f,0x7, 0x1b,0x6a,0x30,0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79, +0xda,0xd8,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0x0, 0x2e,0xa9,0xd0,0xce,0xa2,0x0, 0xa9, +0x95,0xc9,0x22,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0xb3,0x2a,0x73, +0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x74,0x2, 0x2, 0x0, 0x1e,0x7c,0x7b,0xa5,0xbf, +0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x70, +0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0,0x2, +0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xa, +0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78,0xfb, +0x7c,0xb9,0x22,0x7e,0xa3,0x2f,0xa8,0x7e,0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37, +0x38,0xd7,0x40,0x39,0x7e,0x37,0x38,0xd7,0xb, 0x34,0x7a,0x37,0x38,0xd7,0xbe,0x34, +0x0, 0x1, 0x78,0x5, 0x7e,0xb3,0x38,0x1e,0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c, +0xba,0x22,0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x39,0xe5, +0x22,0x9e,0x34,0x0, 0x3, 0x2e,0x37,0x2b,0xb9,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22, +0x70,0x5, 0x7e,0xb3,0x38,0x86,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x1f,0x0, 0x30, +0x12,0x6, 0x7e,0x18,0x34,0x9c,0x80,0x4, 0x7e,0x18,0x34,0xda,0x7a,0x1d,0x14,0x80, +0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1f,0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d,0x31, +0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4,0xd3, +0x8, 0x6d,0x33,0x7a,0x37,0x38,0xd7,0x80,0x2, 0x15,0x1a,0x2, 0x72,0x33,0xbe,0xb0, +0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x73,0x7e,0xbe,0xb0,0x80,0x40,0xc, 0xbe,0xb0, +0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x37,0x4b,0x22,0xb4,0xfc,0x5, 0x7e,0xb3,0x37, +0xf2,0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e,0xb3,0x28,0xa8,0x60,0x3, 0x4e,0xa0,0x1, +0x7e,0xb3,0x37,0x5a,0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba,0x22,0xb4,0xfe,0x5, 0x7e, +0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0x7c,0x7b,0x6c,0xaa,0x12,0x73,0x76,0x78,0x9, +0x7c,0xb7,0x12,0x72,0x80,0x7c,0xab,0x80,0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x2f, +0xfb,0x7c,0xab,0x7c,0xba,0x22,0x30,0x90,0x19,0xc2,0x90,0xe5,0x18,0x70,0x9, 0x75, +0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80,0x11,0x7e,0x71,0x91,0xe5,0x1a,0x12,0x73,0x61, +0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x1a,0xe5,0x1a,0x12,0x73,0x17,0xf5,0x91, +0x22,0x7c,0x6b,0x12,0x73,0x76,0x78,0x5, 0x7c,0xb6,0x2, 0x73,0xb0,0xb4,0x4, 0x5, +0x7c,0xb6,0x2, 0x42,0xec,0x22,0x7e,0xb3,0x38,0x86,0xc4,0x54,0x7, 0x22,0xb4,0xeb, +0x5, 0xe4,0x7a,0xb3,0x38,0xdc,0x7e,0x73,0x38,0xdc,0xa, 0x27,0x2e,0x24,0x0, 0x6, +0x12,0x73,0xff,0x7c,0xab,0x7c,0xb7,0x4, 0x7a,0xb3,0x38,0xdc,0xb4,0x3, 0xb, 0xe4, +0x7a,0xb3,0x38,0xdc,0x6d,0x33,0x7a,0x37,0x38,0xd9,0x75,0x1a,0xeb,0x7c,0xba,0x22, +0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, 0x7c,0xba,0x12,0x74,0x24,0x80,0x2c,0xbe, +0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, 0x7c,0xb3,0x7c,0x7a,0x12,0x74,0x7d,0x80, +0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30,0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c, +0x7a,0x12,0x74,0x4f,0xa5,0xbb,0x8f,0x3, 0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c, +0xba,0x2, 0x2f,0x51,0x74,0x1, 0x7a,0xb3,0x34,0x4f,0x22,0x2e,0x24,0x20,0x80,0x7a, +0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0xca,0x7b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0x83,0xc0,0x82,0x12,0x73,0x36,0xd0,0x82,0xd0,0x83,0xda,0xb, 0xda,0x1b,0xda, +0x2b,0xda,0x7b,0x32,0x7a,0xb3,0x38,0x86,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, +0xb4,0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3, +0x37,0xf2,0x22,0x74,0x1, 0x7a,0xb3,0x37,0xf2,0xe4,0x7a,0xb3,0x38,0x86,0x22,0x7c, +0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e,0x60,0xfd,0x68,0x21,0x1b,0x61,0x68,0x1d,0x1b, +0x62,0x68,0x19,0x1b,0x61,0x68,0x15,0x1b,0x60,0x68,0x11,0x2e,0x60,0xa, 0x78,0x4, +0x7a,0x73,0x37,0xca,0xa, 0x2b,0x19,0x72,0x37,0xcb,0xd2,0x11,0x22,0xbe,0xb0,0xeb, +0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x38,0xd9,0x4d,0x22,0x78,0xe, 0xa5,0xbf,0xaa, +0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x38,0xd9,0x15,0x1a,0x7e,0x27,0x38,0xd9,0xbe, +0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x2, 0x6d, +0x33,0x7a,0x37,0x38,0xd9,0x75,0x1a,0xea,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x1f, +0x34,0x12,0x47,0xfd,0x7e,0xa3,0x2a,0x73,0x7e,0x63,0x2a,0x74,0x6c,0xee,0x80,0x1e, +0xa, 0x2e,0x9, 0x72,0x2a,0xdc,0xbe,0x70,0x1c,0x50,0x11,0xa, 0x27,0x12,0x73,0xfb, +0x7c,0x7b,0x7e,0xb3,0x2a,0xfb,0xa, 0x27,0x19,0xb2,0x1f,0x34,0xb, 0xe0,0xbc,0x6e, +0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73,0x2a,0xb9,0xbe,0x70,0x23,0x50, +0xa, 0x7e,0x63,0x2a,0xfb,0xa, 0x27,0x19,0x62,0x1f,0x50,0xb, 0xe0,0xbc,0xae,0x38, +0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x1f,0x34,0x6d,0x0, 0x7c,0xbf, +0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x7e, +0xa3,0x38,0x85,0x7c,0xba,0x4, 0x7a,0xb3,0x38,0x85,0x7a,0xa3,0x37,0xdc,0x22,0xa9, +0xc0,0x93,0x75,0x18,0x0, 0x32,0x7e,0xb3,0x38,0xdb,0x4, 0x7a,0xb3,0x38,0xdb,0xe5, +0x19,0xb4,0x1, 0x8, 0xe4,0x7a,0xb3,0x38,0xdb,0x75,0x19,0x0, 0x7e,0x73,0x38,0xdb, +0x7a,0x73,0x37,0xda,0x22,0xe4,0x7a,0xb3,0x38,0x86,0x7e,0x8, 0x34,0x9c,0x12,0x75, +0xb4,0x7e,0x8, 0x34,0xda,0x7e,0x34,0x0, 0x3e,0x12,0x20,0xeb,0x7e,0x18,0x34,0x9c, +0x7a,0x1d,0x14,0x12,0x75,0x96,0x2, 0x75,0x89,0x75,0x18,0x0, 0x75,0x1a,0x0, 0x7e, +0xb3,0x38,0x86,0xf5,0x91,0x22,0x2, 0x75,0x99,0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe, +0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2,0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2, +0xc0,0xd2,0xad,0x22,0x7e,0x34,0x0, 0x3e,0x74,0xff,0x2, 0x20,0xeb,0x7c,0xab,0x12, +0x42,0x94,0x7c,0xba,0x12,0x13,0xc7,0x2, 0x0, 0x1e,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0, +0x1, 0x28,0x2, 0xe4,0x22,0x12,0x75,0xbd,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x7a, +0xd7,0x2b,0xd, 0x7e,0x73,0x2a,0xfa,0x12,0x2f,0xed,0xe4,0x7e,0x50,0x1, 0x12,0x13, +0x1, 0x12,0x47,0xa5,0x74,0x1, 0x22,0x30,0x1d,0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12, +0x13,0x2c,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x4f,0x12,0x76,0x59,0x49,0x35,0x34,0x3b, +0x49,0x15,0x34,0x3d,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40, +0x15,0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0x73,0x7e, +0x73,0x2a,0x74,0x12,0x10,0xee,0x7e,0xb3,0x34,0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12, +0x76,0x61,0x28,0xe, 0x12,0x4d,0x7d,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, +0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x34,0x3a,0x22,0x7e,0xa3,0x34,0x39,0x74,0x4, 0xa4, +0x22,0x7e,0x73,0x34,0x38,0xbe,0x73,0x34,0x39,0x22,0x7e,0xb3,0x2a,0x6d,0xca,0x3b, +0x7c,0xdb,0x7a,0x5, 0x38,0x7d,0x71,0x7a,0x25,0x36,0x7a,0x35,0x34,0x12,0x67,0x96, +0x50,0x7c,0x6c,0xcc,0x80,0x11,0x7e,0x73,0x2a,0x6e,0x12,0x77,0x95,0x12,0x77,0x7b, +0x7e,0x34,0x34,0x0, 0x12,0x77,0x9e,0x12,0x77,0xb6,0x38,0xea,0x6c,0xcc,0x80,0x58, +0x7e,0xa3,0x2a,0x6e,0x7c,0x7a,0x12,0x77,0x95,0x75,0x3a,0x0, 0x80,0x27,0x7e,0xb3, +0x38,0x9b,0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac,0x7c,0x49,0x43,0x3, 0x71, +0x80,0x6, 0xac,0x7c,0x49,0x43,0x3, 0x73,0x7e,0x71,0x3a,0x74,0x2, 0xac,0x7b,0x59, +0x43,0x34,0x50,0x5, 0x3a,0x7e,0xb3,0x2a,0x70,0xbe,0xb1,0x3a,0x38,0xd0,0x12,0x77, +0xbd,0x68,0xb, 0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34,0x4e,0x12,0x77, +0x7b,0x7e,0x34,0x34,0x50,0x12,0x77,0x9e,0xbc,0xdc,0x38,0xa4,0x80,0x2c,0x7a,0xd3, +0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x25,0xb7,0xe4,0x7a,0xb3,0x25,0xb9,0x74, +0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0x77,0x25,0xba,0x7a,0x77,0x25,0xbe,0x7e,0x8, 0x25, +0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12,0x77,0xc6,0x7e, +0x35,0x38,0x7a,0x37,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x77,0x8c,0x7a,0xd3, +0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9,0x7a,0x77,0x25, +0xba,0x7e,0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x25,0xb9,0x7e,0x35,0x34, +0x7a,0x37,0x25,0xba,0x7e,0x35,0x36,0x7a,0x37,0x25,0xbc,0x6d,0x33,0x7a,0x37,0x25, +0xc0,0x7e,0x8, 0x25,0xb6,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x74,0xc, 0x7a,0xb3,0x25, +0xb8,0x74,0x1, 0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9,0x7e,0x73,0x2a,0x6e, +0x7a,0x73,0x25,0xb7,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3,0x22,0x7a,0x37, +0x25,0xba,0x7d,0x3f,0x7a,0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e,0x8, 0x25,0xb6, +0x12,0x7, 0x9b,0xb, 0xc0,0x22,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x22,0x90,0x60,0xaa, +0xe4,0x93,0xbe,0xb0,0x1, 0x22,0x7d,0xf3,0x6d,0xee,0x6c,0x99,0x80,0x3c,0x7c,0xb9, +0x12,0x5d,0xc5,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f,0x57,0x2d,0xbc,0xb, 0x5a,0x10, +0x1a,0x2, 0x1a,0x0, 0x7e,0x83,0x2b,0x20,0xa, 0x98,0x6d,0x88,0x7f,0x10,0x7f,0x4, +0x12,0x1e,0xeb,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80, +0x14,0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90,0x7e,0x83,0x2a,0x75,0xbc,0x89, +0x38,0xbc,0x22,0x7f,0x20,0xb, 0x2a,0x10,0xb, 0x1a,0x0, 0x1b,0x2a,0x0, 0x1b,0x1a, +0x10,0x22,0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90, +0x7a,0x7b,0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80,0xa, 0x38,0x9d,0x32,0x12,0x21,0x1d, +0xe5,0x29,0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba, +0x7c,0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70, +0x7a,0xb, 0x70,0x22,0x7d,0xc3,0x7e,0x34,0x61,0x37,0x12,0x79,0x66,0x90,0x61,0x35, +0xe4,0x93,0x70,0x3, 0x7d,0x3c,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e, +0x83,0x2a,0x70,0x80,0x4, 0x7e,0x83,0x2a,0x6f,0x12,0x7f,0xc4,0xbe,0xc4,0x0, 0x3f, +0x38,0x1c,0x7e,0xe4,0x0, 0x3f,0x9d,0xec,0x7e,0x34,0x61,0x3b,0x12,0x79,0x50,0x12, +0x79,0x3f,0xbf,0x71,0x40,0x2, 0x7f,0x71,0x9f,0x17,0x7f,0x71,0x21,0x3c,0x12,0x3f, +0x4a,0xbd,0x5c,0x38,0x21,0x7d,0xec,0x9d,0xe5,0x7e,0x34,0x61,0x3d,0x12,0x79,0x50, +0x90,0x61,0x3a,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40,0x4, 0x7f,0x71,0x1b,0x7c,0x12, +0x79,0x47,0x2f,0x71,0x80,0x66,0x7d,0xb4,0xb, 0xb4,0x1e,0xb4,0x7d,0x5b,0x1b,0x54, +0xbd,0x5c,0x40,0xc, 0x7d,0xf5,0x9d,0xfc,0x6d,0xee,0x7e,0x34,0x61,0x3f,0x80,0xa, +0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x34,0x61,0x41,0x12,0x7f,0xac,0x7f,0x17,0x12, +0x1e,0xfc,0x7f,0x71,0x12,0x3a,0xec,0x7f,0x71,0xbd,0x5c,0x7d,0x3d,0x40,0xc, 0x1e, +0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x6, 0x1e,0x34,0x6d,0x22,0x2f, +0x71,0x12,0x79,0x3f,0x6d,0x22,0xbf,0x71,0x50,0x4, 0x7f,0x71,0x80,0xe, 0x90,0x61, +0x3a,0xe4,0x93,0x12,0x79,0x47,0xbf,0x71,0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22,0x90, +0x61,0x39,0xe4,0x93,0xa, 0x3b,0x22,0xa, 0x2b,0x7d,0x3d,0x9d,0x32,0x6d,0x22,0x22, +0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xad,0xfe,0x6d,0xee,0x7d,0x3f,0x7d,0x2e,0x7c, +0x76,0x7c,0x65,0x7f,0x71,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x22,0x7c,0xbd, +0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70,0x7c,0xe7,0x7c,0xdb,0x7e,0xc0,0x4, 0x7e, +0xb3,0x2a,0x6d,0xf5,0x28,0x7e,0xb3,0x2a,0x6e,0xf5,0x27,0x7e,0x34,0x62,0x10,0x12, +0x79,0x66,0x6c,0xff,0x12,0x5f,0x28,0x7f,0x51,0xe5,0x28,0xa, 0x3b,0x1b,0x34,0xa, +0xcd,0xbd,0xc3,0x58,0x14,0xe5,0x27,0xa, 0x3b,0x1b,0x34,0xa, 0xce,0xbd,0xc3,0x58, +0x8, 0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e,0xf0,0x10,0xb, 0x5a,0x30,0x7e, +0x14,0x62,0x10,0x12,0x3f,0xcd,0x8, 0xc, 0x7e,0x27,0x28,0x8a,0xbe,0x24,0x3, 0x20, +0x8, 0x2, 0x41,0xc3,0xb, 0xa, 0xc0,0x1e,0xc4,0xbd,0x3c,0x8, 0xc, 0x7e,0xc7,0x28, +0x8a,0xbe,0xc4,0x3, 0x20,0x58,0x2, 0x41,0xc3,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c, +0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x37, +0x1b,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d, +0x32,0x1a,0xc8,0xbd,0xc3,0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0x41,0xc3, +0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x2a, +0x6d,0xbc,0xb8,0x8, 0x9, 0x12,0x37,0x1b,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0, +0xb, 0x80,0x1a,0x2c,0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd8,0xbc,0xca, +0x18,0x5, 0x4e,0xf0,0x2, 0x80,0x6c,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe, +0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0x9, 0x12,0x37,0x1b,0x58, +0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a, +0xc9,0xbd,0xc3,0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x35,0x6c,0xaa, +0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x2a,0x6e,0xbc, +0xb9,0x8, 0x9, 0x12,0x37,0x1b,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90, +0x1a,0x2c,0x1a,0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x3, +0x4e,0xf0,0x8, 0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b, +0xd0,0x29,0xb7,0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, +0x1, 0xbc,0xbe,0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38, +0x4, 0x39,0xe7,0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0xca,0x3b,0x7c,0xc7,0x7c,0xfb, +0x7f,0x40,0x6d,0x33,0x7a,0x35,0x24,0x7e,0xa3,0x2a,0x6d,0x7e,0x73,0x2a,0x6e,0x4c, +0xcc,0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc,0xbc,0x78,0x6, 0xa, +0x6c,0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, 0x80,0xb, 0x7c,0xba, +0x14,0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e,0x34,0x0, 0x6, 0xe4, +0x12,0x20,0xeb,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b,0x34,0x7a,0x4b,0x70,0x7e,0x73, +0x2a,0x6e,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec,0x80,0x1c,0x75,0x26, +0x0, 0x7c,0xdf,0x80,0xa, 0x12,0x79,0x6e,0x70,0xa, 0x12,0x7c,0x14,0x1b,0xd0,0xbe, +0xd0,0x0, 0x58,0xf1,0xe5,0x26,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xdf,0x7c, +0xec,0x80,0x23,0x75,0x26,0x0, 0x1a,0x3f,0xb, 0x34,0x7c,0xd7,0x80,0xa, 0x12,0x79, +0x6e,0x70,0xd, 0x12,0x7c,0x14,0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xee, +0xe5,0x26,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xd8,0x1a,0x3c,0xb, 0x34,0x7c, +0xe7,0x80,0x1c,0x75,0x26,0x0, 0x7c,0xdf,0x80,0xa, 0x12,0x79,0x6e,0x70,0xa, 0x12, +0x7c,0x14,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf1,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e, +0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xdc,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x21,0x75, +0x26,0x0, 0x1a,0x6f,0xb, 0x64,0x80,0xa, 0x12,0x79,0x6e,0x70,0xd, 0x12,0x7c,0x14, +0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xee,0xe5,0x26,0x60,0xa, 0xb, 0xe0, +0x7e,0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xd7,0x7e,0x35,0x24,0x7d,0x23,0x39,0x54,0x0, +0x5, 0xda,0x3b,0x22,0x5, 0x26,0x7e,0x35,0x24,0xb, 0x34,0x7a,0x35,0x24,0x22,0xca, +0xd8,0xca,0x79,0xc2,0x0, 0x6d,0x88,0x7a,0x87,0x39,0x26,0xe4,0x7a,0xb3,0x1f,0x58, +0xe5,0x5b,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x5b,0x7e,0xb3,0x28,0x84,0x60,0xc, 0x12, +0x7f,0xcc,0xb, 0x1a,0x80,0xbe,0x87,0x7, 0xfa,0x28,0xa, 0xc2,0x14,0x6d,0x88,0x7a, +0x87,0x38,0xe7,0xa1,0x4a,0x12,0x88,0x97,0x60,0x12,0x7e,0x34,0x62,0x14,0x12,0x7f, +0x9c,0x7a,0x87,0x38,0xdd,0x12,0x7d,0xb8,0x7a,0x87,0x38,0xe7,0x7e,0x87,0x38,0xdd, +0x4d,0x88,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x77,0xe4,0xa, +0x3f,0x19,0xb3,0x1f,0x34,0x12,0x7d,0xd2,0x7e,0x8, 0x1f,0x52,0x7c,0xbd,0x7c,0x7e, +0x12,0x7a,0xfa,0x7d,0x93,0x7e,0x87,0x38,0xe7,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x38, +0xe7,0x7e,0x87,0x39,0x26,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x26,0xe5,0x5b,0xbe, +0xb0,0x5, 0x38,0x1f,0x7e,0x8, 0x38,0xe9,0x12,0x7d,0xff,0x50,0x7, 0x12,0x7d,0xc9, +0xd2,0x0, 0x80,0x2f,0x7e,0x8, 0x38,0xe9,0x7e,0x18,0x1f,0x52,0x12,0x7f,0x6a,0x50, +0x22,0x80,0x10,0x12,0x7d,0xb8,0xbd,0x89,0x38,0x19,0x7e,0x8, 0x1f,0x52,0x12,0x88, +0x22,0x50,0x10,0x12,0x7d,0xc9,0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52,0x12,0x88, +0x71,0xd2,0x0, 0xb, 0xf0,0x12,0x7d,0xb1,0x38,0x84,0x30,0x0, 0x33,0x6c,0xff,0x80, +0x1c,0x12,0x7d,0xd2,0x7e,0x8, 0x1f,0x58,0x12,0x7d,0xff,0x40,0x9, 0xa, 0x3f,0x9, +0xb3,0x1f,0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x7d,0xdf,0xb, 0xf0,0x12,0x7d,0xb1, +0x38,0xdf,0x75,0x5b,0x0, 0x7e,0x34,0x62,0x14,0x12,0x23,0xb7,0x7a,0x37,0x38,0xdd, +0x7e,0x63,0x1f,0x58,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1f, +0x58,0x7e,0x8, 0x38,0xe9,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x37,0x38,0xdd,0x4d,0x33, +0x78,0x39,0x90,0x62,0xf, 0xe4,0x93,0xa, 0x3b,0xbe,0x37,0x38,0xe7,0x38,0x40,0x7c, +0x7b,0x1e,0x70,0xa, 0x37,0xbe,0x37,0x39,0x26,0x38,0x34,0x90,0x60,0x51,0x12,0x7d, +0xc0,0x7e,0x73,0x26,0xf7,0xa, 0x37,0xbd,0x32,0x8, 0x24,0x90,0x60,0x50,0x12,0x7d, +0xc0,0x7e,0x73,0x26,0xf6,0xa, 0x37,0xbd,0x32,0x8, 0x14,0x6c,0xff,0x80,0x7, 0x7c, +0xbf,0x12,0x7d,0xdf,0xb, 0xf0,0x12,0x7d,0xb1,0x38,0xf4,0xd2,0x0, 0x80,0x6, 0x6d, +0x33,0x7a,0x37,0x38,0xe7,0xa2,0x0, 0x92,0x14,0x12,0x7f,0xd5,0xda,0x79,0xda,0xd8, +0x22,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x22,0x90,0x62,0xf, 0xe4,0x93,0xa, 0x8b,0x22, +0xe4,0x93,0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, 0x8f,0x19,0xb8,0x1f, +0x34,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5,0x26,0xfb,0x22,0x7c, +0xab,0x7e,0xb3,0x39,0xf5,0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70,0x11,0x12,0x7f,0xbc, +0x68,0xc, 0x12,0x7f,0xb4,0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x39,0x2f,0x22,0x7c, +0xbd,0x7c,0x7e,0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a, +0x7f,0x70,0x2d,0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b, +0xb0,0xbc,0xb6,0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, +0x1, 0xbc,0xb7,0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba, +0x38,0xc9,0xa2,0x1, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28, +0x99,0xe4,0x7a,0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x4c,0x7e, +0x73,0x28,0x85,0xbe,0x70,0x0, 0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac, +0x5f,0x9, 0xd2,0x27,0x36,0x9, 0xe2,0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12, +0x4, 0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x53,0xbd,0x12,0x58,0x19,0x12,0x7f,0x57,0x49, +0x12,0x4, 0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a, +0xb3,0x28,0xa6,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7, +0x7e,0xb3,0x26,0x83,0x70,0x40,0x12,0x7f,0xa4,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e, +0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x26,0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x7f,0x57,0x49, +0x2, 0x5, 0x7a,0x6d,0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e, +0x49,0x20,0x5, 0x7a,0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, +0xb, 0xf0,0xbc,0x7f,0x38,0xc9,0x12,0xad,0xd5,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37, +0x28,0x88,0x2e,0x37,0x28,0x86,0xbe,0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3, +0x28,0xa9,0x74,0x1, 0x7a,0xb3,0x28,0xaa,0x6c,0xff,0x80,0x1f,0x12,0x7f,0x60,0x49, +0x25,0x25,0xf7,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x21,0x1d,0xbe,0x37,0x28,0x9d, +0x8, 0x7, 0xe4,0x7a,0xb3,0x28,0xaa,0x80,0x7, 0xb, 0xf0,0x12,0x7d,0xb1,0x38,0xdc, +0x6c,0xff,0x80,0x9, 0x12,0x7f,0x60,0x59,0x35,0x25,0xf7,0xb, 0xf0,0x12,0x7d,0xb1, +0x38,0xf2,0xda,0x79,0xda,0xd8,0x22,0xa, 0x1d,0xa, 0x2a,0x2d,0x21,0x3e,0x24,0x22, +0x7c,0xbf,0x12,0x38,0x9e,0x74,0x2, 0xac,0xbf,0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b, +0x90,0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12, +0x7e,0x3, 0x50,0x2, 0xd3,0x22,0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9, +0xb, 0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79,0x50,0xd9,0xc3,0x22,0x7e,0x24,0x0, 0xff, +0xb, 0x1a,0x80,0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0x7e,0x24,0x0, 0xff, +0xb, 0x1a,0x10,0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x38,0x1b, +0xbe,0xb0,0x1, 0x22,0x7e,0x90,0x40,0xac,0x89,0x1b,0x44,0x22,0x7e,0x34,0x61,0x55, +0x7e,0x24,0x0, 0xff,0x22,0x30,0x14,0x13,0x12,0x7f,0xec,0x68,0x6, 0x7e,0xb3,0x39, +0xf5,0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x38,0xe5,0x22,0x7e,0xb3,0x28,0xa8, +0xbe,0xb0,0x1, 0x22,0x2, 0x7f,0xf7,0xca,0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c, +0xee,0x80,0x35,0x7c,0xbe,0x12,0x38,0x9e,0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0x37, +0x3f,0x60,0x23,0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34, +0x27,0x76,0x6d,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12, +0x20,0xc6,0x1b,0xfd,0xb, 0xf0,0xb, 0xe0,0x12,0x5f,0xd9,0x38,0xc6,0x7a,0x73,0x28, +0x93,0x7a,0xf3,0x2a,0x2, 0xda,0x79,0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, +0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x12,0x1f,0x5, 0x7d,0x53,0xbe,0x54,0x0, 0xff, +0x28,0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca,0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f, +0x3a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3, +0x1f,0x35,0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3, +0x1f,0x38,0x7a,0xb3,0x1f,0x39,0x7e,0x8, 0x1f,0x34,0x12,0x5f,0xf0,0x6d,0x22,0x7d, +0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa0,0x2f,0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12, +0x1f,0x7, 0xa, 0x1f,0x6d,0x0, 0x12,0x1f,0x7, 0xda,0xf8,0x22,0x7a,0x37,0x1f,0x38, +0x7e,0x34,0x15,0xa8,0x7a,0x37,0x1f,0x3c,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a, +0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x35,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34, +0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x3e,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40, +0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x42,0x74,0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3, +0x1f,0x37,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x1f,0x44,0x12,0x8, 0x0, 0x7e,0x37,0x1f, +0x4e,0x7e,0x27,0x1f,0x4a,0xbd,0x23,0x28,0x2, 0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, +0x1f,0x34,0x12,0x82,0xff,0x7e,0x1f,0x39,0xdd,0x7a,0x1d,0x27,0x7e,0xb3,0x2a,0x74, +0xf5,0x2e,0x7e,0xb3,0x39,0x70,0xb4,0x1, 0x6, 0x7e,0x38,0x39,0x72,0x80,0x4, 0x7e, +0x38,0x5, 0xf8,0x6d,0x33,0x7a,0x35,0x2b,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39, +0x71,0x70,0xe, 0x7e,0xb3,0x39,0x6f,0x70,0x8, 0x74,0x1, 0x7a,0xb3,0x39,0x71,0x21, +0xe4,0x7e,0xb3,0x39,0x71,0x70,0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x71,0x7e,0xb3,0x39, +0x70,0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80,0x6, 0x12,0x82,0x26,0x12,0x82,0x34,0xe5, +0x2e,0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18,0x75,0x2d,0x0, 0x80,0xc, 0x12,0x82,0x26, +0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0x82,0x34,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed, +0x7e,0x34,0x61,0x5b,0x12,0x23,0xb7,0x7a,0x35,0x2f,0x7e,0x18,0x1f,0x34,0x7f,0x1, +0x12,0x82,0x45,0x75,0x2d,0x0, 0x80,0x10,0x12,0x82,0x19,0xbe,0x35,0x2b,0x8, 0x6, +0x12,0x82,0x19,0x7a,0x35,0x2b,0x5, 0x2d,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xe9,0x12, +0x82,0x11,0x40,0x25,0x7e,0xb3,0x39,0x70,0xb4,0x1, 0x1e,0x5, 0x5a,0xe5,0x5a,0xbe, +0xb0,0xa, 0x40,0x15,0x75,0x5a,0x0, 0xe5,0x2e,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e, +0x1d,0x27,0x7f,0x3, 0x12,0x20,0xc6,0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x82, +0x11,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x39,0xdc,0xe4,0x7a,0xb3,0x39,0x71,0xda,0x3b, +0x22,0x7e,0x37,0x2b,0x7, 0xbe,0x35,0x2b,0x22,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x49, +0x35,0x1f,0x34,0x2, 0x21,0x1d,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35, +0xb, 0x1a,0x20,0x22,0x7e,0xd, 0x27,0x2d,0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35, +0x1f,0x34,0x5, 0x2d,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x2a,0x6e,0xa, +0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc6,0x1b,0xfd,0x6c,0xdd, +0x12,0x83,0x7, 0x7a,0xb3,0x1f,0x6c,0x6c,0xcc,0x80,0x4a,0x12,0x82,0xee,0x78,0x43, +0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x21,0x1d, +0x7d,0x13,0x7d,0x3e,0x12,0x21,0x1d,0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f, +0x8, 0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, +0x7d,0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x6c,0x4, 0x7a, +0xb3,0x1f,0x6c,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xae,0x7e,0x73,0x1f, +0x6c,0x4c,0x77,0x68,0x1d,0x12,0x84,0x12,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80,0xa, +0x12,0x82,0xee,0x78,0x3, 0x12,0x83,0xfd,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c, +0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0x41,0x60,0xda,0x3b,0x22,0xa, 0xec, +0x9, 0x7e,0x2a,0xdc,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22,0x7e, +0x34,0x0, 0x38,0xe4,0x2, 0x20,0xeb,0x7e,0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22,0xca, +0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x22,0xfb,0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, +0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x3e,0x34,0xca, +0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xc6,0x1b,0xfd,0x6c,0xdd,0x12,0x83,0x7, 0x7a, +0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4f,0x12,0x83,0xed,0x40,0x48,0x12,0x83,0xe3,0x50, +0x43,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x21, +0x1d,0x7d,0x3, 0x7d,0x31,0x12,0x21,0x1d,0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15, +0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, +0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34,0x4, +0x7a,0xb3,0x1f,0x34,0xb, 0xc0,0x12,0x77,0xb6,0x38,0xac,0x7e,0x73,0x1f,0x34,0x4c, +0x77,0x68,0x34,0x12,0x84,0x12,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, 0x5, 0x7e, +0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e,0x6c, +0xcc,0x80,0xf, 0x12,0x83,0xed,0x40,0x8, 0x12,0x83,0xe3,0x50,0x3, 0x12,0x83,0xfd, +0xb, 0xc0,0x12,0x77,0xb6,0x38,0xec,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x2, 0x61,0x3c, +0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc,0xab,0x22,0xa, 0xec,0x9, +0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0x74,0x2, 0xac, +0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b,0x1a, +0xe0,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12,0x1f,0x58,0x7d,0x73,0x12,0x21,0x1d, +0x7d,0xe3,0x7d,0x3f,0x12,0x21,0x1d,0xbd,0x3e,0x22,0x74,0xc8,0x7a,0xb3,0x39,0xf0, +0xc2,0x1c,0x80,0xa, 0x12,0x29,0x17,0x30,0x1c,0x4, 0x75,0xe9,0xff,0x22,0x12,0x84, +0x71,0x68,0xf1,0x22,0x74,0x1, 0x12,0x84,0x63,0x20,0x1c,0x6, 0x12,0x29,0x8f,0x12, +0x84,0x6c,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x6, 0x12,0x84,0x2a,0x12,0x84,0x6c,0xe4, +0x2, 0x84,0x63,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x84,0x82,0x22,0xd2,0x1, 0x2, 0x28, +0xc6,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x1, 0x22,0x12,0x84,0x71,0x68,0xfb,0x20,0x93, +0xfd,0x22,0xa, 0x5b,0x2e,0x54,0x0, 0x8, 0xf5,0xcc,0x22,0xa9,0xc4,0xca,0xa9,0xc5, +0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x84,0x82,0xa9,0xd0,0xce,0xa9,0xc0,0xc9,0xd2, +0x2, 0x12,0x28,0xd7,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75,0xc2,0xc, 0xd2,0x0, 0x12, +0x84,0xbc,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1,0x22,0xa2,0x0, 0xa9,0x97, +0xc1,0xa2,0x0, 0xa9,0x97,0xc2,0x22,0x12,0x26,0xc5,0x7e,0x73,0x37,0xca,0xbe,0x70, +0xff,0x68,0x13,0xbe,0x73,0x37,0xf0,0x68,0xd, 0x7a,0x73,0x37,0xf0,0x74,0xff,0x7a, +0xb3,0x37,0xca,0x2, 0x26,0xc5,0x22,0x7e,0x34,0x61,0x57,0x7e,0x24,0x0, 0xff,0xb, +0x1a,0x20,0x12,0x5f,0x42,0x50,0x8, 0x7e,0x27,0x2a,0x4f,0x1e,0x24,0x1e,0x24,0x7d, +0x32,0x22,0x7e,0xb3,0x37,0xf0,0x70,0x2e,0x7e,0x73,0x37,0xd3,0xbe,0x70,0x10,0x40, +0x2, 0x6c,0x77,0x7e,0xb3,0x38,0x1b,0xb4,0x1, 0x3, 0x7e,0x70,0x6, 0xa, 0x37,0x2e, +0x34,0xf, 0xf0,0x12,0x85,0x57,0x7c,0xab,0xe5,0x5f,0xa, 0x3b,0x2e,0x37,0x39,0x6d, +0x7a,0x37,0x39,0x6d,0x80,0xc, 0x7e,0xa3,0x37,0xd4,0xbe,0xa0,0x7f,0x28,0x3, 0x7e, +0xa0,0x7f,0x7c,0xba,0x2, 0x85,0x47,0x75,0x5f,0x0, 0x7a,0xb3,0x39,0xf0,0xc2,0x1c, +0x22,0x2d,0x32,0x2e,0x34,0x21,0xd, 0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22, +0x7c,0x2b,0x7e,0xb3,0x1f,0x33,0xbc,0x2b,0x68,0x4f,0x12,0x67,0xab,0x7c,0x3b,0x7c, +0xb2,0x12,0x67,0xab,0x7c,0xab,0xbe,0x30,0xff,0x68,0x3e,0xbe,0xa0,0xff,0x68,0x39, +0x7e,0x70,0x4, 0xac,0x73,0xa, 0x2a,0x12,0x85,0x51,0xbe,0xb0,0x2, 0x38,0x2a,0xa, +0x2b,0x7e,0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30,0x1b,0x3, +0x2, 0x85,0xc9,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0xf, 0x12,0x87,0xf0,0x7a,0x55,0x29, +0x7e,0x8, 0xd, 0xc8,0x74,0x1, 0x2, 0x85,0xfa,0x22,0x7c,0xab,0x12,0x87,0xdf,0xd2, +0x1b,0x7c,0xba,0x12,0x85,0x60,0xc2,0x1b,0x22,0x7c,0x7b,0x90,0x60,0x93,0xe4,0x93, +0xa, 0x1b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2d,0x1, 0x7e,0x63,0x2a,0x6e,0xa, 0x16, +0xad,0x10,0x7d,0x21,0x12,0x87,0xe7,0xa, 0x26,0x7a,0x25,0x29,0x74,0x1d,0xac,0x7b, +0x2e,0x34,0x38,0x2e,0x6d,0x22,0xe4,0x2, 0x85,0xfa,0x7c,0xab,0x6d,0x44,0x80,0x29, +0x4c,0xaa,0x68,0x11,0x12,0x86,0x3d,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12,0x86, +0x31,0x2d,0xfe,0x80,0xf, 0x12,0x86,0x3d,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb,0x12, +0x86,0x31,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e,0xf5,0x29,0xbd,0xf4,0x38,0xd0, +0x22,0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0,0x22,0x7f,0x71,0x2d, +0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b,0xb0,0x22,0xca, +0xf8,0x7e,0x45,0x24,0x7c,0xb9,0x7a,0xb3,0x39,0x29,0x74,0xff,0x7a,0xb3,0x39,0x28, +0x6d,0x55,0x80,0x19,0x7d,0xf5,0x3e,0xf4,0x12,0x86,0x33,0x7d,0xe5,0x3e,0xe4,0x59, +0xfe,0x1f,0x34,0x69,0xf6,0x0, 0x2, 0x59,0xfe,0x21,0x14,0xb, 0x54,0xbd,0x45,0x38, +0xe3,0x7e,0x33,0x39,0x29,0xbe,0x30,0x4, 0x38,0x2, 0xe1,0x11,0x69,0xf1,0x0, 0x1c, +0x69,0x11,0x0, 0x1e,0xbd,0x1f,0x18,0x19,0x4d,0x11,0x78,0x4, 0x7e,0x14,0x0, 0x1, +0x7d,0x3f,0x7d,0x21,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x40,0x7a,0xb3,0x39,0x2c,0x80, +0x43,0x4d,0xff,0x78,0x4, 0x7e,0xf4,0x0, 0x1, 0x7d,0x31,0x7d,0x2f,0x12,0x1e,0xb9, +0x7c,0xf7,0x74,0x80,0x7a,0xb3,0x39,0x2c,0x7d,0xf, 0x2d,0xf, 0xbd,0x1, 0x8, 0x24, +0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x39,0x2c,0xa, 0x37,0x6d,0x22,0x12,0x1e,0xeb,0x7d, +0x5f,0x1a,0x4a,0x1a,0x48,0x7d,0x1f,0x1a,0x2, 0x1a,0x0, 0x2f,0x2, 0x12,0x1f,0x7, +0x7a,0x73,0x39,0x2c,0xbe,0xf0,0x5, 0x58,0x14,0x12,0x87,0x30,0x12,0xc5,0xc4,0x12, +0x87,0x30,0x12,0xc7,0x2b,0x12,0x87,0x30,0x12,0xc6,0xc1,0x80,0xa, 0x74,0x7d,0x80, +0x2, 0x74,0x7f,0x7a,0xb3,0x39,0x28,0xe4,0x7a,0xb3,0x39,0x29,0x7e,0x73,0x39,0xeb, +0xbe,0x73,0x39,0x28,0x48,0x6, 0x7e,0xb3,0x39,0x2a,0x80,0x1, 0xe4,0xda,0xf8,0x22, +0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x21,0x14,0x22,0x12,0x87,0xd6,0x7a,0x37,0x2f,0x9c, +0x12,0x87,0x61,0x7a,0x37,0x2f,0x9e,0x12,0x3c,0xa, 0x60,0x1, 0x22,0x7e,0x73,0x2f, +0xa8,0xa, 0x37,0x7a,0x35,0x24,0x7e,0x8, 0x2b,0xbf,0x7e,0x18,0x2f,0x80,0x2, 0x86, +0x4f,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x17,0x2f,0x90,0xbd,0x13, +0x28,0xa, 0x7a,0x37,0x2f,0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e,0x17,0x2f,0x88, +0xbd,0x13,0x50,0x8, 0x7a,0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e,0x17,0x2f,0x8e, +0xbd,0x12,0x28,0xa, 0x7a,0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80,0x10,0x7e,0x17, +0x2f,0x96,0xbd,0x12,0x50,0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f,0x94,0x7e,0xb3, +0x2f,0xa8,0xb4,0xa, 0xf, 0x12,0x87,0xd6,0x7a,0x37,0x2f,0xa0,0x12,0x87,0x61,0x7a, +0x37,0x2f,0xa2,0x22,0xb4,0x14,0xe, 0x12,0x87,0xd6,0x7a,0x37,0x2f,0xa4,0x12,0x87, +0x61,0x7a,0x37,0x2f,0xa6,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37,0x2f,0x90,0x22,0xa9, +0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x3e,0x24,0x7e,0xf, 0x39,0xc3,0x2d,0x12,0x22, +0x7e,0xa3,0x2a,0x6e,0x7e,0xb3,0x2a,0x6d,0xa4,0x22,0x12,0x5f,0x42,0x50,0x12,0x7e, +0x37,0x2b,0x7, 0xbe,0x34,0x1, 0x2c,0x28,0x8, 0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x2b, +0x7, 0x22,0x7e,0xb3,0x39,0x70,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39, +0x70,0x22,0x7f,0x20,0xc2,0x1, 0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a, +0x37,0x12,0x21,0x1d,0x7c,0x27,0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37, +0x1a,0x33,0x12,0x21,0x1d,0x7c,0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x21,0x1d, +0x7c,0x67,0x7c,0x72,0xbc,0x32,0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe, +0x70,0x6, 0x58,0x8, 0x7e,0x37,0x38,0xdd,0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, +0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe,0xa0,0xa, 0x50,0x1b,0x7e,0x14,0x0, 0x6, 0xca, +0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d,0x15,0xb, 0x14,0x12,0x20,0xc6,0x1b,0xfd,0x7e, +0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22,0x6c,0xaa,0x7e,0x63,0x2a,0x6e,0x7e,0x73,0x2a, +0x6d,0xac,0x76,0x7d,0x13,0x1e,0x14,0x7e,0x27,0x28,0x88,0x2e,0x27,0x28,0x86,0xbd, +0x21,0x38,0xa, 0x1e,0x34,0x1e,0x34,0xbe,0x37,0x28,0x86,0x50,0x29,0x90,0x60,0x51, +0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26,0xf7,0xa, 0x3b,0xbd,0x32,0x8, 0x16, +0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26,0xf6,0xa, 0x3b,0xbd, +0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7e,0xa3,0x2a,0x3, 0xbe,0xa0,0x0, +0x38,0x2f,0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, 0xbe,0xb3,0x36,0x26, +0x28,0x14,0x7e,0xb3,0x36,0x26,0x4, 0x7a,0xb3,0x36,0x26,0x7a,0xa3,0x2a,0x2, 0x80, +0x5, 0xe4,0x7a,0xb3,0x36,0x26,0x7e,0xb3,0x2a,0x2, 0x70,0x5, 0xe4,0x7a,0xb3,0x2a, +0xb, 0x22,0x12,0x89,0x28,0x2, 0x88,0xe9,0x7e,0xb3,0x2a,0x2, 0x70,0x29,0x12,0x89, +0x61,0x28,0x24,0x7e,0xb3,0x35,0xab,0x70,0x18,0x12,0x89,0x69,0x7e,0x73,0x2a,0x3, +0x7a,0x73,0x2a,0x2, 0x74,0x1, 0x7a,0xb3,0x2a,0x9, 0x7e,0xb3,0x35,0xab,0x4, 0x80, +0x1, 0xe4,0x7a,0xb3,0x35,0xab,0x22,0xe4,0x7a,0xb3,0x35,0xab,0x7a,0xb3,0x2a,0x9, +0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x22,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e, +0x18,0x36,0x54,0x7e,0x8, 0x36,0x90,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x73,0x28,0x94, +0x7a,0x73,0x36,0x50,0x7a,0x73,0x28,0x93,0x22,0x12,0x89,0x61,0x28,0x8, 0x7e,0xb3, +0x28,0x84,0x70,0x2, 0xf5,0x1d,0x7e,0xb3,0x28,0x84,0x70,0x18,0xe5,0x1d,0xbe,0xb0, +0xfa,0x50,0x2, 0x5, 0x1d,0xe5,0x1d,0xbe,0xb0,0x5, 0x40,0x8, 0xe4,0x7a,0xb3,0x32, +0x2c,0x75,0x1d,0xfa,0x22,0xca,0x79,0xc2,0x0, 0x7e,0xf0,0x3, 0x12,0x89,0x89,0x7e, +0xe3,0x2a,0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37,0x31,0xee,0x12,0x8f,0x74,0x38,0x2, +0x41,0x91,0x12,0x8f,0x8e,0x92,0xd, 0x12,0x8e,0xab,0x7c,0xbf,0x12,0x8a,0x9a,0x4c, +0xee,0x68,0xe, 0x7e,0xa3,0x31,0xcb,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x31,0xcc,0x70, +0x4, 0xd2,0x0, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x1e,0xbe,0xb0,0x8, 0x28, +0x4, 0xd2,0x0, 0x80,0x15,0xd2,0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xbe,0x78,0xb, 0x20, +0xd, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c,0xbf,0x12, +0x8a,0x9a,0x7e,0x8, 0x31,0xd0,0x12,0xb1,0x3, 0x7a,0xb3,0x31,0xcf,0xbe,0xb3,0x28, +0x84,0x50,0x3d,0x7e,0x33,0x31,0xcf,0x80,0x29,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23, +0x31,0xf0,0x9, 0x13,0x31,0xf1,0x2e,0x37,0x31,0xee,0xb, 0x38,0x50,0x7e,0x93,0x2a, +0x6e,0xac,0x92,0xa, 0x31,0x2d,0x43,0x12,0xc9,0x3, 0x7c,0xb3,0x7e,0x70,0x1, 0x12, +0x39,0x2f,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xcf,0x74,0x1, 0x7a,0xb3,0x31,0xcd, +0x7e,0xa3,0x31,0xcf,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x31, +0xf0,0x7e,0x8, 0x26,0xfa,0x12,0x20,0xc6,0x1b,0xfd,0x12,0x8e,0xe4,0xf5,0x1e,0x80, +0x6, 0x75,0x1e,0x64,0x12,0x8f,0xe4,0xda,0x79,0x22,0xca,0x3b,0x7c,0xfb,0x75,0x3d, +0x0, 0x75,0x3e,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x43,0x7e,0xb3,0x2a,0x70,0xf5,0x44, +0x7e,0xd3,0x28,0x84,0xe4,0x7a,0xb3,0x31,0xcf,0x7a,0xb3,0x31,0xcb,0x7a,0xb3,0x31, +0xcc,0x7e,0x8, 0x31,0xd0,0x12,0x8f,0x61,0xe4,0x12,0x20,0xeb,0x12,0x8f,0x61,0x3e, +0x34,0x7e,0x8, 0x31,0xf0,0xe4,0x12,0x20,0xeb,0xbe,0xd0,0x2, 0x50,0x2, 0xc1,0xa8, +0x6c,0xcc,0xc1,0xa2,0x12,0x8f,0x84,0xf5,0x24,0x9, 0xb3,0x26,0xfb,0xf5,0x25,0x4c, +0xcc,0x68,0x8, 0xa, 0x3c,0x9, 0xb3,0x31,0xd0,0x70,0xa, 0xa, 0x3c,0xb, 0x34,0xa, +0x2c,0x19,0x72,0x31,0xd0,0x7c,0xbd,0x14,0xbc,0xbc,0x78,0x2, 0xc1,0xa8,0xa, 0x5c, +0xb, 0x54,0xf5,0x2e,0xc1,0x99,0x7e,0x71,0x2e,0x12,0x8f,0xf3,0x7a,0xa1,0x26,0x9, +0xb3,0x26,0xfb,0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0x8e,0xdd,0x7c,0xb7,0xf5,0x28, +0xe5,0x27,0xa, 0x2b,0xe5,0x25,0x12,0x8e,0xdd,0x7c,0xb7,0xf5,0x29,0xe5,0x28,0xbe, +0xb0,0x5, 0x40,0x2, 0xc1,0x97,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xc1,0x97,0x12, +0x8f,0x68,0x12,0xb4,0xa1,0x7a,0xb3,0x31,0xce,0x85,0x25,0x54,0x85,0x26,0x55,0x85, +0x27,0x56,0x7e,0x8, 0x0, 0x31,0x7e,0x18,0x0, 0x33,0xe5,0x24,0x12,0xb6,0xcb,0x75, +0x3d,0x0, 0x75,0x3e,0x0, 0x75,0x30,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x35,0xb5, +0x7a,0x35,0x35,0xe5,0x26,0x7e,0x71,0x27,0x12,0x35,0xb5,0x7a,0x35,0x37,0x7e,0x35, +0x35,0xbe,0x35,0x37,0x8, 0x5, 0x7e,0x35,0x37,0x80,0x3, 0x7e,0x35,0x35,0x7a,0x35, +0x3b,0xe, 0x34,0x7a,0x35,0x39,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x2c,0xe5,0x29,0xbe, +0xb0,0x1, 0x38,0x25,0x7c,0xbf,0x30,0xe1,0x20,0xe5,0x26,0x7e,0x71,0x25,0x12,0x35, +0xb5,0x7d,0x43,0xe5,0x24,0x7e,0x71,0x27,0x12,0x35,0xb5,0x2d,0x34,0xbe,0x35,0x39, +0x18,0x2, 0xc1,0x2e,0x75,0x30,0x1, 0xc1,0x2e,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x9, +0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x2, 0xc1,0x2e,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, +0xc1,0x2e,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xc1,0x2e,0x7c,0xbf,0x20,0xe0,0x2, +0xc1,0x2e,0x6d,0x33,0x7a,0x35,0x4d,0x75,0x4f,0x0, 0x7a,0x35,0x50,0x75,0x52,0x0, +0xc2,0x2, 0xc2,0x3, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x4, 0xe5,0x24,0x80,0x2, 0xe5, +0x26,0xf5,0x2a,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26, +0xf5,0x2c,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5, +0x2b,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2d, +0xe5,0x2c,0xbe,0xb1,0x2a,0x78,0x29,0xd2,0x2, 0xe5,0x2a,0x60,0x8, 0xe5,0x43,0x14, +0xbe,0xb1,0x2a,0x78,0x2, 0xd2,0x3, 0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2a, +0xe5,0x43,0xa, 0x2b,0x1b,0x24,0xe5,0x2c,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2c, +0xe5,0x2d,0xbe,0xb1,0x2b,0x78,0x29,0xd2,0x2, 0xe5,0x2b,0x60,0x8, 0xe5,0x44,0x14, +0xbe,0xb1,0x2b,0x78,0x2, 0xd2,0x3, 0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x2b, +0xe5,0x44,0xa, 0x2b,0x1b,0x24,0xe5,0x2d,0xa, 0x3b,0xbd,0x32,0x58,0x2, 0x5, 0x2d, +0x85,0x2a,0x3f,0x80,0x5b,0x85,0x2b,0x40,0x80,0x4d,0xe5,0x3f,0x7e,0x71,0x40,0x12, +0x35,0xb5,0x7a,0x35,0x41,0xe5,0x2a,0xbe,0xb1,0x3f,0x68,0x15,0xe5,0x2c,0xbe,0xb1, +0x3f,0x68,0xe, 0xe5,0x2b,0xbe,0xb1,0x40,0x68,0x7, 0xe5,0x2d,0xbe,0xb1,0x40,0x78, +0xd, 0x7e,0x35,0x41,0x2e,0x35,0x4d,0x7a,0x35,0x4d,0x5, 0x4f,0x80,0x17,0x5, 0x52, +0x7e,0x35,0x41,0x2e,0x35,0x50,0x7a,0x35,0x50,0x7e,0x35,0x33,0xbe,0x35,0x41,0x58, +0x2, 0x5, 0x3d,0x5, 0x3e,0x5, 0x40,0xe5,0x2d,0xbe,0xb1,0x40,0x50,0xac,0x5, 0x3f, +0xe5,0x2c,0xbe,0xb1,0x3f,0x50,0x9e,0xe5,0x2c,0x7e,0x71,0x2b,0x12,0x35,0xb5,0x7e, +0x45,0x4d,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2d,0x12,0x35,0xb5,0x9d,0x43,0xe5,0x2a, +0x7e,0x71,0x2b,0x12,0x35,0xb5,0x9d,0x43,0xe5,0x2c,0x7e,0x71,0x2d,0x12,0x35,0xb5, +0x7d,0x23,0x7d,0x34,0x9d,0x32,0x7a,0x35,0x4d,0x7e,0x35,0x37,0x2e,0x35,0x35,0x7a, +0x35,0x39,0x30,0x2, 0x10,0x20,0x3, 0xd, 0x7e,0x35,0x4d,0x9e,0x35,0x39,0x7a,0x35, +0x4d,0x15,0x4f,0x15,0x4f,0xe5,0x4f,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x4f,0x24,0xfc, +0xf5,0x4f,0x7e,0x35,0x4d,0xbe,0x34,0x0, 0x0, 0x58,0x5, 0x6d,0x33,0x7a,0x35,0x4d, +0x7e,0xe0,0x22,0xe5,0x43,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, +0xe5,0x24,0x60,0x4, 0xe5,0x26,0x70,0xa, 0x12,0x8f,0x7c,0x28,0x36,0x7e,0xe0,0x2c, +0x80,0x31,0x30,0xa, 0x2e,0x7e,0xb3,0x36,0x51,0xb4,0x1, 0x27,0x7e,0x73,0x36,0x52, +0xbe,0x71,0x2c,0x38,0x1e,0xbe,0x71,0x2a,0x40,0x19,0x7e,0x73,0x36,0x53,0xbe,0x71, +0x2d,0x38,0x10,0xbe,0x71,0x2b,0x40,0xb, 0xa, 0x3e,0x7e,0x24,0x0, 0x3, 0x12,0x1e, +0xb9,0x2c,0xe7,0x7e,0x15,0x50,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4d,0x1a,0x26,0x1a, +0x24,0x2f,0x10,0xa, 0x1e,0x6d,0x0, 0x12,0x1e,0xeb,0x7f,0x71,0x7a,0x7d,0x45,0x7e, +0x15,0x39,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x31,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb, +0xe5,0x52,0xa, 0xdb,0x6d,0xcc,0xe5,0x4f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1e, +0xeb,0x7a,0x1d,0x49,0xbf,0x71,0x8, 0x3, 0x75,0x30,0x2, 0xc2,0x1, 0x20,0xc, 0xe, +0x12,0x8f,0x68,0x12,0xb8,0x3a,0x92,0x1, 0x20,0x1, 0x3, 0x75,0x30,0x0, 0xe5,0x30, +0xbe,0xb0,0x0, 0x28,0x62,0xe5,0x30,0xa, 0x3b,0x2e,0x34,0x31,0xca,0x7e,0x39,0xb0, +0x4, 0x7a,0x39,0xb0,0xe5,0x2e,0xa, 0x3b,0x9, 0xa3,0x31,0xd0,0x4c,0xaa,0x78,0xc, +0xa, 0x2c,0x9, 0xb2,0x31,0xd0,0x19,0xb3,0x31,0xd0,0x80,0x3b,0xa, 0x2c,0x9, 0xb2, +0x31,0xd0,0xf5,0x53,0xbc,0xba,0x28,0x3, 0x7a,0xa1,0x53,0x75,0x2f,0x0, 0x80,0x22, +0x9, 0x33,0x31,0xd0,0xe5,0x2f,0xa, 0x2b,0x9, 0x22,0x31,0xd0,0xbc,0x23,0x68,0xa, +0xa, 0xc, 0x9, 0x30,0x31,0xd0,0xbc,0x23,0x78,0x6, 0xe5,0x53,0x19,0xb2,0x31,0xd0, +0x5, 0x2f,0xbe,0xd1,0x2f,0x38,0xd9,0x5, 0x2e,0xbe,0xd1,0x2e,0x28,0x2, 0x61,0x16, +0xb, 0xc0,0xbc,0xdc,0x28,0x2, 0x41,0xe4,0xda,0x3b,0x22,0x6c,0xaa,0x12,0xb4,0xf9, +0x12,0x8e,0xd6,0x7e,0xb, 0xb0,0x54,0xfe,0x12,0x8e,0xd3,0x7e,0xb, 0xb0,0x54,0x7, +0x12,0x8e,0xd3,0x7e,0xb, 0xb0,0x54,0xfb,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e, +0x40,0xdb,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, 0x5, 0x22,0xa, 0x3b,0x9d, +0x32,0x2, 0x21,0x1d,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4a,0xa, 0x31, +0xb, 0x34,0x7c,0x7, 0x80,0x38,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26,0xfa,0x12, +0x8f,0x59,0x9, 0xb3,0x26,0xfa,0x12,0x8e,0xdd,0x7c,0x97,0x7e,0x70,0x2, 0xac,0x70, +0x9, 0xb3,0x26,0xfb,0x12,0x8f,0x59,0x9, 0xb3,0x26,0xfb,0x12,0x8e,0xdd,0x7c,0x87, +0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28,0xb, 0x0, 0x7e,0xb3, +0x28,0x84,0xbc,0xb0,0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x28,0x84,0xbc,0xb1,0x38,0xae, +0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22,0xbc,0x23,0x28,0x4, +0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x71, +0x22,0x90,0x60,0x9a,0x93,0xa, 0x3b,0x22,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26, +0x7e,0x51,0x27,0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x1, 0x22,0x7e,0x73,0x31,0xce, +0xbe,0x70,0x5, 0x22,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x22,0xca,0x3b, +0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0xb5,0x5, 0x30, +0xe0,0x37,0x6c,0xcc,0x80,0x27,0x12,0x8f,0x84,0x7a,0xb3,0x1f,0x70,0x9, 0xa3,0x26, +0xfb,0x7a,0xa3,0x1f,0x71,0x7f,0x7, 0x12,0xb4,0x69,0x50,0xf, 0x7f,0x7, 0x7e,0xb3, +0x1f,0x71,0x6c,0x77,0x12,0xb4,0x6c,0x50,0x2, 0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38, +0xd5,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb6, +0xc3,0xda,0x3b,0x22,0x7e,0x8, 0x32,0x2d,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x20,0xeb, +0x7e,0x71,0x24,0x74,0x2, 0xac,0x7b,0x9, 0xa3,0x26,0xfa,0x22,0xca,0x3b,0x6d,0x11, +0x7d,0x1, 0x7e,0xe3,0x2a,0x2, 0x4c,0xee,0x78,0x23,0x6c,0xff,0x80,0x1a,0x74,0x2, +0xac,0xbf,0x12,0x91,0xcd,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x35,0xb0,0x74,0x2, +0xa, 0x3f,0x19,0xb3,0x36,0x1a,0xb, 0xf0,0x12,0x56,0x6c,0x38,0xe1,0x12,0x94,0xdb, +0x7e,0x24,0x0, 0x14,0xad,0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c,0xff,0x21,0xa6, +0x74,0x9, 0xac,0xbf,0x9, 0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0x12,0x91,0xe7,0x38,0x2, +0x21,0xa4,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0xbe,0xb0,0x1, 0x78,0x2, 0x21,0x8a,0x75, +0x24,0x0, 0x21,0x7c,0x7e,0x31,0x24,0x74,0x9, 0xac,0x3b,0x9, 0xc1,0x35,0xb0,0xbc, +0xcd,0x68,0x2, 0x21,0x7a,0x7e,0xa3,0x2a,0x70,0x74,0x40,0xa4,0x9e,0x54,0x0, 0x20, +0x7e,0x34,0x60,0xd1,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0x2d,0xf5,0x49,0x21,0x35, +0xae,0xbd,0x2f,0x28,0x9, 0x12,0x91,0xde,0xbd,0x3f,0x38,0x2, 0x21,0x26,0x12,0x91, +0xde,0x9d,0x32,0x12,0x21,0x1d,0x7d,0x3, 0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49,0x25, +0x35,0xac,0x12,0x94,0xb9,0x9d,0x32,0x12,0x21,0x1d,0x2d,0x3, 0xa, 0x1c,0x9, 0xa1, +0x36,0x1a,0xbe,0xa0,0x0, 0x28,0x17,0x7e,0x30,0x2, 0xac,0x3c,0x59,0x1, 0x36,0x6, +0xa, 0x1c,0x2e,0x14,0x36,0x1a,0x7c,0xba,0x14,0x7a,0x19,0xb0,0x21,0xa4,0x74,0x2, +0xac,0xbc,0x49,0x15,0x36,0x6, 0xbe,0x14,0x0, 0x32,0x28,0x8, 0x7d,0xe1,0x2d,0xe4, +0xbd,0xe0,0x40,0x20,0xbe,0x14,0x0, 0x32,0x28,0x8, 0xbe,0x4, 0x0, 0x32,0x28,0x2, +0x80,0x72,0x7d,0xe1,0x2e,0xe4,0x0, 0x32,0xbd,0xe0,0x50,0x8, 0xbe,0x14,0x0, 0x32, +0x28,0x2, 0x80,0x60,0xbe,0x4, 0x0, 0xa0,0x28,0x56,0xa, 0x1d,0x9, 0xb1,0x29,0xbc, +0x70,0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, 0xa, 0x1d,0x19,0xb1,0x29,0xbc,0x74,0x3, +0xa, 0x1c,0x19,0xb1,0x29,0xc6,0xbe,0xe0,0x0, 0x28,0x69,0x1b,0xe0,0x7e,0x70,0x9, +0xac,0x7f,0x2e,0x34,0x28,0xae,0x7e,0x14,0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0x7e, +0x70,0x9, 0xac,0x7e,0x12,0x94,0xb1,0xac,0x3f,0x12,0x91,0xd5,0x7e,0x34,0x1f,0x34, +0x7e,0x30,0x9, 0xac,0x3e,0x12,0x91,0xd5,0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, +0x74,0x2, 0xac,0xbc,0x59,0x5, 0x36,0x6, 0x80,0x2a,0x5, 0x24,0x90,0x60,0x99,0xe4, +0x93,0xbe,0xb1,0x24,0x28,0x2, 0x1, 0x64,0x80,0x1a,0x6d,0x11,0x74,0x2, 0xac,0xbd, +0x12,0x91,0xcd,0x7e,0x30,0x9, 0xac,0x3d,0x19,0xa1,0x35,0xb0,0x74,0x2, 0xa, 0x1d, +0x19,0xb1,0x36,0x1a,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x1, 0x40,0xe4,0x7a,0xb3,0x16, +0x92,0x90,0x60,0x99,0x12,0x92,0xb3,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x35, +0xac,0x12,0x20,0xc6,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, 0xda,0x3b,0x22,0x59,0x15,0x36, +0x6, 0x7e,0xa0,0xff,0x22,0x2e,0x14,0x28,0xae,0x74,0x9, 0x2, 0x1f,0x8c,0x74,0x9, +0xac,0xbf,0x49,0x35,0x28,0xb0,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbd,0x22,0xca, +0x3b,0x7c,0xfb,0x6c,0xee,0x80,0x65,0x6c,0xdd,0x80,0x16,0x74,0x9, 0xac,0xbd,0x9, +0x65,0x29,0x66,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb2,0xbc,0x67,0x68,0x7, 0xb, +0xd0,0x12,0x91,0xe7,0x38,0xe5,0x12,0x91,0xe7,0x28,0x45,0x74,0x9, 0xac,0xbd,0x9, +0xc5,0x29,0x66,0x12,0x3b,0xa7,0x74,0x9, 0xac,0xbd,0x12,0x94,0xce,0x9d,0x32,0x12, +0x21,0x1d,0x2d,0x31,0x7a,0x35,0x24,0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, +0x6d,0x33,0x74,0x2, 0xac,0xbc,0x59,0x35,0x35,0x74,0x59,0x35,0x35,0x97,0x7e,0x35, +0x24,0x7c,0xbd,0x7c,0x5e,0x7c,0x4c,0x12,0x0, 0x6e,0xb, 0xe0,0xbc,0xfe,0x38,0x97, +0xda,0x3b,0x22,0xca,0x79,0x7e,0xf3,0x2a,0x2, 0x7e,0xe3,0x2a,0x3, 0x7c,0xbf,0x7c, +0x7e,0x12,0x92,0xba,0x7c,0xbf,0x12,0x93,0x54,0x4c,0xee,0x78,0x14,0x12,0x92,0xaf, +0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x62,0x12,0x20,0xc6,0x1b,0xfd,0x80, +0xb, 0x7e,0xb3,0x2a,0x9, 0x70,0x5, 0x7c,0xbf,0x12,0x91,0xef,0x7c,0xbf,0x12,0x95, +0x13,0xbe,0xf0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x2a,0xb, 0xda,0x79,0x22,0x90, +0x60,0x99,0xe4,0x93,0x7c,0xab,0x74,0x9, 0xa4,0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf, +0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3,0x2a,0x7, 0xe4,0x7a,0xb3, +0x2a,0x9, 0x7a,0xb3,0x2a,0xa, 0x2, 0x93,0x2f,0xa5,0xbe,0x0, 0x1d,0x6c,0xaa,0x80, +0xe, 0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x62,0x29,0x66,0xb, 0xa0,0x12, +0x56,0x5d,0x38,0xed,0x74,0x1, 0x7a,0xb3,0x2a,0x6, 0x6c,0xaa,0x80,0x20,0x7e,0x30, +0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0x93,0x23,0x1b,0x18,0x20,0x7e,0x30,0x9, +0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0x93,0x23,0x1b,0x18,0x20,0xb, 0xa0,0xbc,0x7a, +0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22,0x12, +0x93,0x48,0x7e,0x8, 0x35,0x97,0xe4,0x12,0x20,0xeb,0x90,0x60,0x99,0x12,0x93,0x4c, +0x7e,0x8, 0x35,0x74,0xe4,0x2, 0x20,0xeb,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74, +0x2, 0xac,0x7b,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x60,0x99,0xe4,0x93,0x7c, +0xfb,0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1f,0x38, +0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x34,0x74,0x9, 0xac,0xb1, +0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d,0x12, +0x94,0xa7,0x7c,0x7d,0x7c,0x6f,0x12,0x94,0xa7,0x6c,0x0, 0x80,0x39,0x6c,0xee,0x80, +0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38,0x74,0x9, 0xac,0xb0,0x9, 0x75,0x28, +0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x15,0x7e, +0x70,0x9, 0xac,0x70,0x12,0x94,0xb1,0xac,0x31,0x2e,0x14,0x1f,0x34,0x74,0x9, 0x12, +0x1f,0x8c,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xc3,0x74,0x9, 0xac,0xbf,0xca,0x59, +0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12,0x20,0xc6,0x1b,0xfd,0xda,0x79,0xda, +0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0x81,0x8d,0x7c,0x57,0x81,0x85, +0x7e,0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66,0x7c,0x98,0x7e,0xd0,0x9, 0xac,0xd5, +0x9, 0xb6,0x28,0xb2,0xbc,0xb9,0x78,0x6b,0xbe,0x90,0xff,0x68,0x66,0x12,0x94,0x9d, +0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x29,0xbc,0x7e,0xf0,0x9, 0x70,0xc, 0xac, +0xf5,0x7d,0x97,0x2e,0x94,0x28,0xae,0x6d,0x88,0x80,0xa, 0xac,0xf6,0x7d,0x97,0x2e, +0x94,0x29,0x62,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x94,0x9d,0x1b,0x7a,0xd0,0x69,0xf4, +0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6,0x0, 0x2, 0x7e, +0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb3,0x12,0x94,0x9d,0x39,0x87,0x0, 0x5, 0x7e, +0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x28,0xb4,0x12,0x94,0x9d,0x39,0x87,0x0, 0x6, 0xb, +0xa0,0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0x81,0x0, 0xb, 0x60,0x90,0x60,0x99, +0xe4,0x93,0xbc,0xb6,0x28,0x2, 0x61,0xfc,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, +0xac,0xfa,0x7f,0x70,0x2d,0xf7,0x22,0x7e,0x8, 0x1f,0x34,0x12,0x93,0xf2,0x7c,0x1b, +0x22,0x2e,0x34,0x28,0xae,0x7e,0x30,0x9, 0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x28, +0xae,0x22,0x7e,0xb3,0x38,0x1b,0x70,0x3, 0x12,0x8f,0xfc,0x2, 0x92,0x63,0x49,0x25, +0x29,0x62,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xae,0x22,0x7e,0x73,0x2a,0x3, 0xbe, +0x73,0x2a,0x2, 0x78,0x13,0x12,0x67,0xe0,0x40,0xe, 0x7e,0x37,0x35,0x88,0xbe,0x34, +0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, 0x7e,0x37,0x35,0x88,0x1e,0x34,0x7a,0x37, +0x35,0x88,0x7e,0xb3,0x2a,0x2, 0x70,0x6, 0x6d,0x33,0x7a,0x37,0x35,0x88,0x7e,0x37, +0x35,0x88,0x22,0x6c,0xaa,0x80,0x49,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x62, +0x12,0x25,0x55,0x59,0x32,0x28,0xae,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x64, +0x12,0x25,0x55,0x59,0x32,0x28,0xb0,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x66, +0x19,0xb4,0x28,0xb2,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x67,0x19,0xb4,0x28, +0xb3,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x68,0x19,0xb4,0x28,0xb4,0xb, 0xa0, +0x12,0x56,0x5d,0x38,0xb2,0x22,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c,0x22,0x80,0x45, +0x74,0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e,0xa0,0x1, 0x6c, +0x99,0x80,0x2c,0xbc,0x92,0x68,0x26,0x7e,0x70,0x2, 0xac,0x79,0x9, 0x83,0x26,0xfa, +0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, 0x31,0x12,0x5a,0xe6,0x18,0xb, 0xa, 0x2f,0xa, +0x30,0x12,0x5a,0xe6,0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc, +0x39,0x38,0xd0,0xb, 0x20,0xbc,0x32,0x38,0xb7,0x7e,0xb3,0x36,0x24,0xbe,0xb0,0x0, +0x28,0x12,0x14,0x7a,0xb3,0x36,0x24,0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c, +0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x37,0xd6,0x70,0x58,0x7e,0xb3,0x39,0xf5,0x70,0x52, +0x7e,0xb3,0x37,0x5a,0x70,0x4c,0x7e,0x37,0x38,0xe7,0xbe,0x34,0x0, 0x14,0x50,0x42, +0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x28,0x84,0xbe,0xb0, +0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x26,0x85,0xbe,0xb0,0x3, 0x50, +0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x26,0xf6,0xbe,0xb0, +0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7,0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3, +0x36,0x24,0xda,0xf8,0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x35,0x8a,0x6c,0x33, +0x80,0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10,0x1, 0x6c,0x0, +0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93,0x26,0xfb,0xa, +0x29,0xa, 0x32,0x12,0x5a,0xe6,0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74, +0x2, 0x7a,0xb3,0x35,0x8a,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc, +0xa3,0x38,0xbf,0x2, 0x95,0x66,0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31, +0xa, 0x4a,0x9, 0x74,0x35,0x8b,0xbe,0x73,0x35,0x95,0x50,0xe, 0x7d,0x24,0x2e,0x24, +0x35,0x8b,0x7c,0xb7,0x4, 0x7a,0x29,0xb0,0xd3,0x22,0xbe,0x73,0x35,0x95,0x40,0x9, +0xbe,0x70,0xff,0x68,0x4, 0xe4,0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4,0x35,0x8b,0x80, +0x17,0xa, 0x3a,0x9, 0xb3,0x35,0x8b,0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x35, +0x8b,0xd3,0x22,0xe4,0x19,0xb3,0x35,0x8b,0xc3,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3, +0x7e,0x17,0x2a,0x62,0xbd,0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22, +0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x1f,0x5, 0xbe,0x34,0x0, 0x10,0x50,0x4, 0x7e, +0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf,0x49,0x25,0x35,0x97,0xbd,0x2f,0x28,0x6, 0x49, +0x35,0x35,0x74,0x80,0x4, 0x59,0x35,0x35,0x74,0x59,0xf5,0x35,0x97,0xbe,0x34,0x1, +0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, 0xda,0xf8,0x22,0xca,0xf8,0x6d,0xcc,0x7e,0xd4, +0x0, 0x8, 0x7e,0xa3,0x28,0x84,0x4c,0xaa,0x78,0x16,0x7a,0xc5,0x1b,0xc2,0xa, 0xc2, +0xb, 0x7e,0x8, 0x36,0x51,0x7e,0x34,0x0, 0x3, 0x74,0xff,0x12,0x20,0xeb,0xe1,0xf0, +0xbe,0xa0,0x2, 0x28,0x2, 0xe1,0xe6,0xbe,0xa0,0x2, 0x78,0x29,0x7e,0x73,0x26,0xfc, +0xa, 0x27,0x7e,0x73,0x26,0xfa,0x12,0x37,0xb, 0xbe,0x34,0x0, 0x5, 0x58,0x16,0x7e, +0x73,0x26,0xfd,0xa, 0x27,0x7e,0x73,0x26,0xfb,0x12,0x37,0xb, 0xbe,0x34,0x0, 0x5, +0x58,0x3, 0x2, 0x98,0xb, 0x6c,0xff,0x80,0x56,0x7c,0xbf,0x12,0xb5,0x4d,0x1a,0x4b, +0x7c,0xbf,0x12,0x38,0x9e,0x7d,0xc3,0xbe,0xc4,0x2, 0x58,0x58,0x4, 0x7e,0xd4,0x0, +0x7, 0x7d,0x5d,0x3e,0x54,0xbd,0x54,0x58,0x4, 0xd2,0xb, 0x80,0xa, 0x7d,0x5d,0xe, +0x54,0xbd,0x54,0x48,0x2, 0xc2,0xb, 0x20,0xb, 0x4, 0xbd,0xd4,0x58,0xc, 0x7e,0x34, +0x1, 0x90,0x7a,0x35,0x1b,0x12,0xc8,0x9f,0x80,0x26,0x7d,0x5d,0xe, 0x54,0xbd,0x54, +0x58,0x5, 0x12,0xc8,0x9f,0x80,0x6, 0x74,0xff,0x7a,0xb3,0x36,0x51,0xb, 0xf0,0x12, +0x7d,0xb1,0x38,0xa5,0x80,0xa, 0x7e,0x35,0x1b,0x9e,0x34,0x0, 0x5, 0x7a,0x35,0x1b, +0x7e,0x35,0x1b,0xbe,0x34,0x0, 0x0, 0x8, 0x12,0x20,0xa, 0x8, 0xd2,0xa, 0x74,0x14, +0x7a,0xb3,0x35,0x72,0x1b,0x34,0x7a,0x35,0x1b,0x80,0x7, 0x6d,0x33,0x7a,0x35,0x1b, +0xc2,0xa, 0xda,0xf8,0x22,0x7c,0xab,0xa5,0xbf,0x0, 0xc, 0x7e,0xb3,0x36,0xcc,0x7a, +0xb3,0x36,0xcd,0x7a,0xa3,0x36,0xcc,0x7e,0xb3,0x36,0xcd,0x60,0x4, 0x74,0x8, 0x80, +0xd, 0x7e,0xb3,0x28,0x84,0x70,0xb, 0x7e,0xb3,0x36,0xce,0x60,0x5, 0x14,0x7a,0xb3, +0x36,0xce,0x7e,0x73,0x36,0xce,0xbe,0x70,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22, +0xe4,0x7a,0xb3,0x36,0xcf,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0x48,0x60, +0x5, 0xe4,0x7a,0xb3,0x37,0x4a,0x22,0xca,0x3b,0x7e,0xb3,0x2a,0x74,0xf5,0x27,0x12, +0x99,0x17,0x50,0x2, 0x21,0xc, 0x6d,0x33,0x9e,0x37,0x2a,0x4f,0x3e,0x34,0xbe,0x37, +0x7, 0xf8,0x8, 0x2, 0x21,0xc, 0x7e,0xb3,0x16,0x92,0x60,0x2, 0x21,0xc, 0x7e,0xb3, +0x28,0xa8,0xb4,0x1, 0x68,0x7e,0x77,0x2a,0x51,0x7e,0x67,0x2a,0x53,0x75,0x24,0x0, +0x80,0x56,0xe5,0x24,0x12,0x37,0x3f,0x60,0x4d,0x12,0x99,0xf, 0x12,0x9f,0xe8,0x7e, +0xb3,0x2a,0x3, 0xb4,0x1, 0xe, 0x90,0x60,0xab,0xe4,0x93,0xbe,0xb1,0x26,0x78,0x4, +0xe, 0x64,0xe, 0x74,0x7e,0xa1,0x26,0x74,0x2, 0xa4,0x49,0x35,0x4, 0xfc,0xbd,0x36, +0x48,0x14,0xe5,0x25,0xa, 0x2b,0xe5,0x27,0xa, 0x3b,0x2d,0x32,0x3e,0x34,0x49,0x33, +0x4, 0xfc,0xbd,0x37,0x58,0x10,0xe5,0x24,0x6c,0x77,0x12,0x39,0x2f,0x12,0x99,0xf, +0x12,0x3f,0xb1,0x12,0x3f,0xd7,0x5, 0x24,0x12,0x9f,0xc0,0x38,0xa5,0x7e,0xb3,0x2a, +0x68,0x70,0x9, 0x7e,0xb3,0x2a,0x6b,0x70,0x3, 0x12,0x9f,0x8, 0xda,0x3b,0x22,0x7e, +0x71,0x24,0x74,0x2, 0xac,0x7b,0x22,0xa2,0x17,0x22,0x7e,0x90,0x1, 0x7e,0x94,0x61, +0xc6,0x7e,0x84,0x0, 0xff,0xb, 0x4a,0x30,0x7a,0x37,0x28,0xa1,0x7e,0xb4,0x61,0xc8, +0x7e,0xa4,0x0, 0xff,0xb, 0x5a,0x30,0x7a,0x37,0x28,0xa3,0x12,0x7f,0xcc,0xb, 0x1a, +0x20,0x7e,0x14,0x61,0x4f,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xd0,0xe4,0x7a,0xb3,0x28, +0xac,0x12,0x9a,0x84,0x7e,0x34,0xff,0xfa,0xad,0x32,0x12,0x9f,0x51,0x7d,0xc3,0xe, +0x34,0x7e,0x27,0x7, 0xfe,0xbd,0x2c,0x58,0x1c,0x7e,0xc7,0x7, 0xfc,0xbd,0xc3,0x58, +0x14,0x6d,0xcc,0x9e,0xc7,0x2a,0x5a,0xbe,0xc7,0x28,0x8e,0x8, 0x8, 0x12,0xaf,0xa2, +0x60,0x3, 0x12,0xa9,0x16,0x12,0xa9,0x25,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12, +0x7f,0xec,0x68,0x6, 0x7e,0xb3,0x39,0xf5,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80, +0x6f,0x12,0x9a,0x8b,0x28,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x30,0x14,0x5, 0xe4,0x7a, +0xb3,0x28,0xad,0x12,0xa9,0x63,0x50,0xa, 0x12,0x9a,0x84,0x12,0x9a,0xa1,0x7c,0x9b, +0x80,0x17,0x7e,0xb3,0x26,0x84,0x70,0x11,0x7e,0xb3,0x26,0x85,0x70,0xb, 0x12,0x9a, +0x8b,0x28,0x6, 0x7e,0x90,0x3, 0x12,0x9a,0x84,0x7e,0xc7,0x7, 0xfa,0xbe,0xc4,0x5, +0xdc,0x8, 0x17,0x12,0x9a,0x8b,0x28,0x12,0x6d,0xcc,0x9d,0xcd,0xbe,0xc7,0x28,0x8e, +0x58,0x8, 0x12,0x9a,0x93,0xe4,0x7a,0xb3,0x28,0xad,0xa, 0x29,0xb, 0x4a,0x30,0xad, +0x32,0x7a,0x37,0x28,0xa1,0xa, 0x29,0xb, 0x5a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa3, +0x12,0x99,0x17,0x50,0xd, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x7f,0xa4,0x28,0x3, 0x12, +0x9a,0x93,0x7e,0xc7,0x28,0x8a,0xbd,0xcd,0x8, 0x1f,0x7e,0x24,0x0, 0x2, 0x7d,0x3d, +0x12,0x1e,0xb9,0x6e,0x34,0xff,0xff,0xb, 0x34,0xbe,0x37,0x28,0x8e,0x58,0xa, 0x12, +0x99,0x17,0x50,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x9b,0xd, 0xb4,0x1, 0x5, 0xe4, +0x7a,0xb3,0x28,0xad,0x12,0xa8,0x7d,0x7e,0xb3,0x2f,0xa9,0xbe,0xb0,0x0, 0x28,0x23, +0x14,0x7a,0xb3,0x2f,0xa9,0x70,0x1c,0xe4,0x7a,0xb3,0x28,0xad,0x74,0x1, 0x7a,0xb3, +0x28,0xac,0xe4,0x7a,0xb3,0x16,0x91,0x7a,0xb3,0x16,0x90,0x7a,0xb3,0x28,0x84,0x7a, +0xb3,0x26,0x83,0x22,0x74,0x1, 0x7a,0xb3,0x28,0xad,0x22,0x7e,0x83,0x28,0x84,0xbe, +0x80,0x0, 0x22,0xe4,0x7a,0xb3,0x2f,0xa9,0x7a,0xb3,0x28,0xac,0x74,0x2, 0x2, 0x33, +0x6f,0x7e,0xa0,0x1, 0x7e,0x47,0x7, 0xf8,0x12,0x7f,0xcc,0xb, 0x1a,0x0, 0x7e,0x34, +0xff,0xfa,0xad,0x30,0x7e,0x14,0x0, 0x2, 0x12,0x9b,0x5, 0x8, 0x12,0x7e,0xb3,0x28, +0xac,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e, +0x34,0xff,0xfb,0xad,0x30,0x12,0x9b,0x5, 0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x23,0x7e, +0x34,0xff,0xfc,0xad,0x30,0x12,0x9b,0x5, 0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x13,0x7e, +0x34,0xff,0xfd,0xad,0x30,0x12,0x9b,0x5, 0x8, 0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e, +0xa0,0x1, 0x7c,0xba,0x22,0x7d,0x21,0x12,0x1e,0xb9,0xbd,0x34,0x22,0xca,0x3b,0x12, +0x9f,0x58,0x38,0x2, 0x61,0xd0,0x7e,0xc3,0x2f,0xac,0x4c,0xcc,0x78,0x3d,0x7a,0xb3, +0x2f,0xac,0xe4,0x7a,0xb3,0x2f,0xae,0x6c,0xaa,0x80,0x26,0x12,0x9b,0xdb,0x7e,0x70, +0x2, 0xac,0x7a,0x9, 0xd3,0x26,0xfa,0x9, 0xe3,0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4, +0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12,0x9b,0xe5,0x59,0x34,0x0, 0x2, 0xb, +0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xd2,0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80, +0x31,0x12,0x9b,0xdb,0x7e,0x49,0xd0,0x9, 0xe4,0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70, +0x4, 0x1b,0xf0,0x80,0x1b,0x12,0x9b,0xe5,0x7d,0x23,0x49,0x34,0x0, 0x2, 0x12,0x67, +0xd8,0xbe,0xf4,0x0, 0x23,0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x5d,0x1, +0xb, 0xa0,0xbc,0xfa,0x38,0xcb,0x4c,0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x2f,0xae, +0xbe,0x70,0x4, 0x40,0x22,0x6c,0xaa,0x80,0xe, 0x12,0x9b,0xdb,0x9, 0xb4,0x0, 0x8, +0xbe,0xb0,0x5, 0x68,0x6, 0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75, +0x5d,0x0, 0x12,0x9b,0xec,0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3,0x2f,0xae,0x80,0x6, +0x12,0x9b,0xec,0x75,0x5d,0x0, 0xe5,0x5d,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a, +0x2e,0x44,0x2f,0xaf,0x22,0x7c,0xbd,0x7c,0x7e,0x2, 0x35,0xb5,0xe4,0x7a,0xb3,0x2f, +0xad,0x7a,0xb3,0x2f,0xac,0x7a,0xb3,0x2f,0xae,0x22,0x12,0xad,0x5, 0x60,0x17,0x12, +0x9a,0x84,0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1,0x7e,0x37,0x28,0xa3, +0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0x12,0x7e,0x45,0x12,0x99,0x1a,0x12,0x9c,0x74, +0x12,0x9b,0xfa,0x7e,0xb3,0x37,0xf0,0xb4,0x1, 0x1e,0x7e,0x34,0x61,0xc6,0x12,0x7f, +0xac,0x7e,0x24,0x0, 0x5, 0xad,0x12,0x7a,0x17,0x28,0xa1,0x7e,0x14,0x61,0xc8,0x12, +0x3e,0x8b,0xad,0x32,0x7a,0x37,0x28,0xa3,0x7e,0xb3,0x39,0xf8,0x60,0x7, 0x14,0x7a, +0xb3,0x39,0xf8,0x80,0x6, 0x7e,0xb3,0x28,0xac,0x60,0x9, 0x12,0x67,0x8d,0x12,0x9c, +0xf0,0x12,0xb9,0x9d,0x7e,0xb3,0x28,0xad,0x60,0x9, 0x12,0xbe,0xfb,0x12,0x9f,0x60, +0x2, 0x9d,0x73,0x22,0xc2,0x0, 0x12,0x5b,0xc3,0x50,0x4b,0x6c,0xaa,0x80,0x39,0x7e, +0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26,0xfb,0xbe,0x70,0x0, 0x28, +0x25,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27,0xbd,0x21,0x58,0x17,0xbe, +0x60,0x0, 0x28,0x12,0x7e,0xb3,0x2a,0x70,0x1e,0xb0,0xa, 0x1b,0xa, 0x26,0xbd,0x21, +0x58,0x4, 0xd2,0x0, 0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84,0xbc,0xba,0x38,0xbf, +0x20,0x0, 0x3, 0x12,0x9a,0x84,0x30,0x1a,0x23,0x5, 0x5e,0xe5,0x5e,0xbe,0xb0,0x50, +0x50,0x16,0x7e,0x34,0x61,0xc6,0x12,0x23,0xb7,0x3e,0x34,0x12,0x9f,0xc8,0x12,0x23, +0xb7,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0xc2,0x1a,0x80,0x0, 0x75,0x5e,0x0, 0x22, +0x12,0x9d,0x30,0x6d,0x33,0x7a,0x37,0x37,0xc6,0x6c,0xaa,0x80,0x5, 0x12,0x9d,0xc1, +0xb, 0xa0,0x12,0x9d,0x6b,0x38,0xf6,0xe4,0x7a,0xb3,0x37,0x5b,0x22,0x7a,0xb3,0x2b, +0xf, 0x12,0x4f,0x61,0x30,0x10,0xc, 0xc2,0x10,0x12,0xac,0xf5,0x30,0x0, 0x4, 0xe4, +0x12,0xa, 0x66,0x30,0x0, 0x9, 0x12,0x9e,0xd6,0x12,0x9e,0x19,0x2, 0x9c,0xf0,0x22, +0x7e,0x37,0x39,0xbc,0x12,0x25,0x55,0x7a,0x37,0x37,0xc6,0x6c,0xaa,0x80,0x23,0x12, +0x9d,0x6b,0x28,0x26,0xa, 0x4a,0x9, 0x64,0x37,0x5f,0xbc,0x6b,0x50,0x12,0x7e,0x50, +0x2, 0xac,0x5a,0x49,0x42,0x39,0xb6,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x37,0x69, +0xb, 0xa0,0x7e,0xb3,0x37,0x5c,0xbc,0xba,0x38,0xd5,0x22,0x90,0x61,0xcb,0xe4,0x93, +0xbc,0xba,0x22,0x6c,0xaa,0x80,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x12,0x9f,0xdb,0xbe, +0x34,0x3, 0xe8,0x8, 0x5, 0x12,0x9d,0xc1,0x80,0x2f,0x7e,0x50,0xc, 0xac,0x5a,0x49, +0x32,0x37,0x6d,0x49,0x12,0x37,0x69,0xbd,0x13,0x28,0xf, 0x7d,0x2, 0x2e,0x4, 0x37, +0x6d,0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, 0xbe,0x34,0x0, 0x2, 0x28,0x9, +0x2e,0x24,0x37,0x6d,0x1b,0x35,0x1b,0x28,0x30,0xb, 0xa0,0x12,0x9d,0x6b,0x38,0xb7, +0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0x69,0x59,0x32,0x37,0x6d,0x22,0x7e, +0xb3,0x37,0x4f,0x60,0x6, 0x14,0x7a,0xb3,0x37,0x4f,0x22,0x12,0x9d,0x30,0x90,0x61, +0xcb,0xe4,0x93,0xbe,0xb0,0x4, 0x28,0x3, 0x12,0x9e,0x19,0x7e,0xb3,0x37,0xd6,0x70, +0xe, 0x7e,0xb3,0x39,0xf9,0xb4,0x1, 0x7, 0xe4,0x12,0x4f,0x95,0x12,0x9f,0xd1,0x12, +0x3f,0x67,0x12,0xab,0x61,0x7e,0xa3,0x37,0xd6,0x7a,0xa3,0x39,0xf9,0xbe,0xb0,0xff, +0x68,0x3, 0x2, 0x4f,0x95,0x22,0x12,0x9e,0xcc,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c, +0xeb,0x6c,0xff,0x7e,0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xc0,0x7e,0x73, +0x38,0xb7,0xa, 0xb7,0x7e,0xb3,0x2b,0x10,0xf5,0x35,0x12,0x9f,0xb8,0xbe,0xd0,0x4, +0x38,0x5, 0xe4,0x7a,0xb3,0x37,0x5b,0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d,0xac,0x75, +0x34,0x0, 0x7e,0xa3,0x37,0x5b,0xbc,0xad,0x40,0x2, 0x80,0x19,0xbe,0xa0,0x0, 0x28, +0x19,0x74,0x5, 0xa4,0x9, 0x75,0x26,0x33,0xbc,0x7e,0x78,0xe, 0x7c,0xbd,0x14,0xbe, +0xb3,0x37,0x5b,0x78,0x5, 0xe4,0x7a,0xb3,0x37,0x5b,0x7e,0xc3,0x37,0x5b,0x80,0x41, +0x7e,0xb3,0x37,0x5b,0x4, 0x7a,0xb3,0x37,0x5b,0x7e,0x90,0x5, 0xac,0x9c,0x9, 0xa4, +0x26,0x33,0xbc,0xae,0x68,0x29,0xe5,0x34,0xa, 0xdb,0x19,0xcd,0x37,0x5f,0xa, 0x9a, +0xad,0x9b,0x2d,0x9c,0x7e,0xa1,0x34,0x7c,0xba,0x4, 0xf5,0x34,0x7c,0xba,0x7d,0x39, +0x7d,0x2a,0x7e,0x31,0x35,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x6, 0xb, +0xc0,0xbc,0xdc,0x38,0xbb,0x7a,0xf3,0x37,0x5c,0xda,0x3b,0x22,0x12,0x9e,0xd6,0x74, +0x1, 0x7a,0xb3,0x37,0x4f,0x22,0x7e,0x8, 0x37,0x63,0x7e,0x34,0x0, 0x60,0xe4,0x12, +0x20,0xeb,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37, +0x65,0x59,0x43,0x37,0x6d,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8,0x7e,0x8, 0x37,0x51, +0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xeb,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12, +0x9f,0x58,0x28,0x35,0x6d,0x22,0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x9f, +0x51,0xbe,0x37,0x7, 0xfa,0x8, 0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, +0x70,0x17,0x7e,0xb3,0x37,0xf2,0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x5c,0xe5,0x5c,0xbe, +0xb0,0x10,0x28,0x5, 0xd2,0x15,0x75,0x5c,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x5c,0x0, +0x22,0x7e,0x24,0x0, 0x2, 0x2, 0x1e,0xb9,0x7e,0xb3,0x28,0x84,0xbe,0xb0,0x0, 0x22, +0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d,0xac,0x54,0x7e,0x17,0x28,0xa1,0x12,0x9f, +0xb1,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x39,0xc3,0x2d,0xf4,0xb, +0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x8, 0xa, 0xb, 0xf8,0x50,0x9d, +0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44, +0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5, +0x22,0xa9,0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x90,0x61,0xcb,0xe4,0x93,0x7c,0xdb,0x22, +0x7e,0x73,0x28,0x84,0xbe,0x71,0x24,0x22,0x7a,0x37,0x28,0xa1,0x7e,0x34,0x61,0xc8, +0x22,0xe4,0x7a,0xb3,0x37,0x52,0x7a,0xb3,0x37,0x5a,0x22,0x49,0x23,0x37,0x6d,0x49, +0x33,0x37,0x69,0x9d,0x32,0x2, 0x21,0x1d,0x9, 0xb3,0x26,0xfa,0xf5,0x25,0x9, 0xb3, +0x26,0xfb,0xf5,0x26,0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12,0x38,0x9e, +0xbe,0x34,0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78, +0x38,0xe9,0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0x7e,0x63,0x2a,0x6e,0x90, +0x60,0xa7,0xe4,0x93,0x60,0x6c,0xc2,0x16,0x6c,0x33,0x80,0x56,0x90,0x60,0xaa,0xe4, +0x93,0x70,0x13,0x7c,0x96,0xac,0x93,0x90,0x60,0xab,0xe4,0x93,0xa, 0x5b,0x1b,0x54, +0x2d,0x45,0x7d,0xd4,0xb, 0xd4,0x7d,0x54,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x2d,0xf5, +0xb, 0x7a,0x50,0xbe,0x57,0x2a,0x5a,0x8, 0x27,0x7c,0xb3,0x12,0x5e,0xf0,0x50,0x20, +0x7d,0x5d,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x7f,0x57,0x2d,0xb5,0xb, 0x5a,0xc0,0x7d, +0x54,0x3e,0x54,0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x5c,0x8, 0x4, 0xd2,0x16,0x80,0xa, +0xb, 0x30,0x7e,0x73,0x2a,0x75,0xbc,0x73,0x38,0xa2,0x30,0x16,0x5, 0xd2,0x0, 0x2, +0xa0,0x93,0x22,0x12,0xa0,0xd5,0x60,0x34,0x6c,0x22,0x80,0x28,0x7c,0xb2,0x12,0x5e, +0xf0,0x50,0x1f,0x7c,0xb2,0x12,0x5d,0xc5,0x3e,0x34,0x7e,0x7f,0x13,0x8a,0x2d,0xf3, +0xb, 0x7a,0x30,0x12,0xa0,0xcd,0x59,0x35,0x39,0xd2,0x30,0x0, 0x5, 0x6d,0x33,0x1b, +0x7a,0x30,0xb, 0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72,0x38,0xd0,0x22,0x7c,0xa3,0xb, +0x30,0x74,0x2, 0xa4,0x22,0x6c,0x33,0x90,0x60,0xa7,0xe4,0x93,0x22,0xca,0xd8,0xca, +0x79,0x7c,0xfb,0x7f,0x70,0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x22,0xff,0x7e, +0x24,0x0, 0xff,0x7e,0x14,0x1f,0x34,0x74,0xc, 0x12,0x1f,0xad,0x6d,0x11,0x7e,0x4, +0x7f,0xff,0x6c,0xee,0x80,0x13,0x12,0xa1,0xf1,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d, +0xdc,0xbd,0xc, 0x28,0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, +0x1e,0x58,0xa, 0x7e,0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0x21,0xe2,0xbe,0xd4,0x4, +0xb0,0x8, 0x2, 0xd2,0x0, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1f,0x34,0xbd, +0x4d,0x58,0x6, 0x49,0xd5,0x1f,0x36,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7, +0xbe,0xe0,0x3, 0x78,0x4, 0x6d,0x33,0x21,0xe2,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, +0x7d,0xd0,0x9f,0x55,0x6c,0xee,0x80,0xb, 0x12,0xa1,0xf1,0x1a,0x26,0x1a,0x24,0x2f, +0x51,0xb, 0xe0,0xbc,0xfe,0x38,0xf1,0xa, 0x1f,0x12,0xa1,0xe7,0x9f,0x55,0x6c,0xee, +0x80,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x90,0x7d,0x39,0x12, +0x21,0x1d,0x7d,0xc3,0xbd,0x1c,0x28,0xa, 0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51, +0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xda,0x6d,0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, +0x1d,0x12,0xa1,0xe7,0xbd,0x1d,0x8, 0x4, 0x7d,0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, +0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c,0xee,0x80,0x12,0x74,0x2, 0xac,0xbe,0x7f,0x17, +0x2d,0x35,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc,0xfe,0x38,0xea, +0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x6d,0x0, 0x7f,0x15,0x12,0x1f,0x58,0x7d,0x13, +0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x21,0x1d,0xca, +0xf8,0x7f,0x71,0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x80,0xc2,0x0, 0x6d,0x44,0x80,0x32, +0x12,0xa2,0xa0,0x12,0xa1,0xf9,0xbd,0x3d,0x48,0x26,0x12,0xa2,0xa0,0xb, 0x1a,0x30, +0xbe,0x34,0x0, 0x0, 0x8, 0x4, 0xd2,0x0, 0x80,0x9, 0x12,0x21,0x1d,0xbd,0x3d,0x68, +0x2, 0xc2,0x0, 0x7d,0x34,0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x12,0xa1,0xf9,0x7d,0xd3, +0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4,0x38,0xc7,0x30,0x0, 0xc, 0x7e,0xf0,0x7f,0x80, +0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, 0xe, 0x34, +0x14,0x78,0xfb,0xa, 0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34,0x7a,0x1b, +0xa0,0x6d,0x44,0x80,0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30, +0x7f,0x60,0x2e,0xd5,0x34,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0x7c, +0xb7,0x12,0xa3,0xed,0xb, 0x44,0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda,0xf8,0x22, +0x7d,0xc4,0x3e,0xc4,0x7f,0x17,0x2d,0x3c,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c,0xcb, +0x7e,0xb3,0x2b,0x1d,0xf5,0x32,0x7e,0xb3,0x2b,0xf, 0xf5,0x33,0x7e,0xd3,0x2b,0x14, +0x7e,0xe3,0x2b,0x1f,0x7e,0xf3,0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18, +0x34,0x0, 0x7e,0x8, 0x24,0xf2,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca, +0x39,0x7e,0x18,0x3, 0x71,0x7e,0x8, 0x25,0x2a,0x12,0x20,0xc6,0x1b,0xfd,0x7c,0xbc, +0x12,0xa4,0x1b,0x74,0x1, 0x7a,0xb3,0x2b,0x1d,0x74,0x5, 0xac,0xbc,0x12,0x4f,0xe7, +0x74,0x5, 0xac,0xbc,0x12,0x4f,0xd5,0x74,0x5, 0xac,0xbc,0x12,0x4f,0xde,0x74,0x5, +0xac,0xbc,0x9, 0x75,0x26,0x37,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62, +0xd2,0x10,0xc2,0x0, 0x12,0x67,0xe8,0x12,0x9d,0xd, 0x12,0x4d,0x49,0x30,0xf, 0xfd, +0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x13,0x86,0x7d, +0x25,0x7e,0x4, 0xd, 0xc8,0x12,0x76,0x6a,0x12,0x87,0xf0,0x7a,0x55,0x34,0x7e,0xd, +0x2e,0x7e,0x18,0xd, 0xc8,0x12,0xa1,0xff,0x12,0xa3,0x9c,0xe5,0x32,0x7a,0xb3,0x2b, +0x1d,0xe5,0x33,0x7a,0xb3,0x2b,0xf, 0x7a,0xd3,0x2b,0x14,0x7a,0xe3,0x2b,0x1f,0x7a, +0xf3,0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x24,0xf2,0x7e,0x8, 0x34, +0x0, 0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x18,0x25,0x2a, +0x7e,0x8, 0x3, 0x71,0x12,0x20,0xc6,0x1b,0xfd,0xda,0x3b,0x22,0x90,0x60,0x93,0xe4, +0x93,0xa, 0xb, 0x7e,0x73,0x2a,0x71,0xa, 0x17,0x2d,0x10,0x7e,0xa3,0x2a,0x6e,0xa, +0x3a,0xad,0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e, +0x7f,0x39,0xc3,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x13, +0x8e,0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, 0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x34, +0x7e,0xf, 0x38,0x2a,0x7e,0x18,0x25,0xb6,0x2, 0xa1,0xff,0xa, 0x4a,0x7f,0x10,0x2d, +0x34,0x7a,0x1b,0xb0,0x22,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, +0x75,0xf5,0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6,0x12,0xa3, +0xeb,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xed,0xc2,0xc9,0x22,0xca,0xf8,0x7c,0xfb,0x7e, +0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x0, 0x61,0x6d,0x22,0x7e,0x8, 0x34, +0x0, 0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0xac,0x7f,0x2e,0x34, +0x1, 0x41,0x6d,0x22,0x7e,0x8, 0x3, 0x71,0x12,0x20,0xc6,0x1b,0xfd,0xda,0xf8,0x22, +0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x31,0x12,0x9f,0xb1,0x7e,0x1f,0x39,0xc3,0x7a,0x37, +0x24,0xfa,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x24,0xf6,0x12,0xa4,0x89,0x12,0xa4,0xc6, +0xe4,0x7a,0xb3,0x24,0xf5,0x7e,0x34,0x0, 0x20,0x7a,0x37,0x24,0xfc,0x7a,0xb3,0x24, +0xf4,0x7e,0x8, 0x24,0xf2,0x2, 0xd, 0x7, 0x22,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x24, +0xf2,0x22,0x7e,0x8, 0x24,0xf2,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x20,0xeb,0x12,0xa4, +0xc6,0x12,0xa4,0x89,0xa9,0xd1,0xcb,0x12,0x6f,0xe9,0x7a,0x37,0x24,0xf6,0x7e,0x1f, +0x39,0xc3,0x7a,0x37,0x24,0xf8,0x7e,0x1f,0x13,0x86,0x7a,0x37,0x24,0xfa,0x6d,0x33, +0x12,0xa4,0xcf,0x2, 0xd, 0x7, 0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x7a, +0x37,0x24,0xfc,0x7e,0x8, 0x24,0xf2,0x22,0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e, +0x7a,0x53,0x24,0xf3,0x7a,0x37,0x24,0xfa,0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24, +0xf5,0x7e,0x34,0x40,0x0, 0x7a,0x37,0x24,0xf6,0x7e,0x34,0x0, 0x20,0x12,0xa4,0xcf, +0x2, 0xd, 0x7, 0x12,0x87,0xdf,0x7e,0x34,0xd, 0xc8,0x7e,0xb3,0x2a,0x6d,0x12,0xa4, +0xd8,0x12,0xa5,0x1f,0x7a,0x37,0x39,0xc0,0x74,0x1, 0x7a,0xb3,0x16,0x91,0x22,0x6d, +0x33,0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xa5,0xd5,0x90,0x60, +0x92,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xa5,0x3c,0x22,0xca,0xf8,0x6d,0xee, +0x7d,0xfe,0x7e,0x83,0x2a,0x6e,0xa, 0xd8,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x2f, +0x7e,0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x18,0x7e,0x70,0x2, 0xac,0x7a,0x49,0x23,0x13, +0xfe,0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0,0x9d,0xc2,0x59,0xc3,0x13,0xc6,0xb, 0xa0, +0xbc,0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4,0x93,0x7c,0x9b,0x6d,0xdd,0x80,0x11,0x7e, +0x8, 0x13,0xfe,0x90,0x60,0x92,0xe4,0x93,0xa, 0xcb,0x1b,0xc4,0x7d,0x3c,0x7c,0x97, +0x6c,0xff,0x80,0x38,0x6c,0xaa,0x80,0x28,0xa, 0x3a,0x7d,0x23,0x2d,0x2e,0x3e,0x24, +0x49,0xc2,0x13,0xfe,0x2d,0x3d,0x3e,0x34,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xb0,0x7d, +0x3c,0x9d,0x3b,0x12,0x21,0x1d,0x7d,0xa3,0xbd,0xfa,0x58,0x2, 0x7d,0xfa,0xb, 0xa0, +0xbc,0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec,0x2d,0xdc,0xb, 0xf0,0xbc,0x9f,0x38,0xc4, +0x7d,0x3f,0xda,0xf8,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x2a,0x6e,0x90,0x60,0x93, +0xe4,0x93,0xa, 0xfb,0x7e,0xb3,0x2a,0x6d,0xa, 0xeb,0x2d,0xef,0xa, 0xff,0xad,0xfe, +0xa, 0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e,0x8, 0x13,0x8e, +0x6c,0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x39,0xc3,0x2d,0x3d, +0xb, 0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, 0x5a,0x30,0x9d, +0x3d,0x59,0x32,0x13,0xc6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, 0x7d,0x5e,0x3e, +0x54,0x7e,0xf, 0x39,0xc3,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea,0x2d,0xef,0x3e, +0xe4,0x7e,0x1f,0x39,0xc3,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, 0xac,0x7a,0x2d, +0x31,0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x21,0x1d,0x7d,0xc3,0xbd, +0x4c,0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34,0xda,0xf8,0x22, +0x7c,0xab,0x7e,0x8, 0x29,0xbc,0x12,0x56,0x5d,0x28,0x1f,0xa, 0x3a,0x7f,0x70,0x2d, +0xf3,0x7e,0x7b,0xb0,0xb4,0x2, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0, +0x74,0x3, 0x2d,0x31,0x7d,0x20,0x39,0xb1,0x0, 0xa, 0x22,0xca,0xd8,0xca,0x79,0x12, +0xa7,0x8f,0xb, 0x1a,0x40,0x90,0x61,0x35,0xe4,0x93,0x70,0x2, 0xe1,0x46,0x90,0x60, +0xa7,0xe4,0x93,0x70,0x2, 0xe1,0x46,0x6c,0xff,0xe1,0x3f,0x7e,0x70,0x9, 0xac,0x7f, +0x9, 0xe3,0x29,0xc, 0x5e,0xe0,0xf, 0x49,0xc3,0x29,0xa, 0x7e,0x14,0x60,0xd1,0x7e, +0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x2d,0x24,0xbd,0xc2,0x40,0x42,0x49,0xd3,0x29,0x8, +0x7d,0x3d,0x12,0xa7,0x54,0x7c,0xdb,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xbd,0x38,0xe, +0x7d,0x34,0x1b,0x34,0x12,0xa7,0x4b,0x7c,0xbe,0x12,0xa6,0x70,0x80,0x3f,0x7e,0x70, +0x2, 0xac,0x7d,0x2e,0x34,0x60,0xc5,0x12,0x79,0x66,0x74,0x9, 0xac,0xbf,0x59,0xd5, +0x29,0x8, 0x7e,0x34,0x60,0xcf,0x12,0x23,0xb7,0x12,0xa7,0x4b,0x80,0x1f,0xbd,0xc4, +0x40,0x1b,0x7d,0x54,0x2e,0x54,0x0, 0xa, 0xbd,0xc5,0x40,0x5, 0x7c,0xbe,0x12,0xa6, +0x70,0x7d,0xc4,0x1b,0xc4,0x74,0x9, 0xac,0xbf,0x59,0xc5,0x29,0xa, 0xb, 0xf0,0x12, +0x56,0x6c,0x28,0x2, 0xc1,0xbb,0xda,0x79,0xda,0xd8,0x22,0x74,0x9, 0xac,0xbf,0x59, +0x35,0x29,0xa, 0x22,0x6c,0xaa,0x80,0x23,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e, +0xf4,0x60,0xb1,0x12,0xa7,0x87,0xbd,0x23,0x38,0xf, 0x2e,0x14,0x60,0xb3,0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0x20,0xbd,0x23,0x50,0xb, 0xb, 0xa0,0x90,0x60,0xa7,0xe4,0x93, +0xbc,0xba,0x38,0xd4,0x7c,0xba,0x22,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0x22,0x7e, +0x34,0x61,0x43,0x7e,0x24,0x0, 0xff,0x22,0x7c,0xab,0x90,0x60,0xab,0xe4,0x93,0xbc, +0xb7,0x78,0x9, 0x7c,0xba,0x12,0x5e,0xf0,0x50,0x2, 0xd3,0x22,0xc3,0x22,0x7c,0xa7, +0x7c,0x7b,0x90,0x60,0xaa,0xe4,0x93,0x60,0x2, 0x7c,0xa7,0x90,0x60,0xab,0xe4,0x93, +0xbc,0xba,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x90,0x60,0xa7,0xe4,0x93,0x60,0x2b,0x6c, +0x33,0x80,0x1f,0x7c,0xb3,0x12,0x5e,0xf0,0x40,0x16,0x7c,0xb3,0x12,0x5d,0xc5,0x7d, +0x43,0x6d,0x55,0x7d,0x4, 0x3e,0x4, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50, +0xb, 0x30,0x7e,0x23,0x2a,0x75,0xbc,0x23,0x38,0xd9,0x22,0x12,0xa8,0xd, 0x7e,0x14, +0x62,0xd, 0x12,0x3f,0xcd,0x28,0x3, 0xd2,0x17,0x22,0xc2,0x17,0x22,0x6d,0x11,0xe4, +0x12,0x0, 0x1e,0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x39,0xdd, +0x2d,0xf0,0x69,0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d,0x32,0x12,0x21,0x1d,0xbd, +0x31,0x28,0x16,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x39,0xdd,0x2d,0x13,0x69,0x20, +0x1, 0x0, 0x69,0x30,0x0, 0x80,0x12,0x3b,0xb3,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f, +0x39,0xdd,0x2d,0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14, +0x7f,0xff,0x69,0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff, +0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba,0x38,0x9d,0x7d,0x31,0x22,0x7e,0x60,0x4, +0x7e,0x27,0x39,0xee,0xbe,0x24,0x3, 0xe8,0x28,0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x28, +0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x2f,0xaa,0xbc,0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x28, +0xad,0x12,0x9a,0x93,0x7e,0xb3,0x2f,0xaa,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a, +0xb3,0x2f,0xaa,0x7e,0xb3,0x28,0xad,0xb4,0x1, 0x17,0x7e,0xa3,0x2f,0xab,0xbe,0xa0, +0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad,0x7c,0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80, +0x1, 0xe4,0x7a,0xb3,0x2f,0xab,0x22,0x6c,0xaa,0x80,0x26,0x7e,0x50,0x2, 0xac,0x5a, +0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, 0x2d,0x31,0x59,0x32,0x5, 0xf8,0x30,0x6, +0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, 0x76,0x2d,0x31,0x59,0x32,0x6, 0x76,0xb, +0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0x3b,0x7e,0xb3,0x2a,0x73,0xa, 0x2b,0x2d,0x23,0xa, +0x3a,0xbd,0x32,0x48,0xc6,0x22,0x74,0x2, 0x7a,0xb3,0x2f,0xa9,0x74,0x1, 0x7a,0xb3, +0x28,0xac,0x2, 0x33,0x6e,0xd2,0x0, 0x6c,0xaa,0x6c,0x77,0x80,0x1f,0x7e,0x63,0x2a, +0x6e,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c,0x65,0x7e,0x50,0x2, 0xac,0x56,0x49,0x22, +0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, 0xb, 0xa0,0xb, 0x70,0x7e,0xb3,0x2a,0x6d, +0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24,0xa, 0x3a,0xbd,0x32,0x8, 0x2, 0xc2,0x0, +0xa2,0x0, 0x22,0x7e,0x63,0x2a,0x6f,0x7e,0xa3,0x2a,0x70,0x7e,0x70,0x1, 0x80,0x25, +0xa, 0x17,0x7e,0xb3,0x2a,0x6e,0xa, 0x2b,0x2d,0x21,0x3e,0x24,0x49,0x12,0x4, 0xfc, +0x7e,0xf4,0x61,0x59,0x12,0xa7,0x87,0x6e,0x24,0xff,0xff,0xb, 0x24,0xbd,0x12,0x58, +0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b,0x14,0xa, 0x27,0xbd,0x21,0x48,0xd1,0x7e, +0x70,0x2, 0x80,0x20,0x7e,0x50,0x2, 0xac,0x57,0x49,0x12,0x4, 0xfc,0x7e,0xf4,0x61, +0x5b,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, 0x6d,0x22,0x9d,0x20,0xbd,0x12,0x58,0x2, +0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27,0xbd,0x21,0x48,0xd6,0xc3,0x22, +0x7e,0xb3,0x37,0x5e,0xb4,0x1, 0x3, 0x2, 0x3f,0xaa,0x7e,0xb3,0x37,0xc4,0x4, 0x7a, +0xb3,0x37,0xc4,0x7e,0xb3,0x37,0x52,0xb4,0x2, 0x18,0x7e,0xb3,0x37,0xc3,0x4, 0x7a, +0xb3,0x37,0xc3,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xc4,0x74,0x1, 0x7a,0xb3, +0x37,0x52,0x7e,0x73,0x37,0xc3,0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x37, +0x5e,0x12,0x3f,0xaa,0x12,0xaa,0x27,0x12,0x3f,0xc3,0x7e,0x73,0x37,0xc4,0xbe,0x70, +0xa, 0x28,0x3, 0x2, 0x3f,0xc3,0x22,0xe4,0x7a,0xb3,0x37,0x50,0x6c,0xaa,0x80,0xd, +0x6d,0x44,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37,0x67,0xb, 0xa0,0x12,0x9d,0x6b, +0x38,0xee,0xe4,0x7a,0xb3,0x37,0x51,0x6d,0x33,0x7a,0x37,0x37,0x58,0x7a,0x37,0x37, +0x4d,0x22,0x7d,0x23,0x7e,0x14,0x61,0xce,0x12,0x3e,0x8b,0x7e,0x14,0x0, 0x5, 0xad, +0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x37,0xc5,0xbe,0x30,0x8, 0x50,0x45, +0x74,0x8, 0x80,0x3d,0x7d,0x13,0x3e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x37,0xc5, +0xbe,0x30,0x6, 0x50,0x30,0x74,0x6, 0x80,0x28,0x7e,0x14,0x0, 0x3, 0xad,0x13,0x1e, +0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x37,0xc5,0xbe,0x30,0x4, 0x50,0x17,0x74,0x4, +0x80,0xf, 0xbd,0x32,0x50,0xf, 0x7e,0x73,0x37,0xc5,0xbe,0x70,0x2, 0x50,0x6, 0x74, +0x2, 0x7a,0xb3,0x37,0xc5,0x7e,0xb3,0x37,0xc5,0xbe,0xb0,0x0, 0x28,0x1b,0x14,0x7a, +0xb3,0x37,0xc5,0x74,0x1, 0x7a,0xb3,0x16,0x92,0x90,0x62,0x3, 0xe4,0x93,0xbe,0xb3, +0x37,0xc5,0x50,0x5, 0xe4,0x7a,0xb3,0x16,0x91,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff, +0x6c,0x22,0x80,0x2a,0x12,0xab,0x53,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0x9f, +0xdb,0x7d,0x23,0x7e,0x70,0xc, 0xac,0x72,0x59,0x23,0x37,0x6b,0x49,0x3, 0x37,0x6b, +0x49,0x23,0x37,0x67,0xbd,0x20,0x50,0x4, 0x59,0x3, 0x37,0x67,0xb, 0x20,0xbc,0x32, +0x50,0xd2,0x6c,0xaa,0x6c,0x22,0x80,0x18,0x12,0xab,0x53,0x68,0x11,0x7e,0x70,0xc, +0xac,0x72,0x49,0x3, 0x37,0x67,0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20, +0xbc,0x32,0x50,0xe4,0x7e,0x37,0x37,0x4d,0xbe,0x37,0x37,0xc6,0x50,0x8, 0x7e,0x37, +0x37,0xc6,0x7a,0x37,0x37,0x4d,0x12,0xac,0x89,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff, +0x7c,0xba,0x22,0x7e,0x10,0x5, 0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, +0x22,0xca,0xd8,0xca,0x79,0x7e,0xe0,0xff,0x12,0xac,0xab,0x7e,0xb3,0x37,0x54,0xb4, +0x1, 0x8, 0x12,0x67,0x8d,0xe4,0x7a,0xb3,0x37,0x54,0x7e,0xb3,0x37,0x53,0x60,0x4, +0x74,0xff,0x81,0x84,0x7e,0xb3,0x37,0x52,0xb4,0x2, 0x2, 0x80,0x2, 0x81,0x78,0x12, +0xac,0xa3,0x38,0xc, 0x12,0xac,0x9b,0x38,0x7, 0x12,0xac,0x93,0x38,0x2, 0x81,0x78, +0x12,0x9f,0xb8,0xa, 0x3d,0x1b,0x34,0xbe,0x34,0x0, 0x3, 0x48,0x4, 0x74,0x3, 0x80, +0x3, 0x7c,0xbd,0x14,0x12,0xaa,0xda,0x7c,0xfb,0x7e,0xb3,0x37,0x51,0x4, 0x7a,0xb3, +0x37,0x51,0x90,0x61,0xcb,0xe4,0x93,0x14,0x12,0xaa,0xda,0x7c,0xab,0xbe,0xa0,0xff, +0x68,0x2c,0xbe,0xf0,0xff,0x68,0x25,0x7e,0x30,0xc, 0xac,0x3f,0x49,0x21,0x37,0x67, +0x7e,0xf4,0x61,0xd2,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x30,0xbd,0x23,0x28,0xf, 0x12, +0xac,0x89,0x3e,0x34,0xbd,0x23,0x28,0x6, 0x7c,0xfa,0x80,0x2, 0x7c,0xfa,0xbe,0xf0, +0xff,0x78,0x11,0xe4,0x7a,0xb3,0x37,0x51,0x7a,0xb3,0x37,0x52,0x7a,0xb3,0x37,0x5e, +0x74,0xff,0x80,0x70,0x90,0x61,0xda,0xe4,0x93,0xbe,0xb3,0x37,0x51,0x50,0x59,0x74, +0xc, 0xac,0xbf,0x49,0x25,0x37,0x67,0x7e,0x14,0x61,0xd2,0x12,0x3e,0x8b,0xbd,0x23, +0x50,0x3d,0x7e,0x34,0x61,0xd6,0x12,0x23,0xb7,0xbe,0x37,0x37,0x4d,0x40,0xd, 0x7e, +0x34,0x61,0xd8,0x12,0x23,0xb7,0xbe,0x37,0x37,0x58,0x50,0x23,0x74,0x5, 0xac,0xbf, +0x9, 0x75,0x26,0x33,0xbe,0x73,0x2b,0xf, 0x68,0x15,0x7c,0xef,0xbe,0xe0,0x4, 0x50, +0x8, 0x12,0x67,0xa7,0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0x54,0xe4, +0x7a,0xb3,0x37,0x5e,0x7a,0xb3,0x37,0x52,0xbe,0xe0,0xff,0x68,0x5, 0xe4,0x7a,0xb3, +0x37,0x51,0x7c,0xbe,0xda,0x79,0xda,0xd8,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33, +0x37,0x67,0x22,0x7e,0x73,0x26,0xf5,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x26,0xf4,0xbe, +0x70,0x0, 0x22,0x7e,0x73,0x28,0x92,0xbe,0x70,0x0, 0x22,0x7e,0xb3,0x37,0x53,0xb4, +0x1, 0x27,0x7e,0xb3,0x37,0xc9,0x4, 0x7a,0xb3,0x37,0xc9,0x7e,0x73,0x37,0xc9,0xbe, +0x70,0x3, 0x40,0x15,0x12,0x9c,0xf0,0x7e,0x73,0x37,0xc9,0xbe,0x70,0x6, 0x40,0x9, +0xe4,0x7a,0xb3,0x37,0xc9,0x7a,0xb3,0x37,0x53,0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab, +0x68,0x6, 0x7a,0xb3,0x2b,0x62,0xd2,0x10,0x30,0x10,0x9, 0xc2,0x10,0x12,0xac,0xf5, +0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x2a,0x6d,0x12,0x3, 0x8b,0x7e,0x8, 0x2a,0x6d, +0x74,0x3, 0x2, 0x11,0x7a,0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c, +0x22,0x80,0x37,0x7e,0xb3,0x2a,0x6e,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e, +0x44,0x7e,0x7f,0x13,0x8a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, +0xbe,0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44, +0xfd,0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x2a,0x6e,0xbc,0x92, +0x38,0xc1,0xb, 0x31,0x7e,0xb3,0x2a,0x6d,0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, +0xad,0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12,0x25,0x57,0xbd,0x12,0x50, +0x22,0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x39,0xf2,0x7e,0xb3,0x39,0xf3,0xbe,0xb0, +0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x39,0xf3,0x80,0x3c,0xe4,0x7a,0xb3,0x39,0xf3,0x74, +0x1, 0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x39,0xf3, +0x7e,0xb3,0x39,0xf2,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x39,0xf2,0x80,0x16, +0xe4,0x7a,0xb3,0x39,0xf2,0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x39,0xf2,0x7a,0xb3, +0x39,0xf3,0x7a,0xb3,0x39,0xf4,0x7e,0xb3,0x39,0xf4,0x22,0xe4,0x7a,0xb3,0x28,0xa8, +0x7a,0xb3,0x39,0xf5,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6c,0xdd,0x7e,0x57,0x28, +0x99,0x7d,0xf5,0x7e,0xe7,0x28,0x97,0x7e,0x37,0x38,0xe5,0x4d,0x33,0x68,0x4, 0x7d, +0xf5,0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x2a,0x6e,0x7c,0x8a,0x7e,0xb3,0x28,0xa5,0x14, +0x68,0x21,0x14,0x68,0x14,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0x16,0x24,0x45,0x78, +0x10,0x7c,0xfa,0x7e,0x83,0x2a,0x6d,0x80,0xa, 0x7e,0x73,0x2a,0x6d,0x2c,0x87,0x80, +0x2, 0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c,0xb9,0x12,0x38,0x9e,0xbe,0x34,0x2, 0x58, +0x8, 0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33,0x28,0x84,0xbc,0x39,0x38,0xe9,0xbe,0xd0, +0x3, 0x40,0x2, 0xe1,0x96,0x7e,0xa3,0x28,0x85,0xbe,0xa0,0x0, 0x38,0xb, 0xbe,0x30, +0x0, 0x28,0x37,0x7e,0xb3,0x26,0x83,0x70,0x31,0x6c,0x99,0x80,0x29,0xa, 0x29,0xa, +0x3f,0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, 0x7a,0xbd,0x2f,0x8, 0x17,0x49,0x3, 0x4, +0xfc,0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d,0x3e,0x12,0x9f,0x51,0xbd,0x3, 0x8, 0x4, +0xd2,0x0, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xd3,0x6d,0xee,0x9e,0xe7,0x2a,0x4f, +0xbe,0xe7,0x7, 0xf8,0x8, 0x2, 0xc2,0x0, 0x30,0x0, 0x20,0x7e,0xb3,0x39,0xf5,0x4, +0x7a,0xb3,0x39,0xf5,0x7e,0x23,0x39,0xf5,0xbe,0x20,0xa, 0x28,0x1d,0x74,0xa, 0x7a, +0xb3,0x39,0xf5,0x74,0x1, 0x7a,0xb3,0x28,0xa8,0x80,0xf, 0x7e,0x23,0x39,0xf5,0xbe, +0x20,0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23,0x39,0xf5,0x6c,0xee,0xbe,0x30,0x0, 0x38, +0x5, 0xbe,0xa0,0x0, 0x28,0x69,0x7e,0xb3,0x28,0xa7,0xb4,0x1, 0x9, 0x7e,0xb3,0x28, +0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x52,0x6c,0x99,0x80, +0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x26,0xfa,0x9, 0xd3,0x26,0xfb,0x12,0xaf, +0x9b,0xbe,0x34,0x0, 0x96,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3, +0x28,0x84,0xbc,0xb9,0x38,0xdb,0x6c,0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, +0xa3,0x27,0x36,0x9, 0xd3,0x27,0x37,0x12,0xaf,0x9b,0xbe,0x34,0xff,0x6a,0x58,0x5, +0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x28,0x85,0xbc,0xb9,0x38,0xdb,0x6c, +0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d,0x5e,0x3e,0x54,0x49,0x55,0x5, 0x7a,0xbd, +0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xe5,0x4c,0xee, +0x78,0x25,0x7e,0xb3,0x39,0xf6,0x4, 0x7a,0xb3,0x39,0xf6,0x7e,0x73,0x39,0xf6,0xbe, +0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3,0x39,0xf6,0x7e,0xb3,0x28,0xa8,0x60,0x2, +0xd2,0x19,0x12,0xad,0xcb,0x80,0xf, 0x7e,0x73,0x39,0xf6,0xbe,0x70,0x0, 0x28,0x6, +0x1e,0x70,0x7a,0x73,0x39,0xf6,0xda,0x79,0xda,0xd8,0x22,0x7c,0xba,0x7c,0x7d,0x2, +0x35,0xb5,0x6c,0x66,0x90,0x60,0xa7,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x71,0x90,0x60, +0xaa,0xe4,0x93,0x70,0x6a,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x63,0x7e,0x73,0x26,0xf2, +0xbe,0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80,0x4e,0xa, 0x23,0x9, 0x72,0x26,0xe6,0x7e, +0xb3,0x2a,0x6e,0x14,0xbc,0x7b,0x78,0x3d,0x6c,0x22,0x80,0x27,0x7c,0xb2,0x7c,0x73, +0x12,0xa7,0x98,0x50,0x1c,0xa, 0x22,0x7e,0x73,0x2a,0x6e,0xa, 0x7, 0x2d,0x2, 0x3e, +0x4, 0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e,0x7, 0x2a,0x4f,0xbd,0x20,0x58,0x2, 0xb, +0x60,0xb, 0x20,0x7e,0x73,0x2a,0x6d,0xbc,0x72,0x38,0xd1,0xbe,0x60,0x0, 0x28,0x3, +0x74,0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e,0x73,0x26,0xf2,0xbc,0x73,0x38,0xaa,0x74, +0x1, 0x22,0xca,0xf8,0x6c,0xff,0x80,0x34,0x7e,0x73,0x0, 0x60,0xbc,0x7f,0x68,0x2a, +0x7e,0x30,0x5, 0xac,0x3f,0x12,0xb0,0xb4,0xca,0x39,0x7e,0x30,0x38,0xac,0x3f,0x12, +0xb0,0xa9,0x12,0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x30,0x8c, +0xac,0x3f,0x12,0xb0,0x9e,0x12,0x20,0xc6,0x1b,0xfd,0xb, 0xf0,0x90,0x61,0xcb,0xe4, +0x93,0xbc,0xbf,0x38,0xc3,0x7e,0x23,0x0, 0x60,0x7e,0x30,0x5, 0xac,0x23,0x12,0xb0, +0xb4,0xca,0x39,0x7e,0x23,0x0, 0x60,0x7e,0x30,0x38,0xac,0x23,0x12,0xb0,0xa9,0x12, +0x20,0xc6,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x23,0x0, 0x60,0x7e,0x30, +0x8c,0xac,0x23,0x12,0xb0,0x9e,0x12,0x20,0xc6,0x1b,0xfd,0xda,0xf8,0x22,0x2e,0x14, +0x1, 0x41,0x6d,0x0, 0x7e,0x18,0x3, 0x71,0x22,0x2e,0x14,0x0, 0x61,0x6d,0x0, 0x7e, +0x18,0x34,0x0, 0x22,0x2e,0x14,0x26,0x33,0x6d,0x0, 0x12,0x4f,0x69,0x7e,0x34,0x0, +0x38,0x22,0x6c,0xaa,0x12,0xb4,0xf9,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, +0x3e,0x90,0x12,0x8e,0xd6,0x7c,0xb8,0x54,0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29,0xb1, +0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, 0x7f, +0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e, +0x40,0xc2,0x22,0xca,0x3b,0x7f,0x40,0x7e,0xe3,0x28,0x84,0x6c,0xdd,0x7e,0xc0,0x1, +0x80,0x1a,0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d, +0x12,0x7e,0xb, 0x70,0xbc,0x76,0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2, +0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0x41,0x68, +0x75,0x2d,0x0, 0x6d,0x33,0x7a,0x35,0x2e,0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18, +0x1f,0x70,0x7a,0x1d,0x29,0x74,0xff,0x7e,0x34,0x1f,0x71,0x7e,0x24,0x0, 0x0, 0x7a, +0x1b,0xb0,0x7e,0x1d,0x29,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, +0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x29,0x12,0xb4,0x4e,0x44,0x1, 0x7a, +0x1b,0xb0,0x75,0x24,0x0, 0x80,0x6c,0x12,0x8f,0xf0,0x9, 0x93,0x26,0xfb,0xe5,0x24, +0x12,0x56,0xc0,0xbc,0xbc,0x78,0x5a,0x5, 0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35, +0x25,0xa, 0x39,0x2e,0x35,0x27,0x7a,0x35,0x27,0x12,0x35,0xb1,0xbe,0x35,0x2e,0x8, +0x6, 0x12,0x35,0xb1,0x7a,0x35,0x2e,0x7e,0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28, +0x3, 0x7a,0x1b,0xa0,0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39, +0xa1,0x0, 0x2, 0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91, +0x0, 0x1, 0x7e,0x1d,0x29,0x29,0xb1,0x0, 0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, +0x3, 0x5, 0x24,0xbe,0xe1,0x24,0x38,0x8f,0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e, +0xd, 0x29,0x12,0xb2,0x7e,0xe5,0x2d,0xa, 0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15, +0x25,0x7e,0x35,0x27,0x8d,0x32,0x7a,0x35,0x27,0x7e,0x55,0x25,0x12,0xb2,0x76,0x19, +0xa3,0x31,0xf0,0x7e,0x55,0x27,0x12,0xb2,0x76,0x19,0xa3,0x31,0xf1,0x7e,0x37,0x28, +0x8a,0xbe,0x35,0x2e,0x78,0xe, 0x7e,0x35,0x25,0x7a,0x73,0x28,0x8c,0x7e,0x35,0x27, +0x7a,0x73,0x28,0x8d,0x7e,0x37,0x31,0xee,0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e, +0x35,0x27,0x12,0x35,0xb5,0x7e,0x25,0x2e,0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x31, +0xee,0x1b,0x38,0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0x21,0x40,0x12,0xb0, +0xc2,0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0xca,0x79, +0x7f,0x70,0x7e,0xb4,0xff,0xff,0x6c,0xee,0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, +0x7e,0x7b,0x70,0xbc,0x76,0x78,0xe, 0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc, +0x76,0x78,0x2, 0xd2,0x2, 0x6c,0xff,0x12,0xb4,0x56,0x6d,0xaa,0x29,0xb6,0x0, 0x5, +0x20,0xe1,0x2, 0x61,0x38,0x7f,0x6, 0x7e,0x7b,0xb0,0x12,0xb4,0x63,0x50,0x2d,0x7f, +0x6, 0x29,0xb7,0x0, 0x2, 0x12,0xb4,0x63,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, +0x6c,0x77,0x12,0xb4,0x6c,0x50,0x15,0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12, +0xb4,0x6c,0x50,0x8, 0x7c,0xef,0xd2,0x1, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, +0x27,0x7e,0x7b,0x70,0x12,0x37,0xb, 0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29, +0x77,0x0, 0x2, 0x12,0x37,0xb, 0x2d,0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77, +0x0, 0x1, 0x12,0x37,0xb, 0x2d,0xa3,0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, +0x3, 0x12,0x37,0xb, 0x2d,0xa3,0xbd,0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4, +0x0, 0x4, 0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0x41, +0xa7,0x20,0x1, 0xb, 0x20,0x2, 0x8, 0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20, +0x1, 0x2, 0x61,0xf9,0x74,0x6, 0xac,0xbe,0x12,0xb4,0x5a,0x29,0x76,0x0, 0x5, 0x7c, +0xb7,0xc4,0x23,0x54,0x1f,0xbe,0xb0,0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, +0x7c,0x67,0x2e,0x60,0x8, 0x5e,0x60,0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70, +0x20,0x2, 0x11,0x29,0xb6,0x0, 0x4, 0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36, +0x4, 0x7a,0x1b,0xb0,0x29,0x67,0x0, 0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, +0x29,0x76,0x0, 0x3, 0x80,0x4, 0x29,0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67, +0x0, 0x2, 0x29,0x76,0x0, 0x2, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, +0x29,0x77,0x0, 0x2, 0x39,0x76,0x0, 0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, +0xbc,0x76,0x50,0x6, 0x29,0x76,0x0, 0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76, +0x0, 0x1, 0x7e,0x7b,0x60,0x7e,0x6b,0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80, +0x3, 0x7e,0x7b,0x70,0x7a,0x6b,0x70,0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, +0xb5,0x32,0x32,0x30,0xe1,0x7, 0xb, 0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e, +0x50,0x39,0x74,0x1, 0x39,0xb7,0x0, 0x4, 0x12,0xb4,0x56,0x7e,0x34,0x0, 0x6, 0xca, +0x39,0x7f,0x17,0x7f,0x6, 0x12,0x20,0xc6,0x1b,0xfd,0x7f,0x16,0x12,0xb4,0x4e,0x44, +0x1, 0x7a,0x1b,0xb0,0x7f,0x16,0x12,0xb4,0x4e,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x2, +0xa, 0x7f,0x16,0x12,0xb4,0x4e,0x44,0x4, 0x7a,0x1b,0xb0,0xda,0x79,0x22,0x2e,0x34, +0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x74,0x6, 0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x32,0x2d, +0x6d,0xcc,0x22,0x7e,0x70,0x1, 0x2, 0xb4,0x6c,0x7e,0x70,0x1, 0x7c,0x87,0x7c,0x9b, +0x29,0xa0,0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, 0x78,0x7, +0x29,0xa0,0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, 0x16,0xbd, +0x1, 0x48,0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3,0x22,0xc3, +0x22,0xca,0x3b,0x12,0xb4,0xf0,0x75,0x54,0x0, 0x7e,0xa1,0x54,0x74,0x6, 0xa4,0x12, +0xb5,0x5, 0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc,0x12,0xb4,0x63,0x50,0x25,0x7f,0x7, +0x7c,0xbe,0x12,0xb4,0x69,0x50,0x1c,0x7f,0x7, 0x7c,0xbd,0x6c,0x77,0x12,0xb4,0x6c, +0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12,0xb4,0x6c,0x50,0x6, 0x29,0xb7,0x0, +0x4, 0x80,0xa, 0x5, 0x54,0xe5,0x54,0xbe,0xb0,0x1e,0x40,0xbd,0xe4,0xda,0x3b,0x22, +0x7c,0xf5,0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x22,0x7e,0x70,0x6, 0xac,0x7a,0x2e,0x34, +0x32,0x2d,0x6d,0x22,0x22,0x7d,0xf5,0x2e,0xf4,0x32,0x2d,0x6d,0xee,0x29,0xb7,0x0, +0x5, 0x22,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0xe8,0x8, 0xa, 0x12,0xb5,0x28,0xbe, +0xb0,0x8, 0x48,0x2, 0xd3,0x22,0xc3,0x22,0xca,0xd8,0xca,0x79,0x6c,0xff,0x6c,0xee, +0x80,0xf, 0x7c,0xbe,0x12,0xb5,0x4d,0x7c,0xdb,0xbc,0xfd,0x58,0x2, 0x7c,0xfd,0xb, +0xe0,0x12,0x5f,0xd9,0x38,0xec,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xca,0xf8,0x7c, +0xfb,0x7e,0x70,0x2, 0x12,0xb8,0x66,0x7f,0x71,0x7c,0xbf,0x12,0x38,0x9e,0x12,0xb5, +0x6b,0x7f,0x17,0x12,0x1f,0x58,0x7c,0xb7,0xda,0xf8,0x22,0x7d,0x13,0x1a,0x2, 0x1a, +0x0, 0x22,0xca,0x3b,0x7c,0xfb,0x7f,0x61,0x7f,0x40,0x9f,0x11,0x7f,0x51,0x7f,0x71, +0x7a,0x1d,0x3c,0x7a,0x1d,0x40,0x7a,0x1d,0x44,0xbe,0xf0,0xa, 0x78,0x6, 0x7e,0x54, +0x1, 0x3c,0x80,0x4, 0x7e,0x54,0x2, 0x35,0x7a,0x57,0x23,0x43,0x6c,0xee,0x80,0x60, +0xa, 0x5e,0x7f,0x14,0x12,0xb6,0xc3,0x7a,0x55,0x4a,0xa, 0x5e,0x7f,0x16,0x12,0xb6, +0xc3,0x7a,0x55,0x48,0x7e,0x35,0x48,0x12,0xb5,0x6b,0x2f,0x50,0x7e,0x65,0x4a,0x7d, +0x16,0x1a,0x2, 0x1a,0x0, 0x2f,0x70,0x12,0xb5,0x6b,0x12,0xb6,0xb9,0x7e,0x1d,0x3c, +0x2f,0x10,0x7a,0x1d,0x3c,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4a,0x12,0xb6, +0xb9,0x7e,0x1d,0x40,0x2f,0x10,0x7a,0x1d,0x40,0x7e,0x15,0x4a,0x1a,0x2, 0x1a,0x0, +0x7e,0x35,0x48,0x12,0xb6,0xb9,0x7e,0x1d,0x44,0x2f,0x10,0x7a,0x1d,0x44,0xb, 0xe0, +0xbc,0xfe,0x38,0x9c,0xa, 0xdf,0x6d,0xcc,0x7f,0x15,0x7f,0x6, 0x12,0x1f,0x58,0x7f, +0x51,0x7f,0x17,0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x71,0x7e,0x94,0x0, 0x64,0x7e,0x1d, +0x3c,0x7d,0x19,0x12,0x1e,0xfc,0x7e,0x87,0x23,0x43,0x7d,0x18,0x7d,0xd8,0x1a,0x12, +0x1a,0xc2,0x7f,0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x3c,0x7e,0x1d,0x40,0x7d,0x19,0x12, +0x1e,0xfc,0x7f,0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x40,0x7e,0x1d,0x44,0x7d,0x19,0x12, +0x1e,0xfc,0x7d,0x18,0x1a,0x2, 0x1a,0x0, 0x12,0x1f,0x58,0x7a,0x1d,0x44,0x7f,0x15, +0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x6d,0x44,0x9f,0x61,0x7f,0x15,0x7f,0x5, 0x12,0x1e, +0xeb,0x7e,0x5d,0x3c,0x9f,0x51,0x7f,0x17,0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x7d,0x40, +0x9f,0x71,0xbe,0x58,0x0, 0x0, 0x68,0x6, 0xbe,0x78,0x0, 0x0, 0x78,0x6, 0x7e,0x44, +0x0, 0x64,0x80,0x18,0x7f,0x16,0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x5, 0x12,0x1f,0x58, +0x7f,0x6, 0x12,0x1e,0xeb,0x7f,0x7, 0x12,0x1f,0x58,0x7d,0x43,0xbe,0x44,0x0, 0x0, +0x18,0x2, 0x6d,0x44,0x7c,0xb9,0xda,0x3b,0x22,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb, +0x7f,0x1, 0x22,0x2d,0x35,0x7e,0x1b,0x70,0xa, 0x57,0x22,0xca,0xf8,0x7c,0xfb,0x7f, +0x61,0x7f,0x50,0x7e,0x34,0x22,0xd1,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x70,0x74, +0x2a,0x12,0x1f,0xad,0x7e,0x48,0x1f,0x70,0x12,0xb5,0x12,0x92,0xc, 0x7c,0xbf,0x7e, +0x71,0x54,0x12,0x35,0xb5,0x7d,0x43,0xe5,0x55,0x7e,0x71,0x56,0x12,0x35,0xb5,0x2d, +0x34,0xe, 0x34,0x7f,0x4, 0x7e,0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69, +0x30,0x0, 0x2, 0x1b,0x5a,0x30,0x69,0x30,0x0, 0x4, 0x1b,0x6a,0x30,0x80,0x8, 0x2e, +0x14,0x0, 0x6, 0x1b,0x50,0x78,0xe1,0x12,0x8f,0x7c,0x28,0x2b,0xb, 0x5a,0x20,0x7e, +0x34,0x0, 0xd, 0xad,0x32,0x7e,0x24,0x0, 0x10,0x12,0x1e,0xb9,0x1b,0x5a,0x30,0xb, +0x6a,0x30,0x1a,0x26,0x1a,0x24,0x7e,0x14,0x0, 0xd, 0x12,0x1e,0xfc,0x7e,0x8, 0x0, +0x10,0x12,0x1f,0x58,0x1b,0x6a,0x30,0xda,0xf8,0x22,0xca,0x3b,0x7c,0x45,0x7c,0x6, +0x7c,0x57,0x7c,0x1b,0x7e,0x34,0x4, 0xfc,0x7e,0xb3,0x26,0x83,0x7e,0xf3,0x2a,0x6e, +0x7c,0x31,0x7c,0xe0,0x7c,0x25,0x7c,0xa4,0xbc,0x1, 0x50,0x4, 0x7c,0x30,0x7c,0xe1, +0xbc,0x45,0x50,0x4, 0x7c,0x24,0x7c,0xa5,0xbe,0xb0,0x1, 0x50,0x3, 0x2, 0xb8,0x20, +0x7e,0x90,0x2, 0xac,0x9f,0x7e,0x50,0x2, 0xac,0x53,0x2d,0x24,0x2d,0x23,0xb, 0x28, +0x20,0x7e,0x10,0x2, 0xac,0x1e,0x2d,0x4, 0x2d,0x3, 0xb, 0x8, 0x40,0xa, 0x3, 0xb, +0x4, 0x7c,0x31,0x80,0x28,0x7e,0xd0,0x2, 0xac,0xdf,0x7e,0x10,0x2, 0xac,0x13,0x2d, +0x6, 0x12,0xb8,0x24,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, 0xbe,0x24,0x0, 0x0, +0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x46,0xb, 0x30,0xbc,0xe3,0x38, +0xd4,0x7e,0x50,0x2, 0xac,0x52,0x2d,0x23,0xb, 0x28,0x20,0x7e,0x90,0x2, 0xac,0x9a, +0x2d,0x43,0xb, 0x48,0x40,0xa, 0x12,0xb, 0x14,0x80,0x21,0x7e,0x10,0x2, 0xac,0x13, +0x12,0xb8,0x24,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, 0xbe,0x24,0x0, 0x0, 0x8, +0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x7, 0xb, 0x30,0xbc,0xa3,0x38,0xdb, +0xd3,0xda,0x3b,0x22,0x2d,0x3, 0xb, 0x8, 0x0, 0x7e,0xf4,0x0, 0x9, 0x7d,0xb2,0xad, +0xbf,0x7e,0xd4,0x0, 0xa, 0xad,0xd0,0xbd,0xdb,0x22,0x12,0xb7,0x5a,0x92,0x4, 0x30, +0x4, 0xc, 0x7e,0xb3,0x32,0x2c,0xbe,0xb0,0xfa,0x50,0x11,0x4, 0x80,0xa, 0x7e,0xb3, +0x32,0x2c,0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x32,0x2c,0x7e,0xb3,0x32,0x2c, +0x70,0x2, 0xc3,0x22,0xd3,0x22,0xca,0x79,0x7c,0xa7,0x7c,0x8b,0x7e,0xb3,0x2a,0x6f, +0x7a,0xb3,0x1f,0x9a,0x7e,0xb3,0x2a,0x70,0x7a,0xb3,0x1f,0x9b,0x7e,0x70,0x2, 0xac, +0x78,0x9, 0x93,0x26,0xfa,0x9, 0x83,0x26,0xfb,0x9f,0x77,0x1a,0x3a,0x1a,0x79,0x9d, +0x73,0x21,0x1e,0x7a,0xf1,0x58,0xbe,0xf0,0x0, 0x58,0xe, 0x1a,0x3f,0x1a,0x29,0x9d, +0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x58,0x7e,0xb3,0x1f,0x9a,0xbc,0xbf,0x18, +0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32,0x7c,0xb7,0xf5,0x58,0x1a, +0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x57,0x80,0x43,0x85,0x57,0x59,0xe5,0x57, +0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x57,0x1a,0x3b,0x1a,0x28,0x9d,0x23,0x1a,0x38,0x2d, +0x32,0x7c,0xb7,0xf5,0x59,0x7e,0xb3,0x1f,0x9b,0xbe,0xb1,0x57,0x18,0x10,0x1a,0x38, +0xe5,0x57,0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x59,0xe5,0x58, +0x7e,0x71,0x59,0x12,0x35,0xb5,0x1a,0x26,0x1a,0x24,0x2f,0x71,0x5, 0x57,0x1a,0x3a, +0x1a,0x28,0x2d,0x23,0xe5,0x57,0x1a,0x3b,0xbd,0x32,0x8, 0xaf,0xb, 0xf0,0x1a,0x3a, +0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18,0x2, 0x1, 0x93,0x7f,0x17,0xda,0x79, +0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x26,0xfa,0x9, 0x65,0x26,0xfb,0x7e, +0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x28,0x8d,0xbc,0x76,0x78,0x2, 0xd3, +0x22,0xc3,0x22,0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13,0x8e,0xe4, +0x12,0x20,0xeb,0x90,0x60,0x93,0x93,0xa, 0x3b,0x7e,0xb3,0x2a,0x71,0xa, 0x2b,0x2d, +0x23,0xa, 0x3a,0xad,0x32,0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d,0x24,0x12, +0x87,0xe7,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e,0xb, 0x18, +0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0x6c,0xaa,0x80, +0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32,0x13,0x8e,0xbd,0x31, +0x28,0x9, 0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, 0xa0,0x7e,0xb3,0x2a, +0x6e,0xbc,0xba,0x38,0xdc,0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9, +0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x5f,0x7e,0x73, +0x39,0xf0,0xbe,0x71,0x5f,0x38,0x2, 0xd2,0x1c,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9, +0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9, +0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5, +0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8, +0x22,0x7e,0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55, +0x50,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44, +0x79,0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc, +0x79,0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c, +0x79,0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0xa9,0xd5,0xcb,0x74,0x10,0x12,0x0, +0x46,0x7c,0x7b,0x12,0x2c,0x78,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24, +0x0, 0xef,0x7e,0xf, 0x39,0xaa,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, +0x39,0xaa,0x79,0x20,0x0, 0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x39,0xaa,0x79,0x20, +0x0, 0x90,0x7c,0x67,0x6c,0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x39,0xaa,0x79,0x30, +0x0, 0x86,0x7e,0x34,0x29,0x90,0x7e,0xf, 0x39,0xaa,0x79,0x30,0x0, 0x8a,0x7e,0x34, +0x6a,0xd1,0x7e,0xf, 0x39,0xaa,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, +0x39,0xaa,0x79,0x30,0x0, 0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec, +0xd2,0x86,0xa9,0xc2,0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a, +0x2f,0xa9,0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75, +0x8d,0x1, 0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, +0x75,0xf7,0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd, +0xa9,0xd0,0xf7,0xd2,0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9, +0xc6,0xb7,0xc2,0xbe,0x22,0x75,0xe7,0x6b,0x2, 0xbb,0x3b,0xe4,0x7e,0x34,0xd7,0xfc, +0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9, +0xff,0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x39,0xee,0xb, 0x34,0x7a, +0x37,0x39,0xee,0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x39, +0xee,0x22,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3,0x39,0xfa,0xb4,0xa5,0x46,0x12, +0xbc,0x30,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0x12,0xbb,0xce,0xa9,0x36,0xb3,0xfc, +0x12,0xbb,0xce,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3, +0xfc,0x12,0xbb,0xce,0xa9,0x36,0xb3,0xfc,0x12,0xbb,0xce,0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e, +0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22,0xa9,0xc6, +0xb3,0x75,0xb5,0x0, 0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c, +0x73,0x7d,0x52,0x7c,0xab,0x7e,0xb3,0x39,0xfa,0xb4,0xa5,0x3c,0x12,0xbc,0x30,0x75, +0xb5,0x1, 0xa9,0x36,0xb3,0xfc,0x12,0xbb,0xce,0xa9,0x36,0xb3,0xfc,0x12,0xbb,0xce, +0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6, +0xb3,0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36, +0xb3,0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0x74,0x4, 0x7d,0x30,0x2, 0xbb,0xd9, +0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74,0x2, 0x7d,0x3f,0x2, 0xbb,0xd9,0x7d,0x42, +0x7f,0x60,0x7d,0x3, 0x12,0xbc,0xfd,0x74,0x2, 0x12,0xbb,0x72,0x7d,0xf3,0x4e,0xf4, +0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0xbc,0x37,0x7a,0x45,0x36,0x7d,0x30,0x6d,0x22, +0x7f,0x6, 0x12,0xbc,0x82,0x5e,0xf4,0xff,0xfd,0x12,0xbc,0x37,0x2, 0xbc,0x6f,0xa9, +0xc5,0xca,0xe4,0x7a,0xb3,0x39,0xfa,0x22,0x74,0x6, 0x12,0xbb,0x72,0x7d,0x3, 0x6c, +0x11,0x22,0x12,0xbc,0x90,0x7e,0x35,0x36,0x12,0xbd,0xd, 0xa9,0xd2,0xb4,0xd3,0x22, +0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39,0x7f,0x21,0xf5,0x38, +0xa9,0xc2,0xb4,0x74,0xb, 0x12,0xbc,0xbb,0xe5,0x3a,0x12,0xbc,0xbb,0xe5,0x39,0x12, +0xbc,0xbb,0xe5,0x38,0x12,0xbc,0xbb,0xe4,0x2, 0xbc,0xbb,0xf5,0xb5,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13, +0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0xbc,0xfd,0xe4,0x12,0xbc,0xe0,0x2, 0xbc,0x6f, +0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0xbb,0x72,0x4c,0xff,0x78,0x5, 0x5e,0x70,0xdf, +0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0xbb,0xd9,0xda,0xf8,0x22,0xa9,0xd5,0xca, +0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x39,0xfa,0x22,0x6d,0x22,0x80, +0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0, +0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4, +0x6c,0x11,0x80,0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x26,0xfb, +0xa, 0x20,0xa, 0x33,0x9d,0x32,0x12,0x21,0x1d,0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, +0x74,0x26,0xfa,0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x21,0x1d,0x7c,0x97,0xbe,0x90, +0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, +0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x28,0x84,0xbc,0x81, +0x18,0xb2,0x22,0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0xbd,0xdd,0xb, 0x7a, +0x20,0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c, +0xab,0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, +0x7d,0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e,0x54,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x1e, +0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12, +0x25,0x55,0x1e,0x34,0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22,0x3, 0x3, 0x54, +0xc0,0x7c,0xab,0xe4,0x22,0x7c,0xab,0x9f,0x11,0x30,0x0, 0x22,0x6c,0x99,0x80,0x1a, +0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b,0xb0,0x7e,0x78,0x0, 0x1, 0x60,0x5, 0x2f, +0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e,0xb, 0x90,0xbc,0xa9,0x38,0xe2,0x22,0xca, +0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c,0xfb,0x7e,0x8, 0x1f,0x34,0x12,0xbe,0x9b,0x7e, +0x8, 0x1f,0x3c,0x12,0xbe,0xa3,0xd2,0x0, 0x7e,0x8, 0x2a,0xdc,0x7c,0xbf,0x12,0xbd, +0xe5,0x7e,0x8, 0x1f,0x34,0x7a,0xf, 0x1f,0x58,0x7f,0x1, 0x7a,0x17,0x1f,0x5c,0x7d, +0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18,0x1f,0x3c,0x7a,0x1f,0x1f,0x64,0x6c,0x77,0x80, +0xe, 0x12,0xbe,0xeb,0x50,0x7, 0x12,0xbe,0xe2,0x19,0x51,0x1f,0x3c,0xb, 0x70,0xbc, +0xf7,0x38,0xee,0x12,0xbe,0x88,0xe4,0x12,0xbe,0x90,0xe4,0x12,0xc, 0x9b,0x6d,0x33, +0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f,0x5e,0x12,0xbe,0x88,0x74,0x1, 0x12,0xbe,0x90, +0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x58,0x22, +0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x7e,0x34,0x0, 0x8, 0xe4, +0x2, 0x20,0xeb,0x7e,0x34,0x0, 0x1c,0x74,0x3f,0x2, 0x20,0xeb,0x7e,0x8, 0x1f,0x34, +0x12,0xbe,0xa3,0x6c,0x77,0x80,0xe, 0x12,0xbe,0xeb,0x50,0x7, 0x12,0xbe,0xe2,0x19, +0x51,0x1f,0x34,0xb, 0x70,0x7e,0x53,0x2a,0x6e,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea, +0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e,0x8, 0x1f,0x34,0x2, +0x11,0x38,0xa, 0x27,0x9, 0x52,0x2b,0x44,0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x2a, +0xdc,0xbe,0x60,0x1c,0x22,0x12,0x67,0xf1,0x50,0xfb,0x22,0x7e,0x27,0x28,0xa3,0x6d, +0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64,0x30,0x5, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49, +0x34,0x5, 0xf8,0x49,0x4, 0x4, 0x0, 0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6,0xb4, +0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x5, 0xf8,0x80,0xc, 0xbd,0x1, 0x58,0x8, +0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, 0xf8,0x30,0x7, 0x2e,0x7e,0x90,0x2, 0xac,0x9a, +0x49,0x34,0x6, 0x76,0x49,0x4, 0x4, 0x7e,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x25,0xf6, +0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x6, 0x76,0x80,0xc, 0xbd,0x1, 0x58, +0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, +0xb, 0x7e,0xb3,0x2a,0x73,0xa, 0x4b,0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22, +0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33,0x19,0xb3,0x27,0x72,0xb, 0x30,0x90,0x60,0x9a, +0xe4,0x93,0x12,0x37,0xd7,0xb, 0x24,0xa, 0x33,0xbd,0x32,0x48,0xe7,0xe4,0x7a,0xb3, +0x28,0x84,0x7a,0xb3,0x28,0x85,0x6d,0x33,0x7a,0x37,0x28,0x86,0x7a,0x37,0x28,0x88, +0x7a,0x37,0x28,0x8a,0x7a,0x37,0x28,0x8e,0x7e,0xd4,0x1f,0x36,0x5e,0xd4,0xff,0xfe, +0x6d,0xcc,0x7e,0x1f,0x13,0x8a,0x7a,0x37,0x1f,0x76,0x7d,0x3d,0x7a,0x37,0x1f,0x7a, +0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x78,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x1f,0x73, +0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x1f,0x72,0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x7c, +0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x7e,0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x80, +0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1f,0x74,0x7e,0x73,0x3, 0xff,0x7a,0x73,0x1f,0x75, +0x7e,0x8, 0x1f,0x72,0x7e,0x18,0x1f,0x82,0x12,0x8, 0x0, 0x7e,0x73,0x1f,0x82,0x7a, +0x73,0x28,0x84,0x7e,0x73,0x1f,0x83,0x7a,0x73,0x28,0x85,0x7e,0x37,0x1f,0x84,0x7a, +0x37,0x28,0x86,0x7e,0x37,0x1f,0x86,0x7a,0x37,0x28,0x88,0x7e,0x37,0x1f,0x8c,0x7a, +0x37,0x28,0x8a,0x7e,0x37,0x1f,0x8e,0x7d,0x23,0x7a,0x53,0x28,0x8c,0xa, 0x36,0x7a, +0x73,0x28,0x8d,0x7e,0x37,0x1f,0x88,0x7a,0x37,0x28,0x8e,0x7e,0x37,0x1f,0x8a,0x7d, +0x23,0x7a,0x53,0x28,0x90,0xa, 0x36,0x7a,0x73,0x28,0x91,0x6c,0x33,0x80,0x20,0x7c, +0xb3,0x7e,0x70,0x1, 0x12,0x39,0x2f,0x74,0x2, 0xac,0xb3,0x49,0x45,0x15,0x9e,0xa, +0x38,0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29,0x19,0x25,0x26,0xfb,0xb, 0x30,0x7e, +0x23,0x28,0x84,0xbc,0x23,0x38,0xd8,0x6c,0x33,0x80,0x1b,0x74,0x2, 0xac,0xb3,0x7f, +0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25,0x27,0x36,0x7c,0x29, +0x19,0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28,0x85,0xbc,0x23,0x38,0xdd,0x22,0x7c, +0x7b,0xa, 0x57,0x9e,0x54,0x0, 0x20,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c, +0xab,0x7c,0x67,0x5e,0x60,0xf0,0xa5,0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24, +0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x7e,0x73,0x39,0xe5,0xa, 0x47,0x5d, +0x42,0x7e,0x73,0x38,0x1c,0x80,0x36,0xa5,0xbe,0x30,0x18,0x12,0xc1,0x32,0x60,0x5, +0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53,0x39,0xe6,0xa, 0x45,0x5d,0x43,0x7e,0x73,0x38, +0x1d,0x80,0x1a,0x12,0xc1,0x32,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, +0xb2,0x39,0xe5,0xa, 0x4b,0x5d,0x43,0xa, 0x5a,0x9, 0x75,0x38,0x1e,0xa, 0x57,0x5d, +0x54,0x22,0x7c,0xb7,0x54,0xf, 0x7e,0x34,0x0, 0x1, 0x22,0x7e,0xb3,0x38,0x1b,0x70, +0x6, 0x12,0xc1,0x74,0x2, 0xc3,0x6, 0x12,0x63,0x1b,0x12,0xc3,0xc, 0x50,0xa, 0x12, +0x87,0x39,0x7c,0x3b,0x12,0xc1,0x74,0x80,0x5, 0x12,0xc1,0x7a,0x7c,0x3b,0x4c,0x33, +0x68,0x11,0x7c,0xb3,0x12,0xc0,0xbf,0x60,0xa, 0x7a,0x33,0x38,0x1e,0x74,0x1, 0x7a, +0xb3,0x2a,0x8, 0x22,0xe4,0x7a,0xb3,0x2f,0x80,0x22,0xca,0xd8,0xca,0x79,0x6c,0xff, +0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x2a,0x2, 0x7e,0xe3,0x2a,0x3, 0x7e,0xb3, +0x39,0xc7,0x60,0x11,0x7e,0xc7,0x39,0xd0,0x4d,0xcc,0x78,0x2, 0x41,0x6e,0xbe,0xd0, +0x1, 0x28,0x2, 0x41,0x6e,0xbe,0xd0,0x1, 0x78,0x1d,0xbe,0xb0,0x4, 0x78,0x2, 0x41, +0x6e,0x7e,0xe7,0x29,0x8, 0x7e,0xf7,0x29,0xa, 0x7d,0x3e,0x7d,0x2f,0x12,0xc2,0xcd, +0xbe,0xb0,0x1, 0x78,0x2, 0x41,0x6e,0x7e,0xa3,0x39,0xc7,0x7c,0xba,0x14,0x68,0x29, +0x14,0x68,0x54,0x14,0x68,0x23,0x14,0x78,0x2, 0x41,0x6b,0xb, 0xb2,0x68,0x2, 0x41, +0x6e,0xbe,0xd0,0x1, 0x68,0x2, 0x41,0x7d,0x4c,0xee,0x68,0x2, 0x41,0x7d,0x74,0x1, +0x7a,0xb3,0x39,0xc7,0x12,0xc2,0x84,0x80,0x65,0x4c,0xdd,0x78,0x1d,0xbe,0xa0,0x1, +0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x39,0xc7,0x7e,0x34,0x62,0x6a,0x80,0x54,0x74,0x4, +0x7a,0xb3,0x39,0xc7,0x7e,0x34,0x62,0x6e,0x80,0x48,0x12,0xc2,0x8d,0x90,0x62,0x5d, +0x12,0xc2,0x96,0x68,0x49,0x80,0x56,0xbe,0xd0,0x1, 0x78,0x51,0x4c,0xee,0x78,0x4d, +0x12,0xc2,0x8d,0x7e,0x34,0x62,0x66,0x12,0x23,0xb7,0x7e,0x14,0x62,0x6a,0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7,0x39,0xd0,0x40,0x21,0x90,0x62,0x5c, +0x12,0xc2,0x96,0x68,0x19,0x12,0xc2,0x84,0x74,0x3, 0x7a,0xb3,0x39,0xc7,0x7e,0x34, +0x62,0x6a,0x12,0x23,0xb7,0x7a,0x37,0x39,0xd0,0x80,0x12,0x7e,0xf0,0x24,0xe4,0x7a, +0xb3,0x39,0xc7,0x6d,0x33,0x7a,0x37,0x39,0xd0,0x7c,0xbf,0x80,0x2, 0x7c,0xbf,0xda, +0x79,0xda,0xd8,0x22,0x7a,0xe7,0x39,0xc8,0x7a,0xf7,0x39,0xca,0x22,0x7a,0xe7,0x39, +0xcc,0x7a,0xf7,0x39,0xce,0x22,0xe4,0x93,0xa, 0x3b,0x12,0xc2,0xa2,0xa, 0xdb,0x4d, +0xdd,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x39,0xcc,0x9e,0x37, +0x39,0xc8,0x12,0x21,0x1d,0xbd,0x31,0x38,0x12,0x7e,0x37,0x39,0xce,0x9e,0x37,0x39, +0xca,0x12,0x21,0x1d,0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0x7d,0x13,0x7e, +0x54,0x62,0x5e,0x12,0xc2,0xfc,0x50,0x21,0x7e,0x54,0x62,0x60,0x12,0xc2,0xfc,0x28, +0x18,0x7e,0x14,0x62,0x62,0x12,0x3e,0x8b,0xbd,0x32,0x50,0xd, 0x7e,0x14,0x62,0x64, +0x12,0x3e,0x8b,0xbd,0x32,0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22,0x7e,0x44,0x0, 0xff, +0xb, 0x2a,0x30,0xbd,0x31,0x22,0xe4,0x7a,0xb3,0x39,0xc7,0x22,0x7e,0xb3,0x2f,0x80, +0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7d,0xf2,0x7d,0xe3,0x7e,0x8, 0x2f,0x80,0x7e, +0x34,0x0, 0x28,0xe4,0x12,0x20,0xeb,0x7e,0x8, 0x2b,0xbf,0x7e,0x34,0x3, 0xc0,0x12, +0x20,0xeb,0x7a,0xb3,0x38,0x1e,0x7e,0x34,0x62,0x94,0x12,0x23,0xb7,0x7a,0x37,0x2b, +0xb7,0x7a,0xe7,0x2f,0x84,0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88,0x7a,0xe7,0x2f, +0x8c,0x7a,0xe7,0x2f,0x90,0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a,0x7a,0xf7,0x2f, +0x8e,0x7a,0xf7,0x2f,0x92,0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb,0x7a,0xf7,0x2b, +0xbd,0x7a,0xb3,0x2f,0xa8,0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x74,0xfe,0x7a,0xb3, +0x38,0x1e,0xe4,0x7a,0xb3,0x2f,0x80,0x22,0xca,0x3b,0xf5,0x2a,0x7f,0x31,0x7a,0xd, +0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3,0x22,0xf7,0x7a,0xb3,0x22,0xf8,0x7e,0x34, +0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c,0x7a,0xb3,0x22,0xf5,0x75,0x2f,0x46,0x75, +0x2b,0x0, 0xa1,0x79,0x12,0xc5,0xb4,0x28,0x1e,0x7e,0x34,0x0, 0x44,0xca,0x39,0x7e, +0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34,0x14,0x6, 0x7e,0x24,0x0, 0xff,0x7e,0x8, +0x22,0xff,0x12,0x20,0xc6,0x1b,0xfd,0x6d,0x33,0x7a,0x37,0x22,0xf9,0x7a,0x35,0x30, +0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a,0x35,0x34,0x7e,0x34,0x22,0xff,0x7a,0x35, +0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38,0x75,0x2c,0x0, 0x80,0x59,0xe5,0x2c,0xa, +0x3b,0x7e,0xd, 0x26,0x12,0xc5,0xbc,0x2e,0x35,0x36,0x12,0x37,0x8, 0x7d,0xd3,0x7e, +0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a,0xd7,0x22,0xfb,0xe5,0x2c,0xa, 0x3b,0x7f, +0x3, 0x12,0xc5,0xbc,0x2e,0x35,0x38,0x12,0x37,0x8, 0x7d,0xc3,0x7e,0x35,0x32,0xbd, +0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37,0x22,0xf9,0x2d,0x3d,0x7a,0x37,0x22,0xf9, +0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30,0x2d,0xcd,0x7e,0x35,0x34,0xbd,0x3c,0x58, +0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a,0xbe,0xb1,0x2c,0x38,0xa0,0xe5,0x2a,0xb4, +0xa, 0x2a,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x40,0x48,0xb, 0x7e,0x25,0x32,0xbe, +0x24,0x0, 0x40,0x48,0x2, 0xa1,0x77,0xbe,0x34,0x0, 0x60,0x8, 0x2, 0xa1,0x77,0x7e, +0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x2, 0xa1,0x77,0x80,0x28,0x7e,0x37,0x22,0xfb, +0xbe,0x34,0x0, 0x20,0x8, 0xb, 0x7e,0x25,0x32,0xbe,0x24,0x0, 0x20,0x8, 0x2, 0xa1, +0x77,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xa1,0x77,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30, +0x8, 0x2, 0xa1,0x77,0x7e,0xa3,0x39,0x2b,0x74,0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58, +0x2, 0xa1,0x77,0x7e,0xa3,0x39,0x2c,0x74,0xc, 0xa4,0xbe,0x55,0x30,0x58,0x2, 0xa1, +0x77,0x7e,0x15,0x36,0x6d,0x0, 0x7e,0x1d,0x26,0xe5,0x2a,0x12,0xb5,0x72,0x7a,0xb3, +0x22,0xf4,0x7e,0x15,0x38,0x6d,0x0, 0x7f,0x13,0xe5,0x2a,0x12,0xb5,0x72,0xf5,0x2d, +0x7e,0x73,0x22,0xf5,0xbe,0x73,0x22,0xf4,0x38,0x7d,0xbe,0x71,0x2d,0x38,0x78,0xe5, +0x2d,0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77, +0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d,0xa, 0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4, +0xa, 0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1f,0x7, 0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe, +0xb1,0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb,0x2e,0x35,0x32,0x2e,0x35,0x34,0x7a,0x35, +0x3a,0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, 0x64,0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a, +0x7a,0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe,0x35,0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a, +0x37,0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22,0xf7,0x7e,0x73,0x23,0x41,0x7a,0x73,0x22, +0xf8,0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, 0x2b,0x12,0xc5,0xb4,0x28,0x2, 0x61,0xb4, +0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40,0x20,0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, +0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e,0x73,0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a, +0x73,0x39,0x28,0x7a,0xb3,0x39,0x2a,0x80,0x6, 0x74,0x7c,0x7a,0xb3,0x39,0x28,0x7c, +0xba,0xda,0x3b,0x22,0x7e,0x73,0x39,0xeb,0xbe,0x71,0x2b,0x22,0x2d,0x13,0x7e,0xb, +0x50,0xa, 0x25,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37,0x2f,0x90,0x7a,0x35, +0x2a,0x7e,0x37,0x2f,0x8e,0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c,0x7a,0x35,0x26,0x7e, +0x37,0x2f,0x9e,0x7a,0x35,0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34,0x0, 0x26,0x7e,0x14, +0x0, 0x2f,0x74,0x9, 0x12,0x1f,0x8c,0x74,0x2, 0xac,0xbf,0x7f,0x4, 0x2d,0x15,0x7f, +0x15,0x2d,0x35,0x12,0xc6,0x13,0xb, 0xf0,0x7e,0x73,0x39,0x29,0xbc,0x7f,0x38,0xda, +0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34,0x0, 0x0, 0x38,0x7, +0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34,0x0, 0x0, 0x38,0x7, +0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35,0x33,0x6d,0x22,0x7e, +0x33,0x39,0x2b,0x12,0xc6,0x68,0x7e,0x15,0x2f,0x12,0x1f,0x5, 0x1b,0x6a,0x30,0xb, +0x7a,0x30,0x9e,0x35,0x35,0x6d,0x22,0x7e,0x33,0x39,0x2c,0x12,0xc6,0x68,0x7e,0x15, +0x31,0x12,0x1f,0x5, 0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, 0x2, 0x1e,0xeb,0x7c, +0x97,0x7c,0xab,0x7f,0x10,0x7e,0x30,0x2, 0xac,0x3a,0x2d,0x13,0x7d,0x2, 0xb, 0xa, +0x10,0x7e,0x10,0x2, 0xac,0x19,0x7f,0x71,0x2d,0xf0,0xb, 0x7a,0x0, 0x7c,0x21,0xa5, +0xba,0x0, 0x14,0xa, 0x3, 0x1b,0x7a,0x0, 0xbc,0x9a,0x68,0x24,0x6d,0x44,0x74,0x2, +0xa4,0x2d,0x35,0x1b,0x1a,0x40,0x22,0xbc,0x9a,0x68,0x15,0xa, 0x2, 0xa, 0x13,0x2d, +0x10,0xe, 0x14,0x1b,0x7a,0x10,0x6d,0x11,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x10, +0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x39,0x29,0xbe,0x70,0x20,0x40,0x52, +0x7e,0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74,0x5, 0x2f,0x11,0x14,0x78,0xfb, +0x7e,0x33,0x39,0x29,0xa, 0x13,0x6d,0x0, 0x12,0x1f,0x7, 0x7c,0xe7,0xbe,0xe0,0x2, +0x50,0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, 0x3e,0x1b,0x34,0x7c,0xc7,0x7f, +0x5, 0x7c,0xbd,0x12,0xc6,0x6f,0x7f,0x6, 0x7c,0xbd,0x7c,0x7c,0x12,0xc6,0x6f,0xb, +0xf0,0x7e,0x73,0x39,0x29,0xbc,0x7f,0x50,0xbc,0x7f,0x5, 0x7f,0x16,0x12,0x6e,0xf8, +0x80,0x6, 0x74,0x7e,0x7a,0xb3,0x39,0x28,0xda,0x3b,0x22,0xca,0x3b,0x7f,0x71,0x7e, +0x60,0x1, 0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b,0x7a,0x53,0x22,0xf4,0x7a,0x43, +0x23,0xe4,0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x2, 0xc8,0x50,0x7e,0x90,0x2, 0xac,0x9a, +0x7f,0x60,0x2d,0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf,0xf5,0x26,0x7f,0x67,0x2d, +0xd4,0xb, 0x6a,0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d,0xad,0x7d,0x7a,0x7c,0x8f, +0xbe,0x80,0x0, 0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, 0xa4,0xa, 0x79,0x9d,0x7a, +0xbe,0xf0,0x0, 0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe,0x80,0x2, 0x58,0x8, 0xbe, +0xf0,0x2, 0x58,0x3, 0x2, 0xc8,0x4e,0xbe,0x60,0x0, 0x18,0x3, 0x2, 0xc8,0x36,0xbe, +0x70,0xec,0x28,0x3, 0x2, 0xc8,0x5b,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0,0x8, 0x48, +0x61,0xa, 0xa7,0xb, 0xa4,0x7d,0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12,0xc8,0xd4, +0x19,0xba,0x22,0xf4,0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0xc8,0xd4,0x19,0xba,0x23, +0xe4,0x9, 0xba,0x22,0xf4,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d,0x6c,0x7c, +0xbd,0xa, 0xc7,0x19,0xbc,0x22,0xf3,0x9, 0xbc,0x23,0xe4,0xa, 0xcb,0xa, 0xa4,0x2d, +0xac,0x12,0xc8,0xd4,0x19,0xba,0x23,0xe3,0x2d,0xdb,0x12,0xc8,0x96,0x19,0xbd,0x22, +0xf5,0xa, 0xd9,0x12,0xc8,0x94,0x19,0xbd,0x23,0xe5,0xb, 0xd5,0x7d,0x6d,0x7c,0x7d, +0x80,0x24,0xbe,0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x26,0xa, 0xcb, +0xa, 0xd5,0x12,0xc8,0x94,0x19,0xbd,0x22,0xf4,0xa, 0xc9,0xa, 0xd4,0x12,0xc8,0x94, +0x19,0xbd,0x23,0xe4,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x20,0x7e,0x51,0x26,0x7c,0x49, +0xe5,0x26,0xa, 0xd7,0x19,0xbd,0x22,0xf4,0x19,0x9d,0x23,0xe4,0xb, 0x70,0xb, 0xa0, +0x7e,0xb3,0x39,0x29,0xbc,0xba,0x28,0x3, 0x2, 0xc7,0x4b,0x7a,0x73,0x39,0x29,0x7e, +0xa0,0x1, 0x80,0x25,0xa, 0x3a,0x9, 0xb3,0x22,0xf4,0xa, 0x2b,0x7e,0x70,0x2, 0xac, +0x7a,0x7f,0x60,0x2d,0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x23,0xe4,0xa, 0x4b, +0x2d,0x3f,0x7d,0x2e,0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x39,0x29,0xbc,0xba,0x38, +0xd3,0xda,0x3b,0x22,0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22,0x74, +0x1, 0x7a,0xb3,0x36,0x51,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfa,0x7a,0x73,0x36, +0x52,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfb,0x7a,0x73,0x36,0x53,0x22,0x74,0x1, +0x7a,0xb3,0x38,0x8a,0x7e,0x34,0x60,0xa3,0x22,0x74,0x1, 0x7a,0xb3,0x2b,0x1, 0x7a, +0xb3,0x2b,0x1d,0x22,0xe, 0xa4,0x7d,0x6a,0x7c,0xbd,0xa, 0xa7,0x22,0x74,0x2, 0xac, +0xbe,0x9, 0xd5,0x26,0xfa,0x9, 0xc5,0x26,0xfb,0x22,0xa, 0x3a,0x19,0xf3,0x1f,0x46, +0x74,0x1, 0x19,0xb4,0x1f,0x50,0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4,0x7e,0x7b,0x60, +0xbc,0x6b,0x22,0x3e,0x44,0x7e,0x1f,0x13,0x8a,0x2d,0x34,0x1b,0x1a,0x50,0x22,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x7a,0x37,0x2a,0x5e,0x22,0x7e,0x30,0x2, 0xac,0x3e,0x2d, +0x31,0xb, 0xa0,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0x8, 0x6, 0xfc,0x22,0xa, 0x2c, +0x2e,0x27,0x2a,0xfe,0x7e,0x29,0x70,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x28, +0xb2,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0x9d,0x32,0x12,0x21, +0x1d,0xbe,0x34,0x0, 0x3, 0x22,0xa, 0x2b,0x1b,0x24,0xa, 0x3d,0xbd,0x32,0x22,0x6d, +0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7e,0x37,0x25,0xf4,0x7a,0x37,0x32,0xe1,0x22, +0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x32,0xe3,0x22,0x7e,0x73,0x38,0xa7,0x7a,0x73,0x2b, +0x20,0x22,0x7e,0xb3,0x38,0xca,0x7e,0x34,0x0, 0x4, 0x22,0x7d,0x2e,0x12,0x1e,0xb9, +0x7d,0xf3,0x22,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x0, 0x22,0x90,0x60,0xa7,0xe4,0x93, +0x7c,0xab,0x22,0xff,0xc9,0xa4,0x36,0x5b,0xaf,0x50,0xa, 0x3b, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_ofiml0X51_Black_V06_D01_20170804_app.i b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_ofiml0X51_Black_V06_D01_20170804_app.i new file mode 100644 index 0000000000000..1752a0cb0dacb --- /dev/null +++ b/drivers/input/touchscreen/ft5435/HQ_D2_XiaoMi_FT5435_ofiml0X51_Black_V06_D01_20170804_app.i @@ -0,0 +1,3295 @@ +0x2, 0x1f,0xd2,0x2, 0xba,0x48,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x5a,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x70,0x6b,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x80,0x54,0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x87,0xe2,0xf5,0xfd,0xe5,0xfe,0x22,0x2, 0x0, 0x69,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x33,0x5, 0x32,0x32,0x2, 0x0, 0x6a,0xb2,0x86, +0x22,0xff,0xff,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xd, 0x7e,0xf, 0x33,0xd3, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x33,0xe3,0x7e,0x73,0x33,0xe3,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xc, 0x80,0x2, 0xc2,0xc, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x88,0x60,0x7e,0x1f,0x33,0xd3,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x33,0xd3,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x33,0xd7,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x33,0xdf,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x33,0xdd,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x39,0xef,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0xbc,0xf2,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x1e, +0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d,0xe2,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x61,0x3f,0x7e,0x34,0x1e,0x19,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x1d,0xb2,0x61,0x3f,0x7e,0x34,0x1d,0x96,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x1d,0xc6,0x61,0x3f,0x7e,0x34,0x1e,0xa, 0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1d, +0xf1,0x61,0x3f,0x7e,0x34,0x1e,0x45,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x1e,0x29,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x1e,0x69,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x1e,0x6a,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x33,0xd3,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xd3,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x33, +0xd3,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x33,0xd3,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x20,0xe3,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x39,0xfe,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x39,0xfe,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x39,0xfe,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x39,0xfe,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x39,0xfe,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x39,0xfe,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x39,0xef,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x33,0xcb,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x39, +0xef,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x33,0xcb,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x39,0xef,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x39,0xef,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x39,0xef,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x33,0xd3,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x33,0xd3,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x1e,0xb9,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x1e,0xb9,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x33,0xd3,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x39,0xfe,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xfe,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x39,0xfe,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x39,0xfe,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xb2,0x82,0x22,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x39,0xfe,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x39,0xfe, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x39,0xfe, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x39,0xfe,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39,0xeb,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x39, +0xeb,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x39,0xeb,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x39,0xeb,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x33,0xcb,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x33,0xcb,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x33,0xcb,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x33,0xcb,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x33,0xd3,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x33,0xd3,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x33, +0xd3,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x33,0xd3,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x33,0xd3,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x33,0xd3,0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x33,0xd3,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x33,0xd3,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x33, +0xd3,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x33,0xd3, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x33,0xd3,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x33,0xd3,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x33,0xd3,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x33,0xd3,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x1e,0xb9,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x1e,0xb9,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xfe, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x39,0xfe,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x39,0xeb,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x39,0xeb,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x39,0xeb,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1d,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x39,0xfe, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x39,0xfe,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x39,0xfe,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x39, +0xfe,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x39,0xfe,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x33,0xd3,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x33,0xd3,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x33,0xd3,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x33,0xd3, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x33,0xd3,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x33,0xd3,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x39,0xfe,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x39,0xfe,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x39,0xfe,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x39,0xfe,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x39,0xfe,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x39,0xfe,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x39,0xef,0x79,0x30, +0x0, 0xe, 0xc2,0x1c,0xe4,0x7a,0xb3,0x39,0xea,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x33,0xcb,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xcb,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x39, +0xef,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x39, +0xef,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x39,0xfe,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x39,0xfe,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x39,0xfe,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x39,0xfe,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x39,0xfe,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x39, +0xfe,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x39,0xfe,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1d,0x7e,0xf, 0x39,0xfe,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x39,0xfe,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x1f,0x58,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x1e,0xeb,0x7d,0x1e,0x12,0x1f,0x5, 0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x33,0xd3,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1c,0x7e,0xf, 0x39,0xef,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x39,0xea,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x39,0xef,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x88,0x60,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x33,0xcb,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x33,0xcb,0x1b,0x1a,0x10,0x7e,0xf, 0x33,0xd3,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xd, 0xe4,0x7a,0xb3,0x33,0xe3,0x7e,0x1f,0x33,0xcb, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x39,0xeb,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x39,0xeb,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x39,0xeb,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x33,0xd3,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x33,0xd3,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x39,0xeb,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x39,0xeb,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x39,0xfe,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x39,0xfe,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x20,0x94,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x20,0x95,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x33,0xcb,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x33,0xcb,0x1b,0x1a,0x10,0x7e, +0x1f,0x33,0xcb,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x33,0xd3,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x39,0xef,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x33,0xcb,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x33,0xcb,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x33, +0xd3,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x33,0xd3,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x33,0xd3,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x33,0xcb,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x6, 0xe, 0x15,0x1a,0x1f,0x26,0x2b,0x2d,0x2e,0x2f, +0x2c,0x2a,0x24,0x1f,0x1a,0x14,0xf, 0x8, 0x3, 0x3, 0x6, 0xb, 0x10,0x15,0x1c,0x22, +0x28,0x2d,0x34,0x39,0x3d,0x40,0xe, 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xc, 0x11,0x16, +0x1c,0x23,0x2b,0x32,0x37,0x3c,0x40,0x45,0x4a,0x4d,0x4c,0x4b,0x4a,0x48,0x46,0x46, +0x45,0x45,0x44,0x44,0x43,0x44,0x45,0x78,0x65,0x55,0x2, 0xd, 0x14,0x1b,0x21,0x25, +0x2b,0x31,0x37,0x36,0x33,0x2d,0x28,0x20,0x19,0x14,0xd, 0x8, 0x1, 0x2, 0x5, 0xb, +0x10,0x18,0x1e,0x23,0x2a,0x30,0x35,0x3a,0x3e,0x3f,0x0, 0x1, 0x1, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x4, 0x9, 0xf, 0x15,0x1d,0x24,0x2a,0x30,0x35,0x3b,0x3e,0x3f,0x40, +0x3f,0x3e,0x3d,0x3d,0x3c,0x3c,0x3b,0x3b,0x39,0x37,0x1a,0x2d,0x65,0x55,0x1b,0x29, +0x27,0x1e,0x14,0x11,0x1a,0x26,0x2e,0x37,0x3d,0x3f,0x3d,0x37,0x2e,0x21,0x16,0xc, +0x5, 0x1, 0x0, 0x0, 0x1, 0x3, 0xa, 0x13,0x1d,0x26,0x2e,0x33,0x38,0x3a,0x16,0x21, +0x2b,0x32,0x30,0x2a,0x27,0x2a,0x2f,0x2d,0x24,0x1a,0x10,0x7, 0x1, 0x0, 0x2, 0x7, +0x10,0x19,0x23,0x2d,0x36,0x41,0x49,0x4c,0x4a,0x45,0x3c,0x34,0x2a,0x27,0x51,0x71, +0x50,0x55,0x28,0x12,0x11,0x18,0x23,0x29,0x2b,0x2a,0x2e,0x35,0x3c,0x3e,0x3f,0x39, +0x31,0x28,0x1e,0x15,0xe, 0x6, 0x3, 0x1, 0x0, 0x0, 0x3, 0xc, 0x16,0x20,0x2b,0x32, +0x37,0x39,0x20,0x29,0x32,0x37,0x31,0x28,0x21,0x2a,0x31,0x2d,0x23,0x1b,0x13,0x8, +0x1, 0x0, 0x1, 0x5, 0xc, 0x18,0x20,0x29,0x34,0x3e,0x47,0x4f,0x50,0x4d,0x45,0x3c, +0x34,0x31,0x26,0xcb,0x50,0x55,0x1d,0x2f,0x2c,0x25,0x1a,0x1b,0x20,0x29,0x31,0x31, +0x2e,0x2d,0x35,0x3d,0x3f,0x3d,0x38,0x2c,0x22,0x15,0xd, 0x6, 0x1, 0x0, 0x1, 0x6, +0x10,0x1b,0x24,0x2f,0x38,0x3d,0xd, 0x1b,0x27,0x31,0x32,0x28,0x1e,0x14,0x15,0x1d, +0x28,0x31,0x34,0x2a,0x1f,0x14,0x9, 0x1, 0x0, 0x4, 0xd, 0x17,0x21,0x2c,0x35,0x40, +0x47,0x47,0x44,0x3c,0x34,0x30,0x1b,0x82,0x50,0x55,0x19,0x2e,0x2a,0x1f,0x18,0x1b, +0x22,0x2d,0x30,0x2e,0x2e,0x35,0x3d,0x3f,0x3d,0x3a,0x2f,0x24,0x18,0xf, 0x7, 0x1, +0x0, 0x0, 0x3, 0xb, 0x16,0x1e,0x29,0x32,0x3a,0x3d,0x11,0x1f,0x28,0x32,0x30,0x26, +0x1b,0x14,0x1c,0x25,0x2e,0x35,0x2e,0x23,0x19,0x11,0x4, 0x0, 0x1, 0x8, 0x10,0x1c, +0x25,0x30,0x38,0x40,0x42,0x3f,0x39,0x32,0x2c,0x27,0xc0,0xd1,0x50,0x55,0x18,0x2c, +0x29,0x1e,0x14,0x13,0x16,0x1e,0x29,0x30,0x2e,0x2c,0x2b,0x37,0x3d,0x3f,0x3e,0x39, +0x30,0x25,0x1b,0x10,0x8, 0x1, 0x0, 0x2, 0x9, 0x13,0x1f,0x2d,0x38,0x3c,0x11,0x1a, +0x23,0x2f,0x33,0x29,0x20,0x16,0xe, 0x13,0x1d,0x28,0x32,0x31,0x28,0x1e,0x16,0xb, +0x2, 0x0, 0x1, 0x8, 0x12,0x1e,0x29,0x33,0x3b,0x3f,0x3c,0x32,0x29,0x26,0x30,0x6e, +0x50,0x55,0x16,0x2b,0x24,0x17,0xd, 0xa, 0xe, 0x15,0x24,0x28,0x25,0x23,0x2b,0x36, +0x3b,0x3d,0x3b,0x37,0x2b,0x20,0x15,0xb, 0x4, 0x0, 0x0, 0x3, 0xe, 0x19,0x27,0x33, +0x3d,0x3f,0x13,0x21,0x2e,0x37,0x3a,0x31,0x27,0x1c,0x13,0x1c,0x28,0x34,0x3e,0x37, +0x2d,0x22,0x18,0xc, 0x1, 0x0, 0x3, 0xd, 0x18,0x25,0x31,0x3c,0x47,0x48,0x42,0x38, +0x2e,0x2a,0x31,0x62,0x50,0x55,0x35,0x2e,0x27,0x22,0x1f,0x1b,0x16,0x10,0xc, 0x8, +0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x6, 0xb, 0xe, 0x12,0x17,0x1d,0x22,0x26, +0x2a,0x30,0x35,0x39,0x3d,0x3f,0x0, 0x0, 0x1, 0x4, 0x6, 0x8, 0xb, 0x10,0x16,0x1b, +0x1f,0x23,0x28,0x2d,0x32,0x36,0x3b,0x40,0x44,0x48,0x4a,0x4b,0x4c,0x4b,0x4a,0x48, +0x46,0x43,0x40,0x3e,0x3c,0x3a,0x3c,0x9c,0x34,0x55,0x9, 0x17,0x1d,0x26,0x2e,0x37, +0x3c,0x3f,0x3b,0x33,0x2b,0x22,0x1a,0x11,0xb, 0x5, 0x3, 0x1, 0x1, 0x0, 0x0, 0x0, +0x1, 0x6, 0xa, 0x11,0x19,0x22,0x2a,0x32,0x39,0x3d,0x30,0x30,0x2f,0x2c,0x26,0x1e, +0x17,0xd, 0x5, 0x0, 0x0, 0x1, 0x6, 0xe, 0x15,0x1e,0x26,0x2c,0x32,0x3a,0x41,0x48, +0x50,0x5b,0x61,0x64,0x64,0x60,0x5b,0x56,0x51,0x4f,0xd8,0x2c,0x33,0x55,0x26,0x1c, +0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x17,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x0, 0x0, 0x1, 0x4, 0xb, 0x12,0x18,0x1f,0x28,0x31,0x37,0x3c,0x40,0x1, 0x7, +0xe, 0x14,0x1c,0x23,0x2c,0x34,0x3e,0x44,0x4c,0x54,0x5b,0x60,0x5d,0x55,0x4f,0x49, +0x43,0x3d,0x38,0x32,0x2b,0x26,0x22,0x1f,0x1e,0x1c,0x1c,0x1c,0x1c,0x1d,0x66,0x54, +0x74,0x55,0x3e,0x2c,0x21,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, +0x1e,0x1e,0x1d,0x1a,0x11,0xc, 0x7, 0x2, 0x0, 0x0, 0x3, 0xa, 0x12,0x1c,0x23,0x2c, +0x38,0x40,0xc, 0x0, 0x6, 0xf, 0x17,0x22,0x29,0x32,0x3b,0x41,0x47,0x4f,0x55,0x5c, +0x66,0x71,0x79,0x3e,0x76,0x6d,0x64,0x5a,0x52,0x4b,0x42,0x39,0x35,0x33,0x32,0x32, +0x31,0x31,0xf3,0xdb,0x74,0x55,0x9, 0x7, 0x6, 0x6, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, +0x3, 0x2, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xa, 0x10,0x14,0x1b,0x22, +0x28,0x2e,0x34,0x39,0x3d,0x40,0x0, 0xb, 0x11,0x16,0x1b,0x22,0x28,0x2c,0x33,0x39, +0x40,0x46,0x4d,0x52,0x56,0x5c,0x61,0x68,0x6d,0x73,0x73,0x71,0x71,0x71,0x70,0x70, +0x6f,0x6f,0x6f,0x6f,0x6d,0x6e,0x79,0x80,0x44,0x55,0x17,0x13,0x12,0x12,0x11,0x10, +0xf, 0xd, 0xc, 0xb, 0x9, 0x8, 0x7, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x1, 0x4, +0xb, 0x10,0x16,0x1d,0x24,0x29,0x31,0x39,0x3d,0x40,0x0, 0xe, 0x16,0x1a,0x1f,0x24, +0x29,0x2e,0x33,0x38,0x3e,0x43,0x47,0x50,0x55,0x59,0x62,0x69,0x6e,0x75,0x7c,0xff, +0x7d,0x7c,0x79,0x73,0x6d,0x68,0x60,0x5a,0x57,0x56,0x5d,0x8, 0x44,0x55,0x0, 0x7, +0xb, 0xd, 0x10,0x12,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x19,0x1c,0x1e,0x20,0x22, +0x23,0x25,0x27,0x29,0x2b,0x30,0x32,0x33,0x35,0x38,0x39,0x3b,0x3d,0x3f,0x3e,0x29, +0x1f,0x18,0xf, 0x7, 0x6, 0xc, 0x12,0x1d,0x25,0x2d,0x36,0x3e,0x3b,0x35,0x2c,0x26, +0x20,0x19,0x11,0xa, 0x3, 0x3, 0x9, 0x10,0x18,0x24,0x2c,0x33,0x3a,0x3e,0x60,0x9b, +0x32,0x55,0x0, 0x5, 0x5, 0x5, 0x4, 0x3, 0x2, 0x3, 0x5, 0x7, 0xa, 0xe, 0x11,0x19, +0x1b,0x1c,0x1d,0x1c,0x1c,0x1d,0x1f,0x22,0x25,0x2a,0x31,0x33,0x35,0x37,0x38,0x39, +0x3c,0x40,0x0, 0x12,0x1c,0x24,0x2b,0x34,0x3c,0x39,0x2f,0x29,0x21,0x16,0xf, 0xd, +0x14,0x1e,0x2a,0x33,0x31,0x27,0x20,0x18,0x10,0x7, 0xa, 0x10,0x1a,0x26,0x2f,0x37, +0x3d,0x3f,0xfb,0x8f,0x32,0x55,0x2c,0x23,0x1f,0x19,0x13,0xc, 0x7, 0x3, 0x0, 0x0, +0x0, 0x1, 0x5, 0xa, 0xf, 0x16,0x1d,0x23,0x2a,0x30,0x36,0x3b,0x3e,0x40,0x3f,0x3e, +0x3b,0x38,0x33,0x2f,0x2b,0x28,0x9, 0x1, 0x0, 0x1, 0x3, 0x9, 0xe, 0x14,0x1b,0x21, +0x27,0x2e,0x36,0x3b,0x3e,0x41,0x41,0x40,0x3d,0x3a,0x36,0x2f,0x2b,0x26,0x20,0x1c, +0x16,0x10,0xc, 0xa, 0x9, 0xb, 0x36,0xdc,0x30,0x55,0x1a,0x9, 0x5, 0x1, 0x0, 0x0, +0x0, 0x2, 0x5, 0x9, 0xf, 0x16,0x1c,0x22,0x2a,0x31,0x36,0x39,0x3c,0x3e,0x3f,0x3f, +0x3d,0x38,0x30,0x27,0x1f,0x18,0x12,0xb, 0x6, 0x5, 0x7, 0x12,0x19,0x22,0x2c,0x36, +0x3f,0x49,0x53,0x5c,0x63,0x66,0x64,0x5f,0x58,0x4c,0x43,0x3d,0x34,0x2b,0x22,0x1b, +0x15,0xb, 0x4, 0x0, 0x0, 0x1, 0x4, 0xb, 0x13,0x18,0xf1,0xc, 0x30,0x55,0x18,0x2c, +0x34,0x39,0x3c,0x3d,0x3f,0x3f,0x3f,0x3d,0x3b,0x36,0x30,0x2a,0x24,0x1c,0x16,0xd, +0x6, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x5, 0x9, 0xf, 0x17,0x1e,0x24,0x1, 0x2, +0x8, 0xe, 0x14,0x1a,0x21,0x28,0x30,0x37,0x40,0x49,0x50,0x55,0x59,0x5c,0x5c,0x58, +0x51,0x48,0x3f,0x38,0x31,0x2b,0x25,0x1d,0x17,0x11,0xa, 0x4, 0x1, 0x1, 0x9d,0xbf, +0x30,0x55,0x16,0x7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x1, 0x4, 0x8, 0xe, 0x16,0x1f,0x28, +0x30,0x38,0x3c,0x3e,0x3f,0x40,0x3f,0x3f,0x3d,0x3b,0x37,0x32,0x2c,0x25,0x1d,0x16, +0xf, 0xc, 0x53,0x46,0x3e,0x35,0x2e,0x27,0x20,0x1a,0x14,0xd, 0x6, 0x1, 0x0, 0x0, +0x3, 0xa, 0x13,0x1a,0x20,0x27,0x2d,0x33,0x3a,0x40,0x48,0x4f,0x54,0x58,0x5a,0x5a, +0x58,0x57,0xc6,0x55,0x30,0x55,0x7, 0x1, 0x4, 0xa, 0x10,0x18,0x20,0x2a,0x32,0x38, +0x3c,0x3e,0x3f,0x3e,0x3d,0x3b,0x39,0x35,0x30,0x27,0x21,0x19,0x12,0xb, 0x6, 0x3, +0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x1d,0x12,0x9, 0x5, 0x1, 0x0, 0x0, 0x1, 0x5, +0xd, 0x17,0x20,0x2a,0x32,0x3b,0x45,0x4e,0x58,0x63,0x69,0x6b,0x6a,0x64,0x5d,0x57, +0x4f,0x47,0x40,0x38,0x32,0x2f,0x1a,0xb5,0x30,0x55,0x21,0x13,0xc, 0x8, 0x5, 0x2, +0x1, 0x0, 0x0, 0x1, 0x3, 0x8, 0xf, 0x17,0x1e,0x24,0x2b,0x32,0x39,0x3d,0x3e,0x3f, +0x3f,0x3d,0x3a,0x36,0x30,0x29,0x21,0x1a,0x16,0x13,0x5, 0x9, 0xe, 0x14,0x1a,0x22, +0x29,0x30,0x38,0x3f,0x47,0x4d,0x51,0x51,0x4f,0x4d,0x49,0x42,0x39,0x31,0x2b,0x25, +0x1e,0x17,0x10,0x8, 0x3, 0x0, 0x0, 0x1, 0x3, 0x5, 0xaf,0x13,0x30,0x55,0x38,0x3f, +0x3d,0x3a,0x36,0x2e,0x26,0x1f,0x14,0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0x9, 0xe, 0x14,0x1c,0x23,0x2a,0x34,0x38,0x3a,0x3b,0x3d,0x3d,0x3d,0x3d,0x29,0x1a, +0x10,0x9, 0x4, 0x0, 0x0, 0x1, 0x4, 0xc, 0x14,0x1c,0x22,0x28,0x2f,0x37,0x3f,0x47, +0x4f,0x56,0x5a,0x5b,0x59,0x56,0x4e,0x47,0x40,0x37,0x30,0x28,0x22,0x1f,0x2a,0xa9, +0x30,0x55,0x3e,0x3b,0x38,0x33,0x2b,0x24,0x1d,0x16,0x10,0x7, 0x3, 0x1, 0x0, 0x0, +0x0, 0x1, 0x1, 0x3, 0x6, 0xc, 0x15,0x1c,0x23,0x29,0x2f,0x35,0x38,0x3b,0x3c,0x3e, +0x3f,0x3f,0x1f,0x10,0xa, 0x6, 0x0, 0x0, 0x0, 0x2, 0x4, 0xc, 0x12,0x18,0x1e,0x25, +0x2c,0x35,0x3c,0x42,0x4a,0x51,0x56,0x56,0x53,0x4e,0x49,0x40,0x3a,0x33,0x2c,0x25, +0x1f,0x1c,0xf9,0xa2,0x30,0x55,0x1f,0x2b,0x31,0x35,0x38,0x3b,0x3e,0x3f,0x3f,0x3d, +0x3a,0x34,0x2d,0x27,0x23,0x1d,0x17,0x10,0x9, 0x4, 0x1, 0x0, 0x0, 0x1, 0x3, 0x6, +0xa, 0xf, 0x15,0x1b,0x20,0x23,0x45,0x42,0x3e,0x38,0x34,0x2d,0x24,0x1c,0x15,0x11, +0xb, 0x6, 0x2, 0x0, 0x0, 0x0, 0x1, 0x3, 0x7, 0xd, 0x12,0x18,0x20,0x28,0x30,0x36, +0x3c,0x42,0x47,0x48,0x49,0x4a,0x65,0x9d,0x30,0x55,0x1c,0x2a,0x33,0x39,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3d,0x3a,0x35,0x2e,0x28,0x23,0x1c,0x15,0xf, 0x9, 0x4, 0x1, 0x0, +0x0, 0x1, 0x1, 0x4, 0x8, 0xd, 0x13,0x19,0x1e,0x22,0x40,0x3e,0x3a,0x33,0x2f,0x29, +0x22,0x1b,0x15,0x10,0xa, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x5, 0xa, 0x11,0x17,0x1c, +0x24,0x2a,0x30,0x35,0x3b,0x40,0x43,0x44,0x45,0x45,0xcb,0xc6,0x30,0x55,0x5, 0x3, +0x4, 0x7, 0xa, 0x10,0x17,0x21,0x28,0x2e,0x33,0x38,0x3c,0x3e,0x3f,0x3f,0x3e,0x3b, +0x38,0x31,0x29,0x21,0x18,0xf, 0x9, 0x4, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26,0x35, +0x3d,0x45,0x4b,0x51,0x53,0x52,0x4f,0x4c,0x46,0x41,0x3b,0x34,0x2e,0x25,0x1e,0x17, +0x11,0x9, 0x3, 0x0, 0x0, 0x2, 0x6, 0xc, 0x12,0x18,0x1e,0x24,0x2c,0x31,0xf4,0xb6, +0x30,0x55,0xa, 0x5, 0x5, 0x5, 0x8, 0xf, 0x16,0x20,0x29,0x31,0x36,0x3a,0x3c,0x3e, +0x3f,0x3f,0x3e,0x3c,0x3a,0x33,0x2d,0x24,0x1c,0x14,0xf, 0x8, 0x4, 0x0, 0x0, 0x0, +0x1, 0x2, 0x35,0x46,0x4e,0x56,0x5d,0x65,0x68,0x66,0x60,0x57,0x4f,0x47,0x3f,0x37, +0x2e,0x25,0x1e,0x16,0x10,0x6, 0x2, 0x0, 0x1, 0x5, 0xb, 0x15,0x1d,0x28,0x2f,0x39, +0x41,0x45,0xf0,0xbc,0x30,0x55,0x7, 0x3, 0x3, 0x3, 0x4, 0x7, 0xf, 0x17,0x20,0x28, +0x30,0x36,0x3b,0x3d,0x3f,0x3f,0x3d,0x39,0x36,0x2d,0x25,0x1d,0x16,0xd, 0x8, 0x2, +0x0, 0x0, 0x1, 0x2, 0x3, 0x5, 0x2e,0x3f,0x48,0x50,0x59,0x5f,0x67,0x68,0x63,0x5d, +0x52,0x4a,0x3e,0x35,0x2b,0x20,0x18,0x10,0xa, 0x3, 0x0, 0x0, 0x1, 0x7, 0xe, 0x19, +0x22,0x2b,0x31,0x3a,0x42,0x47,0xef,0xc9,0x30,0x55,0x3b,0x3c,0x3c,0x3b,0x39,0x36, +0x2f,0x27,0x21,0x19,0x11,0xb, 0x5, 0x1, 0x0, 0x0, 0x1, 0x2, 0x4, 0x6, 0xa, 0x10, +0x16,0x1f,0x26,0x2d,0x33,0x39,0x3c,0x3e,0x3f,0x3f,0x22,0x31,0x3b,0x41,0x47,0x4d, +0x56,0x59,0x5a,0x58,0x55,0x51,0x4b,0x43,0x3d,0x35,0x29,0x20,0x18,0x11,0x9, 0x3, +0x0, 0x0, 0x1, 0x3, 0x7, 0xf, 0x15,0x1b,0x21,0x26,0x2b,0xa0,0x30,0x55,0x37,0x38, +0x37,0x34,0x2d,0x26,0x1c,0x16,0xe, 0x9, 0x4, 0x2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x5, +0xa, 0x10,0x17,0x20,0x26,0x2e,0x35,0x3a,0x3c,0x3e,0x3f,0x3f,0x3e,0x3e,0x30,0x40, +0x49,0x50,0x59,0x5e,0x60,0x5d,0x56,0x50,0x47,0x41,0x39,0x33,0x2a,0x20,0x1a,0x10, +0xa, 0x5, 0x1, 0x0, 0x0, 0x3, 0x8, 0x10,0x17,0x1f,0x25,0x2f,0x38,0x3c,0x37,0xc3, +0x30,0x55,0x3b,0x3d,0x3d,0x3b,0x38,0x32,0x27,0x1c,0x13,0xe, 0x8, 0x3, 0x0, 0x0, +0x0, 0x1, 0x3, 0x7, 0xb, 0x12,0x18,0x20,0x28,0x31,0x39,0x3d,0x3f,0x40,0x3f,0x3f, +0x3e,0x3e,0x33,0x45,0x4e,0x57,0x5d,0x65,0x6c,0x6a,0x66,0x63,0x5c,0x53,0x4a,0x40, +0x38,0x2e,0x25,0x1a,0x11,0x8, 0x4, 0x0, 0x0, 0x2, 0x9, 0x10,0x19,0x21,0x2a,0x32, +0x39,0x3e,0x7, 0x90,0x30,0x55,0x39,0x2b,0x24,0x1c,0x15,0xe, 0x9, 0x6, 0x5, 0x6, +0x9, 0x10,0x19,0x22,0x27,0x2e,0x35,0x3b,0x3e,0x3f,0x3d,0x38,0x32,0x2c,0x26,0x1f, +0x19,0x13,0xb, 0x5, 0x1, 0x0, 0x6, 0x0, 0x1, 0x2, 0x6, 0xb, 0x11,0x17,0x1d,0x24, +0x2a,0x2f,0x32,0x34,0x35,0x36,0x37,0x3b,0x41,0x47,0x4e,0x56,0x5d,0x61,0x64,0x65, +0x65,0x63,0x60,0x5c,0x57,0x54,0xd1,0x4a,0x46,0x55,0x0, 0x1, 0x3, 0x5, 0x7, 0x8, +0xa, 0xb, 0xc, 0xe, 0xf, 0x11,0x12,0x14,0x16,0x1a,0x1e,0x22,0x24,0x27,0x2a,0x2c, +0x2e,0x31,0x33,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x3f,0x1, 0xe, 0x14,0x1b,0x23,0x28, +0x2e,0x35,0x3a,0x40,0x48,0x4f,0x56,0x5d,0x62,0x61,0x5a,0x53,0x4e,0x47,0x40,0x3b, +0x35,0x2d,0x29,0x22,0x1b,0x17,0x10,0x9, 0x5, 0x1, 0x6d,0x7d,0x54,0x55,0x0, 0x2, +0x3, 0x5, 0x6, 0x8, 0xb, 0x10,0x13,0x16,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x22,0x22, +0x22,0x22,0x23,0x25,0x28,0x2e,0x31,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x3f,0x6, 0x17, +0x20,0x27,0x30,0x38,0x3e,0x39,0x32,0x2b,0x25,0x1e,0x18,0x10,0x9, 0x9, 0x10,0x18, +0x1f,0x26,0x2f,0x36,0x3c,0x38,0x2f,0x27,0x1f,0x18,0xf, 0x8, 0x1, 0x2, 0xc7,0x75, +0x31,0x55,0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x3, 0x8, 0xd, 0x12,0x15,0x17,0x18,0x1a, +0x1b,0x1c,0x1d,0x1d,0x1e,0x1f,0x22,0x27,0x2e,0x35,0x38,0x3b,0x3d,0x3e,0x3f,0x40, +0x3f,0x3e,0x6, 0x15,0x1b,0x23,0x29,0x2f,0x37,0x3c,0x37,0x2e,0x27,0x20,0x1a,0x13, +0xe, 0x14,0x1a,0x21,0x27,0x2f,0x38,0x3f,0x3d,0x35,0x2e,0x26,0x20,0x18,0x11,0xb, +0x3, 0x0, 0x67,0x3f,0x31,0x55,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, +0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e, +0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, +0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, +0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, +0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16, +0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, +0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, +0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10, +0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c,0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c, +0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, 0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, +0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, 0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10, +0x19,0x13,0x1c,0x10,0x14,0x1a,0x10,0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15, +0x73,0x23,0x1c,0x74,0x23,0x1c,0x75,0xe, 0x1c,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, +0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e, +0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d, +0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d, +0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31, +0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78, +0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11, +0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78, +0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, +0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d, +0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2, +0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22, +0x9f,0x21,0x7f,0x12,0x12,0x1f,0x7, 0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12, +0x1f,0x7, 0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11, +0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15, +0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d, +0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, +0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x22,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x3a,0x5, 0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0x75,0x5f,0x0, 0xc2,0xe, 0xc2,0xf, 0xc2,0x11,0x75,0x60, +0x0, 0x75,0x61,0x0, 0xc2,0x13,0xc2,0x14,0x75,0x62,0x0, 0xc2,0x16,0x75,0x63,0x0, +0xc2,0x17,0xc2,0x18,0xc2,0x19,0x75,0x64,0x0, 0xc2,0xa, 0x75,0x5d,0x0, 0x75,0x5e, +0x64,0xc2,0x1a,0xc2,0x1b,0x75,0x65,0x0, 0xd2,0x5, 0xd2,0x6, 0xd2,0x7, 0xd2,0x1c, +0xc2,0xc, 0xd2,0xd, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x21,0x25,0xb, 0xa, 0x40,0x5d, +0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0, +0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80,0xdf,0x2, 0x2c,0x9b, +0x0, 0x0, 0x0, 0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd,0xc7,0xfb,0x7e,0xfb,0xfb, +0x1, 0xbb,0xc, 0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, 0xf, 0x2, 0x10,0x3, 0x11, +0x4, 0x12,0x5, 0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, 0x17,0xa, 0x18,0xb, 0x19, +0xc, 0x1a,0xd, 0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94,0x1f,0x81,0x1e,0x70,0x1d, +0x62,0x1c,0x55,0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31,0x17,0x2b,0x16,0x25,0x15, +0x21,0x14,0x1c,0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11,0xf, 0x10,0xe, 0xca,0xf8, +0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, 0x34,0xb, 0x54,0x69,0xff, +0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d,0xff,0x78,0xe6,0x7f,0x10, +0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44,0x7a,0xb, 0xb0,0xb, 0x14, +0x4d,0x44,0x78,0xf5,0x22,0x32,0x1, 0x19,0x1, 0x0, 0x2, 0xf8,0x4, 0xe7,0x5, 0xce, +0x6, 0xc2,0x7, 0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff,0x1, 0x2, 0x0, 0x1, 0xff, +0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, 0x48,0x3, 0x7d,0x32,0x22, +0x6d,0x33,0x9d,0x32,0x22,0x0, 0x4, 0x34,0x8c,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x33, +0xff,0x1, 0x0, 0x1, 0x25,0xf6,0x1, 0x0, 0x1, 0x38,0xb0,0x0, 0x0, 0x2, 0x39,0x2, +0x0, 0x0, 0x0, 0x2, 0x39,0x4, 0x0, 0x0, 0x0, 0x1, 0x39,0x6, 0x0, 0x0, 0x1, 0x3, +0x9e,0xff,0x0, 0x1, 0x36,0x7c,0x0, 0x0, 0x1, 0x3a,0x2, 0x0, 0x0, 0x1, 0x3a,0x3, +0x0, 0x0, 0x2, 0x36,0x93,0x0, 0x0, 0x0, 0x1, 0x36,0xb6,0x0, 0x0, 0x1, 0x37,0x2f, +0x0, 0x0, 0x1, 0x37,0x30,0x0, 0x0, 0x1, 0x37,0x31,0x0, 0x0, 0x3c,0x33,0x50,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x33,0xc8,0x0, +0x0, 0x1, 0x33,0xc9,0x0, 0x0, 0x1, 0x33,0xca,0x0, 0x0, 0x4, 0x0, 0x14,0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x37,0xd3,0x1, 0x0, 0x2, 0x37,0xd6,0x0, 0x0, 0x0, 0x1, 0x0, +0x66,0x0, 0x0, 0x1, 0x0, 0x67,0x0, 0x0, 0x1, 0x0, 0x68,0x0, 0x0, 0x1, 0x37,0xda, +0x1, 0x0, 0x1, 0x38,0x54,0x0, 0x0, 0x1, 0x3a,0x4, 0x0, 0x0, 0x6, 0x34,0x49,0x3f, +0x1f,0x50,0x11,0x20,0x10,0x0, 0x1, 0x34,0x4f,0x24,0x0, 0x1, 0x39,0xf9,0x0, 0x0, +0x1, 0x39,0xfa,0x0, 0x0, 0x1, 0x39,0xfb,0x0, 0x0, 0x1, 0x39,0xfc,0x0, 0x0, 0x1, +0x39,0xfd,0x0, 0x0, 0x1, 0x2f,0xa9,0x0, 0x0, 0x1, 0x33,0x46,0x0, 0x0, 0x1, 0x2, +0x8a,0x0, 0x0, 0x2, 0x2, 0xab,0x0, 0x0, 0x0, 0x1, 0x2, 0xe9,0x0, 0x0, 0x4, 0x38, +0x55,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x39,0xf3,0x0, 0x0, 0x1, 0x39,0xf4,0x0, 0x0, +0x2, 0x39,0xf5,0x0, 0x0, 0x0, 0x1, 0x39,0xf7,0x64,0x0, 0x1, 0x39,0xf8,0x0, 0x0, +0x1, 0x3a,0x5, 0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, 0x1, 0x3, 0xff,0x0, 0x0, 0x2, +0x2b,0xb9,0x2b,0xbf,0x0, 0x1, 0x2f,0x7f,0x2, 0x0, 0x1, 0x2f,0xa8,0x0, 0x0, 0x1, +0x39,0xd5,0x0, 0x0, 0x1, 0x39,0x53,0xff,0x0, 0x1, 0x39,0x54,0x0, 0x0, 0x1, 0x39, +0x55,0x0, 0x0, 0x1, 0x39,0x56,0x40,0x0, 0x1, 0x39,0x57,0x40,0x0, 0x4, 0x39,0xeb, +0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x39,0xef,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x33,0xcb, +0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x33,0xcf,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x33,0xd3, +0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x33,0xe4,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x39,0xfe, +0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x3, 0xe8,0x0, 0xc, 0x1, 0xf4,0x3, 0x20,0x0, 0xa, +0x1, 0x4a,0x2, 0xbc,0x0, 0x9, 0x0, 0xc8,0x1, 0xf4,0x0, 0x6, 0x0, 0x3c,0x1, 0x2c, +0x0, 0x6, 0x0, 0x3c,0x0, 0x64,0x0, 0x6, 0x0, 0x3c,0x0, 0x50,0x0, 0x6, 0x0, 0x0, +0x0, 0xe, 0x1c,0x23,0x5, 0xdc,0x0, 0x32,0x3, 0xe8,0x0, 0x28,0x0, 0x0, 0x0, 0x1e, +0x12,0x39,0x84,0x12,0x47,0xa6,0x12,0x23,0x29,0x12,0x6a,0x5e,0x12,0x6d,0xa5,0x2, +0x23,0x22,0x74,0x1, 0x7a,0xb3,0x37,0xde,0x22,0x12,0x73,0xaf,0x12,0x23,0x5e,0x2, +0x23,0x32,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x23,0x3b,0x7d,0x43,0x7e,0xa3,0x33, +0xe8,0xbe,0xa0,0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a,0x59,0x43,0x33,0xeb,0x59, +0x23,0x33,0xed,0x7c,0xba,0x4, 0x7a,0xb3,0x33,0xe8,0xc3,0x22,0xd3,0x22,0x6d,0x33, +0x7e,0x24,0x6, 0xfc,0x12,0x23,0x3b,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x7, 0x7a,0x2, +0x23,0x3b,0x7e,0x34,0x60,0xa3,0x12,0x23,0xbc,0x12,0x26,0xbb,0x12,0x2f,0xad,0x12, +0x73,0x66,0x12,0x39,0x84,0x12,0x47,0x9f,0x12,0xcc,0x66,0x12,0x23,0x29,0x12,0x6a, +0x5e,0x12,0x6a,0x49,0x12,0x6d,0xa5,0x2, 0x23,0x22,0x7e,0x34,0x61,0x4f,0x7e,0x24, +0x0, 0xff,0xb, 0x1a,0x30,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x61,0x51,0x7e,0x24,0x0, +0xff,0xb, 0x1a,0x30,0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x61,0x53,0x7e,0x24,0x0, 0xff, +0xb, 0x1a,0x30,0x22,0x7e,0x34,0x61,0x55,0x12,0x23,0xbc,0x7a,0x37,0x28,0x95,0x7e, +0x34,0x61,0xc0,0x12,0x23,0xbc,0x7a,0x37,0x28,0x99,0x7e,0x34,0x61,0xbe,0x12,0x23, +0xbc,0x7a,0x37,0x28,0x97,0x7e,0x34,0x62,0x18,0x12,0x23,0xbc,0x7a,0x37,0x28,0x9b, +0x7e,0x34,0x61,0xc2,0x12,0x23,0xbc,0x7a,0x37,0x28,0x9d,0x7e,0x34,0x61,0xc4,0x12, +0x23,0xbc,0x7a,0x37,0x28,0x9f,0x7e,0x34,0x61,0xc6,0x12,0x23,0xbc,0x12,0x8f,0xf3, +0x12,0x23,0xbc,0x7a,0x37,0x28,0xa3,0x90,0x61,0xca,0xe4,0x93,0x7a,0xb3,0x28,0xa5, +0xe4,0x7a,0xb3,0x28,0xa8,0x12,0x4f,0xde,0x3e,0x34,0x7e,0x8, 0x25,0xf7,0xe4,0x2, +0x20,0xe3,0x12,0x25,0xe6,0x7e,0xb3,0x37,0xe5,0xb4,0x1, 0x16,0x7e,0x34,0x62,0x3a, +0x12,0x23,0xbc,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x3c,0x12,0x23,0xbc,0x7a,0x37, +0x2a,0x5c,0x7e,0xb3,0x28,0xa8,0xb4,0x1, 0x37,0x7e,0x34,0x62,0x44,0x12,0x23,0xbc, +0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x46,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x5c,0x7e, +0x34,0x62,0x48,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x62,0x4a,0x12,0x23, +0xbc,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62,0x4c,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x53, +0x7e,0xb3,0x2a,0x2, 0x70,0x21,0x7e,0x27,0x2a,0x5a,0x7d,0x32,0x7e,0x14,0x0, 0x4, +0xad,0x13,0x7d,0x31,0x12,0x25,0x5a,0xbe,0x34,0x0, 0x50,0x28,0x4, 0x7e,0x34,0x0, +0x50,0x2d,0x32,0x7a,0x37,0x2a,0x5a,0x22,0x7e,0x54,0x0, 0x54,0x7e,0x44,0x0, 0xff, +0x69,0x32,0x0, 0x4, 0x69,0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x26,0x7a,0x15, +0x24,0x7e,0x34,0x0, 0x20,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x6, 0x12,0xbc,0xf2, +0x7e,0x34,0x61,0x4f,0x12,0x23,0xbc,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x3, 0x9f,0x7e, +0x34,0x61,0x51,0x12,0x23,0xbc,0xe, 0x34,0xe, 0x34,0x7a,0x73,0x3, 0xa0,0x7e,0x34, +0x61,0x55,0x12,0x23,0xbc,0x12,0x25,0x5a,0x7a,0x73,0x3, 0xa1,0x7e,0x34,0x61,0x59, +0x12,0x23,0xbc,0x12,0x25,0x5a,0x7a,0x73,0x3, 0xa2,0x7e,0x34,0x61,0x5b,0x12,0x23, +0xbc,0x12,0x25,0x5a,0x7a,0x73,0x3, 0xa3,0x7e,0x34,0x61,0x5d,0x12,0x23,0xbc,0x12, +0x25,0x5a,0x7a,0x73,0x3, 0xa4,0x7e,0x34,0x0, 0x59,0xca,0x39,0x7e,0x34,0x61,0x65, +0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x3, 0xa5,0x12,0x20,0xbe,0x1b,0xfd,0xe5,0x25,0x7a, +0xb3,0x3, 0xd0,0xe5,0x28,0x7a,0xb3,0x3, 0xbf,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34, +0x1e,0x34,0x22,0x90,0x60,0x99,0xe4,0x93,0x7a,0xb3,0x2a,0x4d,0x90,0x60,0x9e,0xe4, +0x93,0x7a,0xb3,0x2a,0x4e,0x7e,0x34,0x61,0x55,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x4f, +0x7e,0x34,0x61,0x59,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x51,0x7e,0x14,0x61,0x5b,0x12, +0x47,0xe0,0x7a,0x27,0x2a,0x53,0x7a,0x37,0x2a,0x55,0x90,0x60,0x9d,0xe4,0x93,0x7a, +0xb3,0x2a,0x59,0x12,0x23,0x9a,0x12,0xcc,0xec,0x7e,0x34,0x62,0x18,0x12,0x23,0xbc, +0x7a,0x37,0x2a,0x60,0x90,0x60,0x9f,0xe4,0x93,0x7a,0xb3,0x2a,0x64,0x90,0x60,0xa0, +0xe4,0x93,0x7a,0xb3,0x2a,0x65,0x7e,0x34,0x60,0xa1,0x12,0x23,0xbc,0x7a,0x37,0x2a, +0x66,0x7e,0x34,0x61,0x5d,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x62,0xe4,0x7a,0xb3,0x2a, +0x6b,0x7a,0xb3,0x16,0x92,0x22,0x12,0x23,0x9a,0x12,0xcc,0xec,0x7e,0x34,0x61,0x55, +0x12,0x23,0xbc,0x7a,0x37,0x2a,0x4f,0x7e,0x34,0x61,0x59,0x12,0x23,0xbc,0x7a,0x37, +0x2a,0x51,0x7e,0x34,0x61,0x5b,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x53,0x22,0x7e,0x34, +0x62,0x4e,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x5a,0x7e,0x34,0x62,0x50,0x12,0x23,0xbc, +0x7a,0x37,0x2a,0x5c,0x7e,0x34,0x62,0x52,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x4f,0x7e, +0x34,0x62,0x54,0x12,0x23,0xbc,0x7a,0x37,0x2a,0x51,0x7e,0x34,0x62,0x56,0x12,0x23, +0xbc,0x7a,0x37,0x2a,0x53,0x22,0xca,0xf8,0x7e,0xf3,0x38,0xb5,0xbe,0xf0,0x5, 0x78, +0xb, 0x74,0x1, 0x7a,0xb3,0x38,0xb5,0x12,0x0, 0xa, 0x80,0x52,0xbe,0xf0,0x4, 0x78, +0x13,0x12,0xcc,0x4f,0x12,0x23,0xbc,0x12,0x26,0xbb,0xe4,0x7a,0xb3,0x2b,0x2, 0x12, +0x7a,0x1e,0x80,0x3a,0xbe,0xf0,0x6, 0x78,0x19,0x12,0xcc,0x4f,0x12,0x23,0xbc,0x12, +0x26,0xbb,0x12,0x41,0xa, 0xe4,0x7a,0xb3,0x2b,0x1e,0x12,0x7b,0xdc,0x12,0xcd,0x81, +0x80,0x1c,0xbe,0xf0,0x7, 0x78,0x1d,0x12,0xcc,0x4f,0x12,0x23,0xbc,0x12,0x26,0xbb, +0x12,0x7b,0xd1,0x50,0xfb,0x12,0x7f,0xd8,0x12,0x47,0x8b,0x12,0x6a,0x5e,0x74,0x2, +0x7a,0xb3,0x38,0xb5,0xda,0xf8,0x22,0x7e,0x34,0x3, 0xe8,0x6d,0x22,0x7a,0x27,0x34, +0x38,0x7a,0x37,0x34,0x3a,0x22,0x7e,0xb3,0x3, 0xc4,0x14,0x68,0x5d,0x14,0x78,0x2, +0xe1,0x6d,0x14,0x68,0x6d,0x24,0x3, 0x68,0x2, 0xe1,0x65,0x12,0xcd,0xc2,0x38,0x8, +0x30,0x12,0xf, 0x12,0x95,0x5a,0x68,0xa, 0x12,0x68,0x54,0xe4,0x7a,0xb3,0x39,0x9a, +0x80,0x7b,0x7e,0xb3,0x3, 0xa5,0x30,0xe0,0x74,0x7e,0x73,0x3, 0xa6,0xa, 0x27,0x7e, +0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x3, 0xef,0xb4,0x1, 0xb, 0x7e,0x34,0x62,0x6a, +0x12,0x23,0xbc,0x2e,0x34,0x4, 0x0, 0xbe,0x37,0x39,0x98,0x50,0x50,0x12,0x68,0x54, +0x12,0x6a,0x2f,0xe4,0x7a,0xb3,0x39,0x9c,0x80,0x43,0x12,0xcd,0xc2,0x28,0x39,0xe4, +0x7a,0xb3,0x3, 0xc4,0x7e,0xb3,0x39,0x9a,0xb4,0x1, 0x3, 0x12,0x6a,0x2f,0xd2,0x1b, +0x80,0x26,0x74,0xff,0x7a,0xb3,0x3, 0x9e,0x7e,0x34,0x60,0xa5,0x12,0x23,0xbc,0x12, +0x26,0xbb,0x12,0x29,0xaa,0x12,0x23,0x72,0xe4,0x7a,0xb3,0x3, 0xc4,0x7a,0xb3,0x39, +0xf8,0xd2,0x1b,0x80,0x8, 0x12,0x6a,0x2f,0xe4,0x7a,0xb3,0x39,0xf8,0x12,0x94,0x4c, +0x2, 0x27,0x73,0xca,0x3b,0x7e,0xb3,0x3, 0xc4,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x28, +0xb9,0x6c,0xcc,0x6c,0xdd,0x7e,0xb3,0x3, 0xef,0xb4,0x1, 0xc, 0x90,0x61,0x62,0xe4, +0x93,0x7c,0xeb,0x90,0x61,0x64,0x80,0xa, 0x90,0x61,0x61,0xe4,0x93,0x7c,0xeb,0x90, +0x61,0x63,0xe4,0x93,0x7c,0xfb,0x12,0x94,0xef,0x7d,0xf3,0x12,0x7b,0xd1,0x50,0xfb, +0x74,0x1, 0x7a,0xb3,0x39,0x9b,0x12,0x38,0x1d,0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74, +0xa, 0x12,0x7a,0x7f,0x12,0xcd,0x5e,0x7e,0xe7,0x2b,0xd, 0x7a,0xe5,0x25,0x7e,0xb3, +0x2a,0xfa,0xf5,0x24,0x74,0x4, 0x7a,0xb3,0x2a,0xfa,0x7e,0xe7,0x2b,0xd, 0x5e,0xe4, +0x0, 0x3f,0x7a,0xe7,0x2b,0xd, 0x7e,0xb3,0x2a,0xfa,0x12,0xbf,0x9e,0x7c,0x7b,0x74, +0x6, 0xac,0x7b,0x7e,0x24,0x0, 0x4, 0x12,0x1e,0xb9,0x7d,0x23,0x7d,0x3f,0x12,0x25, +0x5a,0xad,0x32,0x7a,0x37,0x2b,0x7, 0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0x95, +0x62,0x1, 0x9a,0x12,0x26,0xb7,0x30,0xf, 0x2, 0x1, 0xa0,0x7c,0xbe,0x12,0x7f,0xa6, +0x12,0x3f,0xce,0x80,0xf, 0x80,0x7, 0x12,0x29,0x11,0xe4,0x12,0x29,0x49,0x20,0x93, +0xf6,0x12,0x28,0xe1,0x30,0x1c,0xf7,0x30,0x1b,0xf4,0xd2,0x1, 0x12,0x28,0xc7,0xe4, +0x12,0x13,0xde,0xb, 0xc0,0x12,0x91,0x2c,0x12,0x95,0x7a,0x7e,0xa3,0x39,0x9a,0x4c, +0xaa,0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x9b,0x4c,0xaa,0x68,0xb, 0x7e,0xb3,0x3, +0xef,0x70,0x5, 0xe4,0x7a,0xb3,0x39,0x9a,0x12,0x28,0xbc,0x78,0x18,0x7e,0xb3,0x39, +0x9a,0x60,0x12,0xe4,0x7a,0xb3,0x39,0x9a,0x7a,0xb3,0x2a,0x2, 0x7a,0xb3,0x2a,0x3, +0x7e,0xd0,0x1, 0x80,0x1b,0x12,0x28,0xbc,0x68,0x10,0x7e,0xb3,0x39,0x9a,0x70,0xa, +0x7e,0xd0,0x1, 0xe4,0x7a,0xb3,0x3, 0xc4,0x80,0x6, 0xbc,0xfc,0x28,0x2, 0x1, 0x13, +0xe4,0x7a,0xb3,0x2b,0x4, 0x7e,0x35,0x25,0x7a,0x37,0x2b,0xd, 0xe5,0x24,0x7a,0xb3, +0x2a,0xfa,0x4c,0xdd,0x68,0x3, 0x12,0x6a,0x5e,0xda,0x3b,0x22,0x7e,0x73,0x39,0xea, +0xa, 0x37,0x5e,0x34,0x0, 0x2, 0x22,0x30,0x1, 0x6, 0x12,0x2f,0xa5,0x2, 0x13,0x96, +0x12,0xcd,0xbb,0xc2,0x2, 0x2, 0x28,0xd8,0xa9,0xd0,0xce,0xa2,0x2, 0xa9,0x91,0xc9, +0x22,0x30,0x1c,0x5, 0xc2,0x1, 0x12,0x28,0xc7,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30, +0x1b,0x3, 0x20,0x1c,0x14,0x12,0x29,0x11,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, +0x12,0x29,0x49,0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x1, 0x2, 0x28, +0xc7,0x74,0x81,0x7a,0xb3,0x39,0xf3,0x22,0x80,0x1d,0x12,0x29,0x11,0x12,0x94,0x79, +0x68,0x5, 0xc2,0x1, 0x12,0x28,0xc7,0x7e,0xb3,0x33,0xea,0xbe,0xb0,0x2, 0x68,0x18, +0x20,0x1b,0x15,0xe4,0x12,0x29,0x49,0x20,0x93,0xe0,0x12,0x29,0x11,0xa9,0xd1,0xcd, +0xa9,0xc5,0xea,0x74,0x2, 0x2, 0x29,0x49,0x22,0x7c,0xab,0x7e,0xb3,0x39,0xf3,0xb4, +0x81,0x38,0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, +0xc2,0xaf,0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe, +0xa0,0x2, 0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9, +0xd1,0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x39,0xf3,0x22, +0xd2,0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12,0x94,0x79,0x68,0x7, 0xc2,0x0, 0xc2,0x1, +0x12,0x28,0xc7,0x12,0x29,0x18,0x30,0x1b,0xeb,0x22,0x12,0x29,0x11,0x12,0x94,0x81, +0x75,0xcd,0x0, 0xa9,0xd6,0xeb,0xa9,0xd7,0xcd,0xc2,0xce,0x12,0xcd,0x3a,0x12,0x2c, +0xeb,0x74,0x1, 0x12,0x29,0x49,0xa9,0xc6,0xeb,0xa9,0xc7,0xcd,0xd2,0xce,0xe5,0x25, +0x7e,0x71,0x24,0x2, 0x29,0xd6,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x29,0xf7, +0x7a,0x61,0xfc,0x12,0x2c,0x85,0x12,0x7b,0x3a,0xd2,0x0, 0x12,0x94,0xc4,0x12,0x2f, +0xa5,0x12,0x13,0xde,0x2, 0x13,0x96,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xca,0x79,0xa9, +0xd5,0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x12,0x29,0xf7,0x74,0xf, 0x12,0x0, 0x46,0x7c, +0xfb,0x74,0xf, 0x7c,0x7f,0x5e,0x70,0xfe,0x12,0x29,0xf7,0x74,0xc, 0x12,0x0, 0x46, +0x7c,0xfb,0x54,0x7f,0x68,0x8, 0x74,0xc, 0x7e,0x70,0xf8,0x12,0x29,0xf7,0x90,0x61, +0x18,0xe4,0x93,0x7c,0xab,0xbe,0xa0,0x7, 0x38,0x11,0xa, 0x3a,0x2e,0x34,0x0, 0x3, +0x12,0x2d,0x27,0x7c,0xb7,0xa, 0x7b,0xb, 0x75,0x80,0x1c,0x90,0x61,0x17,0xe4,0x93, +0xb4,0x1, 0x14,0xbe,0xa0,0x7, 0x28,0xf, 0xa, 0x3a,0x2e,0x34,0x0, 0x3, 0x12,0x2d, +0x27,0xa, 0x77,0x2e,0x74,0x0, 0x7, 0x74,0xe, 0x7c,0x7f,0x12,0x29,0xf7,0x74,0x7, +0x12,0x0, 0x46,0x7c,0xfb,0x5e,0xf0,0xfb,0x90,0x60,0x2, 0xe4,0x93,0xa, 0x3b,0x3e, +0x34,0x3e,0x34,0x4c,0xf7,0x74,0x7, 0x7c,0x7f,0x12,0x2c,0x82,0xda,0x79,0x22,0xca, +0xd8,0xca,0x79,0x7d,0xd3,0x90,0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90,0x60,0x51,0xe4, +0x93,0x7c,0x8b,0xa, 0x38,0xa, 0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c,0x7c,0xe7,0x12, +0x26,0xb7,0xa9,0xd0,0xc4,0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x0, 0x46,0x7c,0x8b,0x74, +0x7, 0x7e,0x70,0xf, 0x12,0x2c,0x82,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x33,0xcf,0x79, +0x51,0x0, 0x6, 0x7e,0x54,0x0, 0x80,0x7e,0x1f,0x33,0xcf,0x79,0x51,0x0, 0x8, 0x7e, +0x54,0x0, 0xc, 0x7e,0x1f,0x33,0xcf,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78, +0xb, 0x7e,0x1f,0x33,0xcf,0x12,0x2c,0x7a,0x44,0x1, 0x80,0x20,0x7e,0x1f,0x33,0xcf, +0x12,0x2c,0x7a,0x44,0x8, 0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x33,0xcf,0x78,0x7, +0x12,0x2c,0x7a,0x54,0xfb,0x80,0x5, 0x12,0x2c,0x7a,0x44,0x4, 0x1b,0x1a,0x50,0x7e, +0x1f,0x33,0xcb,0x69,0xe1,0x0, 0x84,0x69,0x51,0x0, 0x90,0x7d,0xf5,0x2e,0x34,0x0, +0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3,0x3, 0xd0,0xbe,0xb0,0x6, 0x40,0x3, +0xb4,0xff,0xe, 0x12,0x2c,0x8f,0x54,0xe6,0x12,0x2c,0x8c,0x4e,0x54,0x1, 0xa4,0x80, +0xc, 0x12,0x2c,0x8f,0x5e,0x54,0xfe,0xe6,0x12,0x2c,0x8c,0x44,0xa4,0x1b,0x1a,0x50, +0xbe,0xd4,0x0, 0x2, 0x78,0x2d,0x7e,0x1f,0x33,0xcf,0x12,0x2c,0x7a,0x5e,0x54,0x0, +0xf, 0x1b,0x1a,0x50,0x7e,0x1f,0x33,0xcf,0x12,0x2c,0x7a,0x44,0x50,0x1b,0x1a,0x50, +0x7e,0x34,0x0, 0x2, 0x12,0x2d,0xdc,0x12,0x2d,0xb5,0x12,0x2d,0x92,0x7a,0x37,0x34, +0x90,0x81,0x36,0x6c,0xdd,0x81,0x30,0x4c,0xdd,0x78,0x4, 0x6c,0x99,0x80,0x2b,0xbc, +0xfd,0x40,0x12,0xa, 0xcd,0x9, 0x9c,0x2a,0xb8,0xbe,0x90,0x23,0x40,0x3, 0x7e,0x90, +0x22,0xb, 0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3,0x9, 0x9c,0x2a,0xdb,0xbe, +0x90,0x1c,0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x7e,0x1f,0x33,0xcf,0x12,0x2c, +0x7a,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0xa, 0xc9,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4, +0x3e,0xc4,0x7e,0x1f,0x33,0xcf,0x12,0x2c,0x7a,0x4d,0x5c,0x1b,0x1a,0x50,0xe5,0xe, +0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x4, 0xe5, +0xe, 0xa, 0x3b,0x12,0x2d,0xdc,0x12,0x2d,0xb5,0xbe,0xd4,0x0, 0x1, 0x78,0x10,0x12, +0x2d,0xb5,0x12,0x2d,0x92,0x74,0x2, 0xac,0xbd,0x59,0x35,0x34,0x92,0x80,0xf, 0x12, +0x2d,0x92,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59,0x32,0x34,0x92,0xb, 0xd0, +0xbc,0xed,0x28,0x2, 0x61,0x97,0xa9,0xd5,0xcb,0x74,0x7, 0x7c,0x78,0x12,0x2c,0x82, +0xa9,0xc0,0xc4,0x7e,0x1f,0x33,0xcb,0x79,0xe1,0x0, 0x84,0x7e,0x1f,0x33,0xcb,0x79, +0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x6, 0x7e,0xf, 0x33, +0xcf,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, 0x10,0x7e,0xf, 0x33, +0xcf,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x2e,0x34,0x0, 0xe, 0xb, 0x1a, +0x50,0x22,0x12,0x29,0xf7,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0x1b,0x1a,0x50,0x7e, +0x1f,0x33,0xcb,0x2e,0x34,0x0, 0x84,0xb, 0x1a,0x50,0x22,0x12,0x2f,0xad,0x12,0x24, +0xb8,0x12,0x73,0x66,0x12,0x23,0x10,0x7e,0xb3,0x3, 0xc6,0x24,0xfd,0x68,0x9, 0xb, +0xb1,0x78,0xf4,0x12,0x50,0x18,0x80,0xef,0x12,0x48,0x8f,0x80,0xea,0x6d,0x33,0x7e, +0x8, 0x0, 0x24,0x7e,0x24,0x0, 0x12,0x12,0xbc,0xf2,0xe5,0x34,0x20,0xe7,0x1b,0xa9, +0xd5,0xcb,0x74,0x3, 0x7e,0x71,0x27,0x12,0x29,0xf7,0x74,0xb, 0x7e,0x71,0x2f,0x12, +0x29,0xf7,0x74,0xc, 0x7e,0x71,0x30,0x12,0x2c,0x82,0x22,0x12,0xcd,0xbb,0xc2,0x0, +0x12,0x7b,0xb5,0xc2,0x2, 0x12,0x28,0xd8,0xc2,0x0, 0x12,0x94,0xc4,0xa9,0xd5,0xcb, +0x74,0xf, 0x12,0x0, 0x46,0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77,0x12,0x29,0xf7,0xe5, +0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x2, 0x2c,0x85,0x7e,0xf, 0x33,0xcb,0x69,0x20, +0x0, 0x86,0x5e,0x50,0x1f,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22, +0x7e,0x24,0x3, 0x9f,0x30,0xf, 0x5a,0xc2,0xf, 0x9, 0x72,0x0, 0x2, 0x12,0x2d,0x25, +0x7a,0x37,0x2a,0x4f,0x9, 0x72,0x0, 0x3, 0x12,0x2d,0x25,0x7a,0x37,0x2a,0x51,0x9, +0x72,0x0, 0x4, 0x12,0x2d,0x25,0x7a,0x37,0x2a,0x53,0x7e,0x29,0x70,0xa, 0x37,0x3e, +0x34,0x3e,0x34,0x7a,0x37,0x2a,0x5a,0x9, 0x72,0x0, 0x1, 0xa, 0x37,0x3e,0x34,0x3e, +0x34,0x7a,0x37,0x2a,0x5c,0x9, 0x72,0x0, 0x5, 0x12,0x2d,0x25,0x7a,0x37,0x2a,0x62, +0x9, 0x72,0x0, 0x41,0xbe,0x73,0x2a,0x6b,0x68,0x7, 0x7a,0x73,0x2a,0x6b,0x2, 0xb5, +0x8e,0x22,0x7e,0xf, 0x33,0xcf,0x69,0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10, +0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74,0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60, +0x80,0x14,0x78,0xf4,0x22,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x33,0xcf,0x79,0x30,0x0, +0x4, 0x7e,0xf, 0x33,0xcf,0x69,0x30,0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e, +0x34,0x0, 0x1, 0x79,0x30,0x0, 0x12,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12, +0x7e,0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x7a,0x7f,0x7c,0x23,0x1b,0x30,0xa5,0xba, +0x0, 0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x30,0x8, 0x3b,0xc2,0x8, +0x12,0x26,0x46,0x7e,0x73,0x38,0xb6,0x7a,0x73,0x2a,0x4d,0x7e,0x73,0x38,0xb7,0x7a, +0x73,0x2b,0x1d,0x7e,0x73,0x38,0xb7,0x7a,0x73,0x2b,0x1, 0x7e,0xb3,0x38,0xb8,0x60, +0x18,0x7e,0x34,0x0, 0x2, 0x12,0x2a,0x8f,0x7e,0x34,0x0, 0x1, 0x12,0x2a,0x8f,0x6d, +0x33,0x12,0x2a,0x8f,0xe4,0x7a,0xb3,0x38,0xb8,0x12,0x3d,0x6d,0x2, 0x2e,0x3f,0xe5, +0xc, 0x70,0x2, 0xe1,0x5e,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, 0xfe,0x12,0x72,0xd0, +0x12,0x79,0x1f,0x7e,0x8, 0x2a,0x6d,0x12,0x9, 0xa1,0xe5,0xc, 0x30,0xe1,0x6, 0x53, +0xc, 0xfd,0x12,0xbf,0x5e,0xe5,0xc, 0x30,0xe2,0x32,0x53,0xc, 0xfb,0x7e,0xb3,0x2b, +0x12,0x60,0x9, 0x7e,0x8, 0x2a,0x6d,0x12,0x6, 0xba,0x80,0xb, 0x7e,0xb3,0x2b,0x65, +0x7e,0x73,0x2b,0x64,0x12,0xb, 0xad,0x7e,0x73,0x2b,0x12,0x2e,0x70,0xff,0x92,0x1, +0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x2a,0x77,0x12,0xb, 0x1e,0xe5,0xc, 0x30,0xe3, +0x47,0x53,0xc, 0xf7,0x7e,0x73,0x38,0xe3,0x7a,0x73,0x2b,0xf, 0x12,0x7c,0x90,0x7a, +0xb3,0x2f,0xa9,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e,0x73,0x2f,0xa9,0x7a, +0x73,0x38,0xbb,0x12,0x6c,0x29,0x12,0x46,0x26,0x7e,0x73,0x38,0xe4,0xbe,0x73,0x2b, +0x62,0x68,0x6, 0x7a,0x73,0x2b,0x62,0xd2,0xe, 0x30,0xe, 0x9, 0xc2,0xe, 0x12,0x6f, +0x6e,0xe4,0x12,0xa, 0x66,0x12,0x6d,0xa5,0xe5,0xc, 0x30,0xe4,0xf, 0x53,0xc, 0xef, +0x7e,0x43,0x38,0xe5,0x7e,0x50,0xa, 0xac,0x45,0x12,0x40,0x26,0xe5,0xc, 0x30,0xe6, +0x4e,0x53,0xc, 0xbf,0x7e,0x73,0x38,0xd1,0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a, +0xb3,0x38,0xd1,0xa9,0xd5,0xcb,0x74,0xe, 0x12,0x0, 0x46,0x7c,0x7b,0x5e,0x70,0xf, +0x7e,0x63,0x38,0xd1,0xa, 0x26,0x2e,0x24,0x0, 0x3, 0x12,0xa3,0x5d,0x7c,0x65,0x4c, +0x76,0x74,0xe, 0x12,0x29,0xf7,0x12,0x0, 0x46,0x12,0x2c,0x85,0x7e,0x73,0x38,0xd4, +0x7a,0x73,0x2b,0x14,0x7e,0x73,0x38,0xd3,0x7a,0x73,0x2b,0x1f,0x12,0xcd,0x81,0xe5, +0xc, 0x30,0xe5,0xa, 0x53,0xc, 0xdf,0x7e,0xb3,0x38,0xbb,0x2, 0x40,0x74,0x22,0x24, +0xab,0x68,0x10,0x24,0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74, +0x5, 0x80,0x2d,0x7e,0xb3,0x33,0xff,0xb4,0x5, 0x2a,0x12,0x2d,0xd8,0x12,0xba,0xa3, +0x2, 0xbb,0xbd,0x7e,0xb3,0x33,0xff,0xb4,0x5, 0x1a,0x12,0x2d,0xd8,0x75,0xe9,0xff, +0x22,0x7e,0xb3,0x33,0xff,0xb4,0x5, 0xc, 0x12,0x2d,0xd8,0x2, 0xbb,0xb7,0x74,0x1, +0x7a,0xb3,0x33,0xff,0x22,0xd2,0x2, 0x12,0x28,0xd8,0x74,0x1, 0x22,0xe4,0x12,0x94, +0x93,0x12,0xbb,0x59,0x12,0x26,0xb7,0x12,0xbb,0xd4,0x12,0x29,0xfd,0x12,0xba,0x99, +0x12,0xbb,0x70,0x12,0x0, 0x9, 0x12,0xbb,0x7c,0x12,0x88,0x8, 0x12,0xbb,0x8c,0xd2, +0xaf,0x12,0xba,0xeb,0x12,0xbd,0x2c,0x12,0x2c,0xbd,0x12,0x7b,0x3a,0x7e,0x8, 0x34, +0x3c,0x12,0xac,0xb9,0x90,0x60,0x50,0xe4,0x93,0xca,0xb8,0x90,0x60,0x51,0xe4,0x93, +0x7c,0x7b,0x7e,0x24,0xff,0xff,0xda,0xb8,0x2, 0x12,0x34,0xca,0xf8,0x7c,0xab,0xbe, +0xa0,0x34,0x38,0x2, 0x21,0xc, 0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x2b,0x10,0x41, +0x27,0xbe,0xa0,0x36,0x68,0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23, +0xb, 0x24,0x7a,0x25,0x8, 0x2e,0x37,0x34,0x8a,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68, +0x2, 0x41,0x27,0x75,0x5c,0x36,0x41,0x27,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39, +0x78,0x1b,0x7e,0xf3,0x38,0xd5,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd5,0xbe,0xa0,0x39, +0x78,0x3, 0x75,0x5c,0x38,0xa, 0x3f,0x9, 0xb3,0x2b,0x21,0x41,0x27,0xbe,0xa0,0x3a, +0x68,0x5, 0xbe,0xa0,0x3b,0x78,0x1b,0x7e,0xf3,0x38,0xd7,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xd7,0xbe,0xa0,0x3b,0x78,0x3, 0x75,0x5c,0x3a,0xa, 0x3f,0x9, 0xb3,0x2b,0x44, +0x41,0x27,0xbe,0xa0,0xfb,0x78,0x6, 0x7e,0xb3,0x2b,0x12,0x41,0x27,0xbe,0xa0,0x5e, +0x78,0x26,0x7e,0xf, 0x33,0xcb,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x5e,0x54,0x0, 0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, +0x7c,0xa7,0x4c,0xba,0x44,0x80,0x41,0x27,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d, +0x78,0x1b,0x7e,0xf3,0x38,0xd9,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd9,0xbe,0xa0,0x3d, +0x78,0x3, 0x75,0x5c,0x3c,0xa, 0x3f,0x9, 0xb3,0x2a,0x7a,0x41,0x27,0xbe,0xa0,0x3e, +0x68,0x5, 0xbe,0xa0,0x3f,0x78,0x1b,0x7e,0xf3,0x38,0xdb,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xdb,0xbe,0xa0,0x3f,0x78,0x3, 0x75,0x5c,0x3e,0xa, 0x3f,0x9, 0xb3,0x2a,0x9d, +0x41,0x27,0xbe,0xa0,0x40,0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3, +0x38,0xb1,0x41,0x27,0xbe,0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3, +0x38,0xf6,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xf6,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x5c, +0x4e,0xa, 0x3f,0x2e,0x37,0x34,0x88,0x7e,0x39,0xb0,0x41,0x27,0xbe,0xa0,0x51,0x68, +0x5, 0xbe,0xa0,0x52,0x78,0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff, +0x7e,0xb3,0x39,0x1, 0xa, 0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3, +0x39,0x1, 0xbe,0xa0,0x52,0x78,0x3, 0x75,0x5c,0x51,0x7c,0xb7,0x41,0x27,0xbe,0xa0, +0x5c,0x68,0x5, 0xbe,0xa0,0x5d,0x78,0x1a,0x7e,0xf3,0x38,0xca,0x7c,0xbf,0x4, 0x7a, +0xb3,0x38,0xca,0xbe,0xa0,0x5d,0x78,0x3, 0x75,0x5c,0x5c,0x7c,0xbf,0x12,0xb4,0xc7, +0x41,0x27,0xbe,0xa0,0x60,0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3, +0x33,0xdc,0x41,0x27,0xbe,0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x7a,0xbe,0xa0,0xf4, +0x68,0x5, 0xbe,0xa0,0xf5,0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25, +0xa, 0x9, 0xb3,0x34,0x90,0xbe,0xa0,0xf5,0x78,0x5d,0x75,0x5c,0xf4,0x80,0x58,0xbe, +0xa0,0xf0,0x68,0x5, 0xbe,0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7, +0x80,0x45,0xbe,0xa0,0xf2,0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e, +0x14,0x7e,0x1f,0x34,0x8c,0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, +0x56,0x80,0x24,0x7d,0x53,0x80,0x20,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x17, +0xbe,0xa0,0xf7,0x78,0x9, 0x7e,0x34,0x62,0x4e,0x12,0x32,0x2a,0x80,0x9, 0xbe,0xa0, +0xfd,0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a, +0x50,0x22,0xca,0x3b,0x7e,0x73,0x3, 0xe3,0xa, 0x37,0x6d,0x22,0x7a,0x1d,0x26,0x7e, +0x33,0x3, 0xe5,0xa, 0x13,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x33,0x3, 0xe4,0xa, 0x93, +0x6d,0x88,0x7e,0x33,0x3, 0xe6,0xa, 0x73,0x6d,0x66,0x7e,0x14,0x61,0x37,0x7e,0x4, +0x0, 0xff,0xb, 0xa, 0x40,0x12,0x32,0xf9,0x7a,0x1d,0x26,0x7e,0x34,0x61,0x43,0x12, +0x32,0x2a,0x7e,0x1d,0x2a,0x7d,0x15,0x12,0x32,0xfb,0x7a,0x1d,0x2a,0x7f,0x14,0x12, +0x32,0xf9,0x7f,0x41,0x7f,0x13,0x7d,0x15,0x12,0x1e,0xfc,0x7c,0xf6,0x7c,0xe5,0xa, +0x64,0x12,0x4f,0xfc,0x50,0x60,0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x59,0x75,0x2e,0x0, +0x80,0x4b,0x7e,0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x76,0x12,0x89,0x21,0x7a, +0x35,0x24,0x7e,0xa1,0x2e,0x74,0x9, 0xa4,0x49,0x35,0x27,0x78,0x12,0x35,0x7e,0x7d, +0xa3,0x7e,0x35,0x24,0x6d,0x22,0x7e,0xd, 0x26,0xbf,0x10,0x40,0x17,0x7d,0x5a,0x6d, +0x44,0x7e,0xd, 0x2a,0xbf,0x20,0x40,0xc, 0xbf,0x14,0x38,0x8, 0x7d,0x3a,0x6d,0x22, +0xbf,0x13,0x28,0x7, 0xe5,0x2e,0x6c,0x77,0x12,0x5f,0x7, 0x5, 0x2e,0x7e,0x73,0x28, +0x84,0xbe,0x71,0x2e,0x38,0xac,0xda,0x3b,0x22,0x7d,0x14,0x12,0x1e,0xfc,0x7c,0x76, +0x7c,0x65,0xa, 0x24,0x22,0xca,0x79,0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c, +0xb4,0x12,0xa5,0xc7,0x7d,0x3, 0x30,0x13,0x2a,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28, +0xb5,0xbe,0x73,0x33,0x4c,0x78,0xa, 0x9, 0x65,0x28,0xb6,0xbe,0x63,0x33,0x4e,0x68, +0x10,0xbe,0x73,0x33,0x4d,0x78,0xc, 0x9, 0x75,0x28,0xb6,0xbe,0x73,0x33,0x4f,0x78, +0x2, 0x1e,0x4, 0x74,0x9, 0xac,0xbf,0x12,0xa5,0x13,0x12,0x33,0xd1,0x7d,0x30,0xad, +0x31,0x12,0x32,0xfe,0x7d,0x13,0x5d,0x1e,0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x29, +0x62,0x74,0x9, 0xac,0xbe,0x49,0x25,0x28,0xae,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e, +0x54,0x29,0x62,0x7d,0x2f,0x2d,0x21,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34,0x29,0x62, +0x9d,0xf1,0x1b,0x38,0xf0,0x74,0x9, 0xac,0xbf,0x12,0x33,0xc5,0x7d,0x30,0xad,0x31, +0x12,0x32,0xfe,0x7d,0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49,0x32,0x29,0x64, +0x74,0x9, 0xac,0xbe,0x49,0x5, 0x28,0xb0,0xbd,0x3, 0x28,0xd, 0x7d,0x2, 0x2e,0x4, +0x29,0x64,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x9, 0x2e,0x24,0x29,0x64,0x9d,0x31,0x1b, +0x28,0x30,0xda,0x79,0x22,0x49,0x25,0x29,0x64,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28, +0xb0,0x9d,0x32,0x12,0x21,0x15,0x7d,0x13,0x22,0x7d,0x41,0x7d,0x2, 0x7c,0x37,0x7c, +0x2b,0x74,0x4, 0xac,0xb2,0x49,0x35,0x2b,0xbf,0x49,0xf5,0x2b,0xc1,0x74,0x4, 0xac, +0xb3,0x49,0x25,0x2b,0xbf,0x49,0x55,0x2b,0xc1,0x12,0x33,0xd1,0x7d,0x3f,0x9d,0x35, +0x12,0x21,0x15,0x9d,0x34,0x12,0x21,0x15,0x7e,0x54,0x62,0x70,0x7e,0x44,0x0, 0xff, +0xb, 0x2a,0x20,0xbd,0x32,0x50,0x11,0x12,0x6f,0xde,0x7e,0x14,0x62,0x70,0x12,0x47, +0xe0,0xbd,0x32,0x50,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xf8,0x6c,0xff,0x7e,0xb7, +0x2f,0x9c,0x7e,0xc7,0x2f,0x9e,0x7e,0x97,0x2f,0x84,0x7e,0xd7,0x2f,0x86,0x7e,0xa7, +0x2f,0x98,0x7e,0xe7,0x2f,0x9a,0xe4,0x7e,0x73,0x2f,0xa8,0x1b,0x70,0x7d,0x2b,0x7d, +0x1c,0x12,0x33,0xd9,0x70,0x2, 0xa1,0x59,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0xa, 0x28, +0x13,0xe4,0x7e,0x70,0x9, 0x7e,0x27,0x2f,0xa0,0x7e,0x17,0x2f,0xa2,0x12,0x33,0xd9, +0x70,0x2, 0xa1,0x59,0x7e,0x73,0x2f,0xa8,0xbe,0x70,0x14,0x28,0x13,0xe4,0x7e,0x70, +0x13,0x7e,0x27,0x2f,0xa4,0x7e,0x17,0x2f,0xa6,0x12,0x33,0xd9,0x70,0x2, 0xa1,0x59, +0x7e,0x34,0x62,0x78,0x12,0x35,0x5e,0x28,0x4a,0x7e,0x34,0x62,0x76,0x12,0x35,0x68, +0x50,0x41,0x7e,0xb3,0x2f,0x81,0x70,0x3b,0x7e,0x34,0x62,0x7c,0x12,0x23,0xbc,0x12, +0x35,0x72,0x7d,0x8f,0x9d,0x83,0xbe,0x87,0x2f,0x82,0x50,0x27,0x7e,0x34,0x62,0x7a, +0x12,0xcd,0x93,0x9d,0xf8,0xbe,0xf7,0x2f,0x82,0x28,0x18,0x7d,0xfc,0x3e,0xf4,0xbd, +0xfb,0x40,0x2, 0xa1,0x59,0xbd,0xa9,0x50,0x5, 0x7e,0xf0,0x20,0x80,0x7b,0x7e,0xf0, +0x21,0x80,0x76,0x7e,0x34,0x62,0x80,0x12,0x35,0x68,0x28,0x6d,0x7e,0x34,0x62,0x7e, +0x12,0x35,0x5e,0x50,0x64,0x7e,0xb3,0x2f,0x81,0x70,0x5e,0x7e,0x34,0x62,0x84,0x12, +0x23,0xbc,0x12,0x35,0x72,0x7d,0xaf,0x9d,0xa3,0xbe,0xa7,0x2f,0x82,0x50,0x4a,0x7e, +0x34,0x62,0x82,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xa0,0x9d,0xfa,0xbe,0xf7,0x2f,0x82, +0x28,0x37,0x7d,0xfb,0x3e,0xf4,0xbd,0xfc,0x50,0x2f,0xbd,0xed,0x50,0x5, 0x7e,0xf0, +0x22,0x80,0x26,0x12,0xc3,0x6a,0x49,0x35,0x2b,0xbb,0x49,0x15,0x2b,0xbd,0x49,0x25, +0x2b,0xab,0x49,0x5, 0x2b,0xad,0x9d,0x10,0xbe,0x14,0x0, 0x20,0x18,0x8, 0x9d,0x32, +0xbe,0x34,0x0, 0x10,0x58,0x3, 0x7e,0xf0,0x23,0x7c,0xbf,0xda,0xf8,0x22,0x7e,0x24, +0x0, 0xff,0xb, 0x1a,0xf0,0xbd,0xfc,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xbd, +0xfb,0x22,0x7e,0x14,0x62,0x94,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xf0,0x22,0x7d,0xe3, +0x9f,0x11,0x7e,0x14,0x61,0x43,0x12,0x35,0x76,0x90,0x61,0x35,0xe4,0x93,0x70,0x3, +0x7d,0x3e,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x2a,0x6f,0x80, +0x4, 0x7e,0x83,0x2a,0x70,0x12,0x8f,0xeb,0xbe,0xe4,0x0, 0x3f,0x38,0x1e,0x7e,0x24, +0x0, 0x3f,0x9d,0x2e,0x7e,0x14,0x61,0x47,0x12,0x36,0xb3,0x12,0x36,0xd1,0x90,0x61, +0x45,0x12,0x36,0xc8,0x48,0x2, 0x7f,0x10,0x9f,0x1, 0x7f,0x10,0x12,0xcd,0xca,0xbe, +0xa0,0x0, 0x28,0x3a,0x7d,0x14,0x9e,0x14,0x0, 0x3f,0xbd,0x1e,0x38,0x17,0x12,0x37, +0xd3,0x2d,0x10,0xbd,0x1e,0x40,0xe, 0x12,0x36,0xa5,0x12,0x36,0xbb,0x48,0x36,0x7f, +0x10,0x1b,0x1c,0x80,0x30,0x12,0x37,0xd3,0x2d,0x10,0xbd,0x1e,0x50,0x31,0x7d,0x34, +0x9e,0x34,0x0, 0x20,0x12,0x36,0xab,0x12,0x36,0xd1,0x7d,0x1f,0x80,0x1d,0x4c,0xaa, +0x78,0x1d,0x12,0x37,0xc2,0xbd,0x5e,0x38,0x16,0x12,0x36,0xa5,0x12,0x36,0xbb,0x48, +0x4, 0x7f,0x10,0x1b,0x1c,0xa, 0xb, 0x7d,0x1f,0x9d,0x10,0x6d,0x0, 0x2f,0x10,0xbe, +0xe4,0x0, 0x3f,0x28,0x6f,0x12,0x37,0xc2,0xbd,0x5e,0x28,0x68,0x7d,0xd4,0xb, 0xd4, +0x1e,0xd4,0x7d,0x5d,0x1b,0x54,0xbd,0x5e,0x40,0xc, 0x7d,0x35,0x9d,0x3e,0x6d,0x22, +0x7e,0x14,0x61,0x4b,0x80,0xa, 0x7d,0x3e,0x9d,0x3d,0x6d,0x22,0x7e,0x14,0x61,0x4d, +0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x10,0x12,0x1e,0xfc,0x12,0x36,0xd5,0xbd,0x5e,0x7d, +0x1f,0x40,0xc, 0x1e,0x14,0x1b,0x14,0x6d,0x0, 0x9f,0x1, 0x7f,0x10,0x80,0x6, 0x1e, +0x14,0x6d,0x0, 0x2f,0x10,0x90,0x61,0x45,0x12,0x36,0xc8,0x58,0x4, 0x7f,0x10,0x80, +0x13,0x90,0x61,0x46,0xe4,0x93,0xa, 0xb, 0x7d,0x1f,0x9d,0x10,0x6d,0x0, 0xbf,0x10, +0x8, 0x2, 0x7f,0x10,0x22,0x7d,0x34,0x9e,0x34,0x0, 0x40,0x7d,0x2e,0x9d,0x23,0x7e, +0x14,0x61,0x49,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x22,0xad,0x32,0x6d,0x22,0x7c, +0x76,0x7c,0x65,0x1a,0x24,0x90,0x61,0x46,0xe4,0x93,0xa, 0x1b,0x6d,0x0, 0xbf,0x10, +0x22,0xad,0x32,0x6d,0x22,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x22,0x7e,0x73,0x37,0xdd, +0x7a,0x73,0x38,0x53,0x7e,0x27,0x33,0xe1,0x7e,0x14,0x61,0xce,0x12,0x36,0xb3,0x1e, +0x34,0xbd,0x32,0x50,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xdd,0x7e,0x14,0x61,0xce,0x12, +0x36,0xb3,0xbd,0x32,0x50,0x8, 0xe4,0x7a,0xb3,0x37,0xdb,0x12,0x37,0xbb,0x7e,0x37, +0x37,0xe3,0xbd,0x32,0x50,0x4, 0x7a,0x27,0x37,0xe3,0x12,0xb3,0x33,0x38,0x10,0x12, +0xb3,0x2b,0x38,0xb, 0x12,0xb3,0x23,0x38,0x6, 0x7e,0xb3,0x16,0x91,0x70,0x3d,0x12, +0xb0,0x5a,0x7e,0x14,0x61,0xce,0x12,0x36,0xb3,0x1e,0x34,0x1e,0x34,0xbd,0x32,0x28, +0x21,0x7e,0xb3,0x37,0xdb,0x4, 0x7a,0xb3,0x37,0xdb,0x7e,0x73,0x37,0xdb,0xbe,0x70, +0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x37,0xdb,0x12,0xcc,0xf7,0x7a,0xb3,0x38,0x50, +0x80,0x5, 0xe4,0x7a,0xb3,0x37,0xdb,0x7d,0x32,0x2, 0xb0,0xdc,0x2, 0x37,0x6f,0x12, +0x37,0xc9,0xe4,0x7a,0xb3,0x37,0xe9,0x22,0x12,0x36,0xdc,0x2, 0x37,0x7e,0x7e,0xb3, +0x37,0xdd,0x60,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xe5,0x7e,0xb3,0x38,0x53,0x70,0x3, +0x12,0xb0,0xb1,0x7e,0xb3,0x37,0xe5,0xb4,0x1, 0xc, 0x74,0x3, 0x12,0x37,0xb2,0x12, +0x23,0xbc,0x3e,0x34,0x80,0x7, 0xe4,0x12,0x37,0xb2,0x12,0x23,0xbc,0x7a,0x37,0x2a, +0x62,0x22,0x7a,0xb3,0x36,0xa1,0x7e,0x34,0x61,0x5d,0x22,0x74,0x2, 0x7a,0xb3,0x37, +0xdd,0x22,0x7d,0x54,0x9e,0x54,0x0, 0x3f,0x22,0xe4,0x7a,0xb3,0x38,0x4f,0x7a,0xb3, +0x38,0x4e,0x22,0x7d,0x4, 0x9e,0x4, 0x0, 0x1f,0x7e,0xd4,0x60,0xd1,0x7e,0xc4,0x0, +0xff,0xb, 0x6a,0x10,0x22,0x12,0xcd,0x8a,0xb4,0x1, 0x14,0xca,0x39,0x7e,0x18,0x38, +0xf1,0x7e,0x8, 0x25,0xee,0x12,0x20,0xbe,0x1b,0xfd,0x12,0x3d,0x64,0x80,0x12,0xca, +0x39,0x7e,0x18,0x38,0xf1,0x7e,0x8, 0x2b,0x70,0x12,0x20,0xbe,0x1b,0xfd,0x12,0x3a, +0x7e,0x2, 0x38,0x14,0x7a,0x1f,0x2a,0xfc,0x7a,0xf, 0x2a,0xf8,0x22,0x7a,0xb3,0x2b, +0x0, 0x70,0x14,0x12,0x3a,0x7e,0x12,0x38,0x14,0x7e,0x18,0x6, 0x76,0x7a,0x1f,0x6, +0xf4,0x7e,0x18,0x4, 0x7e,0x80,0x10,0xb4,0x1, 0x11,0x12,0x3d,0x64,0x12,0x38,0x14, +0x12,0x77,0xbe,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8,0x22,0x74,0x1, 0x12,0x0, +0x1e,0xe4,0x12,0x38,0x1d,0x12,0x38,0x64,0xe4,0x12,0x0, 0x1e,0x74,0x1, 0x12,0x38, +0x1d,0x2, 0x38,0x64,0xca,0x3b,0x7e,0xd3,0x2a,0x73,0x7e,0xc3,0x2a,0x74,0x7e,0x8, +0x1f,0x44,0x12,0x3f,0xe0,0x7e,0x8, 0x1f,0x8a,0x7e,0x34,0x0, 0x46,0x12,0x20,0xe3, +0x7e,0x8, 0x1f,0xd0,0x7e,0x34,0x0, 0xa, 0xe4,0x12,0x20,0xe3,0x7e,0x8, 0x1f,0xda, +0x7e,0x34,0x0, 0xa, 0x12,0x20,0xe3,0x7e,0xf3,0x2a,0xfc,0x7e,0x18,0x2a,0xdc,0x7a, +0x1d,0x24,0x7e,0x18,0x1f,0xd0,0x7a,0x1d,0x28,0x7c,0xbd,0x7c,0x7c,0x7e,0x8, 0x2a, +0xb9,0x12,0x39,0xba,0x6c,0xee,0x80,0x2b,0xa, 0x3e,0x9, 0xa3,0x2a,0xdc,0xa, 0x3a, +0x2e,0x34,0x20,0x78,0x12,0x7c,0x87,0x7c,0xab,0xbe,0xa0,0x1c,0x50,0x13,0xa, 0x3e, +0x12,0x39,0x7c,0xa, 0x4a,0x19,0xb4,0x1f,0x44,0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f, +0x8a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee,0x80,0x24,0xa, 0x3e,0x9, 0xa3,0x2a, +0xb9,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, 0x3c,0x2d,0x32,0x12,0x39,0x7c,0xa, +0x4a,0x19,0xb4,0x1f,0x60,0x7e,0xb3,0x2a,0xfb,0x19,0xb4,0x1f,0xa6,0xb, 0xe0,0xbc, +0xde,0x38,0xd8,0x7e,0xb3,0x2a,0xfd,0x7e,0x8, 0x1f,0xe4,0x60,0x9, 0x7e,0x18,0x1f, +0xd0,0x12,0xbd,0xb6,0x80,0x3, 0x12,0xbf,0x44,0x6c,0xee,0x7e,0x18,0x1f,0xe4,0x7a, +0x1f,0x1f,0x34,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1f,0xd0,0x7a,0x37,0x1f,0x38,0x74, +0x2, 0xac,0xbe,0x49,0x35,0x1f,0xda,0x7a,0x37,0x1f,0x3a,0x7e,0x70,0xe, 0xac,0x7e, +0x2e,0x34,0x1f,0x44,0x6d,0x22,0x7a,0x1f,0x1f,0x3c,0x7e,0x70,0xe, 0xac,0x7e,0x2e, +0x34,0x1f,0x8a,0x7a,0x1f,0x1f,0x40,0x7e,0x8, 0x1f,0x34,0x7c,0xbf,0x7c,0x7e,0x12, +0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b,0x22,0x2e,0x37,0x2a,0xfe, +0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x3, 0xc6,0x12,0x6f,0x6e,0x12,0x13,0xf5, +0x12,0xbe,0xb8,0xe4,0x12,0xa, 0x66,0x7e,0x24,0x3, 0xd4,0x12,0x40,0x26,0x74,0x1, +0x12,0x38,0x1d,0x12,0x7b,0xae,0x7e,0x34,0xd0,0xc, 0x12,0x1, 0xe, 0x12,0x38,0x4c, +0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7c,0x57,0x7c,0xab,0x6c,0x77, +0x80,0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e,0x7b,0x60,0xa, 0x46,0x2e,0x44, +0x20,0x78,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93,0x7c,0x6b,0xbe,0x60,0xd, 0x38, +0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d, +0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4, +0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40, +0xb, 0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80,0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2, +0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12,0x3a,0x77,0x60,0x5, 0x3e,0x44,0x14, +0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60, +0xe, 0x12,0x3a,0x77,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4, +0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0x3a,0x77,0x60,0x5, 0x3e,0x44,0x14,0x78, +0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20, +0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, 0x1, 0x7c,0xb6,0x22,0x7e,0x1f, +0x2b,0x74,0x7e,0xf, 0x2b,0x70,0x22,0x7a,0xb3,0x2b,0x0, 0x70,0x5, 0x12,0x3a,0x7e, +0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x3d,0x64,0x12,0x38,0x14,0x22,0x12,0xcd,0x8a,0xb4, +0x1, 0x17,0xca,0x39,0x7e,0x18,0x25,0xee,0x7e,0x8, 0x38,0xf1,0x12,0x20,0xbe,0x1b, +0xfd,0x12,0xcd,0x6f,0x12,0x3d,0x64,0x80,0x1a,0xca,0x39,0x7e,0x18,0x2b,0x70,0x7e, +0x8, 0x38,0xf1,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x37,0x2b,0x76,0x7a,0x37,0x34,0x88, +0x12,0x3a,0x7e,0x2, 0x38,0x14,0xca,0xf8,0x7c,0x6b,0xa5,0xbe,0x0, 0x9, 0x7c,0xb7, +0x12,0x87,0x0, 0xd2,0x8, 0xa1,0x58,0xa5,0xbe,0x1, 0x3d,0x7a,0x73,0x38,0xb2,0xa5, +0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, 0xd2,0x9, 0xa1,0x58,0xa5,0xbf,0xaa, +0x5, 0x12,0xcd,0x78,0x80,0x1e,0xa5,0xbf,0xab,0xa, 0x7e,0x34,0x5, 0x7a,0x7a,0x37, +0x34,0x8a,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80,0x2, 0xa1,0x58,0x7e,0x34,0x4, 0xfc, +0x7a,0x37,0x34,0x8a,0x6d,0x33,0x61,0xd4,0xbe,0x60,0x4, 0x40,0x20,0xbe,0x60,0x8, +0x38,0x1b,0x12,0x3d,0x5b,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, 0xa1,0x58, +0xa5,0xbe,0x8, 0x2, 0x80,0x2, 0xa1,0x58,0x12,0x0, 0x6e,0xa1,0x58,0xa5,0xbe,0xa, +0x9, 0x43,0xc, 0x20,0x7a,0x73,0x38,0xbb,0xa1,0x58,0xa5,0xbe,0xb, 0x8, 0x12,0x3d, +0x5b,0x12,0x7, 0xfb,0xa1,0x58,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c,0x38,0x2, +0x81,0xf0,0xbe,0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23,0x38,0x8, 0x12,0x3d,0x5d,0x43, +0xc, 0x40,0xa1,0x58,0xbe,0x60,0x15,0x40,0x1a,0xbe,0x60,0x18,0x38,0x15,0x12,0x3d, +0x5d,0xd2,0x8, 0xa5,0xbe,0x15,0x2, 0x80,0x2, 0xa1,0x58,0x74,0x7, 0x7a,0xb3,0x38, +0xb5,0xa1,0x58,0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3,0x38,0xca,0xa1,0x58,0xbe,0x60, +0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0x81,0xf0,0xa5,0xbe,0x2d,0x1b,0x12,0x3d, +0x5d,0x20,0x9, 0x2, 0xa1,0x58,0x7e,0x63,0x38,0xdd,0x7c,0x46,0x6c,0x55,0xa, 0x37, +0x2d,0x32,0x3e,0x34,0x7a,0x35,0x8, 0xa1,0x58,0xbe,0x60,0x2f,0x40,0xa, 0xbe,0x60, +0x33,0x38,0x5, 0x43,0xc, 0x8, 0x81,0xf0,0xa5,0xbe,0x34,0xf, 0x43,0xc, 0x10,0xbe, +0x70,0x64,0x38,0x2, 0x81,0xf0,0x7e,0x70,0x64,0x81,0xf0,0xbe,0x60,0x38,0x68,0x4, +0xa5,0xbe,0x39,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xd6,0x7c,0xbf,0x4, 0x7a,0xb3, +0x38,0xd6,0xa, 0x2f,0x19,0x72,0x2b,0x21,0xa5,0xbe,0x39,0x2, 0x80,0x2, 0xa1,0x58, +0x75,0x5c,0x38,0xa1,0x58,0xbe,0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21,0x43,0xc, +0x2, 0x7e,0xf3,0x38,0xd8,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xd8,0xa, 0x2f,0x19,0x72, +0x2b,0x44,0xa5,0xbe,0x3b,0x2, 0x80,0x2, 0xa1,0x58,0x75,0x5c,0x3a,0xa1,0x58,0xa5, +0xbe,0xfb,0x9, 0x43,0xc, 0x4, 0x7a,0x73,0x2b,0x12,0xa1,0x58,0xa5,0xbe,0x50,0x6, +0x7a,0x73,0x39,0x1, 0xa1,0x58,0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d,0x21,0x43, +0xc, 0x1, 0x7e,0xf3,0x38,0xda,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xda,0xa, 0x2f,0x19, +0x72,0x2a,0x7a,0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0xa1,0x58,0x75,0x5c,0x3c,0xa1,0x58, +0xbe,0x60,0x3e,0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x38,0xdc, +0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xdc,0xa, 0x2f,0x19,0x72,0x2a,0x9d,0xa5,0xbe,0x3f, +0x2, 0x80,0x2, 0xa1,0x58,0x75,0x5c,0x3e,0xa1,0x58,0xbe,0x60,0x40,0x40,0xd, 0xbe, +0x60,0x42,0x38,0x8, 0x12,0x3d,0x5d,0x75,0xd, 0x1, 0x80,0xa, 0xa5,0xbe,0x43,0xb, +0x12,0x3d,0x5d,0x75,0xd, 0x2, 0x12,0x37,0xe5,0x80,0x7d,0xa5,0xbe,0x44,0x8, 0x12, +0x3d,0x5d,0x12,0x3a,0x9c,0x80,0x71,0xbe,0x60,0x45,0x68,0x4, 0xa5,0xbe,0x46,0x5, +0x12,0x3d,0x5d,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, 0xa5,0xbe,0x4f,0x20,0x43,0xd, +0x4, 0x7e,0xf3,0x38,0xf7,0x7c,0xbf,0x4, 0x7a,0xb3,0x38,0xf7,0xa, 0x2f,0x2e,0x27, +0x34,0x88,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75,0x5c,0x4e,0x80,0x3a,0xa5,0xbe, +0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0,0x40,0x25,0xbe,0x60,0xf3,0x38, +0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0xf3,0x1a,0x7e,0x15, +0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x34,0x8c,0x2d,0x30,0x1b,0x1a,0x10,0x80, +0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8,0x22,0xd2,0x8, 0xa, 0x26,0x19, +0x72,0x38,0xb1,0x22,0x7e,0x1f,0x25,0xf2,0x7e,0xf, 0x25,0xee,0x22,0xe5,0xd, 0x60, +0x5a,0xe5,0xd, 0x30,0xe0,0xa, 0x53,0xd, 0xfe,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4, +0xe5,0xd, 0x30,0xe1,0x18,0x53,0xd, 0xfd,0x7e,0xb3,0x38,0xf5,0x70,0x4, 0x74,0x1, +0x80,0x1, 0xe4,0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0xbe,0x18,0xe5,0xd, 0x30, +0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a,0xb3,0x38,0xf6,0x7e,0xb3,0x38,0xf5,0x70,0xa, +0x74,0x1, 0x12,0x0, 0x1e,0x12,0x3a,0x7e,0x80,0x7, 0xe4,0x12,0x0, 0x1e,0x12,0x3d, +0x64,0x12,0x38,0x14,0x7e,0xb3,0x2a,0xfc,0x2, 0x3d,0xcc,0x22,0xca,0x79,0x7c,0xfb, +0x7e,0x8, 0x24,0xf2,0x12,0x3f,0xe0,0x7e,0xa3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x6c, +0xee,0x80,0x1d,0xa, 0x2e,0x9, 0x62,0x2a,0xdc,0xa, 0x26,0x12,0x81,0xeb,0x7c,0x6b, +0xbe,0x60,0x1c,0x50,0x9, 0xa, 0x2e,0x12,0x3e,0x44,0x19,0xb2,0x24,0xf2,0xb, 0xe0, +0xbc,0x7e,0x38,0xdf,0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, 0x62,0x2a,0xb9,0xbe,0x60, +0x23,0x50,0xd, 0xa, 0x1e,0xa, 0x27,0x2d,0x21,0x12,0x3e,0x44,0x19,0xb2,0x25,0xe, +0xb, 0xe0,0xbc,0xae,0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x24, +0xf2,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40, +0xe7,0xda,0x79,0x22,0x2e,0x27,0x2a,0xfe,0x7e,0x29,0xb0,0xa, 0x26,0x22,0xca,0xd8, +0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a,0xb3,0x2a,0xfa,0x12,0x3f,0xb0,0x7c,0xe7, +0x80,0x63,0x12,0x26,0xb7,0x12,0x3f,0x9f,0x12,0x3f,0xce,0x30,0x1c,0xfd,0x12,0x3f, +0xe9,0x12,0xcc,0x7f,0x12,0x0, 0x1e,0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, 0xac,0x5d, +0x49,0x32,0x6, 0xfc,0xbe,0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17,0x2a,0xfe, +0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18,0xbe,0x34, +0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x39,0x7c,0xbe,0xb0,0xff,0x68,0x8, 0x4, 0x7a, +0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x3f,0xbf,0xa, 0x3d,0xbd,0x32,0x48, +0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x95,0xda,0x79,0xda, +0xd8,0x22,0xca,0x3b,0x7e,0xe3,0x2a,0x74,0x7e,0xf3,0x2a,0xfa,0x74,0x1, 0x7a,0xb3, +0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x12,0xcd,0x5e,0x12,0x3f,0xb0,0x7e, +0x17,0x2a,0xfe,0x6d,0x0, 0x12,0x20,0xe3,0x7e,0xd0,0x7, 0x12,0x26,0xb7,0x6c,0xcc, +0x80,0x19,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c, +0x67,0x12,0x3f,0xf3,0x4c,0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x3f,0xbf,0xa, 0x3c, +0xbd,0x32,0x48,0xde,0x12,0x3f,0x9f,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12, +0x7a,0x9a,0x12,0x7b,0x9, 0x12,0x3f,0xd9,0x30,0x1c,0xfd,0x12,0x3f,0xe9,0x7e,0xb3, +0x2a,0x73,0x7c,0x7e,0x12,0x10,0xee,0x74,0x2, 0x12,0x0, 0x1e,0x6c,0xcc,0x80,0x29, +0x74,0x2, 0xac,0xbc,0x49,0x35,0x6, 0xfc,0xbe,0x34,0x15,0x40,0x50,0x19,0x7e,0x34, +0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff,0x12, +0x3f,0xf3,0x5c,0x7b,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x3f,0xbf,0xa, 0x3c,0xbd,0x32, +0x48,0xce,0x1b,0xd0,0xbe,0xd0,0x0, 0x48,0x2, 0xc1,0xfb,0x12,0x3e,0x4e,0x12,0x3f, +0x9f,0x7a,0xf3,0x2a,0xfa,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0xda,0x3b,0x22,0x74, +0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x2a,0xfc,0x12,0x3d,0xcc,0x74,0x2, 0x2, 0x0, 0x1e, +0x7e,0x73,0x2a,0x74,0xa, 0x27,0x7e,0x73,0x2a,0x73,0xa, 0x37,0x2d,0x32,0x22,0x7e, +0x73,0x2a,0x74,0xa, 0x37,0x7e,0x53,0x2a,0x73,0xa, 0x25,0x2d,0x23,0x22,0x74,0x5, +0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x7a,0x9a,0x7e,0xb3,0x2a,0xfc,0x2, 0xe, 0x94, +0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x20,0xe3,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0x8, +0x6, 0xfc,0x22,0xa, 0x2c,0x2e,0x27,0x2a,0xfe,0x7e,0x29,0x70,0x22,0x12,0xcd,0x78, +0x12,0xcd,0x6f,0x6d,0x33,0x7a,0x35,0xa, 0x12,0x40,0x53,0x12,0x40,0x2d,0x74,0x50, +0x7a,0xb3,0x38,0xe5,0x7e,0x24,0x3, 0x20,0x12,0x40,0x26,0xe4,0x12,0xcc,0x68,0x6d, +0x33,0x7a,0x37,0x39,0xf5,0x22,0x7d,0x32,0x74,0xfa,0x2, 0x12,0xd0,0x7e,0x73,0x2b, +0x62,0x7a,0x73,0x38,0xe4,0x22,0xa2,0xc, 0xe4,0x33,0x7a,0xb3,0x38,0xdf,0x7e,0x73, +0x38,0xe3,0xbe,0x73,0x2b,0xf, 0x68,0xa, 0xe5,0xc, 0x70,0x6, 0x12,0x40,0x53,0x12, +0x40,0x2d,0x22,0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xe3,0x7e,0x73,0x2b,0x1f,0x7a, +0x73,0x38,0xd3,0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xd2,0x7e,0x73,0x2b,0x14,0x7a, +0x73,0x38,0xd4,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x90,0x61,0xcb,0xe4,0x93,0x7c, +0xab,0xbe,0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff,0x80,0xb, 0x12,0x40,0xe5, +0x38,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0x80,0x1a,0xbe,0xd0, +0x81,0x78,0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x40,0xe5,0x40,0x4, 0x7c,0xeb, +0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38,0x2, 0x6c,0xdd,0x7c,0xbd, +0x12,0x6d,0x1d,0x12,0x40,0x6b,0x7e,0x73,0x2b,0x1f,0x7a,0x73,0x38,0xd3,0x12,0x41, +0x1, 0x7e,0x73,0x2b,0xf, 0x7a,0x73,0x38,0xe3,0x12,0x40,0x2d,0x7a,0xd3,0x38,0xbb, +0xda,0x79,0xda,0xd8,0x22,0x7e,0x90,0x5, 0xac,0x9f,0x9, 0xb4,0x26,0x33,0xbc,0xbe, +0x22,0x30,0x0, 0x3, 0x12,0x40,0x6b,0xa2,0x1, 0x92,0x2, 0x12,0x41,0xcd,0x2, 0x41, +0x1, 0x7e,0x73,0x2b,0x20,0x7a,0x73,0x38,0xd2,0x22,0x74,0x40,0x7a,0xb3,0x2b,0x20, +0x12,0x47,0x7a,0x50,0x9, 0xd2,0x0, 0xd2,0x1, 0x12,0x40,0xf1,0x80,0x1c,0x74,0x1, +0x12,0x41,0x48,0x7e,0x43,0x38,0xd0,0x7e,0x50,0x64,0xac,0x45,0x12,0x90,0x50,0x7a, +0xb3,0x2b,0x1f,0x7e,0xf, 0x33,0xe4,0x12,0x44,0x8c,0x12,0x41,0x1, 0x7e,0x73,0x2b, +0x1f,0x7a,0x73,0x38,0xd3,0x2, 0x40,0x6b,0xca,0x3b,0x7c,0xdb,0xe4,0x7a,0xb3,0x2b, +0x14,0x12,0x46,0x26,0x7e,0xc0,0xa, 0x12,0x45,0x46,0x12,0x0, 0x4e,0x30,0xd, 0xfd, +0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x1f,0x33,0xe4,0x12,0x90,0xcc,0x7d,0x73,0xbe,0x74, +0xff,0xff,0x78,0xc, 0x12,0x41,0xc4,0xb, 0xa, 0x30,0x2e,0x34,0x0, 0x3, 0x80,0x1e, +0xbe,0x74,0x80,0x0, 0x28,0xa, 0x12,0x41,0xc4,0xb, 0xa, 0x30,0xb, 0x35,0x80,0xe, +0xbe,0x74,0x40,0x0, 0x28,0xf, 0x12,0x41,0xc4,0xb, 0xa, 0x30,0xb, 0x34,0x1b,0xa, +0x30,0x1b,0xc0,0x78,0xb2,0xbe,0xd0,0x1, 0x78,0x9, 0x7e,0x1f,0x33,0xe4,0x12,0x90, +0x6f,0x7d,0x73,0x7e,0x1f,0x33,0xd3,0x69,0x31,0x0, 0x1a,0x7a,0x73,0x2b,0x14,0x7d, +0x37,0xda,0x3b,0x22,0x7e,0xf, 0x33,0xd3,0x2e,0x14,0x0, 0x1a,0x22,0xca,0x3b,0x7e, +0x34,0xff,0xff,0x7a,0x35,0x34,0x7e,0xb3,0x38,0xc6,0xf5,0x29,0x7e,0xb3,0x2a,0x6d, +0xf5,0x2a,0x7e,0xb3,0x2a,0x6e,0xf5,0x2b,0x7e,0xb3,0x2a,0x70,0xf5,0x2c,0x7e,0xb3, +0x2a,0x6f,0xf5,0x2d,0x7e,0x34,0x27,0x10,0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a, +0x1d,0x30,0x12,0x45,0x3f,0x12,0x0, 0x4e,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, +0x7e,0x8, 0x34,0x0, 0x12,0x47,0xe8,0x6c,0xff,0x80,0x35,0x12,0x44,0x50,0x6c,0xee, +0x80,0x19,0x7e,0x11,0x2b,0xac,0x1e,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3f,0x2d,0x10, +0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x10,0x12,0x44,0x57,0xe5,0x2d,0xbc,0xbe,0x38, +0xe1,0xe5,0x2d,0x12,0x44,0x66,0x74,0x2, 0xac,0xbf,0x59,0x35,0x34,0x0, 0xb, 0xf0, +0xe5,0x2c,0xbc,0xbf,0x38,0xc5,0x12,0x47,0x71,0x68,0xe, 0x7e,0x34,0x10,0x0, 0x7e, +0xa1,0x2b,0x74,0x2, 0xa4,0x59,0x35,0x33,0xfe,0x6c,0xff,0x80,0x78,0x12,0x44,0x50, +0x6c,0xee,0x80,0x14,0x12,0x45,0x18,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80, +0x14,0x78,0xf4,0x7d,0x13,0x12,0x44,0x57,0xe5,0x29,0xbc,0xbe,0x38,0xe6,0xe5,0x29, +0x12,0x44,0x66,0x74,0x4, 0xac,0xbf,0x59,0x35,0x32,0xba,0xe5,0x29,0xbe,0xb1,0x2c, +0x50,0x35,0x12,0x44,0x50,0x7e,0xe1,0x29,0x80,0x14,0x12,0x45,0x18,0x1e,0x34,0x1e, +0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x13,0x12,0x44,0x57,0xe5,0x2c, +0xbc,0xbe,0x38,0xe6,0xe5,0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, +0x9f,0x1, 0x12,0x44,0x6a,0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59, +0x35,0x32,0xbc,0xb, 0xf0,0xe5,0x2d,0xbc,0xbf,0x38,0x82,0xe5,0x2c,0xa, 0x1b,0x6d, +0x0, 0x7e,0x18,0x0, 0xcc,0x12,0x1f,0x7, 0x6c,0xff,0x80,0x2e,0x74,0x2, 0xac,0xbf, +0x49,0x25,0x34,0x0, 0xa, 0x5f,0xad,0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12, +0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21, +0x74,0x2, 0xac,0xbf,0x59,0x25,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc, +0xe5,0x2a,0xa, 0x1b,0x6d,0x0, 0x7e,0x18,0x0, 0x28,0x12,0x1f,0x7, 0x6c,0xff,0x80, +0x5c,0x74,0x4, 0xac,0xbf,0x49,0x25,0x32,0xba,0xa, 0x1f,0xad,0x13,0x7e,0xf4,0x10, +0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, 0x4e,0xf4,0x80, +0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25,0x32,0xba,0xe5,0x29, +0xbe,0xb1,0x2c,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49,0x25,0x32,0xbc,0x2e,0x14,0x10, +0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14,0x78, +0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x32,0xbc,0xb, 0xf0,0xe5,0x2a,0xbc, +0xbf,0x38,0x9e,0x7e,0x73,0x38,0xc8,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14, +0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x1f,0x5, 0x7d,0xe3,0x7a,0xe5,0x34, +0x7e,0x73,0x38,0xc9,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14,0x78,0xfb,0x7d, +0x1f,0x12,0x1f,0x5, 0x7d,0x63,0x6c,0xff,0x80,0x20,0x74,0x2, 0xac,0xbf,0x49,0x45, +0x34,0x0, 0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x34,0x0, 0x80,0x8, +0xbd,0x46,0x50,0x4, 0x59,0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xda, +0x6c,0xff,0x80,0x3a,0x74,0x4, 0xac,0xbf,0x49,0x45,0x32,0xba,0xbe,0x45,0x34,0x28, +0x9, 0x7e,0x35,0x34,0x59,0x35,0x32,0xba,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65, +0x32,0xba,0x49,0x45,0x32,0xbc,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35, +0x32,0xbc,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x32,0xbc,0xb, 0xf0,0xe5,0x2a, +0xbc,0xbf,0x38,0xc0,0x30,0x2, 0x6, 0x7e,0xd, 0x30,0x12,0x44,0x8c,0xda,0x3b,0x22, +0x9f,0x11,0x7a,0x1f,0x24,0xf4,0x22,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x2f,0x10,0x7a, +0x1f,0x24,0xf4,0xb, 0xe0,0x22,0xa, 0x1b,0x6d,0x0, 0x7e,0x1f,0x24,0xf4,0x12,0x1f, +0x7, 0x7a,0x1f,0x24,0xf4,0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d,0x22, +0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x1f,0x5, 0x12,0x44,0x96,0xb, +0x34,0x7a,0x73,0x2b,0x20,0x22,0xca,0x79,0x7f,0x10,0x9f,0x0, 0x12,0xcd,0xca,0x4c, +0xaa,0x78,0x6, 0x7e,0x34,0x0, 0x40,0x80,0x6c,0x6c,0x99,0x80,0x38,0xa, 0xe9,0x2e, +0xe4,0x60,0xac,0x7d,0x7e,0x7a,0xf1,0x82,0x7a,0xe1,0x83,0xe4,0x93,0x7c,0x8b,0x90, +0x60,0xaa,0xe4,0x93,0x70,0xe, 0x7e,0xf3,0x2a,0x6e,0xac,0xf8,0x7e,0xb3,0x2a,0x70, +0xa, 0xfb,0x2d,0xf7,0x7d,0xef,0x3e,0xe4,0x7f,0x61,0x2d,0xde,0xb, 0x6a,0xd0,0x6d, +0xcc,0x2f,0x6, 0xb, 0x90,0xbc,0xa9,0x38,0xc4,0xbe,0x8, 0x0, 0x0, 0x78,0x2, 0xb, +0xc, 0xa, 0x5a,0x6d,0x44,0x7f,0x10,0x7f,0x2, 0x12,0x1f,0x7, 0x7f,0x1, 0xb, 0xc, +0x7e,0x34,0xc4,0x0, 0x7e,0x24,0x0, 0x9, 0x12,0x1f,0x7, 0xbe,0x34,0x0, 0xfa,0x28, +0x4, 0x7e,0x34,0x0, 0xfa,0xda,0x79,0x22,0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e, +0x30,0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27, +0x24,0xf2,0x74,0x2, 0xac,0xbe,0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0x7e, +0x8, 0x2a,0x6d,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x2, +0x13,0x2c,0xb4,0x3, 0x5, 0x12,0x45,0x65,0x80,0x2, 0xe4,0x22,0x12,0x45,0x4a,0x12, +0x0, 0x4e,0x74,0x1, 0x22,0x12,0x47,0x68,0xe4,0x12,0x0, 0xe, 0x12,0x46,0x26,0x2, +0x45,0x72,0x7e,0x63,0x2b,0xf, 0x7e,0x73,0x38,0xe2,0x7e,0x14,0x60,0xd6,0x12,0x47, +0xe0,0xac,0x67,0x2d,0x32,0x12,0x7b,0xc7,0x28,0x3, 0x7e,0x70,0x7, 0x12,0x2d,0x1a, +0x2, 0x45,0x93,0x3e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x86,0x22,0x7e,0xf, 0x13,0x8a, +0x7e,0x18,0x8, 0xa, 0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30,0x12,0x7f,0xce,0x7a,0x55, +0x31,0x7e,0xb3,0x2b,0x1d,0xf5,0x2e,0xe4,0x7a,0xb3,0x2b,0x1d,0x7f,0x3, 0x7e,0x1d, +0x29,0x12,0x79,0x68,0x12,0x47,0x68,0x12,0x46,0x26,0x75,0x2d,0x0, 0x12,0x45,0x46, +0x12,0x45,0x72,0x12,0x0, 0x4e,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x47,0xf0,0x7e,0x14, +0x40,0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x46,0x2d,0x12,0xb9,0xd5,0x6d,0x33,0x80,0x19, +0x7e,0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d, +0x13,0x12,0x7b,0xbe,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe, +0x35,0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb0,0xe5,0x2e,0x7a, +0xb3,0x2b,0x1d,0xda,0x3b,0x22,0x7e,0x8, 0x2a,0x6d,0x2, 0xd, 0x72,0x7e,0xb3,0x2a, +0x6d,0xca,0x3b,0x7c,0xdb,0x7a,0x5, 0x38,0x7d,0x71,0x7a,0x25,0x36,0x7a,0x35,0x34, +0x12,0x47,0x7a,0x50,0x7c,0x6c,0xcc,0x80,0x11,0x7e,0x73,0x2a,0x6e,0x12,0x47,0x58, +0x12,0x47,0x3e,0x7e,0x34,0x34,0x0, 0x12,0x47,0xaf,0x12,0x47,0x61,0x38,0xea,0x6c, +0xcc,0x80,0x58,0x7e,0xa3,0x2a,0x6e,0x7c,0x7a,0x12,0x47,0x58,0x75,0x3a,0x0, 0x80, +0x27,0x7e,0xb3,0x38,0xc6,0xbe,0xb1,0x3a,0x7e,0x70,0x4, 0x28,0x8, 0xac,0x7c,0x49, +0x43,0x32,0xba,0x80,0x6, 0xac,0x7c,0x49,0x43,0x32,0xbc,0x7e,0x71,0x3a,0x74,0x2, +0xac,0x7b,0x59,0x43,0x34,0x50,0x5, 0x3a,0x7e,0xb3,0x2a,0x70,0xbe,0xb1,0x3a,0x38, +0xd0,0x12,0x47,0x71,0x68,0xb, 0x7e,0x34,0x10,0x0, 0x74,0x2, 0xa4,0x59,0x35,0x34, +0x4e,0x12,0x47,0x3e,0x7e,0x34,0x34,0x50,0x12,0x47,0xaf,0xbc,0xdc,0x38,0xa4,0x80, +0x2c,0x7a,0xd3,0x25,0xb6,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x25,0xb7,0xe4,0x7a,0xb3, +0x25,0xb9,0x74,0x6, 0x7a,0xb3,0x25,0xb8,0x7a,0x77,0x25,0xba,0x7a,0x77,0x25,0xbe, +0x7e,0x8, 0x25,0xb6,0x7e,0x73,0x2b,0x1f,0xa, 0x37,0x12,0xe, 0x37,0x7d,0x37,0x12, +0x87,0x95,0x7e,0x35,0x38,0x7a,0x37,0x25,0xbe,0xe4,0x7a,0xb3,0x25,0xb8,0x12,0x47, +0x4f,0x7a,0xd3,0x25,0xb6,0x7e,0xb3,0x2b,0x1d,0x70,0xf, 0xe4,0x7a,0xb3,0x25,0xb9, +0x7a,0x77,0x25,0xba,0x7e,0x34,0x0, 0x20,0x80,0x16,0x74,0x1, 0x7a,0xb3,0x25,0xb9, +0x7e,0x35,0x34,0x7a,0x37,0x25,0xba,0x7e,0x35,0x36,0x7a,0x37,0x25,0xbc,0x6d,0x33, +0x7a,0x37,0x25,0xc0,0x7e,0x8, 0x25,0xb6,0x12,0xd, 0x7, 0xda,0x3b,0x22,0x74,0xc, +0x7a,0xb3,0x25,0xb8,0x74,0x1, 0x7a,0xb3,0x25,0xb6,0xe4,0x7a,0xb3,0x25,0xb9,0x7e, +0x73,0x2a,0x6e,0x7a,0x73,0x25,0xb7,0x22,0xac,0x7c,0x3e,0x34,0x7d,0xf7,0x2d,0xf3, +0x22,0x7e,0x73,0x2a,0x6f,0xbc,0x7c,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, +0x1e,0x90,0x60,0xaa,0xe4,0x93,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x3, 0xc6,0xb4,0x3, +0x8, 0x7e,0xb3,0x38,0xc7,0x70,0x2, 0xc3,0x22,0xd3,0x22,0x30,0x11,0x10,0x12,0x47, +0x7a,0x50,0x3, 0x12,0x6e,0x5b,0x12,0x45,0x9c,0x12,0x7c,0x2, 0xc2,0x11,0x22,0x7e, +0x34,0xd, 0xac,0x12,0x26,0xbb,0x12,0x7a,0x1e,0x12,0x7b,0xdc,0x2, 0x47,0x8b,0x7a, +0x37,0x25,0xba,0x7d,0x3f,0x7a,0x37,0x25,0xbc,0x7a,0x37,0x25,0xbe,0x7e,0x8, 0x25, +0xb6,0x12,0x7, 0x9b,0xb, 0xc0,0x22,0x12,0x88,0xc7,0x38,0x2, 0xe4,0x22,0x12,0x88, +0xbf,0x49,0x55,0x33,0xeb,0xbe,0xb0,0x2, 0x38,0x3, 0x2, 0x7a,0xc9,0x2, 0x45,0x52, +0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x20,0x22,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x20,0xe3, +0x12,0x0, 0xe, 0x7e,0x1f,0x13,0x86,0x22,0x2, 0x47,0xfb,0xe4,0x7a,0xb3,0x2b,0x2, +0x7a,0xb3,0x2b,0x1e,0x22,0xca,0xd8,0xca,0x79,0x7e,0x73,0x2a,0x6e,0x7e,0xf3,0x2a, +0x6d,0xac,0xf7,0x7d,0x37,0x3e,0x34,0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x20,0xe3,0x7e, +0xb3,0x38,0xcc,0xb4,0x1, 0x64,0x7e,0x73,0x38,0xcd,0xbe,0x70,0x0, 0x28,0x5b,0x6c, +0xdd,0x80,0x3c,0x12,0x26,0xb7,0x12,0x6a,0x78,0x6d,0x33,0x80,0x28,0x7e,0x35,0x24, +0x3e,0x34,0x49,0x33,0xd, 0xc8,0x12,0x21,0x15,0x7a,0x35,0x26,0x7e,0x35,0x24,0x7d, +0x13,0x3e,0x14,0x49,0x21,0x1f,0x34,0xbe,0x25,0x26,0x58,0x7, 0x7e,0x25,0x26,0x59, +0x21,0x1f,0x34,0xb, 0x34,0x7a,0x35,0x24,0xbe,0x75,0x24,0x38,0xd0,0xb, 0xd0,0x7e, +0x73,0x38,0xcd,0xbc,0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f, +0x34,0x7e,0x8, 0xd, 0xc8,0x12,0x20,0xbe,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x12, +0x3f,0xfd,0x7e,0xb3,0x3, 0xc6,0xb4,0x3, 0x69,0x12,0xbb,0xdb,0x12,0x26,0xb7,0x12, +0x2d,0xfb,0x7e,0xb3,0x38,0xb1,0x30,0xe7,0xe9,0x12,0x6a,0x78,0x12,0x3f,0xb0,0x3e, +0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, 0xfc,0x12,0x20,0xbe,0x1b,0xfd, +0x12,0x3f,0xb0,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x7e,0x7e,0x8, 0x5, 0x7a,0x12, +0x20,0xbe,0x1b,0xfd,0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0x15,0x12,0x84,0xf5,0x12,0x76, +0x27,0x12,0xa9,0x97,0x12,0x8a,0x2f,0x12,0x83,0x4d,0x12,0x49,0x8, 0x12,0x48,0x5, +0x12,0x40,0x36,0x12,0xb5,0x47,0x7e,0xb3,0x38,0xb1,0x54,0x7f,0x7a,0xb3,0x38,0xb1, +0x80,0x90,0x12,0x7f,0xb0,0x2, 0x47,0xf8,0x12,0x66,0x50,0x12,0x4a,0xff,0x12,0x4a, +0xff,0x12,0x5e,0x6a,0x12,0x5e,0x83,0x12,0xa6,0x23,0x12,0x4a,0xff,0x12,0x9a,0x83, +0x12,0x4a,0xff,0x12,0xa6,0xe9,0x12,0x4a,0xff,0x2, 0x49,0x2c,0xca,0x3b,0x75,0x24, +0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x33,0x8c,0x7e, +0x8, 0x33,0x50,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0xf3,0x28,0x84,0xa, 0xcf,0x3e,0xc4, +0xca,0xc9,0x7e,0x18,0x26,0xfa,0x7e,0x8, 0x1f,0x34,0x12,0x20,0xbe,0x1b,0xfd,0x6c, +0x88,0x6c,0xee,0x41,0x0, 0x7e,0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99,0x80,0x4c, +0x74,0x2, 0xac,0xb9,0x9, 0xb5,0x1f,0x34,0xbe,0xb0,0xff,0x68,0x3d,0x7c,0xb9,0x12, +0x4f,0xc5,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1f,0x35,0xa, 0x27,0x74,0x2, +0xac,0xbe,0x9, 0x75,0x33,0x8d,0x12,0x4f,0xe8,0x7d,0x13,0x74,0x2, 0xac,0xb9,0x9, +0x75,0x1f,0x34,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x33,0x8c,0x12,0x4f,0xe8, +0x2d,0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9,0x38,0xb0, +0xbe,0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x1f,0x34,0x9, 0x73, +0x1f,0x35,0x12,0x4b,0x45,0xbe,0x37,0x2a,0x5a,0x48,0x23,0x7e,0x70,0x2, 0xac,0x7c, +0x9, 0x53,0x1f,0x34,0x74,0x2, 0xac,0xbd,0x19,0x55,0x1f,0x70,0x9, 0x53,0x1f,0x35, +0x19,0x55,0x1f,0x71,0x74,0xff,0x19,0xb3,0x1f,0x34,0xb, 0x80,0xb, 0xd0,0xb, 0xe0, +0x7e,0x73,0x33,0x48,0xbc,0x7e,0x28,0x2, 0x21,0x65,0x7c,0xe8,0x80,0x6d,0x6d,0xdd, +0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x4f,0xc5,0x60,0x33,0x12,0xcd, +0xb, 0xbe,0xb0,0xff,0x68,0x2b,0x9, 0x73,0x1f,0x35,0x12,0x86,0xea,0x7f,0x71,0xb, +0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, 0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0, +0xbd,0xcd,0x8, 0xd, 0x12,0xcd,0xb, 0xf5,0x24,0x9, 0xc3,0x1f,0x35,0x7d,0xdc,0x7c, +0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0,0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74, +0x2, 0xac,0xbd,0x19,0x75,0x1f,0x70,0x19,0xc5,0x1f,0x71,0x7e,0xa0,0xff,0x7e,0x70, +0x2, 0xac,0x78,0x19,0xa3,0x1f,0x34,0xb, 0xd0,0xb, 0xe0,0x90,0x60,0x99,0xe4,0x93, +0xbc,0xbe,0x38,0x8a,0x90,0x60,0x9a,0xe4,0x93,0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59, +0x7e,0x18,0x1f,0x70,0x7e,0x8, 0x1f,0x34,0x12,0x20,0xbe,0x1b,0xfd,0x7c,0xfd,0x12, +0xa3,0x7f,0x7e,0x8, 0x33,0x8c,0x74,0xff,0x12,0x20,0xe3,0xbe,0xf0,0x0, 0x28,0x35, +0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x26,0xfa,0x12,0x20, +0xbe,0x1b,0xfd,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x33, +0x8c,0x12,0x20,0xbe,0x1b,0xfd,0x6c,0xee,0x80,0x7, 0x7c,0xbe,0x12,0x5f,0x4, 0xb, +0xe0,0xbc,0xfe,0x38,0xf5,0x7a,0xf3,0x33,0x48,0x7a,0xf3,0x28,0x84,0x90,0x60,0x99, +0xe4,0x93,0xbe,0xb3,0x28,0x84,0x50,0x4, 0x7a,0xb3,0x28,0x84,0xda,0x3b,0x22,0xca, +0x79,0x6c,0xff,0x6c,0xee,0x80,0x2e,0x7c,0xbe,0x12,0x4f,0xc5,0x60,0x25,0x7e,0x34, +0x0, 0x2, 0xca,0x39,0xac,0x7e,0x2e,0x34,0x26,0xfa,0x6d,0x22,0x7e,0x30,0x2, 0xac, +0x3f,0x2e,0x14,0x26,0xfa,0x6d,0x0, 0x12,0x20,0xbe,0x1b,0xfd,0x7c,0xbf,0x12,0x5f, +0x4, 0xb, 0xf0,0xb, 0xe0,0x12,0x5f,0xf1,0x38,0xcd,0x7a,0xf3,0x28,0x84,0xda,0x79, +0x22,0x7c,0xba,0x7c,0x79,0x12,0x86,0xea,0xb, 0x1a,0x30,0x22,0xca,0x3b,0x7c,0xfb, +0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x7e,0xb3,0x2a,0x6f,0xf5,0x43,0x7e,0xb3,0x2a,0x70, +0xf5,0x44,0x7e,0xd3,0x28,0x84,0xe4,0x7a,0xb3,0x2, 0x8c,0x7a,0xb3,0x2, 0x88,0x7a, +0xb3,0x2, 0x89,0x7e,0x8, 0x2, 0x8d,0x12,0x4f,0xde,0xe4,0x12,0x20,0xe3,0x12,0x4f, +0xde,0x3e,0x34,0x7e,0x8, 0x2, 0xad,0xe4,0x12,0x20,0xe3,0x6d,0x33,0x7d,0x43,0x6c, +0xcc,0x80,0x18,0xa, 0x2c,0x7e,0xb3,0x2a,0x6e,0xa, 0x1b,0x2d,0x12,0x3e,0x14,0x49, +0x21,0x4, 0xfc,0xbd,0x24,0x8, 0x2, 0x7d,0x42,0xb, 0xc0,0xe5,0x43,0xbc,0xbc,0x38, +0xe2,0x6c,0xcc,0x80,0x11,0x7e,0x30,0x2, 0xac,0x3c,0x49,0x21,0x4, 0xfc,0xbd,0x23, +0x8, 0x2, 0x7d,0x32,0xb, 0xc0,0xe5,0x44,0xbc,0xbc,0x38,0xe9,0xbe,0x34,0x1, 0x90, +0x48,0x6, 0xbe,0x44,0x1, 0xf4,0x58,0x0, 0x7e,0x37,0x28,0x8e,0xbe,0x34,0xff,0x9c, +0x8, 0x0, 0xbe,0xd0,0x2, 0x50,0x2, 0xe1,0xc2,0x6c,0xcc,0xe1,0xbc,0x12,0xb7,0xc2, +0xf5,0x24,0x9, 0xb3,0x26,0xfb,0xf5,0x25,0x4c,0xcc,0x68,0x8, 0xa, 0x3c,0x9, 0xb3, +0x2, 0x8d,0x70,0xa, 0xa, 0x3c,0xb, 0x34,0xa, 0x2c,0x19,0x72,0x2, 0x8d,0x7c,0xbd, +0x14,0xbc,0xbc,0x78,0x2, 0xe1,0xc2,0xa, 0x5c,0xb, 0x54,0xf5,0x2e,0xe1,0xb3,0x7e, +0x71,0x2e,0x12,0xcc,0x5d,0x7a,0xa1,0x26,0x9, 0xb3,0x26,0xfb,0xf5,0x27,0xa, 0x2a, +0xe5,0x24,0x12,0x4f,0xef,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5,0x25,0x12,0x4f,0xef, +0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x2, 0xe1,0xb1,0xe5,0x29,0xbe,0xb0,0x5, +0x40,0x2, 0xe1,0xb1,0x12,0xcc,0xe0,0x12,0x9f,0x79,0x7a,0xb3,0x2, 0x8b,0x85,0x25, +0x54,0x85,0x26,0x55,0x85,0x27,0x56,0x7e,0x8, 0x0, 0x31,0x7e,0x18,0x0, 0x33,0xe5, +0x24,0x12,0xb6,0xd5,0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x75,0x30,0x0, 0xe5,0x24,0x7e, +0x71,0x25,0x12,0x4b,0x45,0x7a,0x35,0x35,0xe5,0x26,0x7e,0x71,0x27,0x12,0x4b,0x45, +0x7a,0x35,0x37,0x7e,0x35,0x35,0xbe,0x35,0x37,0x8, 0x5, 0x7e,0x35,0x37,0x80,0x3, +0x7e,0x35,0x35,0x7a,0x35,0x3b,0xe, 0x34,0x7a,0x35,0x39,0xe5,0x28,0xbe,0xb0,0x1, +0x38,0x2c,0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x25,0x7c,0xbf,0x30,0xe1,0x20,0xe5,0x26, +0x7e,0x71,0x25,0x12,0x4b,0x45,0x7d,0x43,0xe5,0x24,0x7e,0x71,0x27,0x12,0x4b,0x45, +0x2d,0x34,0xbe,0x35,0x39,0x18,0x2, 0xe1,0x48,0x75,0x30,0x1, 0xe1,0x48,0xe5,0x28, +0xbe,0xb0,0x1, 0x38,0x9, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x2, 0xe1,0x48,0xe5,0x28, +0xbe,0xb0,0x5, 0x40,0x2, 0xe1,0x48,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xe1,0x48, +0x7c,0xbf,0x20,0xe0,0x2, 0xe1,0x48,0x6d,0x33,0x7a,0x35,0x4d,0x75,0x4f,0x0, 0x7a, +0x35,0x50,0x75,0x52,0x0, 0xc2,0x2, 0xc2,0x3, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x4, +0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2a,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5, +0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2c,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x4, 0xe5,0x25, +0x80,0x2, 0xe5,0x27,0xf5,0x2b,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80, +0x2, 0xe5,0x27,0xf5,0x2d,0xe5,0x2c,0xbe,0xb1,0x2a,0x78,0x29,0xd2,0x2, 0xe5,0x2a, +0x60,0x8, 0xe5,0x43,0x14,0xbe,0xb1,0x2a,0x78,0x2, 0xd2,0x3, 0xe5,0x2a,0xbe,0xb0, +0x0, 0x28,0x2, 0x15,0x2a,0xe5,0x43,0xa, 0x2b,0x1b,0x24,0xe5,0x2c,0xa, 0x3b,0xbd, +0x32,0x58,0x2, 0x5, 0x2c,0xe5,0x2d,0xbe,0xb1,0x2b,0x78,0x29,0xd2,0x2, 0xe5,0x2b, +0x60,0x8, 0xe5,0x44,0x14,0xbe,0xb1,0x2b,0x78,0x2, 0xd2,0x3, 0xe5,0x2b,0xbe,0xb0, +0x0, 0x28,0x2, 0x15,0x2b,0xe5,0x44,0xa, 0x2b,0x1b,0x24,0xe5,0x2d,0xa, 0x3b,0xbd, +0x32,0x58,0x2, 0x5, 0x2d,0x85,0x2a,0x3f,0x80,0x5b,0x85,0x2b,0x40,0x80,0x4d,0xe5, +0x3f,0x7e,0x71,0x40,0x12,0x4b,0x45,0x7a,0x35,0x41,0xe5,0x2a,0xbe,0xb1,0x3f,0x68, +0x15,0xe5,0x2c,0xbe,0xb1,0x3f,0x68,0xe, 0xe5,0x2b,0xbe,0xb1,0x40,0x68,0x7, 0xe5, +0x2d,0xbe,0xb1,0x40,0x78,0xd, 0x7e,0x35,0x41,0x2e,0x35,0x4d,0x7a,0x35,0x4d,0x5, +0x4f,0x80,0x17,0x5, 0x52,0x7e,0x35,0x41,0x2e,0x35,0x50,0x7a,0x35,0x50,0x7e,0x35, +0x33,0xbe,0x35,0x41,0x58,0x2, 0x5, 0x3d,0x5, 0x3e,0x5, 0x40,0xe5,0x2d,0xbe,0xb1, +0x40,0x50,0xac,0x5, 0x3f,0xe5,0x2c,0xbe,0xb1,0x3f,0x50,0x9e,0xe5,0x2c,0x7e,0x71, +0x2b,0x12,0x4b,0x45,0x7e,0x45,0x4d,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2d,0x12,0x4b, +0x45,0x9d,0x43,0xe5,0x2a,0x7e,0x71,0x2b,0x12,0x4b,0x45,0x9d,0x43,0xe5,0x2c,0x7e, +0x71,0x2d,0x12,0x4b,0x45,0x7d,0x23,0x7d,0x34,0x9d,0x32,0x7a,0x35,0x4d,0x7e,0x35, +0x37,0x2e,0x35,0x35,0x7a,0x35,0x39,0x30,0x2, 0x10,0x20,0x3, 0xd, 0x7e,0x35,0x4d, +0x9e,0x35,0x39,0x7a,0x35,0x4d,0x15,0x4f,0x15,0x4f,0xe5,0x4f,0xbe,0xb0,0x4, 0x28, +0x6, 0xe5,0x4f,0x24,0xfc,0xf5,0x4f,0x7e,0x35,0x4d,0xbe,0x34,0x0, 0x0, 0x58,0x5, +0x6d,0x33,0x7a,0x35,0x4d,0x7e,0xe0,0x22,0xe5,0x43,0x14,0xbe,0xb1,0x24,0x68,0xd, +0xbe,0xb1,0x26,0x68,0x8, 0xe5,0x24,0x60,0x4, 0xe5,0x26,0x70,0xa, 0x12,0xb7,0x64, +0x28,0x4b,0x7e,0xe0,0x2c,0x80,0x46,0x30,0x13,0x43,0x7e,0x73,0x33,0x4c,0xbe,0x71, +0x2c,0x38,0x13,0xbe,0x71,0x2a,0x40,0xe, 0x7e,0x73,0x33,0x4e,0xbe,0x71,0x2d,0x38, +0x5, 0xbe,0x71,0x2b,0x50,0x1c,0x7e,0x73,0x33,0x4d,0xbe,0x71,0x2c,0x38,0x1e,0xbe, +0x71,0x2a,0x40,0x19,0x7e,0x73,0x33,0x4f,0xbe,0x71,0x2d,0x38,0x10,0xbe,0x71,0x2b, +0x40,0xb, 0xa, 0x3e,0x7e,0x24,0x0, 0x3, 0x12,0x1e,0xb9,0x2c,0xe7,0x7e,0x15,0x50, +0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4d,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xa, 0x1e,0x6d, +0x0, 0x12,0x1e,0xeb,0x7f,0x71,0x7a,0x7d,0x45,0x7e,0x15,0x39,0x1a,0x2, 0x1a,0x0, +0x7e,0x35,0x31,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0xe5,0x52,0xa, 0xdb,0x6d,0xcc, +0xe5,0x4f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1e,0xeb,0x7a,0x1d,0x49,0xbf,0x71, +0x8, 0x3, 0x75,0x30,0x2, 0xc2,0x1, 0x20,0xa, 0xe, 0x12,0xcc,0xe0,0x12,0xb8,0xbc, +0x92,0x1, 0x20,0x1, 0x3, 0x75,0x30,0x0, 0xe5,0x30,0xbe,0xb0,0x0, 0x28,0x62,0xe5, +0x30,0xa, 0x3b,0x2e,0x34,0x2, 0x87,0x7e,0x39,0xb0,0x4, 0x7a,0x39,0xb0,0xe5,0x2e, +0xa, 0x3b,0x9, 0xa3,0x2, 0x8d,0x4c,0xaa,0x78,0xc, 0xa, 0x2c,0x9, 0xb2,0x2, 0x8d, +0x19,0xb3,0x2, 0x8d,0x80,0x3b,0xa, 0x2c,0x9, 0xb2,0x2, 0x8d,0xf5,0x53,0xbc,0xba, +0x28,0x3, 0x7a,0xa1,0x53,0x75,0x2f,0x0, 0x80,0x22,0x9, 0x33,0x2, 0x8d,0xe5,0x2f, +0xa, 0x2b,0x9, 0x22,0x2, 0x8d,0xbc,0x23,0x68,0xa, 0xa, 0xc, 0x9, 0x30,0x2, 0x8d, +0xbc,0x23,0x78,0x6, 0xe5,0x53,0x19,0xb2,0x2, 0x8d,0x5, 0x2f,0xbe,0xd1,0x2f,0x38, +0xd9,0x5, 0x2e,0xbe,0xd1,0x2e,0x28,0x2, 0x81,0x1f,0xb, 0xc0,0xbc,0xdc,0x28,0x2, +0x61,0xed,0xda,0x3b,0x22,0x7c,0x7b,0x12,0x77,0xa2,0x9, 0xa2,0x27,0x72,0x7c,0xb7, +0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x12,0x7c,0x87,0x5c,0xba,0x22,0x90,0x60, +0x9a,0x93,0xa, 0x3b,0x22,0x7e,0x39,0x70,0xa, 0x37,0x9d,0x32,0x2, 0x21,0x15,0xa, +0x3b,0x9d,0x32,0x12,0x21,0x15,0x7c,0xb7,0x22,0x2, 0x4f,0xfc,0x7e,0x73,0x2a,0x6b, +0x2e,0x70,0xff,0x22,0x7e,0xb3,0x3, 0xc3,0xb4,0x1, 0x4, 0xe4,0x2, 0x50,0x10,0x22, +0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0x12,0x6a,0x36,0x12,0x80,0x44,0x7e,0xb3, +0x3, 0xc6,0xb4,0x1, 0x6b,0x12,0xbb,0xdb,0x7e,0x34,0x60,0xa5,0x12,0x23,0xbc,0x12, +0x26,0xbb,0x12,0x7f,0x61,0x12,0x2d,0x30,0x12,0x6a,0x78,0x50,0xde,0x12,0x84,0xf5, +0x12,0x76,0x27,0x7e,0xb3,0x3, 0xc3,0xb4,0x1, 0x4, 0xe4,0x12,0x50,0x10,0x12,0xa9, +0x97,0x12,0x56,0xe0,0x40,0xc5,0x12,0x8a,0x2f,0x12,0x56,0xe0,0x40,0xbd,0x12,0x83, +0x4d,0x12,0x49,0x8, 0x12,0x57,0x94,0x12,0x32,0x32,0x12,0x8f,0xfc,0x12,0x99,0xf0, +0x12,0x50,0x96,0x12,0xa5,0x7, 0x12,0x57,0x2c,0x12,0x5e,0x3a,0x12,0x8e,0xfe,0x12, +0x7f,0x22,0x12,0x53,0x38,0x12,0x70,0x30,0x12,0x94,0xcf,0x12,0x67,0xfa,0x80,0x8b, +0x12,0x7f,0xb0,0x2, 0x50,0x4, 0xca,0xf8,0x7e,0x68,0x29,0xbc,0x6c,0xaa,0x80,0x19, +0x7e,0x70,0xff,0x12,0xcd,0x15,0xe4,0xa, 0x4a,0x19,0xb4,0x1f,0x34,0x74,0xff,0x19, +0xb4,0x1f,0x46,0x19,0xb4,0x1f,0x50,0xb, 0xa0,0x12,0x53,0x21,0x38,0xe2,0x7e,0x73, +0x2a,0x2, 0xa5,0xbf,0x0, 0x23,0x7e,0xb3,0x3a,0x2, 0x70,0x2, 0x41,0xa5,0x6c,0xaa, +0x80,0x10,0x7e,0x44,0x7f,0xff,0x12,0xcd,0x1f,0x79,0x40,0x0, 0x14,0x12,0xcd,0x66, +0xb, 0xa0,0x12,0x53,0x21,0x38,0xeb,0x41,0xa5,0x7e,0xb3,0x3a,0x2, 0x70,0x3d,0xbe, +0x70,0x0, 0x28,0x38,0x6c,0xaa,0x80,0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x28, +0xae,0x12,0xcd,0x1f,0x79,0x30,0x0, 0x14,0x49,0x34,0x28,0xb0,0x7f,0x6, 0x2d,0x12, +0x79,0x30,0x0, 0x28,0x74,0x1, 0xa, 0x3a,0x19,0xb3,0x1f,0x34,0x19,0xa4,0x28,0xb2, +0xb, 0xa0,0x7e,0xb3,0x2a,0x2, 0xbc,0xba,0x38,0xce,0x41,0xa5,0x6c,0xaa,0x80,0x17, +0x12,0x57,0x22,0x3e,0x34,0x59,0x43,0x15,0x4e,0x59,0x43,0x15,0x50,0x59,0x43,0x15, +0x76,0x59,0x43,0x15,0x78,0xb, 0xa0,0x12,0x53,0x21,0x38,0xe4,0x6c,0xaa,0x80,0x3d, +0x6c,0xff,0x80,0x32,0x7e,0x70,0x2, 0xac,0x7f,0x7f,0x6, 0x2d,0x13,0x69,0x30,0x0, +0x14,0xbe,0x34,0x7f,0xff,0x68,0x1d,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x14, +0x12,0xcd,0xd2,0x59,0x32,0x15,0x4e,0x69,0x30,0x0, 0x28,0x59,0x32,0x15,0x50,0x12, +0xcc,0xbb,0x80,0x7, 0xb, 0xf0,0x12,0x53,0x30,0x38,0xc9,0xb, 0xa0,0x7e,0xb3,0x3a, +0x2, 0xbc,0xba,0x38,0xbb,0x6c,0xaa,0x80,0x24,0xa, 0x3a,0x9, 0xb3,0x1f,0x46,0xb4, +0xff,0x19,0x6c,0xff,0x80,0x10,0xa, 0x4f,0x9, 0xb4,0x1f,0x50,0xb4,0xff,0x5, 0x12, +0xcc,0xbb,0x80,0x7, 0xb, 0xf0,0x12,0x53,0x30,0x38,0xeb,0xb, 0xa0,0x12,0x53,0x21, +0x38,0xd7,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x28,0xae,0x12, +0xcd,0xd2,0x59,0x42,0x15,0x76,0x49,0x33,0x28,0xb0,0x59,0x32,0x15,0x78,0xb, 0xa0, +0x7e,0xb3,0x2a,0x2, 0xbc,0xba,0x38,0xde,0x7e,0x34,0x15,0x4e,0x7a,0x37,0x1f,0x40, +0x7e,0x34,0x15,0x76,0x7a,0x37,0x1f,0x42,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x44, +0x7e,0x73,0x3a,0x2, 0x7a,0x73,0x1f,0x3e,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x1f,0x3f, +0x7e,0x8, 0x1f,0x3e,0x12,0x4, 0xad,0x6c,0xaa,0x80,0x59,0x7e,0x70,0xff,0x6c,0xff, +0x80,0x19,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12,0x15,0x9e,0xa, 0x2a,0xbd,0x21,0x78, +0x8, 0xa, 0x3f,0x9, 0x73,0x1f,0x46,0x80,0x7, 0xb, 0xf0,0x12,0x53,0x30,0x38,0xe2, +0xbe,0x70,0xff,0x68,0x2d,0x12,0xcd,0x15,0x74,0x1, 0xa, 0x47,0x19,0xb4,0x1f,0x34, +0x7e,0x90,0x9, 0xac,0x9a,0x49,0x24,0x28,0xae,0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d, +0x7d,0xc, 0x79,0x20,0x0, 0x14,0x49,0x44,0x28,0xb0,0x7e,0x50,0x2, 0xac,0x57,0x12, +0xcd,0x66,0xb, 0xa0,0x7e,0x63,0x2a,0x2, 0xbc,0x6a,0x38,0x9f,0x6c,0xaa,0x80,0x20, +0xa, 0x3a,0x9, 0xb3,0x1f,0x34,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x57,0x22,0x7f,0x6, +0x2d,0x13,0x79,0x40,0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28,0xb, 0xa0, +0x12,0x53,0x21,0x38,0xdb,0x7e,0xf3,0x2a,0x2, 0x7a,0xf3,0x3a,0x2, 0x6c,0xaa,0x80, +0x68,0xa, 0x3a,0x9, 0xb3,0x1f,0x34,0xb4,0x1, 0x2c,0x12,0x53,0x29,0x29,0xb1,0x0, +0xa, 0xb4,0x1, 0x6, 0x74,0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x53,0x29,0x29,0x31,0x0, +0xa, 0xa5,0xbb,0x3, 0x6, 0xe4,0x7a,0x1b,0xb0,0x80,0x32,0xa5,0xbb,0x0, 0x2e,0x74, +0x2, 0x7a,0x1b,0xb0,0x80,0x27,0x12,0x53,0x29,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, +0x68,0x2, 0x70,0x14,0x74,0x1, 0x7a,0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, +0xac,0x23,0x19,0xa1,0x28,0xb2,0x80,0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x53,0x29, +0x7e,0x1b,0xb0,0x39,0xb1,0x0, 0xa, 0xb, 0xa0,0x12,0x53,0x21,0x38,0x93,0xda,0xf8, +0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xba,0x22,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c,0x22, +0x90,0x60,0x99,0xe4,0x93,0xbc,0xbf,0x22,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xff,0x12, +0xcd,0x33,0x75,0x28,0x3, 0x6c,0xee,0x7e,0x48,0x29,0xbc,0x7e,0xb3,0x2a,0x3, 0x70, +0x13,0x7e,0xb3,0x2a,0x2, 0xb4,0x1, 0xc, 0x7e,0xb3,0x36,0x7c,0x70,0x6, 0x74,0x3, +0x7a,0xb3,0x36,0x7c,0x7e,0xb3,0x2a,0xb, 0x70,0xe, 0x7e,0xb3,0x2a,0x7, 0x70,0x8, +0x7e,0xb3,0x2a,0x8, 0x70,0x2, 0xc1,0xac,0x30,0x10,0x6, 0x7e,0x68,0x35,0xe4,0x80, +0x4, 0x7e,0x68,0x35,0xa6,0x7f,0x6, 0x12,0x88,0x57,0x7e,0x73,0x2a,0x4, 0x7a,0x6b, +0x70,0x6c,0xdd,0xc1,0x51,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x29,0xc, 0x7c,0xbc,0x54, +0xf, 0x12,0x9f,0xe5,0xf5,0x28,0x7c,0xbc,0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, 0xc1, +0x4f,0xe5,0x28,0xbe,0xb0,0x3, 0x78,0x2, 0xc1,0x4f,0x7e,0x8, 0x0, 0x28,0x7c,0xbc, +0x12,0xa5,0x73,0x50,0x2, 0xc1,0x4f,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xd, 0xf5, +0x25,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xe, 0xc4,0x54,0xf0,0xf5,0x26,0x7e,0x73, +0x2a,0x4d,0xbc,0x7c,0x28,0x54,0x7e,0xb3,0x2a,0x9, 0x70,0x2a,0x75,0x2b,0xf, 0x7e, +0x8, 0x0, 0x25,0xa, 0x3c,0x2e,0x34,0x35,0x92,0x6d,0x22,0x74,0x1, 0x12,0x88,0xdf, +0x75,0x2b,0x20,0x7e,0x8, 0x0, 0x26,0xa, 0x3c,0x2e,0x34,0x35,0x9c,0x6d,0x22,0x74, +0x10,0x12,0x88,0xdf,0x80,0xe, 0xa, 0x3c,0x9, 0xb3,0x35,0x92,0xf5,0x25,0x9, 0xb3, +0x35,0x9c,0xf5,0x26,0xa, 0x3c,0x12,0x9f,0xe7,0xb4,0x1, 0xe, 0xe4,0xa, 0x3c,0x19, +0xb3,0x35,0x92,0x19,0xb3,0x35,0x9c,0x12,0xcd,0x33,0x7e,0xb3,0x2a,0x64,0xb4,0xff, +0x13,0x75,0x25,0x0, 0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x29,0xc, 0xbe,0xb0,0xff,0x68, +0x3, 0x75,0x25,0x1, 0x74,0x9, 0xac,0xbd,0x49,0xb5,0x29,0x8, 0x49,0xa5,0x29,0xa, +0x7d,0x3b,0x2d,0x3b,0x78,0x2, 0xb, 0xb4,0xe5,0x28,0xb4,0x1, 0x2c,0x75,0x27,0x0, +0x80,0x1d,0x7e,0x71,0x27,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x36,0x26,0x54,0xf, 0xbc, +0xbc,0x78,0xa, 0x49,0xb3,0x36,0x22,0x49,0xa3,0x36,0x24,0x80,0xc, 0x5, 0x27,0x90, +0x60,0x99,0xe4,0x93,0xbe,0xb1,0x27,0x38,0xd9,0x7e,0xa3,0x36,0x7c,0xbe,0xa0,0x3, +0x78,0x32,0x7e,0xb3,0x2a,0x3, 0x70,0x1a,0x7e,0xb3,0x2a,0x2, 0xb4,0x1, 0x13,0x7e, +0x34,0x61,0x43,0x12,0x23,0xbc,0x1e,0x34,0x1e,0x34,0xbd,0x3a,0x40,0x2, 0xa1,0xea, +0x80,0xb, 0x7e,0xb3,0x2a,0x2, 0xbe,0xb0,0x1, 0x38,0x2, 0xa1,0xea,0xe4,0x7a,0xb3, +0x36,0x7c,0xa1,0xea,0x4c,0xaa,0x78,0x2, 0xa1,0xea,0x7e,0xb3,0x2a,0x2, 0x70,0x6, +0x74,0x1, 0x7a,0xb3,0x2a,0x2, 0xe5,0x28,0xbe,0xb0,0x2, 0x68,0x9, 0xe5,0x28,0xb4, +0x1, 0x2, 0x80,0x2, 0xa1,0xea,0x7e,0xb3,0x2a,0x2, 0xb4,0x1, 0x2, 0x80,0x2, 0xa1, +0xea,0x74,0x9, 0xac,0xbc,0x49,0x25,0x36,0x22,0x7d,0x3b,0x12,0xcd,0x29,0x18,0xf, +0x74,0x9, 0xac,0xbc,0x49,0x25,0x36,0x24,0x7d,0x3a,0x12,0xcd,0x29,0x8, 0x73,0x7e, +0xb3,0x36,0x7c,0xb4,0x2, 0x6c,0x7e,0x90,0x9, 0xac,0x9c,0x49,0x14,0x36,0x22,0x7d, +0x3b,0x9d,0x31,0x7e,0x4, 0x0, 0x3, 0xad,0x30,0x7d,0x20,0x12,0x1e,0xb9,0x9d,0x13, +0x7a,0x15,0x29,0xbe,0x14,0x0, 0x0, 0x58,0x4, 0x6d,0xbb,0x80,0x14,0x7e,0x34,0x61, +0x37,0x12,0x8a,0x27,0xbe,0x15,0x29,0x58,0x5, 0xb, 0x1a,0xb0,0x80,0x3, 0x7e,0xb5, +0x29,0x74,0x9, 0xac,0xbc,0x49,0x35,0x36,0x24,0x7d,0x1a,0x9d,0x13,0xad,0x10,0x9d, +0x31,0x7a,0x35,0x29,0xbe,0x34,0x0, 0x0, 0x58,0x4, 0x6d,0xaa,0x80,0x14,0x7e,0x34, +0x61,0x43,0x12,0x8a,0x27,0xbe,0x15,0x29,0x58,0x5, 0xb, 0x1a,0xa0,0x80,0x3, 0x7e, +0xa5,0x29,0xe5,0x28,0xb4,0x1, 0x2b,0x7e,0xb3,0x36,0x7c,0xb4,0x2, 0x24,0x74,0x2, +0xac,0xbc,0x7f,0x14,0x2d,0x35,0x79,0xb1,0x0, 0x14,0x7f,0x14,0x2d,0x35,0x79,0xa1, +0x0, 0x28,0x74,0x9, 0xac,0xbc,0x59,0xb5,0x29,0x8, 0x74,0x9, 0xac,0xbc,0x59,0xa5, +0x29,0xa, 0x7e,0xb3,0x36,0x7c,0xb4,0x2, 0x5, 0x75,0x28,0x0, 0x80,0x3, 0x75,0x28, +0x2, 0xe4,0xa, 0x3c,0x2d,0x39,0x7d,0x28,0x39,0xb1,0x0, 0xa, 0x74,0x2, 0xa, 0x3c, +0x2d,0x39,0x7a,0x1b,0xb0,0xe4,0x7a,0xb3,0x2a,0x7, 0x5e,0xb4,0xf, 0xff,0x5e,0xa4, +0xf, 0xff,0x7e,0x90,0x9, 0xac,0x9d,0x9, 0x74,0x29,0xc, 0xa, 0x57,0xc4,0x54,0xf0, +0x7c,0xab,0xe4,0x2d,0xa5,0xbe,0x70,0xff,0x68,0x16,0xe5,0x28,0xbe,0xb0,0x1, 0x68, +0x2, 0x5, 0x24,0xb, 0xf0,0xe5,0x28,0xa, 0x5b,0x12,0xbe,0x10,0x2d,0xb5,0x80,0x4, +0x2e,0xb4,0xc0,0x0, 0x7e,0x70,0x6, 0xac,0x7e,0x7f,0x6, 0x2d,0x13,0x79,0xb0,0x0, +0x2, 0x7f,0x6, 0x2d,0x13,0x79,0xa0,0x0, 0x4, 0xe5,0x25,0x7f,0x6, 0x2d,0x13,0x39, +0xb0,0x0, 0x6, 0xe5,0x26,0x2d,0x3d,0x7d,0x2c,0x39,0xb1,0x0, 0x7, 0xb, 0xe0,0xb, +0xd0,0x7e,0x73,0x2a,0x4d,0xbc,0x7d,0x28,0x2, 0x61,0x95,0xe5,0x24,0x39,0xb6,0x0, +0x1, 0x7e,0xb3,0x3, 0xef,0xb4,0x1, 0xc, 0x7e,0xb3,0x2a,0x8, 0xb4,0x1, 0x23,0x12, +0x87,0xe9,0x80,0x19,0xbe,0xf0,0x0, 0x38,0x6, 0x7e,0xb3,0x2a,0x8, 0x60,0x13,0xb2, +0x10,0x12,0x87,0xe9,0x7e,0xb3,0x36,0x7c,0xbe,0xb0,0x3, 0x68,0x5, 0x74,0x1, 0x12, +0x50,0x10,0x7e,0xb3,0x2a,0x7, 0x60,0x5, 0x7f,0x4, 0x12,0x56,0xf8,0xe4,0x7a,0xb3, +0x2a,0xb, 0x7a,0xb3,0x2a,0x7, 0x7a,0xb3,0x2a,0x8, 0x80,0x4, 0xe4,0x12,0x50,0x10, +0x12,0xa2,0xe6,0xca,0x59,0x7e,0x18,0x29,0x8, 0x7e,0x8, 0x36,0x22,0x12,0x20,0xbe, +0x1b,0xfd,0x4c,0xff,0x78,0xc, 0x12,0x74,0x23,0x7e,0x8, 0x36,0x22,0x74,0xff,0x12, +0x20,0xe3,0x7e,0xb3,0x36,0x7c,0x60,0x5, 0x14,0x7a,0xb3,0x36,0x7c,0xda,0x3b,0x22, +0xc2,0x0, 0x7e,0xb3,0x16,0x91,0x60,0x6, 0x7e,0xb3,0x16,0x90,0x70,0x7, 0x12,0x9f, +0xd4,0x28,0x2, 0xd2,0x0, 0xa2,0x0, 0x22,0x6c,0xaa,0x80,0x20,0x74,0x3, 0x12,0xac, +0xaf,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, 0x12,0x57,0x22,0x7f,0x70,0x2d,0xf3, +0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, 0x28,0xb, 0xa0,0x12,0x53,0x21,0x38, +0xdb,0x22,0x7e,0x44,0x7f,0xff,0x7e,0x70,0x2, 0xac,0x7a,0x22,0xca,0xf8,0x7e,0xa3, +0x2a,0x2, 0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x2a,0x3, 0xbe,0xb0,0x0, 0x28,0x13,0x74, +0x1, 0x7a,0xb3,0x2a,0x7, 0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3, +0x2a,0xb, 0x12,0xa2,0xe6,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29,0x8, 0x12, +0x20,0xbe,0x1b,0xfd,0x90,0x61,0x35,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x23,0x6c,0xff, +0x80,0x1a,0x12,0xa4,0xfe,0x12,0x89,0x21,0x74,0x9, 0xac,0xbf,0x59,0x35,0x29,0x8, +0x49,0x35,0x28,0xb0,0x12,0x35,0x7e,0x12,0x8f,0xaf,0xb, 0xf0,0x12,0x53,0x30,0x38, +0xe1,0xda,0xf8,0x22,0x2, 0x57,0x97,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x2a,0x6f,0xf5, +0x27,0x7e,0xb3,0x2a,0x70,0xf5,0x28,0x75,0x2b,0x0, 0x7e,0xb3,0x16,0x91,0xbe,0xb0, +0x1, 0x68,0x11,0x60,0x3, 0x2, 0x59,0x36,0x7e,0xb3,0x28,0x84,0xb4,0x1, 0x2, 0x80, +0x3, 0x2, 0x59,0x36,0x6c,0xee,0x2, 0x59,0x2a,0x12,0xcc,0x9a,0x7e,0xb3,0x28,0x84, +0xb4,0x1, 0xb, 0x7e,0xb3,0x37,0xe5,0x70,0x5, 0x12,0x59,0x40,0x80,0x6, 0x75,0x25, +0x2, 0x75,0x26,0x2, 0x7c,0xbe,0x12,0x83,0x7a,0xd2,0x0, 0x12,0x84,0xbb,0x7e,0xb3, +0x3, 0xaa,0xb4,0x1, 0x1b,0x7e,0xb3,0x2a,0x3, 0xb4,0x1, 0x14,0x7e,0xb3,0x28,0x84, +0xb4,0x1, 0xd, 0x7e,0x37,0x28,0x86,0xbe,0x34,0x0, 0xa, 0x40,0x3, 0x12,0x59,0x40, +0x4c,0xdd,0x68,0x7, 0xe5,0x27,0x12,0xcd,0x4c,0x48,0x3, 0x75,0x25,0x1, 0x4c,0xcc, +0x68,0xc, 0xe5,0x28,0xa, 0x2b,0x1b,0x24,0xa, 0x3c,0xbd,0x32,0x48,0x3, 0x75,0x26, +0x1, 0x75,0x24,0x0, 0x80,0x4e,0xe5,0x24,0xbc,0xbe,0x68,0x46,0x12,0xcc,0x5a,0x7a, +0xa1,0x29,0x9, 0xb3,0x26,0xfb,0xf5,0x2a,0xa, 0x2a,0x12,0x59,0x39,0xbe,0x34,0x0, +0x3, 0x18,0x11,0x12,0x59,0x47,0xbe,0x34,0x0, 0x3, 0x18,0x8, 0x75,0x25,0x1, 0x75, +0x26,0x1, 0x80,0x25,0xe5,0x29,0xa, 0x2b,0x12,0x59,0x39,0xbe,0x34,0x0, 0x5, 0x18, +0x11,0x12,0x59,0x47,0xbe,0x34,0x0, 0x5, 0x18,0x8, 0x75,0x25,0x2, 0x75,0x26,0x2, +0x80,0x7, 0x5, 0x24,0x12,0xcd,0xab,0x38,0xad,0x7c,0xbd,0x7c,0x7c,0x12,0xa6,0x94, +0x50,0x8, 0x12,0x59,0x65,0x12,0xcd,0x33,0x80,0x28,0x12,0x5c,0xf0,0x50,0x23,0x7e, +0x73,0x33,0x4c,0xbc,0x7d,0x78,0x8, 0x7e,0x73,0x33,0x4e,0xbc,0x7c,0x68,0x10,0x7e, +0x73,0x33,0x4d,0xbc,0x7d,0x78,0xb, 0x7e,0x73,0x33,0x4f,0xbc,0x7c,0x78,0x3, 0x12, +0x59,0x40,0x4c,0xdd,0x78,0x2, 0x80,0x7, 0xe5,0x27,0x14,0xbc,0xbd,0x78,0xd, 0x12, +0x59,0x52,0xb, 0xa, 0x30,0x9e,0x34,0x0, 0x32,0x1b,0xa, 0x30,0xe5,0x28,0x14,0xbc, +0xbc,0x78,0x2, 0x80,0x4, 0x4c,0xcc,0x78,0xd, 0x12,0x59,0x52,0xb, 0xa, 0x30,0x9e, +0x34,0x0, 0x3c,0x1b,0xa, 0x30,0xe5,0x25,0x7e,0x71,0x26,0x7c,0x6e,0x7c,0x5f,0x7e, +0x41,0x2b,0x12,0x5a,0x41,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x16,0x7e,0x70,0x9, +0xac,0x7e,0x7d,0x13,0x2e,0x14,0x27,0x76,0x6d,0x0, 0x2e,0x34,0x27,0x78,0x6d,0x22, +0x12,0x88,0xd0,0x12,0x59,0x65,0xb, 0xf0,0xb, 0xe0,0x12,0x5f,0xf1,0x28,0x3, 0x2, +0x57,0xc9,0x7a,0xf3,0x28,0x84,0xda,0x3b,0x22,0xa, 0x3d,0x9d,0x32,0x2, 0x21,0x15, +0x75,0x25,0x3, 0x75,0x26,0x3, 0x22,0xe5,0x2a,0xa, 0x2b,0xa, 0x3c,0x9d,0x32,0x2, +0x21,0x15,0x7e,0x73,0x2a,0x6e,0xac,0x7d,0xa, 0x2c,0x2d,0x32,0x3e,0x34,0x7e,0xf, +0x13,0x8a,0x2d,0x13,0x22,0x12,0x86,0xc8,0x60,0x28,0x6c,0x22,0x80,0x1c,0x7c,0xb2, +0x12,0x83,0x58,0x50,0x13,0x7c,0xb2,0x12,0x84,0x88,0x7d,0x3, 0x12,0x86,0xc0,0x49, +0x55,0x39,0xe0,0x7d,0x40,0x12,0xcc,0xd4,0xb, 0x20,0x7e,0x73,0x2a,0x75,0xbc,0x72, +0x38,0xdc,0x22,0xca,0x3b,0x12,0x4a,0xff,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3, +0x37,0xd3,0x60,0x9, 0xe4,0x7a,0xb3,0x37,0xd5,0x7a,0xb3,0x37,0x5a,0x7e,0xb3,0x37, +0xd3,0x70,0x6b,0x6c,0x99,0x80,0x5f,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x26,0xfa,0x9, +0xf5,0x26,0xfb,0x7c,0xb9,0x12,0xb9,0xb3,0x40,0x4a,0x6c,0xee,0x80,0x3e,0x74,0x2, +0xac,0xbe,0x9, 0xd5,0x37,0x5b,0x9, 0xc5,0x37,0x5c,0xa, 0x28,0x12,0x59,0x39,0x4d, +0x33,0x78,0x27,0xa, 0x2f,0x12,0x59,0x4b,0x4d,0x33,0x78,0x1e,0x7c,0xb9,0x12,0x5e, +0x76,0x7e,0x14,0x62,0x31,0x12,0x47,0xe0,0xbd,0x32,0x58,0xe, 0x7c,0xb9,0x6c,0x77, +0x12,0x5f,0x7, 0x7c,0xb8,0x7c,0x7f,0x12,0xa9,0x7c,0xb, 0xe0,0x7e,0x73,0x37,0xd5, +0xbc,0x7e,0x38,0xba,0xb, 0x90,0x7e,0x73,0x28,0x84,0xbc,0x79,0x38,0x99,0x7e,0x73, +0x37,0x5a,0x7a,0x73,0x37,0xd5,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x37,0x97, +0x7e,0x8, 0x37,0x5b,0x12,0x20,0xbe,0x1b,0xfd,0xe4,0x7a,0xb3,0x37,0xd3,0xda,0x3b, +0x22,0xca,0x3b,0x7a,0x41,0x2c,0x12,0x9f,0xdc,0x74,0x9, 0xac,0xbf,0x7d,0x95,0x2e, +0x94,0x27,0x76,0x6d,0x88,0x7e,0xe7,0x2a,0x66,0xe4,0x39,0xb4,0x0, 0x6, 0x7e,0x70, +0x2, 0xac,0x7e,0x9, 0xb3,0x26,0xfa,0xf5,0x37,0x9, 0xb3,0x26,0xfb,0xf5,0x38,0x7e, +0x73,0x2a,0x6e,0x7c,0x6d,0x7e,0x8, 0x0, 0x3b,0x12,0x5c,0x9d,0xf5,0x39,0xe5,0x37, +0x7e,0x73,0x2a,0x6d,0x7c,0x6c,0x7e,0x8, 0x0, 0x3a,0x12,0x5c,0x9d,0x7c,0xab,0xe5, +0x3a,0x7e,0x71,0x3b,0x12,0x86,0xea,0x7d,0xf3,0x7a,0xf5,0x43,0x7e,0xf4,0x15,0x9e, +0x7a,0xf5,0x45,0x85,0x3a,0x3d,0x85,0x3b,0x3e,0x7a,0xa1,0x3f,0x85,0x39,0x40,0x7e, +0xb3,0x2a,0x59,0xf5,0x41,0x75,0x42,0x0, 0xe5,0x2c,0xb4,0x1, 0x8, 0xe5,0x41,0x1e, +0xb0,0x1e,0xb0,0xf5,0x41,0x7e,0x8, 0x0, 0x3d,0x12,0x90,0xc4,0x7d,0x23,0x6d,0x33, +0x7e,0xb7,0x15,0xa0,0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x15,0xa2,0x6d,0x22,0x7d,0x3, +0x6d,0x11,0x7e,0x37,0x15,0xa4,0x2f,0x10,0x7a,0x1d,0x2d,0x7e,0x37,0x15,0xa6,0x6d, +0x22,0x7d,0x3, 0x7e,0x37,0x15,0xa8,0x2f,0x10,0x7a,0x1d,0x31,0x7f,0x65,0xa, 0x4c, +0xe5,0x37,0xa, 0x5b,0x9d,0x54,0xf5,0x35,0x61,0xe1,0xa, 0x4d,0xe5,0x38,0xa, 0x5b, +0x9d,0x54,0xf5,0x36,0x61,0xcb,0xe5,0x35,0xbe,0xb0,0x0, 0x58,0x2, 0x61,0xc9,0x7e, +0x73,0x2a,0x6d,0xbe,0x71,0x35,0x18,0x2, 0x61,0xc9,0xe5,0x36,0xbe,0xb0,0x0, 0x58, +0x2, 0x61,0xc9,0x7e,0x73,0x2a,0x6e,0xbe,0x71,0x36,0x18,0x2, 0x61,0xc9,0xe5,0x35, +0x7e,0x71,0x36,0x12,0x4b,0x45,0x7e,0x53,0x2a,0x59,0xa, 0x25,0x7d,0xf3,0x9d,0xf2, +0xbe,0xf4,0x0, 0x0, 0x8, 0x73,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e,0x34,0x0, 0x6, +0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5,0x37,0xa, 0x2b,0xe5,0x35,0x12,0x5c,0x82, +0x18,0xb, 0xe5,0x38,0xa, 0x2b,0xe5,0x36,0x12,0x5c,0x82,0x8, 0x4c,0xe5,0x35,0x7e, +0x71,0x36,0x7c,0x6e,0x12,0xb6,0x1f,0xf5,0x3c,0xb4,0x2, 0x6, 0x7d,0x3f,0xe, 0x34, +0x9d,0xf3,0xe5,0x3c,0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3c,0xb4,0x1, 0x2b,0x12,0x5c, +0x71,0xe5,0x35,0x12,0x5c,0x78,0x7e,0x1d,0x2d,0x9f,0x10,0x7a,0x1d,0x2d,0x12,0x5c, +0x71,0xe5,0x36,0x12,0x5c,0x78,0x7e,0x1d,0x31,0x9f,0x10,0x7a,0x1d,0x31,0x12,0x5c, +0x71,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f,0x61,0x5, 0x36,0xa, 0x2d,0xe5,0x38,0xa, +0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x36,0x1a,0x3b,0xbd,0x32,0x18,0x2, 0x61,0x16,0x5, +0x35,0xa, 0x2c,0xe5,0x37,0xa, 0x3b,0x2d,0x32,0x1a,0x37,0xe5,0x35,0x1a,0xfb,0xbd, +0xf3,0x18,0x2, 0x61,0xa, 0xbe,0x58,0x0, 0x0, 0x78,0x2, 0xb, 0x5c,0xbe,0x68,0x0, +0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2d,0x7f,0x5, 0x12,0x5c,0x8e,0x1b,0x4a,0x30, +0x7e,0x1d,0x31,0x7f,0x6, 0x12,0x5c,0x8e,0x79,0x34,0x0, 0x2, 0x7e,0xb3,0x2a,0x65, +0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80,0x0, 0x14,0x78,0xf3,0xbe, +0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d,0x39,0x74,0x0, 0x5, 0x74, +0x9, 0xac,0xbe,0x9, 0x75,0x27,0x7c,0x39,0x74,0x0, 0x6, 0xbe,0x70,0xf, 0x28,0x6, +0x74,0xf, 0x39,0xb4,0x0, 0x6, 0x7e,0xa1,0x37,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3, +0x27,0x7d,0x7e,0xa1,0x38,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x27,0x7e,0xda,0x3b, +0x22,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x22,0x1a,0x1b,0x1a,0x2, 0x12,0x1e,0xeb,0x7f, +0x1, 0x22,0x1a,0x3b,0x9d,0x32,0x12,0x21,0x15,0xbe,0x34,0x0, 0x1, 0x22,0x74,0x6, +0x2f,0x11,0x14,0x78,0xfb,0x12,0x1f,0x7, 0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c, +0xf6,0x7c,0x87,0x7c,0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc, +0xf9,0x38,0x14,0xa, 0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18, +0x6, 0x7c,0xab,0xa, 0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d, +0x53,0xb, 0x54,0x7c,0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39, +0x9d,0x53,0x7c,0xab,0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22, +0xa2,0x13,0x22,0xca,0x79,0x7e,0xa3,0x2a,0x2, 0x7e,0x8, 0x29,0xbc,0x7e,0x90,0xa, +0x12,0x5c,0xf0,0x50,0x3, 0x7e,0x90,0x19,0x4c,0xaa,0x78,0x5, 0x12,0x6a,0x49,0xc1, +0x25,0x6c,0x88,0xc1,0x1a,0x7e,0x70,0x9, 0xac,0x78,0x9, 0xf3,0x29,0xc, 0xbe,0xf0, +0xff,0x78,0x2, 0xc1,0x18,0xa, 0x2f,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0xe0,0xbe,0xe0, +0x2, 0x68,0x2, 0xa1,0xfb,0x7e,0x50,0x4, 0xac,0x5f,0x49,0x22,0x37,0x32,0x49,0x33, +0x29,0x8, 0x12,0xcd,0x9b,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x23,0x37,0x34,0x12,0x5e, +0x30,0x9d,0x32,0x12,0x21,0x15,0x7d,0xe3,0x7e,0xb3,0x36,0x7d,0xa, 0x3b,0xbd,0x3f, +0x28,0x54,0xbd,0x3e,0x28,0x50,0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x37,0x32,0x7e, +0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0x8, 0x7e,0x70,0x4, 0xac,0x7f,0x49,0x33,0x37, +0x34,0x7e,0x50,0x9, 0xac,0x58,0x59,0x32,0x29,0xa, 0xbe,0xa0,0x0, 0x28,0x2, 0x1b, +0xa0,0x4c,0xaa,0x68,0x2, 0xc1,0x18,0x7e,0xb3,0x36,0x7e,0x4, 0x7a,0xb3,0x36,0x7e, +0xbe,0xb0,0x32,0x40,0x73,0xe4,0x7a,0xb3,0x36,0x7e,0x12,0x5e,0x28,0x50,0x69,0x4, +0x7a,0xb3,0x36,0x7d,0x80,0x62,0x7e,0x70,0x9, 0xac,0x78,0x49,0xd3,0x29,0x8, 0x7e, +0x50,0x4, 0xac,0x5f,0x59,0xd2,0x37,0x32,0x49,0x33,0x29,0xa, 0x59,0x32,0x37,0x34, +0x12,0x5c,0xf0,0x50,0x7, 0x12,0x5e,0x28,0x28,0x1a,0x80,0x13,0x7e,0x73,0x36,0x7d, +0xbc,0x79,0x40,0x4, 0x74,0x1, 0x80,0x8, 0xbe,0x70,0x1, 0x28,0x7, 0x7c,0xb7,0x14, +0x7a,0xb3,0x36,0x7d,0xe4,0x7a,0xb3,0x36,0x7e,0x80,0x1d,0x4c,0xee,0x78,0x19,0x7e, +0x70,0x9, 0xac,0x78,0x49,0x33,0x29,0x8, 0x7e,0x50,0x4, 0xac,0x5f,0x59,0x32,0x37, +0x32,0x12,0x5e,0x30,0x59,0x32,0x37,0x34,0xb, 0x80,0x90,0x60,0x99,0xe4,0x93,0xbc, +0xb8,0x28,0x2, 0xa1,0x15,0xda,0x79,0x22,0x7e,0xb3,0x36,0x7d,0xbe,0xb0,0x1, 0x22, +0x7e,0x70,0x9, 0xac,0x78,0x49,0x33,0x29,0xa, 0x22,0x12,0x5c,0xf3,0x2, 0x5e,0x40, +0x7e,0xb3,0x2a,0x9, 0x70,0x23,0x7e,0xb3,0x36,0x95,0xb4,0x2, 0x9, 0x12,0xa4,0xf6, +0x28,0x4, 0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x36,0xa0,0x7e,0x73,0x36,0xa1,0xbe, +0x73,0x36,0xa0,0x28,0x4, 0x7a,0x73,0x36,0xa0,0x22,0x12,0xa8,0xee,0x12,0x62,0xb4, +0x12,0x5f,0x46,0x2, 0x59,0x93,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7a,0x12,0x62,0xab, +0x2, 0x4b,0x45,0xca,0x79,0x6c,0x88,0x80,0x70,0x74,0x2, 0xac,0xb8,0x9, 0xf5,0x26, +0xfa,0x9, 0x75,0x26,0xfb,0x7a,0x71,0x24,0x7c,0xbf,0x12,0x86,0xd0,0x50,0x58,0x6c, +0xee,0x80,0x4f,0xbc,0xe8,0x68,0x49,0x7e,0x70,0x2, 0xac,0x7e,0x12,0xcc,0x8d,0x6c, +0x99,0x90,0x60,0xaa,0xe4,0x93,0x70,0x18,0x7e,0xb3,0x2a,0x70,0x14,0xbe,0xb1,0x26, +0x78,0xe, 0xa, 0x2f,0xe5,0x25,0xa, 0x3b,0x12,0x5c,0x84,0x18,0x3, 0x7e,0x90,0x1, +0xbe,0x90,0x1, 0x78,0x1b,0x7c,0xbe,0x12,0x5e,0x76,0x7d,0xf3,0x7c,0xb8,0x12,0x5e, +0x76,0xbd,0x3f,0x8, 0x4, 0x7c,0xbe,0x80,0x2, 0x7c,0xb8,0x6c,0x77,0x12,0x5f,0x7, +0xb, 0xe0,0x12,0x5f,0xf1,0x38,0xac,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc,0x78,0x38, +0x88,0xda,0x79,0x22,0x7e,0x70,0x1, 0x7c,0x67,0x7c,0x7b,0xc4,0x23,0x54,0x1f,0x7c, +0xab,0x7c,0xb7,0x54,0x7, 0xa, 0x2b,0x2e,0x24,0x0, 0x5e,0x12,0x81,0xef,0x7c,0x7b, +0x4c,0x66,0x68,0xf, 0xa, 0x2a,0x2e,0x24,0x27,0x72,0x7e,0x29,0xb0,0x4c,0xb7,0x7a, +0x29,0xb0,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a,0x2e,0x24,0x27,0x72,0x7e,0x29,0x70, +0x5c,0x7b,0x7a,0x29,0x70,0x22,0xca,0xd8,0xca,0x79,0x7e,0x34,0x62,0x2d,0x12,0xcd, +0xb3,0x12,0xa9,0x56,0x50,0x2, 0xe1,0xec,0x7e,0x34,0x62,0x31,0x12,0x23,0xbc,0x7a, +0x35,0x2a,0x90,0x62,0x2c,0xe4,0x93,0x70,0x2, 0xe1,0xec,0x7e,0xb3,0x28,0xa8,0xb4, +0x1, 0x7, 0x7e,0x34,0x62,0x2f,0x12,0xcd,0xb3,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x4, +0x4c,0x8, 0x69,0x6c,0xdd,0x80,0x5d,0xc2,0x0, 0x7c,0xbd,0x12,0x5e,0x76,0x7a,0x35, +0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xb8,0xe8,0x7a,0x35,0x24,0x9e,0x35,0x26,0x7a, +0x35,0x24,0x7e,0x35,0x26,0x3e,0x34,0x3e,0x34,0x12,0x5f,0xf8,0x7a,0x35,0x28,0xbe, +0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e,0x35,0x28,0xbe,0x35,0x24,0x8, 0xa, 0x7e, +0x35,0x2a,0xbe,0x35,0x26,0x8, 0x2, 0xd2,0x0, 0x7c,0xbd,0x12,0xb9,0xb3,0x50,0x2, +0xc2,0x0, 0x30,0x0, 0xd, 0x7c,0xbd,0x12,0xcd,0x43,0xac,0x7d,0x12,0x62,0xab,0x12, +0xa9,0x7c,0xb, 0xd0,0x7e,0x73,0x28,0x84,0xbc,0x7d,0x38,0x9b,0xda,0x79,0xda,0xd8, +0x22,0x7e,0x73,0x28,0x84,0xbc,0x7e,0x22,0x7e,0x24,0x0, 0x2, 0x2, 0x1e,0xb9,0xff, +0x70,0x8f,0x0, 0xff,0x51,0xae,0x5a,0xa5,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x34,0x37,0x32,0x1, 0xd2,0x0, 0x34,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x6, 0xf9,0x44,0x32,0x5f,0x4f,0x66,0x69,0x6c,0x6d,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xe, 0x19,0xb, 0xa, 0xc, 0xd, 0xe, 0x7, 0x9, 0x6, 0x5, 0x4, 0x3, 0x2, 0x0, 0x1, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0xc, 0xb, 0xd, 0xa, +0x9, 0x18,0x15,0x17,0x14,0x16,0x13,0xf, 0x12,0xe, 0x11,0x7, 0x10,0x8, 0x0, 0x0, +0x0, 0x5, 0x0, 0x4, 0xff,0x23,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x14,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x3, 0x1, 0x0, 0x0, 0x18,0x2, 0x6, 0xb, 0x0, +0x0, 0x0, 0x64,0x0, 0xfa,0x1, 0x2c,0x2, 0xbc,0x2, 0xee,0x4, 0x1a,0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc8,0x1, 0xf4,0x3, 0x20,0x0, 0x0, 0x0, 0x0, 0x7, +0xf8,0x0, 0x14,0x1, 0x19,0x1e,0x1, 0xf4,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, +0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x0, 0x4, 0x3e,0x28,0x1, 0x20,0x3, 0x0, 0x0, +0x0, 0x0, 0x1, 0xf4,0x5a,0x40,0xe, 0x19,0x27,0x13,0xd, 0x6, 0x80,0x13,0xd, 0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x46,0x45,0x2, 0x4e,0x2, 0x4e,0x1, +0x38,0x1, 0x3b,0x7, 0x80,0x46,0x48,0x2, 0xe, 0x2, 0xe, 0x1, 0x43,0x1, 0x43,0x0, +0xa0,0x0, 0x8c,0x0, 0x8c,0x0, 0xc8,0x0, 0x64,0x0, 0xb4,0x0, 0xb4,0xa, 0x0, 0x0, +0xdc,0x6, 0xa, 0x14,0x28,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x15, +0x0, 0x1, 0x54,0x1, 0x0, 0x6, 0x1, 0x51,0x1, 0x14,0x0, 0x5a,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x96, +0x2, 0x26,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8, +0x0, 0x50,0x1, 0xf4,0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x3, 0x3e,0x5a,0x28, +0x24,0x3, 0x41,0x5c,0x28,0x2b,0x3, 0x43,0x5d,0x28,0x33,0x3, 0x47,0x5f,0x28,0x1e, +0x3, 0x3e,0x5a,0x28,0x1e,0x3, 0x3e,0x5a,0x28,0x1e,0x3, 0x3e,0x5a,0x28,0x1e,0x3, +0x3e,0x5a,0x28,0x4, 0x5, 0xd, 0xe, 0xf, 0x10,0x11,0x4, 0x0, 0x96,0x1, 0x90,0x28, +0x1, 0x2c,0x1, 0x5e,0x0, 0xc8,0x0, 0x64,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, +0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, +0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, 0x90, +0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, 0x50, +0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x8, 0x0, 0x50, +0x3, 0xe8,0x0, 0x50,0x7, 0x30,0x0, 0x32,0x1, 0xf4,0x1, 0xf4,0x2, 0x58,0x0, 0xc8, +0x0, 0x4d,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x0, 0xf0,0x0, 0x3c,0x3, 0xe8,0x1, 0xe0, +0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x7, 0x80,0x0, 0x64, +0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, +0xb, 0xc, 0x5, 0x6, 0x8, 0x9, 0x6, 0x6, 0xc, 0x64,0xc8,0x9, 0xb3,0x26,0xfa,0x9, +0x73,0x26,0xfb,0x22,0xca,0x3b,0x7e,0xb3,0x2a,0x74,0xf5,0x27,0x12,0x63,0x64,0x50, +0x2, 0x61,0x59,0x6d,0x33,0x9e,0x37,0x2a,0x4f,0x3e,0x34,0xbe,0x37,0x7, 0xf8,0x8, +0x2, 0x61,0x59,0x7e,0xb3,0x16,0x92,0x60,0x2, 0x61,0x59,0x7e,0xb3,0x28,0xa8,0xb4, +0x1, 0x68,0x7e,0x77,0x2a,0x51,0x7e,0x67,0x2a,0x53,0x75,0x24,0x0, 0x80,0x56,0xe5, +0x24,0x12,0x4f,0xc5,0x60,0x4d,0x12,0x63,0x5c,0x12,0xcc,0x8d,0x7e,0xb3,0x2a,0x3, +0xb4,0x1, 0xe, 0x90,0x60,0xab,0xe4,0x93,0xbe,0xb1,0x26,0x78,0x4, 0xe, 0x64,0xe, +0x74,0x7e,0xa1,0x26,0x74,0x2, 0xa4,0x49,0x35,0x4, 0xfc,0xbd,0x36,0x48,0x14,0xe5, +0x25,0xa, 0x2b,0xe5,0x27,0xa, 0x3b,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xfc,0xbd, +0x37,0x58,0x10,0xe5,0x24,0x6c,0x77,0x12,0x5f,0x7, 0x12,0x63,0x5c,0x12,0x62,0xab, +0x12,0xa9,0x7c,0x5, 0x24,0x12,0xcd,0xab,0x38,0xa5,0x7e,0xb3,0x2a,0x68,0x70,0x9, +0x7e,0xb3,0x2a,0x6b,0x70,0x3, 0x12,0xa9,0x5, 0xda,0x3b,0x22,0x7e,0x71,0x24,0x74, +0x2, 0xac,0x7b,0x22,0xa2,0x16,0x22,0x7e,0x90,0x1, 0x7e,0x94,0x61,0xc6,0x7e,0x84, +0x0, 0xff,0xb, 0x4a,0x30,0x7a,0x37,0x28,0xa1,0x7e,0xb4,0x61,0xc8,0x7e,0xa4,0x0, +0xff,0xb, 0x5a,0x30,0x7a,0x37,0x28,0xa3,0x12,0x66,0x47,0xb, 0x1a,0x20,0x7e,0x14, +0x61,0x4f,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xd0,0xe4,0x7a,0xb3,0x28,0xac,0x12,0x64, +0xd1,0x7e,0x34,0xff,0xfa,0xad,0x32,0x12,0x5f,0xf8,0x7d,0xc3,0xe, 0x34,0x7e,0x27, +0x7, 0xfe,0xbd,0x2c,0x58,0x1c,0x7e,0xc7,0x7, 0xfc,0xbd,0xc3,0x58,0x14,0x6d,0xcc, +0x9e,0xc7,0x2a,0x5a,0xbe,0xc7,0x28,0x8e,0x8, 0x8, 0x12,0xb4,0x47,0x60,0x3, 0x12, +0xb0,0xd, 0x12,0xb0,0x1c,0x40,0x5, 0xe4,0x7a,0xb3,0x28,0xa8,0x12,0x99,0x5d,0x68, +0x6, 0x7e,0xb3,0x39,0xfc,0x60,0x7, 0xe4,0x7a,0xb3,0x28,0xad,0x80,0x6f,0x12,0x64, +0xd8,0x28,0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x30,0x12,0x5, 0xe4,0x7a,0xb3,0x28,0xad, +0x12,0xad,0x4b,0x50,0xa, 0x12,0x64,0xd1,0x12,0x64,0xee,0x7c,0x9b,0x80,0x17,0x7e, +0xb3,0x26,0x84,0x70,0x11,0x7e,0xb3,0x26,0x85,0x70,0xb, 0x12,0x64,0xd8,0x28,0x6, +0x7e,0x90,0x3, 0x12,0x64,0xd1,0x7e,0xc7,0x7, 0xfa,0xbe,0xc4,0x5, 0xdc,0x8, 0x17, +0x12,0x64,0xd8,0x28,0x12,0x6d,0xcc,0x9d,0xcd,0xbe,0xc7,0x28,0x8e,0x58,0x8, 0x12, +0x64,0xe0,0xe4,0x7a,0xb3,0x28,0xad,0xa, 0x29,0xb, 0x4a,0x30,0xad,0x32,0x7a,0x37, +0x28,0xa1,0xa, 0x29,0xb, 0x5a,0x30,0xad,0x32,0x7a,0x37,0x28,0xa3,0x12,0x63,0x64, +0x50,0xd, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x8f,0xe3,0x28,0x3, 0x12,0x64,0xe0,0x7e, +0xc7,0x28,0x8a,0xbd,0xcd,0x8, 0x1f,0x7e,0x24,0x0, 0x2, 0x7d,0x3d,0x12,0x1e,0xb9, +0x6e,0x34,0xff,0xff,0xb, 0x34,0xbe,0x37,0x28,0x8e,0x58,0xa, 0x12,0x63,0x64,0x50, +0x5, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x65,0x5a,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x28, +0xad,0x12,0xaf,0x74,0x7e,0xb3,0x0, 0x66,0xbe,0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3, +0x0, 0x66,0x70,0x1c,0xe4,0x7a,0xb3,0x28,0xad,0x74,0x1, 0x7a,0xb3,0x28,0xac,0xe4, +0x7a,0xb3,0x16,0x91,0x7a,0xb3,0x16,0x90,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x26,0x83, +0x22,0x74,0x1, 0x7a,0xb3,0x28,0xad,0x22,0x7e,0x83,0x28,0x84,0xbe,0x80,0x0, 0x22, +0xe4,0x7a,0xb3,0x0, 0x66,0x7a,0xb3,0x28,0xac,0x74,0x2, 0x2, 0x47,0xfc,0x7e,0xa0, +0x1, 0x7e,0x47,0x7, 0xf8,0x12,0x66,0x47,0xb, 0x1a,0x0, 0x7e,0x34,0xff,0xfa,0xad, +0x30,0x7e,0x14,0x0, 0x2, 0x12,0x65,0x52,0x8, 0x12,0x7e,0xb3,0x28,0xac,0x60,0x7, +0xe4,0x7a,0xb3,0x28,0xad,0x80,0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb, +0xad,0x30,0x12,0x65,0x52,0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x23,0x7e,0x34,0xff,0xfc, +0xad,0x30,0x12,0x65,0x52,0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x13,0x7e,0x34,0xff,0xfd, +0xad,0x30,0x12,0x65,0x52,0x8, 0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c, +0xba,0x22,0x7d,0x21,0x12,0x1e,0xb9,0xbd,0x34,0x22,0xca,0x3b,0x12,0xa9,0x4e,0x38, +0x2, 0xc1,0x1d,0x7e,0xc3,0x0, 0x69,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x0, 0x69,0xe4, +0x7a,0xb3,0x0, 0x6b,0x6c,0xaa,0x80,0x26,0x12,0x66,0x28,0x7e,0x70,0x2, 0xac,0x7a, +0x9, 0xd3,0x26,0xfa,0x9, 0xe3,0x26,0xfb,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74, +0x1, 0x19,0xb4,0x0, 0x8, 0x12,0x66,0x32,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3, +0x28,0x84,0xbc,0xba,0x38,0xd2,0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80,0x31,0x12,0x66, +0x28,0x7e,0x49,0xd0,0x9, 0xe4,0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0, +0x80,0x1b,0x12,0x66,0x32,0x7d,0x23,0x49,0x34,0x0, 0x2, 0x12,0xcd,0x9b,0xbe,0xf4, +0x0, 0x23,0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x63,0x1, 0xb, 0xa0,0xbc, +0xfa,0x38,0xcb,0x4c,0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x0, 0x6b,0xbe,0x70,0x4, +0x40,0x22,0x6c,0xaa,0x80,0xe, 0x12,0x66,0x28,0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, +0x68,0x6, 0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x63,0x0, 0x12, +0x66,0x39,0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3,0x0, 0x6b,0x80,0x6, 0x12,0x66,0x39, +0x75,0x63,0x0, 0xe5,0x63,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x0, +0x6c,0x22,0x7c,0xbd,0x7c,0x7e,0x2, 0x4b,0x45,0xe4,0x7a,0xb3,0x0, 0x6a,0x7a,0xb3, +0x0, 0x69,0x7a,0xb3,0x0, 0x6b,0x22,0x7e,0x34,0x61,0x55,0x7e,0x24,0x0, 0xff,0x22, +0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6d,0x88,0x7a,0x87,0x39,0x51,0xe4,0x7a,0xb3,0x1f, +0x58,0xe5,0x61,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x61,0x7e,0xb3,0x28,0x84,0x60,0xc, +0x12,0x66,0x47,0xb, 0x1a,0x80,0xbe,0x87,0x7, 0xfa,0x28,0xa, 0xc2,0x12,0x6d,0x88, +0x7a,0x87,0x39,0x12,0xe1,0x7b,0x12,0x99,0x65,0x60,0x12,0x7e,0x34,0x62,0x14,0x12, +0xcd,0x93,0x7a,0x87,0x39,0x8, 0x12,0x67,0xe9,0x7a,0x87,0x39,0x12,0x7e,0x87,0x39, +0x8, 0x4d,0x88,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xa9,0x6c,0xff,0x80,0x77,0xe4, +0xa, 0x3f,0x19,0xb3,0x1f,0x34,0x12,0xcc,0xae,0x7e,0x8, 0x1f,0x52,0x7c,0xbd,0x7c, +0x7e,0x12,0x97,0x70,0x7d,0x93,0x7e,0x87,0x39,0x12,0xbd,0x89,0x50,0x4, 0x7a,0x97, +0x39,0x12,0x7e,0x87,0x39,0x51,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x39,0x51,0xe5,0x61, +0xbe,0xb0,0x5, 0x38,0x1f,0x7e,0x8, 0x39,0x14,0x12,0x98,0xce,0x50,0x7, 0x12,0xcd, +0x55,0xd2,0x0, 0x80,0x2f,0x7e,0x8, 0x39,0x14,0x7e,0x18,0x1f,0x52,0x12,0x99,0x14, +0x50,0x22,0x80,0x10,0x12,0x67,0xe9,0xbd,0x89,0x38,0x19,0x7e,0x8, 0x1f,0x52,0x12, +0x95,0x8a,0x50,0x10,0x12,0xcd,0x55,0x7e,0x8, 0x1f,0x58,0x7e,0x18,0x1f,0x52,0x12, +0x98,0xa8,0xd2,0x0, 0xb, 0xf0,0x12,0x67,0xe2,0x38,0x84,0x30,0x0, 0x33,0x6c,0xff, +0x80,0x1c,0x12,0xcc,0xae,0x7e,0x8, 0x1f,0x58,0x12,0x98,0xce,0x40,0x9, 0xa, 0x3f, +0x9, 0xb3,0x1f,0x34,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x95,0x3a,0xb, 0xf0,0x12,0x67, +0xe2,0x38,0xdf,0x75,0x61,0x0, 0x7e,0x34,0x62,0x14,0x12,0x23,0xbc,0x7a,0x37,0x39, +0x8, 0x7e,0x63,0x1f,0x58,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18, +0x1f,0x58,0x7e,0x8, 0x39,0x14,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x37,0x39,0x8, 0x4d, +0x33,0x78,0x39,0x90,0x62,0xf, 0xe4,0x93,0xa, 0x3b,0xbe,0x37,0x39,0x12,0x38,0x40, +0x7c,0x7b,0x1e,0x70,0xa, 0x37,0xbe,0x37,0x39,0x51,0x38,0x34,0x90,0x60,0x51,0x12, +0x67,0xf1,0x7e,0x73,0x26,0xf7,0xa, 0x37,0xbd,0x32,0x8, 0x24,0x90,0x60,0x50,0x12, +0x67,0xf1,0x7e,0x73,0x26,0xf6,0xa, 0x37,0xbd,0x32,0x8, 0x14,0x6c,0xff,0x80,0x7, +0x7c,0xbf,0x12,0x95,0x3a,0xb, 0xf0,0x12,0x67,0xe2,0x38,0xf4,0xd2,0x0, 0x80,0x6, +0x6d,0x33,0x7a,0x37,0x39,0x12,0xa2,0x0, 0x92,0x12,0x12,0x99,0x46,0xda,0x79,0xda, +0xd8,0x22,0x7e,0x73,0x28,0x84,0xbc,0x7f,0x22,0x90,0x62,0xf, 0xe4,0x93,0xa, 0x8b, +0x22,0xe4,0x93,0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x7e,0x8, 0x39,0x8, 0x12,0x68, +0x38,0x7e,0x8, 0x39,0x10,0x12,0x68,0x38,0x12,0x68,0x31,0x12,0x68,0x4d,0x2, 0x68, +0x11,0x7e,0x37,0x39,0x8, 0xbe,0x34,0x0, 0x0, 0x28,0x15,0x7e,0x73,0x39,0xf8,0xbe, +0x70,0x5, 0x50,0xc, 0x7e,0xb3,0x3, 0xef,0x70,0x6, 0x12,0x68,0x54,0x12,0x6a,0x2f, +0x22,0x7e,0x8, 0x2b,0xb7,0x2, 0x68,0x38,0xb, 0xa, 0x30,0xe5,0x65,0xa, 0x2b,0xbd, +0x32,0x28,0x4, 0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e,0x8, 0x39, +0xde,0x2, 0x68,0x38,0x6d,0x33,0x7a,0x37,0x39,0x98,0x22,0xca,0xf8,0x7e,0xa3,0x2a, +0x2, 0x7e,0xb3,0x2a,0x3, 0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0,0x1, 0x38,0x1c,0x7e, +0x47,0x28,0x86,0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x2f,0x80,0x4c, +0xff,0x68,0x17,0x7e,0x47,0x2b,0xb7,0x4d,0x44,0x78,0xf, 0x12,0x68,0x54,0x74,0x1, +0x7a,0xb3,0x39,0x9a,0x7a,0xb3,0x3, 0xc4,0x80,0x35,0x4c,0xaa,0x78,0x36,0xb4,0x1, +0x33,0x7e,0x37,0x2b,0xb7,0x7a,0x37,0x2f,0x82,0x7e,0xb3,0x2f,0x80,0xb4,0x3, 0x1f, +0x7e,0x37,0x2b,0xb7,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a,0xb3,0x2f,0x80, +0x7e,0x37,0x2f,0x98,0x7e,0x27,0x2f,0x9a,0x12,0x69,0x6c,0x21,0x65,0x80,0x0, 0x12, +0xc3,0xd7,0x21,0x65,0x7e,0xc7,0x29,0x8, 0x7e,0xd7,0x29,0xa, 0x4c,0xff,0x78,0x19, +0x70,0x57,0xbe,0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12,0xc3,0x72,0x12,0x69, +0x68,0x74,0x1, 0x7a,0xb3,0x2f,0x80,0x80,0x40,0xbe,0xf0,0x1, 0x78,0x2e,0x7e,0x27, +0x2f,0x88,0x9e,0x27,0x2f,0x90,0x7e,0x14,0x62,0x90,0x12,0x36,0xb3,0xbd,0x23,0x38, +0x13,0x7e,0x27,0x2f,0x96,0x9e,0x27,0x2f,0x8e,0x7e,0x14,0x62,0x92,0x12,0x36,0xb3, +0xbd,0x23,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2f,0x80,0x80,0x5, 0xbe,0xf0,0x3, 0x78, +0x8, 0x7a,0xc7,0x2f,0x98,0x7a,0xd7,0x2f,0x9a,0x7e,0xb3,0x2f,0x80,0x60,0x26,0x7d, +0x3c,0x7d,0x2d,0x7e,0x17,0x2b,0xbb,0x7e,0x7, 0x2b,0xbd,0x12,0x6a,0x17,0xa, 0x2b, +0x7e,0x73,0x2f,0x7f,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x69,0x68,0x7a,0xc7,0x2b, +0xbb,0x7a,0xd7,0x2b,0xbd,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42,0x7d,0x13, +0x7d,0x24,0x12,0xc3,0x49,0x7d,0x31,0x12,0x7e,0xad,0x2, 0x69,0x7d,0x7e,0x3, 0x2f, +0xa8,0xbe,0x0, 0xf0,0x50,0x2, 0x41,0x16,0x41,0xb, 0x6c,0x99,0x7e,0xb3,0x2f,0x7f, +0xbe,0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2f,0x7f,0x7e,0x1f,0x2b,0xbf,0x7a,0x1f, +0x1f,0x34,0x7e,0x80,0x1, 0x80,0x49,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2b,0xbf,0x49, +0x25,0x2b,0xc1,0x7e,0x17,0x1f,0x34,0x7e,0x7, 0x1f,0x36,0x12,0x6a,0x17,0x7c,0x1b, +0x7e,0x3, 0x2f,0x7f,0xbc,0x1, 0x38,0x26,0xb, 0x90,0x7e,0x70,0x4, 0xac,0x78,0x2e, +0x34,0x2b,0xbf,0x7e,0x14,0x1f,0x34,0x74,0x4, 0x12,0x1f,0x8c,0x7e,0x34,0x1f,0x34, +0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14,0x2b,0xbf,0x74,0x4, 0x12,0x1f,0x8c,0xb, 0x80, +0x7e,0x3, 0x2f,0xa8,0xbc,0x8, 0x38,0xaf,0xa, 0x59,0xb, 0x54,0x7c,0xb, 0x7a,0x3, +0x2f,0xa8,0x7e,0x3, 0x2f,0x7f,0xbe,0x0, 0x20,0x50,0xb, 0x7e,0x3, 0x2f,0xa8,0xbe, +0x0, 0xec,0x40,0x2, 0x21,0x8a,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x21,0x15, +0x7c,0xa7,0x12,0x6f,0xde,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22,0x74, +0x1, 0x7a,0xb3,0x3, 0xc4,0x22,0x12,0xcc,0x66,0x12,0x68,0x54,0x7a,0x37,0x39,0xf5, +0x12,0x47,0x9f,0x12,0x6a,0x5e,0x2, 0x6a,0x49,0x7e,0x70,0xa, 0x12,0x5c,0xf0,0x50, +0x3, 0x7e,0x70,0x19,0x7a,0x73,0x36,0x7d,0xe4,0x7a,0xb3,0x36,0x7e,0x22,0xe4,0x7a, +0xb3,0x33,0xea,0x7a,0xb3,0x33,0xe9,0x12,0x47,0xc7,0xb4,0x1, 0x4, 0x74,0x1, 0x80, +0x2, 0x74,0x3, 0x7a,0xb3,0x33,0xea,0x22,0xca,0x3b,0x12,0x7b,0xd1,0x50,0xfb,0x7e, +0xf3,0x2b,0xf, 0x7c,0xbf,0x12,0x6f,0x30,0x12,0xae,0xa2,0x7e,0xb3,0x2b,0x1f,0xf5, +0x28,0x7e,0xc3,0x2b,0x20,0x7e,0xb3,0x3, 0xc6,0xb4,0x1, 0xf, 0x12,0x6d,0x5e,0x7e, +0xb3,0x16,0x91,0x70,0x6, 0x12,0x6a,0x5e,0xc3,0x61,0x74,0x12,0x3f,0xb0,0x3e,0x34, +0xca,0x39,0x7e,0x18,0x6, 0xfc,0x7e,0x8, 0x4, 0x7e,0x12,0x20,0xbe,0x1b,0xfd,0x12, +0x3f,0xb0,0x3e,0x34,0xca,0x39,0x7e,0x18,0x7, 0x7a,0x7e,0x8, 0x4, 0x0, 0x12,0x20, +0xbe,0x1b,0xfd,0x7e,0xb3,0x3, 0xc6,0xb4,0x3, 0x7, 0x12,0xad,0xb8,0x7a,0x37,0x38, +0xf8,0x74,0x1, 0x7a,0xb3,0x16,0x90,0x12,0x47,0xa6,0x12,0x6f,0x3f,0x12,0x6b,0x77, +0xe4,0x12,0x13,0xde,0x12,0x6a,0x5e,0x7e,0x8, 0x4, 0x7e,0x7a,0xd, 0x29,0x7e,0x18, +0x6, 0x76,0x7e,0xb3,0x2b,0x72,0x12,0x6b,0xd1,0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29, +0x7e,0x18,0x5, 0xf8,0x7e,0xb3,0x25,0xf0,0x12,0x6b,0xd1,0x7e,0xd3,0x2b,0x1f,0x7e, +0xe3,0x2b,0x20,0xe5,0x28,0x7a,0xb3,0x2b,0x1f,0x7a,0xc3,0x2b,0x20,0x7e,0x34,0x8, +0xa, 0x7e,0x4, 0xd, 0xc8,0x7d,0x20,0x7d,0x10,0x12,0x46,0x2d,0x7a,0xd3,0x2b,0x1f, +0x7a,0xe3,0x2b,0x20,0x7c,0xbf,0x12,0x7c,0xb2,0x12,0x8e,0xbd,0x7e,0xb3,0x39,0xf8, +0x4, 0x7a,0xb3,0x39,0xf8,0x7e,0x73,0x39,0xf8,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64, +0x7a,0xb3,0x39,0xf8,0x7e,0xb3,0x16,0x90,0x60,0x9, 0x7e,0xb3,0x16,0x91,0x60,0x3, +0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e,0xa3,0x2f,0xa9,0xbe,0xa0,0xff,0x68,0x48, +0xbe,0xa3,0x33,0x46,0x68,0x42,0x74,0x5, 0xa4,0x12,0x6f,0x1d,0x12,0x6b,0xc9,0x12, +0x6f,0x14,0x12,0x6b,0xc9,0x12,0x6f,0xb, 0x12,0x47,0x7a,0x50,0x9, 0x7e,0xb3,0x2f, +0xa9,0x12,0xac,0xdf,0x80,0x6, 0x12,0x6b,0xc9,0x12,0x6f,0x2, 0x12,0x6c,0x29,0x12, +0x6e,0xfb,0x7e,0x73,0x2b,0x14,0xa, 0x37,0x7e,0xf, 0x33,0xd3,0x79,0x30,0x0, 0x1a, +0x7e,0x73,0x2f,0xa9,0x7a,0x73,0x33,0x46,0x22,0x7e,0xa3,0x2f,0xa9,0x74,0x5, 0xa4, +0x22,0xca,0x79,0x7f,0x51,0x7f,0x40,0x7e,0xa3,0x2a,0x74,0xa, 0x3a,0x7e,0xa3,0x2a, +0x73,0xa, 0x7a,0x2d,0x73,0x7e,0xd, 0x29,0x7c,0x7f,0x12,0x7b,0x74,0xa, 0x3f,0x3e, +0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f,0x4, 0x12,0x20,0xbe,0x1b,0xfd,0x7e,0xb3,0x2b, +0x1, 0xb4,0x1, 0x22,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d, +0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d,0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30, +0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda,0x79,0x22,0x12,0x6c,0x31,0x7a,0x37,0x2b,0x1b, +0x22,0x7e,0x23,0x2b,0xf, 0x7e,0x33,0x38,0xe2,0x7e,0x34,0x60,0xd6,0x7e,0x24,0x0, +0xff,0xb, 0x1a,0x0, 0xac,0x23,0x2d,0x10,0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14, +0x0, 0xa, 0x7e,0x63,0x2b,0x10,0xbe,0x14,0xf, 0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c, +0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x21,0xbe,0x14,0x3, 0x84,0x40,0x16,0x90, +0x61,0x1b,0xe4,0x93,0x7c,0x7b,0xbe,0x70,0x1, 0x28,0x4, 0x74,0x1, 0x80,0xb, 0x7a, +0x73,0x2b,0x10,0x80,0x9, 0x90,0x61,0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x7e,0x73, +0x2b,0x10,0xbc,0x76,0x68,0x2, 0xd2,0xe, 0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32, +0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e,0x1f,0x33,0xcb,0x69,0x51, +0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, +0x2d,0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x12,0x6f,0xf5,0x2, 0x1f,0x58,0x7a,0xb3, +0x2b,0xf, 0x12,0x6c,0x29,0x30,0xe, 0xc, 0xc2,0xe, 0x12,0x6f,0x6e,0x30,0x0, 0x4, +0xe4,0x12,0xa, 0x66,0x30,0x0, 0x9, 0x12,0x6f,0xfe,0x12,0x6d,0xa8,0x2, 0x6f,0x7e, +0x22,0x7e,0xb, 0x70,0x7a,0x73,0x2b,0xf, 0x29,0x70,0x0, 0x4, 0x7a,0x73,0x2b,0x62, +0x29,0x70,0x0, 0x1, 0x7a,0x73,0x2b,0x14,0x29,0x70,0x0, 0x3, 0x7a,0x73,0x2b,0x20, +0x12,0x6c,0x29,0x12,0x6e,0xfb,0xd2,0x0, 0xc2,0x1, 0x2, 0x40,0xf1,0xca,0xf8,0x7c, +0xfb,0x74,0x5, 0xac,0xbf,0x12,0x6f,0x1d,0x12,0x6f,0x14,0x12,0x6f,0x2, 0x12,0x6f, +0xb, 0x7a,0xf3,0x2f,0xa9,0x7c,0xbf,0x12,0xac,0xdf,0x12,0x6c,0x29,0x74,0x5, 0xac, +0xbf,0x9, 0xb5,0x26,0x37,0x12,0x6f,0x53,0x12,0x6d,0xa8,0x12,0x23,0x22,0xe4,0x7a, +0xb3,0x16,0x91,0x7a,0xb3,0x38,0x50,0x7a,0xb3,0x16,0x92,0xda,0xf8,0x22,0x7e,0xb3, +0x37,0xda,0x60,0x6, 0x14,0x7a,0xb3,0x37,0xda,0x22,0x12,0x6f,0x9b,0x90,0x61,0xcb, +0xe4,0x93,0xbe,0xb0,0x4, 0x28,0x3, 0x12,0x6d,0xa8,0x7e,0xb3,0x3, 0xaa,0x70,0xe, +0x7e,0xb3,0x3a,0x4, 0xb4,0x1, 0x7, 0xe4,0x12,0x6d,0x1d,0x12,0xcc,0xf7,0x12,0x37, +0x78,0x12,0xb1,0xeb,0x7e,0xa3,0x3, 0xaa,0x7a,0xa3,0x3a,0x4, 0xbe,0xb0,0xff,0x68, +0x3, 0x2, 0x6d,0x1d,0x22,0x12,0x6f,0x26,0x7e,0xb3,0x2b,0xf, 0xca,0x3b,0x7c,0xeb, +0x6c,0xff,0x7e,0x34,0x60,0xd6,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xc0,0x7e,0x73,0x38, +0xe2,0xa, 0xb7,0x7e,0xb3,0x2b,0x10,0xf5,0x35,0x12,0x6f,0xed,0xbe,0xd0,0x4, 0x38, +0x5, 0xe4,0x7a,0xb3,0x37,0xe6,0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d,0xac,0x75,0x34, +0x0, 0x7e,0xa3,0x37,0xe6,0xbc,0xad,0x40,0x2, 0x80,0x19,0xbe,0xa0,0x0, 0x28,0x19, +0x74,0x5, 0xa4,0x9, 0x75,0x26,0x33,0xbc,0x7e,0x78,0xe, 0x7c,0xbd,0x14,0xbe,0xb3, +0x37,0xe6,0x78,0x5, 0xe4,0x7a,0xb3,0x37,0xe6,0x7e,0xc3,0x37,0xe6,0x80,0x41,0x7e, +0xb3,0x37,0xe6,0x4, 0x7a,0xb3,0x37,0xe6,0x7e,0x90,0x5, 0xac,0x9c,0x9, 0xa4,0x26, +0x33,0xbc,0xae,0x68,0x29,0xe5,0x34,0xa, 0xdb,0x19,0xcd,0x37,0xea,0xa, 0x9a,0xad, +0x9b,0x2d,0x9c,0x7e,0xa1,0x34,0x7c,0xba,0x4, 0xf5,0x34,0x7c,0xba,0x7d,0x39,0x7d, +0x2a,0x7e,0x31,0x35,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x6, 0xb, 0xc0, +0xbc,0xdc,0x38,0xbb,0x7a,0xf3,0x37,0xe7,0xda,0x3b,0x22,0xca,0xf8,0x6c,0xff,0x80, +0x34,0x7e,0x73,0x2f,0xa9,0xbc,0x7f,0x68,0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x6e, +0xd7,0xca,0x39,0x7e,0x30,0x38,0xac,0x3f,0x12,0x6e,0xf0,0x12,0x20,0xbe,0x1b,0xfd, +0x7e,0x34,0x0, 0x8c,0xca,0x39,0x7e,0x30,0x8c,0xac,0x3f,0x12,0x6e,0xe5,0x12,0x20, +0xbe,0x1b,0xfd,0xb, 0xf0,0x90,0x61,0xcb,0xe4,0x93,0xbc,0xbf,0x38,0xc3,0x7e,0x23, +0x2f,0xa9,0x7e,0x30,0x5, 0xac,0x23,0x12,0x6e,0xd7,0xca,0x39,0x7e,0x23,0x2f,0xa9, +0x7e,0x30,0x38,0xac,0x23,0x12,0x6e,0xf0,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x34,0x0, +0x8c,0xca,0x39,0x7e,0x23,0x2f,0xa9,0x7e,0x30,0x8c,0xac,0x23,0x12,0x6e,0xe5,0x12, +0x20,0xbe,0x1b,0xfd,0xda,0xf8,0x22,0x2e,0x14,0x26,0x33,0x6d,0x0, 0x12,0x6c,0xf1, +0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x30,0x8a,0x6d,0x0, 0x7e,0x18,0x32,0xba,0x22, +0x2e,0x14,0x2f,0xaa,0x6d,0x0, 0x7e,0x18,0x34,0x0, 0x22,0x7e,0x8, 0x2a,0x6d,0x2, +0x3, 0x8b,0x9, 0x75,0x26,0x35,0x7a,0x73,0x2b,0x1f,0x22,0x9, 0x75,0x26,0x36,0x7a, +0x73,0x2b,0x20,0x22,0x9, 0x75,0x26,0x34,0x7a,0x73,0x2b,0x14,0x22,0x9, 0x75,0x26, +0x33,0x7a,0x73,0x2b,0xf, 0x22,0x12,0x6f,0xfe,0x74,0x1, 0x7a,0xb3,0x37,0xda,0x22, +0x7c,0xab,0x12,0x6f,0xe5,0xd2,0x1a,0x7c,0xba,0x12,0x7c,0xb2,0xc2,0x1a,0x22,0x12, +0xad,0xb8,0x7e,0x14,0x62,0xd, 0x12,0x47,0xe0,0xbd,0x32,0x28,0x3, 0xd2,0x16,0x22, +0xc2,0x16,0x22,0x7e,0xa3,0x2b,0x62,0xbc,0xab,0x68,0x6, 0x7a,0xb3,0x2b,0x62,0xd2, +0xe, 0x30,0xe, 0x9, 0xc2,0xe, 0x12,0x6f,0x6e,0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, +0x2a,0x6d,0x12,0x3, 0x8b,0x7e,0x8, 0x2a,0x6d,0x74,0x3, 0x2, 0x11,0x7a,0x12,0x6f, +0x9b,0x6d,0x33,0x7a,0x37,0x38,0x51,0x6c,0xaa,0x80,0x5, 0x12,0xcc,0x71,0xb, 0xa0, +0x12,0x6f,0xd6,0x38,0xf6,0xe4,0x7a,0xb3,0x37,0xe6,0x22,0x7e,0x37,0x33,0xdd,0x12, +0x25,0x5a,0x7a,0x37,0x38,0x51,0x6c,0xaa,0x80,0x23,0x12,0x6f,0xd6,0x28,0x26,0xa, +0x4a,0x9, 0x64,0x37,0xea,0xbc,0x6b,0x50,0x12,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42, +0x33,0xd7,0x7e,0x70,0xc, 0xac,0x67,0x59,0x43,0x37,0xf4,0xb, 0xa0,0x7e,0xb3,0x37, +0xe7,0xbc,0xba,0x38,0xd5,0x22,0x90,0x61,0xcb,0xe4,0x93,0xbc,0xba,0x22,0x7d,0x31, +0x9d,0x30,0x2, 0x21,0x15,0xa9,0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x90,0x61,0xcb, +0xe4,0x93,0x7c,0xdb,0x22,0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x22,0x7e,0x8, +0x37,0xee,0x7e,0x34,0x0, 0x60,0xe4,0x12,0x20,0xe3,0x6c,0xaa,0x7e,0x44,0xff,0xff, +0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x37,0xf0,0x59,0x43,0x37,0xf8,0xb, 0xa0,0xbe, +0xa0,0x8, 0x40,0xe8,0x7e,0x8, 0x37,0xdc,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x20,0xe3, +0x7e,0x73,0x28,0x93,0x7a,0x73,0x28,0x94,0x7e,0x73,0x2a,0x2, 0x7a,0x73,0x2a,0x3, +0xe4,0x7a,0xb3,0x2a,0x6, 0x22,0x7e,0x37,0x34,0x38,0xb, 0x34,0x7a,0x37,0x34,0x38, +0x7e,0x37,0x34,0x3a,0xbe,0x37,0x34,0x38,0x28,0x3, 0x2, 0x70,0x61,0x22,0x2, 0x70, +0x46,0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca, +0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12, +0x70,0x5e,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b, +0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x34,0x61, +0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b,0x70,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x34, +0x2a,0xe, 0x7a,0x37,0x2b,0x76,0xe4,0x7a,0xb3,0x2b,0x74,0x7a,0xb3,0x2b,0x75,0x7e, +0x34,0x0, 0x4, 0xca,0x39,0x12,0x79,0x13,0x7e,0x8, 0x25,0xee,0x12,0x20,0xbe,0x1b, +0xfd,0x7e,0x34,0x2b,0x78,0x7a,0x37,0x25,0xf4,0xe4,0x7a,0xb3,0x25,0xf2,0x74,0x1, +0x7a,0xb3,0x25,0xf3,0x22,0xca,0xd8,0xca,0x79,0x90,0x60,0x50,0xe4,0x93,0x7c,0xdb, +0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e,0x73,0x2a,0x74,0xbc,0x7e,0x28,0x4, 0x7c, +0xf7,0x80,0x2, 0x7c,0xfe,0x7a,0xd3,0x2a,0x6d,0x7a,0xe3,0x2a,0x6e,0x7a,0xd3,0x2a, +0x71,0x7a,0xe3,0x2a,0x72,0x7a,0xd3,0x2a,0x73,0x7a,0xe3,0x2a,0x74,0x90,0x60,0xa8, +0xe4,0x93,0x7c,0xab,0x7a,0xa3,0x2a,0x77,0x90,0x60,0xa9,0xe4,0x93,0xa, 0x2b,0xa, +0x3d,0x9d,0x32,0x7c,0xb7,0x7a,0xb3,0x2a,0x6f,0xa, 0x2a,0xa, 0x3e,0x9d,0x32,0x7a, +0x73,0x2a,0x70,0x90,0x60,0x91,0xe4,0x93,0x7a,0xb3,0x2a,0x78,0x90,0x60,0x94,0xe4, +0x93,0x7a,0xb3,0x2a,0x79,0xa, 0x3d,0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, +0xff,0x7e,0x8, 0x2a,0x7a,0x12,0x20,0xbe,0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34, +0x60,0x75,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x9d,0x12,0x20,0xbe,0x1b,0xfd,0x7e, +0x34,0x0, 0x23,0xca,0x39,0x7e,0x34,0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2b, +0x21,0x12,0x20,0xbe,0x1b,0xfd,0x12,0x72,0xd0,0x12,0x79,0x1f,0x90,0x60,0xaa,0xe4, +0x93,0x70,0x8, 0x7a,0xd3,0x2a,0x75,0x7a,0xe3,0x2a,0x76,0x12,0x70,0x97,0x74,0x1, +0x12,0x38,0x1d,0xe4,0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x2, 0x12,0x74,0x2f,0x7a, +0x37,0x2b,0xd, 0x74,0x3, 0x7a,0xb3,0x2b,0x3, 0xe4,0x7a,0xb3,0x2b,0x4, 0x74,0x2, +0x7a,0xb3,0x2b,0x5, 0x7e,0x34,0x61,0x5b,0x12,0x23,0xbc,0x7a,0x37,0x2b,0x7, 0x74, +0x4, 0x7a,0xb3,0x2b,0x6, 0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x2b,0x9, 0x7e,0x34,0x20, +0x5f,0x7a,0x37,0x2b,0xb, 0x90,0x61,0x1a,0xe4,0x93,0x7a,0xb3,0x2b,0x62,0x90,0x61, +0x1b,0xe4,0x93,0x7a,0xb3,0x2b,0x10,0x90,0x61,0x1c,0xe4,0x93,0x7a,0xb3,0x2b,0x11, +0x74,0x4, 0x7a,0xb3,0x2b,0x13,0x90,0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x2b,0xf, 0x12, +0x6c,0x29,0xe4,0x7a,0xb3,0x2b,0x1d,0x7a,0xb3,0x2b,0x1e,0x7e,0x34,0x61,0x22,0x12, +0x23,0xbc,0x7a,0x37,0x2b,0x19,0x90,0x60,0xd3,0x93,0x7a,0xb3,0x2b,0x12,0x90,0x61, +0x24,0xe4,0x93,0x7a,0xb3,0x2b,0x20,0x90,0x61,0x19,0xe4,0x93,0x7a,0xb3,0x2b,0x1f, +0x7e,0x34,0x61,0x1e,0x12,0x23,0xbc,0x7a,0x37,0x2b,0x15,0x7e,0x34,0x61,0x20,0x12, +0x23,0xbc,0x7a,0x37,0x2b,0x17,0x90,0x61,0x1d,0xe4,0x93,0x7a,0xb3,0x2b,0x14,0x7e, +0x34,0x0, 0x30,0x7a,0x37,0x2b,0x6a,0x74,0x1, 0x7a,0xb3,0x2b,0x67,0x7e,0x34,0x0, +0x5, 0x7a,0x37,0x2b,0x68,0xe4,0x7a,0xb3,0x2b,0x66,0x7e,0x34,0x4, 0x6d,0x7a,0x37, +0x2b,0x6c,0x74,0x1, 0x7a,0xb3,0x2b,0x63,0x74,0x2, 0x7a,0xb3,0x2b,0x64,0xe4,0x7a, +0xb3,0x2b,0x65,0x74,0x1, 0x7a,0xb3,0x2b,0x60,0xe4,0x7a,0xb3,0x2b,0x61,0x7e,0x34, +0x20,0x60,0x7a,0x37,0x2b,0x6e,0xa, 0x3e,0xca,0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24, +0x0, 0xff,0x7e,0x8, 0x2b,0x44,0x12,0x20,0xbe,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22, +0x12,0xcd,0x3a,0x12,0x73,0x32,0x90,0x60,0x50,0xe4,0x93,0xa, 0x3b,0x7d,0x13,0x2e, +0x14,0x2a,0x7a,0x6d,0x0, 0x9, 0xb3,0x2a,0x79,0x12,0x73,0x19,0xa, 0x3b,0x7d,0x13, +0x2e,0x14,0x2b,0x21,0x6d,0x0, 0x9, 0xb3,0x2b,0x20,0x12,0x73,0x19,0xa, 0x1b,0x2e, +0x14,0x2a,0x7c,0x12,0x73,0x26,0xe5,0x25,0x12,0x73,0x1d,0xa, 0x1b,0x2e,0x14,0x2b, +0x23,0x12,0x73,0x26,0xe5,0x24,0x2, 0x20,0xe3,0x7e,0x34,0x0, 0x2, 0x12,0x20,0xe3, +0x90,0x60,0x50,0xe4,0x93,0x22,0x6d,0x0, 0x90,0x60,0x91,0xe4,0x93,0xa, 0x3b,0x1b, +0x35,0x22,0x6c,0xaa,0x6c,0x99,0x80,0xc, 0xa, 0xf9,0x9, 0xbf,0x2a,0x7a,0xbc,0xba, +0x68,0x7, 0xb, 0x90,0x12,0x73,0x5e,0x38,0xef,0x12,0x73,0x5e,0x68,0x7, 0xb, 0xa0, +0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, 0xa0,0x74,0x6e,0x7a,0x1b,0xb0,0x22,0x90,0x60, +0x50,0xe4,0x93,0xbc,0xb9,0x22,0x12,0x77,0xeb,0x12,0x70,0xe5,0x12,0x0, 0x42,0x12, +0x77,0xbe,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xf8,0x7e,0xf, 0x6, 0xf8,0x7e,0x1f, +0x6, 0xf4,0x12,0x79,0x8b,0x7e,0x18,0x8, 0xa, 0x7a,0x1f,0x13,0x86,0x7e,0x18,0xd, +0xc8,0x7a,0x1f,0x13,0x8a,0x7e,0xf, 0x13,0x8a,0x7e,0x1f,0x13,0x86,0x12,0x79,0x68, +0x12,0x79,0x1c,0x12,0x25,0x63,0x12,0x73,0xe5,0x12,0x73,0xbd,0x2, 0x73,0xaf,0xe4, +0x7a,0xb3,0x33,0xe8,0x7a,0xb3,0x33,0xe9,0x7a,0xb3,0x33,0xea,0x22,0x12,0x74,0x23, +0x7e,0x24,0x0, 0x3, 0xad,0x32,0x7e,0x8, 0x28,0xae,0x74,0xff,0x12,0x20,0xe3,0x12, +0xa6,0x17,0x7e,0x8, 0x29,0xbc,0x12,0x56,0xf8,0x7e,0x8, 0x2a,0x2, 0x7e,0x34,0x0, +0xb, 0xe4,0x2, 0x20,0xe3,0x7e,0x8, 0x26,0x5b,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x20, +0xe3,0x90,0x60,0x9c,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0x8c,0x74,0xff,0x12, +0x20,0xe3,0x90,0x60,0x9c,0xe4,0x93,0xa, 0x3b,0x3e,0x34,0x7e,0x8, 0x26,0xb4,0x74, +0xff,0x12,0x20,0xe3,0x90,0x60,0x9a,0x12,0x74,0x26,0x7e,0x8, 0x27,0x76,0x74,0xff, +0x2, 0x20,0xe3,0x90,0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x9, 0xac,0x7b,0x22,0x6d, +0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2,0x2a,0xdc,0x54,0x1, 0x78,0x5, 0x4e, +0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x2a,0x74,0xbc,0x5a,0x38, +0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2,0x2a,0xb9,0xbe,0xb0,0xd, 0x38,0x5, +0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e, +0x60,0x50,0xb, 0xa0,0x12,0x74,0x7a,0x38,0xdc,0x22,0x7e,0xb3,0x2a,0x73,0xbc,0xba, +0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab,0x7d,0x8b,0x6d,0x22,0x7d,0x32,0x7d, +0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, 0xfc,0x7e,0x8, 0x5, 0x7a,0xe4,0x7a, +0xb3,0x8, 0x8, 0x7a,0xb3,0x8, 0x9, 0x7a,0xb3,0x26,0xf6,0x7a,0xb3,0x26,0xf8,0x7a, +0xb3,0x26,0xf7,0x7a,0xb3,0x26,0xf9,0x6c,0xaa,0x80,0x5f,0x12,0x75,0xf0,0xb, 0x6a, +0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3,0x8, 0x2, 0x7d,0x3c,0x2d,0x71,0x7d, +0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d,0x9d,0x7e,0x67,0x2a,0x53,0x7e,0x74, +0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, 0x24,0x12,0x75,0xdd,0xb, 0x3a,0xd0, +0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x26,0xf7,0x4, 0x7a,0xb3,0x26,0xf7,0x80,0x19,0x12, +0x75,0xe6,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff,0xb, 0xd4,0xbd,0xcd,0x58,0x9, 0x7e, +0xb3,0x26,0xf9,0x4, 0x7a,0xb3,0x26,0xf9,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xbc,0xba, +0x38,0x99,0x7a,0xa7,0x7, 0xfe,0x7a,0x37,0x8, 0x2, 0xe5,0x24,0x7a,0xb3,0x8, 0x9, +0x7a,0x97,0x8, 0x6, 0x12,0x75,0xd5,0x2d,0xf5,0x6c,0xaa,0x80,0x50,0x12,0x75,0xf0, +0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d,0xbd,0xd2,0x8, 0x2, 0x7d,0x2d,0x7e, +0x67,0x2a,0x51,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xd7,0x8, 0x2, 0xb, 0x90,0x12, +0x75,0xdd,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, 0x7e,0xb3,0x26,0xf6,0x4, 0x7a,0xb3, +0x26,0xf6,0x80,0x17,0x12,0x75,0xe6,0xb, 0x3a,0xd0,0x6d,0x99,0x9d,0x9c,0xbd,0xd9, +0x58,0x9, 0x7e,0xb3,0x26,0xf8,0x4, 0x7a,0xb3,0x26,0xf8,0xb, 0xa0,0x12,0x74,0x7a, +0x38,0xab,0x7a,0x87,0x7, 0xfc,0x7a,0x27,0x8, 0x0, 0x7a,0x93,0x8, 0x8, 0x12,0x75, +0xd5,0x2d,0x15,0x6c,0xaa,0x80,0xe, 0x12,0xc7,0xe5,0xb, 0x7a,0x90,0xbd,0x9b,0x58, +0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x74,0x7a,0x38,0xed,0x7a,0xb7,0x8, 0x4, 0xbd,0x8a, +0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0xf8,0xbd,0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37, +0x7, 0xfa,0xda,0x3b,0x22,0x7e,0xa3,0x2a,0x74,0x74,0x2, 0xa4,0x22,0x7e,0x74,0x62, +0x16,0x7e,0x64,0x0, 0xff,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x2d,0x7f,0x7d,0x6e,0x22, +0x7e,0xf0,0x2, 0xac,0xfa,0x7f,0x67,0x2d,0xd7,0x22,0xca,0x3b,0x7f,0x31,0x7a,0xd, +0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24,0x7f,0x13,0x12,0x92,0x55,0x7e, +0x35,0x28,0x7a,0x35,0x2a,0x12,0x75,0xd5,0x7e,0xd, 0x24,0x2d,0x15,0x7f,0x13,0x2d, +0x35,0x12,0x93,0x17,0xda,0x3b,0x22,0x7e,0x37,0x2a,0x4f,0x1e,0x34,0x7a,0x35,0x28, +0x7e,0x8, 0x4, 0xfc,0x7e,0x18,0x4, 0x0, 0x12,0x75,0xfa,0x7e,0x37,0x28,0x99,0xe, +0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x7a,0x7e,0x18,0x4, 0x7e,0x12,0x75,0xfa,0x12, +0x76,0x69,0x12,0x86,0x48,0x2, 0x76,0x58,0xe4,0x7a,0xb3,0x3, 0xff,0x7e,0xb3,0x28, +0xa8,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xff,0x22,0xca,0x3b,0x7e,0xf3,0x2a,0x6e,0x7e, +0xe3,0x2a,0x6f,0x7e,0xd3,0x2a,0x70,0x6c,0xcc,0x80,0xe, 0x7c,0x7c,0xac,0x7f,0x12, +0x59,0x5c,0x7c,0xbd,0x12,0xa9,0xc1,0xb, 0xc0,0xbc,0xec,0x38,0xee,0xda,0x3b,0x22, +0xe4,0x7a,0xb3,0x28,0x93,0x12,0xc1,0x5, 0x7e,0xb3,0x16,0x91,0xb4,0x1, 0x8, 0x7e, +0x73,0x28,0x84,0x7a,0x73,0x28,0x92,0x7e,0x18,0x4, 0xfc,0x7a,0x1f,0x6, 0xf8,0x12, +0x77,0xbe,0x12,0x76,0xd8,0x12,0x74,0x81,0x7e,0xb3,0x16,0x90,0xb4,0x1, 0x18,0x7e, +0x73,0x26,0x83,0x7a,0x73,0x26,0xf3,0x7e,0x73,0x26,0x85,0x7a,0x73,0x26,0xf5,0x7e, +0x73,0x26,0x84,0x7a,0x73,0x26,0xf4,0x22,0x7e,0x8, 0x26,0x86,0x7e,0x34,0x0, 0x3, +0xe4,0x12,0x20,0xe3,0x7e,0x8, 0x26,0x89,0x7e,0x34,0x0, 0x3, 0x12,0x20,0xe3,0x7a, +0xb3,0x26,0x83,0x7a,0xb3,0x26,0x84,0x7a,0xb3,0x26,0x85,0x7a,0xb3,0x26,0xf0,0x7a, +0xb3,0x26,0xf1,0x7a,0xb3,0x26,0xf2,0x7e,0x18,0x26,0x6f,0x12,0x77,0xdb,0x6c,0x55, +0x12,0xc2,0x44,0x7a,0xb3,0x26,0x85,0x7e,0x18,0x26,0x5b,0x12,0xcc,0x36,0x6c,0x55, +0x12,0xc2,0x44,0x7a,0xb3,0x26,0x84,0x6c,0x77,0x80,0x14,0x12,0x77,0xc7,0x60,0x5, +0x3e,0x24,0x14,0x78,0xfb,0x12,0x77,0x9e,0x2e,0x24,0x26,0x86,0x12,0x77,0xd0,0x7e, +0x63,0x26,0x84,0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0x77,0xc7,0x60,0x5, +0x3e,0x24,0x14,0x78,0xfb,0x12,0x77,0x9e,0x2e,0x24,0x26,0x89,0x12,0x77,0xd0,0x7e, +0xa3,0x26,0x85,0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x26,0x84,0xa4,0x7a,0xb3,0x26,0x83, +0x7e,0x18,0x26,0xe6,0x12,0x77,0xdb,0x7e,0x50,0x1, 0x12,0xc2,0x44,0x7a,0xb3,0x26, +0xf2,0x7e,0x18,0x26,0xdc,0x12,0xcc,0x36,0x7e,0x50,0x1, 0x12,0xc2,0x44,0x7c,0xab, +0x7a,0xa3,0x26,0xf1,0x7e,0xb3,0x26,0xf2,0xa4,0x7a,0xb3,0x26,0xf0,0x22,0x7c,0xa5, +0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b,0x22,0x12,0x77,0xaf,0x2, 0x76,0x90,0x12, +0x25,0xe6,0x2, 0x77,0xb5,0x12,0x4f,0xfc,0x50,0x3, 0x2, 0x26,0xe, 0x22,0x7e,0x18, +0x5, 0xf8,0x7a,0x1f,0x6, 0xf4,0x22,0x7c,0xb7,0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x22, +0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70,0x22,0x7a,0x1d,0x24,0x7e,0xf, +0x6, 0xf8,0x7e,0xb3,0x2a,0x6e,0x7e,0x37,0x2a,0x53,0x22,0xe4,0x7a,0xb3,0x38,0xb1, +0x7a,0xb3,0x38,0xb2,0x90,0x60,0x50,0x93,0x7a,0xb3,0x38,0xb3,0x90,0x60,0x51,0xe4, +0x93,0x7a,0xb3,0x38,0xb4,0xe4,0x7a,0xb3,0x38,0xb5,0x90,0x60,0x99,0x93,0x7a,0xb3, +0x38,0xb6,0xe4,0x7a,0xb3,0x38,0xb7,0x7a,0xb3,0x38,0xb8,0x90,0x61,0xca,0x93,0x7a, +0xb3,0x38,0xba,0x7e,0x34,0x61,0x4f,0x12,0x23,0xbc,0x1e,0x34,0x1e,0x34,0x7a,0x73, +0x38,0xbe,0x7e,0x34,0x61,0x55,0x12,0x23,0xbc,0x1e,0x34,0x1e,0x34,0x7a,0x73,0x38, +0xbf,0x74,0x64,0x7a,0xb3,0x38,0xd0,0x90,0x61,0x18,0xe4,0x93,0x7a,0xb3,0x38,0xd1, +0x90,0x61,0x17,0xe4,0x93,0x7a,0xb3,0x38,0xbd,0x90,0x61,0x19,0xe4,0x93,0x7a,0xb3, +0x38,0xd3,0x90,0x61,0x24,0xe4,0x93,0x7a,0xb3,0x38,0xd2,0x90,0x61,0x1d,0xe4,0x93, +0x7a,0xb3,0x38,0xd4,0x90,0x61,0x25,0xe4,0x93,0x7a,0xb3,0x38,0xcf,0xe4,0x7a,0xb3, +0x38,0xca,0x74,0xfa,0x7a,0xb3,0x38,0xc8,0x74,0x1e,0x7a,0xb3,0x38,0xc9,0x74,0x1, +0x7a,0xb3,0x38,0xc7,0x74,0xc, 0x7a,0xb3,0x38,0xc6,0x74,0x1, 0x7a,0xb3,0x38,0xcb, +0xe4,0x7a,0xb3,0x38,0xcc,0x7a,0xb3,0x38,0xcd,0x7e,0x8, 0x38,0xd5,0x7e,0x34,0x0, +0x2c,0x12,0x20,0xe3,0x7e,0x34,0x60,0xd6,0x12,0x23,0xbc,0xa, 0x36,0x7a,0x73,0x38, +0xe0,0x7e,0x34,0x60,0xd6,0x12,0x23,0xbc,0x7a,0x73,0x38,0xe1,0x90,0x60,0xd4,0x93, +0x7a,0xb3,0x38,0xe2,0x90,0x60,0xd5,0xe4,0x93,0x7a,0xb3,0x38,0xe3,0x7e,0x34,0x0, +0x4, 0xca,0x39,0x12,0x79,0x13,0x7e,0x8, 0x38,0xf1,0x12,0x20,0xbe,0x1b,0xfd,0x74, +0x5, 0x7a,0xb3,0x38,0xfe,0x74,0x1, 0x7a,0xb3,0x38,0xf5,0x7e,0x34,0x0, 0x28,0xca, +0x39,0x7e,0x34,0x61,0xdb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x26,0x33,0x12,0x20,0xbe, +0x1b,0xfd,0x22,0x7e,0x34,0x61,0x29,0x7e,0x24,0x0, 0xff,0x22,0x2, 0x23,0xc4,0xca, +0xf8,0x7e,0x73,0x2a,0x78,0xa, 0x47,0x7e,0x73,0x2a,0x71,0xa, 0x57,0x2d,0x54,0x7e, +0xa3,0x2a,0x73,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x2a,0x72,0x7e,0xa3,0x2a, +0x74,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xb9,0x7e,0x18, +0x2a,0x7a,0x12,0xd, 0xd9,0x75,0x25,0x15,0x7e,0x8, 0x2a,0xdc,0x7e,0x18,0x2a,0x9d, +0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7f,0x60,0x7e,0xa3,0x2a,0x6d,0x7e,0xb3, +0x2a,0x6e,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d,0x3f,0xe4,0x12,0x20,0xe3,0x7f, +0x6, 0x7d,0x3f,0x12,0x20,0xe3,0x7a,0xb3,0x16,0x91,0x22,0x7f,0x70,0x7e,0x33,0x2a, +0x74,0xa, 0x43,0x7e,0x33,0x2a,0x73,0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4, +0x7a,0xb3,0x16,0x90,0x7f,0x1, 0xa, 0x3a,0x12,0x20,0xe3,0x7f,0x7, 0xa, 0x3a,0x2, +0x20,0xe3,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40,0x7f,0x15,0x12,0x79, +0x8b,0x12,0x7b,0xae,0x7e,0xe0,0x1, 0x12,0x3f,0xce,0x30,0x1c,0xfd,0x74,0x2, 0x12, +0x0, 0x1e,0x7f,0x4, 0x12,0xcc,0x7f,0x12,0x0, 0x1e,0x6c,0xdd,0x80,0x18,0x74,0x2, +0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x5, 0x2d, +0x15,0x12,0x7b,0xbe,0xb, 0xd0,0x7e,0x73,0x2a,0x74,0xa, 0x7, 0x7e,0x63,0x2a,0x73, +0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4,0x1b,0xe0,0x78,0xb9,0x7f,0x5, +0x7c,0xbf,0x2e,0x73,0x2a,0x73,0x12,0x7b,0x74,0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3, +0x2b,0x2, 0x70,0x41,0x12,0x7b,0xd1,0x50,0xfb,0xe4,0x6c,0x77,0x6c,0x66,0x12,0x7a, +0x66,0x7e,0x8, 0x6, 0xfc,0x7e,0x1f,0x6, 0xf4,0x7e,0xb3,0x2b,0x72,0x12,0x79,0xb2, +0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x7a,0x66,0x7e,0x8, 0x7, 0x7a,0x7e, +0x1f,0x6, 0xf4,0x7e,0xb3,0x25,0xf0,0x12,0x79,0xb2,0x74,0x2, 0x7a,0xb3,0x2b,0x2, +0xe4,0x7a,0xb3,0x16,0x90,0x22,0x7c,0x96,0x7c,0xa7,0x12,0x38,0x1d,0x7c,0xba,0x12, +0x13,0xc7,0x74,0xa, 0x12,0x7a,0x7f,0x7c,0xb9,0x12,0x0, 0x1e,0x2, 0x3e,0xd2,0x7c, +0xab,0x80,0xe, 0x7e,0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, +0xf7,0x7c,0x6a,0x1b,0xa0,0xa5,0xbe,0x0, 0xea,0x22,0x6c,0xaa,0x80,0x22,0xa, 0x3a, +0x9, 0x73,0x2a,0xdc,0x2e,0x34,0x20,0x78,0x12,0x7c,0x87,0x7c,0x7b,0xa, 0x47,0x7e, +0x50,0x2, 0xac,0x5a,0x7e,0xf, 0x33,0xcb,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, 0xa0, +0x7e,0x63,0x2a,0x74,0xbc,0x6a,0x38,0xd6,0x22,0x7e,0xd7,0x2b,0xd, 0xbe,0xb0,0x1, +0x28,0x2, 0xe4,0x22,0x12,0x7a,0xf9,0x7e,0x8, 0x2a,0x6d,0x12,0x5, 0xb4,0x7a,0xd7, +0x2b,0xd, 0x7e,0x73,0x2a,0xfa,0xa, 0x37,0x3e,0x34,0x3e,0x34,0xe4,0x7e,0x50,0x1, +0x12,0x13,0x1, 0x12,0x3f,0xce,0x74,0x1, 0x22,0x7c,0xab,0x12,0x3a,0x87,0x7c,0xba, +0x12,0x13,0xc7,0x12,0x0, 0x1e,0x2, 0x7b,0x9, 0x7e,0x33,0x2a,0xf8,0x7e,0x23,0x2a, +0xf9,0xa, 0x32,0x6d,0x22,0xa, 0x13,0x6d,0x0, 0x2f,0x1, 0x74,0x4, 0x2f,0x0, 0x14, +0x78,0xfb,0x2e,0x8, 0x0, 0x2a,0x12,0x6f,0xf5,0x12,0x1f,0x58,0x12,0x7b,0xc7,0x28, +0x3, 0x7e,0x70,0x7, 0x12,0x2d,0x1a,0x2, 0x45,0x93,0xca,0xf8,0xa2,0xaf,0xe4,0x33, +0x7c,0xfb,0xd2,0x0, 0x12,0x7b,0xb5,0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75, +0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0, +0xcd,0x74,0x41,0x12,0x7a,0x7f,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92, +0xaf,0xda,0xf8,0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f,0x70,0x12,0xbf,0x9e,0x7c, +0xeb,0x6c,0xdd,0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x30, +0x6d,0x22,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e,0x6d,0x0, 0x12,0x1f,0x7, +0x1b,0x6a,0x30,0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79,0xda,0xd8,0x22,0x7e,0x8, +0x2a,0x6d,0x2, 0x0, 0x2e,0xa9,0xd0,0xce,0xa2,0x0, 0xa9,0x95,0xc9,0x22,0xb, 0xa, +0x30,0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0x24,0x1, 0xf4,0x8d,0x32,0xbe,0x70,0x7, +0x22,0x7e,0xb3,0x33,0xea,0xb4,0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x7e,0xb3,0x2b,0x1e, +0x70,0x1f,0x12,0x26,0xb7,0x12,0x7b,0xd1,0x50,0xfb,0x12,0x45,0x9c,0x12,0x7f,0xd8, +0x20,0x11,0x3, 0x12,0x7c,0x2, 0x74,0x2, 0x7a,0xb3,0x2b,0x1e,0xe4,0x7a,0xb3,0x16, +0x91,0x22,0xca,0x3b,0x7e,0xb3,0x2b,0xf, 0x7a,0xb3,0x1f,0x33,0x7e,0xf3,0x2b,0x62, +0x12,0x7c,0x94,0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x64,0x6c,0xcc,0x12,0x7f,0xc5,0xf5, +0x29,0x7e,0x73,0x2b,0xf, 0xbe,0x71,0x29,0x68,0x36,0x7e,0x70,0x4, 0xac,0x7d,0xa, +0x2c,0x12,0x7c,0x81,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, +0xe0,0xad,0x10,0x2e,0x14,0x16,0x93,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x1d,0xac, +0x7e,0x2e,0x34,0x38,0x59,0x6d,0x22,0x7a,0x1f,0x38,0x55,0x7c,0xbc,0x12,0xab,0x6a, +0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xb5,0x7e,0x73,0x2b,0x62,0xbc,0x7f,0x68,0x6, 0x7a, +0xf3,0x2b,0x62,0xd2,0xe, 0xd2,0x0, 0x7e,0xb3,0x1f,0x33,0x12,0x6c,0xce,0xda,0x3b, +0x22,0x2d,0x32,0x2e,0x34,0x21,0x5, 0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22, +0x7e,0xb3,0x2b,0xf, 0x7c,0xab,0x6c,0x77,0x7e,0x50,0x5, 0xac,0x57,0x9, 0x62,0x26, +0x33,0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74, +0xff,0x22,0x7c,0x2b,0x7e,0xb3,0x1f,0x33,0xbc,0x2b,0x68,0x4f,0x12,0x7c,0x94,0x7c, +0x3b,0x7c,0xb2,0x12,0x7c,0x94,0x7c,0xab,0xbe,0x30,0xff,0x68,0x3e,0xbe,0xa0,0xff, +0x68,0x39,0x7e,0x70,0x4, 0xac,0x73,0xa, 0x2a,0x12,0x7c,0x81,0xbe,0xb0,0x2, 0x38, +0x2a,0xa, 0x2b,0x7e,0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x16,0x93,0x6d,0x22,0x30, +0x1a,0x3, 0x2, 0x7d,0xc, 0x7e,0xb3,0x2b,0x1d,0xb4,0x1, 0xf, 0x12,0x7f,0xce,0x7a, +0x55,0x29,0x7e,0x8, 0xd, 0xc8,0x74,0x1, 0x2, 0x7d,0x3d,0x22,0x7c,0x7b,0x90,0x60, +0x93,0xe4,0x93,0xa, 0x1b,0x7e,0x63,0x2a,0x71,0xa, 0x6, 0x2d,0x1, 0x7e,0x63,0x2a, +0x6e,0xa, 0x16,0xad,0x10,0x7d,0x21,0x12,0x7f,0xbc,0xa, 0x26,0x7a,0x25,0x29,0x74, +0x1d,0xac,0x7b,0x2e,0x34,0x38,0x59,0x6d,0x22,0xe4,0x2, 0x7d,0x3d,0x7c,0xab,0x6d, +0x44,0x80,0x29,0x4c,0xaa,0x68,0x11,0x12,0x7d,0x80,0x60,0x5, 0x3e,0xe4,0x14,0x78, +0xfb,0x12,0x7d,0x74,0x2d,0xfe,0x80,0xf, 0x12,0x7d,0x80,0x60,0x5, 0x3e,0xe4,0x14, +0x78,0xfb,0x12,0x7d,0x74,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e,0xf5,0x29,0xbd, +0xf4,0x38,0xd0,0x22,0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, 0x6a,0xf0,0x22, +0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b, +0xb0,0x22,0xca,0xf8,0x7e,0x45,0x24,0x7c,0xb9,0x7a,0xb3,0x39,0x54,0x74,0xff,0x7a, +0xb3,0x39,0x53,0x6d,0x55,0x80,0x19,0x7d,0xf5,0x3e,0xf4,0x12,0x7d,0x76,0x7d,0xe5, +0x3e,0xe4,0x59,0xfe,0x1f,0x34,0x69,0xf6,0x0, 0x2, 0x59,0xfe,0x21,0x14,0xb, 0x54, +0xbd,0x45,0x38,0xe3,0x7e,0x33,0x39,0x54,0xbe,0x30,0x4, 0x38,0x2, 0xc1,0x54,0x69, +0xf1,0x0, 0x1c,0x69,0x11,0x0, 0x1e,0xbd,0x1f,0x18,0x19,0x4d,0x11,0x78,0x4, 0x7e, +0x14,0x0, 0x1, 0x7d,0x3f,0x7d,0x21,0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x40,0x7a,0xb3, +0x39,0x57,0x80,0x43,0x4d,0xff,0x78,0x4, 0x7e,0xf4,0x0, 0x1, 0x7d,0x31,0x7d,0x2f, +0x12,0x1e,0xb9,0x7c,0xf7,0x74,0x80,0x7a,0xb3,0x39,0x57,0x7d,0xf, 0x2d,0xf, 0xbd, +0x1, 0x8, 0x24,0x1a,0x2, 0x1a,0x0, 0x7e,0x73,0x39,0x57,0xa, 0x37,0x6d,0x22,0x12, +0x1e,0xeb,0x7d,0x5f,0x1a,0x4a,0x1a,0x48,0x7d,0x1f,0x1a,0x2, 0x1a,0x0, 0x2f,0x2, +0x12,0x1f,0x7, 0x7a,0x73,0x39,0x57,0xbe,0xf0,0x5, 0x58,0x14,0x12,0x7e,0x73,0x12, +0xc9,0x48,0x12,0x7e,0x73,0x12,0xca,0xaf,0x12,0x7e,0x73,0x12,0xca,0x45,0x80,0xa, +0x74,0x7d,0x80,0x2, 0x74,0x7f,0x7a,0xb3,0x39,0x53,0xe4,0x7a,0xb3,0x39,0x54,0x7e, +0x73,0x34,0x4f,0xbe,0x73,0x39,0x53,0x48,0x6, 0x7e,0xb3,0x39,0x55,0x80,0x1, 0xe4, +0xda,0xf8,0x22,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x21,0x14,0x22,0x12,0x7f,0x19,0x7a, +0x37,0x2f,0x9c,0x12,0x7e,0xa4,0x7a,0x37,0x2f,0x9e,0x12,0x34,0x2a,0x60,0x1, 0x22, +0x7e,0x73,0x2f,0xa8,0xa, 0x37,0x7a,0x35,0x24,0x7e,0x8, 0x2b,0xbf,0x7e,0x18,0x2f, +0x80,0x2, 0x7d,0x92,0x7e,0x37,0x2f,0x96,0x9e,0x37,0x2f,0x8e,0x22,0x7e,0x17,0x2f, +0x90,0xbd,0x13,0x28,0xa, 0x7a,0x37,0x2f,0x90,0x7a,0x27,0x2f,0x92,0x80,0x10,0x7e, +0x17,0x2f,0x88,0xbd,0x13,0x50,0x8, 0x7a,0x37,0x2f,0x88,0x7a,0x27,0x2f,0x8a,0x7e, +0x17,0x2f,0x8e,0xbd,0x12,0x28,0xa, 0x7a,0x27,0x2f,0x8e,0x7a,0x37,0x2f,0x8c,0x80, +0x10,0x7e,0x17,0x2f,0x96,0xbd,0x12,0x50,0x8, 0x7a,0x27,0x2f,0x96,0x7a,0x37,0x2f, +0x94,0x7e,0xb3,0x2f,0xa8,0xb4,0xa, 0xf, 0x12,0x7f,0x19,0x7a,0x37,0x2f,0xa0,0x12, +0x7e,0xa4,0x7a,0x37,0x2f,0xa2,0x22,0xb4,0x14,0xe, 0x12,0x7f,0x19,0x7a,0x37,0x2f, +0xa4,0x12,0x7e,0xa4,0x7a,0x37,0x2f,0xa6,0x22,0x7e,0x37,0x2f,0x88,0x9e,0x37,0x2f, +0x90,0x22,0x7e,0xb3,0x3, 0xef,0x70,0x6, 0x12,0x7f,0x5b,0x2, 0x7f,0xb6,0x12,0x68, +0x5b,0x12,0x7f,0xec,0x50,0xa, 0x12,0x7e,0x7c,0x7c,0x3b,0x12,0x7f,0x5b,0x80,0x5, +0x12,0xc4,0xe, 0x7c,0x3b,0x4c,0x33,0x68,0x11,0x7c,0xb3,0x12,0xc2,0xcd,0x60,0xa, +0x7a,0x33,0x3, 0xf2,0x74,0x1, 0x7a,0xb3,0x2a,0x8, 0x22,0xe4,0x7a,0xb3,0x2f,0x80, +0x22,0x7e,0xb3,0x3, 0xc4,0x70,0x2e,0x7e,0x73,0x3, 0xa7,0xbe,0x70,0x10,0x40,0x2, +0x6c,0x77,0x7e,0xb3,0x3, 0xef,0xb4,0x1, 0x3, 0x7e,0x70,0x6, 0xa, 0x37,0x2e,0x34, +0xf, 0xf0,0x12,0x7c,0x87,0x7c,0xab,0xe5,0x65,0xa, 0x3b,0x2e,0x37,0x39,0x98,0x7a, +0x37,0x39,0x98,0x80,0xc, 0x7e,0xa3,0x3, 0xa8,0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0, +0x7f,0x7c,0xba,0x2, 0x7f,0xa6,0x75,0x65,0x0, 0x7a,0xb3,0x39,0xf7,0xc2,0x1b,0x22, +0x12,0x7b,0xd1,0x50,0xfb,0x22,0xe4,0x7a,0xb3,0x39,0xd5,0x22,0x3e,0x24,0x7e,0xf, +0x33,0xe4,0x2d,0x12,0x22,0x74,0x5, 0xac,0xbc,0x9, 0xb5,0x26,0x33,0x22,0x7e,0xa3, +0x2a,0x6e,0x7e,0xb3,0x2a,0x6d,0xa4,0x22,0x12,0x47,0x7a,0x50,0x3, 0xd2,0x11,0x22, +0xc2,0x11,0x22,0x12,0xaf,0xce,0x12,0xae,0x28,0x2, 0x7f,0xd8,0x7e,0xb3,0x2f,0x80, +0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7e,0xa3,0x2f,0xa8,0x7e,0x70,0x4, 0xac,0x7a, +0xb, 0x34,0xbe,0x37,0x39,0x2, 0x40,0x39,0x7e,0x37,0x39,0x2, 0xb, 0x34,0x7a,0x37, +0x39,0x2, 0xbe,0x34,0x0, 0x1, 0x78,0x5, 0x7e,0xb3,0x3, 0xf2,0x22,0xbe,0x34,0x0, +0x2, 0x78,0x3, 0x7c,0xba,0x22,0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25, +0x9, 0xb2,0x34,0x49,0x22,0x9e,0x34,0x0, 0x3, 0x2e,0x37,0x2b,0xb9,0x7e,0x39,0xb0, +0x22,0x74,0xff,0x22,0x7e,0xa3,0x38,0xb0,0x7c,0xba,0x4, 0x7a,0xb3,0x38,0xb0,0x7a, +0xa3,0x3, 0xb0,0x22,0xca,0x7b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82, +0x12,0x80,0x70,0xd0,0x82,0xd0,0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32, +0x30,0x90,0x19,0xc2,0x90,0xe5,0x5a,0x70,0x9, 0x75,0x5a,0x1, 0xe5,0x91,0xf5,0x5c, +0x80,0x11,0x7e,0x71,0x91,0xe5,0x5c,0x12,0x80,0x9b,0x5, 0x5c,0x30,0x91,0xb, 0xc2, +0x91,0x5, 0x5c,0xe5,0x5c,0x12,0x80,0xb0,0xf5,0x91,0x22,0x7c,0x6b,0x12,0x80,0xcf, +0x78,0x5, 0x7c,0xb6,0x2, 0x80,0xd7,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x3a,0xd6,0x22, +0x7c,0x7b,0x6c,0xaa,0x12,0x80,0xcf,0x78,0x9, 0x7c,0xb7,0x12,0x81,0x22,0x7c,0xab, +0x80,0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x2f,0xfb,0x7c,0xab,0x7c,0xba,0x22,0x7e, +0xb3,0x38,0xb1,0xc4,0x54,0x7, 0x22,0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, 0x7c, +0xba,0x12,0x87,0x0, 0x80,0x2c,0xbe,0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, 0x7c, +0xb3,0x7c,0x7a,0x12,0x87,0x59,0x80,0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30,0xdf, +0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12,0x87,0x2b,0xa5,0xbb,0x8f,0x3, 0x75, +0x5b,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, 0x2f,0x5f,0x74,0x1, 0x7a,0xb3,0x33, +0xff,0x22,0x70,0x5, 0x7e,0xb3,0x38,0xb1,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x5f, +0x0, 0x30,0x10,0x6, 0x7e,0x18,0x35,0xa6,0x80,0x4, 0x7e,0x18,0x35,0xe4,0x7a,0x1d, +0x1c,0x80,0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x5f,0x0, 0xa, 0x1b,0x7e,0x1d,0x1c, +0x2d,0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10, +0xb4,0xd3,0x8, 0x6d,0x33,0x7a,0x37,0x39,0x2, 0x80,0x2, 0x15,0x5c,0x2, 0x7f,0xf7, +0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x81,0xb9,0xbe,0xb0,0x80,0x40,0xc, +0xbe,0xb0,0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x3, 0x1f,0x22,0xb4,0xfc,0x5, 0x7e, +0xb3,0x3, 0xc6,0x22,0xb4,0xfd,0x17,0x6c,0xaa,0x7e,0xb3,0x28,0xa8,0x60,0x3, 0x4e, +0xa0,0x1, 0x7e,0xb3,0x37,0xe5,0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba,0x22,0xb4,0xfe, +0x5, 0x7e,0xb3,0x2b,0xf, 0x22,0x74,0xff,0x22,0xb4,0xeb,0x5, 0xe4,0x7a,0xb3,0x39, +0x7, 0x7e,0x73,0x39,0x7, 0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x81,0xef,0x7c,0xab, +0x7c,0xb7,0x4, 0x7a,0xb3,0x39,0x7, 0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x39,0x7, 0x6d, +0x33,0x7a,0x37,0x39,0x4, 0x75,0x5c,0xeb,0x7c,0xba,0x22,0x2e,0x24,0x20,0x78,0x7a, +0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0xca,0x3b,0x6d,0xee,0x7e,0xc3,0x2a,0x6e, +0x7e,0xd3,0x2a,0x6d,0x7e,0xb3,0x3, 0xef,0xb4,0x1, 0x3, 0xe4,0x61,0x2e,0x7e,0xb3, +0x28,0x84,0x70,0x2, 0x41,0x9d,0x7e,0xb3,0x2a,0x3, 0x60,0x2, 0x80,0x7f,0x7e,0xa3, +0x26,0xfa,0x7e,0x73,0x26,0xfb,0x7a,0x71,0x24,0x6c,0xee,0x6d,0xff,0x6c,0xff,0xa, +0x47,0x80,0x20,0x12,0x4b,0x41,0xbe,0x34,0x0, 0x96,0x8, 0x1d,0xb, 0xe0,0xbe,0xa0, +0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x83,0x34,0x12,0x83,0x44,0x58,0x3, 0x12,0x83, +0x31,0x1b,0x44,0xbe,0x44,0x0, 0x0, 0x58,0xda,0xe5,0x24,0xa, 0x4b,0x80,0x1e,0x12, +0x4b,0x41,0xbe,0x34,0x0, 0x96,0x8, 0x21,0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c, +0xba,0x14,0x12,0x83,0x34,0x12,0x83,0x44,0x58,0x3, 0x12,0x83,0x31,0x7d,0x24,0xb, +0x24,0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xd6,0xbe,0xe0,0x3, 0x50,0x2, 0x80,0xd, +0xa, 0x2f,0x7d,0x3f,0x12,0x1e,0xb9,0xbe,0x34,0x0, 0x28,0x8, 0x7, 0xe4,0x7a,0xb3, +0x37,0x30,0x61,0x2e,0x6d,0xdd,0xbe,0xa0,0x0, 0x28,0x8, 0x7c,0xba,0x14,0x12,0x83, +0x3e,0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, 0xca,0xbd,0xc3,0x58,0x8, 0x7c,0xba,0x4, +0x12,0x83,0x3e,0x2d,0xd3,0x7e,0x70,0x8, 0x80,0x2a,0x7e,0x50,0x2, 0xac,0x57,0x7d, +0xc2,0x2e,0xc4,0x20,0xf5,0x7d,0x1c,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0x1a, +0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x20,0xf6,0x7d,0x2c,0x12,0x81,0xef, +0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xce,0x7c,0xba,0x12,0x83, +0x3e,0x12,0x21,0x15,0xbe,0x34,0xa, 0xf0,0x8, 0x4, 0x2e,0xe4,0x0, 0x28,0xbe,0xe4, +0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x37,0x30,0xa, 0x3b,0xbd,0x3e, +0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x37,0x30,0x7e,0xb3,0x37,0x30,0xda,0x3b, +0x22,0x7c,0xba,0x4, 0x7c,0x79,0x12,0x4b,0x45,0x2d,0xf3,0xb, 0xf0,0x22,0x7e,0x71, +0x24,0x2, 0x4b,0x45,0xa, 0x2d,0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0x12,0x85,0x28, +0x12,0x81,0xf8,0x7a,0xb3,0x2a,0xc, 0x22,0x7c,0xab,0x6c,0x77,0x80,0x11,0xa, 0x27, +0x2e,0x24,0x60,0xac,0x12,0x81,0xef,0xbc,0xba,0x78,0x2, 0xd3,0x22,0xb, 0x70,0x90, +0x60,0xa7,0xe4,0x93,0xbc,0xb7,0x38,0xe6,0xc3,0x22,0xca,0x3b,0x7c,0x5b,0x7e,0x43, +0x28,0x84,0xbe,0x40,0x1, 0x28,0x2, 0x81,0x75,0x7e,0xa3,0x2a,0x6e,0x7e,0x70,0x2, +0xac,0x75,0x9, 0xd3,0x26,0xfa,0x9, 0xc3,0x26,0xfb,0x7c,0xbd,0x7c,0x7c,0x12,0x86, +0xea,0x7f,0x1, 0x90,0x60,0xaa,0xe4,0x93,0x70,0x12,0x7c,0xfc,0x7c,0x9d,0x7e,0x83, +0x2a,0x70,0x7e,0xe3,0x2a,0x6f,0xa, 0xca,0x6d,0xbb,0x9d,0xbc,0xa, 0xa8,0x1b,0xa5, +0xa, 0x5f,0xbd,0x5a,0x58,0x2, 0x81,0x75,0xa, 0x59,0x1b,0x54,0xbe,0x54,0x0, 0x0, +0x48,0x4e,0x7c,0xb9,0x14,0x12,0x83,0x58,0x50,0x46,0x7c,0xb9,0x14,0x12,0x84,0x78, +0xb, 0x1a,0xe0,0x7d,0x3b,0x12,0x84,0xad,0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, +0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a,0x12,0x84,0xa5,0x7c,0xb8,0x24,0xfe,0xbc, +0xbf,0x78,0x1d,0x90,0x60,0xaa,0xe4,0x93,0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f, +0x12,0x84,0x7f,0xb, 0x1a,0x30,0xbd,0x3a,0x8, 0x6, 0x12,0x84,0x81,0x1b,0x1a,0xa0, +0xa, 0xa9,0xb, 0xa4,0xa, 0x5e,0xbd,0xa5,0x58,0x4b,0x7c,0xb9,0x4, 0x12,0x83,0x58, +0x50,0x43,0x7c,0xb9,0x4, 0x12,0x84,0x78,0xb, 0x1a,0xe0,0x7d,0x3c,0x12,0x84,0xad, +0x8, 0x11,0x9d,0xae,0xbe,0xa4,0x0, 0x0, 0x58,0x4, 0x6d,0x55,0x80,0x2, 0x7d,0x5a, +0x12,0x84,0xa5,0x7c,0xb8,0x24,0xfe,0xbc,0xbf,0x78,0x1a,0x90,0x60,0xaa,0xe4,0x93, +0x70,0x4, 0x7d,0xfd,0x1b,0xf4,0x7d,0x5f,0x12,0x84,0x7f,0xb, 0x1a,0x50,0xbd,0x5a, +0x8, 0x3, 0x1b,0x1a,0xa0,0xda,0x3b,0x22,0x12,0x84,0x88,0x7d,0xd3,0x7d,0x5d,0x3e, +0x54,0x7e,0x1f,0x13,0x8a,0x2d,0x35,0x22,0x7c,0x5b,0x7e,0x43,0x2a,0x6e,0x90,0x60, +0xab,0xe4,0x93,0x7c,0xab,0x90,0x60,0xaa,0xe4,0x93,0x70,0x8, 0x7c,0x75,0xac,0x74, +0xa, 0x2a,0x2d,0x32,0x22,0x2d,0x31,0x7d,0x20,0x1b,0x1a,0x50,0x22,0x3e,0x34,0x7f, +0x40,0x2d,0x93,0xb, 0x4a,0xa0,0xbe,0xe4,0x0, 0x0, 0x22,0x12,0x86,0xc8,0x60,0x34, +0x6c,0x22,0x80,0x28,0x7c,0xb2,0x12,0x83,0x58,0x50,0x1f,0x7c,0xb2,0x12,0x84,0x88, +0x3e,0x34,0x7e,0x7f,0x13,0x8a,0x2d,0xf3,0xb, 0x7a,0x30,0x12,0x86,0xc0,0x59,0x35, +0x39,0xe0,0x30,0x0, 0x5, 0x6d,0x33,0x1b,0x7a,0x30,0xb, 0x20,0x7e,0x73,0x2a,0x75, +0xbc,0x72,0x38,0xd0,0x22,0x90,0x60,0xa7,0xe4,0x93,0x60,0x2b,0x6c,0x33,0x80,0x1f, +0x7c,0xb3,0x12,0x83,0x58,0x40,0x16,0x7c,0xb3,0x12,0x84,0x88,0x7d,0x43,0x6d,0x55, +0x7d,0x4, 0x3e,0x4, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x1b,0x1a,0x50,0xb, 0x30,0x7e, +0x23,0x2a,0x75,0xbc,0x23,0x38,0xd9,0x22,0x7e,0xa3,0x28,0x84,0xe4,0x7a,0xb3,0x36, +0x95,0x6c,0x33,0x80,0x3d,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x26,0xfb,0x7e,0x10, +0x1, 0x6c,0x0, 0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70,0x2, 0xac,0x70,0x9, 0x93, +0x26,0xfb,0xa, 0x29,0xa, 0x32,0x12,0x5c,0x84,0x18,0x2, 0xb, 0x10,0xbe,0x10,0x2, +0x40,0x8, 0x74,0x2, 0x7a,0xb3,0x36,0x95,0x80,0x6, 0xb, 0x0, 0xbc,0xa0,0x38,0xd5, +0xb, 0x30,0xbc,0xa3,0x38,0xbf,0x2, 0x85,0x79,0xca,0xf8,0x7e,0x33,0x28,0x84,0x6c, +0x22,0x80,0x45,0x74,0x2, 0xac,0xb2,0x9, 0x15,0x26,0xfa,0x9, 0x5, 0x26,0xfb,0x7e, +0xa0,0x1, 0x6c,0x99,0x80,0x2c,0xbc,0x92,0x68,0x26,0x7e,0x70,0x2, 0xac,0x79,0x9, +0x83,0x26,0xfa,0x9, 0xf3,0x26,0xfb,0xa, 0x28,0xa, 0x31,0x12,0x5c,0x84,0x18,0xb, +0xa, 0x2f,0xa, 0x30,0x12,0x5c,0x84,0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, +0xb, 0x90,0xbc,0x39,0x38,0xd0,0xb, 0x20,0xbc,0x32,0x38,0xb7,0x7e,0xb3,0x37,0x2f, +0xbe,0xb0,0x0, 0x28,0x12,0x14,0x7a,0xb3,0x37,0x2f,0xbe,0xb0,0x14,0x28,0x8, 0x7e, +0x34,0x0, 0x8c,0x7a,0x37,0x2a,0x5a,0x7e,0xb3,0x3, 0xaa,0x70,0x58,0x7e,0xb3,0x39, +0xfc,0x70,0x52,0x7e,0xb3,0x37,0xe5,0x70,0x4c,0x7e,0x37,0x39,0x12,0xbe,0x34,0x0, +0x14,0x50,0x42,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x28, +0x84,0xbe,0xb0,0x3, 0x40,0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x26,0x85,0xbe, +0xb0,0x3, 0x50,0x9, 0x7e,0xb3,0x26,0x84,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x26, +0xf6,0xbe,0xb0,0x8, 0x50,0x9, 0x7e,0xb3,0x26,0xf7,0xbe,0xb0,0x8, 0x40,0x6, 0x74, +0x1e,0x7a,0xb3,0x37,0x2f,0xda,0xf8,0x22,0x7e,0x63,0x2a,0x6e,0x90,0x60,0xa7,0xe4, +0x93,0x60,0x6c,0xc2,0x15,0x6c,0x33,0x80,0x56,0x90,0x60,0xaa,0xe4,0x93,0x70,0x13, +0x7c,0x96,0xac,0x93,0x90,0x60,0xab,0xe4,0x93,0xa, 0x5b,0x1b,0x54,0x2d,0x45,0x7d, +0xd4,0xb, 0xd4,0x7d,0x54,0x3e,0x54,0x7e,0x7f,0x13,0x8a,0x2d,0xf5,0xb, 0x7a,0x50, +0xbe,0x57,0x2a,0x5a,0x8, 0x27,0x7c,0xb3,0x12,0x83,0x58,0x50,0x20,0x7d,0x5d,0x3e, +0x54,0x7e,0x7f,0x13,0x8a,0x7f,0x57,0x2d,0xb5,0xb, 0x5a,0xc0,0x7d,0x54,0x3e,0x54, +0x2d,0xf5,0xb, 0x7a,0x50,0xbd,0x5c,0x8, 0x4, 0xd2,0x15,0x80,0xa, 0xb, 0x30,0x7e, +0x73,0x2a,0x75,0xbc,0x73,0x38,0xa2,0x30,0x15,0x5, 0xd2,0x0, 0x2, 0x84,0xbb,0x22, +0x7c,0xa3,0xb, 0x30,0x74,0x2, 0xa4,0x22,0x6c,0x33,0x90,0x60,0xa7,0xe4,0x93,0x22, +0x7c,0xab,0x90,0x60,0xab,0xe4,0x93,0xbc,0xb7,0x78,0x9, 0x7c,0xba,0x12,0x83,0x58, +0x50,0x2, 0xd3,0x22,0xc3,0x22,0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x2a,0x6e,0xac,0x1b, +0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10,0x7e,0x1f,0x13,0x8a,0x2d,0x31,0x22, +0x7a,0xb3,0x38,0xb1,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, 0xb4,0x2, 0x4, 0x74, +0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3,0x3, 0xc6,0x22,0x74, +0x1, 0x7a,0xb3,0x3, 0xc6,0xe4,0x7a,0xb3,0x38,0xb1,0x22,0x7c,0x6b,0x2e,0x60,0xdd, +0x68,0x26,0x2e,0x60,0xfd,0x68,0x21,0x1b,0x61,0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b, +0x61,0x68,0x15,0x1b,0x60,0x68,0x11,0x2e,0x60,0xa, 0x78,0x4, 0x7a,0x73,0x3, 0x9e, +0xa, 0x2b,0x19,0x72,0x3, 0x9f,0xd2,0xf, 0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec, +0x33,0x7e,0x27,0x39,0x4, 0x4d,0x22,0x78,0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, +0x1, 0x7a,0x27,0x39,0x4, 0x15,0x5c,0x7e,0x27,0x39,0x4, 0xbe,0x24,0x0, 0x1, 0x78, +0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x39, +0x4, 0x75,0x5c,0xea,0x22,0x7d,0xf3,0x6d,0xee,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12, +0x84,0x88,0x7d,0xd3,0x7d,0xcd,0x3e,0xc4,0x7f,0x57,0x2d,0xbc,0xb, 0x5a,0x10,0x1a, +0x2, 0x1a,0x0, 0x7e,0x83,0x2b,0x20,0xa, 0x98,0x6d,0x88,0x7f,0x10,0x7f,0x4, 0x12, +0x1e,0xeb,0x74,0x6, 0x7f,0x1, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20,0x80,0x14, +0x78,0xf4,0x7d,0xc1,0x1b,0x5a,0xc0,0xb, 0x90,0x7e,0x83,0x2a,0x75,0xbc,0x89,0x38, +0xbc,0x22,0xa9,0xc0,0x93,0x75,0x5a,0x0, 0x32,0x7e,0xb3,0x39,0x6, 0x4, 0x7a,0xb3, +0x39,0x6, 0xe5,0x5b,0xb4,0x1, 0x8, 0xe4,0x7a,0xb3,0x39,0x6, 0x75,0x5b,0x0, 0x7e, +0x73,0x39,0x6, 0x7a,0x73,0x3, 0xae,0x22,0xe4,0x7a,0xb3,0x38,0xb1,0x7e,0x8, 0x35, +0xa6,0x12,0x88,0x57,0x7e,0x8, 0x35,0xe4,0x7e,0x34,0x0, 0x3e,0x12,0x20,0xe3,0x7e, +0x18,0x35,0xa6,0x7a,0x1d,0x1c,0x12,0x88,0x39,0x2, 0x88,0x2c,0x75,0x5a,0x0, 0x75, +0x5c,0x0, 0x7e,0xb3,0x38,0xb1,0xf5,0x91,0x22,0x2, 0x88,0x3c,0x90,0x60,0x0, 0xe4, +0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2,0xc9,0x54,0xfe,0xf5,0x92, +0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0x7e,0x34,0x0, 0x3e,0x74,0xff,0x2, 0x20,0xe3, +0x30,0x1c,0x5, 0x74,0x5, 0x12,0x45,0x4c,0x7e,0xb3,0x33,0xea,0xb4,0x1, 0x4f,0x12, +0x88,0xbf,0x49,0x35,0x33,0xeb,0x49,0x15,0x33,0xed,0x6d,0x0, 0xbe,0x8, 0x0, 0x0, +0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15,0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12,0x0, +0x1e,0x7e,0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x7e,0xb3,0x33,0xe9, +0x4, 0x7a,0xb3,0x33,0xe9,0x12,0x88,0xc7,0x28,0xe, 0x12,0x47,0xc7,0xb4,0x1, 0x4, +0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x33,0xea,0x22,0x7e, +0xa3,0x33,0xe9,0x74,0x4, 0xa4,0x22,0x7e,0x73,0x33,0xe8,0xbe,0x73,0x33,0xe9,0x22, +0x7f,0x20,0xb, 0x2a,0x10,0xb, 0x1a,0x0, 0x1b,0x2a,0x0, 0x1b,0x1a,0x10,0x22,0x7c, +0x9b,0x7f,0x71,0x7e,0x7b,0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b,0x90, +0x22,0xa, 0x28,0x7e,0xb, 0x80,0xa, 0x38,0x9d,0x32,0x12,0x21,0x15,0xe5,0x2b,0xa, +0x2b,0xbd,0x32,0x8, 0x15,0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba,0x28, +0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, 0x70, +0x22,0x7d,0xc3,0x7e,0x34,0x61,0x37,0x12,0x8e,0xf6,0x90,0x61,0x35,0xe4,0x93,0x70, +0x3, 0x7d,0x3c,0x22,0x90,0x61,0x36,0xe4,0x93,0xb4,0x1, 0x6, 0x7e,0x83,0x2a,0x70, +0x80,0x4, 0x7e,0x83,0x2a,0x6f,0x12,0x8f,0xeb,0xbe,0xc4,0x0, 0x3f,0x38,0x20,0x7e, +0xe4,0x0, 0x3f,0x9d,0xec,0x7e,0x34,0x61,0x3b,0x12,0x8a,0x15,0x7c,0x65,0x7f,0x71, +0x12,0x8a,0x4, 0xbf,0x71,0x40,0x2, 0x7f,0x71,0x9f,0x17,0x7f,0x71,0x41,0x1, 0x12, +0x37,0xc2,0xbd,0x5c,0x38,0x25,0x7d,0xec,0x9d,0xe5,0x7e,0x34,0x61,0x3d,0x12,0x8a, +0x15,0x7c,0x65,0x7f,0x71,0x90,0x61,0x3a,0xe4,0x93,0xa, 0x3b,0xbf,0x71,0x40,0x4, +0x7f,0x71,0x1b,0x7c,0x12,0x8a,0xc, 0x2f,0x71,0x80,0x66,0x7d,0xb4,0xb, 0xb4,0x1e, +0xb4,0x7d,0x5b,0x1b,0x54,0xbd,0x5c,0x40,0xc, 0x7d,0xf5,0x9d,0xfc,0x6d,0xee,0x7e, +0x34,0x61,0x3f,0x80,0xa, 0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x34,0x61,0x41,0x12, +0x8a,0x27,0x7f,0x17,0x12,0x1e,0xfc,0x7f,0x71,0x12,0x32,0xfe,0x7f,0x71,0xbd,0x5c, +0x7d,0x3d,0x40,0xc, 0x1e,0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x80,0x6, +0x1e,0x34,0x6d,0x22,0x2f,0x71,0x12,0x8a,0x4, 0x6d,0x22,0xbf,0x71,0x50,0x4, 0x7f, +0x71,0x80,0xe, 0x90,0x61,0x3a,0xe4,0x93,0x12,0x8a,0xc, 0xbf,0x71,0x28,0x2, 0x7f, +0x71,0x7d,0x3f,0x22,0x90,0x61,0x39,0xe4,0x93,0xa, 0x3b,0x22,0xa, 0x2b,0x7d,0x3d, +0x9d,0x32,0x6d,0x22,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0xad,0xfe,0x6d,0xee, +0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x10,0x22,0x12, +0x8b,0xc4,0x12,0x63,0x67,0x12,0x8b,0x48,0x12,0x8a,0x8c,0x7e,0xb3,0x3, 0xc4,0xb4, +0x1, 0x1e,0x7e,0x34,0x61,0xc6,0x12,0x8a,0x27,0x7e,0x24,0x0, 0x5, 0xad,0x12,0x7a, +0x17,0x28,0xa1,0x7e,0x14,0x61,0xc8,0x12,0x36,0xb3,0xad,0x32,0x7a,0x37,0x28,0xa3, +0x7e,0xb3,0x3a,0x3, 0x60,0x7, 0x14,0x7a,0xb3,0x3a,0x3, 0x80,0x6, 0x7e,0xb3,0x28, +0xac,0x60,0x9, 0x12,0x7f,0xe3,0x12,0x6f,0x7e,0x12,0xba,0x1f,0x7e,0xb3,0x28,0xad, +0x60,0x9, 0x12,0xc0,0x80,0x12,0x8a,0xf7,0x2, 0x8a,0xa9,0x22,0x12,0xb3,0x77,0x60, +0x17,0x12,0x64,0xd1,0x7e,0x37,0x28,0xa1,0x3e,0x34,0x7a,0x37,0x28,0xa1,0x7e,0x37, +0x28,0xa3,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0x6c,0xaa,0x80,0x44,0x7e,0x70,0xc, +0xac,0x7a,0x12,0xb3,0x3b,0xbe,0x34,0x3, 0xe8,0x8, 0x5, 0x12,0xcc,0x71,0x80,0x2f, +0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0xf8,0x49,0x12,0x37,0xf4,0xbd,0x13,0x28, +0xf, 0x7d,0x2, 0x2e,0x4, 0x37,0xf8,0x7d,0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, +0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24,0x37,0xf8,0x1b,0x35,0x1b,0x28,0x30,0xb, +0xa0,0x12,0x6f,0xd6,0x38,0xb7,0x22,0x7e,0x43,0x2a,0x6e,0x7e,0x53,0x2a,0x6d,0xac, +0x54,0x7e,0x17,0x28,0xa1,0x12,0x8e,0xb6,0x6d,0x0, 0x80,0x37,0x7d,0x40,0x3e,0x44, +0x7e,0x7f,0x33,0xe4,0x2d,0xf4,0xb, 0x7a,0x30,0xbd,0x13,0x58,0x10,0x7d,0xf4,0x2e, +0xf4,0x8, 0xa, 0xb, 0xf8,0x50,0x9d,0x51,0x1b,0xf8,0x50,0x80,0x14,0x6d,0x55,0x9d, +0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44,0x8, 0xa, 0xb, 0x48,0x50,0x2d,0x51,0x1b,0x48, +0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5,0x22,0xc2,0x0, 0x12,0x4f,0xfc,0x50,0x4b,0x6c, +0xaa,0x80,0x39,0x7e,0x50,0x2, 0xac,0x5a,0x9, 0x72,0x26,0xfa,0x9, 0x62,0x26,0xfb, +0xbe,0x70,0x0, 0x28,0x25,0x7e,0xb3,0x2a,0x6f,0xa, 0x1b,0x1b,0x14,0xa, 0x27,0xbd, +0x21,0x58,0x17,0xbe,0x60,0x0, 0x28,0x12,0x7e,0xb3,0x2a,0x70,0x1e,0xb0,0xa, 0x1b, +0xa, 0x26,0xbd,0x21,0x58,0x4, 0xd2,0x0, 0x80,0xa, 0xb, 0xa0,0x7e,0xb3,0x28,0x84, +0xbc,0xba,0x38,0xbf,0x20,0x0, 0x3, 0x12,0x64,0xd1,0x30,0x19,0x23,0x5, 0x64,0xe5, +0x64,0xbe,0xb0,0x50,0x50,0x16,0x7e,0x34,0x61,0xc6,0x12,0x23,0xbc,0x3e,0x34,0x12, +0x8f,0xf3,0x12,0x23,0xbc,0x3e,0x34,0x7a,0x37,0x28,0xa3,0x22,0xc2,0x19,0x80,0x0, +0x75,0x64,0x0, 0x22,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x2a,0x6e,0x7e,0x47,0x28,0x99, +0xe4,0x7a,0xb3,0x28,0xa6,0x7e,0xb3,0x26,0xf0,0xbe,0xb0,0x0, 0x28,0x4c,0x7e,0x73, +0x28,0x85,0xbe,0x70,0x0, 0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f, +0x9, 0xd2,0x27,0x36,0x9, 0xe2,0x27,0x37,0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, +0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x53,0xbd,0x12,0x58,0x19,0x12,0x8c,0xd6,0x49,0x12, +0x4, 0xfc,0x6d,0x22,0x9e,0x27,0x2a,0x51,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3, +0x28,0xa6,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x28,0xa7,0x7e, +0xb3,0x26,0x83,0x70,0x40,0x12,0x8f,0xe3,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50, +0x2, 0xac,0x5f,0x9, 0xd2,0x26,0xfa,0x9, 0xe2,0x26,0xfb,0x12,0x8c,0xd6,0x49,0x2, +0x5, 0x7a,0x6d,0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49, +0x20,0x5, 0x7a,0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x28,0xa7,0x80,0x6, 0xb, +0xf0,0xbc,0x7f,0x38,0xc9,0x12,0x8c,0xe9,0xe4,0x7a,0xb3,0x28,0xa9,0x7e,0x37,0x28, +0x88,0x2e,0x37,0x28,0x86,0xbe,0x37,0x28,0x9f,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28, +0xa9,0x74,0x1, 0x7a,0xb3,0x28,0xaa,0x6c,0xff,0x80,0x1f,0x12,0x8c,0xdf,0x49,0x25, +0x25,0xf7,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x21,0x15,0xbe,0x37,0x28,0x9d,0x8, +0x7, 0xe4,0x7a,0xb3,0x28,0xaa,0x80,0x7, 0xb, 0xf0,0x12,0x67,0xe2,0x38,0xdc,0x6c, +0xff,0x80,0x9, 0x12,0x8c,0xdf,0x59,0x35,0x25,0xf7,0xb, 0xf0,0x12,0x67,0xe2,0x38, +0xf2,0xda,0x79,0xda,0xd8,0x22,0xa, 0x1d,0xa, 0x2a,0x2d,0x21,0x3e,0x24,0x22,0x7c, +0xbf,0x12,0x5e,0x76,0x74,0x2, 0xac,0xbf,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6c, +0xdd,0x7e,0x57,0x28,0x99,0x7d,0xf5,0x7e,0xe7,0x28,0x97,0x7e,0x37,0x39,0x10,0x4d, +0x33,0x68,0x4, 0x7d,0xf5,0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x2a,0x6e,0x7c,0x8a,0x7e, +0xb3,0x28,0xa5,0x14,0x68,0x21,0x14,0x68,0x14,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68, +0x16,0x24,0x45,0x78,0x10,0x7c,0xfa,0x7e,0x83,0x2a,0x6d,0x80,0xa, 0x7e,0x73,0x2a, +0x6d,0x2c,0x87,0x80,0x2, 0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c,0xb9,0x12,0x5e,0x76, +0xbe,0x34,0x2, 0x58,0x8, 0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33,0x28,0x84,0xbc,0x39, +0x38,0xe9,0xbe,0xd0,0x3, 0x40,0x2, 0xc1,0xaa,0x7e,0xa3,0x28,0x85,0xbe,0xa0,0x0, +0x38,0xb, 0xbe,0x30,0x0, 0x28,0x37,0x7e,0xb3,0x26,0x83,0x70,0x31,0x6c,0x99,0x80, +0x29,0xa, 0x29,0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, 0x7a,0xbd,0x2f,0x8, +0x17,0x49,0x3, 0x4, 0xfc,0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d,0x3e,0x12,0x5f,0xf8, +0xbd,0x3, 0x8, 0x4, 0xd2,0x0, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xd3,0x6d,0xee, +0x9e,0xe7,0x2a,0x4f,0xbe,0xe7,0x7, 0xf8,0x8, 0x2, 0xc2,0x0, 0x30,0x0, 0x20,0x7e, +0xb3,0x39,0xfc,0x4, 0x7a,0xb3,0x39,0xfc,0x7e,0x23,0x39,0xfc,0xbe,0x20,0xa, 0x28, +0x1d,0x74,0xa, 0x7a,0xb3,0x39,0xfc,0x74,0x1, 0x7a,0xb3,0x28,0xa8,0x80,0xf, 0x7e, +0x23,0x39,0xfc,0xbe,0x20,0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23,0x39,0xfc,0x6c,0xee, +0xbe,0x30,0x0, 0x38,0x5, 0xbe,0xa0,0x0, 0x28,0x69,0x7e,0xb3,0x28,0xa7,0xb4,0x1, +0x9, 0x7e,0xb3,0x28,0xaa,0xbe,0xb0,0x1, 0x68,0x59,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x52,0x6c,0x99,0x80,0x1d,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x26,0xfa,0x9, 0xd3, +0x26,0xfb,0x12,0x8e,0xaf,0xbe,0x34,0x0, 0x96,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0xa, +0xb, 0x90,0x7e,0xb3,0x28,0x84,0xbc,0xb9,0x38,0xdb,0x6c,0x99,0x80,0x1d,0x7e,0x70, +0x2, 0xac,0x79,0x9, 0xa3,0x27,0x36,0x9, 0xd3,0x27,0x37,0x12,0x8e,0xaf,0xbe,0x34, +0xff,0x6a,0x58,0x5, 0x7e,0xe0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0xb3,0x28,0x85,0xbc, +0xb9,0x38,0xdb,0x6c,0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d,0x5e,0x3e,0x54,0x49, +0x55,0x5, 0x7a,0xbd,0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, 0xb, 0x90,0xbc,0x89, +0x38,0xe5,0x4c,0xee,0x78,0x25,0x7e,0xb3,0x39,0xfd,0x4, 0x7a,0xb3,0x39,0xfd,0x7e, +0x73,0x39,0xfd,0xbe,0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3,0x39,0xfd,0x7e,0xb3, +0x28,0xa8,0x60,0x2, 0xd2,0x18,0x12,0xb4,0x3d,0x80,0xf, 0x7e,0x73,0x39,0xfd,0xbe, +0x70,0x0, 0x28,0x6, 0x1e,0x70,0x7a,0x73,0x39,0xfd,0xda,0x79,0xda,0xd8,0x22,0x7c, +0xba,0x7c,0x7d,0x2, 0x4b,0x45,0xa9,0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0xb3,0x2b, +0x1d,0xb4,0x1, 0x31,0x12,0x8e,0xb6,0x7e,0x1f,0x33,0xe4,0x7a,0x37,0x24,0xfa,0x7e, +0x34,0xd, 0xc8,0x7a,0x37,0x24,0xf6,0x12,0xae,0x65,0x12,0xae,0x6e,0xe4,0x7a,0xb3, +0x24,0xf5,0x7e,0x34,0x0, 0x20,0x7a,0x37,0x24,0xfc,0x7a,0xb3,0x24,0xf4,0x7e,0x8, +0x24,0xf2,0x2, 0xd, 0x7, 0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xd0,0x22,0xca,0xd8, +0xca,0x79,0x7e,0x34,0x61,0x43,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x40,0x90,0x61,0x35, +0xe4,0x93,0x70,0x2, 0xe1,0xaa,0x90,0x60,0xa7,0xe4,0x93,0x70,0x2, 0xe1,0xaa,0x6c, +0xff,0xe1,0xa3,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x29,0xc, 0x5e,0xe0,0xf, 0x49, +0xc3,0x29,0xa, 0x7e,0x14,0x60,0xd1,0x12,0x47,0xe0,0x2d,0x24,0xbd,0xc2,0x40,0x42, +0x49,0xd3,0x29,0x8, 0x7d,0x3d,0x12,0xad,0x14,0x7c,0xdb,0x90,0x60,0xa7,0xe4,0x93, +0xbc,0xbd,0x38,0xe, 0x7d,0x34,0x1b,0x34,0x12,0x8f,0xaf,0x7c,0xbe,0x12,0x8f,0xb8, +0x80,0x3f,0x7e,0x70,0x2, 0xac,0x7d,0x2e,0x34,0x60,0xc5,0x12,0x8e,0xf6,0x74,0x9, +0xac,0xbf,0x59,0xd5,0x29,0x8, 0x7e,0x34,0x60,0xcf,0x12,0x23,0xbc,0x12,0x8f,0xaf, +0x80,0x1f,0xbd,0xc4,0x40,0x1b,0x7d,0x54,0x2e,0x54,0x0, 0xa, 0xbd,0xc5,0x40,0x5, +0x7c,0xbe,0x12,0x8f,0xb8,0x7d,0xc4,0x1b,0xc4,0x74,0x9, 0xac,0xbf,0x59,0xc5,0x29, +0xa, 0xb, 0xf0,0x12,0x53,0x30,0x28,0x2, 0xe1,0x23,0xda,0x79,0xda,0xd8,0x22,0x74, +0x9, 0xac,0xbf,0x59,0x35,0x29,0xa, 0x22,0x7c,0xab,0x7e,0x8, 0x29,0xbc,0x12,0x53, +0x21,0x28,0x1f,0xa, 0x3a,0x7f,0x70,0x2d,0xf3,0x7e,0x7b,0xb0,0xb4,0x2, 0x4, 0x74, +0x1, 0x80,0x2, 0x74,0x3, 0x7a,0x7b,0xb0,0x74,0x3, 0x2d,0x31,0x7d,0x20,0x39,0xb1, +0x0, 0xa, 0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x0, 0x22,0x7e,0x90,0x40,0xac,0x89, +0x1b,0x44,0x22,0x7a,0x37,0x28,0xa1,0x7e,0x34,0x61,0xc8,0x22,0x2, 0x8f,0xff,0xca, +0x79,0x6c,0xff,0x7e,0xd7,0x2a,0x5a,0x6c,0xee,0x80,0x35,0x7c,0xbe,0x12,0x5e,0x76, +0xbd,0x3d,0x48,0x2a,0x7c,0xbe,0x12,0x4f,0xc5,0x60,0x23,0x7e,0xc4,0x0, 0x9, 0xca, +0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x27,0x76,0x6d,0x22,0x7e,0x30,0x9, 0xac, +0x3f,0x2e,0x14,0x28,0xae,0x6d,0x0, 0x12,0x20,0xbe,0x1b,0xfd,0xb, 0xf0,0xb, 0xe0, +0x12,0x5f,0xf1,0x38,0xc6,0x7a,0x73,0x28,0x93,0x7a,0xf3,0x2a,0x2, 0xda,0x79,0x22, +0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x12, +0x1f,0x5, 0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28,0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca, +0xf8,0x7e,0xf3,0x2a,0x70,0x7a,0x37,0x1f,0x3a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f, +0x3c,0xe4,0x7a,0xb3,0x1f,0x34,0x7a,0xb3,0x1f,0x35,0x7e,0x73,0x2a,0x6f,0x7a,0x73, +0x1f,0x36,0x7a,0xf3,0x1f,0x37,0x7a,0xb3,0x1f,0x38,0x7a,0xb3,0x1f,0x39,0x7e,0x8, +0x1f,0x34,0x12,0x90,0xc4,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x15,0xa0,0x2f, +0x10,0x7e,0x33,0x1f,0x36,0x6d,0x0, 0x12,0x1f,0x7, 0xa, 0x1f,0x6d,0x0, 0x12,0x1f, +0x7, 0xda,0xf8,0x22,0x12,0xc, 0x29,0x7e,0x37,0x15,0x9e,0x22,0x7a,0x37,0x1f,0x38, +0x7e,0x34,0x15,0xa8,0x7a,0x37,0x1f,0x3c,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x3a, +0x7e,0x73,0x2a,0x6f,0x7a,0x73,0x1f,0x35,0x7e,0x73,0x2a,0x70,0x7a,0x73,0x1f,0x34, +0x7e,0x37,0x2a,0x5c,0x7a,0x37,0x1f,0x3e,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x40, +0x7e,0x37,0x2a,0x60,0x7a,0x37,0x1f,0x42,0x74,0x1, 0x7a,0xb3,0x1f,0x36,0x7a,0xb3, +0x1f,0x37,0x7e,0x8, 0x1f,0x34,0x7e,0x18,0x1f,0x44,0x12,0x8, 0x0, 0x7e,0x37,0x1f, +0x4e,0x7e,0x27,0x1f,0x4a,0xbd,0x23,0x28,0x2, 0x7d,0x32,0x22,0xca,0x3b,0x7e,0x8, +0x1f,0x34,0x12,0x47,0xe8,0x7e,0x1f,0x39,0xeb,0x7a,0x1d,0x27,0x7e,0xb3,0x2a,0x74, +0xf5,0x2e,0x7e,0xb3,0x39,0x9b,0xb4,0x1, 0x6, 0x7e,0x38,0x39,0x9d,0x80,0x4, 0x7e, +0x38,0x5, 0xf8,0x6d,0x33,0x7a,0x35,0x2b,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x39, +0x9c,0x70,0xe, 0x7e,0xb3,0x39,0x9a,0x70,0x8, 0x74,0x1, 0x7a,0xb3,0x39,0x9c,0x21, +0xf4,0x7e,0xb3,0x39,0x9c,0x70,0x6, 0x74,0x1, 0x7a,0xb3,0x39,0x9c,0x7e,0xb3,0x39, +0x9b,0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80,0x6, 0x12,0x92,0x36,0x12,0x92,0x44,0xe5, +0x2e,0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18,0x75,0x2d,0x0, 0x80,0xc, 0x12,0x92,0x36, +0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0x92,0x44,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed, +0x7e,0x34,0x61,0x5b,0x12,0x23,0xbc,0x7a,0x35,0x2f,0x7e,0x18,0x1f,0x34,0x7f,0x1, +0x12,0x92,0x55,0x75,0x2d,0x0, 0x80,0x10,0x12,0x92,0x29,0xbe,0x35,0x2b,0x8, 0x6, +0x12,0x92,0x29,0x7a,0x35,0x2b,0x5, 0x2d,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xe9,0x12, +0x92,0x21,0x40,0x25,0x7e,0xb3,0x39,0x9b,0xb4,0x1, 0x1e,0x5, 0x60,0xe5,0x60,0xbe, +0xb0,0xa, 0x40,0x15,0x75,0x60,0x0, 0xe5,0x2e,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e, +0x1d,0x27,0x7f,0x3, 0x12,0x20,0xbe,0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x92, +0x21,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x39,0xea,0xe4,0x7a,0xb3,0x39,0x9c,0xda,0x3b, +0x22,0x7e,0x37,0x2b,0x7, 0xbe,0x35,0x2b,0x22,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x49, +0x35,0x1f,0x34,0x2, 0x21,0x15,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35, +0xb, 0x1a,0x20,0x22,0x7e,0xd, 0x27,0x2d,0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35, +0x1f,0x34,0x5, 0x2d,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x2a,0x6e,0xa, +0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xbe,0x1b,0xfd,0x6c,0xdd, +0x12,0x93,0xf, 0x7a,0xb3,0x1f,0x6c,0x6c,0xcc,0x80,0x4a,0x12,0x92,0xfe,0x78,0x43, +0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x21,0x15, +0x7d,0x13,0x7d,0x3e,0x12,0x21,0x15,0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f, +0x8, 0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, +0x7d,0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x6c,0x4, 0x7a, +0xb3,0x1f,0x6c,0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c,0x38,0xae,0x7e,0x73,0x1f, +0x6c,0x4c,0x77,0x68,0x1d,0x12,0x94,0x1a,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80,0xa, +0x12,0x92,0xfe,0x78,0x3, 0x12,0x94,0x5, 0xb, 0xc0,0x7e,0x73,0x2a,0x70,0xbc,0x7c, +0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0x41,0x70,0xda,0x3b,0x22,0xa, 0xec, +0x9, 0x7e,0x2a,0xdc,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22,0x7e, +0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x23, +0x0, 0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e, +0x73,0x2a,0x6d,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x20,0xbe, +0x1b,0xfd,0x6c,0xdd,0x12,0x93,0xf, 0x7a,0xb3,0x1f,0x34,0x6c,0xcc,0x80,0x4f,0x12, +0x93,0xf5,0x40,0x48,0x12,0x93,0xeb,0x50,0x43,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d, +0x35,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x21,0x15,0x7d,0x3, 0x7d,0x31,0x12,0x21,0x15, +0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15,0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, +0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a, +0x24,0x2f,0x41,0x7e,0xb3,0x1f,0x34,0x4, 0x7a,0xb3,0x1f,0x34,0xb, 0xc0,0x12,0x47, +0x61,0x38,0xac,0x7e,0x73,0x1f,0x34,0x4c,0x77,0x68,0x34,0x12,0x94,0x1a,0x8, 0x2, +0x7d,0x7f,0xbe,0x75,0x2a,0x8, 0x5, 0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5, +0x2a,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e,0x6c,0xcc,0x80,0xf, 0x12,0x93,0xf5,0x40,0x8, +0x12,0x93,0xeb,0x50,0x3, 0x12,0x94,0x5, 0xb, 0xc0,0x12,0x47,0x61,0x38,0xec,0xb, +0xd0,0xbe,0xd0,0x3, 0x50,0x2, 0x61,0x44,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d, +0xa5,0xe7,0xbc,0xab,0x22,0xa, 0xec,0x9, 0xae,0x2a,0xb9,0x7c,0x1d,0x2e,0x10,0x2c, +0xa5,0xe7,0xbc,0xab,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0, +0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b,0x1a,0xe0,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14, +0x12,0x1f,0x58,0x7d,0x73,0x12,0x21,0x15,0x7d,0xe3,0x7d,0x3f,0x12,0x21,0x15,0xbd, +0x3e,0x22,0x74,0xc8,0x7a,0xb3,0x39,0xf7,0xc2,0x1b,0x80,0xa, 0x12,0x29,0x18,0x30, +0x1b,0x4, 0x75,0xe9,0xff,0x22,0x12,0x94,0x79,0x68,0xf1,0x22,0x74,0x1, 0x12,0x94, +0x6b,0x20,0x1b,0x6, 0x12,0x29,0x90,0x12,0x94,0x74,0x7e,0xb3,0x33,0xea,0xb4,0x1, +0x6, 0x12,0x94,0x32,0x12,0x94,0x74,0xe4,0x2, 0x94,0x6b,0xbe,0xb0,0x8, 0x50,0x3, +0x12,0x94,0x8a,0x22,0xd2,0x1, 0x2, 0x28,0xc7,0x7e,0xb3,0x33,0xea,0xbe,0xb0,0x1, +0x22,0x12,0x94,0x79,0x68,0xfb,0x20,0x93,0xfd,0x22,0xa, 0x5b,0x2e,0x54,0x0, 0x8, +0xf5,0xcc,0x22,0xa9,0xc4,0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x94, +0x8a,0xa9,0xd0,0xce,0xa9,0xc0,0xc9,0xd2,0x2, 0x12,0x28,0xd8,0xa9,0xc2,0xea,0x75, +0xc1,0x6, 0x75,0xc2,0xc, 0xd2,0x0, 0x12,0x94,0xc4,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4, +0xa9,0xc2,0xe1,0x22,0xa2,0x0, 0xa9,0x97,0xc1,0xa2,0x0, 0xa9,0x97,0xc2,0x22,0x12, +0x26,0xc6,0x7e,0x73,0x3, 0x9e,0xbe,0x70,0xff,0x68,0x13,0xbe,0x73,0x3, 0xc4,0x68, +0xd, 0x7a,0x73,0x3, 0xc4,0x74,0xff,0x7a,0xb3,0x3, 0x9e,0x2, 0x26,0xc6,0x22,0x7e, +0x34,0x61,0x57,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x20,0x12,0x95,0xa, 0x50,0x8, 0x7e, +0x27,0x2a,0x4f,0x1e,0x24,0x1e,0x24,0x7d,0x32,0x22,0xc2,0x0, 0x12,0x95,0x32,0x68, +0x7, 0x7e,0xb3,0x2a,0x68,0xb4,0x1, 0x17,0x7e,0xb3,0x37,0xe5,0x70,0x11,0x12,0x4f, +0xfc,0x40,0xa, 0x7e,0x37,0x28,0x8a,0xbe,0x34,0x1, 0x90,0x58,0x2, 0xd2,0x0, 0xa2, +0x0, 0x22,0x7e,0xb3,0x2a,0x6b,0xbe,0xb0,0x1, 0x22,0x7c,0xab,0x7e,0xb3,0x39,0xfc, +0x70,0x17,0x7e,0xb3,0x28,0xa8,0x70,0x11,0x12,0x95,0x5a,0x68,0xc, 0x12,0x95,0x32, +0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x5f,0x7, 0x22,0x7e,0xb3,0x3, 0xef,0xbe,0xb0, +0x1, 0x22,0x12,0x95,0xa, 0x50,0x12,0x7e,0x37,0x2b,0x7, 0xbe,0x34,0x1, 0x2c,0x28, +0x8, 0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x2b,0x7, 0x22,0x7e,0xb3,0x39,0x9b,0x70,0x4, +0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x39,0x9b,0x22,0x7f,0x20,0xc2,0x1, 0x7e,0x2b, +0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x21,0x15,0x7c,0x27,0x29,0x72, +0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x21,0x15,0x7c,0x37,0x1a, +0x23,0x1a,0x32,0x9d,0x32,0x12,0x21,0x15,0x7c,0x67,0x7c,0x72,0xbc,0x32,0x58,0x2, +0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, 0x7e,0x37,0x39,0x8, +0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0xca,0x3b,0x7f,0x70,0x7c,0xe7,0x7c, +0xdb,0x7e,0xc0,0x4, 0x7e,0xb3,0x2a,0x6d,0xf5,0x28,0x7e,0xb3,0x2a,0x6e,0xf5,0x27, +0x7e,0x34,0x62,0x10,0x12,0x8e,0xf6,0x6c,0xff,0x12,0x86,0xe6,0x7f,0x51,0xe5,0x28, +0xa, 0x3b,0x1b,0x34,0xa, 0xcd,0xbd,0xc3,0x58,0x14,0xe5,0x27,0xa, 0x3b,0x1b,0x34, +0xa, 0xce,0xbd,0xc3,0x58,0x8, 0x4c,0xee,0x68,0x4, 0x4c,0xdd,0x78,0x3, 0x4e,0xf0, +0x10,0xb, 0x5a,0x30,0x7e,0x14,0x62,0x10,0x12,0x47,0xe0,0xbd,0x32,0x8, 0xc, 0x7e, +0x27,0x28,0x8a,0xbe,0x24,0x3, 0x20,0x8, 0x2, 0xe1,0x32,0xb, 0xa, 0xc0,0x1e,0xc4, +0xbd,0x3c,0x8, 0xc, 0x7e,0xc7,0x28,0x8a,0xbe,0xc4,0x3, 0x20,0x58,0x2, 0xe1,0x32, +0x6c,0xaa,0x7c,0x8d,0x80,0x1e,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x13,0x7e,0xb3,0x2a, +0x6d,0xbc,0xb8,0x8, 0xb, 0x12,0x97,0x69,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, +0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8,0xbd,0xc3,0x18,0xd6, +0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0xe1,0x32,0x6c,0xaa,0x7c,0x8d,0x80,0x1e,0x7c, +0x9e,0xbe,0x80,0x0, 0x48,0x13,0x7e,0xb3,0x2a,0x6d,0xbc,0xb8,0x8, 0xb, 0x12,0x97, +0x69,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a,0x2c,0x1a, +0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd6,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x2, +0x80,0x70,0x6c,0xaa,0x7c,0x9e,0x80,0x1e,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x13,0x7e, +0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0xb, 0x12,0x97,0x69,0xbd,0x3d,0x58,0x14,0xb, 0xa0, +0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3, +0x18,0xd6,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x37,0x6c,0xaa,0x7c,0x9e,0x80, +0x1e,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x13,0x7e,0xb3,0x2a,0x6e,0xbc,0xb9,0x8, 0xb, +0x12,0x97,0x69,0xbd,0x3d,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90,0x1a, +0x2c,0x1a,0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd6,0xbc,0xca,0x18,0x3, 0x4e, +0xf0,0x8, 0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b,0xd0, +0x29,0xb7,0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, 0x1, +0xbc,0xbe,0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38,0x4, +0x39,0xe7,0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x2, 0x4b,0x45, +0xca,0x3b,0x7c,0xc7,0x7c,0xfb,0x7f,0x40,0x6d,0x33,0x7a,0x35,0x24,0x7e,0xa3,0x2a, +0x6d,0x7e,0x73,0x2a,0x6e,0x4c,0xcc,0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7, +0x14,0xbc,0xbc,0x78,0x6, 0xa, 0x6c,0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e, +0xf0,0x1, 0x80,0xb, 0x7c,0xba,0x14,0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f, +0x4, 0x7e,0x34,0x0, 0x6, 0xe4,0x12,0x20,0xe3,0x7e,0x73,0x2a,0x6d,0xa, 0x37,0x1b, +0x34,0x7a,0x4b,0x70,0x7e,0x73,0x2a,0x6e,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, +0x7c,0xec,0x80,0x1f,0x75,0x26,0x0, 0x7c,0xdf,0x80,0xd, 0x12,0x98,0x96,0x12,0x95, +0xd9,0x70,0xa, 0x12,0x98,0x9d,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xee,0xe5,0x26,0x60, +0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xdc,0x7c,0xec,0x80,0x26,0x75,0x26,0x0, 0x1a, +0x3f,0xb, 0x34,0x7c,0xd7,0x80,0xd, 0x12,0x98,0x96,0x12,0x95,0xd9,0x70,0xd, 0x12, +0x98,0x9d,0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xeb,0xe5,0x26,0x60,0x7, +0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xd5,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x1f,0x75, +0x26,0x0, 0x7c,0xdf,0x80,0xd, 0x12,0x98,0x96,0x12,0x95,0xd9,0x70,0xa, 0x12,0x98, +0x9d,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xee,0xe5,0x26,0x60,0xa, 0xb, 0xe0,0x7e,0x73, +0x2a,0x6e,0xbc,0x7e,0x18,0xd9,0x1a,0x3c,0xb, 0x34,0x7c,0xe7,0x80,0x24,0x75,0x26, +0x0, 0x1a,0x6f,0xb, 0x64,0x80,0xd, 0x12,0x98,0x96,0x12,0x95,0xd9,0x70,0xd, 0x12, +0x98,0x9d,0xb, 0xd0,0x7e,0x73,0x2a,0x6d,0xbc,0x7d,0x18,0xeb,0xe5,0x26,0x60,0xa, +0xb, 0xe0,0x7e,0x73,0x2a,0x6e,0xbc,0x7e,0x18,0xd4,0x7e,0x35,0x24,0x7d,0x23,0x39, +0x54,0x0, 0x5, 0xda,0x3b,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0x22,0x5, 0x26,0x7e, +0x35,0x24,0xb, 0x34,0x7a,0x35,0x24,0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe,0xa0,0xa, +0x50,0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d,0x15,0xb, +0x14,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22,0x7c,0xbd, +0x7c,0x7e,0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a,0x7f, +0x70,0x2d,0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b,0xb0, +0xbc,0xb6,0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, 0x1, +0xbc,0xb7,0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x38, +0xc9,0xa2,0x1, 0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90,0x80,0x1f,0x29,0x86,0x0, +0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x98,0xd2,0x50,0x2, 0xd3,0x22, +0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, 0x90,0x29,0x76,0x0, 0x2, +0xbc,0x79,0x50,0xd9,0xc3,0x22,0x30,0x12,0x13,0x12,0x99,0x5d,0x68,0x6, 0x7e,0xb3, +0x39,0xfc,0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a,0x37,0x39,0x10,0x22,0x7e,0xb3,0x28, +0xa8,0xbe,0xb0,0x1, 0x22,0x6c,0xaa,0x7e,0x63,0x2a,0x6e,0x7e,0x73,0x2a,0x6d,0xac, +0x76,0x7d,0x13,0x1e,0x14,0x7e,0x27,0x28,0x88,0x2e,0x27,0x28,0x86,0xbd,0x21,0x38, +0xa, 0x1e,0x34,0x1e,0x34,0xbe,0x37,0x28,0x86,0x50,0x29,0x90,0x60,0x51,0xe4,0x93, +0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26,0xf7,0xa, 0x3b,0xbd,0x32,0x8, 0x16,0x90,0x60, +0x50,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x26,0xf6,0xa, 0x3b,0xbd,0x32,0x8, +0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7e,0xa3,0x2a,0x3, 0xbe,0xa0,0x0, 0x38,0x2f, +0xbe,0xa3,0x2a,0x2, 0x50,0x19,0x7e,0xb3,0x2a,0xc, 0xbe,0xb3,0x37,0x31,0x28,0x14, +0x7e,0xb3,0x37,0x31,0x4, 0x7a,0xb3,0x37,0x31,0x7a,0xa3,0x2a,0x2, 0x80,0x5, 0xe4, +0x7a,0xb3,0x37,0x31,0x7e,0xb3,0x2a,0x2, 0x70,0x5, 0xe4,0x7a,0xb3,0x2a,0xb, 0x22, +0x12,0x99,0xf6,0x2, 0x99,0xb7,0x7e,0xb3,0x2a,0x2, 0x70,0x29,0x12,0x9a,0x2f,0x28, +0x24,0x7e,0xb3,0x36,0xb6,0x70,0x18,0x12,0x9a,0x37,0x7e,0x73,0x2a,0x3, 0x7a,0x73, +0x2a,0x2, 0x74,0x1, 0x7a,0xb3,0x2a,0x9, 0x7e,0xb3,0x36,0xb6,0x4, 0x80,0x1, 0xe4, +0x7a,0xb3,0x36,0xb6,0x22,0xe4,0x7a,0xb3,0x36,0xb6,0x7a,0xb3,0x2a,0x9, 0x22,0x7e, +0x73,0x2a,0x3, 0xbe,0x70,0x0, 0x22,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e,0x18,0x33, +0x50,0x7e,0x8, 0x33,0x8c,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x73,0x28,0x94,0x7a,0x73, +0x33,0x48,0x7a,0x73,0x28,0x93,0x22,0x12,0x9a,0x2f,0x28,0x8, 0x7e,0xb3,0x28,0x84, +0x70,0x2, 0xf5,0x5d,0x7e,0xb3,0x28,0x84,0x70,0x18,0xe5,0x5d,0xbe,0xb0,0xfa,0x50, +0x2, 0x5, 0x5d,0xe5,0x5d,0xbe,0xb0,0x5, 0x40,0x8, 0xe4,0x7a,0xb3,0x2, 0xe9,0x75, +0x5d,0xfa,0x22,0xca,0x79,0xc2,0x0, 0x7e,0xf0,0x3, 0x12,0x9a,0x57,0x7e,0xe3,0x2a, +0x3, 0x7e,0x34,0x1f,0x34,0x7a,0x37,0x2, 0xab,0x12,0x9f,0xd4,0x38,0x2, 0x61,0x5f, +0x12,0xb7,0x6c,0x92,0xb, 0x12,0x9b,0x68,0x7c,0xbf,0x12,0x4b,0x4c,0x4c,0xee,0x68, +0xe, 0x7e,0xa3,0x2, 0x88,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x2, 0x89,0x70,0x4, 0xd2, +0x0, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x5e,0xbe,0xb0,0x8, 0x28,0x4, 0xd2, +0x0, 0x80,0x15,0xd2,0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xbe,0x78,0xb, 0x20,0xb, 0x8, +0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c,0xbf,0x12,0x4b,0x4c, +0x7e,0x8, 0x2, 0x8d,0x12,0x9b,0xdb,0x7a,0xb3,0x2, 0x8c,0xbe,0xb3,0x28,0x84,0x50, +0x3d,0x7e,0x33,0x2, 0x8c,0x80,0x29,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x2, 0xad, +0x9, 0x13,0x2, 0xae,0x2e,0x37,0x2, 0xab,0xb, 0x38,0x50,0x7e,0x93,0x2a,0x6e,0xac, +0x92,0xa, 0x31,0x2d,0x43,0x12,0xcc,0xd4,0x7c,0xb3,0x7e,0x70,0x1, 0x12,0x5f,0x7, +0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xcf,0x74,0x1, 0x7a,0xb3,0x2, 0x8a,0x7e,0xa3, +0x2, 0x8c,0x7a,0xa3,0x28,0x84,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x2, 0xad,0x7e, +0x8, 0x26,0xfa,0x12,0x20,0xbe,0x1b,0xfd,0x12,0xb5,0x96,0xf5,0x5e,0x80,0x6, 0x75, +0x5e,0x64,0x12,0x9f,0xef,0xda,0x79,0x22,0x6c,0xaa,0x12,0x9f,0xc8,0x12,0x9b,0x93, +0x7e,0xb, 0xb0,0x54,0xfe,0x12,0x9b,0x90,0x7e,0xb, 0xb0,0x54,0x7, 0x12,0x9b,0x90, +0x7e,0xb, 0xb0,0x54,0xfb,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xdb,0x22, +0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, 0x5, 0x22,0x6c,0xaa,0x12,0x9f,0xc8,0x29, +0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x12,0x9b,0x93,0x7c,0xb8,0x54, +0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13, +0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0, +0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xc2,0x22,0xca,0x3b,0x7f,0x40,0x7e, +0xe3,0x28,0x84,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, 0x3d,0x2d,0x39,0x7d,0x28, +0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, 0x70,0xbc,0x76,0x40,0x2, +0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0xa1,0x40,0x75,0x2d,0x0, 0x6d,0x33,0x7a,0x35,0x2e, +0x7a,0x35,0x25,0x7a,0x35,0x27,0x7e,0x18,0x1f,0x70,0x7a,0x1d,0x29,0x74,0xff,0x7e, +0x34,0x1f,0x71,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0,0x7e,0x1d,0x29,0x7a,0x1b,0xb0, +0xe4,0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x3, 0x7e,0x1d,0x29,0x39,0xb1,0x0, 0x2, 0x7e, +0x1d,0x29,0x12,0x9f,0x26,0x44,0x1, 0x7a,0x1b,0xb0,0x75,0x24,0x0, 0x80,0x6c,0x12, +0xcc,0x5a,0x9, 0x93,0x26,0xfb,0xe5,0x24,0x12,0x9f,0xe5,0xbc,0xbc,0x78,0x5a,0x5, +0x2d,0xa, 0x3a,0x2e,0x35,0x25,0x7a,0x35,0x25,0xa, 0x39,0x2e,0x35,0x27,0x7a,0x35, +0x27,0x12,0x4b,0x41,0xbe,0x35,0x2e,0x8, 0x6, 0x12,0x4b,0x41,0x7a,0x35,0x2e,0x7e, +0x1d,0x29,0x7e,0x1b,0xb0,0xbc,0xba,0x28,0x3, 0x7a,0x1b,0xa0,0x7e,0x1d,0x29,0x29, +0xb1,0x0, 0x2, 0xbc,0xba,0x50,0x4, 0x39,0xa1,0x0, 0x2, 0x7e,0x1d,0x29,0x29,0xb1, +0x0, 0x1, 0xbc,0xb9,0x28,0x4, 0x39,0x91,0x0, 0x1, 0x7e,0x1d,0x29,0x29,0xb1,0x0, +0x3, 0xbc,0xb9,0x50,0x4, 0x39,0x91,0x0, 0x3, 0x5, 0x24,0xbe,0xe1,0x24,0x38,0x8f, +0xe5,0x2d,0xbe,0xb0,0x0, 0x28,0x67,0x7e,0xd, 0x29,0x12,0x9d,0x56,0xe5,0x2d,0xa, +0x2b,0x7e,0x15,0x25,0x8d,0x12,0x7a,0x15,0x25,0x7e,0x35,0x27,0x8d,0x32,0x7a,0x35, +0x27,0x7e,0x55,0x25,0x12,0x9d,0x4e,0x19,0xa3,0x2, 0xad,0x7e,0x55,0x27,0x12,0x9d, +0x4e,0x19,0xa3,0x2, 0xae,0x7e,0x37,0x28,0x8a,0xbe,0x35,0x2e,0x78,0xe, 0x7e,0x35, +0x25,0x7a,0x73,0x28,0x8c,0x7e,0x35,0x27,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x2, 0xab, +0x4d,0x33,0x68,0x18,0x7e,0x55,0x25,0x7e,0x35,0x27,0x12,0x4b,0x45,0x7e,0x25,0x2e, +0x7e,0x70,0x2, 0xac,0x7f,0x2e,0x37,0x2, 0xab,0x1b,0x38,0x20,0xb, 0xf0,0xb, 0xc0, +0xbc,0xdc,0x40,0x2, 0x81,0x18,0x12,0x9b,0x9a,0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xab, +0x7e,0x70,0x2, 0xac,0x7f,0x22,0xca,0x79,0x7f,0x70,0x7e,0xb4,0xff,0xff,0x6c,0xee, +0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, 0x7e,0x7b,0x70,0xbc,0x76,0x78,0xe, 0x29, +0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78,0x2, 0xd2,0x2, 0x6c,0xff,0x12, +0x9f,0x2e,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1,0x2, 0xc1,0x10,0x7f,0x6, 0x7e, +0x7b,0xb0,0x12,0x9f,0x73,0x50,0x2d,0x7f,0x6, 0x29,0xb7,0x0, 0x2, 0x12,0x9f,0x73, +0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77,0x12,0x9f,0x3e,0x50,0x15,0x7f, +0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x9f,0x3e,0x50,0x8, 0x7c,0xef,0xd2,0x1, +0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e,0x7b,0x70,0x12,0x4f,0xe8,0x2d, +0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, 0x2, 0x12,0x4f,0xe8,0x2d,0xa3, +0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, 0x12,0x4f,0xe8,0x2d,0xa3,0x29, +0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12,0x4f,0xe8,0x2d,0xa3,0xbd,0xab, +0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, 0x38,0x4, 0xd2,0x1, 0x80,0x9, +0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0xa1,0x7f,0x20,0x1, 0xb, 0x20,0x2, 0x8, 0xbe, +0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, 0x2, 0xc1,0xd1,0x74,0x6, 0xac,0xbe, +0x12,0x9f,0x32,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xbe,0xb0,0x1f, +0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67,0x2e,0x60,0x8, 0x5e,0x60,0xf8, +0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x2, 0x11,0x29,0xb6,0x0, 0x4, 0xbe, +0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a,0x1b,0xb0,0x29,0x67,0x0, 0x3, +0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x3, 0x80,0x4, 0x29,0x77, +0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, 0x29,0x76,0x0, 0x2, 0xbc,0x76, +0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77,0x0, 0x2, 0x39,0x76,0x0, 0x2, +0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76,0x50,0x6, 0x29,0x76,0x0, 0x1, +0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, 0x7e,0x7b,0x60,0x7e,0x6b,0x70, +0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e,0x7b,0x70,0x7a,0x6b,0x70,0x80, +0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x2, 0xef,0x30,0xe1,0x7, 0xb, 0xf0, +0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x39,0x74,0x1, 0x39,0xb7,0x0, 0x4, +0x12,0x9f,0x2e,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f,0x17,0x7f,0x6, 0x12,0x20,0xbe, +0x1b,0xfd,0x7f,0x16,0x12,0x9f,0x26,0x44,0x1, 0x7a,0x1b,0xb0,0x7f,0x16,0x12,0x9f, +0x26,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x2, 0xa, 0x7f,0x16,0x12,0x9f,0x26,0x44,0x4, +0x7a,0x1b,0xb0,0xda,0x79,0x22,0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x74,0x6, +0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x2, 0xea,0x6d,0xcc,0x22,0x7e,0x70,0x1, 0x7c,0x87, +0x7c,0x9b,0x29,0xa0,0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, +0x78,0x7, 0x29,0xa0,0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, +0x16,0xbd,0x1, 0x48,0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3, +0x22,0xc3,0x22,0x7e,0x70,0x1, 0x2, 0x9f,0x3e,0xca,0x3b,0x12,0x9f,0xdc,0x75,0x54, +0x0, 0x7e,0xa1,0x54,0x74,0x6, 0xa4,0x12,0xb7,0xcc,0x30,0xe1,0x2e,0x7f,0x7, 0x7c, +0xbc,0x12,0x9f,0x73,0x50,0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x9f,0x3b,0x50,0x1c,0x7f, +0x7, 0x7c,0xbd,0x6c,0x77,0x12,0x9f,0x3e,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77, +0x12,0x9f,0x3e,0x50,0x6, 0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x54,0xe5,0x54,0xbe, +0xb0,0x1e,0x40,0xbd,0xe4,0xda,0x3b,0x22,0x7e,0x70,0x6, 0xac,0x7a,0x2e,0x34,0x2, +0xea,0x6d,0x22,0x22,0x7e,0x73,0x28,0x84,0xbe,0x70,0x1, 0x22,0x7c,0xf5,0x7c,0xe6, +0x7c,0xd7,0x7c,0xcb,0x22,0xa, 0x3b,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0x22,0x7e, +0x8, 0x2, 0xea,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x20,0xe3,0xca,0x3b,0x6d,0x11,0x7d, +0x1, 0x7e,0xe3,0x2a,0x2, 0x4c,0xee,0x78,0x23,0x6c,0xff,0x80,0x1a,0x74,0x2, 0xac, +0xbf,0x12,0xa1,0xcc,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x36,0xbb,0x74,0x2, 0xa, +0x3f,0x19,0xb3,0x37,0x25,0xb, 0xf0,0x12,0x53,0x30,0x38,0xe1,0x12,0xa2,0x62,0x7e, +0x24,0x0, 0x14,0xad,0x32,0x7d,0x43,0x2e,0x44,0x3, 0x20,0x6c,0xff,0x21,0xa5,0x74, +0x9, 0xac,0xbf,0x9, 0xd5,0x28,0xb2,0x5e,0xd0,0xf, 0x12,0xa1,0xe6,0x38,0x2, 0x21, +0xa3,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0xbe,0xb0,0x1, 0x78,0x2, 0x21,0x89,0x75,0x24, +0x0, 0x21,0x7b,0x7e,0x31,0x24,0x74,0x9, 0xac,0x3b,0x9, 0xc1,0x36,0xbb,0xbc,0xcd, +0x68,0x2, 0x21,0x79,0x7e,0xa3,0x2a,0x70,0x74,0x40,0xa4,0x9e,0x54,0x0, 0x20,0x7e, +0x34,0x60,0xd1,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0xf0,0x2d,0xf5,0x49,0x21,0x36,0xb9, +0xbd,0x2f,0x28,0x9, 0x12,0xa1,0xdd,0xbd,0x3f,0x38,0x2, 0x21,0x25,0x12,0xa1,0xdd, +0x9d,0x32,0x12,0x21,0x15,0x7d,0x3, 0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x49,0x25,0x36, +0xb7,0x12,0xa4,0xfe,0x9d,0x32,0x12,0x21,0x15,0x2d,0x3, 0xa, 0x1c,0x9, 0xa1,0x37, +0x25,0xbe,0xa0,0x0, 0x28,0x17,0x7e,0x30,0x2, 0xac,0x3c,0x59,0x1, 0x37,0x11,0xa, +0x1c,0x2e,0x14,0x37,0x25,0x7c,0xba,0x14,0x7a,0x19,0xb0,0x21,0xa3,0x74,0x2, 0xac, +0xbc,0x49,0x15,0x37,0x11,0xbe,0x14,0x0, 0x32,0x28,0x8, 0x7d,0xe1,0x2d,0xe4,0xbd, +0xe0,0x40,0x20,0xbe,0x14,0x0, 0x32,0x28,0x8, 0xbe,0x4, 0x0, 0x32,0x28,0x2, 0x80, +0x72,0x7d,0xe1,0x2e,0xe4,0x0, 0x32,0xbd,0xe0,0x50,0x8, 0xbe,0x14,0x0, 0x32,0x28, +0x2, 0x80,0x60,0xbe,0x4, 0x0, 0xa0,0x28,0x56,0xa, 0x1d,0x9, 0xb1,0x29,0xbc,0x70, +0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, 0xa, 0x1d,0x19,0xb1,0x29,0xbc,0x74,0x3, 0xa, +0x1c,0x19,0xb1,0x29,0xc6,0xbe,0xe0,0x0, 0x28,0x69,0x1b,0xe0,0x7e,0x70,0x9, 0xac, +0x7f,0x2e,0x34,0x28,0xae,0x7e,0x14,0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0x7e,0x70, +0x9, 0xac,0x7e,0x12,0xa4,0xee,0xac,0x3f,0x12,0xa1,0xd4,0x7e,0x34,0x1f,0x34,0x7e, +0x30,0x9, 0xac,0x3e,0x12,0xa1,0xd4,0x1b,0xf0,0x74,0x2, 0xac,0xbc,0x80,0x4, 0x74, +0x2, 0xac,0xbc,0x59,0x5, 0x37,0x11,0x80,0x2a,0x5, 0x24,0x90,0x60,0x99,0xe4,0x93, +0xbe,0xb1,0x24,0x28,0x2, 0x1, 0x63,0x80,0x1a,0x6d,0x11,0x74,0x2, 0xac,0xbd,0x12, +0xa1,0xcc,0x7e,0x30,0x9, 0xac,0x3d,0x19,0xa1,0x36,0xbb,0x74,0x2, 0xa, 0x1d,0x19, +0xb1,0x37,0x25,0xb, 0xf0,0xbc,0xef,0x28,0x2, 0x1, 0x3f,0xe4,0x7a,0xb3,0x16,0x92, +0x90,0x60,0x99,0x12,0xa2,0xea,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x36,0xb7, +0x12,0x20,0xbe,0x1b,0xfd,0x7a,0xe3,0x2a,0x2, 0xda,0x3b,0x22,0x59,0x15,0x37,0x11, +0x7e,0xa0,0xff,0x22,0x2e,0x14,0x28,0xae,0x74,0x9, 0x2, 0x1f,0x8c,0x74,0x9, 0xac, +0xbf,0x49,0x35,0x28,0xb0,0x22,0x90,0x60,0x99,0xe4,0x93,0xbc,0xbd,0x22,0xca,0x3b, +0x7c,0xfb,0x6c,0xee,0x80,0x65,0x6c,0xdd,0x80,0x16,0x74,0x9, 0xac,0xbd,0x9, 0x65, +0x29,0x66,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x28,0xb2,0xbc,0x67,0x68,0x7, 0xb, 0xd0, +0x12,0xa1,0xe6,0x38,0xe5,0x12,0xa1,0xe6,0x28,0x45,0x74,0x9, 0xac,0xbd,0x9, 0xc5, +0x29,0x66,0x12,0x33,0xc5,0x74,0x9, 0xac,0xbd,0x12,0xa5,0x13,0x9d,0x32,0x12,0x21, +0x15,0x2d,0x31,0x7a,0x35,0x24,0xa, 0x3c,0x9, 0xb3,0x29,0xbc,0xb4,0x1, 0xe, 0x6d, +0x33,0x74,0x2, 0xac,0xbc,0x59,0x35,0x36,0x7f,0x59,0x35,0x36,0xa2,0x7e,0x35,0x24, +0x7c,0xbd,0x7c,0x5e,0x7c,0x4c,0x12,0x0, 0x66,0xb, 0xe0,0xbc,0xfe,0x38,0x97,0xda, +0x3b,0x22,0x7e,0x73,0x2a,0x3, 0xbe,0x73,0x2a,0x2, 0x78,0x13,0x12,0xa4,0xf6,0x40, +0xe, 0x7e,0x37,0x36,0x93,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, 0x7e, +0x37,0x36,0x93,0x1e,0x34,0x7a,0x37,0x36,0x93,0x7e,0xb3,0x2a,0x2, 0x70,0x6, 0x6d, +0x33,0x7a,0x37,0x36,0x93,0x7e,0x37,0x36,0x93,0x22,0xca,0x79,0x7e,0xf3,0x2a,0x2, +0x7e,0xe3,0x2a,0x3, 0x7c,0xbf,0x7c,0x7e,0x12,0xa2,0xf1,0x7c,0xbf,0x12,0xa3,0x8b, +0x4c,0xee,0x78,0x14,0x12,0xa2,0xe6,0xca,0x59,0x7e,0x18,0x28,0xae,0x7e,0x8, 0x29, +0x62,0x12,0x20,0xbe,0x1b,0xfd,0x80,0xb, 0x7e,0xb3,0x2a,0x9, 0x70,0x5, 0x7c,0xbf, +0x12,0xa1,0xee,0x7c,0xbf,0x12,0xa5,0x20,0xbe,0xf0,0x0, 0x28,0x6, 0x74,0x1, 0x7a, +0xb3,0x2a,0xb, 0xda,0x79,0x22,0x90,0x60,0x99,0xe4,0x93,0x7c,0xab,0x74,0x9, 0xa4, +0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, 0x74,0x1, +0x7a,0xb3,0x2a,0x7, 0xe4,0x7a,0xb3,0x2a,0x9, 0x7a,0xb3,0x2a,0xa, 0x2, 0xa3,0x66, +0xa5,0xbe,0x0, 0x1d,0x6c,0xaa,0x80,0xe, 0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a, +0x19,0x62,0x29,0x66,0xb, 0xa0,0x12,0x53,0x21,0x38,0xed,0x74,0x1, 0x7a,0xb3,0x2a, +0x6, 0x6c,0xaa,0x80,0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xae,0x12,0xa3, +0x5a,0x1b,0x18,0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x28,0xb0,0x12,0xa3,0x5a, +0x1b,0x18,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xdc,0x22,0xb, 0x18,0x20,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x22,0x12,0xa3,0x7f,0x7e,0x8, 0x36,0xa2,0xe4,0x12,0x20, +0xe3,0x90,0x60,0x99,0x12,0xa3,0x83,0x7e,0x8, 0x36,0x7f,0xe4,0x2, 0x20,0xe3,0x90, +0x60,0x99,0xe4,0x93,0x7c,0x7b,0x74,0x2, 0xac,0x7b,0x22,0xca,0xd8,0xca,0x79,0x7c, +0xdb,0x90,0x60,0x99,0xe4,0x93,0x7c,0xfb,0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74, +0x9, 0xac,0xb1,0x19,0x5, 0x1f,0x38,0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59, +0x35,0x1f,0x34,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1f,0x36,0xb, 0x10,0xbc,0xf1,0x38, +0xdb,0xe4,0x6c,0x77,0x7c,0x6d,0x12,0xa4,0xe4,0x7c,0x7d,0x7c,0x6f,0x12,0xa4,0xe4, +0x6c,0x0, 0x80,0x39,0x6c,0xee,0x80,0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1f,0x38, +0x74,0x9, 0xac,0xb0,0x9, 0x75,0x28,0xb2,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e, +0x38,0xe6,0xbc,0x1e,0x78,0x15,0x7e,0x70,0x9, 0xac,0x70,0x12,0xa4,0xee,0xac,0x31, +0x2e,0x14,0x1f,0x34,0x74,0x9, 0x12,0x1f,0x8c,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38, +0xc3,0x74,0x9, 0xac,0xbf,0xca,0x59,0x7e,0x18,0x1f,0x34,0x7e,0x8, 0x29,0x62,0x12, +0x20,0xbe,0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c, +0x66,0x81,0xcc,0x7c,0x57,0x81,0xc4,0x7e,0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x29,0x66, +0x7c,0x98,0x7e,0xd0,0x9, 0xac,0xd5,0x9, 0xb6,0x28,0xb2,0xbc,0xb9,0x78,0x73,0xbe, +0x90,0xff,0x68,0x6e,0x12,0xa4,0xdc,0x2d,0xf7,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, +0xbf,0x29,0xbc,0x7e,0xf0,0x9, 0x70,0xc, 0xac,0xf5,0x7d,0x97,0x2e,0x94,0x28,0xae, +0x6d,0x88,0x80,0xa, 0xac,0xf6,0x7d,0x97,0x2e,0x94,0x29,0x62,0x6d,0x88,0xb, 0x4a, +0xd0,0x12,0xa4,0xdc,0x2d,0xf7,0x1b,0x7a,0xd0,0x69,0xf4,0x0, 0x2, 0x7e,0xf0,0x9, +0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, +0x87,0x28,0xb3,0x12,0xa4,0xdc,0x2d,0xf7,0x39,0x87,0x0, 0x5, 0x7e,0xf0,0x9, 0xac, +0xf5,0x9, 0x87,0x28,0xb4,0x12,0xa4,0xdc,0x2d,0xf7,0x39,0x87,0x0, 0x6, 0xb, 0xa0, +0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0x81,0x37,0xb, 0x60,0x90,0x60,0x99,0xe4, +0x93,0xbc,0xb6,0x28,0x2, 0x81,0x33,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac, +0xfa,0x7f,0x70,0x22,0x7e,0x8, 0x1f,0x34,0x12,0xa4,0x29,0x7c,0x1b,0x22,0x2e,0x34, +0x28,0xae,0x7e,0x30,0x9, 0x22,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x1, 0x22,0x74,0x9, +0xac,0xbf,0x49,0x35,0x28,0xae,0x22,0x7e,0xb3,0x3, 0xef,0x70,0x3, 0x12,0x9f,0xfb, +0x2, 0xa2,0x9a,0x49,0x25,0x29,0x62,0x74,0x9, 0xac,0xbe,0x49,0x35,0x28,0xae,0x22, +0x6c,0xaa,0x80,0x49,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x62,0x12,0x25,0x5a, +0x59,0x32,0x28,0xae,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x29,0x64,0x12,0x25,0x5a, +0x59,0x32,0x28,0xb0,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x66,0x19,0xb4,0x28, +0xb2,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x67,0x19,0xb4,0x28,0xb3,0x7e,0x90, +0x9, 0xac,0x9a,0x9, 0xb4,0x29,0x68,0x19,0xb4,0x28,0xb4,0xb, 0xa0,0x12,0x53,0x21, +0x38,0xb2,0x22,0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, +0x74,0x36,0x96,0xbe,0x73,0x36,0xa0,0x50,0xe, 0x7d,0x24,0x2e,0x24,0x36,0x96,0x7c, +0xb7,0x4, 0x7a,0x29,0xb0,0xd3,0x22,0xbe,0x73,0x36,0xa0,0x40,0x9, 0xbe,0x70,0xff, +0x68,0x4, 0xe4,0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4,0x36,0x96,0x80,0x17,0xa, 0x3a, +0x9, 0xb3,0x36,0x96,0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x36,0x96,0xd3,0x22, +0xe4,0x19,0xb3,0x36,0x96,0xc3,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3,0x7e,0x17,0x2a, +0x62,0xbd,0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22,0x7c,0x56,0x7c, +0x67,0x6c,0x77,0x12,0x1f,0x5, 0xbe,0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10, +0x74,0x2, 0xac,0xbf,0x49,0x25,0x36,0xa2,0xbd,0x2f,0x28,0x6, 0x49,0x35,0x36,0x7f, +0x80,0x4, 0x59,0x35,0x36,0x7f,0x59,0xf5,0x36,0xa2,0xbe,0x34,0x1, 0x0, 0x28,0x4, +0x7e,0x34,0x1, 0x0, 0xda,0xf8,0x22,0x7e,0x8, 0x36,0x95,0x7e,0x34,0x0, 0xd, 0xe4, +0x2, 0x20,0xe3,0x6c,0x0, 0x6c,0x11,0x80,0x16,0x7c,0xb1,0x12,0x4f,0xc5,0x60,0xd, +0x12,0xa6,0x83,0x12,0xa6,0x94,0x40,0x5, 0x7e,0x0, 0x1, 0x80,0xa, 0xb, 0x10,0x7e, +0x73,0x28,0x84,0xbc,0x71,0x38,0xe2,0x7c,0xb0,0x6c,0x77,0x12,0xa6,0xae,0xbe,0x0, +0x1, 0x68,0xb, 0x7c,0xb0,0x7e,0x70,0x1, 0x12,0xa6,0xae,0xb4,0x1, 0x24,0x6c,0x11, +0x80,0x18,0x7c,0xb1,0x12,0x4f,0xc5,0x60,0xf, 0x12,0xa6,0x83,0x12,0xa6,0x94,0x50, +0x7, 0x7c,0xb1,0x6c,0x77,0x12,0x5f,0x7, 0xb, 0x10,0x7e,0x3, 0x28,0x84,0xbc,0x1, +0x38,0xe0,0x22,0x74,0x2, 0xac,0xb1,0x9, 0x25,0x26,0xfa,0x9, 0x35,0x26,0xfb,0x7c, +0xb2,0x7c,0x73,0x22,0x7c,0xa7,0x7c,0x7b,0x90,0x60,0xaa,0xe4,0x93,0x60,0x2, 0x7c, +0xa7,0x90,0x60,0xab,0xe4,0x93,0xbc,0xba,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x7c,0xab, +0xa5,0xbf,0x0, 0xc, 0x7e,0xb3,0x33,0xc8,0x7a,0xb3,0x33,0xc9,0x7a,0xa3,0x33,0xc8, +0x7e,0xb3,0x33,0xc9,0x60,0x4, 0x74,0x8, 0x80,0xd, 0x7e,0xb3,0x28,0x84,0x70,0xb, +0x7e,0xb3,0x33,0xca,0x60,0x5, 0x14,0x7a,0xb3,0x33,0xca,0x7e,0x73,0x33,0xca,0xbe, +0x70,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xd8,0xca,0x79,0x7e,0xd4,0x0, +0x6, 0x7e,0xb3,0x28,0x84,0x70,0x15,0x12,0xa8,0xd8,0xc2,0x13,0x9f,0x11,0x7a,0x1d, +0x18,0x12,0xa8,0xe1,0xe4,0x7a,0xb3,0x33,0x49,0x2, 0xa8,0xbd,0xe4,0x7a,0xb3,0x33, +0x49,0x6c,0xdd,0x2, 0xa8,0x7c,0x7e,0x73,0x33,0x49,0xbe,0x70,0x2, 0x40,0x21,0x7c, +0xfd,0x80,0x15,0x7e,0x18,0x0, 0x1, 0x7c,0xbf,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb, +0x12,0xcc,0x27,0x7a,0x1d,0x18,0xb, 0xf0,0x12,0x67,0xe2,0x38,0xe6,0x2, 0xa8,0x87, +0x7e,0x44,0x0, 0xff,0x6c,0xff,0x80,0x36,0xbc,0xdf,0x68,0x30,0x74,0x2, 0xac,0xbf, +0x9, 0x75,0x26,0xfa,0xa, 0x27,0x12,0xa8,0xc2,0x12,0x4f,0xe8,0xbe,0x34,0x0, 0x4, +0x58,0x1a,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x26,0xfb,0xa, 0x27,0x12,0xa8,0xcf,0x12, +0x4f,0xe8,0xbe,0x34,0x0, 0x4, 0x58,0x4, 0x6d,0x44,0x80,0x7, 0xb, 0xf0,0x12,0x67, +0xe2,0x38,0xc5,0x4d,0x44,0x78,0x13,0x12,0xcc,0xa7,0x60,0x5, 0x2f,0x11,0x14,0x78, +0xfb,0x12,0xcc,0x27,0x7a,0x1d,0x18,0x2, 0xa8,0x7a,0x7c,0xbd,0x12,0xb6,0xb0,0x1a, +0x4b,0x7c,0xbd,0x12,0x5e,0x76,0x7d,0xc3,0xbe,0xc4,0x2, 0x58,0x58,0x4, 0x7e,0xd4, +0x0, 0x5, 0xbd,0xd4,0x58,0x12,0x12,0xcc,0xa7,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb, +0x4e,0x35,0x1a,0x4e,0x25,0x18,0x80,0x15,0x7d,0x5d,0x1b,0x55,0xbd,0x54,0x48,0x10, +0x12,0xcc,0xa7,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x12,0xcc,0x27,0x7a,0x1d,0x18, +0x12,0xcc,0xa7,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x12,0xcc,0x2f,0xbe,0x18,0x0, +0x0, 0x28,0x2d,0x7e,0x24,0x1, 0x90,0x7e,0xa3,0x33,0x49,0x7c,0xba,0x3e,0xb0,0x24, +0x14,0xa, 0x3b,0x1b,0x38,0x20,0xa, 0x5a,0x19,0xd5,0x33,0x4a,0x12,0xa8,0xc2,0x7e, +0x63,0x33,0x49,0xa, 0x56,0x12,0xa8,0xcb,0x7e,0x63,0x33,0x49,0xa, 0x56,0x80,0x3b, +0x7e,0x73,0x33,0x4a,0xbc,0x7d,0x68,0x8, 0x7e,0x63,0x33,0x4b,0xbc,0x6d,0x78,0x4a, +0xbc,0x7d,0x78,0x4, 0x6c,0xee,0x80,0x3, 0x7e,0xe0,0x1, 0x7c,0xbe,0x3e,0xb0,0x24, +0x14,0xa, 0x3b,0xb, 0x38,0x50,0xbe,0x54,0x0, 0x0, 0x28,0x1e,0x1b,0x54,0x1b,0x38, +0x50,0x12,0xa8,0xc2,0xa, 0x5e,0x12,0xa8,0xcb,0xa, 0x5e,0x19,0x75,0x33,0x4e,0x7e, +0xb3,0x33,0x49,0x4, 0x7a,0xb3,0x33,0x49,0x80,0x10,0x74,0xff,0xa, 0x3e,0x19,0xb3, +0x33,0x4a,0x19,0xb3,0x33,0x4c,0x19,0xb3,0x33,0x4e,0xb, 0xd0,0x7e,0x73,0x28,0x84, +0xbc,0x7d,0x28,0x3, 0x2, 0xa7,0x16,0x7e,0xa3,0x33,0x49,0xbe,0xa0,0x0, 0x28,0x25, +0x20,0x13,0x8, 0xd2,0x13,0x74,0x14,0x7a,0xb3,0x36,0x7d,0xbe,0xa0,0x1, 0x78,0x1d, +0x74,0xff,0x7a,0xb3,0x33,0x4b,0x7a,0xb3,0x33,0x4d,0x7a,0xb3,0x33,0x4f,0x6d,0x33, +0x7a,0x35,0x16,0x80,0x8, 0xc2,0x13,0x12,0xa8,0xe1,0x12,0xa8,0xd8,0xda,0x79,0xda, +0xd8,0x22,0x74,0x2, 0xac,0xbd,0x9, 0x75,0x26,0xfa,0x22,0x19,0x75,0x33,0x4c,0x74, +0x2, 0xac,0xbd,0x9, 0x75,0x26,0xfb,0x22,0x6d,0x33,0x7a,0x35,0x16,0x7a,0x35,0x14, +0x22,0x7e,0x8, 0x33,0x4a,0x7e,0x34,0x0, 0x6, 0x74,0xff,0x2, 0x20,0xe3,0xe4,0x7a, +0xb3,0x37,0x5a,0x7e,0xb3,0x28,0x84,0x60,0x6, 0x7e,0xb3,0x37,0xd3,0x60,0x5, 0xe4, +0x7a,0xb3,0x37,0xd5,0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x2a,0x4f,0x12,0xa9,0x4e,0x28, +0x35,0x6d,0x22,0x9d,0x23,0xbe,0x27,0x7, 0xf8,0x58,0x2b,0x12,0x5f,0xf8,0xbe,0x37, +0x7, 0xfa,0x8, 0x22,0xe4,0x7a,0xb3,0x28,0x84,0x7e,0xb3,0x2a,0x3, 0x70,0x17,0x7e, +0xb3,0x3, 0xc6,0xb4,0x1, 0x10,0x6c,0xaa,0x5, 0x62,0xe5,0x62,0xbe,0xb0,0x10,0x28, +0x5, 0xd2,0x14,0x75,0x62,0x0, 0x4c,0xaa,0x68,0x3, 0x75,0x62,0x0, 0x22,0x7e,0xb3, +0x28,0x84,0xbe,0xb0,0x0, 0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12,0x5e, +0x76,0xbe,0x34,0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x28,0x84,0xbc, +0x78,0x38,0xe9,0xbe,0x90,0x1, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0x7c,0x6b,0x7e,0xa3, +0x37,0x5a,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x37,0x97,0x19,0x72,0x37,0x98,0x7c, +0xba,0x4, 0x7a,0xb3,0x37,0x5a,0x22,0x12,0x77,0xa9,0x12,0x4f,0xf9,0x12,0xa9,0xb0, +0x90,0x60,0xa7,0xe4,0x93,0x60,0x8, 0x30,0x15,0x5, 0x12,0x59,0x65,0xc2,0x15,0x22, +0x12,0x4f,0xfc,0x40,0xb, 0x12,0x24,0x32,0xe4,0x7a,0xb3,0x3, 0xfe,0x2, 0x76,0x90, +0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x70,0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e, +0x34,0x23,0x4, 0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x34,0x74,0xc, 0x12,0x1f,0xad, +0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c,0xee,0x80,0x13,0x12,0xaa,0xd5,0x7d,0xc3,0xbd, +0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, 0x28,0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38, +0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, 0x7e,0xb3,0x28,0x94,0x70,0x4, 0x6d,0x33,0x41, +0xc6,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, 0xd2,0x0, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49, +0x45,0x1f,0x34,0xbd,0x4d,0x58,0x6, 0x49,0xd5,0x1f,0x36,0x80,0x7, 0xb, 0xe0,0xbe, +0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, 0x78,0x4, 0x6d,0x33,0x41,0xc6,0xbd,0xd, 0x8, +0x5, 0x30,0x0, 0x2, 0x7d,0xd0,0x9f,0x55,0x6c,0xee,0x80,0xb, 0x12,0xaa,0xd5,0x1a, +0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0,0xbc,0xfe,0x38,0xf1,0xa, 0x1f,0x12,0xaa,0xcb, +0x9f,0x55,0x6c,0xee,0x80,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a, +0x90,0x7d,0x39,0x12,0x21,0x15,0x7d,0xc3,0xbd,0x1c,0x28,0xa, 0x7d,0x39,0x1a,0x26, +0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xda,0x6d,0x11,0xbe,0xd0, +0x0, 0x28,0x5, 0xa, 0x1d,0x12,0xaa,0xcb,0xbd,0x1d,0x8, 0x4, 0x7d,0x1d,0x80,0xa, +0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c,0xee,0x80,0x12,0x74,0x2, +0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0, +0xbc,0xfe,0x38,0xea,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x6d,0x0, 0x7f,0x15,0x12, +0x1f,0x58,0x7d,0x13,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30, +0x2, 0x21,0x15,0xca,0xf8,0x7f,0x71,0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x7f,0xc2,0x0, +0x6d,0x44,0x80,0x1e,0x7d,0xc4,0x3e,0xc4,0x7f,0x17,0x2d,0x3c,0x12,0xaa,0xdd,0xbd, +0x3d,0x48,0xd, 0x7d,0x34,0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x12,0xaa,0xdd,0x7d,0xd3, +0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4,0x38,0xdb,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, +0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd, +0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34,0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d, +0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e, +0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb,0x7c,0xb7,0x12,0xac,0xb1,0xb, 0x44, +0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda,0xf8,0x22,0xca,0x3b,0x7a,0xd, 0x2e,0x7c, +0xcb,0x7e,0xb3,0x2b,0x1d,0xf5,0x32,0x7e,0xb3,0x2b,0xf, 0xf5,0x33,0x7e,0xd3,0x2b, +0x14,0x7e,0xe3,0x2b,0x1f,0x7e,0xf3,0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e, +0x18,0x34,0x0, 0x7e,0x8, 0x24,0xf2,0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x34,0x0, 0x8c, +0xca,0x39,0x7e,0x18,0x32,0xba,0x7e,0x8, 0x25,0x2a,0x12,0x20,0xbe,0x1b,0xfd,0x7c, +0xbc,0x12,0xac,0xdf,0x74,0x1, 0x7a,0xb3,0x2b,0x1d,0x74,0x5, 0xac,0xbc,0x12,0x6f, +0x14,0x74,0x5, 0xac,0xbc,0x12,0x6f,0x2, 0x74,0x5, 0xac,0xbc,0x12,0x6f,0xb, 0x74, +0x5, 0xac,0xbc,0x9, 0x75,0x26,0x37,0xbe,0x73,0x2b,0x62,0x68,0x6, 0x7a,0x73,0x2b, +0x62,0xd2,0xe, 0xc2,0x0, 0x12,0x7f,0xc5,0x12,0x6c,0xce,0x12,0x45,0x3f,0x12,0x0, +0x4e,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d,0x31,0x7e, +0x2f,0x13,0x86,0x7d,0x25,0x7e,0x4, 0xd, 0xc8,0x12,0x46,0x2d,0x12,0x7f,0xce,0x7a, +0x55,0x34,0x7e,0xd, 0x2e,0x7e,0x18,0xd, 0xc8,0x12,0xaa,0xe3,0x12,0xac,0x60,0xe5, +0x32,0x7a,0xb3,0x2b,0x1d,0xe5,0x33,0x7a,0xb3,0x2b,0xf, 0x7a,0xd3,0x2b,0x14,0x7a, +0xe3,0x2b,0x1f,0x7a,0xf3,0x2b,0x20,0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x24, +0xf2,0x7e,0x8, 0x34,0x0, 0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39, +0x7e,0x18,0x25,0x2a,0x7e,0x8, 0x32,0xba,0x12,0x20,0xbe,0x1b,0xfd,0xda,0x3b,0x22, +0x90,0x60,0x93,0xe4,0x93,0xa, 0xb, 0x7e,0x73,0x2a,0x71,0xa, 0x17,0x2d,0x10,0x7e, +0xa3,0x2a,0x6e,0xa, 0x3a,0xad,0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, 0x3, 0x2d, +0x2, 0x3e,0x4, 0x7e,0x7f,0x33,0xe4,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90,0x2, 0xac, +0x93,0x49,0xf4,0x13,0x8e,0x9d,0xf, 0x59,0x4, 0x25,0xb6,0xb, 0x30,0xbc,0xa3,0x38, +0xdc,0x7a,0x35,0x34,0x7e,0xf, 0x38,0x55,0x7e,0x18,0x25,0xb6,0x2, 0xaa,0xe3,0xa, +0x4a,0x7f,0x10,0x2d,0x34,0x7a,0x1b,0xb0,0x22,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3, +0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9, +0xe5,0xf6,0x12,0xac,0xaf,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xed,0xc2,0xc9,0x22,0xca, +0xf8,0x7c,0xfb,0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x2f,0xaa,0x6d, +0x22,0x7e,0x8, 0x34,0x0, 0x12,0x20,0xbe,0x1b,0xfd,0x7e,0x34,0x0, 0x8c,0xca,0x39, +0xac,0x7f,0x2e,0x34,0x30,0x8a,0x6d,0x22,0x7e,0x8, 0x32,0xba,0x12,0x20,0xbe,0x1b, +0xfd,0xda,0xf8,0x22,0x6c,0xaa,0x80,0x1f,0x7e,0x30,0x4, 0xac,0x3a,0x7d,0xf1,0x2e, +0xf4,0x60,0xb1,0x12,0xad,0x43,0xbd,0x23,0x38,0xb, 0x2e,0x14,0x60,0xb3,0x12,0x47, +0xe0,0xbd,0x23,0x50,0xb, 0xb, 0xa0,0x90,0x60,0xa7,0xe4,0x93,0xbc,0xba,0x38,0xd8, +0x7c,0xba,0x22,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x20,0x22,0x7e,0x63,0x2a,0x6f,0x7e, +0xa3,0x2a,0x70,0x7e,0x70,0x1, 0x80,0x25,0xa, 0x17,0x7e,0xb3,0x2a,0x6e,0xa, 0x2b, +0x2d,0x21,0x3e,0x24,0x49,0x12,0x4, 0xfc,0x7e,0xf4,0x61,0x59,0x12,0xad,0x43,0x6e, +0x24,0xff,0xff,0xb, 0x24,0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b, +0x14,0xa, 0x27,0xbd,0x21,0x48,0xd1,0x7e,0x70,0x2, 0x80,0x20,0x7e,0x50,0x2, 0xac, +0x57,0x49,0x12,0x4, 0xfc,0x7e,0xf4,0x61,0x5b,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x0, +0x6d,0x22,0x9d,0x20,0xbd,0x12,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15, +0xa, 0x27,0xbd,0x21,0x48,0xd6,0xc3,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e,0x6c,0xaa, +0x80,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x39,0xeb,0x2d,0xf0,0x69,0x27,0x1, +0x0, 0x69,0x37,0x0, 0x80,0x9d,0x32,0x12,0x21,0x15,0xbd,0x31,0x28,0x16,0x7e,0x70, +0x2, 0xac,0x7a,0x7e,0xf, 0x39,0xeb,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69,0x30,0x0, +0x80,0x12,0x33,0xd1,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x39,0xeb,0x2d,0x30,0x69, +0x1, 0x0, 0x80,0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69,0x1, 0x1, +0x0, 0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e,0xb3,0x2a, +0x74,0xbc,0xba,0x38,0x9d,0x7d,0x31,0x22,0x7e,0x8, 0x24,0xf2,0x7e,0x34,0x0, 0xc, +0xe4,0x12,0x20,0xe3,0x12,0xae,0x6e,0x12,0xae,0x65,0xa9,0xd1,0xcb,0x12,0x47,0xf0, +0x7a,0x37,0x24,0xf6,0x7e,0x1f,0x33,0xe4,0x7a,0x37,0x24,0xf8,0x7e,0x1f,0x13,0x86, +0x7a,0x37,0x24,0xfa,0x6d,0x33,0x12,0xae,0x5c,0x2, 0xd, 0x7, 0x7a,0x37,0x24,0xfc, +0x7e,0x8, 0x24,0xf2,0x22,0x7e,0x73,0x2a,0x6d,0x7a,0x73,0x24,0xf2,0x22,0x7e,0x73, +0x2a,0x6e,0x7a,0x73,0x24,0xf3,0x22,0x7a,0xb3,0x24,0xf2,0x7e,0x53,0x2a,0x6e,0x7a, +0x53,0x24,0xf3,0x7a,0x37,0x24,0xfa,0xe4,0x7a,0xb3,0x24,0xf4,0x7a,0xb3,0x24,0xf5, +0x7e,0x34,0x40,0x0, 0x7a,0x37,0x24,0xf6,0x7e,0x34,0x0, 0x20,0x12,0xae,0x5c,0x2, +0xd, 0x7, 0x12,0x6f,0xe5,0x7e,0x34,0xd, 0xc8,0x7e,0xb3,0x2a,0x6d,0x12,0xae,0x77, +0x12,0xae,0xbe,0x7a,0x37,0x33,0xe1,0x74,0x1, 0x7a,0xb3,0x16,0x91,0x22,0x6d,0x33, +0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xbf,0xe5,0x90,0x60,0x92, +0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xae,0xdb,0x22,0xca,0xf8,0x6d,0xee,0x7d, +0xfe,0x7e,0x83,0x2a,0x6e,0xa, 0xd8,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x2f,0x7e, +0x8, 0x13,0x8e,0x6c,0xaa,0x80,0x18,0x7e,0x70,0x2, 0xac,0x7a,0x49,0x23,0x13,0xfe, +0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0,0x9d,0xc2,0x59,0xc3,0x13,0xc6,0xb, 0xa0,0xbc, +0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4,0x93,0x7c,0x9b,0x6d,0xdd,0x80,0x11,0x7e,0x8, +0x13,0xfe,0x90,0x60,0x92,0xe4,0x93,0xa, 0xcb,0x1b,0xc4,0x7d,0x3c,0x7c,0x97,0x6c, +0xff,0x80,0x38,0x6c,0xaa,0x80,0x28,0xa, 0x3a,0x7d,0x23,0x2d,0x2e,0x3e,0x24,0x49, +0xc2,0x13,0xfe,0x2d,0x3d,0x3e,0x34,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xb0,0x7d,0x3c, +0x9d,0x3b,0x12,0x21,0x15,0x7d,0xa3,0xbd,0xfa,0x58,0x2, 0x7d,0xfa,0xb, 0xa0,0xbc, +0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec,0x2d,0xdc,0xb, 0xf0,0xbc,0x9f,0x38,0xc4,0x7d, +0x3f,0xda,0xf8,0x22,0x7e,0x60,0x4, 0x7e,0x27,0x39,0xf5,0xbe,0x24,0x3, 0xe8,0x28, +0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x28,0xac,0xb4,0x1, 0x1a,0x7e,0x73,0x0, 0x67,0xbc, +0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x28,0xad,0x12,0x64,0xe0,0x7e,0xb3,0x0, 0x67,0x4, +0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x67,0x7e,0xb3,0x28,0xad,0xb4,0x1, +0x17,0x7e,0xa3,0x0, 0x68,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x28,0xad,0x7c, +0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x68,0x22,0x6c,0xaa, +0x80,0x26,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0xf8,0x49,0x32,0x4, 0x0, 0x2d, +0x31,0x59,0x32,0x5, 0xf8,0x30,0x6, 0xe, 0x49,0x12,0x4, 0x7e,0x49,0x32,0x6, 0x76, +0x2d,0x31,0x59,0x32,0x6, 0x76,0xb, 0xa0,0x7e,0xb3,0x2a,0x74,0xa, 0x3b,0x7e,0xb3, +0x2a,0x73,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0x74,0x2, 0x7a, +0xb3,0x0, 0x66,0x74,0x1, 0x7a,0xb3,0x28,0xac,0x2, 0x47,0xfb,0xd2,0x0, 0x6c,0xaa, +0x6c,0x77,0x80,0x1f,0x7e,0x63,0x2a,0x6e,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c,0x65, +0x7e,0x50,0x2, 0xac,0x56,0x49,0x22,0x5, 0x7a,0xbe,0x24,0xfe,0xc, 0x58,0x2, 0xb, +0xa0,0xb, 0x70,0x7e,0xb3,0x2a,0x6d,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24,0xa, +0x3a,0xbd,0x32,0x8, 0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0x7e,0xb3,0x37,0xe9,0xb4,0x1, +0x3, 0x2, 0x37,0xbb,0x7e,0xb3,0x38,0x4f,0x4, 0x7a,0xb3,0x38,0x4f,0x7e,0xb3,0x37, +0xdd,0xb4,0x2, 0x18,0x7e,0xb3,0x38,0x4e,0x4, 0x7a,0xb3,0x38,0x4e,0xb4,0x1, 0x6, +0x74,0x1, 0x7a,0xb3,0x38,0x4f,0x74,0x1, 0x7a,0xb3,0x37,0xdd,0x7e,0x73,0x38,0x4e, +0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x37,0xe9,0x12,0x37,0xbb,0x12,0xb0, +0xb1,0x12,0x37,0xc9,0x7e,0x73,0x38,0x4f,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0x37,0xc9, +0x22,0xe4,0x7a,0xb3,0x37,0xdb,0x6c,0xaa,0x80,0xd, 0x6d,0x44,0x7e,0x70,0xc, 0xac, +0x7a,0x59,0x43,0x37,0xf2,0xb, 0xa0,0x12,0x6f,0xd6,0x38,0xee,0xe4,0x7a,0xb3,0x37, +0xdc,0x6d,0x33,0x7a,0x37,0x37,0xe3,0x7a,0x37,0x37,0xd8,0x22,0x7d,0x23,0x7e,0x14, +0x61,0xce,0x12,0x36,0xb3,0x7e,0x14,0x0, 0x5, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50, +0xd, 0x7e,0x33,0x38,0x50,0xbe,0x30,0x8, 0x50,0x45,0x74,0x8, 0x80,0x3d,0x7d,0x13, +0x3e,0x14,0xbd,0x12,0x50,0xd, 0x7e,0x33,0x38,0x50,0xbe,0x30,0x6, 0x50,0x30,0x74, +0x6, 0x80,0x28,0x7e,0x14,0x0, 0x3, 0xad,0x13,0x1e,0x14,0xbd,0x12,0x50,0xd, 0x7e, +0x33,0x38,0x50,0xbe,0x30,0x4, 0x50,0x17,0x74,0x4, 0x80,0xf, 0xbd,0x32,0x50,0xf, +0x7e,0x73,0x38,0x50,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a,0xb3,0x38,0x50,0x7e, +0xb3,0x38,0x50,0xbe,0xb0,0x0, 0x28,0x1b,0x14,0x7a,0xb3,0x38,0x50,0x74,0x1, 0x7a, +0xb3,0x16,0x92,0x90,0x62,0x3, 0xe4,0x93,0xbe,0xb3,0x38,0x50,0x50,0x5, 0xe4,0x7a, +0xb3,0x16,0x91,0x22,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a,0x12,0xb1, +0xdd,0x68,0x23,0x7e,0x70,0xc, 0xac,0x72,0x12,0xb3,0x3b,0x7d,0x23,0x7e,0x70,0xc, +0xac,0x72,0x59,0x23,0x37,0xf6,0x49,0x3, 0x37,0xf6,0x49,0x23,0x37,0xf2,0xbd,0x20, +0x50,0x4, 0x59,0x3, 0x37,0xf2,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa,0x6c,0x22, +0x80,0x18,0x12,0xb1,0xdd,0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, 0x37,0xf2, +0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4,0x7e,0x37, +0x37,0xd8,0xbe,0x37,0x38,0x51,0x50,0x8, 0x7e,0x37,0x38,0x51,0x7a,0x37,0x37,0xd8, +0x12,0xb3,0x19,0x4d,0x33,0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e,0x10,0x5, +0xac,0x12,0x9, 0xb0,0x26,0x33,0xbe,0xb3,0x2b,0xf, 0x22,0xca,0xd8,0xca,0x79,0x7e, +0xe0,0xff,0x12,0xb3,0x48,0x7e,0xb3,0x37,0xdf,0xb4,0x1, 0x8, 0x12,0x7f,0xe3,0xe4, +0x7a,0xb3,0x37,0xdf,0x7e,0xb3,0x37,0xde,0x60,0x4, 0x74,0xff,0x61,0x14,0x7e,0xb3, +0x37,0xdd,0xb4,0x2, 0x2, 0x80,0x2, 0x61,0x8, 0x12,0xb3,0x33,0x38,0x12,0x12,0xb3, +0x2b,0x38,0xd, 0x12,0xb3,0x23,0x38,0x8, 0x7e,0xb3,0x16,0x91,0x60,0x2, 0x61,0x8, +0x12,0x6f,0xed,0xa, 0x3d,0x1b,0x34,0xbe,0x34,0x0, 0x3, 0x48,0x4, 0x74,0x3, 0x80, +0x3, 0x7c,0xbd,0x14,0x12,0xb1,0x64,0x7c,0xfb,0x7e,0xb3,0x37,0xdc,0x4, 0x7a,0xb3, +0x37,0xdc,0x90,0x61,0xcb,0xe4,0x93,0x14,0x12,0xb1,0x64,0x7c,0xab,0xbe,0xa0,0xff, +0x68,0x2c,0xbe,0xf0,0xff,0x68,0x25,0x7e,0x30,0xc, 0xac,0x3f,0x49,0x21,0x37,0xf2, +0x7e,0xf4,0x61,0xd2,0x7e,0xe4,0x0, 0xff,0xb, 0x7a,0x30,0xbd,0x23,0x28,0xf, 0x12, +0xb3,0x19,0x3e,0x34,0xbd,0x23,0x28,0x6, 0x7c,0xfa,0x80,0x2, 0x7c,0xfa,0xbe,0xf0, +0xff,0x78,0x11,0xe4,0x7a,0xb3,0x37,0xdc,0x7a,0xb3,0x37,0xdd,0x7a,0xb3,0x37,0xe9, +0x74,0xff,0x80,0x70,0x90,0x61,0xda,0xe4,0x93,0xbe,0xb3,0x37,0xdc,0x50,0x59,0x74, +0xc, 0xac,0xbf,0x49,0x25,0x37,0xf2,0x7e,0x14,0x61,0xd2,0x12,0x36,0xb3,0xbd,0x23, +0x50,0x3d,0x7e,0x34,0x61,0xd6,0x12,0x23,0xbc,0xbe,0x37,0x37,0xd8,0x40,0xd, 0x7e, +0x34,0x61,0xd8,0x12,0x23,0xbc,0xbe,0x37,0x37,0xe3,0x50,0x23,0x74,0x5, 0xac,0xbf, +0x9, 0x75,0x26,0x33,0xbe,0x73,0x2b,0xf, 0x68,0x15,0x7c,0xef,0xbe,0xe0,0x4, 0x50, +0x8, 0x12,0x7c,0x90,0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xdf,0xe4, +0x7a,0xb3,0x37,0xe9,0x7a,0xb3,0x37,0xdd,0xbe,0xe0,0xff,0x68,0x5, 0xe4,0x7a,0xb3, +0x37,0xdc,0x7c,0xbe,0xda,0x79,0xda,0xd8,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33, +0x37,0xf2,0x22,0x7e,0x73,0x26,0xf5,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x26,0xf4,0xbe, +0x70,0x0, 0x22,0x7e,0x73,0x28,0x92,0xbe,0x70,0x0, 0x22,0x49,0x23,0x37,0xf8,0x49, +0x33,0x37,0xf4,0x9d,0x32,0x2, 0x21,0x15,0x7e,0xb3,0x37,0xde,0xb4,0x1, 0x27,0x7e, +0xb3,0x38,0x54,0x4, 0x7a,0xb3,0x38,0x54,0x7e,0x73,0x38,0x54,0xbe,0x70,0x3, 0x40, +0x15,0x12,0x6f,0x7e,0x7e,0x73,0x38,0x54,0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3, +0x38,0x54,0x7a,0xb3,0x37,0xde,0x22,0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80, +0x45,0x6c,0x22,0x80,0x37,0x7e,0xb3,0x2a,0x6e,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d, +0x45,0x3e,0x44,0x7e,0x7f,0x13,0x8a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32, +0x8, 0x8, 0xbe,0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, +0xbe,0x44,0xfd,0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x2a,0x6e, +0xbc,0x92,0x38,0xc1,0xb, 0x31,0x7e,0xb3,0x2a,0x6d,0xbc,0xb3,0x38,0xb3,0x7e,0x54, +0x0, 0x6, 0xad,0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12,0x25,0x5c,0xbd, +0x12,0x50,0x22,0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x39,0xf9,0x7e,0xb3,0x39,0xfa, +0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x39,0xfa,0x80,0x3c,0xe4,0x7a,0xb3,0x39, +0xfa,0x74,0x1, 0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3, +0x39,0xfa,0x7e,0xb3,0x39,0xf9,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x39,0xf9, +0x80,0x16,0xe4,0x7a,0xb3,0x39,0xf9,0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x39,0xf9, +0x7a,0xb3,0x39,0xfa,0x7a,0xb3,0x39,0xfb,0x7e,0xb3,0x39,0xfb,0x22,0xe4,0x7a,0xb3, +0x28,0xa8,0x7a,0xb3,0x39,0xfc,0x22,0x6c,0x66,0x90,0x60,0xa7,0xe4,0x93,0xbe,0xb0, +0x0, 0x28,0x71,0x90,0x60,0xaa,0xe4,0x93,0x70,0x6a,0x7e,0xb3,0x28,0xa8,0xb4,0x1, +0x63,0x7e,0x73,0x26,0xf2,0xbe,0x70,0x0, 0x28,0x5a,0x6c,0x33,0x80,0x4e,0xa, 0x23, +0x9, 0x72,0x26,0xe6,0x7e,0xb3,0x2a,0x6e,0x14,0xbc,0x7b,0x78,0x3d,0x6c,0x22,0x80, +0x27,0x7c,0xb2,0x7c,0x73,0x12,0x86,0xd0,0x50,0x1c,0xa, 0x22,0x7e,0x73,0x2a,0x6e, +0xa, 0x7, 0x2d,0x2, 0x3e,0x4, 0x49,0x20,0x4, 0xfc,0x6d,0x0, 0x9e,0x7, 0x2a,0x4f, +0xbd,0x20,0x58,0x2, 0xb, 0x60,0xb, 0x20,0x7e,0x73,0x2a,0x6d,0xbc,0x72,0x38,0xd1, +0xbe,0x60,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xb, 0x30,0x7e,0x73,0x26,0xf2, +0xbc,0x73,0x38,0xaa,0x74,0x1, 0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e,0xb3, +0x2a,0x6e,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51,0x7e, +0x13,0x2a,0x6e,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x2a,0x6d,0xa, 0x10,0xa, 0x21,0x2d, +0x12,0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x32, +0xba,0x80,0x2d,0x7e,0x3, 0x2a,0x6d,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42,0xa, +0x3a,0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58,0xe, +0x9d,0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x32,0xbc,0x80,0x2, 0xe4,0x22, +0x7e,0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60, +0x80,0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0xb4,0xc7, +0xa, 0x1b,0x7e,0x63,0x2a,0x6e,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac,0x1f, +0x2d,0x3, 0x7e,0x1f,0x13,0x8a,0x2d,0x30,0x12,0xb5,0x86,0x9d,0x35,0x1b,0x1a,0x10, +0xb, 0xf0,0x12,0xb5,0x86,0x7e,0x73,0x2a,0x6e,0xa, 0x27,0x2d,0x25,0xa, 0x3f,0xbd, +0x32,0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x2a,0x6d,0x74,0x2, 0xa4,0x22,0x12,0x4f, +0xfc,0xd2,0x19,0x2, 0x47,0xfb,0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4e, +0xa, 0x31,0xb, 0x34,0x7c,0x7, 0x80,0x3c,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x26, +0xfa,0x12,0xb6,0xf, 0x9, 0xb3,0x26,0xfa,0xa, 0x3b,0x12,0xb6,0x17,0x7e,0x70,0x2, +0xac,0x70,0x9, 0xb3,0x26,0xfb,0x12,0xb6,0xf, 0x9, 0xb3,0x26,0xfb,0xa, 0x3b,0x9d, +0x32,0x12,0x21,0x15,0x7c,0x87,0xbc,0x39,0x28,0x2, 0x7c,0x39,0xbc,0x28,0x28,0x2, +0x7c,0x28,0xb, 0x0, 0x7e,0xb3,0x28,0x84,0xbc,0xb0,0x38,0xbc,0xb, 0x10,0x7e,0xb3, +0x28,0x84,0xbc,0xb1,0x38,0xaa,0xa5,0xbb,0x64,0x2, 0x6c,0x33,0xa5,0xba,0x64,0x2, +0x6c,0x22,0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, 0x7c,0xa3,0x7c,0xba,0x22,0xa, +0x2b,0x7e,0x70,0x2, 0xac,0x71,0x22,0x9d,0x32,0x12,0x21,0x15,0x7c,0x97,0x22,0x7c, +0xa6,0x7c,0x37,0x7c,0x2b,0xe4,0x6c,0x11,0x80,0x42,0xbc,0xa1,0x68,0x3c,0x1a,0x41, +0x3e,0x44,0x9, 0x4, 0x26,0xfb,0xa, 0x20,0xa, 0x33,0x9d,0x32,0x12,0x21,0x15,0x7c, +0x7, 0x1a,0x41,0x3e,0x44,0x9, 0x74,0x26,0xfa,0xa, 0x27,0xa, 0x32,0x12,0xb6,0x17, +0xbe,0x90,0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, +0x18,0x8, 0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x28,0x84, +0xbc,0x81,0x18,0xb6,0x22,0x7e,0x37,0x28,0x8a,0xbe,0x34,0x3, 0xe8,0x8, 0xa, 0x12, +0xb6,0x8b,0xbe,0xb0,0x8, 0x48,0x2, 0xd3,0x22,0xc3,0x22,0xca,0xd8,0xca,0x79,0x6c, +0xff,0x6c,0xee,0x80,0xf, 0x7c,0xbe,0x12,0xb6,0xb0,0x7c,0xdb,0xbc,0xfd,0x58,0x2, +0x7c,0xfd,0xb, 0xe0,0x12,0x5f,0xf1,0x38,0xec,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22, +0xca,0xf8,0x7c,0xfb,0x7e,0x70,0x2, 0x12,0xb8,0xe8,0x7f,0x71,0x7c,0xbf,0x12,0x5e, +0x76,0x12,0xb6,0xce,0x7f,0x17,0x12,0x1f,0x58,0x7c,0xb7,0xda,0xf8,0x22,0x7d,0x13, +0x1a,0x2, 0x1a,0x0, 0x22,0xca,0xf8,0x7c,0xfb,0x7f,0x61,0x7f,0x50,0x7e,0x34,0x22, +0xd6,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1f,0x70,0x74,0x2a,0x12,0x1f,0xad,0x7e,0x48, +0x1f,0x70,0x12,0xb6,0x75,0x92,0xa, 0x7c,0xbf,0x7e,0x71,0x54,0x12,0x4b,0x45,0x7d, +0x43,0xe5,0x55,0x7e,0x71,0x56,0x12,0x4b,0x45,0x2d,0x34,0xe, 0x34,0x7f,0x4, 0x7e, +0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b,0x5a,0x30, +0x69,0x30,0x0, 0x4, 0x1b,0x6a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78, +0xe1,0x12,0xb7,0x64,0x28,0x2b,0xb, 0x5a,0x20,0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e, +0x24,0x0, 0x10,0x12,0x1e,0xb9,0x1b,0x5a,0x30,0xb, 0x6a,0x30,0x1a,0x26,0x1a,0x24, +0x7e,0x14,0x0, 0xd, 0x12,0x1e,0xfc,0x7e,0x8, 0x0, 0x10,0x12,0x1f,0x58,0x1b,0x6a, +0x30,0xda,0xf8,0x22,0x7e,0x73,0x2, 0x8b,0xbe,0x70,0x5, 0x22,0xca,0x3b,0x7e,0xe3, +0x28,0x84,0x6c,0xdd,0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0xb7,0xcc,0x30,0xe0,0x37, +0x6c,0xcc,0x80,0x27,0x12,0xb7,0xc2,0x7a,0xb3,0x1f,0x70,0x9, 0xa3,0x26,0xfb,0x7a, +0xa3,0x1f,0x71,0x7f,0x7, 0x12,0x9f,0x3b,0x50,0xf, 0x7f,0x7, 0x7e,0xb3,0x1f,0x71, +0x6c,0x77,0x12,0x9f,0x3e,0x50,0x2, 0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38,0xd5,0xbe, +0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb6,0xc3,0xda, +0x3b,0x22,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x26,0xfa,0x22,0x7d,0xf5,0x2e,0xf4, +0x2, 0xea,0x6d,0xee,0x29,0xb7,0x0, 0x5, 0x22,0xca,0x3b,0x7c,0x45,0x7c,0x6, 0x7c, +0x57,0x7c,0x1b,0x7e,0x34,0x4, 0xfc,0x7e,0xb3,0x26,0x83,0x7e,0xf3,0x2a,0x6e,0x7c, +0x31,0x7c,0xe0,0x7c,0x25,0x7c,0xa4,0xbc,0x1, 0x50,0x4, 0x7c,0x30,0x7c,0xe1,0xbc, +0x45,0x50,0x4, 0x7c,0x24,0x7c,0xa5,0xbe,0xb0,0x1, 0x50,0x2, 0x1, 0xa6,0x7e,0x90, +0x2, 0xac,0x9f,0x7e,0x50,0x2, 0xac,0x53,0x2d,0x24,0x2d,0x23,0xb, 0x28,0x20,0x7e, +0x10,0x2, 0xac,0x1e,0x2d,0x4, 0x2d,0x3, 0xb, 0x8, 0x40,0xa, 0x3, 0xb, 0x4, 0x7c, +0x31,0x80,0x2c,0x7e,0xd0,0x2, 0xac,0xdf,0x7e,0x10,0x2, 0xac,0x13,0x2d,0x6, 0x12, +0xb8,0xaa,0xad,0xd0,0xbd,0xdb,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58,0xf, 0xbe,0x24, +0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x4a,0xb, 0x30,0xbc, +0xe3,0x38,0xd0,0x7e,0x50,0x2, 0xac,0x52,0x2d,0x23,0xb, 0x28,0x20,0x7e,0x90,0x2, +0xac,0x9a,0x2d,0x43,0xb, 0x48,0x40,0xa, 0x12,0xb, 0x14,0x80,0x25,0x7e,0x10,0x2, +0xac,0x13,0x12,0xb8,0xaa,0xad,0xd0,0xbd,0xdb,0x58,0x15,0xad,0xf4,0xbd,0xdf,0x58, +0xf, 0xbe,0x24,0x0, 0x0, 0x8, 0x9, 0xbe,0x44,0x0, 0x0, 0x8, 0x3, 0xc3,0x80,0x7, +0xb, 0x30,0xbc,0xa3,0x38,0xd7,0xd3,0xda,0x3b,0x22,0x2d,0x3, 0xb, 0x8, 0x0, 0x7e, +0xf4,0x0, 0x9, 0x7d,0xb2,0xad,0xbf,0x7e,0xd4,0x0, 0xa, 0x22,0x12,0xb7,0xd9,0x92, +0x4, 0x30,0x4, 0xc, 0x7e,0xb3,0x2, 0xe9,0xbe,0xb0,0xfa,0x50,0x11,0x4, 0x80,0xa, +0x7e,0xb3,0x2, 0xe9,0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x2, 0xe9,0x7e,0xb3, +0x2, 0xe9,0x70,0x2, 0xc3,0x22,0xd3,0x22,0xca,0x79,0x7c,0xa7,0x7c,0x8b,0x7e,0xb3, +0x2a,0x6f,0x7a,0xb3,0x1f,0x9a,0x7e,0xb3,0x2a,0x70,0x7a,0xb3,0x1f,0x9b,0x7e,0x70, +0x2, 0xac,0x78,0x9, 0x93,0x26,0xfa,0x9, 0x83,0x26,0xfb,0x9f,0x77,0x1a,0x3a,0x1a, +0x79,0x9d,0x73,0x21,0xa0,0x7a,0xf1,0x58,0xbe,0xf0,0x0, 0x58,0xe, 0x1a,0x3f,0x1a, +0x29,0x9d,0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x58,0x7e,0xb3,0x1f,0x9a,0xbc, +0xbf,0x18,0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32,0x7c,0xb7,0xf5, +0x58,0x1a,0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x57,0x80,0x43,0x85,0x57,0x59, +0xe5,0x57,0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x57,0x1a,0x3b,0x1a,0x28,0x9d,0x23,0x1a, +0x38,0x2d,0x32,0x7c,0xb7,0xf5,0x59,0x7e,0xb3,0x1f,0x9b,0xbe,0xb1,0x57,0x18,0x10, +0x1a,0x38,0xe5,0x57,0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x59, +0xe5,0x58,0x7e,0x71,0x59,0x12,0x4b,0x45,0x1a,0x26,0x1a,0x24,0x2f,0x71,0x5, 0x57, +0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x57,0x1a,0x3b,0xbd,0x32,0x8, 0xaf,0xb, 0xf0, +0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32,0x18,0x2, 0x21,0x15,0x7f,0x17, +0xda,0x79,0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x26,0xfa,0x9, 0x65,0x26, +0xfb,0x7e,0x73,0x28,0x8c,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x28,0x8d,0xbc,0x76,0x78, +0x2, 0xd3,0x22,0xc3,0x22,0x7e,0xa3,0x2a,0x6e,0xa, 0x3a,0x3e,0x34,0x7e,0x8, 0x13, +0x8e,0xe4,0x12,0x20,0xe3,0x90,0x60,0x93,0x93,0xa, 0x3b,0x7e,0xb3,0x2a,0x71,0xa, +0x2b,0x2d,0x23,0xa, 0x3a,0xad,0x32,0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, 0x27,0x2d, +0x24,0x12,0x7f,0xbc,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14,0x13,0x8e, +0xb, 0x18,0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf,0x22,0x6c, +0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x13,0xc6,0x49,0x32,0x13,0x8e, +0xbd,0x31,0x28,0x9, 0x2e,0x24,0x13,0x8e,0x9d,0x31,0x1b,0x28,0x30,0xb, 0xa0,0x7e, +0xb3,0x2a,0x6e,0xbc,0xba,0x38,0xdc,0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5, +0xea,0xa9,0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x65, +0x7e,0x73,0x39,0xf7,0xbe,0x71,0x65,0x38,0x2, 0xd2,0x1b,0xa9,0xd0,0x9e,0xa9,0xd7, +0x9e,0xa9,0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2, +0xcd,0xa9,0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9, +0x36,0xe5,0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88, +0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e, +0x24,0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24, +0x41,0x44,0x79,0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24, +0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24, +0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0xa9,0xd5,0xcb,0x74,0x10, +0x12,0x0, 0x46,0x7c,0x7b,0x12,0x2c,0x85,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd, +0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x33,0xcb,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f, +0x7e,0xf, 0x33,0xcb,0x79,0x20,0x0, 0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x33,0xcb, +0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c,0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x33,0xcb, +0x79,0x30,0x0, 0x86,0x7e,0x34,0x29,0x90,0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x8a, +0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61, +0x7e,0xf, 0x33,0xcb,0x79,0x30,0x0, 0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9, +0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22, +0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89, +0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75, +0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7, +0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2, +0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22,0x75,0xe7,0x6b,0x2, 0xbb,0xbd,0xe4,0x7e,0x34, +0xd7,0xfc,0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0, +0x75,0xe9,0xff,0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x39,0xf5,0xb, +0x34,0x7a,0x37,0x39,0xf5,0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a, +0x37,0x39,0xf5,0x22,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3,0x3a,0x5, 0xb4,0xa5, +0x52,0x12,0xbc,0xe4,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5, +0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9, +0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0xa1,0xb5, +0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22,0x74,0x6, 0x12,0xbb, +0xf4,0x7d,0x3, 0x6c,0x11,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0xbb,0xf4,0x4c, +0xff,0x78,0x5, 0x5e,0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0xbc,0x87, +0xda,0xf8,0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c,0x73,0x7d, +0x52,0x7c,0xab,0x7e,0xb3,0x3a,0x5, 0xb4,0xa5,0x42,0x12,0xbc,0xe4,0x75,0xb5,0x1, +0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6, +0xb3,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36, +0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a, +0xa1,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0x74,0x4, 0x7d, +0x30,0x2, 0xbc,0x87,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74,0x2, 0x7d,0x3f,0x2, +0xbc,0x87,0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0xbd,0x8a,0x74,0x2, 0x12,0xbb,0xf4, +0x7d,0xf3,0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0xbc,0xeb,0x7a,0x45,0x36, +0x7d,0x30,0x6d,0x22,0x7f,0x6, 0x12,0xbd,0x46,0x5e,0xf4,0xff,0xfd,0x12,0xbc,0xeb, +0x2, 0xbd,0x23,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x3a,0x5, 0x22,0xd2,0xc8,0x43,0xed, +0xf, 0xc2,0xea,0x75,0xb3,0x13,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0xbd,0x8a,0xe4, +0x12,0xbc,0x66,0x2, 0xbd,0x23,0x12,0xbd,0x54,0x7e,0x35,0x36,0x12,0xbd,0x9a,0xa9, +0xd2,0xb4,0xd3,0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39, +0x7f,0x21,0xf5,0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0xbd,0x7f,0xe5,0x3a,0x12,0xbd, +0x7f,0xe5,0x39,0x12,0xbd,0x7f,0xe5,0x38,0x12,0xbd,0x7f,0xe4,0x2, 0xbd,0x7f,0xf5, +0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xa9,0xd5,0xca,0xa9,0xd1,0xea, +0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x3a,0x5, 0x22,0x6d,0x22,0x80,0x13,0x75,0xb5, +0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0,0xb, 0x14,0xb, +0x24,0xbd,0x32,0x38,0xe9,0x22,0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0xbe, +0x10,0xb, 0x7a,0x20,0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4, +0x54,0xf0,0x7c,0xab,0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69, +0x37,0x0, 0x6, 0x7d,0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e,0x54,0x1e,0x24,0x1e,0x24, +0x1e,0x24,0x1e,0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45, +0x6c,0x55,0x12,0x25,0x5a,0x1e,0x34,0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22, +0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x1f,0x34, +0x12,0x3f,0xe0,0x7e,0xa3,0x2a,0x73,0x7e,0x63,0x2a,0x74,0x6c,0xee,0x80,0x1e,0xa, +0x2e,0x9, 0x72,0x2a,0xdc,0xbe,0x70,0x1c,0x50,0x11,0xa, 0x27,0x12,0x81,0xeb,0x7c, +0x7b,0x7e,0xb3,0x2a,0xfb,0xa, 0x27,0x19,0xb2,0x1f,0x34,0xb, 0xe0,0xbc,0x6e,0x38, +0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73,0x2a,0xb9,0xbe,0x70,0x23,0x50,0xa, +0x7e,0x63,0x2a,0xfb,0xa, 0x27,0x19,0x62,0x1f,0x50,0xb, 0xe0,0xbc,0xae,0x38,0xe5, +0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x1f,0x34,0x6d,0x0, 0x7c,0xbf,0x7c, +0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x7c,0xab, +0x9f,0x11,0x30,0x0, 0x22,0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e, +0x7b,0xb0,0x7e,0x78,0x0, 0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d, +0x2e,0xb, 0x90,0xbc,0xa9,0x38,0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c, +0xfb,0x7e,0x8, 0x1f,0x34,0x12,0xbf,0x44,0x7e,0x8, 0x1f,0x3c,0x12,0xbf,0x4c,0xd2, +0x0, 0x7e,0x8, 0x2a,0xdc,0x7c,0xbf,0x12,0xbe,0x8e,0x7e,0x8, 0x1f,0x34,0x7a,0xf, +0x1f,0x58,0x7f,0x1, 0x7a,0x17,0x1f,0x5c,0x7d,0x32,0x7a,0x37,0x1f,0x5e,0x7e,0x18, +0x1f,0x3c,0x7a,0x1f,0x1f,0x64,0x6c,0x77,0x80,0xe, 0x12,0xbf,0x94,0x50,0x7, 0x12, +0xbf,0x55,0x19,0x51,0x1f,0x3c,0xb, 0x70,0xbc,0xf7,0x38,0xee,0x12,0xbf,0x31,0xe4, +0x12,0xbf,0x39,0xe4,0x12,0xc, 0x9b,0x6d,0x33,0x7a,0x37,0x1f,0x5c,0x7a,0x37,0x1f, +0x5e,0x12,0xbf,0x31,0x74,0x1, 0x12,0xbf,0x39,0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8, +0x22,0xa9,0xc6,0xea,0x7e,0x8, 0x1f,0x58,0x22,0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e, +0x8, 0x1f,0x58,0x22,0x7e,0x34,0x0, 0x8, 0xe4,0x2, 0x20,0xe3,0x7e,0x34,0x0, 0x1c, +0x74,0x3f,0x2, 0x20,0xe3,0xa, 0x27,0x9, 0x52,0x2b,0x44,0xa, 0x16,0x22,0x7e,0x8, +0x1f,0x34,0x12,0xbf,0x4c,0x6c,0x77,0x80,0xe, 0x12,0xbf,0x94,0x50,0x7, 0x12,0xbf, +0x55,0x19,0x51,0x1f,0x34,0xb, 0x70,0x7e,0x53,0x2a,0x6e,0xbc,0x57,0x38,0xea,0xa9, +0xc6,0xea,0x7e,0x8, 0x1f,0x34,0xe4,0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e,0x8, 0x1f, +0x34,0x2, 0x11,0x38,0xa, 0x27,0x9, 0x62,0x2a,0xdc,0xbe,0x60,0x1c,0x22,0x7c,0x7b, +0xa5,0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21, +0xbe,0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e, +0xa0,0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0, +0x4, 0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14, +0x78,0xfb,0x7c,0xb9,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x2a,0x6e,0x90,0x60,0x93, +0xe4,0x93,0xa, 0xfb,0x7e,0xb3,0x2a,0x6d,0xa, 0xeb,0x2d,0xef,0xa, 0xff,0xad,0xfe, +0xa, 0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e,0x8, 0x13,0x8e, +0x6c,0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x33,0xe4,0x2d,0x3d, +0xb, 0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, 0x5a,0x30,0x9d, +0x3d,0x59,0x32,0x13,0xc6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, 0x7d,0x5e,0x3e, +0x54,0x7e,0xf, 0x33,0xe4,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea,0x2d,0xef,0x3e, +0xe4,0x7e,0x1f,0x33,0xe4,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, 0xac,0x7a,0x2d, +0x31,0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x21,0x15,0x7d,0xc3,0xbd, +0x4c,0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34,0xda,0xf8,0x22, +0x7e,0x27,0x28,0xa3,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64,0x30,0x5, 0x2e,0x7e, +0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xf8,0x49,0x4, 0x4, 0x0, 0xbd,0x2, 0x8, 0x11, +0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x5, 0xf8,0x80, +0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, 0xf8,0x30,0x7, 0x2e, +0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x6, 0x76,0x49,0x4, 0x4, 0x7e,0xbd,0x2, 0x8, +0x11,0x7e,0xb3,0x25,0xf6,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x6, 0x76, +0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x6, 0x76,0xb, 0xa0, +0x7e,0xb3,0x2a,0x74,0xa, 0xb, 0x7e,0xb3,0x2a,0x73,0xa, 0x4b,0x2d,0x40,0xa, 0xa, +0xbd,0x4, 0x48,0x88,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33,0x19,0xb3,0x27,0x72, +0xb, 0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0x77,0xa2,0xb, 0x24,0xa, 0x33,0xbd,0x32, +0x48,0xe7,0xe4,0x7a,0xb3,0x28,0x84,0x7a,0xb3,0x28,0x85,0x6d,0x33,0x7a,0x37,0x28, +0x86,0x7a,0x37,0x28,0x88,0x7a,0x37,0x28,0x8a,0x7a,0x37,0x28,0x8e,0x7e,0xd4,0x1f, +0x36,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x13,0x8a,0x7a,0x37,0x1f,0x76,0x7d, +0x3d,0x7a,0x37,0x1f,0x7a,0x7e,0x34,0x15,0x9e,0x7a,0x37,0x1f,0x78,0x7e,0x73,0x2a, +0x6d,0x7a,0x73,0x1f,0x73,0x7e,0x73,0x2a,0x6e,0x7a,0x73,0x1f,0x72,0x7e,0x37,0x2a, +0x5c,0x7a,0x37,0x1f,0x7c,0x7e,0x37,0x2a,0x5e,0x7a,0x37,0x1f,0x7e,0x7e,0x37,0x2a, +0x60,0x7a,0x37,0x1f,0x80,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1f,0x74,0x7e,0x73,0x3, +0xff,0x7a,0x73,0x1f,0x75,0x7e,0x8, 0x1f,0x72,0x7e,0x18,0x1f,0x82,0x12,0x8, 0x0, +0x7e,0x73,0x1f,0x82,0x7a,0x73,0x28,0x84,0x7e,0x73,0x1f,0x83,0x7a,0x73,0x28,0x85, +0x7e,0x37,0x1f,0x84,0x7a,0x37,0x28,0x86,0x7e,0x37,0x1f,0x86,0x7a,0x37,0x28,0x88, +0x7e,0x37,0x1f,0x8c,0x7a,0x37,0x28,0x8a,0x7e,0x37,0x1f,0x8e,0x7d,0x23,0x7a,0x53, +0x28,0x8c,0xa, 0x36,0x7a,0x73,0x28,0x8d,0x7e,0x37,0x1f,0x88,0x7a,0x37,0x28,0x8e, +0x7e,0x37,0x1f,0x8a,0x7d,0x23,0x7a,0x53,0x28,0x90,0xa, 0x36,0x7a,0x73,0x28,0x91, +0x6c,0x33,0x80,0x20,0x7c,0xb3,0x7e,0x70,0x1, 0x12,0x5f,0x7, 0x74,0x2, 0xac,0xb3, +0x49,0x45,0x15,0x9e,0xa, 0x38,0x7c,0x27,0x19,0x25,0x26,0xfa,0x7c,0x29,0x19,0x25, +0x26,0xfb,0xb, 0x30,0x7e,0x23,0x28,0x84,0xbc,0x23,0x38,0xd8,0x6c,0x33,0x80,0x1b, +0x74,0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19, +0x25,0x27,0x36,0x7c,0x29,0x19,0x25,0x27,0x37,0xb, 0x30,0x7e,0x23,0x28,0x85,0xbc, +0x23,0x38,0xdd,0x22,0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff, +0x80,0x70,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55, +0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, +0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78, +0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69, +0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff, +0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x19,0xbd,0xfe,0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24, +0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0x90,0x60,0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, +0xb, 0xf0,0xbc,0x4f,0x38,0x8c,0x7c,0xba,0xda,0xf8,0xda,0x69,0x22,0x7c,0x7b,0xa, +0x57,0x9e,0x54,0x0, 0x20,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c, +0x67,0x5e,0x60,0xf0,0xa5,0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, +0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x7e,0x73,0x34,0x49,0xa, 0x47,0x5d,0x42,0x7e, +0x73,0x3, 0xf0,0x80,0x36,0xa5,0xbe,0x30,0x18,0x12,0xc3,0x40,0x60,0x5, 0x3e,0x34, +0x14,0x78,0xfb,0x7e,0x53,0x34,0x4a,0xa, 0x45,0x5d,0x43,0x7e,0x73,0x3, 0xf1,0x80, +0x1a,0x12,0xc3,0x40,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x34, +0x49,0xa, 0x4b,0x5d,0x43,0xa, 0x5a,0x9, 0x75,0x3, 0xf2,0xa, 0x57,0x5d,0x54,0x22, +0x7c,0xb7,0x54,0xf, 0x7e,0x34,0x0, 0x1, 0x22,0x7e,0xa3,0x2f,0xa8,0xbe,0xa0,0xf0, +0x50,0x17,0x74,0x4, 0xa4,0x59,0x35,0x2b,0xbf,0x12,0xc3,0x6a,0x59,0x25,0x2b,0xc1, +0x7e,0xb3,0x2f,0xa8,0x4, 0x7a,0xb3,0x2f,0xa8,0x22,0x7e,0xa3,0x2f,0xa8,0x74,0x4, +0xa4,0x22,0x7d,0xf2,0x7d,0xe3,0x7e,0x8, 0x2f,0x80,0x7e,0x34,0x0, 0x28,0xe4,0x12, +0x20,0xe3,0x7e,0x8, 0x2b,0xbf,0x7e,0x34,0x3, 0xc0,0x12,0x20,0xe3,0x7a,0xb3,0x3, +0xf2,0x7e,0x34,0x62,0x94,0x12,0x23,0xbc,0x7a,0x37,0x2b,0xb7,0x7a,0xe7,0x2f,0x84, +0x7a,0xf7,0x2f,0x86,0x7a,0xe7,0x2f,0x88,0x7a,0xe7,0x2f,0x8c,0x7a,0xe7,0x2f,0x90, +0x7a,0xe7,0x2f,0x94,0x7a,0xf7,0x2f,0x8a,0x7a,0xf7,0x2f,0x8e,0x7a,0xf7,0x2f,0x92, +0x7a,0xf7,0x2f,0x96,0x7a,0xe7,0x2b,0xbb,0x7a,0xf7,0x2b,0xbd,0x7a,0xb3,0x2f,0xa8, +0x74,0x2, 0x7a,0xb3,0x2f,0x7f,0x22,0x74,0xfe,0x7a,0xb3,0x3, 0xf2,0xe4,0x7a,0xb3, +0x2f,0x80,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x37,0x39,0xda,0x9e, +0x37,0x39,0xd6,0x12,0x21,0x15,0xbd,0x31,0x38,0x12,0x7e,0x37,0x39,0xdc,0x9e,0x37, +0x39,0xd8,0x12,0x21,0x15,0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4,0x22,0xca,0xd8, +0xca,0x79,0x6c,0xff,0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x2a,0x2, 0x7e,0xe3, +0x2a,0x3, 0x7e,0xb3,0x39,0xd5,0x60,0x11,0x7e,0xc7,0x39,0xde,0x4d,0xcc,0x78,0x2, +0xa1,0x2, 0xbe,0xd0,0x1, 0x28,0x2, 0xa1,0x2, 0xbe,0xd0,0x1, 0x78,0x1d,0xbe,0xb0, +0x4, 0x78,0x2, 0xa1,0x2, 0x7e,0xe7,0x29,0x8, 0x7e,0xf7,0x29,0xa, 0x7d,0x3e,0x7d, +0x2f,0x12,0xc5,0x36,0xbe,0xb0,0x1, 0x78,0x2, 0xa1,0x2, 0x7e,0xa3,0x39,0xd5,0x7c, +0xba,0x14,0x68,0x29,0x14,0x68,0x54,0x14,0x68,0x23,0x14,0x78,0x2, 0x81,0xff,0xb, +0xb2,0x68,0x2, 0xa1,0x2, 0xbe,0xd0,0x1, 0x68,0x2, 0xa1,0x11,0x4c,0xee,0x68,0x2, +0xa1,0x11,0x74,0x1, 0x7a,0xb3,0x39,0xd5,0x12,0xc5,0x24,0x80,0x65,0x4c,0xdd,0x78, +0x1d,0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x39,0xd5,0x7e,0x34,0x62,0x6a, +0x80,0x54,0x74,0x4, 0x7a,0xb3,0x39,0xd5,0x7e,0x34,0x62,0x6e,0x80,0x48,0x12,0xc5, +0x2d,0x90,0x62,0x5d,0x12,0xc5,0x18,0x68,0x49,0x80,0x56,0xbe,0xd0,0x1, 0x78,0x51, +0x4c,0xee,0x78,0x4d,0x12,0xc5,0x2d,0x7e,0x34,0x62,0x66,0x12,0x23,0xbc,0x7e,0x14, +0x62,0x6a,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7,0x39,0xde,0x40, +0x21,0x90,0x62,0x5c,0x12,0xc5,0x18,0x68,0x19,0x12,0xc5,0x24,0x74,0x3, 0x7a,0xb3, +0x39,0xd5,0x7e,0x34,0x62,0x6a,0x12,0x23,0xbc,0x7a,0x37,0x39,0xde,0x80,0x12,0x7e, +0xf0,0x24,0xe4,0x7a,0xb3,0x39,0xd5,0x6d,0x33,0x7a,0x37,0x39,0xde,0x7c,0xbf,0x80, +0x2, 0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xe4,0x93,0xa, 0x3b,0x12,0xc3,0xe3,0xa, +0xdb,0x4d,0xdd,0x22,0x7a,0xe7,0x39,0xd6,0x7a,0xf7,0x39,0xd8,0x22,0x7a,0xe7,0x39, +0xda,0x7a,0xf7,0x39,0xdc,0x22,0x7d,0x13,0x7e,0x54,0x62,0x5e,0x12,0xc5,0x65,0x50, +0x21,0x7e,0x54,0x62,0x60,0x12,0xc5,0x65,0x28,0x18,0x7e,0x14,0x62,0x62,0x12,0x36, +0xb3,0xbd,0x32,0x50,0xd, 0x7e,0x14,0x62,0x64,0x12,0x36,0xb3,0xbd,0x32,0x28,0x2, +0xe4,0x22,0x74,0x1, 0x22,0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x30,0xbd,0x31,0x22,0xca, +0x3b,0xf5,0x2a,0x7f,0x31,0x7a,0xd, 0x26,0xe4,0x7a,0xb3,0x22,0xf6,0x7a,0xb3,0x22, +0xf7,0x7a,0xb3,0x22,0xf8,0x7e,0x34,0x3, 0xe8,0x7a,0x37,0x22,0xfd,0x74,0x3c,0x7a, +0xb3,0x22,0xf5,0x75,0x2f,0x46,0x75,0x2b,0x0, 0xe1,0x60,0x12,0xc7,0x9b,0x28,0x1e, +0x7e,0x34,0x0, 0x44,0xca,0x39,0x7e,0x71,0x2b,0x74,0x44,0xac,0x7b,0x2e,0x34,0x14, +0x6, 0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x22,0xff,0x12,0x20,0xbe,0x1b,0xfd,0x6d,0x33, +0x7a,0x37,0x22,0xf9,0x7a,0x35,0x30,0x7a,0x37,0x22,0xfb,0x7a,0x35,0x32,0x7a,0x35, +0x34,0x7e,0x34,0x22,0xff,0x7a,0x35,0x36,0x7e,0x34,0x23,0x1f,0x7a,0x35,0x38,0x75, +0x2c,0x0, 0x80,0x59,0xe5,0x2c,0xa, 0x3b,0x7e,0xd, 0x26,0x12,0xc7,0xa3,0x2e,0x35, +0x36,0x12,0x4f,0xe5,0x7d,0xd3,0x7e,0xc7,0x22,0xfb,0xbd,0xcd,0x58,0x4, 0x7a,0xd7, +0x22,0xfb,0xe5,0x2c,0xa, 0x3b,0x7f,0x3, 0x12,0xc7,0xa3,0x2e,0x35,0x38,0x12,0x4f, +0xe5,0x7d,0xc3,0x7e,0x35,0x32,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x32,0x7e,0x37,0x22, +0xf9,0x2d,0x3d,0x7a,0x37,0x22,0xf9,0x7d,0x3c,0x2e,0x35,0x30,0x7a,0x35,0x30,0x2d, +0xcd,0x7e,0x35,0x34,0xbd,0x3c,0x58,0x3, 0x7a,0xc5,0x34,0x5, 0x2c,0xe5,0x2a,0xbe, +0xb1,0x2c,0x38,0xa0,0xe5,0x2a,0xb4,0xa, 0x2a,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, +0x40,0x48,0xb, 0x7e,0x25,0x32,0xbe,0x24,0x0, 0x40,0x48,0x2, 0xe1,0x5e,0xbe,0x34, +0x0, 0x60,0x8, 0x2, 0xe1,0x5e,0x7e,0x35,0x32,0xbe,0x34,0x0, 0x60,0x8, 0x2, 0xe1, +0x5e,0x80,0x28,0x7e,0x37,0x22,0xfb,0xbe,0x34,0x0, 0x20,0x8, 0xb, 0x7e,0x25,0x32, +0xbe,0x24,0x0, 0x20,0x8, 0x2, 0xe1,0x5e,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xe1,0x5e, +0x7e,0x35,0x32,0xbe,0x34,0x0, 0x30,0x8, 0x2, 0xe1,0x5e,0x7e,0xa3,0x39,0x56,0x74, +0xc, 0xa4,0xbe,0x57,0x22,0xf9,0x58,0x2, 0xe1,0x5e,0x7e,0xa3,0x39,0x57,0x74,0xc, +0xa4,0xbe,0x55,0x30,0x58,0x2, 0xe1,0x5e,0x7e,0x15,0x36,0x6d,0x0, 0x7e,0x1d,0x26, +0xe5,0x2a,0x12,0xc7,0xef,0x7a,0xb3,0x22,0xf4,0x7e,0x15,0x38,0x6d,0x0, 0x7f,0x13, +0xe5,0x2a,0x12,0xc7,0xef,0xf5,0x2d,0x7e,0x73,0x22,0xf5,0xbe,0x73,0x22,0xf4,0x38, +0x7d,0xbe,0x71,0x2d,0x38,0x78,0xe5,0x2d,0x7e,0x31,0x2d,0xac,0x3b,0x1a,0x2, 0x1a, +0x0, 0x7e,0x73,0x22,0xf4,0xac,0x77,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x2d,0xa, +0x5b,0x6d,0x44,0x7e,0x33,0x22,0xf4,0xa, 0x13,0x6d,0x0, 0x2f,0x2, 0x12,0x1f,0x7, +0x7c,0xb7,0xf5,0x2e,0xe5,0x2f,0xbe,0xb1,0x2e,0x38,0x43,0x7e,0x37,0x22,0xfb,0x2e, +0x35,0x32,0x2e,0x35,0x34,0x7a,0x35,0x3a,0xe5,0x2e,0xa, 0x2b,0x7e,0x34,0x0, 0x64, +0x9d,0x32,0x3e,0x34,0x2e,0x35,0x3a,0x7a,0x35,0x3a,0x7e,0x37,0x22,0xfd,0xbe,0x35, +0x3a,0x8, 0x1b,0x7e,0x35,0x3a,0x7a,0x37,0x22,0xfd,0xe5,0x2e,0x7a,0xb3,0x22,0xf7, +0x7e,0x73,0x23,0x41,0x7a,0x73,0x22,0xf8,0xe5,0x2b,0x7a,0xb3,0x22,0xf6,0x5, 0x2b, +0x12,0xc7,0x9b,0x28,0x2, 0xa1,0x9b,0x7e,0xa3,0x22,0xf7,0xbe,0xa1,0x2f,0x40,0x20, +0x7e,0xb3,0x22,0xf8,0xbe,0xb0,0x0, 0x28,0x17,0xbe,0xb0,0xff,0x50,0x12,0x7e,0x73, +0x22,0xf6,0xa, 0x37,0xb, 0x34,0x7a,0x73,0x39,0x53,0x7a,0xb3,0x39,0x55,0x80,0x6, +0x74,0x7c,0x7a,0xb3,0x39,0x53,0x7c,0xba,0xda,0x3b,0x22,0x7e,0x73,0x34,0x4f,0xbe, +0x71,0x2b,0x22,0x2d,0x13,0x7e,0xb, 0x50,0xa, 0x25,0x22,0xca,0x79,0x6c,0xaa,0x12, +0xc7,0xe5,0xb, 0x7a,0xf0,0x7d,0x7f,0x7c,0xbf,0xa, 0xfa,0x19,0xbf,0x39,0x58,0x7f, +0x71,0x2d,0xf4,0xb, 0x7a,0x40,0x7c,0xb9,0xa, 0x4a,0x19,0xb4,0x39,0x78,0xb, 0xa0, +0xbe,0xa0,0x20,0x40,0xda,0x7e,0x8, 0x39,0x58,0x7e,0x18,0x39,0x78,0x74,0x20,0x12, +0xc5,0x6f,0xda,0x79,0x22,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4,0x22,0xca, +0x3b,0x7c,0xfb,0x7f,0x61,0x7f,0x40,0x9f,0x11,0x7f,0x51,0x7f,0x71,0x7a,0x1d,0x3c, +0x7a,0x1d,0x40,0x7a,0x1d,0x44,0xbe,0xf0,0xa, 0x78,0x6, 0x7e,0x54,0x1, 0x3c,0x80, +0x4, 0x7e,0x54,0x2, 0x35,0x7a,0x57,0x23,0x43,0x6c,0xee,0x80,0x60,0xa, 0x5e,0x7f, +0x14,0x12,0xc9,0x40,0x7a,0x55,0x4a,0xa, 0x5e,0x7f,0x16,0x12,0xc9,0x40,0x7a,0x55, +0x48,0x7e,0x35,0x48,0x12,0xb6,0xce,0x2f,0x50,0x7e,0x65,0x4a,0x7d,0x16,0x1a,0x2, +0x1a,0x0, 0x2f,0x70,0x12,0xb6,0xce,0x12,0xc9,0x36,0x7e,0x1d,0x3c,0x2f,0x10,0x7a, +0x1d,0x3c,0x7d,0x16,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x4a,0x12,0xc9,0x36,0x7e,0x1d, +0x40,0x2f,0x10,0x7a,0x1d,0x40,0x7e,0x15,0x4a,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x48, +0x12,0xc9,0x36,0x7e,0x1d,0x44,0x2f,0x10,0x7a,0x1d,0x44,0xb, 0xe0,0xbc,0xfe,0x38, +0x9c,0xa, 0xdf,0x6d,0xcc,0x7f,0x15,0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x51,0x7f,0x17, +0x7f,0x6, 0x12,0x1f,0x58,0x7f,0x71,0x7e,0x94,0x0, 0x64,0x7e,0x1d,0x3c,0x7d,0x19, +0x12,0x1e,0xfc,0x7e,0x87,0x23,0x43,0x7d,0x18,0x7d,0xd8,0x1a,0x12,0x1a,0xc2,0x7f, +0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x3c,0x7e,0x1d,0x40,0x7d,0x19,0x12,0x1e,0xfc,0x7f, +0x6, 0x12,0x1f,0x58,0x7a,0x1d,0x40,0x7e,0x1d,0x44,0x7d,0x19,0x12,0x1e,0xfc,0x7d, +0x18,0x1a,0x2, 0x1a,0x0, 0x12,0x1f,0x58,0x7a,0x1d,0x44,0x7f,0x15,0x7f,0x7, 0x12, +0x1e,0xeb,0x7e,0x6d,0x44,0x9f,0x61,0x7f,0x15,0x7f,0x5, 0x12,0x1e,0xeb,0x7e,0x5d, +0x3c,0x9f,0x51,0x7f,0x17,0x7f,0x7, 0x12,0x1e,0xeb,0x7e,0x7d,0x40,0x9f,0x71,0xbe, +0x58,0x0, 0x0, 0x68,0x6, 0xbe,0x78,0x0, 0x0, 0x78,0x6, 0x7e,0x44,0x0, 0x64,0x80, +0x18,0x7f,0x16,0x7d,0x19,0x12,0x1e,0xfc,0x7f,0x5, 0x12,0x1f,0x58,0x7f,0x6, 0x12, +0x1e,0xeb,0x7f,0x7, 0x12,0x1f,0x58,0x7d,0x43,0xbe,0x44,0x0, 0x0, 0x18,0x2, 0x6d, +0x44,0x7c,0xb9,0xda,0x3b,0x22,0x1a,0x26,0x1a,0x24,0x12,0x1e,0xeb,0x7f,0x1, 0x22, +0x2d,0x35,0x7e,0x1b,0x70,0xa, 0x57,0x22,0xca,0xf8,0x7f,0x51,0x7f,0x40,0x7e,0x37, +0x2f,0x90,0x7a,0x35,0x2a,0x7e,0x37,0x2f,0x8e,0x7a,0x35,0x2c,0x7e,0x37,0x2f,0x9c, +0x7a,0x35,0x26,0x7e,0x37,0x2f,0x9e,0x7a,0x35,0x28,0x6c,0xff,0x80,0x1e,0x7e,0x34, +0x0, 0x26,0x7e,0x14,0x0, 0x2f,0x74,0x9, 0x12,0x1f,0x8c,0x74,0x2, 0xac,0xbf,0x7f, +0x4, 0x2d,0x15,0x7f,0x15,0x2d,0x35,0x12,0xc9,0x97,0xb, 0xf0,0x7e,0x73,0x39,0x54, +0xbc,0x7f,0x38,0xda,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0x35,0x2f,0xbe,0x34, +0x0, 0x0, 0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x34, +0x0, 0x0, 0x38,0x7, 0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x31,0xb, 0x6a,0x30,0x9e,0x35, +0x33,0x6d,0x22,0x7e,0x33,0x39,0x56,0x12,0xc9,0xec,0x7e,0x15,0x2f,0x12,0x1f,0x5, +0x1b,0x6a,0x30,0xb, 0x7a,0x30,0x9e,0x35,0x35,0x6d,0x22,0x7e,0x33,0x39,0x57,0x12, +0xc9,0xec,0x7e,0x15,0x31,0x12,0x1f,0x5, 0x1b,0x7a,0x30,0x22,0xa, 0x13,0x6d,0x0, +0x2, 0x1e,0xeb,0x7c,0x97,0x7c,0xab,0x7f,0x10,0x7e,0x30,0x2, 0xac,0x3a,0x2d,0x13, +0x7d,0x2, 0xb, 0xa, 0x10,0x7e,0x10,0x2, 0xac,0x19,0x7f,0x71,0x2d,0xf0,0xb, 0x7a, +0x0, 0x7c,0x21,0xa5,0xba,0x0, 0x14,0xa, 0x3, 0x1b,0x7a,0x0, 0xbc,0x9a,0x68,0x24, +0x6d,0x44,0x74,0x2, 0xa4,0x2d,0x35,0x1b,0x1a,0x40,0x22,0xbc,0x9a,0x68,0x15,0xa, +0x2, 0xa, 0x13,0x2d,0x10,0xe, 0x14,0x1b,0x7a,0x10,0x6d,0x11,0x74,0x2, 0xa4,0x2d, +0x35,0x1b,0x1a,0x10,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x73,0x39,0x54,0xbe, +0x70,0x20,0x40,0x52,0x7e,0xf0,0x2, 0x80,0x3c,0xa, 0x3f,0x6d,0x22,0x74,0x5, 0x2f, +0x11,0x14,0x78,0xfb,0x7e,0x33,0x39,0x54,0xa, 0x13,0x6d,0x0, 0x12,0x1f,0x7, 0x7c, +0xe7,0xbe,0xe0,0x2, 0x50,0x3, 0x7e,0xe0,0x2, 0xa, 0x6f,0x1b,0x64,0xa, 0x3e,0x1b, +0x34,0x7c,0xc7,0x7f,0x5, 0x7c,0xbd,0x12,0xc9,0xf3,0x7f,0x6, 0x7c,0xbd,0x7c,0x7c, +0x12,0xc9,0xf3,0xb, 0xf0,0x7e,0x73,0x39,0x54,0xbc,0x7f,0x50,0xbc,0x7f,0x5, 0x7f, +0x16,0x12,0xc7,0xab,0x80,0x6, 0x74,0x7e,0x7a,0xb3,0x39,0x53,0xda,0x3b,0x22,0xca, +0x3b,0x7f,0x71,0x7e,0x60,0x1, 0xb, 0xa, 0x20,0xb, 0x7a,0x50,0x7c,0x4b,0x7a,0x53, +0x22,0xf4,0x7a,0x43,0x23,0xe4,0x7e,0x70,0x1, 0x7e,0xa0,0x1, 0x61,0xd0,0x7e,0x90, +0x2, 0xac,0x9a,0x7f,0x60,0x2d,0xd4,0xb, 0x6a,0xd0,0x7d,0x7d,0x7c,0xbf,0xf5,0x26, +0x7f,0x67,0x2d,0xd4,0xb, 0x6a,0x40,0xa, 0xd5,0xa, 0xbb,0x7d,0xab,0x9d,0xad,0x7d, +0x7a,0x7c,0x8f,0xbe,0x80,0x0, 0x58,0x5, 0x6e,0x80,0xff,0xb, 0x80,0xa, 0xa4,0xa, +0x79,0x9d,0x7a,0xbe,0xf0,0x0, 0x58,0x5, 0x6e,0xf0,0xff,0xb, 0xf0,0xbe,0x80,0x2, +0x58,0x7, 0xbe,0xf0,0x2, 0x58,0x2, 0x61,0xce,0xbe,0x60,0x0, 0x18,0x2, 0x61,0xb6, +0xbe,0x70,0xec,0x28,0x2, 0x61,0xda,0xbe,0x80,0x8, 0x58,0x5, 0xbe,0xf0,0x8, 0x48, +0x61,0xa, 0xa7,0xb, 0xa4,0x7d,0x6a,0x7c,0x7d,0xa, 0xa5,0x2d,0xab,0x12,0xcc,0x1e, +0x19,0xba,0x22,0xf4,0xa, 0xd9,0xa, 0xa4,0x2d,0xad,0x12,0xcc,0x1e,0x19,0xba,0x23, +0xe4,0x9, 0xba,0x22,0xf4,0xa, 0xdb,0xa, 0xc5,0x2d,0xcd,0xe, 0xc4,0x7d,0x6c,0x7c, +0xbd,0xa, 0xc7,0x19,0xbc,0x22,0xf3,0x9, 0xbc,0x23,0xe4,0xa, 0xcb,0xa, 0xa4,0x2d, +0xac,0x12,0xcc,0x1e,0x19,0xba,0x23,0xe3,0x2d,0xdb,0x12,0xcc,0x15,0x19,0xbd,0x22, +0xf5,0xa, 0xd9,0x12,0xcc,0x13,0x19,0xbd,0x23,0xe5,0xb, 0xd5,0x7d,0x6d,0x7c,0x7d, +0x80,0x24,0xbe,0x80,0x4, 0x58,0x5, 0xbe,0xf0,0x4, 0x48,0x1a,0xe5,0x26,0xa, 0xcb, +0xa, 0xd5,0x12,0xcc,0x13,0x19,0xbd,0x22,0xf4,0xa, 0xc9,0xa, 0xd4,0x12,0xcc,0x13, +0x19,0xbd,0x23,0xe4,0xb, 0x70,0xbe,0x70,0xf0,0x50,0x1f,0x7e,0x51,0x26,0x7c,0x49, +0xe5,0x26,0xa, 0xd7,0x19,0xbd,0x22,0xf4,0x19,0x9d,0x23,0xe4,0xb, 0x70,0xb, 0xa0, +0x7e,0xb3,0x39,0x54,0xbc,0xba,0x28,0x2, 0x41,0xce,0x7a,0x73,0x39,0x54,0x7e,0xa0, +0x1, 0x80,0x25,0xa, 0x3a,0x9, 0xb3,0x22,0xf4,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x7a, +0x7f,0x60,0x2d,0xd3,0x1b,0x6a,0x20,0xa, 0x2a,0x9, 0xb2,0x23,0xe4,0xa, 0x4b,0x2d, +0x3f,0x7d,0x2e,0x1b,0x1a,0x40,0xb, 0xa0,0x7e,0xb3,0x39,0x54,0xbc,0xba,0x38,0xd3, +0xda,0x3b,0x22,0x2d,0xdc,0xe, 0xd4,0x7d,0x6d,0x7c,0xbd,0xa, 0xd7,0x22,0xe, 0xa4, +0x7d,0x6a,0x7c,0xbd,0xa, 0xa7,0x22,0x6e,0x34,0xff,0xff,0x6e,0x24,0xff,0xff,0x5e, +0x35,0x1a,0x5e,0x25,0x18,0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x2a,0x6e,0x74,0x2, 0xa4, +0x7e,0xf, 0x6, 0xf8,0x2d,0x15,0x7e,0xb3,0x2a,0x6d,0x7e,0x37,0x2a,0x51,0x22,0x74, +0x1, 0x7a,0xb3,0x38,0xb5,0x7e,0x34,0x60,0xa3,0x22,0x7e,0x71,0x24,0x74,0x2, 0xac, +0x7b,0x9, 0xa3,0x26,0xfa,0x22,0x74,0x1, 0x7a,0xb3,0x2b,0x1, 0x7a,0xb3,0x2b,0x1d, +0x22,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x37,0xf4,0x59,0x32,0x37,0xf8,0x22,0x7e, +0xb3,0x2a,0x73,0x7e,0x73,0x2a,0x74,0x12,0x10,0xee,0x74,0x2, 0x22,0x9, 0xb3,0x26, +0xfa,0xf5,0x25,0x9, 0xb3,0x26,0xfb,0xf5,0x26,0x22,0x74,0x2, 0xac,0xbe,0x9, 0xd5, +0x26,0xfa,0x9, 0xc5,0x26,0xfb,0x22,0x7e,0x18,0x0, 0x1, 0x7c,0xbd,0x22,0x74,0x2, +0xac,0xbf,0x9, 0xd5,0x26,0xfa,0x9, 0xe5,0x26,0xfb,0x22,0xa, 0x3a,0x19,0xf3,0x1f, +0x46,0x74,0x1, 0x19,0xb4,0x1f,0x50,0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4,0x7e,0x7b, +0x60,0xbc,0x6b,0x22,0x3e,0x44,0x7e,0x1f,0x13,0x8a,0x2d,0x34,0x1b,0x1a,0x50,0x22, +0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26,0x7e,0x51,0x27,0x22,0x6e,0x34,0xff,0xff, +0xb, 0x34,0x7a,0x37,0x2a,0x5e,0x22,0xe4,0x7a,0xb3,0x37,0xdd,0x7a,0xb3,0x37,0xe5, +0x22,0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x31,0xb, 0xa0,0x22,0x7e,0x70,0x2, 0xac,0x79, +0x9, 0xb3,0x1f,0x34,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x28,0xb2,0x22,0x7e, +0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0x9d,0x32,0x12,0x21,0x15,0xbe,0x34, +0x0, 0x8, 0x22,0x75,0x25,0x0, 0x75,0x26,0x0, 0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18, +0x0, 0x24,0x22,0x6c,0x77,0x12,0x5f,0x7, 0x7e,0x70,0x2, 0x22,0xa, 0x2b,0x1b,0x24, +0xa, 0x3d,0xbd,0x32,0x22,0x74,0x1, 0xa, 0x8f,0x19,0xb8,0x1f,0x34,0x22,0x6d,0x33, +0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x7f,0x6, 0x2d,0x12,0x79,0x40,0x0, 0x28,0x22,0x7e, +0x37,0x25,0xf4,0x7a,0x37,0x34,0x88,0x22,0x7e,0x34,0xd, 0xc8,0x7a,0x37,0x34,0x8a, +0x22,0x7e,0x73,0x38,0xd2,0x7a,0x73,0x2b,0x20,0x22,0x7e,0xb3,0x38,0xf5,0x7e,0x34, +0x0, 0x4, 0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x80,0x22,0x9d,0x32,0x12,0x21,0x15, +0x7d,0xf3,0x22,0x7d,0x2e,0x12,0x1e,0xb9,0x7d,0xf3,0x22,0x7e,0x73,0x28,0x84,0xbe, +0x71,0x24,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x70,0x22,0xe4,0x12,0x13,0xde,0x2, +0x13,0x96,0x7e,0x73,0x2a,0x2, 0xbe,0x70,0x0, 0x22,0x90,0x60,0xa7,0xe4,0x93,0x7c, +0xab,0x22,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x22,0xcd,0xda,0x32,0x25,0x75,0x8a, +0x6, 0x51, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft5435/Makefile b/drivers/input/touchscreen/ft5435/Makefile new file mode 100644 index 0000000000000..5dd5dd9121c0d --- /dev/null +++ b/drivers/input/touchscreen/ft5435/Makefile @@ -0,0 +1,9 @@ +obj-$(CONFIG_TOUCHSCREEN_FT5435) += ft5435_ts.o +obj-$(CONFIG_TOUCHSCREEN_FT5435) += focaltech_esd_protection.o +obj-$(CONFIG_TOUCHSCREEN_FT5435) += lib/ +# for focaltech tp firmware power on upgrade + #EXTRA_CFLAGS += -DFOCALTECH_PWRON_UPGRADE + #EXTRA_CFLAGS += -DFOCALTECH_TP_GESTURE + #EXTRA_CFLAGS += -DFOCALTECH_FAE_MOD + #EXTRA_CFLAGS += -DFOCALTECH_FW_COMPAT + diff --git a/drivers/input/touchscreen/ft5435/focaltech_esd_protection.c b/drivers/input/touchscreen/ft5435/focaltech_esd_protection.c new file mode 100644 index 0000000000000..0b1605a4c8f23 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/focaltech_esd_protection.c @@ -0,0 +1,199 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2016, FocalTech Systems, Ltd., all rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + + /************************************************************************ +* +* File Name: focaltech_esd_protection.c +* +* Author: Software Department, FocalTech +* +* Created: 2016-03-18 +* +* Modify: +* + +************************************************************************/ + +/******************************************************************************* +* Included header files +*******************************************************************************/ +#include +#include +#include +#include "ft5435_ts.h" +#if CTP_ESD_PROTECT + +/******************************************************************************* +* Private constant and macro definitions using #define +*******************************************************************************/ +#define FOCALTECH_ESD_PROTECTION_INFO "File Version of focaltech_esd_protection.c: V1.1.0 2016-03-24" +#define FTS_ESD_PROTECTION_EN 1 +#define ESD_PROTECTION_WAIT_TIME 2000 + +/******************************************************************************* +* Private enumerations, structures and unions using typedef +*******************************************************************************/ + + + +/******************************************************************************* +* Static variables +*******************************************************************************/ +static struct timeval g_last_comm_time; +static struct task_struct *thread_esd_protection; + +static DECLARE_WAIT_QUEUE_HEAD(esd_protection_waiter); + +static int g_start_esd_protection = 0; +static int g_esd_protection_use_i2c = 0; +static int g_esd_protection_checking = 0; +/******************************************************************************* +* Global variable or extern global variabls/functions +*******************************************************************************/ +extern void ctp_esd_check_func(void); +/******************************************************************************* +* Static function prototypes +*******************************************************************************/ +static int fts_esd_protection_timeout(void *unused); +static int fts_esd_protection_check(void); + +int fts_esd_protection_init(void); +int fts_esd_protection_exit(void); +int fts_esd_protection_notice(void); +int fts_esd_protection_suspend(void); +int fts_esd_protection_resume(void); + +/******************************************************************************* +* functions body +*******************************************************************************/ + +int fts_esd_protection_init(void) +{ + int err = 0; + + if (0 == FTS_ESD_PROTECTION_EN) + return 0; + + g_start_esd_protection = 1; + g_esd_protection_use_i2c = 0; + g_esd_protection_checking = 0; + + do_gettimeofday(&g_last_comm_time); + + thread_esd_protection = kthread_run(fts_esd_protection_timeout, 0, "focal_esd_protection"); + if (IS_ERR(thread_esd_protection)) + { + err = PTR_ERR(thread_esd_protection); + printk("failed to create kernel thread: %d\n", err); + } + + return 0; +} +int fts_esd_protection_exit(void) +{ + if (0 == FTS_ESD_PROTECTION_EN) + return 0; + + kthread_stop(thread_esd_protection); + + msleep(ESD_PROTECTION_WAIT_TIME); + return 0; +} +static int fts_esd_protection_timeout(void *unused) +{ + unsigned int iDeltaTime = 0; + unsigned long uljiffies = 0; + struct timeval tv; + + struct sched_param param = { .sched_priority = 5 }; + sched_setscheduler(current, SCHED_RR, ¶m); + uljiffies = msecs_to_jiffies(ESD_PROTECTION_WAIT_TIME + 20); + do + { + wait_event_interruptible_timeout(esd_protection_waiter, 0, uljiffies); + if (0 == g_start_esd_protection) + continue; + + do_gettimeofday(&tv); + iDeltaTime = (tv.tv_sec - g_last_comm_time.tv_sec)*MSEC_PER_SEC + (tv.tv_usec - g_last_comm_time.tv_usec)/1000; + + printk("xyf fts DeltaTime : %d\n", iDeltaTime); + + if (ESD_PROTECTION_WAIT_TIME < iDeltaTime) + { + fts_esd_protection_check(); + } + }while(!kthread_should_stop()); + + return 0; +} + +int fts_esd_protection_suspend(void) +{ + g_start_esd_protection = 0; + printk("%s enter\n", __func__); + return 0; +} +int fts_esd_protection_resume(void) +{ + g_start_esd_protection = 1; + printk("%s enter\n", __func__); + return 0; +} + +int fts_esd_protection_notice(void) +{ + int i = 0; + + if (0 == FTS_ESD_PROTECTION_EN) + return 0; + + if (1 == g_esd_protection_use_i2c) + return -3; + + for (i = 0; i < 10; i++) + { + if (0 == g_esd_protection_checking) + break; + msleep(2); + } + if (i == 10) + { + + return -EPERM; + } + + /* + if(0 == g_start_esd_protection) + g_start_esd_protection = 1; + */ + do_gettimeofday(&g_last_comm_time); + + return 0; +} + +static int fts_esd_protection_check(void) +{ + g_esd_protection_checking = 1; + g_esd_protection_use_i2c = 1; + ctp_esd_check_func(); + g_esd_protection_use_i2c = 0; + g_esd_protection_checking = 0; + return 0; +} +#endif diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.c b/drivers/input/touchscreen/ft5435/ft5435_ts.c new file mode 100644 index 0000000000000..abf0df17eb238 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.c @@ -0,0 +1,5657 @@ +/* + * + * FocalTech ft5435 TouchScreen driver. + * + * Copyright (c) 2010 Focal tech Ltd. + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ft5435_ts.h" + +#ifdef FOCALTECH_ITO_TEST +#include "mcap_test_lib.h" +#endif + +#include +#include + +#if defined(CONFIG_FB) +#include +#include + +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add virtual P-sensor funtion*/ +#include +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +/* Early-suspend level */ +#define FT_SUSPEND_LEVEL 1 +#endif + +#define FTS_POINT_REPORT_CHECK_EN 0 +#define FTS_RESUME_EN 1 +struct mutex report_mutex; +struct input_dev *ft5435_input_dev; +#if defined(FOCALTECH_AUTO_UPGRADE) +#define FTS_VENDOR_1 0x3b +#define FTS_VENDOR_2 0x51 +#define FTS_VENDOR_3 0xD0 + +#ifdef CONFIG_XIAOMI_D2A +static unsigned char firmware_data_vendor1[] = { + + #include "HQ_D2A_XiaoMi_FT5435_BIEL0X3b_Black_V10_D01_20170817_app.i" +}; + + +#else +static unsigned char firmware_data_vendor1[] = { + + #include "HQ_D2_XiaoMi_FT5435_BIEL0X3b_Black_V0A_D01_20170712_app.i" +}; +#endif +static unsigned char firmware_data_vendor2[] = { + + #include "D1S_1_FT5446_Ofilm_TM_Black_V01_D01_20171219_app.i" +}; + +static unsigned char firmware_data_vendor3[] = { + #include "HQ_D2_XiaoMi_FT5435_BIEL0X3b+CTC0Xd0_Black_V09_D01_20170811_app.i" + +}; + +#endif +#if CTP_ESD_PROTECT + +extern int fts_esd_protection_init(void); +extern int fts_esd_protection_exit(void); +extern int fts_esd_protection_notice(void); +extern int fts_esd_protection_suspend(void); +extern int fts_esd_protection_resume(void); + +void ctp_esd_check_func(void); +#endif + + + +#if FTS_POINT_REPORT_CHECK_EN + +#define POINT_REPORT_CHECK_WAIT_TIME 200 + + +static struct delayed_work ft5435_point_report_check_work; +static struct workqueue_struct *ft5435_point_report_check_workqueue; + + + +void ft5435_point_report_check_queue_work(void) +{ + cancel_delayed_work(&ft5435_point_report_check_work); + queue_delayed_work(ft5435_point_report_check_workqueue, &ft5435_point_report_check_work, msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME)); +} + + +int ft5435_point_report_check_exit(void) +{ + + + destroy_workqueue(ft5435_point_report_check_workqueue); + + return 0; +} +#endif /* FTS_POINT_REPORT_CHECK_EN */ + +#define TCT_KEY_BACK 158 +#define TCT_KEY_HOME 172 +#define TCT_KEY_MENU 139 + + + +#define TCT_KEY_BACK_POS_X 100 +#define TCT_KEY_BACK_POS_Y 1321 + +#define TCT_KEY_HOME_POS_X 360 +#define TCT_KEY_HOME_POS_Y 1321 + +#define TCT_KEY_MENU_POS_X 620 +#define TCT_KEY_MENU_POS_Y 1321 + +#define TX_NUM_MAX 50 +#define RX_NUM_MAX 50 + + + +/* [PLATFORM]-Mod-BEGIN by TCTNB.ZXZ, PR-814306, 2014/10/24, add for rawdata test */ +#if 1 +#define CONFIG_TCT_TP_FTDEBUG + +#endif +/* [PLATFORM]-Mod-END by TCTNB.ZXZ */ + +#define FT_DRIVER_VERSION 0x02 + +#define TRULY 0x79 +#define CHAOSHENG 0x57 + +#define FT_META_REGS 3 +#define FT_ONE_TCH_LEN 6 +#define FT_TCH_LEN(x) (FT_META_REGS + FT_ONE_TCH_LEN * x) + +#define FT_PRESS 0x7F +#define FT_MAX_ID 0x0F +#define FT_TOUCH_X_H_POS 3 +#define FT_TOUCH_X_L_POS 4 +#define FT_TOUCH_Y_H_POS 5 +#define FT_TOUCH_Y_L_POS 6 +#define FT_TD_STATUS 2 +#define FT_TOUCH_EVENT_POS 3 +#define FT_TOUCH_ID_POS 5 +#define FT_TOUCH_DOWN 0 +#define FT_TOUCH_CONTACT 2 + +/*register address*/ +#define FT_REG_DEV_MODE 0x00 +#define FT_DEV_MODE_REG_CAL 0x02 +#define FT_REG_ID 0xA3 +#define FT_REG_PMODE 0xA5 +#define FT_REG_FW_VER 0xA6 +#define FT_REG_FW_VENDOR_ID 0xA8 +#define FT_REG_POINT_RATE 0x88 +#define FT_REG_THGROUP 0x80 +#define FT_REG_ECC 0xCC +#define FT_REG_RESET_FW 0x07 +#define FT_REG_FW_MIN_VER 0xB2 +#define FT_REG_FW_SUB_MIN_VER 0xB3 + +/* power register bits*/ +#define FT_PMODE_ACTIVE 0x00 +#define FT_PMODE_MONITOR 0x01 +#define FT_PMODE_STANDBY 0x02 +#define FT_PMODE_HIBERNATE 0x03 +#define FT_FACTORYMODE_VALUE 0x40 +#define FT_WORKMODE_VALUE 0x00 +#define FT_RST_CMD_REG1 0xFC +#define FT_RST_CMD_REG2 0xBC +#define FT_READ_ID_REG 0x90 +#define FT_ERASE_APP_REG 0x61 +#define FT_ERASE_PANEL_REG 0x63 +#define FT_FW_START_REG 0xBF + +#define FT_STATUS_NUM_TP_MASK 0x0F + +#define FT_VTG_MIN_UV 2600000 +#define FT_VTG_MAX_UV 3300000 +#define FT_I2C_VTG_MIN_UV 1800000 +#define FT_I2C_VTG_MAX_UV 1800000 + +#define FT_COORDS_ARR_SIZE 4 +#define MAX_BUTTONS 4 + +#define FT_8BIT_SHIFT 8 +#define FT_4BIT_SHIFT 4 +#define FT_FW_NAME_MAX_LEN 50 + +#define FT5316_ID 0x0A +#define FT5306I_ID 0x55 +#define FT6X06_ID 0x06 +#define FT6X36_ID 0x36 +#define FT5X46_ID 0x54 + +#define FT_UPGRADE_AA 0xAA +#define FT_UPGRADE_55 0x55 + +#define FT_FW_MIN_SIZE 8 +#define FT_FW_MAX_SIZE 65536 + +/* Firmware file is not supporting minor and sub minor so use 0 */ +#define FT_FW_FILE_MAJ_VER(x) ((x)->data[(x)->size - 2]) +#define FT_FW_FILE_MIN_VER(x) 0 +#define FT_FW_FILE_SUB_MIN_VER(x) 0 +#define FT_FW_FILE_VENDOR_ID(x) ((x)->data[(x)->size - 1]) + +#define FT_FW_FILE_MAJ_VER_FT6X36(x) ((x)->data[0x10a]) +#define FT_FW_FILE_VENDOR_ID_FT6X36(x) ((x)->data[0x108]) + +/** +* Application data verification will be run before upgrade flow. +* Firmware image stores some flags with negative and positive value +* in corresponding addresses, we need pick them out do some check to +* make sure the application data is valid. +*/ +#define FT_FW_CHECK(x, ts_data) \ + (ts_data->family_id == FT6X36_ID ? \ + (((x)->data[0x104] ^ (x)->data[0x105]) == 0xFF \ + && ((x)->data[0x106] ^ (x)->data[0x107]) == 0xFF) : \ + (((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \ + && ((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \ + && ((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF)) + +#define FT_MAX_TRIES 5 +#define FT_RETRY_DLY 20 + +#define FT_MAX_WR_BUF 10 +#define FT_MAX_RD_BUF 2 +#define FT_FW_PKT_LEN 128 +#define FT_FW_PKT_META_LEN 6 +#define FT_FW_PKT_DLY_MS 20 +#define FT_FW_LAST_PKT 0x6ffa +#define FT_EARSE_DLY_MS 100 +#define FT_55_AA_DLY_NS 5000 + +#define FT_UPGRADE_LOOP 30 +#define FT_CAL_START 0x04 +#define FT_CAL_FIN 0x00 +#define FT_CAL_STORE 0x05 +#define FT_CAL_RETRY 100 +#define FT_REG_CAL 0x00 +#define FT_CAL_MASK 0x70 + +#define FT_INFO_MAX_LEN 512 + +#define FT_BLOADER_SIZE_OFF 12 +#define FT_BLOADER_NEW_SIZE 30 +#define FT_DATA_LEN_OFF_OLD_FW 8 +#define FT_DATA_LEN_OFF_NEW_FW 14 +#define FT_FINISHING_PKT_LEN_OLD_FW 6 +#define FT_FINISHING_PKT_LEN_NEW_FW 12 +#define FT_MAGIC_BLOADER_Z7 0x7bfa +#define FT_MAGIC_BLOADER_LZ4 0x6ffa +#define FT_MAGIC_BLOADER_GZF_30 0x7ff4 +#define FT_MAGIC_BLOADER_GZF 0x7bf4 + +enum { + FT_BLOADER_VERSION_LZ4 = 0, + FT_BLOADER_VERSION_Z7 = 1, + FT_BLOADER_VERSION_GZF = 2, +}; + +enum { + FT_FT5336_FAMILY_ID_0x11 = 0x11, + FT_FT5336_FAMILY_ID_0x12 = 0x12, + FT_FT5336_FAMILY_ID_0x13 = 0x13, + FT_FT5336_FAMILY_ID_0x14 = 0x14, +}; + +enum proximity_sensor_vendor +{ + TAOS = 1, + STK, + TOTAL, +}; + + +extern int TX_NUM; +extern int RX_NUM; +extern int SCab_1; +extern int SCab_2; +extern int SCab_3; +extern int SCab_4; +extern int SCab_5; +extern int SCab_6; +extern int SCab_7; +extern int SCab_8; +extern int Save_rawData1[TX_NUM_MAX][RX_NUM_MAX]; + + +#define FTS_FACTORYMODE_VALUE 0x40 +#define FTS_WORKMODE_VALUE 0x00 +static struct i2c_client *ft_g_client; + +#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_vkey_support, \ + fw_name, fw_maj, fw_min, fw_sub_min) \ + snprintf(buf, FT_INFO_MAX_LEN, \ + "controller\t= focaltech\n" \ + "model\t\t= 0x%x\n" \ + "name\t\t= %s\n" \ + "max_touches\t= %d\n" \ + "drv_ver\t\t= 0x%x\n" \ + "group_id\t= 0x%x\n" \ + "fw_vkey_support\t= %s\n" \ + "fw_name\t\t= %s\n" \ + "fw_ver\t\t= %d.%d.%d\n", id, name, \ + max_tch, FT_DRIVER_VERSION, group_id, \ + fw_vkey_support, fw_name, fw_maj, fw_min, \ + fw_sub_min) + +#define FT_DEBUG_DIR_NAME "ts_debug" + + u8 fts_fw_vendor_id; + +struct ft5435_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + struct mutex report_mutex; /* xlg, 2017.6.22 */ + const struct ft5435_ts_platform_data *pdata; + struct regulator *vdd; + struct regulator *vcc_i2c; + char fw_name[FT_FW_NAME_MAX_LEN]; + bool loading_fw; + u8 family_id; + struct dentry *dir; + u16 addr; + bool suspended; + char *ts_info; + u8 *tch_data; + u32 tch_data_len; + u8 fw_ver[3]; +/*[Feature]-Add-BEGIN by xingchen.wang, task 1292137, 2016/01/05, modify ft5436_tp_log sys node */ + int touch_log_switch; +/*[Feature]-Add-END by xingchen.wang, task 1292137, 2016/01/05*/ +#if defined(FOCALTECH_FW_COMPAT) + u8 fw_compat; +#endif +#if defined(FOCALTECH_PWRON_UPGRADE) + struct delayed_work focaltech_update_work; +#endif + u8 fw_vendor_id; +#if 1 +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif +#else +#if defined(CONFIG_FB) + struct work_struct fb_notify_work; + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + +#endif + struct pinctrl *ts_pinctrl; + struct pinctrl_state *gpio_state_active; + struct pinctrl_state *gpio_state_suspend; +#if 0 + u8 gesture_id; + u8 gesture_set; +#endif + +#if defined(FOCALTECH_TP_GLOVE) + u8 glove_id; +#endif + +#if defined(USB_CHARGE_DETECT) +struct work_struct work; +u8 charger_in; +#endif +#if defined(LEATHER_COVER) +struct work_struct work_cover; +u8 cover_on; +#endif +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add cover and vr funtion*/ +#if defined(VR_GLASS) +struct work_struct work_vr; +u8 vr_on; +#endif +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +}; +bool is_ft5435 = false; +struct wake_lock ft5436_wakelock; + +static int ft5435_i2c_read(struct i2c_client *client, char *writebuf, + int writelen, char *readbuf, int readlen); +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add virtual P-sensor funtion*/ +static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val); + +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR +struct virtualpsensor { + char const *name; + struct input_dev *proximity_dev; + int proximity_function; + int vps_enabled; + struct sensors_classdev vps_cdev; + int value; +}; + +struct virtualpsensor *vps_ft5436; + +#define VPS_NAME "virtual-proximity" + +struct sensors_classdev virtual_sensors_proximity_cdev2 = { + .name = VPS_NAME, + .vendor = "NULL", + .version = 1, + .handle = SENSORS_PROXIMITY_HANDLE, + .type = SENSOR_TYPE_PROXIMITY, + .max_range = "5", + .resolution = "5.0", + .sensor_power = "3", + .min_delay = 0, /* in microseconds */ + .fifo_reserved_event_count = 0, + .fifo_max_event_count = 0, + .enabled = 0, + .delay_msec = 100, + .sensors_enable = NULL, + .sensors_poll_delay = NULL, +}; + +static int vps_set_enable(struct sensors_classdev *sensors_cdev, unsigned int enable); + +static void tp_prox_sensor_enable(struct i2c_client *client, int enable); +#endif +static int ft5435_i2c_write(struct i2c_client *client, char *writebuf, int writelen); +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +static struct workqueue_struct *ft5435_wq_cover; +#if defined(VR_GLASS) +static struct workqueue_struct *ft5435_wq_vr; +#endif +static struct workqueue_struct *ft5435_wq; +static struct ft5435_ts_data *g_ft5435_ts_data; + +static int init_ok; + + +module_param_named(init_ok, init_ok, int, 0644); + + + +#if FTS_RESUME_EN + +#define FTS_RESUME_WAIT_TIME 20 + +static struct delayed_work ft5435_resume_work; +static struct workqueue_struct *ft5435_resume_workqueue; +static int ft5435_ts_resume(struct device *dev); +static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val); + + + +static void ft5435_resume_func(struct work_struct *work) +{ + + + + struct ft5435_ts_data *data = g_ft5435_ts_data; + printk("Exter %s", __func__); + + msleep(data->pdata->soft_rst_dly); + mutex_lock(&data->report_mutex); + + + + ft5x0x_write_reg(data->client, 0x8c, 0x01); + enable_irq_wake(data->client->irq); + data->suspended = false; + + mutex_unlock(&data->report_mutex); + + +} + +void ft5435_resume_queue_work(void) +{ + cancel_delayed_work(&ft5435_resume_work); + queue_delayed_work(ft5435_resume_workqueue, &ft5435_resume_work, msecs_to_jiffies(FTS_RESUME_WAIT_TIME)); +} + + +int ft5435_resume_init(void) +{ + + INIT_DELAYED_WORK(&ft5435_resume_work, ft5435_resume_func); + ft5435_resume_workqueue = create_workqueue("fts_resume_wq"); + if (ft5435_resume_workqueue == NULL) + { + + } + else + { + + } + + + return 0; +} + +int ft5435_resume_exit(void) +{ + + + destroy_workqueue(ft5435_resume_workqueue); + + return 0; +} + + + +#endif +static void ft5435_update_fw_ver(struct ft5435_ts_data *data) +{ + struct i2c_client *client = data->client; + u8 reg_addr; + int err; + + reg_addr = FT_REG_FW_VER; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_ver[0], 1); + if (err < 0) + dev_err(&client->dev, "fw major version read failed"); + + reg_addr = FT_REG_FW_MIN_VER; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_ver[1], 1); + if (err < 0) + dev_err(&client->dev, "fw minor version read failed"); + + reg_addr = FT_REG_FW_SUB_MIN_VER; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_ver[2], 1); + if (err < 0) + dev_err(&client->dev, "fw sub minor version read failed"); + + dev_info(&client->dev, "Firmware version = %d.%d.%d\n", + data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); +} + +static struct mutex g_device_mutex; + +#if defined(FOCALTECH_TP_GESTURE) + +/* [PLATFORM]-Mod-BEGIN by TCTNB.YQJ, FR797197, 2014/11/28 modify for 5x36 tp register of gesture */ +#define FT5435_REG_GESTURE_SET 0xd0 +#define FT5435_REG_GESTURE_STATE 0xd3 + +#define GESTURE_DB 0x24 + +/* [PLATFORM]-Mod-END by TCTNB.YQJ */ +static int ft_tp_suspend(struct ft5435_ts_data *data); +#if 0 + +static struct class *tp_device_class; + +static struct device *tp_gesture_dev; +static struct device *tp_fw_dev; +/*[Feature]-Add-BEGIN by xingchen.wang, task 1292137, 2016/01/05, modify ft5436_tp_log sys node */ +static struct device *tp_debug_dev; + +/* + u8 gesture_id; 0: close gesture function, + > 0: gesture_ids. 1: for unlock, 2: for power. +*/ +static ssize_t tp_gesture_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + int ret; + + data = dev_get_drvdata(dev); + ret = snprintf(buf, 50, "%d\n", data->gesture_id); + + return ret; +} + +static ssize_t tp_gesture_id_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = NULL; + unsigned long val = 0; + ssize_t ret = -EINVAL; + + data = dev_get_drvdata(dev); + + if (data->suspended) + return ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + + if (0 == val) + { + data->gesture_id = 0x00; + device_init_wakeup(&data->client->dev, 0); + } else + if (val > 0) + { + data->gesture_id = val; + device_init_wakeup(&data->client->dev, 1); + } else { + pr_err("invalid command! \n"); + return -EPERM; + } + printk("gesture_id = %d \n", data->gesture_id); + + return size; +} + + +static ssize_t tp_fw_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + struct i2c_client *client = NULL; + int ret; + + u8 reg_addr, reg_data; + int err; + + data = dev_get_drvdata(dev); + client = data->client; + + ft5435_update_fw_ver(data); + + reg_addr = 0xA8; + err = ft5435_i2c_read(client, ®_addr, 1, ®_data, 1); + if (err < 0) + dev_err(&client->dev, "reg_data"); + + ret = snprintf(buf, 100, "FocalTech TP (0xA8) is 0x%x, fw_version (0xA6) is 0x%x.\n", reg_data, data->fw_ver[0]); + + return ret; +} + +static ssize_t tp_kreg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + struct i2c_client *client = NULL; + int ret; + + u8 reg_addr, reg_data0, reg_data1; + int err; + + data = dev_get_drvdata(dev); + client = data->client; + + reg_data0 = 0; + reg_data1 = 0; + + reg_addr = 0x96; + err = ft5435_i2c_read(client, ®_addr, 1, ®_data0, 1); + if (err < 0) + dev_err(&client->dev, "reg_data0"); + + reg_addr = 0xB0; + err = ft5435_i2c_read(client, ®_addr, 1, ®_data1, 1); + if (err < 0) + dev_err(&client->dev, "reg_data1"); + + ret = snprintf(buf, 100, "FocalTech (0x96) is 0x%x, fw_version (0xB0) is 0x%x.\n", reg_data0, reg_data1); + + return ret; +} +/*[Feature]-Add-BEGIN by xingchen.wang, task 528443, 2015/11/12, add register log*/ +/*[Feature]-Add-BEGIN by xingchen.wang, task 1292137, 2016/01/05, modify ft5436_tp_log sys node */ +static ssize_t ft5436_tp_log_switch_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + struct ft5435_ts_data *data = NULL; + + data = dev_get_drvdata(dev); + + ret = snprintf(buf, 50, "%d\n", data->touch_log_switch); + return ret; +} + + +static ssize_t ft5436_tp_log_switch_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + + struct ft5435_ts_data *data = NULL; + u8 reg = 0x00, *reg_buf; + int i; + + ssize_t ret = -EINVAL; + unsigned long val = 0; + + data = dev_get_drvdata(dev); + + ret = kstrtoul(buf, 10, &val); + if (ret){ + printk("[wxc]kstrtoul failed, ret = %zd\n", ret); + return size; + } + data->touch_log_switch = val; + printk("[wxc]%s, TP debug log show\n", __func__); + printk("[wxc]cover:%d, proximity:%d, vr:%d\n", data->cover_on, vps_ft5436->vps_enabled, data->vr_on); + printk("[wxc]glove:%d\n", data->glove_id); + if (val) + { + reg_buf = data->tch_data; + reg = 0x00; + ret = ft5435_i2c_read(data->client, ®, 1, + reg_buf, 15); + if (ret < 0) { + dev_err(&data->client->dev, "%s: read data i2C fail !!!!\n", __func__); + } + for (i = 0; i < 15; i++){ + printk("[wxc]reg[%d]: reg[0x%2x] = 0x%2x\n", i, i, reg_buf[i]); + } + } + return size; +} + +/*[Feature]-Add-END by xingchen.wang, task 1292137, 2016/01/05 */ +static ssize_t tp_reg_dump_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + int ret; + u8 reg = 0x00, *reg_buf; + + char *s = buf; + int i; + + data = dev_get_drvdata(dev); + reg_buf = data->tch_data; + reg = 0x00; + ret = ft5435_i2c_read(data->client, ®, 1, + reg_buf, 15); + if (ret < 0) { + dev_err(&data->client->dev, "%s: read data fail\n", __func__); + } + for (i = 0; i < 15; i++){ + s += sprintf(s, "reg[%d]: reg[%d] = 0x%x\n", i, i, reg_buf[i]); + printk("reg[%d]: reg[%d] = 0x%x\n", i, i, reg_buf[i]); + } + + return (s - buf); +} + +static DEVICE_ATTR(tp_reg_dump, 0444, tp_reg_dump_show, NULL); +/*[Feature]-Add-END by xingchen.wang, 2015/11/12*/ +/*[Feature]-Add-BEGIN by xingchen.wang, task 1292137, 2016/01/05, modify ft5436_tp_log sys node */ +static DEVICE_ATTR(tp_log_switch, 0644, ft5436_tp_log_switch_show, ft5436_tp_log_switch_store); +/*[Feature]-Add-END by xingchen.wang, task 1292137, 2016/01/05 */ + +static DEVICE_ATTR(doubleclick_enable, 0644, tp_gesture_id_show, tp_gesture_id_store); + +static DEVICE_ATTR(fw_version, 0444, tp_fw_version_show, NULL); + +static DEVICE_ATTR(tp_kreg_val, 0444, tp_kreg_show, NULL); +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add test node for cover funtion*/ + +static ssize_t tp_cover_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + u8 reg; + int ret; + printk("[wxc]%s\n", __func__); + data = dev_get_drvdata(dev); + ret = ft5x0x_read_reg(data->client, 0xC1, ®); + ret |= snprintf(buf, 50, "%d\n", reg); + + return ret; +} + +static ssize_t tp_cover_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = NULL; + unsigned long val = 0; + char val_read = 0; + ssize_t ret = -EINVAL; + char txbuf[2]; + txbuf[0] = 0xc1; + + + data = dev_get_drvdata(dev); + + if (data->suspended){ + printk("[wxc]%s, already in suspend mode\n", __func__); + return ret; + } + + ret = kstrtoul(buf, 10, &val); + if (ret){ + printk("[wxc]%s, kstrtoul failed\n", __func__); + return ret; + } + + if (0 == val) + { + txbuf[1] = 0x00; + ft5435_i2c_write(data->client, txbuf, sizeof(txbuf)); + } else + if (1 == val) + { + txbuf[1] = 0x01; + ft5435_i2c_write(data->client, txbuf, sizeof(txbuf)); + } else { + pr_err("invalid command! \n"); + return -EPERM; + } + ft5435_i2c_read(data->client, &txbuf[0], 1, &val_read, 1); + printk("set cover = %d\n", val_read); + + return size; + +} + +static DEVICE_ATTR(tp_cover, 0644, tp_cover_show, tp_cover_store); +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ + +void tp_gestures_register (struct ft5435_ts_data *data) +{ + int rc = 0; + + tp_device_class = class_create(THIS_MODULE, "tp_device"); + if (IS_ERR(tp_device_class)) + pr_err("Failed to create class(tp_device_class)!\n"); + + tp_gesture_dev = device_create(tp_device_class, NULL, 0, NULL, "tp_gesture"); + + if (IS_ERR(tp_gesture_dev)) + pr_err("Failed to create device(lcd_ce_ctrl)!\n"); + + + + rc = device_create_file(tp_gesture_dev, &dev_attr_doubleclick_enable); + + if (rc < 0) + + pr_err("Failed to create device file(%s)!\n", dev_attr_doubleclick_enable.attr.name); + + rc = device_create_file(tp_gesture_dev, &dev_attr_tp_kreg_val); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_tp_kreg_val.attr.name); + +/*[Feature]-Add-BEGIN by xingchen.wang, task 528443, 2015/11/12, add register log*/ + rc = device_create_file(tp_gesture_dev, &dev_attr_tp_reg_dump); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_tp_reg_dump.attr.name); +/*[Feature]-Add-END by xingchen.wang, 2015/11/12*/ +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add test node for cover funtion*/ + rc = device_create_file(tp_gesture_dev, &dev_attr_tp_cover); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_tp_cover.attr.name); + + dev_set_drvdata(tp_gesture_dev, data); + + tp_fw_dev = device_create(tp_device_class, NULL, 0, NULL, "tp_fw"); + + rc = device_create_file(tp_fw_dev, &dev_attr_fw_version); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_fw_version.attr.name); + + dev_set_drvdata(tp_fw_dev, data); +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +/*[Feature]-Add-BEGIN by xingchen.wang, task 1292137, 2016/01/05, modify ft5436_tp_log sys node */ + tp_debug_dev = device_create(tp_device_class, NULL, 0, NULL, "tp_debug"); + + rc = device_create_file(tp_debug_dev, &dev_attr_tp_log_switch); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_tp_log_switch.attr.name); + + dev_set_drvdata(tp_debug_dev, data); +/*[Feature]-Add-END by xingchen.wang, task 1292137, 2016/01/05 */ + +} +#endif +#endif +static int ft5435_i2c_read(struct i2c_client *client, char *writebuf, + int writelen, char *readbuf, int readlen) +{ + int ret; +#if CTP_ESD_PROTECT + int i = 0; + + for (i = 0; i < 3; i++) + { + ret = fts_esd_protection_notice(); + if (0 == ret) + break; + else + { + + continue; + } + } + if (3 == i) + { + printk("[focal] ESD are still use I2C. \n"); + } + + +#endif + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) + dev_err(&client->dev, "%s: i2c read error.\n", + __func__); + } else { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) + dev_err(&client->dev, "%s:i2c read error.\n", __func__); + } + return ret; +} + +static int ft5435_i2c_write(struct i2c_client *client, char *writebuf, + int writelen) +{ + int ret; + + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + }; + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) + dev_err(&client->dev, "%s: i2c write error.\n", __func__); + return ret; +} + +#if defined(FOCALTECH_TP_GLOVE) + +#define FOCALTECH_TP_GLOVE_SET 0xc0 +#define FOCALTECH_TP_GLOVE_ENABLE 0x01 + +static struct device *tp_glove_dev; + +/* + u8 glove_id; 0: close glove function, 1: open glove function +*/ +static ssize_t tp_glove_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = NULL; + int ret; + + data = dev_get_drvdata(dev); + + ret = snprintf(buf, 50, "glove_id show:%d\n", data->glove_id); + + return ret; +} + +static ssize_t tp_glove_id_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = NULL; + unsigned long val = 0; + char val_read = 0; + ssize_t ret = -EINVAL; + char txbuf[2]; + txbuf[0] = FOCALTECH_TP_GLOVE_SET; + + + data = dev_get_drvdata(dev); + + if (data->suspended) + return ret; + + ret = kstrtoul(buf, 10, &val); + if (ret) + return ret; + + + if (0 == val) + { + data->glove_id = 0x00; + txbuf[1] = 0x00; + ft5435_i2c_write(data->client, txbuf, sizeof(txbuf)); + } else + if (1 == val) + { + data->glove_id = 0x01; + txbuf[1] = FOCALTECH_TP_GLOVE_ENABLE; + ft5435_i2c_write(data->client, txbuf, sizeof(txbuf)); + } else { + pr_err("invalid command! \n"); + return -EPERM; + } + printk("set glove_id = %d \n", data->glove_id); + ft5435_i2c_read(data->client, &txbuf[0], 1, &val_read, 1); + printk("read glove_id = %d\n", val_read); + + return size; +} +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, change sys node for glove funtion*/ +static DEVICE_ATTR(glove_enable, 0644, tp_glove_id_show, tp_glove_id_store); + +void tp_glove_register (struct ft5435_ts_data *data) +{ + int rc = 0; + + tp_glove_dev = device_create(tp_device_class, NULL, 0, NULL, "tp_glove"); + if (IS_ERR(tp_glove_dev)) + pr_err("Failed to create device(glove_ctrl)!\n"); + + + rc = device_create_file(tp_glove_dev, &dev_attr_glove_enable); + if (rc < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_glove_enable.attr.name); +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ + dev_set_drvdata(tp_glove_dev, data); + + printk("~~~~~ %s enable!!!!!\n", __func__); + +} +#endif + + + +static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val) +{ + u8 buf[2] = {0}; + + buf[0] = addr; + buf[1] = val; + + return ft5435_i2c_write(client, buf, sizeof(buf)); +} + +static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val) +{ + return ft5435_i2c_read(client, &addr, 1, val, 1); +} +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add virtual P-sensor funtion*/ +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR +int virtual_psensor_input_register2(struct i2c_client *pClient) +{ + s32 nRetVal = 0; + + pr_err("*** %s() ***\n", __func__); + + vps_ft5436->proximity_dev = input_allocate_device(); + if (vps_ft5436->proximity_dev == NULL) + { + pr_err("*** input device allocation failed ***\n"); + return -ENOMEM; + } + + vps_ft5436->proximity_dev->name = "proximity"; + vps_ft5436->proximity_dev->id.bustype = BUS_I2C; + + /* set the supported event type for input device */ + set_bit(EV_ABS, vps_ft5436->proximity_dev->evbit); + set_bit(ABS_DISTANCE, vps_ft5436->proximity_dev->absbit); + input_set_abs_params(vps_ft5436->proximity_dev, ABS_DISTANCE, 0, 1, 0, 0); + + nRetVal = input_register_device(vps_ft5436->proximity_dev); + if (nRetVal < 0) + { + pr_err("*** Unable to register virtual P-sensor input device ***\n"); + return nRetVal; + } + + vps_ft5436->vps_cdev = virtual_sensors_proximity_cdev2; + vps_ft5436->vps_cdev.sensors_enable = vps_set_enable; + vps_ft5436->vps_cdev.sensors_poll_delay = NULL; + + nRetVal = sensors_classdev_register(&pClient->dev, &vps_ft5436->vps_cdev); + if (nRetVal) { + pr_err("%s: Unable to register to sensors class: %d\n", __func__, nRetVal); + return nRetVal; + } + + return 0; +} +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +static void tp_prox_sensor_enable(struct i2c_client *client, int enable) +{ + u8 state; + int ret = -1; + + if (client == NULL) + return; + + if (gpio_is_valid(g_ft5435_ts_data->pdata->reset_gpio)) { + gpio_set_value_cansleep(g_ft5435_ts_data->pdata->reset_gpio, 0); + printk("reset tp ~~~ \n"); + msleep(g_ft5435_ts_data->pdata->hard_rst_dly); + gpio_set_value_cansleep(g_ft5435_ts_data->pdata->reset_gpio, 1); + } + msleep(g_ft5435_ts_data->pdata->soft_rst_dly); + + if (enable){ + state = 0x01; + }else{ + state = 0x00; + } + ret = ft5x0x_write_reg(client, 0xB0, state); + if (ret < 0) + { + printk("[proxi_5206]write psensor switch command failed\n"); + } + ft5x0x_read_reg(client, 0xB0, &state); + printk(" proximity function status[0x%x]\n", state); + if ((!enable) && (g_ft5435_ts_data->suspended) && (g_ft5435_ts_data->gesture_id > 0)) + { + printk("double click function enable again \n"); + ft_tp_suspend(g_ft5435_ts_data); + } + + return; +} +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add virtual P-sensor funtion*/ +static int vps_set_enable(struct sensors_classdev *sensors_cdev, unsigned int enable) +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +{ + u8 status, reg_value; + + printk("FT vps_set_enable in. enable[%d]\n", enable); + vps_ft5436->vps_enabled = enable ? 1 : 0; + if (enable == 1) + { + ft5x0x_read_reg(g_ft5435_ts_data->client, 0xB0, ®_value); + printk("FT proxi_fts 0xB0 state value is0x%02X\n", reg_value); + if (!(reg_value&0x01)) + { + tp_prox_sensor_enable(g_ft5435_ts_data->client, 1); + } + ft5x0x_read_reg(g_ft5435_ts_data->client, 0x01, &status); + printk("FT 0x01 reg status[0x%x]\n", status); + if (status == 0xC0) + { + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 0); + input_sync(vps_ft5436->proximity_dev); + } + else if (status == 0xE0) + { + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 1); + input_sync(vps_ft5436->proximity_dev); + } + } + + return 0; +} + +ssize_t ft_virtual_proximity_enable_show(struct device *pDevice, struct device_attribute *pAttr, char *pBuf) +{ + return sprintf(pBuf, "%d", vps_ft5436->vps_enabled); +} +ssize_t ft_virtual_proximity_enable_store(struct device *pDevice, struct device_attribute *pAttr, const char *pBuf, size_t nSize) +{ + int enable; + if (pBuf != NULL) + { + sscanf(pBuf, "%d\n", &enable); + vps_set_enable(&vps_ft5436->vps_cdev, enable); + if (g_ft5435_ts_data->gesture_id == 0){ + if (enable) + device_init_wakeup(&g_ft5435_ts_data->client->dev, 1); + else + device_init_wakeup(&g_ft5435_ts_data->client->dev, 0); + } + } + return nSize; +} + +static DEVICE_ATTR(enable, 0664, ft_virtual_proximity_enable_show, ft_virtual_proximity_enable_store); +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, remove virtual P-sensor vendor section*/ + + +#if 0 +ssize_t ft_proximity_vendor_show(struct device *pDevice, struct device_attribute *pAttr, char *pBuf) +{ + switch(vps_ft5436->value) + { + case TAOS:vps_ft5436->vendor = "taos"; break; + case STK:vps_ft5436->vendor = "stk"; break; + default:break; + } + + if (vps_ft5436->vendor == NULL) + return sprintf(pBuf, "%s", "error"); + + return sprintf(pBuf, "%s", vps_ft5436->vendor); +} + +ssize_t ft_proximity_vendor_store(struct device *pDevice, struct device_attribute *pAttr, const char *pBuf, size_t nSize) +{ + extern struct input_dev *get_taos_input_device(void); + extern struct input_dev *get_stk_input_device(void); + + printk("proximity_vendor_store in!\n"); + if (pBuf != NULL) + { + sscanf(pBuf, "%d", &vps_ft5436->value); + if (vps_ft5436->value == 0 || vps_ft5436->value >= TOTAL) + printk("wrong vendor value!\n"); + + switch(vps_ft5436->value) + { + + case TAOS: + + vps_ft5436->proximity_dev = NULL; + if (vps_ft5436->proximity_dev == NULL) + printk("proximity input device is NULL!\n"); + printk("TAOS priximity sensor\n"); + break; + case STK: + + vps_ft5436->proximity_dev = NULL; + if (vps_ft5436->proximity_dev == NULL) + printk("proximity input device is NULL!\n"); + printk("STK priximity sensor\n"); + break; + + default: + printk("error proximity vendor!\n"); + break; + } + } + return nSize; +} +#endif + + + +ssize_t ft_proximity_function_enable_show(struct device *pDevice, struct device_attribute *pAttr, char *pBuf) +{ + return sprintf(pBuf, "%x", vps_ft5436->proximity_function); +} + +ssize_t ft_proximity_function_enable_store(struct device *pDevice, struct device_attribute *pAttr, const char *pBuf, size_t nSize) +{ + u32 nProximityMode; + if (pBuf != NULL) + { + sscanf(pBuf, "%x", &nProximityMode); + printk("nProximityMode = 0x%x\n", nProximityMode); + vps_ft5436->proximity_function = nProximityMode; + tp_prox_sensor_enable(g_ft5435_ts_data->client, nProximityMode); + } + return nSize; +} + +static DEVICE_ATTR(proximity, 0664, ft_proximity_function_enable_show, ft_proximity_function_enable_store); + +static int sys_device_create(void) +{ + struct class *virtual_proximity = NULL; + struct device *virtual_proximity_device = NULL; + + virtual_proximity = class_create(THIS_MODULE, "virtual-proximity"); + if (IS_ERR(virtual_proximity)) + printk("Failed to create class(virtual_proximity)!\n"); + + virtual_proximity_device = device_create(virtual_proximity, NULL, 0, NULL, "device"); + if (IS_ERR(virtual_proximity_device)) + printk("Failed to create device(virtual_proximity_device)!\n"); + + if (device_create_file(virtual_proximity_device, &dev_attr_enable) < 0) + printk("Failed to create device file(%s)!\n", dev_attr_enable.attr.name); + + + +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ + + if (device_create_file(virtual_proximity_device, &dev_attr_proximity) < 0) + printk("Failed to create device file(%s)!\n", dev_attr_enable.attr.name); + + return 0; +} + +#endif +#if defined(LEATHER_COVER) + void ft5435_enable_leather_cover(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->cover_on = 1; + + queue_work(ft5435_wq_cover, &data->work_cover); +} +EXPORT_SYMBOL(ft5435_enable_leather_cover); +void ft5435_disable_leather_cover(void) +{ + struct ft5435_ts_data *data; + + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->cover_on = 0; + + queue_work(ft5435_wq_cover, &data->work_cover); +} +EXPORT_SYMBOL(ft5435_disable_leather_cover); +void ft5435_change_leather_cover_switch(struct work_struct *work) +{ + u8 cover_flag = 0; + struct ft5435_ts_data *data; + + + data = g_ft5435_ts_data; + + if (data->suspended) + { + printk(KERN_ERR"data->suspended, data->cover_on = %d \n", data->cover_on); + return ; + } + if (ft_g_client == NULL) + return ; + ft5x0x_read_reg(ft_g_client, 0xc1, &cover_flag); + printk("[Fu]%s cover_flag=%d, data->cover_on=%d\n", __func__, cover_flag, data->cover_on); + if (cover_flag != data->cover_on) + { + printk(KERN_ERR"[Fu]%s: Write %d to 0xc1\n", __FUNCTION__, data->cover_on); + ft5x0x_write_reg(ft_g_client, 0xc1, data->cover_on); + } +} + +#endif +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add vr function*/ +#if defined(VR_GLASS) + void ft5435_enable_vr(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->vr_on = 1; + + queue_work(ft5435_wq_vr, &data->work_vr); +} +EXPORT_SYMBOL(ft5435_enable_vr); +void ft5435_disable_vr(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + printk("[wxc]%s\n", __func__); + data = g_ft5435_ts_data; + + data->vr_on = 0; + + queue_work(ft5435_wq_vr, &data->work_vr); +} +EXPORT_SYMBOL(ft5435_disable_vr); +void ft5435_change_vr_switch(struct work_struct *work) +{ + u8 vr_flag = 0; + struct ft5435_ts_data *data; + + + data = g_ft5435_ts_data; + + if (data->suspended) + { + printk(KERN_ERR"data->suspended, data->vr_on = %d \n", data->vr_on); + return ; + } + if (ft_g_client == NULL) + return ; + ft5x0x_read_reg(ft_g_client, 0xc1, &vr_flag); + printk("[wxc]%s cover_flag=%d, data->vr_on=%d\n", __func__, vr_flag, data->vr_on); + if (vr_flag != data->vr_on) + { + printk(KERN_ERR"[wxc]%s: Write %d to 0xc1\n", __FUNCTION__, data->vr_on); + ft5x0x_write_reg(ft_g_client, 0xc1, data->vr_on); + } +} + +#endif +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +#if defined(USB_CHARGE_DETECT) + void ft5435_enable_change_scanning_frq(void) +{ + struct ft5435_ts_data *data; + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + + data = g_ft5435_ts_data; + + data->charger_in = 1; + pr_debug("%s \n", __func__); + + queue_work(ft5435_wq, &data->work); +} +EXPORT_SYMBOL(ft5435_enable_change_scanning_frq); +void ft5435_disable_change_scanning_frq(void) +{ + struct ft5435_ts_data *data; + + + if (!ft_g_client) + return ; + if (init_ok == 0) + return; + + data = g_ft5435_ts_data; + + data->charger_in = 0; + pr_debug("%s \n", __func__); + + queue_work(ft5435_wq, &data->work); +} +EXPORT_SYMBOL(ft5435_disable_change_scanning_frq); +void ft5435_change_scanning_frq_switch(struct work_struct *work) +{ + u8 charger_in_flag = 0; + struct ft5435_ts_data *data; + + + data = container_of(work, struct ft5435_ts_data, work); + + if (data->suspended) + { + printk(KERN_ERR"changer_in = %d \n", data->charger_in); + return ; + } + if (ft_g_client == NULL) + return ; + ft5x0x_read_reg(ft_g_client, 0x8b, &charger_in_flag); + + if (charger_in_flag != data->charger_in) + { + printk(KERN_ERR"[ft5435]%s: Write %d to 0x8b\n", __FUNCTION__, data->charger_in); + ft5x0x_write_reg(ft_g_client, 0x8b, data->charger_in); + } +} + +void tpd_usb_plugin(bool mode) +{ + struct ft5435_ts_data *data = g_ft5435_ts_data; + int ret = -1; + if (data->suspended) + { + return ; + } + if (ft_g_client == NULL) + { + return ; + } + ret = ft5x0x_write_reg(ft_g_client, 0x8b, mode); + if (ret < 0) + { + pr_err("usb detect write err: %s %d.\n", __FUNCTION__, mode); + } +} + +#else + void ft5435_enable_change_scanning_frq(void) +{ +} +EXPORT_SYMBOL(ft5435_enable_change_scanning_frq); +void ft5435_disable_change_scanning_frq(void) +{ +} +EXPORT_SYMBOL(ft5435_disable_change_scanning_frq); +#endif +static void ft5435_update_fw_vendor_id(struct ft5435_ts_data *data) +{ + struct i2c_client *client = data->client; + u8 reg_addr; + int err; + + reg_addr = FT_REG_FW_VENDOR_ID; + err = ft5435_i2c_read(client, ®_addr, 1, &data->fw_vendor_id, 1); + if (err < 0) + dev_err(&client->dev, "fw vendor id read failed"); + printk("[Fu]fw_vendor_id=0x%x\n", data->fw_vendor_id); +} + + +int fts_ctpm_auto_clb(struct i2c_client *client) +{ + unsigned char uc_temp = 0x00; + unsigned char i = 0; + + /*start auto CLB */ + msleep(200); + + ft5x0x_write_reg(client, 0, FTS_FACTORYMODE_VALUE); + /*make sure already enter factory mode */ + msleep(100); + /*write command to start calibration */ + ft5x0x_write_reg(client, 2, 0x4); + msleep(300); + for (i = 0; i < 100; i++) { + ft5x0x_read_reg(client, 0, &uc_temp); + /*return to normal mode, calibration finish */ + if (0x0 == ((uc_temp & 0x70) >> 4)) + break; + } + + msleep(200); + /*calibration OK */ + msleep(300); + ft5x0x_write_reg(client, 0, FTS_FACTORYMODE_VALUE); /*goto factory mode for store */ + msleep(100); /*make sure already enter factory mode */ + ft5x0x_write_reg(client, 2, 0x5); /*store CLB result */ + msleep(300); + ft5x0x_write_reg(client, 0, FTS_WORKMODE_VALUE); /*return to normal mode */ + msleep(300); + + /*store CLB result OK */ + return 0; +} + + +/* [PLATFORM]-Mod-BEGIN by TCTNB.ZXZ, PR-814306, 2014/10/24, add for alto5 premium firmware version*/ +#ifdef CONFIG_TCT_8X16_ALTO5_PREMIUM +static struct class *firm_ver_class; +static struct device *firm_ver_dev; + +static ssize_t firm_ver_show (struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 reg_ver; + u8 reg_vendor; + u8 ver_value, vendor_value; + int err; + reg_ver = FT_REG_FW_VER; + err = ft5435_i2c_read(ft_g_client, ®_ver, 1, &ver_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "can't read firmware version \n"); + } + pr_err("0xA6=0x%x\n", ver_value); + reg_vendor = 0xA8; + err = ft5435_i2c_read(ft_g_client, ®_vendor, 1, &vendor_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "ft irmware version(0xA6) is 0x%x\n can't read tp moudule version \n" , ver_value); + } + pr_err("0xA8=0x%x\n", vendor_value); + + return sprintf (buf, "ft TP module (0xA8)is 0x%x , fimware version(0xA6) is 0x%x\n", vendor_value, ver_value); +} + +static DEVICE_ATTR(firm_ver, 0664, firm_ver_show, NULL); + + +static void firm_ver_attr_create(void) +{ + firm_ver_class = class_create(THIS_MODULE, "firmware_ver"); + if (IS_ERR(firm_ver_class)) + pr_err("Failed to create class(firm_ver_class)!\n"); + firm_ver_dev = device_create(firm_ver_class, + NULL, 0, NULL, "device"); + if (IS_ERR(firm_ver_dev)) + pr_err("Failed to create device(gt_dclick_dev)!\n"); + + + if (device_create_file(firm_ver_dev, &dev_attr_firm_ver) < 0) + pr_err("Failed to create device file(%s)!\n", dev_attr_firm_ver.attr.name); +} +#endif +/* [PLATFORM]-Mod-END by TCTNB.ZXZ*/ + +#if defined(FOCALTECH_TP_GESTURE) +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 +static bool gesture_func_on = true; +static int ft5435_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + if (type == EV_SYN && code == SYN_CONFIG) + { + if (value == WAKEUP_OFF){ + gesture_func_on = false; + }else if (value == WAKEUP_ON){ + gesture_func_on = true; + } + } + return 0; +} + +static int ft_tp_interrupt(struct ft5435_ts_data *data) +{ + int rc = 0; + u8 reg_value, reg = 0x00; + printk("[FTS]%s start\n", __func__); + reg = FT5435_REG_GESTURE_STATE; + rc = ft5435_i2c_read(data->client, ®, 1, ®_value, 1); + if (rc < 0) { + dev_err(&data->client->dev, "%s: read data fail\n", __func__); + return rc; + } + + if (GESTURE_DB == reg_value) + { + input_report_key(data->input_dev, KEY_WAKEUP, 1); + input_sync(data->input_dev); + input_report_key(data->input_dev, KEY_WAKEUP, 0); + input_sync(data->input_dev); + printk("[FTS]gesture KEY_POWER\n"); + } else { + printk("[FTS]gesture_id, reg_value=0x%x \n", reg_value); + } + + return rc; +} +#endif +#if FTS_POINT_REPORT_CHECK_EN + +static void ft5435_point_report_check_func(struct work_struct *work) +{ + + + unsigned int finger_count = 0; + + + + /* xlg, 2017.6.23 */ + mutex_lock(&data->report_mutex); + + + for (finger_count = 0; finger_count < g_ft5435_ts_data->pdata->num_max_touches; finger_count++) + { + input_mt_slot(ft5435_input_dev, finger_count); + input_mt_report_slot_state(ft5435_input_dev, MT_TOOL_FINGER, false); + } + + input_report_key(ft5435_input_dev, BTN_TOUCH, 0); + input_sync(ft5435_input_dev); + + mutex_unlock(&data->report_mutex); + +} + +int ft5435_point_report_check_init(void) +{ + + INIT_DELAYED_WORK(&ft5435_point_report_check_work, ft5435_point_report_check_func); + ft5435_point_report_check_workqueue = create_workqueue("fts_point_report_check_func_wq"); + if (ft5435_point_report_check_workqueue == NULL) + { + + } + else + { + + } + + + return 0; +} +#endif + +static irqreturn_t ft5435_ts_interrupt(int irq, void *dev_id) +{ +#if 1 + struct ft5435_ts_data *data = dev_id; + struct input_dev *ip_dev; + int rc, i, j; + u32 id, x, y, status, num_touches; + u8 reg = 0x00, *buf; + bool update_input = false; + + #ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR + u8 reg_value; + u8 proximity_status; + #endif + #ifdef FOCALTECH_TP_GESTURE + int ret = 0; + u8 state = 0; + #endif + if (!data) { + pr_err("%s: Invalid data\n", __func__); + return IRQ_HANDLED; + } +#if defined(FOCALTECH_TP_GESTURE) + if (gesture_func_on){ + ret = ft5x0x_read_reg(data->client, 0xd0, &state); + if (ret < 0) + { + printk("[FTS]read value fail\n"); + } + + if (state == 1) + { + ft_tp_interrupt(data); + return IRQ_HANDLED; + } + } +#endif + + ip_dev = data->input_dev; + buf = data->tch_data; +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR + if (vps_ft5436->vps_enabled) + { + ft5x0x_read_reg(data->client, 0xB0, ®_value); + printk("proxi_fts 0xB0 state value is0x%02X\n", reg_value); + if (!(reg_value&0x01)) + { + tp_prox_sensor_enable(data->client, 1); + } + ft5x0x_read_reg(data->client, 0x01, &proximity_status); + printk("FT 0x01 reg proximity_status[0x%x]--%s\n", proximity_status, __FUNCTION__); + if (proximity_status == 0xC0) + { + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 0); + input_sync(vps_ft5436->proximity_dev); + printk("[Fu]close\n"); + } + else if (proximity_status == 0xE0) + { + wake_lock_timeout(&ft5436_wakelock, 1*HZ); + input_report_abs(vps_ft5436->proximity_dev, ABS_DISTANCE, 1); + input_sync(vps_ft5436->proximity_dev); + printk("[Fu]leave\n"); + } + } +#endif + + + + rc = ft5435_i2c_read(data->client, ®, 1, + buf, data->tch_data_len); + if (rc < 0) { + dev_err(&data->client->dev, "%s: read data fail\n", __func__); + return IRQ_HANDLED; + } + + /* xlg 2017.6.22 */ + mutex_lock(&data->report_mutex); +#if FTS_POINT_REPORT_CHECK_EN + ft5435_point_report_check_queue_work(); +#endif + + + for (i = 0; i < data->pdata->num_max_touches; i++) { + id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4; + if (id >= FT_MAX_ID) + break; + + update_input = true; + + x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 | + (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]); + y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 | + (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]); + + status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6; + + num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK; + + /* invalid combination */ + if (!num_touches && !status && !id) + break; + input_mt_slot(ip_dev, id); + + if (status == FT_TOUCH_DOWN) + printk("[FTS]Down pid[%d]:[%d, %d]\n", id, x, y); + else if (status == 1) + printk("[FTS]Up pid[%d]:[%d, %d]\n", id, x, y); + + if (x < data->pdata->panel_maxx && y < data->pdata->panel_maxy){ + input_mt_slot(ip_dev, id); /* xlg, 2017.6.22 */ + if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) { + input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1); + input_report_abs(ip_dev, ABS_MT_POSITION_X, x); + input_report_abs(ip_dev, ABS_MT_POSITION_Y, y); + /* xlg 2017.6.22 */ + input_report_abs(ip_dev, BTN_TOUCH, 1); + } else { + input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0); + } + }else{ + if (data->pdata->fw_vkey_support){ + for (j = 0; j < data->pdata->num_virkey; j++) { + if (x == data->pdata->vkeys[j].x) { + if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) + input_report_key(data->input_dev, data->pdata->vkeys[j].keycode, true); + else { + input_report_key(data->input_dev, data->pdata->vkeys[j].keycode, false); + } + /* xlg 2017.6.22 */ + input_sync(ip_dev); + } + } + + } + + } + } + if (update_input){ +#if defined(FOCALTECH_FAE_MOD) + if (num_touches == 0) + { /* release all touches */ + for (i = 0; i < 10; i++) { + input_mt_slot(data->input_dev, i); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); + } + /* xlg 2017.6.22 */ + input_report_abs(ip_dev, BTN_TOUCH, 0); + } + /* xlg 2017.6.22 */ + else { + input_report_abs(ip_dev, BTN_TOUCH, 1); + } +#endif + input_mt_report_pointer_emulation(ip_dev, false); + input_sync(ip_dev); + } + /* xlg 2017.6.22 */ + mutex_unlock(&data->report_mutex); + #endif + return IRQ_HANDLED; +} + +static int ft5435_power_on(struct ft5435_ts_data *data, bool on) +{ + int rc; + + if (!on) + goto power_off; + + rc = regulator_enable(data->vdd); + if (rc) { + dev_err(&data->client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + return rc; + } + +#if 1 + rc = regulator_enable(data->vcc_i2c); + if (rc) { + dev_err(&data->client->dev, + "Regulator vcc_i2c enable failed rc=%d\n", rc); + regulator_disable(data->vdd); + } +#endif + + + return rc; + +power_off: +#if 1 + rc = regulator_disable(data->vdd); + if (rc) { + dev_err(&data->client->dev, + "Regulator vdd disable failed rc=%d\n", rc); + return rc; + } +#endif + +#if 1 + rc = regulator_disable(data->vcc_i2c); + if (rc) { + dev_err(&data->client->dev, + "Regulator vcc_i2c disable failed rc=%d\n", rc); + rc = regulator_enable(data->vdd); + if (rc) { + dev_err(&data->client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + } + } +#endif + + + return rc; +} + +static int ft5435_power_init(struct ft5435_ts_data *data, bool on) +{ + int rc; + + if (!on) + goto pwr_deinit; + + data->vdd = regulator_get(&data->client->dev, "vdd"); + if (IS_ERR(data->vdd)) { + rc = PTR_ERR(data->vdd); + dev_err(&data->client->dev, + "Regulator get failed vdd rc=%d\n", rc); + return rc; + } + + if (regulator_count_voltages(data->vdd) > 0) { + rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV, + FT_VTG_MAX_UV); + if (rc) { + dev_err(&data->client->dev, + "Regulator set_vtg failed vdd rc=%d\n", rc); + goto reg_vdd_put; + } + } + +#if 1 + data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c"); + if (IS_ERR(data->vcc_i2c)) { + rc = PTR_ERR(data->vcc_i2c); + dev_err(&data->client->dev, + "Regulator get failed vcc_i2c rc=%d\n", rc); + goto reg_vdd_set_vtg; + } + + if (regulator_count_voltages(data->vcc_i2c) > 0) { + rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV, + FT_I2C_VTG_MAX_UV); + if (rc) { + dev_err(&data->client->dev, + "Regulator set_vtg failed vcc_i2c rc=%d\n", rc); + goto reg_vcc_i2c_put; + } + } +#endif + + + return 0; + +#if 1 +reg_vcc_i2c_put: + regulator_put(data->vcc_i2c); + +reg_vdd_set_vtg: + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV); +#endif + +reg_vdd_put: + regulator_put(data->vdd); + return rc; + +pwr_deinit: + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV); + + regulator_put(data->vdd); + +#if 0 + if (regulator_count_voltages(data->vcc_i2c) > 0) + regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV); + + regulator_put(data->vcc_i2c); +#endif + + return 0; +} + +static int ft5435_ts_pinctrl_init(struct ft5435_ts_data *ft5435_data) +{ + int retval; + + /* Get pinctrl if target uses pinctrl */ + ft5435_data->ts_pinctrl = devm_pinctrl_get(&(ft5435_data->client->dev)); + if (IS_ERR_OR_NULL(ft5435_data->ts_pinctrl)) { + dev_dbg(&ft5435_data->client->dev, + "Target does not use pinctrl\n"); + retval = PTR_ERR(ft5435_data->ts_pinctrl); + ft5435_data->ts_pinctrl = NULL; + goto err_pinctrl_get; + } + + ft5435_data->gpio_state_active + = pinctrl_lookup_state(ft5435_data->ts_pinctrl, + "pmx_ts_active"); + if (IS_ERR_OR_NULL(ft5435_data->gpio_state_active)) { + dev_dbg(&ft5435_data->client->dev, + "Can not get ts default pinstate\n"); + retval = PTR_ERR(ft5435_data->gpio_state_active); + ft5435_data->ts_pinctrl = NULL; + goto err_pinctrl_lookup; + } + + ft5435_data->gpio_state_suspend + = pinctrl_lookup_state(ft5435_data->ts_pinctrl, + "pmx_ts_suspend"); + if (IS_ERR_OR_NULL(ft5435_data->gpio_state_suspend)) { + dev_err(&ft5435_data->client->dev, + "Can not get ts sleep pinstate\n"); + retval = PTR_ERR(ft5435_data->gpio_state_suspend); + ft5435_data->ts_pinctrl = NULL; + goto err_pinctrl_lookup; + } + + return 0; +err_pinctrl_lookup: + devm_pinctrl_put(ft5435_data->ts_pinctrl); +err_pinctrl_get: + ft5435_data->ts_pinctrl = NULL; + return retval; +} + +static int ft5435_ts_pinctrl_select(struct ft5435_ts_data *ft5435_data, + bool on) +{ + struct pinctrl_state *pins_state; + int ret; + pins_state = on ? ft5435_data->gpio_state_active + : ft5435_data->gpio_state_suspend; + if (!IS_ERR_OR_NULL(pins_state)) { + ret = pinctrl_select_state(ft5435_data->ts_pinctrl, pins_state); + if (ret) { + dev_err(&ft5435_data->client->dev, + "can not set %s pins\n", + on ? "pmx_ts_active" : "pmx_ts_suspend"); + return ret; + } + } else { + dev_err(&ft5435_data->client->dev, + "not a valid '%s' pinstate\n", + on ? "pmx_ts_active" : "pmx_ts_suspend"); + } + return 0; +} + + +/******************************************************esd******************************************/ +#ifdef CTP_ESD_PROTECT + + + + +u8 flow_work_cnt_last = 0; +u8 flow_work_hold_cnt = 0; + +u8 i2c_nack_cnt = 0; + + + + /************************************************************************ + * Name: force_reset_guitar + * Brief: reset + * Input: no + * Output: no + * Return: 0 + ***********************************************************************/ + static void force_reset_guitar(void) + { + struct ft5435_ts_data *data; + int i = 0; + + data = g_ft5435_ts_data; + + + gpio_set_value_cansleep(data->pdata->reset_gpio, 0); + msleep(5); + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + msleep(300); + + for (i = 0; i < data->pdata->num_max_touches; i++) { + input_mt_slot(data->input_dev, i); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); + } + + input_mt_report_pointer_emulation(data->input_dev, false); + input_sync(data->input_dev); + + + } + + +static bool get_flow_cnt(void) +{ + struct ft5435_ts_data *data ; + int err = 0; + u8 reg_value = 0; + data = g_ft5435_ts_data; + + + + err = ft5x0x_read_reg(data->client, 0x91, ®_value); + if (err < 0) + { + printk("[ESD]: Read Reg 0x91 failed ret = %d!!", err); + + i2c_nack_cnt++; + printk("Read Reg 0x91 failed, i2c_nack_cnt = %d\n", i2c_nack_cnt); + } + else + { + if (reg_value == flow_work_cnt_last) + { + flow_work_hold_cnt++; + } + else + { + flow_work_hold_cnt = 0; + } + + flow_work_cnt_last = reg_value; + } + + + if (flow_work_hold_cnt >= 5) + { + + + return 1; + } + + return 0; +} + + + + +#define A3_REG_VALUE 0x54 + + +void ctp_esd_check_func(void) +{ + + struct ft5435_ts_data *data ; + int i; + int ret ; + u8 reg_data; + + data = g_ft5435_ts_data; + +/****0xA3*****/ + for (i = 0; i < 3; i++) + { + + ret = ft5x0x_read_reg(data->client, 0xA3, ®_data); + + printk("focal--fts_esd_check_0xA3:ret= %d, 0xA3=0x%02x\n", ret, reg_data); + + if (ret > 0 && A3_REG_VALUE == reg_data) { + break; + } + } + + if (i >= 3) { + force_reset_guitar(); + printk("focal--tpd reset. i >= 3 ret = %d A3_Reg_Value = 0x%02x\n ", ret, reg_data); + + goto FOCAL_RESET_A3_REGISTER; + } + +/***0x91****/ + ret = get_flow_cnt(); + + if (ret == 1) + { + force_reset_guitar(); + printk("Flow Work Cnt(reg0x91) keep a value for 5 times, TP reset\n"); + goto FOCAL_RESET_A3_REGISTER; + } + + + FOCAL_RESET_A3_REGISTER: + + reg_data = 0; + flow_work_hold_cnt = 0 ; + + + return; +} + +#endif + + + + + +/***********************************************************esd*****************************/ +#if defined(FOCALTECH_TP_GESTURE) +static int ft_tp_suspend(struct ft5435_ts_data *data) +{ + int i = 0; + u8 state = 0; + + printk("[FTS] FTS_GESTRUE suspend\n"); + ft5x0x_write_reg(data->client, 0xd0, 0x01); + ft5x0x_write_reg(data->client, 0xd1, 0xff); + ft5x0x_write_reg(data->client, 0xd2, 0xff); + ft5x0x_write_reg(data->client, 0xd5, 0xff); + ft5x0x_write_reg(data->client, 0xd6, 0xff); + ft5x0x_write_reg(data->client, 0xd7, 0xff); + ft5x0x_write_reg(data->client, 0xd8, 0xff); + msleep(10); + + for (i = 0; i < 10; i++) + { + printk("[FTS]tpd_suspend4 %d\t", i); + ft5x0x_read_reg(data->client, 0xd0, &state); + + if (state == 1) + { + printk("[FTS]TPD gesture write 0x01 OK\n"); + break; + } + else + { + ft5x0x_write_reg(data->client, 0xd0, 0x01); + ft5x0x_write_reg(data->client, 0xd1, 0xff); + ft5x0x_write_reg(data->client, 0xd2, 0xff); + ft5x0x_write_reg(data->client, 0xd5, 0xff); + ft5x0x_write_reg(data->client, 0xd6, 0xff); + ft5x0x_write_reg(data->client, 0xd7, 0xff); + ft5x0x_write_reg(data->client, 0xd8, 0xff); + msleep(10); + } + } + + if (i >= 9) + { + printk("[FTS]TPD gesture write 0x01 to d0 fail \n"); + } + + data->suspended = true; + printk("[FTS] FTS_GESTRUE suspend end\n"); + return 0; +} +#endif + +#ifdef CONFIG_PM +static int ft5435_ts_suspend(struct device *dev) +{ + struct ft5435_ts_data *data = g_ft5435_ts_data; + char i; + u8 state = -1; + u8 reg_addr; + u8 reg_value; + +#if (CTP_ESD_PROTECT) + fts_esd_protection_suspend(); +#endif + + if (data->loading_fw) { + dev_info(dev, "Firmware loading in process...\n"); + return 0; + } + + if (data->suspended) { + dev_info(dev, "Already in suspend state\n"); + return 0; + } + + disable_irq_wake(data->client->irq); + + + + + + + + + +#if defined(FOCALTECH_TP_GESTURE) + { + if (gesture_func_on){ + enable_irq_wake(data->client->irq); + ft_tp_suspend(data); + return 0; + } + } +#endif + + reg_addr = FT_REG_ID; + ft5435_i2c_read(data->client, ®_addr, 1, ®_value, 1); + printk("reg_value : %0x\n", reg_value); + + if (reg_value != 0x54){ + printk("i2c read err , set rst\n"); + if (gpio_is_valid(data->pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + msleep(300); + } + }else{ + printk("i2c read OK , no rst\n"); + } + + if (gpio_is_valid(data->pdata->reset_gpio)) { + for (i = 0; i < 10; i++) + { + ft5x0x_write_reg(data->client, 0xa5, 0x03); + ft5x0x_read_reg(data->client, 0xa5, &state); + if ((state != 0) && (state != 1)) + { + printk("[FTS]Ft5435 TPDwrite OK [%d]\n", i); + break; + }else + { + printk("[FTS]Ft5435 TPDwrite Error[%d]\n", i); + } + } + } + +#if 0 + if (data->pdata->power_on) { + err = data->pdata->power_on(false); + if (err) { + dev_err(dev, "power off failed"); + goto pwr_off_fail; + } + } else { + err = ft5435_power_on(data, false); + if (err) { + dev_err(dev, "power off failed"); + goto pwr_off_fail; + } + } +#endif + data->suspended = true; + return 0; +#if 0 +pwr_off_fail: + if (gpio_is_valid(data->pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 0); + msleep(data->pdata->hard_rst_dly); + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + } + enable_irq(data->client->irq); + return err; +#endif +} + +static int ft5435_ts_resume(struct device *dev) +{ + struct ft5435_ts_data *data = g_ft5435_ts_data; + int i = 0; + + + + if (!data->suspended) { + dev_dbg(dev, "Already in awake state\n"); + return 0; + } + /* xlg 2017.6.22 */ + mutex_lock(&data->report_mutex); + for (i = 0; i < data->pdata->num_max_touches; i++) { + input_mt_slot(data->input_dev, i); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0); + } + + /* xlg 2017.6.22 */ + input_report_abs(data->input_dev, BTN_TOUCH, 0); + input_mt_report_pointer_emulation(data->input_dev, false); + input_sync(data->input_dev); + mutex_unlock(&data->report_mutex); + + /* release all touches */ + + + +#if 0 + if (data->pdata->power_on) { + err = data->pdata->power_on(true); + if (err) { + dev_err(dev, "power on failed"); + return err; + } + } else { + err = ft5435_power_on(data, true); + if (err) { + dev_err(dev, "power on failed"); + return err; + } + } +#endif +#if 1/*hw rst*/ + if (gpio_is_valid(data->pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 0); + msleep(2); + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + } +#endif +#if FTS_RESUME_EN + ft5435_resume_queue_work(); +#else + msleep(data->pdata->soft_rst_dly); + + + ft5x0x_write_reg(data->client, 0x8c, 0x01); + enable_irq_wake(data->client->irq); + data->suspended = false; +#endif + +#if defined(USB_CHARGE_DETECT) + queue_work(ft5435_wq, &data->work); +#endif + +#if defined(LEATHER_COVER) + queue_work(ft5435_wq_cover, &data->work_cover); +#endif +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add vr function*/ +#if defined(VR_GLASS) + queue_work(ft5435_wq_vr, &data->work_vr); +#endif +#if CTP_ESD_PROTECT + + fts_esd_protection_resume(); +#endif +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ + return 0; +} + +static const struct dev_pm_ops ft5435_ts_pm_ops = { +#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) + .suspend = ft5435_ts_suspend, + .resume = ft5435_ts_resume, +#endif +}; + +#else +static int ft5435_ts_suspend(struct device *dev) +{ + return 0; +} + +static int ft5435_ts_resume(struct device *dev) +{ + return 0; +} + +#endif + +#if 1 +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct ft5435_ts_data *ft5435_data = + container_of(self, struct ft5435_ts_data, fb_notif); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + ft5435_data && ft5435_data->client) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + ft5435_ts_resume(&ft5435_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + ft5435_ts_suspend(&ft5435_data->client->dev); + } + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void ft5435_ts_early_suspend(struct early_suspend *handler) +{ + struct ft5435_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + ft5435_ts_suspend(&data->client->dev); +} + +static void ft5435_ts_late_resume(struct early_suspend *handler) +{ + struct ft5435_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + ft5435_ts_resume(&data->client->dev); +} +#endif +#else +#if defined(CONFIG_FB) +static void fb_notify_resume_work(struct work_struct *work) +{ + struct ft5435_ts_data *ft5435_data = + container_of(work, struct ft5435_ts_data, fb_notify_work); + ft5435_ts_resume(&ft5435_data->client->dev); +} + +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct ft5435_ts_data *ft5435_data = + container_of(self, struct ft5435_ts_data, fb_notif); + + if (evdata && evdata->data && ft5435_data && ft5435_data->client) { + blank = evdata->data; + if (ft5435_data->pdata->resume_in_workqueue) { + if (event == FB_EARLY_EVENT_BLANK && + *blank == FB_BLANK_UNBLANK) + schedule_work(&ft5435_data->fb_notify_work); + else if (event == FB_EVENT_BLANK && + *blank == FB_BLANK_POWERDOWN) { + flush_work(&ft5435_data->fb_notify_work); + ft5435_ts_suspend(&ft5435_data->client->dev); + } + } else { + if (event == FB_EVENT_BLANK) { + if (*blank == FB_BLANK_UNBLANK) + ft5435_ts_resume( + &ft5435_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + ft5435_ts_suspend( + &ft5435_data->client->dev); + } + } + } + + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void ftft5346_ts_early_suspend(struct early_suspend *handler) +{ + struct ftft5346_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + /* + * During early suspend/late resume, the driver doesn't access xPU/SMMU + * protected HW resources. So, there is no compelling need to block, + * but notifying the userspace that a power event has occurred is + * enough. Hence 'blocking' variable can be set to false. + */ + ft5435_secure_touch_stop(data, false); + ft5435_ts_suspend(&data->client->dev); +} + +static void ft5435_ts_late_resume(struct early_suspend *handler) +{ + struct ft5435_ts_data *data = container_of(handler, + struct ft5435_ts_data, + early_suspend); + + ft5435_secure_touch_stop(data, false); + ft5435_ts_resume(&data->client->dev); +} +#endif + +#endif + +static int ft5435_auto_cal(struct i2c_client *client) +{ + struct ft5435_ts_data *data = i2c_get_clientdata(client); + u8 temp = 0, i; + + /* set to factory mode */ + msleep(2 * data->pdata->soft_rst_dly); + ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE); + msleep(data->pdata->soft_rst_dly); + + /* start calibration */ + ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START); + msleep(2 * data->pdata->soft_rst_dly); + for (i = 0; i < FT_CAL_RETRY; i++) { + ft5x0x_read_reg(client, FT_REG_CAL, &temp); + /*return to normal mode, calibration finish */ + if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN) + break; + } + + /*calibration OK */ + msleep(2 * data->pdata->soft_rst_dly); + ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE); + msleep(data->pdata->soft_rst_dly); + + /* store calibration data */ + ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE); + msleep(2 * data->pdata->soft_rst_dly); + + /* set to normal mode */ + ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE); + msleep(2 * data->pdata->soft_rst_dly); + + return 0; +} + +int hid_to_i2c(struct i2c_client *client) +{ + u8 auc_i2c_write_buf[5] = {0}; + int bRet = 0; + + auc_i2c_write_buf[0] = 0xeb; + auc_i2c_write_buf[1] = 0xaa; + auc_i2c_write_buf[2] = 0x09; + + ft5435_i2c_write(client, auc_i2c_write_buf, 3); + + msleep(10); + + auc_i2c_write_buf[0] = auc_i2c_write_buf[1] = auc_i2c_write_buf[2] = 0; + + ft5435_i2c_read(client, auc_i2c_write_buf, 0, auc_i2c_write_buf, 3); + + + if (1) + { + bRet = 1; + } + else bRet = 0; + return bRet; +} + + +static int ft5435_fw_upgrade_start(struct i2c_client *client, + const u8 *data, u32 data_len) +{ + struct ft5435_ts_data *ts_data = i2c_get_clientdata(client); + struct fw_upgrade_info info = ts_data->pdata->info; + u8 reset_reg; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN]; + int i, j; + u32 pkt_num, pkt_len, temp; + + u8 is_5336_fwsize_30 = false; + u8 fw_ecc; + hid_to_i2c(client); + /* determine firmware size */ + if (*(data + data_len - FT_BLOADER_SIZE_OFF) == FT_BLOADER_NEW_SIZE) + is_5336_fwsize_30 = true; + else + is_5336_fwsize_30 = false; + + for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + /* reset - write 0xaa and 0x55 to reset register */ + if (ts_data->family_id == FT6X06_ID + || ts_data->family_id == FT6X36_ID) + reset_reg = FT_RST_CMD_REG1; + else + reset_reg = FT_RST_CMD_REG1; + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA); + msleep(info.delay_aa); + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55); + if (i <= (FT_UPGRADE_LOOP / 2)) + msleep(info.delay_55 + i * 3); + else + msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2); + hid_to_i2c(client); + msleep(10); + w_buf[0] = 0x55; + w_buf[1] = 0xaa; + temp = 0; + do { + temp++; + ft5435_i2c_write(client, w_buf, 2); + msleep(5); + } while (temp < 1); + + /* check READ_ID */ + msleep(info.delay_readid); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] != info.upgrade_id_1 + || r_buf[1] != info.upgrade_id_2) { + dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1], + info.upgrade_id_1, info.upgrade_id_2); + } else + break; + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + /* erase app and panel paramenter area */ + w_buf[0] = FT_ERASE_APP_REG; + ft5435_i2c_write(client, w_buf, 1); + msleep(info.delay_erase_flash); + + for (i = 0; i < 15; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + printk("1~~~~1 r_buf[0] =%x r_buf[1] = %x \n ", r_buf[0], r_buf[1]); + if (0xF0 == r_buf[0] && 0xAA == r_buf[1]) + { + break; + } + msleep(50); + } + + w_buf[0] = 0xB0; + w_buf[1] = (u8) ((data_len >> 16) & 0xFF); + w_buf[2] = (u8) ((data_len >> 8) & 0xFF); + w_buf[3] = (u8) (data_len & 0xFF); + printk("data_len = %d \n", data_len); + ft5435_i2c_write(client, w_buf, 4); + + +/*********Step 5:write firmware(FW) to ctpm flash*********/ + fw_ecc = 0; + printk("Step 5:write firmware(FW) to ctpm flash\n"); + temp = 0; + pkt_num = (data_len) / FT_FW_PKT_LEN; + pkt_buf[0] = 0xbf; + pkt_buf[1] = 0x00; + printk("@@@@@pkt_num = %x \n", pkt_num); + for (j = 0; j < pkt_num; j++) { + temp = j * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + pkt_len = FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (pkt_len >> 8); + pkt_buf[5] = (u8) pkt_len; + for (i = 0; i < FT_FW_PKT_LEN; i++) { + pkt_buf[6 + i] = data[j * FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, FT_FW_PKT_LEN + 6); + + for (i = 0; i < 30; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + { + break; + } + msleep(1); + } + } + + if ((data_len) % FT_FW_PKT_LEN > 0) { + temp = pkt_num * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + temp = (data_len) % FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (temp >> 8); + pkt_buf[5] = (u8) temp; + + for (i = 0; i < temp; i++) { + pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, temp + 6); + + for (i = 0; i < 30; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + printk("@~~~~@ r_buf[0] =%x r_buf[1] = %x j =%x \n ", r_buf[0], r_buf[1], j); + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + { + break; + } + msleep(1); + } + } + + msleep(50); + + /*********Step 6: read out checksum***********************/ + /*send the opration head */ + printk("Step 6: read out checksum\n"); + w_buf[0] = 0x64; + ft5435_i2c_write(client, w_buf, 1); + msleep(300); + + temp = 0; + w_buf[0] = 0x65; + w_buf[1] = (u8)(temp >> 16); + w_buf[2] = (u8)(temp >> 8); + w_buf[3] = (u8)(temp); + temp = data_len; + w_buf[4] = (u8)(temp >> 8); + w_buf[5] = (u8)(temp); + ft5435_i2c_write(client, w_buf, 6); + msleep(data_len/256); + + for (i = 0; i < 100; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + printk("~~~~ r_buf[0] =%x r_buf[1] = %x \n ", r_buf[0], r_buf[1]); + if (0xF0 == r_buf[0] && 0x55 == r_buf[1]) + { + break; + } + msleep(1); + } + w_buf[0] = 0x66; + ft5435_i2c_read(client, w_buf, 1, r_buf, 1); + if (r_buf[0] != fw_ecc) + { + dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n", + r_buf[0], + fw_ecc); + + return -EIO; + } + printk(KERN_WARNING "checksum %x %x \n", r_buf[0], fw_ecc); + /* reset */ + w_buf[0] = FT_REG_RESET_FW; + ft5435_i2c_write(client, w_buf, 1); + msleep(ts_data->pdata->soft_rst_dly); + + dev_info(&client->dev, "Firmware upgrade successful\n"); + + return 0; +} +#if defined(FOCALTECH_AUTO_UPGRADE) + +static int ft5x46_fw_upgrade_start(struct i2c_client *client, + const u8 *data, u32 data_len) +{ + struct ft5435_ts_data *ts_data = i2c_get_clientdata(client); + struct fw_upgrade_info info = ts_data->pdata->info; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN]; + int i, j, temp; + u32 pkt_num, pkt_len; + u8 fw_ecc; + int i_ret; + + printk("%s\n", __func__); + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + { + printk("[FTS] hid1 change to i2c fail ! \n"); + } + + for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(2); + + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55); + + msleep(200); + + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + { + printk("[FTS] hid%d change to i2c fail ! \n", i); + + } + msleep(10); + + /*********Step 2:Enter upgrade mode *****/ + w_buf[0] = FT_UPGRADE_55; + w_buf[1] = FT_UPGRADE_AA; + i_ret = ft5435_i2c_write(client, w_buf, 2); + + if (i_ret < 0) + { + printk("[FTS] failed writing 0x55 and 0xaa ! \n"); + continue; + } + + /*********Step 3:check READ-ID***********************/ + msleep(1); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + r_buf[0] = r_buf[1] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] == 0x54 && r_buf[1] == 0x2c) { + printk("Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1], info.upgrade_id_1, info.upgrade_id_2); + break; + } else{ + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + r_buf[0], r_buf[1]); + continue; + } + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + + /******Step 4:erase app and panel paramenter area******/ + printk("Step 4:erase app and panel paramenter area\n"); + w_buf[0] = 0x61; + ft5435_i2c_write(client, w_buf, 1); + msleep(1350); + + for (i = 0; i < 15; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if (0xF0 == r_buf[0] && 0xAA == r_buf[1]) + { + break; + } + msleep(50); + + } + + w_buf[0] = 0xB0; + w_buf[1] = (u8) ((data_len >> 16) & 0xFF); + w_buf[2] = (u8) ((data_len >> 8) & 0xFF); + w_buf[3] = (u8) (data_len & 0xFF); + + ft5435_i2c_write(client, w_buf, 4); + + /*********Step 5:write firmware(FW) to ctpm flash*********/ + fw_ecc = 0; + printk("Step 5:write firmware(FW) to ctpm flash\n"); + temp = 0; + pkt_num = (data_len) / FT_FW_PKT_LEN; + pkt_buf[0] = 0xbf; + pkt_buf[1] = 0x00; + + for (j = 0; j < pkt_num; j++) { + temp = j * FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + pkt_len = FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (pkt_len >> 8); + pkt_buf[5] = (u8) pkt_len; + + for (i = 0; i < FT_FW_PKT_LEN; i++) { + pkt_buf[6 + i] = data[j * FT_FW_PKT_LEN + i]; + fw_ecc ^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, FT_FW_PKT_LEN + 6); + + for (i = 0; i < 30; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + { + break; + } + msleep(1); + + } + } + + if ((data_len) % FT_FW_PKT_LEN > 0) { + temp = pkt_num* FT_FW_PKT_LEN; + pkt_buf[2] = (u8) (temp >> 8); + pkt_buf[3] = (u8) temp; + temp = (data_len) % FT_FW_PKT_LEN; + pkt_buf[4] = (u8) (temp >> 8); + pkt_buf[5] = (u8) temp; + + for (i = 0; i < temp; i++) { + pkt_buf[6 + i] = data[pkt_num* FT_FW_PKT_LEN + i]; + fw_ecc^= pkt_buf[6 + i]; + } + ft5435_i2c_write(client, pkt_buf, temp + 6); + + for (i = 0; i < 30; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if ((j + 0x1000) == (((r_buf[0]) << 8) | r_buf[1])) + { + break; + } + msleep(1); + + } + } + + msleep(50); + +/*********Step 6: read out checksum***********************/ + /*send the opration head */ + printk("Step 6: read out checksum\n"); + w_buf[0] = 0x64; + ft5435_i2c_write(client, w_buf, 1); + msleep(300); + + temp = 0; + w_buf[0] = 0x65; + w_buf[1] = (u8)(temp >> 16); + w_buf[2] = (u8)(temp >> 8); + w_buf[3] = (u8)(temp); + temp = data_len; + w_buf[4] = (u8)(temp >> 8); + w_buf[5] = (u8)(temp); + i_ret = ft5435_i2c_write(client, w_buf, 6); + msleep(data_len/256); + + for (i = 0; i < 100; i++) + { + w_buf[0] = 0x6a; + r_buf[0] = r_buf[1] = 0x00; + ft5435_i2c_read(client, w_buf, 1, r_buf, 2); + + if (0xF0 == r_buf[0] && 0x55 == r_buf[1]) + { + break; + } + msleep(1); + + } + w_buf[0] = 0x66; + ft5435_i2c_read(client, w_buf, 1, r_buf, 1); + if (r_buf[0] != fw_ecc) + { + dev_err(&client->dev, "[FTS]--ecc error! FW=%02x bt_ecc=%02x\n", + r_buf[0], fw_ecc); + + return -EIO; + } + printk(KERN_WARNING "checksum %X %X \n", r_buf[0], fw_ecc); + + /*********Step 7: reset the new FW***********************/ + printk("Step 7: reset the new FW\n"); + w_buf[0] = 0x07; + ft5435_i2c_write(client, w_buf, 1); + msleep(130); + + return 0; +} +#endif +#if defined(FOCALTECH_FW_COMPAT) +static int ft5435_fw_upgrade_arbitrate(struct i2c_client *client) +{ + struct ft5435_ts_data *ts_data = i2c_get_clientdata(client); + struct fw_upgrade_info info = ts_data->pdata->info; + u8 reset_reg; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + int i; + + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + /* reset - write 0xaa and 0x55 to reset register */ + if (ts_data->family_id == FT6X06_ID + || ts_data->family_id == FT6X36_ID) + reset_reg = FT_RST_CMD_REG2; + else + reset_reg = FT_RST_CMD_REG1; + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA); + msleep(info.delay_aa); + + ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55); + if (i <= (FT_UPGRADE_LOOP / 2)) + msleep(info.delay_55 + i * 3); + else + msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2); + + /* Enter upgrade mode */ + w_buf[0] = FT_UPGRADE_55; + ft5435_i2c_write(client, w_buf, 1); + usleep(FT_55_AA_DLY_NS); + w_buf[0] = FT_UPGRADE_AA; + ft5435_i2c_write(client, w_buf, 1); + + /* check READ_ID */ + msleep(info.delay_readid); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] != info.upgrade_id_1 + || r_buf[1] != info.upgrade_id_2) { + dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1], + info.upgrade_id_1, info.upgrade_id_2); + } else + break; + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + +/* get tp vid */ + + w_buf[0] = 0x03; + w_buf[1] = 0x00; + w_buf[2] = 0x78; + w_buf[3] = 0x40; + ft5435_i2c_read(client, w_buf, 4, r_buf, 1); + ts_data->fw_compat = r_buf[0]; + printk("%s line=%d, fw_compat=%x \n", __func__, __LINE__, ts_data->fw_compat); + + /* reset */ + w_buf[0] = FT_REG_RESET_FW; + ft5435_i2c_write(client, w_buf, 1); + msleep(ts_data->pdata->soft_rst_dly); + +/* New TP with fw_version >= 0x30 */ + if (ts_data->fw_compat >= 0x30) { + strlcpy(ts_data->fw_name, "ft_fw3.bin", strlen("ft_fw3.bin") + 1); + } + + return 0; +} +#endif + +static unsigned int booting_into_recovery; +static int __init get_boot_mode(char *str) +{ + if (strcmp("boot_with_recovery", str) == 0) { + booting_into_recovery = 1; + } + + printk("zakk: booting_into_recovery=%d\n", booting_into_recovery); + return 0; +} +__setup("androidboot.boot_reason=", get_boot_mode); + +static int ft5435_fw_upgrade(struct device *dev, bool force) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + const struct firmware *fw = NULL; + int rc; + u8 fw_file_maj, fw_file_min, fw_file_sub_min, fw_file_vendor_id; + bool fw_upgrade = false; + + if (data->suspended) { + dev_err(dev, "Device is in suspend state: Exit FW upgrade\n"); + return -EBUSY; + } + +#if defined(FOCALTECH_FW_COMPAT) + rc = ft5435_fw_upgrade_arbitrate(data->client); + if (rc < 0) { + printk(">>-- distinguish tp failed ! \n"); + return rc; + } +#endif + + ft5435_update_fw_vendor_id(data); + + printk("[Fu]%s, booting_into_recovery=%d\n", __func__, booting_into_recovery); + +#if 0 + if (!booting_into_recovery) { + if (data->fw_vendor_id == TRULY) { + rc = request_firmware(&fw, data->fw_name, dev); + } else if (data->fw_vendor_id == CHAOSHENG) { + strcpy(data->fw_name, "chaosheng_fw.bin"); + rc = request_firmware(&fw, data->fw_name, dev); + } else { + printk("[Fu]unknown fw_vendor_id error"); + rc = -1; + } + } else { + + return rc; + } +#endif + rc = request_firmware(&fw, data->fw_name, dev); + + + if (rc < 0) { + dev_err(dev, "[Fu]Request firmware failed - %s (%d)\n", + data->fw_name, rc); + return rc; + } + + if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) { + dev_err(dev, "Invalid firmware size (%zu)\n", fw->size); + rc = -EIO; + goto rel_fw; + } + + if (data->family_id == FT6X36_ID) { + fw_file_maj = FT_FW_FILE_MAJ_VER_FT6X36(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID_FT6X36(fw); + } else { + fw_file_maj = FT_FW_FILE_MAJ_VER(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw); + } + fw_file_min = FT_FW_FILE_MIN_VER(fw); + fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw); + + printk("[Fu]Current firmware: %d.%d.%d", data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + printk("[Fu]New firmware: %d.%d.%d", fw_file_maj, + fw_file_min, fw_file_sub_min); + + if (force) + fw_upgrade = true; + + else if (fw_file_maj == 18 && data->fw_ver[0] != 18){ + fw_upgrade = true; + printk("\n[wxc]roll back firmware to v12 for temp\n"); + } + + else if ((data->fw_ver[0] < fw_file_maj) && + (data->pdata->ignore_id_check || (data->fw_vendor_id == fw_file_vendor_id))) + fw_upgrade = true; + + if (!fw_upgrade) { + dev_info(dev, "Exiting fw upgrade...\n"); + rc = -EFAULT; + goto rel_fw; + } + + /* start firmware upgrade */ + if (FT_FW_CHECK(fw, data)) { + rc = ft5435_fw_upgrade_start(data->client, fw->data, fw->size); + if (rc < 0) + dev_err(dev, "update failed (%d). try later...\n", rc); + else if (data->pdata->info.auto_cal) + ft5435_auto_cal(data->client); + } else { + dev_err(dev, "FW format error\n"); + rc = -EIO; + } + + ft5435_update_fw_ver(data); + + FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + data->pdata->num_max_touches, data->pdata->group_id, + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); +rel_fw: + release_firmware(fw); + return rc; +} +#if defined(FOCALTECH_AUTO_UPGRADE) +static unsigned char ft5435_fw_Vid_get_from_boot( struct i2c_client *client) +{ + unsigned char auc_i2c_write_buf[10]; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0}; + unsigned char i = 0; + unsigned char vid = 0xFF; + int i_ret; + + i_ret = hid_to_i2c(client); + + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(2); + + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55); + + msleep(200); + + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + { + printk("[FTS] hid%d change to i2c fail ! \n", i); + + } + msleep(10); + + /*********Step 2:Enter upgrade mode *****/ + w_buf[0] = FT_UPGRADE_55; + w_buf[1] = FT_UPGRADE_AA; + + i_ret = ft5435_i2c_write(client, w_buf, 2); + + if (i_ret < 0) + { + printk("[FTS] failed writing 0x55 and 0xaa ! \n"); + continue; + } + + /*********Step 3:check READ-ID***********************/ + msleep(1); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + r_buf[0] = r_buf[1] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] == 0x54 && r_buf[1] == 0x2c) { + /* + printk("Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1],info.upgrade_id_1, info.upgrade_id_2); + */ + break; + } else{ + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + r_buf[0], r_buf[1]); + continue; + } + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + + printk("FTS_UPGRADE_LOOP ok is i = %d \n", i); + + msleep(10); + auc_i2c_write_buf[0] = 0x03; + auc_i2c_write_buf[1] = 0x00; + for (i = 0; i < FT_UPGRADE_LOOP; i++) + { + auc_i2c_write_buf[2] = 0xd7; + auc_i2c_write_buf[3] = 0x83; + i_ret = ft5435_i2c_write(client, auc_i2c_write_buf, 4); + if (i_ret < 0) + { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + i_ret = ft5435_i2c_read(client, auc_i2c_write_buf, 0, r_buf, 2); + if (i_ret < 0) + { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + + vid = r_buf[1]; + + printk("%s: REG VAL ID1 = 0x%x, ID2 = 0x%x\n", __func__, r_buf[0], r_buf[1]); + break; + } + + printk("%s: reset the tp\n", __func__); + auc_i2c_write_buf[0] = 0x07; + ft5435_i2c_write(client, auc_i2c_write_buf, 1); + msleep(300); + return vid; +} + +static int ft5435_fw_upgrade_by_array_data(struct device *dev, char *fw_data, int size, bool force) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + struct firmware *fw = NULL; + int rc; + u8 fw_file_maj, fw_file_min, fw_file_sub_min, fw_file_vendor_id; + bool fw_upgrade = false; + char *pfw_data = fw_data; + int fw_size = size; + + printk("%s, suspended=%d\n", __func__, data->suspended); + if (data->suspended) { + dev_err(dev, "Device is in suspend state: Exit FW upgrade\n"); + return -EBUSY; + } + + fw = kzalloc(sizeof(struct firmware), GFP_KERNEL); + fw->size = fw_size; + fw->data = pfw_data; + + if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) { + dev_err(dev, "Invalid firmware size (%zu)\n", fw->size); + rc = -EIO; + goto rel_fw; + } + + if (data->family_id == FT6X36_ID) { + fw_file_maj = FT_FW_FILE_MAJ_VER_FT6X36(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID_FT6X36(fw); + } else { + fw_file_maj = FT_FW_FILE_MAJ_VER(fw); + fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw); + } + fw_file_min = FT_FW_FILE_MIN_VER(fw); + fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw); + + dev_info(dev, "Current firmware: 0x%02x.%d.%d", data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + dev_info(dev, "New firmware: 0x%02x.%d.%d", fw_file_maj, + fw_file_min, fw_file_sub_min); + + if (force) + fw_upgrade = true; + + + else if (data->fw_ver[0] != fw_file_maj) + fw_upgrade = true; + + if (!fw_upgrade) { + dev_info(dev, "Exiting fw upgrade...\n"); + rc = -EFAULT; + goto rel_fw; + } + + /* start firmware upgrade */ + if (data->family_id == FT5X46_ID) { + rc = ft5x46_fw_upgrade_start(data->client, fw->data, fw->size); + if (rc < 0) + dev_err(dev, "update failed (%d). try later...\n", rc); + }else if (FT_FW_CHECK(fw, data)) { + rc = ft5435_fw_upgrade_start(data->client, fw->data, fw->size); + if (rc < 0) + dev_err(dev, "update failed (%d). try later...\n", rc); + else if (data->pdata->info.auto_cal) + ft5435_auto_cal(data->client); + } else { + dev_err(dev, "FW format error\n"); + rc = -EIO; + } + + ft5435_update_fw_ver(data); + + /*FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + data->pdata->num_max_touches, data->pdata->group_id, + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]);*/ + +rel_fw: + kfree(fw); + printk("%s done\n", __func__); + return rc; +} + +#endif +#if defined(FOCALTECH_LOCK_DOWN_INFO) +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = +{ + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; + +static unsigned char ft5435_fw_LockDownInfo_get_from_boot(struct i2c_client *client, char *pProjectCode) +{ + unsigned char auc_i2c_write_buf[10]; + u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[10] = {0}; + unsigned char i = 0, j = 0; + + + int i_ret; + + printk("[fts]%s, fw_vendor_id=0x%02x\n", __func__, fts_fw_vendor_id); + i_ret = hid_to_i2c(client); + + for (i = 0; i < FT_UPGRADE_LOOP; i++) { + msleep(FT_EARSE_DLY_MS); + + /*********Step 1:Reset CTPM *****/ + /*write 0xaa to register 0xfc */ + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_AA); + msleep(2); + + ft5x0x_write_reg(client, 0xfc, FT_UPGRADE_55); + + msleep(200); + + i_ret = hid_to_i2c(client); + + if (i_ret == 0) + { + printk("[FTS] hid%d change to i2c fail ! \n", i); + + } + msleep(10); + + /*********Step 2:Enter upgrade mode *****/ + w_buf[0] = FT_UPGRADE_55; + w_buf[1] = FT_UPGRADE_AA; + i_ret = ft5435_i2c_write(client, w_buf, 2); + + if (i_ret < 0) + { + printk("[FTS] failed writing 0x55 and 0xaa ! \n"); + continue; + } + + /*********Step 3:check READ-ID***********************/ + msleep(10); + w_buf[0] = FT_READ_ID_REG; + w_buf[1] = 0x00; + w_buf[2] = 0x00; + w_buf[3] = 0x00; + + r_buf[0] = r_buf[1] = 0x00; + + ft5435_i2c_read(client, w_buf, 4, r_buf, 2); + + if (r_buf[0] == 0x54 && r_buf[1] == 0x2c) { + /* + printk("Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n", + i, r_buf[0], r_buf[1],info.upgrade_id_1, info.upgrade_id_2); + */ + break; + } else{ + printk("[FTS] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n", + r_buf[0], r_buf[1]); + continue; + } + } + + if (i >= FT_UPGRADE_LOOP) { + dev_err(&client->dev, "Abort upgrade\n"); + return -EIO; + } + + printk("%s, FTS_UPGRADE_LOOP ok is i = %d \n", __func__, i); + + /********* Step 4: read project code from app param area ***********************/ + msleep(10); + auc_i2c_write_buf[0] = 0x03; + auc_i2c_write_buf[1] = 0x00; + for (i = 0; i < FT_UPGRADE_LOOP; i++) + { + auc_i2c_write_buf[2] = 0xd7; + auc_i2c_write_buf[3] = 0xa0; + i_ret = ft5435_i2c_write(client, auc_i2c_write_buf, 4); + if (i_ret < 0) + { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + msleep(10); + i_ret = ft5435_i2c_read(client, auc_i2c_write_buf, 0, r_buf, 8); + if (i_ret < 0) + { + printk("[FTS] Step 4: read lcm id from flash error when i2c write, i_ret = %d\n", i_ret); + continue; + } + + for (j = 0; j < 8; j++) + { + printk("%s: REG VAL = 0x%02x, j=%d\n", __func__, r_buf[j], j); + } + sprintf(pProjectCode, "%02x%02x%02x%02x%02x%02x%02x%02x", \ + r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]); + break; + } + + printk("%s: reset the tp\n", __func__); + auc_i2c_write_buf[0] = 0x07; + ft5435_i2c_write(client, auc_i2c_write_buf, 1); + msleep(300); + return 0; +} +#endif + + +static ssize_t ft5435_update_fw_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + return snprintf(buf, 2, "%d\n", data->loading_fw); +} + +static ssize_t ft5435_update_fw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + unsigned long val; + int rc; + + if (size > 2) + return -EINVAL; + + rc = kstrtoul(buf, 10, &val); + if (rc != 0) + return rc; + + if (data->suspended) { + dev_info(dev, "In suspend state, try again later...\n"); + return size; + } + + mutex_lock(&data->input_dev->mutex); + if (!data->loading_fw && val) { + data->loading_fw = true; + ft5435_fw_upgrade(dev, true); + data->loading_fw = false; + } + mutex_unlock(&data->input_dev->mutex); + + return size; +} + +static DEVICE_ATTR(update_fw, 0664, ft5435_update_fw_show, + ft5435_update_fw_store); + +static ssize_t ft5435_force_update_fw_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + unsigned long val; + int rc; + + if (size > 2) + return -EINVAL; + + rc = kstrtoul(buf, 10, &val); + if (rc != 0) + return rc; + + mutex_lock(&data->input_dev->mutex); + if (!data->loading_fw && val) { + data->loading_fw = true; + ft5435_fw_upgrade(dev, true); + data->loading_fw = false; + } + mutex_unlock(&data->input_dev->mutex); + + return size; +} + +static DEVICE_ATTR(force_update_fw, 0664, ft5435_update_fw_show, + ft5435_force_update_fw_store); + +#ifdef SET_COVER_MODE +static int set_cover_mode_buf; +static ssize_t fts_set_cover_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret = 0; + struct ft5435_ts_data *data = dev_get_drvdata(dev); + sscanf(buf, "%d\n", &set_cover_mode_buf) ; + if (set_cover_mode_buf == 1){ + ret = ft5x0x_write_reg(data->client, 0xC1, 0x01); + ret = ft5x0x_write_reg(data->client, 0xC4, 0x00); + ret = ft5x0x_write_reg(data->client, 0xC5, 0xff); + ret = ft5x0x_write_reg(data->client, 0xC6, 0x00); + ret = ft5x0x_write_reg(data->client, 0xC7, 0x78); + } else if (set_cover_mode_buf == 0){ + ret = ft5x0x_write_reg(data->client, 0xC1, 0x00); + } + + return ret; +} +static DEVICE_ATTR(set_cover_mode, 0664, NULL, + fts_set_cover_mode); + +#endif +static ssize_t ft5435_fw_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name); +} + +static ssize_t ft5435_fw_name_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + + if (size > FT_FW_NAME_MAX_LEN - 1) + return -EINVAL; + + strlcpy(data->fw_name, buf, size); + if (data->fw_name[size-1] == '\n') + data->fw_name[size-1] = 0; + + return size; +} + +static DEVICE_ATTR(fw_name, 0664, ft5435_fw_name_show, ft5435_fw_name_store); + +static ssize_t ft5435_fw_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ft5435_ts_data *data = dev_get_drvdata(dev); + return sprintf(buf, "v%d.%d.%d\n", data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]); +} + +static ssize_t ft5435_fw_version_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + return 0; +} + +static DEVICE_ATTR(fw_version, 0664, ft5435_fw_version_show, ft5435_fw_version_store); + + +static bool ft5435_debug_addr_is_valid(int addr) +{ + if (addr < 0 || addr > 0xFF) { + pr_err("FT reg address is invalid: 0x%x\n", addr); + return false; + } + + return true; +} + +static int ft5435_debug_data_set(void *_data, u64 val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + + if (ft5435_debug_addr_is_valid(data->addr)) + dev_info(&data->client->dev, + "Writing into FT registers not supported\n"); + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +static int ft5435_debug_data_get(void *_data, u64 *val) +{ + struct ft5435_ts_data *data = _data; + int rc; + u8 reg; + + mutex_lock(&data->input_dev->mutex); + + if (ft5435_debug_addr_is_valid(data->addr)) { + rc = ft5x0x_read_reg(data->client, data->addr, ®); + if (rc < 0) + dev_err(&data->client->dev, + "FT read register 0x%x failed (%d)\n", + data->addr, rc); + else + *val = reg; + } + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5435_debug_data_get, + ft5435_debug_data_set, "0x%02llX\n"); + +static int ft5435_debug_addr_set(void *_data, u64 val) +{ + struct ft5435_ts_data *data = _data; + + if (ft5435_debug_addr_is_valid(val)) { + mutex_lock(&data->input_dev->mutex); + data->addr = val; + mutex_unlock(&data->input_dev->mutex); + } + + return 0; +} + +static int ft5435_debug_addr_get(void *_data, u64 *val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + + if (ft5435_debug_addr_is_valid(data->addr)) + *val = data->addr; + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5435_debug_addr_get, + ft5435_debug_addr_set, "0x%02llX\n"); + +static int ft5435_debug_suspend_set(void *_data, u64 val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + + if (val) + ft5435_ts_suspend(&data->client->dev); + else + ft5435_ts_resume(&data->client->dev); + + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +static int ft5435_debug_suspend_get(void *_data, u64 *val) +{ + struct ft5435_ts_data *data = _data; + + mutex_lock(&data->input_dev->mutex); + *val = data->suspended; + mutex_unlock(&data->input_dev->mutex); + + return 0; +} + +#ifdef FOCALTECH_ITO_TEST +struct i2c_client *G_Client = NULL; +#define FTXXXX_INI_FILEPATH "/system/etc/" +#define FTXXXX_SAVEDATA_FILEPATH "/mnt/sdcard/" +static unsigned char ito_test_result = 0; +static unsigned char ito_test_status = 0; + +static int ftxxxx_GetInISize(char *config_name) +{ + struct file *pfile = NULL; + struct inode *inode; + unsigned long magic; + off_t fsize = 0; + char filepath[128]; + memset(filepath, 0, sizeof(filepath)); + + sprintf(filepath, "%s%s", FTXXXX_INI_FILEPATH, config_name); + + if (NULL == pfile) + pfile = filp_open(filepath, O_RDONLY, 0); + + if (IS_ERR(pfile)) { + pr_err("error occured while opening file %s.\n", filepath); + return -EIO; + } + + inode = pfile->f_dentry->d_inode; + magic = inode->i_sb->s_magic; + fsize = inode->i_size; + filp_close(pfile, NULL); + return fsize; +} + +static int ftxxxx_ReadInIData(char *config_name, char *config_buf) +{ + struct file *pfile = NULL; + struct inode *inode; + unsigned long magic; + off_t fsize; + char filepath[128]; + loff_t pos; + mm_segment_t old_fs; + + memset(filepath, 0, sizeof(filepath)); + sprintf(filepath, "%s%s", FTXXXX_INI_FILEPATH, config_name); + if (NULL == pfile) + pfile = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(pfile)) { + pr_err("error occured while opening file %s.\n", filepath); + return -EIO; + } + + inode = pfile->f_dentry->d_inode; + magic = inode->i_sb->s_magic; + fsize = inode->i_size; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_read(pfile, config_buf, fsize, &pos); + filp_close(pfile, NULL); + set_fs(old_fs); + + return 0; +} + +static int ftxxxx_SaveTestData(char *file_name, char *data_buf, int iLen) +{ + struct file *pfile = NULL; + + char filepath[128]; + loff_t pos; + mm_segment_t old_fs; + + memset(filepath, 0, sizeof(filepath)); + sprintf(filepath, "%s%s", FTXXXX_SAVEDATA_FILEPATH, file_name); + if (NULL == pfile) + pfile = filp_open(filepath, O_CREAT|O_RDWR, 0); + if (IS_ERR(pfile)) { + pr_err("error occured while opening file %s.\n", filepath); + return -EIO; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + vfs_write(pfile, data_buf, iLen, &pos); + filp_close(pfile, NULL); + set_fs(old_fs); + + return 0; +} + +char filedata_store[1024*20] ; + +static int ftxxxx_get_testparam_from_ini(char *config_name) +{ + char *filedata = NULL; + + int inisize = ftxxxx_GetInISize(config_name); + + pr_info("inisize = %d \n ", inisize); + if (inisize <= 0) { + pr_err("%s ERROR:Get firmware size failed\n", + __func__); + return -EIO; + } + + + memset(filedata_store, 0, sizeof(filedata_store)); + filedata = filedata_store; + + + if (filedata == NULL) + { + printk("lancelot filedata kmalloc error Null .\n"); + return -EIO; + } + if (ftxxxx_ReadInIData(config_name, filedata)) { + pr_err("%s() - ERROR: request_firmware failed\n", + __func__); + + return -EIO; + } else { + pr_info("ftxxxx_ReadInIData successful\n"); + } + + set_param_data(filedata); + return 0; +} + + +int FTS_I2c_Read(unsigned char *wBuf, int wLen, unsigned char *rBuf, int rLen) +{ + if (NULL == G_Client) + { + return -EPERM; + } + + return ft5435_i2c_read(G_Client, wBuf, wLen, rBuf, rLen); + +} + +int FTS_I2c_Write(unsigned char *wBuf, int wLen) +{ + if (NULL == G_Client) + { + return -EPERM; + } + + return ft5435_i2c_write(G_Client, wBuf, wLen); +} + +static ssize_t ftxxxx_ftsscaptest_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t num_read_chars = 0; + + mutex_lock(&g_device_mutex); + + switch(ito_test_status){ + case 0: + num_read_chars = snprintf(buf, PAGE_SIZE, "0\n"); + break; + case 1: + case 2: + num_read_chars = snprintf(buf, PAGE_SIZE, "1\n"); + break; + case 3: + if (ito_test_result) + num_read_chars = snprintf(buf, PAGE_SIZE, "PASS\n"); + else + num_read_chars = snprintf(buf, PAGE_SIZE, "FAILED\n"); + break; + case 4: + num_read_chars = snprintf(buf, PAGE_SIZE, "FAILED\n"); + break; + } + + mutex_unlock(&g_device_mutex); + + return num_read_chars; +} + +char testdata_store[1024*8]; +static ssize_t ftxxxx_ftsscaptest_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + char cfgname[128]; + int iTestDataLen = 0; + char *testdata = NULL; +#if (CTP_ESD_PROTECT) + fts_esd_protection_suspend(); +#endif + + ito_test_status = 1; + + memset(testdata_store, 0, sizeof(testdata_store)); + testdata = testdata_store; + if (!testdata) + { + printk("kmalloc failed in function:%s\n", __func__); + return -EPERM; + } + printk("tony_test buf=%s\n", buf); + + memset(cfgname, 0, sizeof(cfgname)); + sprintf(cfgname, "%s", buf); + cfgname[count-1] = '\0'; + + mutex_lock(&g_device_mutex); + + init_i2c_write_func(FTS_I2c_Write); + init_i2c_read_func(FTS_I2c_Read); + + if (ftxxxx_get_testparam_from_ini(cfgname) < 0) + { + printk("[FTS]get testparam from ini failure\n"); + } + else + { + printk("[FTS]tp test Start...\n"); + + if (true == start_test_tp()){ + printk("tp test pass\n"); + ito_test_result = 1; + } + else{ + printk("tp test failure\n"); + ito_test_result = 0; + } + ito_test_status = 2; + iTestDataLen = get_test_data(testdata); + printk("%s\n", testdata); + if (0 == ftxxxx_SaveTestData("testdata.csv", testdata, iTestDataLen)) + ito_test_status = 3; + else + ito_test_status = 4; + + + } + + free_test_param_data(); + + mutex_unlock(&g_device_mutex); +#if (CTP_ESD_PROTECT) + fts_esd_protection_resume(); +#endif + + return count; +} +static DEVICE_ATTR(ftsmcaptest, 0664, ftxxxx_ftsscaptest_show, ftxxxx_ftsscaptest_store); + +#endif + + + +DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5435_debug_suspend_get, + ft5435_debug_suspend_set, "%lld\n"); + +static int ft5435_debug_dump_info(struct seq_file *m, void *v) +{ + struct ft5435_ts_data *data = m->private; + + seq_printf(m, "%s\n", data->ts_info); + + return 0; +} + +static int debugfs_dump_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, ft5435_debug_dump_info, inode->i_private); +} + +static const struct file_operations debug_dump_info_fops = { + .owner = THIS_MODULE, + .open = debugfs_dump_info_open, + .read = seq_read, + .release = single_release, +}; + +#ifdef CONFIG_OF +static int ft5435_get_dt_coords(struct device *dev, char *name, + struct ft5435_ts_platform_data *pdata) +{ + u32 coords[FT_COORDS_ARR_SIZE]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + coords_size = prop->length / sizeof(u32); + if (coords_size != FT_COORDS_ARR_SIZE) { + dev_err(dev, "invalid %s\n", name); + return -EINVAL; + } + + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read %s\n", name); + return rc; + } + + if (!strcmp(name, "focaltech,panel-coords")) { + pdata->panel_minx = coords[0]; + pdata->panel_miny = coords[1]; + pdata->panel_maxx = coords[2]; + pdata->panel_maxy = coords[3]; + } else if (!strcmp(name, "focaltech,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + dev_err(dev, "unsupported property %s\n", name); + return -EINVAL; + } + + return 0; +} +static int ft5435_get_dt_vkey(struct device *dev, struct ft5435_ts_platform_data *pdata) +{ + u32 coords[FOCALTECH_MAX_VKEY_NUM]; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size, rc, i; + char name[128]; + memset(name, 0, sizeof(name)); + + sprintf(name, "focal,virtual_key_1"); + prop = of_find_property(np, name, NULL); + printk("[%s]000\n", __FUNCTION__); + if (!prop) + return -EINVAL; + printk("[%s]111\n", __FUNCTION__); + if (!prop->value) + return -ENODATA; + printk("[%s]222\n", __FUNCTION__); + coords_size = prop->length / sizeof(u32); + if (coords_size != pdata->num_virkey) { + printk("[%s]invalid %s\n", __FUNCTION__, name); + return -EINVAL; + } + printk("[%s]333\n", __FUNCTION__); + for (i = 0; i < pdata->num_virkey; i++) { + sprintf(name, "focal,virtual_key_%d", i+1); + rc = of_property_read_u32_array(np, name, coords, coords_size); + if (rc && (rc != -EINVAL)) { + printk("[%s]Unable to read %s\n", __FUNCTION__, name); + return rc; + } + + pdata->vkeys[i].keycode = coords[0]; + pdata->vkeys[i].x = coords[1]; + pdata->vkeys[i].y = coords[2]; + printk("[FTS]keycode = %d, x= %d, y=%d \n", pdata->vkeys[i].keycode, + pdata->vkeys[i].x, pdata->vkeys[i].y); + } + printk("[%s]5555\n", __FUNCTION__); + return 0; + + +} + +static int ft5435_parse_dt(struct device *dev, + struct ft5435_ts_platform_data *pdata) +{ + int rc; + struct device_node *np = dev->of_node; + u32 temp_val; + + pdata->name = "focaltech"; + rc = of_property_read_string(np, "focaltech,name", &pdata->name); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read name\n"); + return rc; + } + + rc = ft5435_get_dt_coords(dev, "focaltech,panel-coords", pdata); + if (rc && (rc != -EINVAL)) + return rc; + + rc = ft5435_get_dt_coords(dev, "focaltech,display-coords", pdata); + if (rc) + return rc; + + pdata->i2c_pull_up = of_property_read_bool(np, + "focaltech,i2c-pull-up"); + + pdata->no_force_update = of_property_read_bool(np, + "focaltech,no-force-update"); + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", + 0, &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) + return pdata->reset_gpio; + + pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", + 0, &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) + return pdata->irq_gpio; + + pdata->fw_name = "ft_fw.bin"; + rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw name\n"); + return rc; + } + + rc = of_property_read_u32(np, "focaltech,group-id", &temp_val); + if (!rc) + pdata->group_id = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms", + &temp_val); + if (!rc) + pdata->hard_rst_dly = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms", + &temp_val); + if (!rc) + pdata->soft_rst_dly = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val); + if (!rc) + pdata->num_max_touches = temp_val; + else + return rc; + + rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay aa\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_aa = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay 55\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_55 = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw upgrade id1\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.upgrade_id_1 = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw upgrade id2\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.upgrade_id_2 = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms", + &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay read id\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_readid = temp_val; + + rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms", + &temp_val); + if (rc && (rc != -EINVAL)) { + dev_err(dev, "Unable to read fw delay erase flash\n"); + return rc; + } else if (rc != -EINVAL) + pdata->info.delay_erase_flash = temp_val; + + pdata->info.auto_cal = of_property_read_bool(np, + "focaltech,fw-auto-cal"); + + pdata->resume_in_workqueue = of_property_read_bool(np, + "focaltech,resume-in-workqueue"); + + + pdata->fw_vkey_support = of_property_read_bool(np, + "focaltech,fw-vkey-support"); + + pdata->ignore_id_check = of_property_read_bool(np, + "focaltech,ignore-id-check"); + + rc = of_property_read_u32(np, "focaltech,num-virtual-key", &temp_val); + if (rc && (rc != -EINVAL)){ + printk("[%s]focaltech,num-virtual-key, dts parase failed\n", __FUNCTION__); + return rc; + } + else if (rc != -EINVAL){ + pdata->num_virkey = temp_val; + } + rc = ft5435_get_dt_vkey(dev, pdata); + if (rc){ + printk("[%s]focaltech,ft5435_get_dt_vkey failed\n", __FUNCTION__); + return rc; + } + + rc = of_property_read_u32(np, "focaltech,family-id", &temp_val); + if (!rc) + pdata->family_id = temp_val; + else + return rc; + + return 0; +} +#else +static int ft5435_parse_dt(struct device *dev, + struct ft5435_ts_platform_data *pdata) +{ + return -ENODEV; +} +#endif + +#if defined(FOCALTECH_PWRON_UPGRADE) +static void ft_init_update_work(struct work_struct *work) +{ + struct delayed_work *delay_work; + struct ft5435_ts_data *ts; + struct device *dev; + + delay_work = to_delayed_work(work); + ts = container_of(delay_work, struct ft5435_ts_data, focaltech_update_work); + dev = &ts->input_dev->dev; + + mutex_lock(&ts->input_dev->mutex); + ft5435_fw_upgrade(dev, false); + + mutex_unlock(&ts->input_dev->mutex); +} + +u8 ft_init_update_proc(struct ft5435_ts_data *ts) +{ + dev_dbg(&ts->client->dev, "Ready to run update work."); + + INIT_DELAYED_WORK(&ts->focaltech_update_work, ft_init_update_work); + schedule_delayed_work(&ts->focaltech_update_work, + msecs_to_jiffies(3000)); + + return 0; +} +#endif + +#if defined(FOCALTECH_TP_GESTURE) +void keyset_for_tp_gesture(struct input_dev *input_dev) +{ + input_set_capability(input_dev, EV_KEY, KEY_WAKEUP); + +} +#endif + + +#if defined(RAWDATA_INTERFACE) +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1208391, 2016/01/06, new rawdata interface*/ +extern struct ft5435_rawdata_test_result ft5436_rawdata_test_result; +extern int rawdata_fail_num; +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1208391, 2016/01/06*/ +#define FTS_TX_MAX 40 +#define FTS_RX_MAX 40 +#define FTS_DEVICE_MODE_REG 0x00 +#define FTS_RAW_READ_REG 0x01 +#define FTS_RAW_BEGIN_REG 0x10 + +static int ft5x0x_enter_factory(void) +{ + u8 regval; + + ft5x0x_write_reg(ft_g_client, 0, 0x40); + mdelay(100); + if (ft5x0x_read_reg(ft_g_client, 0x00, ®val) < 0){ + pr_err("%s ERROR: could not read register\n", __FUNCTION__); + return -EPERM; + } + + if ((regval & 0x70) != 0x40) + { + pr_err("%s ERROR:Touch Panel put in Factory Mode err. Mode reg: 0x%02X\n", __func__, regval); + return -EPERM; + } + + return 0; +} + +static int ft5x0x_enter_work(void) +{ + u8 regval; + ft5x0x_write_reg(ft_g_client, 0x00, 0x00); + msleep(100); + + if (ft5x0x_read_reg(ft_g_client, 0x00, ®val) < 0){ + pr_err("%s ERROR: could not read register\n", __FUNCTION__); + return -EPERM; + } + + if ((regval & 0x70) != 0x00) + { + pr_err("%s ERROR:Touch Panel put in Work Mode err. Mode reg: 0x%02X\n", __func__, regval); + return -EPERM; + } + + return 0; +} + + +static int ft5x0x_read_rawdata(u16 rawdata[][FTS_RX_MAX], + u8 tx, u8 rx) +{ + u8 i = 0, j = 0, k = 0; + int err = 0; + u8 regvalue = 0x00; + u8 regaddr = 0x00; + u16 dataval = 0x0000; + u8 writebuf[2] = {0}; + u8 read_buffer[FTS_RX_MAX * 2]; + /*scan*/ + err = ft5x0x_read_reg(ft_g_client, FTS_DEVICE_MODE_REG, ®value); + if (err < 0) + return err; + + regvalue |= 0x80; + err = ft5x0x_write_reg(ft_g_client, FTS_DEVICE_MODE_REG, regvalue); + if (err < 0) + return err; + + for (i = 0; i < 20; i++) + { + msleep(8); + err = ft5x0x_read_reg(ft_g_client,FTS_DEVICE_MODE_REG, + ®value); + if (err < 0) + return err; + + if (0 == (regvalue >> 7)) + break; + } + + /*get rawdata*/ + + for (i = 0; i < tx; i++) + { + memset(read_buffer, 0x00, (FTS_RX_MAX * 2)); + writebuf[0] = FTS_RAW_READ_REG; + writebuf[1] = i; + err = ft5435_i2c_write(ft_g_client, writebuf, 2); + if (err < 0) { + return err; + } + /* Read the data for this row */ + regaddr = FTS_RAW_BEGIN_REG; + err = ft5435_i2c_read(ft_g_client, ®addr, 1, read_buffer, rx*2); + if (err < 0) { + return err; + } + + k = 0; + for (j = 0; j < rx*2; j += 2){ + dataval = read_buffer[j]; + dataval = (dataval << 8); + dataval |= read_buffer[j+1]; + rawdata[i][k] = dataval; + k++; + } + } + + return 0; +} + +static int fts_get_channel_info(u8 *rx, u8 *tx) +{ + /*get rx and tx num*/ + if (ft5x0x_read_reg(ft_g_client, 0x02, tx) < 0){ + printk("%s: get tx info err!\n", __func__); + return -EPERM; + } + + if (ft5x0x_read_reg(ft_g_client, 0x03, rx) < 0){ + printk("%s: get rx info err!\n", __func__); + return -EPERM; + } + + return 0; +} + +static u16 g_rawdata[FTS_TX_MAX][FTS_RX_MAX]; +static ssize_t ft5435_rawdata_register(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + struct ft5435_ts_data *data = i2c_get_clientdata(ft_g_client); + int i, j, p = 0; + u8 rx, tx; + int ret; + +printk("ft5435_rawdata_register: start\n"); + mutex_lock(&data->input_dev->mutex); + if (data->loading_fw) { + p = sprintf(buf+p, "loading fw!!!"); + goto RAW_ERROR; + } + + data->loading_fw = true; + if (ft5x0x_enter_factory()){ + p = sprintf(buf+p, "enter factory mode err!!!"); + goto RAW_ERROR; + } + + if (fts_get_channel_info( &rx, &tx)){ + p = sprintf(buf+p, "read channel info error!!\n"); + goto RAW_ERROR; + } + +/*[BUGFIX] ADD BEGIN - hui.wang,2014/03/17 PR-618021 To get the params*/ + p+=sprintf(buf+p, "tp channel: tx = %u, rx = %u\n", tx, rx); +/*[BUGFIX] ADD END - hui.wang,2014/03/17 PR-618021 To get the params*/ + + ret = ft5x0x_read_rawdata(g_rawdata, tx, rx); + + if (ret < 0) { + p = sprintf(buf+p, "rawdata read error!\n"); + goto RAW_ERROR; + } + + for (i = 0; i < tx; i++){ + for (j = 0; j < rx; j++){ + p+=sprintf(buf+p, "%u ", g_rawdata[i][j]); + } + p+=sprintf(buf+p, "\n"); + } + +RAW_ERROR: + /*enter work mode*/ + data->loading_fw = false; + if (ft5x0x_enter_work()) + p = sprintf(buf+p, "enter work mode error!!\n"); + msleep(100); + mutex_unlock(&data->input_dev->mutex); + return p; +} +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1208391, 2016/01/06, new rawdata interface*/ +static ssize_t rd_result_show (struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + char *s = buf; + int i; + + + s += sprintf(s, "**************************\nAA Zone:"); + + if (rawdata_fail_num == 0){ + s += sprintf(s, "PASS\n"); + } else { + s += sprintf(s, "NG\n"); + for (i = 0; i < rawdata_fail_num; i ++){ + if (ft5436_rawdata_test_result.index[i][1] < 25){ + s += sprintf(s, "X%dY%d(%u)\n", ft5436_rawdata_test_result.index[i][0], + ft5436_rawdata_test_result.index[i][1], + ft5436_rawdata_test_result.index[i][2]); + } + } + } + s += sprintf(s, "Min: %u Max: %u\n", ft5436_rawdata_test_result.min_value, ft5436_rawdata_test_result.max_value); + s += sprintf(s, "Spec Min: %u Max: %u\n", ft5436_rawdata_test_result.min_limited_value, ft5436_rawdata_test_result.max_limited_value); + + + s += sprintf(s, "**************************\nKey Zone:"); + if (rawdata_fail_num == 0){ + s += sprintf(s, "PASS\n"); + } else { + s += sprintf(s, "NG\n"); + } + s += sprintf(s, "Spec Min: %u Max: %u\n", ft5436_rawdata_test_result.min_limited_value, ft5436_rawdata_test_result.max_limited_value); + s += sprintf(s, "**************************\n"); + + return (s-buf); +} + + +static ssize_t jrd_ic_info_show (struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + u8 reg_ver; + u8 reg_vendor; + u8 ver_value, vendor_value; + int err; + char *ret = buf; + + reg_ver = FT_REG_FW_VER; + err = ft5435_i2c_read(ft_g_client, ®_ver, 1, &ver_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "can't read firmware version \n"); + } + pr_err("0xA6=0x%x\n", ver_value); + reg_vendor = 0xA8; + err = ft5435_i2c_read(ft_g_client, ®_vendor, 1, &vendor_value, 1); + if (err < 0) { + pr_err("TP FW version read failure\n"); + return sprintf (buf, "ft irmware version(0xA6) is 0x%x\n can't read tp moudule version \n" , ver_value); + } + pr_err("0xA8=0x%x\n", vendor_value); + + ret += sprintf(ret, "%s", "TP IC: FT5436\n"); + ret += sprintf(ret, "TP module (0xA8) is 0x%x\n", vendor_value); + ret += sprintf(ret, "fimware version (0xA6) is 0x%x\n", ver_value); + return (ret - buf); +} + +static struct kobj_attribute ft5435_rawdata_attr = { + .attr = { + .name = "ft5435_rawdata", + .mode = S_IRUGO, + }, + .show = &ft5435_rawdata_register, +}; + +static struct kobj_attribute rd_result = { + .attr = { + .name = "rd_result", + .mode = S_IRUGO, + }, + .show = &rd_result_show, +}; + +static struct kobj_attribute ft5435_ic_info_attr = { + .attr = { + .name = "jrd_tp_ic_info", + .mode = S_IRUGO, + }, + .show = &jrd_ic_info_show, +}; + + +static struct kobj_attribute ft5435_ftsscaptest_attr = { + .attr = { + .name = "ft5435_ftsscaptest", + .mode = S_IRUGO | S_IWUGO, + }, + .show = &ftxxxx_ftsscaptest_show, + .store = &ftxxxx_ftsscaptest_store, +}; + +static struct attribute *ft5435_rawdata_properties_attrs[] = { + &ft5435_rawdata_attr.attr, + &rd_result.attr, + &ft5435_ftsscaptest_attr.attr, + &ft5435_ic_info_attr.attr, + NULL, +}; +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1208391, 2016/01/06*/ +static struct attribute_group ft5435_rawdata_properties_attr_group = { + .attrs = ft5435_rawdata_properties_attrs, +}; +#endif + +#if defined(CONFIG_TCT_TP_FTDEBUG) +#define FTS_PACKET_LENGTH 128 +#define PROC_UPGRADE 0 +#define PROC_READ_REGISTER 1 +#define PROC_WRITE_REGISTER 2 +#define PROC_AUTOCLB 4 +#define PROC_UPGRADE_INFO 5 +#define PROC_WRITE_DATA 6 +#define PROC_READ_DATA 7 + +#define PROC_NAME "ft5x0x-debug" +static unsigned char proc_operate_mode = PROC_UPGRADE; +static struct proc_dir_entry *ft5x0x_proc_entry; + + +/*interface of write proc*/ +static ssize_t ft5x0x_debug_write(struct file *filp, const char __user *buffer, size_t count, loff_t *off) +{ + struct i2c_client *client = ft_g_client; + unsigned char writebuf[FTS_PACKET_LENGTH]; + int buflen = count; + int writelen = 0; + int ret = 0; + + if (copy_from_user(writebuf, (void __user *)buffer, buflen)) { + dev_err(&client->dev, "%s:copy from user error\n", __func__); + return -EFAULT; + } + + proc_operate_mode = writebuf[0]; + printk("proc_operate_mode = %d\n", proc_operate_mode); + switch (proc_operate_mode) { + case PROC_READ_REGISTER: + printk("%s, %d:PROC_READ_REGISTER\n", __func__, __LINE__); + writelen = 1; + ret = ft5435_i2c_write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + case PROC_WRITE_REGISTER: + printk("%s, %d:PROC_WRITE_REGISTER\n", __func__, __LINE__); + writelen = 2; + ret = ft5435_i2c_write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + case PROC_AUTOCLB: + printk("%s, %d:PROC_AUTOCLB\n", __func__, __LINE__); + printk("%s: autoclb\n", __func__); + fts_ctpm_auto_clb(client); + break; + case PROC_READ_DATA: + case PROC_WRITE_DATA: + printk("%s, %d:PROC_READ_DATA, PROC_WRITE_DATA\n", __func__, __LINE__); + writelen = count - 1; + ret = ft5435_i2c_write(client, writebuf + 1, writelen); + if (ret < 0) { + dev_err(&client->dev, "%s:write iic error\n", __func__); + return ret; + } + break; + default: + printk("%s, %d:default\n", __func__, __LINE__); + break; + } + + return count; +} + +/*interface of read proc*/ +static ssize_t ft5x0x_debug_read(struct file *file, char __user *page, size_t size, loff_t *ppos) +{ + struct i2c_client *client = ft_g_client; + int ret = 0; + unsigned char buf[1000]; + int num_read_chars = 0; + int readlen = 0; + u8 regvalue = 0x00, regaddr = 0x00; + + switch (proc_operate_mode) { + case PROC_UPGRADE: + /*after calling ft5x0x_debug_write to upgrade*/ + printk("%s, %d:PROC_UPGRADE\n", __func__, __LINE__); + regaddr = 0xA6; + ret = ft5x0x_read_reg(client, regaddr, ®value); + if (ret < 0) + num_read_chars = sprintf(buf, "%s", "get fw version failed.\n"); + else + num_read_chars = sprintf(buf, "current fw version:0x%02x\n", regvalue); + break; + case PROC_READ_REGISTER: + readlen = 1; + ret = ft5435_i2c_read(client, NULL, 0, buf, readlen); + if (ret < 0) { + dev_err(&client->dev, "%s:read iic error\n", __func__); + return ret; + } + printk("%s, %d:PROC_READ_REGISTER, buf = %c\n", __func__, __LINE__, *buf); + num_read_chars = 1; + break; + case PROC_READ_DATA: + printk("%s, %d:PROC_READ_DATA\n", __func__, __LINE__); + readlen = size; + ret = ft5435_i2c_read(client, NULL, 0, buf, readlen); + if (ret < 0) { + dev_err(&client->dev, "%s:read iic error\n", __func__); + return ret; + } + + num_read_chars = readlen; + break; + case PROC_WRITE_DATA: + printk("%s, %d:PROC_WRITE_DATA\n", __func__, __LINE__); + break; + default: + printk("%s, %d:default\n", __func__, __LINE__); + break; + } + + memcpy(page, buf, num_read_chars); + + return num_read_chars; +} + +static const struct file_operations ft5x0x_debug_ops = { + .owner = THIS_MODULE, + .read = ft5x0x_debug_read, + .write = ft5x0x_debug_write, +}; + +static int ft5x0x_create_apk_debug_channel(struct i2c_client *client) +{ + ft5x0x_proc_entry = proc_create(PROC_NAME, 0777, NULL, &ft5x0x_debug_ops); + + if (NULL == ft5x0x_proc_entry) { + dev_err(&client->dev, "Couldn't create proc entry!\n"); + return -ENOMEM; + } else { + dev_info(&client->dev, "Create proc entry success!\n"); + + + + } + return 0; +} + +static void ft5x0x_release_apk_debug_channel(void) +{ + if (ft5x0x_proc_entry) + remove_proc_entry(PROC_NAME, NULL); +} +#endif + + +static char tp_info_summary[80] = ""; + +static int ft5435_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ft5435_ts_platform_data *pdata; + struct ft5435_ts_data *data; + struct input_dev *input_dev; + struct dentry *temp; + u8 reg_value; + u8 reg_addr; + int err, len; + u8 w_buf[FT_MAX_WR_BUF] = {0}; + int i; + int retry = 3; + char tp_temp_info[80]; + printk("~~~~~ ft5435_ts_probe start\n"); + #ifdef FOCALTECH_ITO_TEST + G_Client = client; + #endif + +#if defined(CONFIG_FB) + printk("[%s]CONFIG_FB is defined\n", __FUNCTION__); +#endif +#if defined(CONFIG_PM) + printk("[%s]CONFIG_PM is defined\n", __FUNCTION__); +#endif + + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, + sizeof(struct ft5435_ts_platform_data), GFP_KERNEL); + if (!pdata) { + dev_err(&client->dev, "Failed to allocate memory\n"); + return -ENOMEM; + } + + err = ft5435_parse_dt(&client->dev, pdata); + if (err) { + dev_err(&client->dev, "DT parsing failed\n"); + return err; + } + } else + pdata = client->dev.platform_data; + + if (!pdata) { + dev_err(&client->dev, "Invalid pdata\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "I2C not supported\n"); + return -ENODEV; + } + + data = devm_kzalloc(&client->dev, + sizeof(struct ft5435_ts_data), GFP_KERNEL); + if (!data) { + dev_err(&client->dev, "Not enough memory\n"); + return -ENOMEM; + } + + if (pdata->fw_name) { + len = strlen(pdata->fw_name); + if (len > FT_FW_NAME_MAX_LEN - 1) { + dev_err(&client->dev, "Invalid firmware name\n"); + return -EINVAL; + } + + strlcpy(data->fw_name, pdata->fw_name, len + 1); + } + + data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches); + data->tch_data = devm_kzalloc(&client->dev, + data->tch_data_len, GFP_KERNEL); + if (!data) { + dev_err(&client->dev, "Not enough memory\n"); + return -ENOMEM; + } + + ft5435_input_dev = input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&client->dev, "failed to allocate input device\n"); + return -ENOMEM; + } + + ft_g_client = client; + data->input_dev = input_dev; + data->client = client; + data->pdata = pdata; + + input_dev->name = "ft5435_ts"; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &client->dev; + + input_set_drvdata(input_dev, data); + i2c_set_clientdata(client, data); + + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + + for (i = 0; i < pdata->num_virkey; i++) { + input_set_capability(input_dev, EV_KEY, + pdata->vkeys[i].keycode); + } + input_mt_init_slots(input_dev, pdata->num_max_touches, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, + pdata->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, + pdata->y_max, 0, 0); +#if defined(USB_CHARGE_DETECT) +INIT_WORK(&data->work, ft5435_change_scanning_frq_switch); +#endif + +#if defined(LEATHER_COVER) +INIT_WORK(&data->work_cover, ft5435_change_leather_cover_switch); +#endif +#if defined(VR_GLASS) +INIT_WORK(&data->work_vr, ft5435_change_vr_switch); +#endif + + + +#if defined(FOCALTECH_TP_GESTURE) + keyset_for_tp_gesture(input_dev); + input_dev->event = ft5435_gesture_switch; +#endif + err = input_register_device(input_dev); + if (err) { + dev_err(&client->dev, "Input device registration failed\n"); + goto free_inputdev; + } + + if (gpio_is_valid(pdata->reset_gpio)) { + err = gpio_request(pdata->reset_gpio, "ft5435_reset_gpio"); + if (err) { + dev_err(&client->dev, "reset gpio request failed"); + goto unreg_inputdev; + } + + err = gpio_direction_output(pdata->reset_gpio, 0); + if (err) { + dev_err(&client->dev, + "set_direction for reset gpio failed\n"); + goto free_reset_gpio; + } + msleep(2); + } + + if (pdata->power_init) { + err = pdata->power_init(true); + if (err) { + dev_err(&client->dev, "power init failed"); + goto free_reset_gpio; + } + } else { + err = ft5435_power_init(data, true); + if (err) { + dev_err(&client->dev, "power init failed"); + goto free_reset_gpio; + } + } + + if (pdata->power_on) { + err = pdata->power_on(true); + if (err) { + dev_err(&client->dev, "power on failed"); + goto pwr_deinit; + } + } else { + err = ft5435_power_on(data, true); + if (err) { + dev_err(&client->dev, "power on failed"); + goto pwr_deinit; + } + } + + msleep(2); + + err = ft5435_ts_pinctrl_init(data); + if (!err && data->ts_pinctrl) { + err = ft5435_ts_pinctrl_select(data, true); + if (err < 0) + goto pwr_off; + } + + if (gpio_is_valid(pdata->irq_gpio)) { + err = gpio_request(pdata->irq_gpio, "ft5435_irq_gpio"); + if (err) { + dev_err(&client->dev, "irq gpio request failed"); + goto pwr_off; + } + err = gpio_direction_input(pdata->irq_gpio); + if (err) { + dev_err(&client->dev, + "set_direction for irq gpio failed\n"); + goto free_irq_gpio; + } + } + + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + } + + /* make sure CTP already finish startup process */ + msleep(data->pdata->soft_rst_dly); + + /* check the controller id */ + reg_addr = FT_REG_ID; + while(retry--){ + err = ft5435_i2c_read(client, ®_addr, 1, ®_value, 1); + if (!(err < 0)){ + + dev_info(&client->dev, "Device ID = 0x%x\n", reg_value); + break; + } + if (gpio_is_valid(pdata->reset_gpio)) { + gpio_set_value_cansleep(data->pdata->reset_gpio, 0); + msleep(10); + gpio_set_value_cansleep(data->pdata->reset_gpio, 1); + msleep(200); + } + if (retry==0) { + dev_err(&client->dev, "version read failed"); + goto free_irq_gpio; + } + } +#if 0 + if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) { + dev_err(&client->dev, "%s:Unsupported controller\n", __func__); + goto free_irq_gpio; + } else { + is_ft5435 = true; + } +#endif + data->family_id = pdata->family_id; + + +#ifdef CONFIG_TOUCHPANEL_PROXIMITY_SENSOR + vps_ft5436 = kzalloc(sizeof(struct virtualpsensor), GFP_KERNEL); + if (!vps_ft5436) { + dev_err(&client->dev, "Not enough memory\n"); + return -ENOMEM; + } +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add virtual P-sensor function*/ + virtual_psensor_input_register2(client) ; +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ + sys_device_create(); +#endif + + + mutex_init(&g_device_mutex); + +#if defined(FOCALTECH_PWRON_UPGRADE) + err = ft_init_update_proc(data); + if (err < 0) { + dev_err(&client->dev, + "GTP Create firmware update thread error.\n"); + + } +#endif + mutex_init(&data->report_mutex); /* xlg, 2017.6.22 */ + err = request_threaded_irq(client->irq, NULL, + ft5435_ts_interrupt, + pdata->irqflags | IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + client->dev.driver->name, data); + if (err) { + dev_err(&client->dev, "request irq failed\n"); + goto free_reset_gpio; + } + +#if CTP_ESD_PROTECT + + fts_esd_protection_init(); + +#endif +#if FTS_POINT_REPORT_CHECK_EN + ft5435_point_report_check_init(); +#endif + +#if FTS_RESUME_EN + ft5435_resume_init(); +#endif + + err = device_create_file(&client->dev, &dev_attr_fw_name); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto irq_free; + } + + err = device_create_file(&client->dev, &dev_attr_fw_version); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_fw_name_sys; + } + + #ifdef FOCALTECH_ITO_TEST + err = device_create_file(&client->dev, &dev_attr_ftsmcaptest); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_fw_version_sys; + } + #endif + + err = device_create_file(&client->dev, &dev_attr_update_fw); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + #ifdef FOCALTECH_ITO_TEST + goto free_ftsmcaptest_sys; + #else + goto free_fw_version_sys; + #endif + } + + err = device_create_file(&client->dev, &dev_attr_force_update_fw); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_update_fw_sys; + } +#ifdef SET_COVER_MODE + err = device_create_file(&client->dev, &dev_attr_set_cover_mode); + if (err) { + dev_err(&client->dev, "sys file creation failed\n"); + goto free_set_cover_mode; + } +#endif + data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL); + if (data->dir == NULL || IS_ERR(data->dir)) { + pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir)); + err = PTR_ERR(data->dir); + goto free_force_update_fw_sys; + } + + temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, data->dir, data, + &debug_addr_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, data->dir, data, + &debug_data_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, data->dir, + data, &debug_suspend_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR, data->dir, + data, &debug_dump_info_fops); + if (temp == NULL || IS_ERR(temp)) { + pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp)); + err = PTR_ERR(temp); + goto free_debug_dir; + } + + data->ts_info = devm_kzalloc(&client->dev, + FT_INFO_MAX_LEN, GFP_KERNEL); + if (!data->ts_info) { + dev_err(&client->dev, "Not enough memory\n"); + goto free_debug_dir; + } + + /*get some register information */ + reg_addr = FT_REG_POINT_RATE; + ft5435_i2c_read(client, ®_addr, 1, ®_value, 1); + if (err < 0) + dev_err(&client->dev, "report rate read failed"); + + dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10); + + reg_addr = FT_REG_THGROUP; + err = ft5435_i2c_read(client, ®_addr, 1, ®_value, 1); + if (err < 0) + dev_err(&client->dev, "threshold read failed"); + + dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4); + +#ifdef FOCALTECH_LOCK_DOWN_INFO + ft5435_fw_LockDownInfo_get_from_boot(client, tp_lockdown_info); + printk("tpd_probe, ft5x46_ctpm_LockDownInfo_get_from_boot, tp_lockdown_info=%s\n", tp_lockdown_info); + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) + { + printk("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); + } +#endif + + ft5435_update_fw_ver(data); + ft5435_update_fw_vendor_id(data); + if (data->fw_vendor_id == 0x51){ + printk("Ft5435 + Ofilm + TM\n"); + fts_fw_vendor_id = data->fw_vendor_id; + } else if (data->fw_vendor_id == 0xd0){ + printk("Ft5435 + Biel + EGGB\n"); + fts_fw_vendor_id = data->fw_vendor_id; + }else if (data->fw_vendor_id == 0x3b){ + if (!strncmp(tp_lockdown_info, "3136", 4)){ + printk("Ft5435 +Biel + TM\n"); + fts_fw_vendor_id = data->fw_vendor_id; + }else if (!strncmp(tp_lockdown_info, "3137", 4)){ + printk("Ft5435 +Biel + EGGB\n"); + fts_fw_vendor_id = 0xd0; + } + }else{ + printk("fw_vendor_id is unkwon \n"); + } + + printk("upgrade, data->fw_vendor_id = 0x%02x, fts_fw_vendor_id=0x%02x, \n", data->fw_vendor_id, fts_fw_vendor_id); +#if defined(FOCALTECH_AUTO_UPGRADE) +#if (CTP_ESD_PROTECT) + fts_esd_protection_suspend(); +#endif + if ((fts_fw_vendor_id != FTS_VENDOR_1) && (fts_fw_vendor_id != FTS_VENDOR_2) && ((fts_fw_vendor_id != FTS_VENDOR_3))) + { + fts_fw_vendor_id = ft5435_fw_Vid_get_from_boot(client); + printk("get_Vid_from_boot, fw_vendor_id=0x%02x\n", fts_fw_vendor_id); + } + + mutex_lock(&data->input_dev->mutex); + if (!data->loading_fw) + { + data->loading_fw = true; + if (fts_fw_vendor_id == FTS_VENDOR_1) + ft5435_fw_upgrade_by_array_data(&client->dev, firmware_data_vendor1, sizeof(firmware_data_vendor1), !data->pdata->no_force_update); + else if (fts_fw_vendor_id == FTS_VENDOR_2) + ft5435_fw_upgrade_by_array_data(&client->dev, firmware_data_vendor2, sizeof(firmware_data_vendor2), !data->pdata->no_force_update); + else if (fts_fw_vendor_id == FTS_VENDOR_3) + ft5435_fw_upgrade_by_array_data(&client->dev, firmware_data_vendor3, sizeof(firmware_data_vendor3), !data->pdata->no_force_update); + else + printk("[FTS] FW unmatched,stop upgrade\n"); + data->loading_fw = false; + } + mutex_unlock(&data->input_dev->mutex); +#if (CTP_ESD_PROTECT) + fts_esd_protection_resume(); +#endif + + +#endif + + FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name, + data->pdata->num_max_touches, data->pdata->group_id, + data->pdata->fw_vkey_support ? "yes" : "no", + data->pdata->fw_name, data->fw_ver[0], + data->fw_ver[1], data->fw_ver[2]); + +#if defined(CONFIG_FB) + + data->fb_notif.notifier_call = fb_notifier_callback; + + err = fb_register_client(&data->fb_notif); + + if (err) + dev_err(&client->dev, "Unable to register fb_notifier: %d\n", + err); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + + FT_SUSPEND_LEVEL; + data->early_suspend.suspend = ft5435_ts_early_suspend; + data->early_suspend.resume = ft5435_ts_late_resume; + register_early_suspend(&data->early_suspend); +#endif + + +/* [PLATFORM]-Mod-BEGIN by TCTNB.ZXZ, PR-814306, 2014/10/24, add for alto5 premium firmware version*/ +#ifdef CONFIG_TCT_8X16_ALTO5_PREMIUM +firm_ver_attr_create(); +#endif +/* [PLATFORM]-Mod-END by TCTNB.ZXZ*/ + +#if 0 + tp_gestures_register(data); +#endif + +#ifdef FOCALTECH_TP_GLOVE + tp_glove_register(data); +#endif + + +g_ft5435_ts_data = data; + + +#if defined(RAWDATA_INTERFACE) +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1208391, 2016/01/06, new rawdata interface*/ +{ + static struct kobject *ft5435_rawdata_properties_kobj; + static struct kobject *ft5435_CTP_properties_kobj; + int rc = 0; + + ft5435_rawdata_properties_kobj = + kobject_create_and_add("rawdata", NULL); + + if (ft5435_rawdata_properties_kobj) + rc = sysfs_create_group(ft5435_rawdata_properties_kobj, + &ft5435_rawdata_properties_attr_group); + + if (!ft5435_rawdata_properties_kobj || rc) + pr_err("%s: failed to create rawdata\n", __func__); + + ft5435_CTP_properties_kobj = + kobject_create_and_add("CTP", NULL); + + if (ft5435_CTP_properties_kobj) + rc = sysfs_create_group(ft5435_CTP_properties_kobj, + &ft5435_rawdata_properties_attr_group); + + if (!ft5435_CTP_properties_kobj || rc) + pr_err("%s: failed to create rawdata\n", __func__); +} +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1208391, 2016/01/06*/ +#endif + +#if defined(CONFIG_TCT_TP_FTDEBUG) + if (ft5x0x_create_apk_debug_channel(client) < 0) + ft5x0x_release_apk_debug_channel(); +#endif + + w_buf[0] = FT_REG_RESET_FW; + ft5435_i2c_write(client, w_buf, 1); + init_ok = 1; + wake_lock_init(&ft5436_wakelock, WAKE_LOCK_SUSPEND, "ft5436"); + if (fts_fw_vendor_id == FTS_VENDOR_1){ + strcpy(tp_info_summary, "[Vendor]Biel + TM, [IC]FT5435, [FW]Ver"); + }else if (fts_fw_vendor_id == FTS_VENDOR_2){ + strcpy(tp_info_summary, "[Vendor]Ofilm + EGGB, [IC]FT5435, [FW]Ver"); + }else if (fts_fw_vendor_id == FTS_VENDOR_3){ + strcpy(tp_info_summary, "[Vendor]Biel + EGGB, [IC]FT5435, [FW]Ver"); + }else{ + strcpy(tp_info_summary, "[Vendor]Unknown, [IC]FT5435, [FW]Ver"); + } + sprintf(tp_temp_info, "%d", data->fw_ver[0]); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + + printk("~~~~~ ft5435_ts_probe end\n"); + return 0; + +free_debug_dir: + debugfs_remove_recursive(data->dir); +free_force_update_fw_sys: + device_remove_file(&client->dev, &dev_attr_force_update_fw); +free_update_fw_sys: + device_remove_file(&client->dev, &dev_attr_update_fw); + +#ifdef SET_COVER_MODE +free_set_cover_mode: + device_remove_file(&client->dev, &dev_attr_set_cover_mode); +#endif + +#ifdef FOCALTECH_ITO_TEST +free_ftsmcaptest_sys: + device_remove_file(&client->dev, &dev_attr_ftsmcaptest); +#endif +free_fw_version_sys: + device_remove_file(&client->dev, &dev_attr_fw_version); + +free_fw_name_sys: + device_remove_file(&client->dev, &dev_attr_fw_name); +irq_free: + free_irq(client->irq, data); + +free_irq_gpio: + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); + if (data->ts_pinctrl) { + err = ft5435_ts_pinctrl_select(data, false); + if (err < 0) + pr_err("Cannot get idle pinctrl state\n"); + } + if (data->ts_pinctrl) { + devm_pinctrl_put(data->ts_pinctrl); + data->ts_pinctrl = NULL; + } + if (gpio_is_valid(pdata->reset_gpio)){ + gpio_direction_output(pdata->reset_gpio, 1); + mdelay(2); + } +pwr_off: + if (pdata->power_on) + pdata->power_on(false); + else + ft5435_power_on(data, false); +pwr_deinit: + if (pdata->power_init) + pdata->power_init(false); + else + ft5435_power_init(data, false); +free_reset_gpio: + if (gpio_is_valid(pdata->reset_gpio)){ + gpio_direction_output(pdata->reset_gpio, 1); + mdelay(5); + gpio_free(pdata->reset_gpio); + } +unreg_inputdev: + input_unregister_device(input_dev); + input_dev = NULL; +free_inputdev: + input_free_device(input_dev); + return err; +} + +static int ft5435_ts_remove(struct i2c_client *client) +{ + struct ft5435_ts_data *data = i2c_get_clientdata(client); + int retval; + #if CTP_ESD_PROTECT + fts_esd_protection_exit(); + #endif + debugfs_remove_recursive(data->dir); + device_remove_file(&client->dev, &dev_attr_force_update_fw); + device_remove_file(&client->dev, &dev_attr_update_fw); + device_remove_file(&client->dev, &dev_attr_fw_name); + +#if defined(CONFIG_FB) + if (fb_unregister_client(&data->fb_notif)) + dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&data->early_suspend); +#endif + free_irq(client->irq, data); + + if (gpio_is_valid(data->pdata->reset_gpio)) + gpio_free(data->pdata->reset_gpio); + + if (gpio_is_valid(data->pdata->irq_gpio)) + gpio_free(data->pdata->irq_gpio); + + if (data->ts_pinctrl) { + retval = ft5435_ts_pinctrl_select(data, false); + if (retval < 0) + pr_err("Cannot get idle pinctrl state\n"); + devm_pinctrl_put(data->ts_pinctrl); + data->ts_pinctrl = NULL; + } + + if (data->pdata->power_on) + data->pdata->power_on(false); + else + ft5435_power_on(data, false); + + if (data->pdata->power_init) + data->pdata->power_init(false); + else + ft5435_power_init(data, false); + + +#if defined(CONFIG_TCT_TP_FTDEBUG) + ft5x0x_release_apk_debug_channel(); +#endif + + input_unregister_device(data->input_dev); + wake_lock_destroy(&ft5436_wakelock); + + return 0; +} + +static const struct i2c_device_id ft5435_ts_id[] = { + {"ft5435_ts", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, ft5435_ts_id); + +#ifdef CONFIG_OF +static struct of_device_id ft5435_match_table[] = { + { .compatible = "focaltech,5435",}, + { }, +}; +#else +#define ft5435_match_table NULL +#endif + +static struct i2c_driver ft5435_ts_driver = { + .probe = ft5435_ts_probe, + .remove = ft5435_ts_remove, + .driver = { + .name = "ft5435_ts", + .owner = THIS_MODULE, + .of_match_table = ft5435_match_table, +#ifdef CONFIG_PM + .pm = &ft5435_ts_pm_ops, +#endif + }, + .id_table = ft5435_ts_id, +}; + +static int __init ft5435_ts_init(void) +{ + printk("tony_test:[%s]\n", __FUNCTION__); + ft5435_wq = create_singlethread_workqueue("ft5435_wq"); + if (!ft5435_wq) + { + printk("Creat ft5435 workqueue failed. \n"); + return -ENOMEM; + } + ft5435_wq_cover = create_singlethread_workqueue("ft5435_wq_cover"); + if (!ft5435_wq_cover) + { + printk("Creat ft5435_wq_cover workqueue failed. \n"); + return -ENOMEM; + } +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add vr function*/ +#if defined(VR_GLASS) + ft5435_wq_vr = create_singlethread_workqueue("ft5435_wq_vr"); + if (!ft5435_wq_vr) + { + printk("Creat ft5435_wq_vr workqueue failed. \n"); + return -ENOMEM; + } +#endif +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ + return i2c_add_driver(&ft5435_ts_driver); +} +module_init(ft5435_ts_init); + +static void __exit ft5435_ts_exit(void) +{ + if (ft5435_wq) + { + destroy_workqueue(ft5435_wq); + } + i2c_del_driver(&ft5435_ts_driver); +} +module_exit(ft5435_ts_exit); + +MODULE_DESCRIPTION("FocalTech ft5435 TouchScreen driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/ft5435/ft5435_ts.h b/drivers/input/touchscreen/ft5435/ft5435_ts.h new file mode 100644 index 0000000000000..a4036dd07ed29 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ft5435_ts.h @@ -0,0 +1,104 @@ +/* + * + * FocalTech ft5435 TouchScreen driver header file. + * + * Copyright (c) 2010 Focal tech Ltd. + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __LINUX_FT5435_TS_H__ +#define __LINUX_FT5435_TS_H__ + +#define FT5435_ID 0x55 +#define FT5X16_ID 0x0A +#define FT5X36_ID 0x14 +#define FT6X06_ID 0x06 +#define FT6X36_ID 0x36 +/* [PLATFORM]-Mod-BEGIN by TCTNB.YQJ, FR797197, 2014/11/28 add for tp gesture */ + +#define SET_COVER_MODE +#define FOCALTECH_AUTO_UPGRADE 1 +#define FOCALTECH_LOCK_DOWN_INFO 1 +#define FOCALTECH_TP_GESTURE +#define FOCALTECH_FAE_MOD + +#define USB_CHARGE_DETECT +#define FOCALTECH_ITO_TEST 1 +#define FOCALTECH_MAX_VKEY_NUM 3 +#define CTP_ESD_PROTECT 0 + + +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1238223, 2015/12/25, add vr funtion*/ + +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1238223, 2015/12/25*/ +/* [PLATFORM]-Mod-END by TCTNB.YQJ*/ + + + + +struct fw_upgrade_info { + bool auto_cal; + u16 delay_aa; + u16 delay_55; + u8 upgrade_id_1; + u8 upgrade_id_2; + u16 delay_readid; + u16 delay_erase_flash; +}; +struct virkey{ + int keycode; + int x; + int y; +}; +struct ft5435_ts_platform_data { + struct fw_upgrade_info info; + const char *name; + const char *fw_name; + u32 irqflags; + u32 irq_gpio; + u32 irq_gpio_flags; + u32 reset_gpio; + u32 reset_gpio_flags; + u32 family_id; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 panel_minx; + u32 panel_miny; + u32 panel_maxx; + u32 panel_maxy; + u32 group_id; + u32 hard_rst_dly; + u32 soft_rst_dly; + u32 num_max_touches; + bool fw_vkey_support; + bool no_force_update; + bool i2c_pull_up; + bool ignore_id_check; + bool resume_in_workqueue; + int (*power_init) (bool); + int (*power_on) (bool); + int num_virkey; + struct virkey vkeys[FOCALTECH_MAX_VKEY_NUM]; +}; +/*[FEATURE]-Modified-BEGIN by TCTSH.xingchen.wang for task 1208391, 2016/01/06, new rawdata interface*/ +struct ft5435_rawdata_test_result { + int result; + int min_limited_value; + int max_limited_value; + int min_value; + int max_value; + int index[350][3]; +}; +/*[FEATURE]-Modified-END by TCTSH.xingchen.wang for task 1208391, 2016/01/06*/ +#endif diff --git a/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0x3b.ini b/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0x3b.ini new file mode 100644 index 0000000000000..7425e2eb31cd2 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0x3b.ini @@ -0,0 +1,293 @@ +[Valid_File] +OnlyMultipleTest=1 +[Interface] +IC_Type=FT5435 +Normalize_Type=1 +Interface_Type=0 +Slave_Addr=0x70 +Freq_Index=2 +Phase_Pola=-1 +Max_Points=10 +iRotationDegree=0 +isReversed=0 +ixMaxPixel=1080 +iyMaxPixel=1920 +[Config] +Run_Mode=0 +Read_Bytes=256 +Write_Bytes=128 +Test_Way=0 +Handle_SN=0 +SN_Length=18 +SN_AutoTest=1 +SKey_Index=0 +SKeyValue=13 +TP_AutoTest=0 +TP_AutoTest_Time=0 +TP_ReplaceTP=0 +TP_ReplaceTP_Time=0 +TP_Always_Replace=0 +TP_Always_Replace_Time=0 +Store_Result=0 +Auto_Switch=0 +Continue_Test_After_Fail=0 +CB_Test_Mode=1 +Tip_After_TestNG=0 +Show_Res=0 +Check_Mode=0 +Non_Common_GND=0 +Output_LevelSignal=0 +Output_NgSignal=0 +Input_LevelSignal=0 +Reverse_Time=0 +Switch_Protocol=0 +CLB_Other_Return=0 +Count_Result=0 +Count_Result_Type=0 +Full_Screen=0 +Impulsing=0 +Use_LockDown=0 +[Android_Terminal] +I2C_Interface=0 +I2C_Index=0 +RW_Byte=1 +CustomConfPath=0 +AutoSave=1 +ResultPath= +[OnLine_Setting] +IPAddress=127.0.0.1 +TCPPort=5555 +[TestItem] +FW_VERSION_TEST=0 +FACTORY_ID_TEST=0 +IC_VERSION_TEST=0 +PROJECT_CODE_TEST=0 +LCM_ID_TEST=0 +PANEL_ID_TEST=0 +RAWDATA_TEST=1 +ADC_DETECT_TEST=0 +PANEL_DIFFER_TEST=1 +PANEL_DIFFER_UNIFORMITY_TEST=0 +SCAP_CB_TEST=1 +SCAP_RAWDATA_TEST=1 +CHANNEL_NUM_TEST=0 +INT_PIN_TEST=0 +RESET_PIN_TEST=0 +NOISE_TEST=0 +WEAK_SHORT_CIRCUIT_TEST=0 +UNIFORMITY_TEST=0 +CM_TEST=0 +RAWDATA_MARGIN_TEST=0 +TE_TEST=0 +SITO_RAWDATA_UNIFORMITY_TEST=0 +PATTERN_TEST=0 +GPIO_TEST=0 +LCD_NOISE_TEST=0 +FPC_OPEN_TEST=0 +VIRTUAL_BUTTON_TEST=0 +ONELINE_TEST=0 +DIAGONAL_TEST=0 +FREEPAINT_TEST=0 +SPECIAL_BUTTON_TEST=0 +HOME_KEY_TEST=0 +LINEARITY_TEST=0 +CIRCLE_TEST=0 +SQUARE_TEST=0 +KEY_TEST=0 +PRESS_CHANNEL_TEST=0 +[Basic_Threshold] +FW_VER_VALUE=255 +Factory_ID_Number=255 +IC_Version=0 +Project_Code= +Ori_ProjectCode=0 +LCM_ID=1 +PANEL_ID=255 +UniformityTest_Check_Rx=0 +UniformityTest_Check_Tx=0 +RawDataTest_Low_Min=7000 +RawDataTest_Low_Max=11000 +RawDataTest_High_Min=6000 +RawDataTest_High_Max=13000 +RawDataTest_NonCommonGND=0 +RawDataTest_LowFreq=1 +RawDataTest_HighFreq=1 +SCapCbTest_OFF_Min=0 +SCapCbTest_OFF_Max=250 +SCapCbTest_ON_Min=0 +SCapCbTest_ON_Max=250 +ScapCBTest_SetWaterproof_OFF=1 +ScapCBTest_SetWaterproof_ON=1 +SCapCBTest_LetTx_Disable=0 +ScapCBTest_SpecialMode_Off=0 +SCapCbTest_MaxNum_Off=5 +SCapCbTest_ContinuousNum_Off=3 +SCapRawDataTest_OFF_Min=2000 +SCapRawDataTest_OFF_Max=20000 +SCapRawDataTest_ON_Min=2000 +SCapRawDataTest_ON_Max=20000 +SCapRawDataTest_SetWaterproof_OFF=1 +SCapRawDataTest_SetWaterproof_ON=1 +SCapRawDataTest_LetTx_Disable=0 +PanelDifferTest_Min=500 +PanelDifferTest_Max=1300 +Distance_Diagonal=50 +Type_Diagonal=2 +MaxNG_Diagonal=0 +LimitTime_Diagonal=0 +LinearityCheck_Diagonal=1 +LimitTime_HomeKey=10 +HomeKey_LeftChannel=0 +HomeKey_RightChannel=0 +HomeKey_TopChannel=0 +HomeKey_BottonChannel=0 +HomeKey_Hole=0 +SET_TOUCH_THRESHOLD_INCELL=0 +Key_Div_Number_Incell=1 +Preserved_key_threshold_Incell=4 +SET_TOUCH_THRESHOLD_INCELL2=0 +Key_Div_Number_Incell2=1 +Preserved_key_threshold_Incell2=4 +Preserved_key_threshold_Dynamic=1 +CIRCLE_TEST_MAX_NG=0 +CIRCLE_TEST_LIMITE_TIME=0 +CIRCLE_TEST_BOARDER=360 +CIRCLE_TEST_EDGE=20 +CIRCLE_TEST_TRACK=10 +CIRCLE_TEST_CENTER1=270 +CIRCLE_TEST_CENTER2=120 +CIRCLE_TEST_LINEARITY=35 +CIRCLE_TEST_SPLITS=10 +SET_TOUCH_THRESHOLD=0 +Key_Div_Number=1 +Preserved_key_threshold=800 +1_key_threshold=800 +2_key_threshold=800 +3_key_threshold=800 +4_key_threshold=800 +Key_Threshold=800 +KEY_TEST_MAX_NG=0 +KEY_TEST_LIMITE_TIME=0 +KEY_TEST_KEY_NUM=21 +PressChannelTest_Min=5000 +Press_Test_LimitedTime=0 +[INVALID_NODE] +InvalidNode[1][25]=0 +InvalidNode[2][25]=0 +InvalidNode[3][25]=2 +InvalidNode[4][25]=0 +InvalidNode[5][25]=0 +InvalidNode[6][25]=0 +InvalidNode[7][25]=2 +InvalidNode[8][25]=0 +InvalidNode[9][25]=0 +InvalidNode[10][25]=0 +InvalidNode[11][25]=0 +InvalidNode[12][25]=2 +InvalidNode[13][25]=0 +InvalidNode[14][25]=0 +[SiuParam] +Check_Siu_Version=0 +Siu_MainVersion=0 +Siu_SubVersion=0 +Check_Set_IICVol=0 +IIC_Vol_Type=0 +IIC_Vdd_Type=0 +Check_Iovcc=0 +Iovcc_Vol_Type=0 +Iovcc_Current_Type=0 +Iovcc_Min_Hole=0 +Iovcc_Max_Hole=50 +Check_Vdd=0 +Vdd_Vol_Type=0 +Check_Normal=0 +Check_Sleep=0 +Vdd_Normal_Min=0 +Vdd_Normal_Max=500 +Vdd_Sleep_Min=0 +Vdd_Sleep_Max=150 +[SpecialSet] +RawData_Avg_High_Tx1=9986, 9895, 9865, 9958, 9936, 9875, 9872, 9840, 9805, 9797, 9796, 9887, 9653, 9688, 9675, 9637, 9629, 9607, 9612, 9622, 9621, 9634, 9659, 9680, 0, +RawData_Avg_High_Tx2=10007, 9973, 9959, 9939, 9922, 9887, 9883, 9851, 9808, 9798, 9784, 9800, 9668, 9705, 9685, 9651, 9638, 9622, 9622, 9642, 9635, 9652, 9675, 9697, 0, +RawData_Avg_High_Tx3=10008, 9978, 9970, 9922, 9905, 9889, 9868, 9843, 9812, 9787, 9767, 9769, 9682, 9709, 9690, 9658, 9642, 9631, 9626, 9637, 9636, 9659, 9668, 9692, 9859, +RawData_Avg_High_Tx4=9977, 9969, 9962, 9919, 9905, 9879, 9869, 9844, 9817, 9793, 9767, 9757, 9681, 9703, 9690, 9668, 9653, 9636, 9630, 9641, 9637, 9656, 9661, 9669, 0, +RawData_Avg_High_Tx5=9973, 9968, 9956, 9912, 9897, 9853, 9844, 9834, 9808, 9786, 9773, 9758, 9686, 9711, 9688, 9677, 9663, 9643, 9646, 9646, 9635, 9644, 9652, 9649, 0, +RawData_Avg_High_Tx6=9979, 9983, 9952, 9922, 9895, 9857, 9852, 9834, 9808, 9791, 9784, 9760, 9705, 9713, 9705, 9688, 9673, 9656, 9668, 9660, 9655, 9674, 9675, 9670, 0, +RawData_Avg_High_Tx7=9983, 9979, 9967, 9932, 9899, 9880, 9861, 9846, 9822, 9801, 9785, 9748, 9742, 9723, 9725, 9700, 9686, 9677, 9668, 9672, 9674, 9692, 9685, 9670, 9350, +RawData_Avg_High_Tx8=9971, 9954, 9934, 9904, 9874, 9864, 9840, 9823, 9813, 9784, 9760, 9725, 9747, 9727, 9731, 9704, 9696, 9675, 9677, 9670, 9667, 9669, 9654, 9628, 0, +RawData_Avg_High_Tx9=9946, 9930, 9915, 9891, 9868, 9855, 9833, 9807, 9807, 9778, 9755, 9721, 9777, 9753, 9748, 9721, 9706, 9685, 9682, 9665, 9655, 9643, 9611, 9574, 0, +RawData_Avg_High_Tx10=9935, 9924, 9911, 9885, 9876, 9865, 9838, 9804, 9801, 9781, 9763, 9725, 9826, 9786, 9779, 9754, 9737, 9724, 9688, 9660, 9645, 9613, 9578, 9530, 0, +RawData_Avg_High_Tx11=9921, 9919, 9895, 9860, 9865, 9856, 9826, 9799, 9796, 9774, 9752, 9703, 9872, 9826, 9803, 9766, 9754, 9734, 9693, 9654, 9626, 9581, 9544, 9486, 0, +RawData_Avg_High_Tx12=9925, 9920, 9900, 9863, 9861, 9851, 9829, 9810, 9812, 9780, 9757, 9701, 9920, 9858, 9825, 9785, 9763, 9745, 9697, 9652, 9611, 9553, 9511, 9466, 9513, +RawData_Avg_High_Tx13=9927, 9904, 9891, 9850, 9835, 9830, 9804, 9800, 9804, 9780, 9756, 9698, 9981, 9904, 9858, 9841, 9811, 9759, 9706, 9652, 9582, 9503, 9446, 9402, 0, +RawData_Avg_High_Tx14=9963, 9930, 9897, 9871, 9855, 9850, 9820, 9816, 9819, 9796, 9774, 9723, 10050, 9931, 9878, 9952, 9898, 9819, 9742, 9665, 9572, 9466, 9391, 9320, 0, +RawData_Max_High_Tx1=13481, 13358, 13317, 13443, 13413, 13331, 13327, 13284, 13236, 13225, 13224, 13347, 13031, 13078, 13061, 13009, 12999, 12969, 12976, 12989, 12988, 13005, 13039, 13068, 0, +RawData_Max_High_Tx2=13509, 13463, 13444, 13417, 13394, 13347, 13342, 13298, 13240, 13227, 13208, 13230, 13051, 13101, 13074, 13028, 13011, 12989, 12989, 13016, 13007, 13030, 13061, 13090, 0, +RawData_Max_High_Tx3=13510, 13470, 13459, 13394, 13371, 13350, 13321, 13288, 13246, 13212, 13185, 13188, 13070, 13107, 13081, 13038, 13016, 13001, 12995, 13009, 13008, 13039, 13051, 13084, 13309, +RawData_Max_High_Tx4=13468, 13458, 13448, 13390, 13371, 13336, 13323, 13289, 13252, 13220, 13185, 13171, 13069, 13099, 13081, 13051, 13031, 13008, 13000, 13015, 13009, 13035, 13042, 13053, 0, +RawData_Max_High_Tx5=13463, 13456, 13440, 13381, 13360, 13301, 13289, 13275, 13240, 13211, 13193, 13173, 13076, 13109, 13078, 13063, 13045, 13018, 13022, 13022, 13007, 13019, 13030, 13026, 0, +RawData_Max_High_Tx6=13471, 13477, 13435, 13394, 13358, 13306, 13300, 13275, 13240, 13217, 13208, 13176, 13101, 13112, 13101, 13078, 13058, 13035, 13051, 13041, 13034, 13059, 13061, 13054, 0, +RawData_Max_High_Tx7=13477, 13471, 13455, 13408, 13363, 13338, 13312, 13292, 13259, 13231, 13209, 13159, 13151, 13126, 13128, 13095, 13076, 13063, 13051, 13057, 13059, 13084, 13074, 13054, 12622, +RawData_Max_High_Tx8=13460, 13437, 13410, 13370, 13329, 13316, 13284, 13261, 13247, 13208, 13176, 13128, 13158, 13131, 13136, 13100, 13089, 13061, 13063, 13054, 13050, 13053, 13032, 12997, 0, +RawData_Max_High_Tx9=13427, 13405, 13385, 13352, 13321, 13304, 13274, 13239, 13239, 13200, 13169, 13123, 13198, 13166, 13159, 13123, 13103, 13074, 13070, 13047, 13034, 13018, 12974, 12924, 0, +RawData_Max_High_Tx10=13412, 13397, 13379, 13344, 13332, 13317, 13281, 13235, 13231, 13204, 13180, 13128, 13265, 13211, 13201, 13167, 13144, 13127, 13078, 13041, 13020, 12977, 12930, 12865, 0, +RawData_Max_High_Tx11=13393, 13390, 13358, 13311, 13317, 13305, 13265, 13228, 13224, 13194, 13165, 13099, 13327, 13265, 13234, 13184, 13167, 13140, 13085, 13032, 12995, 12934, 12884, 12806, 0, +RawData_Max_High_Tx12=13398, 13392, 13365, 13315, 13312, 13298, 13269, 13243, 13246, 13203, 13171, 13096, 13392, 13308, 13263, 13209, 13180, 13155, 13090, 13030, 12974, 12896, 12839, 12779, 12842, +RawData_Max_High_Tx13=13401, 13370, 13352, 13297, 13277, 13270, 13235, 13230, 13235, 13203, 13170, 13092, 13474, 13370, 13308, 13285, 13244, 13174, 13103, 13030, 12935, 12829, 12752, 12692, 0, +RawData_Max_High_Tx14=13450, 13405, 13360, 13325, 13304, 13297, 13257, 13251, 13255, 13224, 13194, 13126, 13567, 13406, 13335, 13435, 13362, 13255, 13151, 13047, 12922, 12779, 12677, 12582, 0, +RawData_Min_High_Tx1=6491, 6432, 6413, 6473, 6459, 6419, 6417, 6396, 6374, 6369, 6368, 6427, 6275, 6298, 6289, 6265, 6259, 6245, 6248, 6255, 6254, 6263, 6279, 6292, 0, +RawData_Min_High_Tx2=6505, 6483, 6474, 6461, 6450, 6427, 6424, 6404, 6376, 6369, 6360, 6370, 6285, 6309, 6296, 6274, 6265, 6255, 6255, 6268, 6263, 6274, 6289, 6304, 0, +RawData_Min_High_Tx3=6506, 6486, 6481, 6450, 6439, 6428, 6415, 6398, 6378, 6362, 6349, 6350, 6294, 6311, 6299, 6278, 6268, 6261, 6257, 6265, 6264, 6279, 6285, 6300, 6409, +RawData_Min_High_Tx4=6486, 6480, 6476, 6448, 6439, 6422, 6415, 6399, 6382, 6366, 6349, 6343, 6293, 6307, 6299, 6285, 6275, 6264, 6260, 6267, 6265, 6277, 6280, 6285, 0, +RawData_Min_High_Tx5=6483, 6480, 6472, 6443, 6434, 6405, 6399, 6393, 6376, 6361, 6353, 6343, 6296, 6313, 6298, 6291, 6281, 6268, 6270, 6270, 6263, 6269, 6274, 6272, 0, +RawData_Min_High_Tx6=6487, 6489, 6469, 6450, 6432, 6408, 6404, 6393, 6376, 6365, 6360, 6344, 6309, 6314, 6309, 6298, 6288, 6277, 6285, 6279, 6276, 6289, 6289, 6286, 0, +RawData_Min_High_Tx7=6489, 6487, 6479, 6456, 6435, 6422, 6410, 6400, 6385, 6371, 6361, 6337, 6333, 6320, 6322, 6305, 6296, 6291, 6285, 6287, 6289, 6300, 6296, 6286, 6078, +RawData_Min_High_Tx8=6482, 6471, 6458, 6438, 6419, 6412, 6396, 6385, 6379, 6360, 6344, 6322, 6336, 6323, 6326, 6308, 6303, 6289, 6291, 6286, 6284, 6285, 6276, 6259, 0, +RawData_Min_High_Tx9=6465, 6455, 6445, 6430, 6415, 6406, 6392, 6375, 6375, 6356, 6341, 6319, 6356, 6340, 6337, 6319, 6309, 6296, 6294, 6283, 6276, 6268, 6248, 6224, 0, +RawData_Min_High_Tx10=6458, 6451, 6443, 6426, 6420, 6413, 6395, 6373, 6371, 6358, 6346, 6322, 6387, 6361, 6357, 6341, 6330, 6321, 6298, 6279, 6270, 6249, 6226, 6195, 0, +RawData_Min_High_Tx11=6449, 6448, 6432, 6409, 6413, 6407, 6387, 6370, 6368, 6354, 6339, 6307, 6417, 6387, 6372, 6348, 6341, 6328, 6301, 6276, 6257, 6228, 6204, 6166, 0, +RawData_Min_High_Tx12=6452, 6448, 6435, 6411, 6410, 6404, 6389, 6377, 6378, 6357, 6343, 6306, 6448, 6408, 6387, 6361, 6346, 6335, 6304, 6274, 6248, 6210, 6183, 6153, 6184, +RawData_Min_High_Tx13=6453, 6438, 6430, 6403, 6393, 6390, 6373, 6370, 6373, 6357, 6342, 6304, 6488, 6438, 6408, 6397, 6378, 6344, 6309, 6274, 6229, 6177, 6140, 6112, 0, +RawData_Min_High_Tx14=6476, 6455, 6434, 6417, 6406, 6403, 6383, 6381, 6383, 6368, 6354, 6320, 6533, 6456, 6421, 6469, 6434, 6383, 6333, 6283, 6222, 6153, 6105, 6058, 0, +Panel_Differ_Avg_Tx1=822, 831, 834, 849, 850, 849, 853, 859, 862, 871, 878, 901, 730, 746, 753, 765, 775, 790, 804, 824, 839, 860, 884, 896, 0, +Panel_Differ_Avg_Tx2=820, 835, 839, 844, 846, 847, 851, 856, 860, 867, 873, 888, 769, 785, 794, 806, 817, 832, 847, 868, 886, 907, 932, 945, 0, +Panel_Differ_Avg_Tx3=795, 810, 814, 817, 819, 820, 823, 830, 833, 840, 845, 859, 770, 786, 795, 807, 818, 833, 847, 868, 885, 907, 931, 945, 986, +Panel_Differ_Avg_Tx4=782, 798, 802, 804, 807, 808, 812, 818, 822, 828, 832, 844, 781, 797, 805, 818, 829, 845, 859, 880, 898, 920, 944, 955, 0, +Panel_Differ_Avg_Tx5=764, 780, 784, 786, 788, 790, 793, 799, 803, 810, 815, 827, 787, 801, 810, 824, 835, 852, 866, 887, 903, 924, 949, 960, 0, +Panel_Differ_Avg_Tx6=751, 767, 770, 773, 774, 776, 778, 785, 789, 796, 801, 812, 794, 809, 818, 832, 843, 860, 875, 896, 912, 934, 959, 969, 0, +Panel_Differ_Avg_Tx7=733, 749, 752, 756, 757, 758, 760, 766, 770, 777, 782, 791, 799, 812, 822, 836, 846, 864, 877, 899, 916, 939, 963, 972, 935, +Panel_Differ_Avg_Tx8=727, 741, 744, 747, 749, 752, 753, 760, 765, 770, 773, 785, 814, 826, 838, 851, 863, 880, 894, 916, 933, 955, 979, 988, 0, +Panel_Differ_Avg_Tx9=720, 735, 738, 741, 743, 746, 748, 754, 759, 765, 768, 778, 831, 843, 854, 868, 879, 896, 911, 931, 949, 969, 991, 998, 0, +Panel_Differ_Avg_Tx10=715, 729, 732, 737, 739, 742, 743, 748, 754, 759, 764, 773, 849, 861, 871, 885, 896, 914, 925, 945, 963, 981, 1003, 1010, 0, +Panel_Differ_Avg_Tx11=709, 722, 726, 730, 732, 735, 737, 743, 747, 754, 758, 766, 867, 878, 887, 901, 912, 931, 941, 959, 976, 993, 1015, 1021, 0, +Panel_Differ_Avg_Tx12=696, 710, 713, 717, 720, 723, 724, 730, 735, 741, 745, 753, 880, 889, 898, 912, 922, 941, 952, 971, 985, 1002, 1024, 1031, 951, +Panel_Differ_Avg_Tx13=699, 713, 716, 719, 721, 724, 726, 733, 738, 744, 748, 756, 906, 915, 923, 937, 948, 964, 975, 993, 1005, 1019, 1040, 1048, 0, +Panel_Differ_Avg_Tx14=697, 710, 712, 716, 718, 721, 722, 729, 735, 741, 745, 753, 930, 936, 943, 969, 977, 990, 998, 1014, 1023, 1036, 1053, 1058, 0, +Panel_Differ_Max_Tx1=1109, 1121, 1125, 1146, 1147, 1146, 1151, 1159, 1163, 1175, 1185, 1216, 985, 1007, 1016, 1032, 1046, 1066, 1085, 1112, 1132, 1161, 1193, 1209, 0, +Panel_Differ_Max_Tx2=1107, 1127, 1132, 1139, 1142, 1143, 1148, 1155, 1161, 1170, 1178, 1198, 1038, 1059, 1071, 1088, 1102, 1123, 1143, 1171, 1196, 1224, 1258, 1275, 0, +Panel_Differ_Max_Tx3=1073, 1093, 1098, 1102, 1105, 1107, 1111, 1120, 1124, 1134, 1140, 1159, 1039, 1061, 1073, 1089, 1104, 1124, 1143, 1171, 1194, 1224, 1256, 1275, 1331, +Panel_Differ_Max_Tx4=1055, 1077, 1082, 1085, 1089, 1090, 1096, 1104, 1109, 1117, 1123, 1139, 1054, 1075, 1086, 1104, 1119, 1140, 1159, 1188, 1212, 1242, 1274, 1289, 0, +Panel_Differ_Max_Tx5=1031, 1053, 1058, 1061, 1063, 1066, 1070, 1078, 1084, 1093, 1100, 1116, 1062, 1081, 1093, 1112, 1127, 1150, 1169, 1197, 1219, 1247, 1281, 1296, 0, +Panel_Differ_Max_Tx6=1013, 1035, 1039, 1043, 1044, 1047, 1050, 1059, 1065, 1074, 1081, 1096, 1071, 1092, 1104, 1123, 1138, 1161, 1181, 1209, 1231, 1260, 1294, 1308, 0, +Panel_Differ_Max_Tx7=989, 1011, 1015, 1020, 1021, 1023, 1026, 1034, 1039, 1048, 1055, 1067, 1078, 1096, 1109, 1128, 1142, 1166, 1183, 1213, 1236, 1267, 1300, 1312, 1262, +Panel_Differ_Max_Tx8=981, 1000, 1004, 1008, 1011, 1015, 1016, 1026, 1032, 1039, 1043, 1059, 1098, 1115, 1131, 1148, 1165, 1188, 1206, 1236, 1259, 1289, 1321, 1333, 0, +Panel_Differ_Max_Tx9=972, 992, 996, 1000, 1003, 1007, 1009, 1017, 1024, 1032, 1036, 1050, 1121, 1138, 1152, 1171, 1186, 1209, 1229, 1256, 1281, 1308, 1337, 1347, 0, +Panel_Differ_Max_Tx10=965, 984, 988, 994, 997, 1001, 1003, 1009, 1017, 1024, 1031, 1043, 1146, 1162, 1175, 1194, 1209, 1233, 1248, 1275, 1300, 1324, 1354, 1363, 0, +Panel_Differ_Max_Tx11=957, 974, 980, 985, 988, 992, 994, 1003, 1008, 1017, 1023, 1034, 1170, 1185, 1197, 1216, 1231, 1256, 1270, 1294, 1317, 1340, 1370, 1378, 0, +Panel_Differ_Max_Tx12=939, 958, 962, 967, 972, 976, 977, 985, 992, 1000, 1005, 1016, 1188, 1200, 1212, 1231, 1244, 1270, 1285, 1310, 1329, 1352, 1382, 1391, 1283, +Panel_Differ_Max_Tx13=943, 962, 966, 970, 973, 977, 980, 989, 996, 1004, 1009, 1020, 1223, 1235, 1246, 1264, 1279, 1301, 1316, 1340, 1356, 1375, 1404, 1414, 0, +Panel_Differ_Max_Tx14=940, 958, 961, 966, 969, 973, 974, 984, 992, 1000, 1005, 1016, 1255, 1263, 1273, 1308, 1318, 1336, 1347, 1368, 1381, 1398, 1421, 1428, 0, +Panel_Differ_Min_Tx1=535, 541, 543, 552, 553, 552, 555, 559, 561, 567, 571, 586, 475, 485, 490, 498, 504, 514, 523, 536, 546, 559, 575, 583, 0, +Panel_Differ_Min_Tx2=533, 543, 546, 549, 550, 551, 554, 557, 559, 564, 568, 578, 500, 511, 517, 524, 532, 541, 551, 565, 576, 590, 606, 615, 0, +Panel_Differ_Min_Tx3=517, 527, 530, 532, 533, 533, 535, 540, 542, 546, 550, 559, 501, 511, 517, 525, 532, 542, 551, 565, 576, 590, 606, 615, 641, +Panel_Differ_Min_Tx4=509, 519, 522, 523, 525, 526, 528, 532, 535, 539, 541, 549, 508, 519, 524, 532, 539, 550, 559, 572, 584, 598, 614, 621, 0, +Panel_Differ_Min_Tx5=497, 507, 510, 511, 513, 514, 516, 520, 522, 527, 530, 538, 512, 521, 527, 536, 543, 554, 563, 577, 587, 601, 617, 624, 0, +Panel_Differ_Min_Tx6=489, 499, 501, 503, 504, 505, 506, 511, 513, 518, 521, 528, 517, 526, 532, 541, 548, 559, 569, 583, 593, 608, 624, 630, 0, +Panel_Differ_Min_Tx7=477, 487, 489, 492, 493, 493, 494, 498, 501, 506, 509, 515, 520, 528, 535, 544, 550, 562, 571, 585, 596, 611, 626, 632, 608, +Panel_Differ_Min_Tx8=473, 482, 484, 486, 487, 489, 490, 494, 498, 501, 503, 511, 530, 537, 545, 554, 561, 572, 582, 596, 607, 621, 637, 643, 0, +Panel_Differ_Min_Tx9=468, 478, 480, 482, 483, 485, 487, 491, 494, 498, 500, 506, 541, 548, 556, 565, 572, 583, 593, 606, 617, 630, 645, 649, 0, +Panel_Differ_Min_Tx10=465, 474, 476, 480, 481, 483, 483, 487, 491, 494, 497, 503, 552, 560, 567, 576, 583, 595, 602, 615, 626, 638, 652, 657, 0, +Panel_Differ_Min_Tx11=461, 470, 472, 475, 476, 478, 480, 483, 486, 491, 493, 498, 564, 571, 577, 586, 593, 606, 612, 624, 635, 646, 660, 664, 0, +Panel_Differ_Min_Tx12=453, 462, 464, 467, 468, 470, 471, 475, 478, 482, 485, 490, 572, 578, 584, 593, 600, 612, 619, 632, 641, 652, 666, 671, 619, +Panel_Differ_Min_Tx13=455, 464, 466, 468, 469, 471, 472, 477, 480, 484, 487, 492, 589, 595, 600, 610, 617, 627, 634, 646, 654, 663, 676, 682, 0, +Panel_Differ_Min_Tx14=454, 462, 463, 466, 467, 469, 470, 474, 478, 482, 485, 490, 605, 609, 613, 630, 636, 644, 649, 660, 665, 674, 685, 688, 0, diff --git a/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0x51.ini b/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0x51.ini new file mode 100644 index 0000000000000..7425e2eb31cd2 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0x51.ini @@ -0,0 +1,293 @@ +[Valid_File] +OnlyMultipleTest=1 +[Interface] +IC_Type=FT5435 +Normalize_Type=1 +Interface_Type=0 +Slave_Addr=0x70 +Freq_Index=2 +Phase_Pola=-1 +Max_Points=10 +iRotationDegree=0 +isReversed=0 +ixMaxPixel=1080 +iyMaxPixel=1920 +[Config] +Run_Mode=0 +Read_Bytes=256 +Write_Bytes=128 +Test_Way=0 +Handle_SN=0 +SN_Length=18 +SN_AutoTest=1 +SKey_Index=0 +SKeyValue=13 +TP_AutoTest=0 +TP_AutoTest_Time=0 +TP_ReplaceTP=0 +TP_ReplaceTP_Time=0 +TP_Always_Replace=0 +TP_Always_Replace_Time=0 +Store_Result=0 +Auto_Switch=0 +Continue_Test_After_Fail=0 +CB_Test_Mode=1 +Tip_After_TestNG=0 +Show_Res=0 +Check_Mode=0 +Non_Common_GND=0 +Output_LevelSignal=0 +Output_NgSignal=0 +Input_LevelSignal=0 +Reverse_Time=0 +Switch_Protocol=0 +CLB_Other_Return=0 +Count_Result=0 +Count_Result_Type=0 +Full_Screen=0 +Impulsing=0 +Use_LockDown=0 +[Android_Terminal] +I2C_Interface=0 +I2C_Index=0 +RW_Byte=1 +CustomConfPath=0 +AutoSave=1 +ResultPath= +[OnLine_Setting] +IPAddress=127.0.0.1 +TCPPort=5555 +[TestItem] +FW_VERSION_TEST=0 +FACTORY_ID_TEST=0 +IC_VERSION_TEST=0 +PROJECT_CODE_TEST=0 +LCM_ID_TEST=0 +PANEL_ID_TEST=0 +RAWDATA_TEST=1 +ADC_DETECT_TEST=0 +PANEL_DIFFER_TEST=1 +PANEL_DIFFER_UNIFORMITY_TEST=0 +SCAP_CB_TEST=1 +SCAP_RAWDATA_TEST=1 +CHANNEL_NUM_TEST=0 +INT_PIN_TEST=0 +RESET_PIN_TEST=0 +NOISE_TEST=0 +WEAK_SHORT_CIRCUIT_TEST=0 +UNIFORMITY_TEST=0 +CM_TEST=0 +RAWDATA_MARGIN_TEST=0 +TE_TEST=0 +SITO_RAWDATA_UNIFORMITY_TEST=0 +PATTERN_TEST=0 +GPIO_TEST=0 +LCD_NOISE_TEST=0 +FPC_OPEN_TEST=0 +VIRTUAL_BUTTON_TEST=0 +ONELINE_TEST=0 +DIAGONAL_TEST=0 +FREEPAINT_TEST=0 +SPECIAL_BUTTON_TEST=0 +HOME_KEY_TEST=0 +LINEARITY_TEST=0 +CIRCLE_TEST=0 +SQUARE_TEST=0 +KEY_TEST=0 +PRESS_CHANNEL_TEST=0 +[Basic_Threshold] +FW_VER_VALUE=255 +Factory_ID_Number=255 +IC_Version=0 +Project_Code= +Ori_ProjectCode=0 +LCM_ID=1 +PANEL_ID=255 +UniformityTest_Check_Rx=0 +UniformityTest_Check_Tx=0 +RawDataTest_Low_Min=7000 +RawDataTest_Low_Max=11000 +RawDataTest_High_Min=6000 +RawDataTest_High_Max=13000 +RawDataTest_NonCommonGND=0 +RawDataTest_LowFreq=1 +RawDataTest_HighFreq=1 +SCapCbTest_OFF_Min=0 +SCapCbTest_OFF_Max=250 +SCapCbTest_ON_Min=0 +SCapCbTest_ON_Max=250 +ScapCBTest_SetWaterproof_OFF=1 +ScapCBTest_SetWaterproof_ON=1 +SCapCBTest_LetTx_Disable=0 +ScapCBTest_SpecialMode_Off=0 +SCapCbTest_MaxNum_Off=5 +SCapCbTest_ContinuousNum_Off=3 +SCapRawDataTest_OFF_Min=2000 +SCapRawDataTest_OFF_Max=20000 +SCapRawDataTest_ON_Min=2000 +SCapRawDataTest_ON_Max=20000 +SCapRawDataTest_SetWaterproof_OFF=1 +SCapRawDataTest_SetWaterproof_ON=1 +SCapRawDataTest_LetTx_Disable=0 +PanelDifferTest_Min=500 +PanelDifferTest_Max=1300 +Distance_Diagonal=50 +Type_Diagonal=2 +MaxNG_Diagonal=0 +LimitTime_Diagonal=0 +LinearityCheck_Diagonal=1 +LimitTime_HomeKey=10 +HomeKey_LeftChannel=0 +HomeKey_RightChannel=0 +HomeKey_TopChannel=0 +HomeKey_BottonChannel=0 +HomeKey_Hole=0 +SET_TOUCH_THRESHOLD_INCELL=0 +Key_Div_Number_Incell=1 +Preserved_key_threshold_Incell=4 +SET_TOUCH_THRESHOLD_INCELL2=0 +Key_Div_Number_Incell2=1 +Preserved_key_threshold_Incell2=4 +Preserved_key_threshold_Dynamic=1 +CIRCLE_TEST_MAX_NG=0 +CIRCLE_TEST_LIMITE_TIME=0 +CIRCLE_TEST_BOARDER=360 +CIRCLE_TEST_EDGE=20 +CIRCLE_TEST_TRACK=10 +CIRCLE_TEST_CENTER1=270 +CIRCLE_TEST_CENTER2=120 +CIRCLE_TEST_LINEARITY=35 +CIRCLE_TEST_SPLITS=10 +SET_TOUCH_THRESHOLD=0 +Key_Div_Number=1 +Preserved_key_threshold=800 +1_key_threshold=800 +2_key_threshold=800 +3_key_threshold=800 +4_key_threshold=800 +Key_Threshold=800 +KEY_TEST_MAX_NG=0 +KEY_TEST_LIMITE_TIME=0 +KEY_TEST_KEY_NUM=21 +PressChannelTest_Min=5000 +Press_Test_LimitedTime=0 +[INVALID_NODE] +InvalidNode[1][25]=0 +InvalidNode[2][25]=0 +InvalidNode[3][25]=2 +InvalidNode[4][25]=0 +InvalidNode[5][25]=0 +InvalidNode[6][25]=0 +InvalidNode[7][25]=2 +InvalidNode[8][25]=0 +InvalidNode[9][25]=0 +InvalidNode[10][25]=0 +InvalidNode[11][25]=0 +InvalidNode[12][25]=2 +InvalidNode[13][25]=0 +InvalidNode[14][25]=0 +[SiuParam] +Check_Siu_Version=0 +Siu_MainVersion=0 +Siu_SubVersion=0 +Check_Set_IICVol=0 +IIC_Vol_Type=0 +IIC_Vdd_Type=0 +Check_Iovcc=0 +Iovcc_Vol_Type=0 +Iovcc_Current_Type=0 +Iovcc_Min_Hole=0 +Iovcc_Max_Hole=50 +Check_Vdd=0 +Vdd_Vol_Type=0 +Check_Normal=0 +Check_Sleep=0 +Vdd_Normal_Min=0 +Vdd_Normal_Max=500 +Vdd_Sleep_Min=0 +Vdd_Sleep_Max=150 +[SpecialSet] +RawData_Avg_High_Tx1=9986, 9895, 9865, 9958, 9936, 9875, 9872, 9840, 9805, 9797, 9796, 9887, 9653, 9688, 9675, 9637, 9629, 9607, 9612, 9622, 9621, 9634, 9659, 9680, 0, +RawData_Avg_High_Tx2=10007, 9973, 9959, 9939, 9922, 9887, 9883, 9851, 9808, 9798, 9784, 9800, 9668, 9705, 9685, 9651, 9638, 9622, 9622, 9642, 9635, 9652, 9675, 9697, 0, +RawData_Avg_High_Tx3=10008, 9978, 9970, 9922, 9905, 9889, 9868, 9843, 9812, 9787, 9767, 9769, 9682, 9709, 9690, 9658, 9642, 9631, 9626, 9637, 9636, 9659, 9668, 9692, 9859, +RawData_Avg_High_Tx4=9977, 9969, 9962, 9919, 9905, 9879, 9869, 9844, 9817, 9793, 9767, 9757, 9681, 9703, 9690, 9668, 9653, 9636, 9630, 9641, 9637, 9656, 9661, 9669, 0, +RawData_Avg_High_Tx5=9973, 9968, 9956, 9912, 9897, 9853, 9844, 9834, 9808, 9786, 9773, 9758, 9686, 9711, 9688, 9677, 9663, 9643, 9646, 9646, 9635, 9644, 9652, 9649, 0, +RawData_Avg_High_Tx6=9979, 9983, 9952, 9922, 9895, 9857, 9852, 9834, 9808, 9791, 9784, 9760, 9705, 9713, 9705, 9688, 9673, 9656, 9668, 9660, 9655, 9674, 9675, 9670, 0, +RawData_Avg_High_Tx7=9983, 9979, 9967, 9932, 9899, 9880, 9861, 9846, 9822, 9801, 9785, 9748, 9742, 9723, 9725, 9700, 9686, 9677, 9668, 9672, 9674, 9692, 9685, 9670, 9350, +RawData_Avg_High_Tx8=9971, 9954, 9934, 9904, 9874, 9864, 9840, 9823, 9813, 9784, 9760, 9725, 9747, 9727, 9731, 9704, 9696, 9675, 9677, 9670, 9667, 9669, 9654, 9628, 0, +RawData_Avg_High_Tx9=9946, 9930, 9915, 9891, 9868, 9855, 9833, 9807, 9807, 9778, 9755, 9721, 9777, 9753, 9748, 9721, 9706, 9685, 9682, 9665, 9655, 9643, 9611, 9574, 0, +RawData_Avg_High_Tx10=9935, 9924, 9911, 9885, 9876, 9865, 9838, 9804, 9801, 9781, 9763, 9725, 9826, 9786, 9779, 9754, 9737, 9724, 9688, 9660, 9645, 9613, 9578, 9530, 0, +RawData_Avg_High_Tx11=9921, 9919, 9895, 9860, 9865, 9856, 9826, 9799, 9796, 9774, 9752, 9703, 9872, 9826, 9803, 9766, 9754, 9734, 9693, 9654, 9626, 9581, 9544, 9486, 0, +RawData_Avg_High_Tx12=9925, 9920, 9900, 9863, 9861, 9851, 9829, 9810, 9812, 9780, 9757, 9701, 9920, 9858, 9825, 9785, 9763, 9745, 9697, 9652, 9611, 9553, 9511, 9466, 9513, +RawData_Avg_High_Tx13=9927, 9904, 9891, 9850, 9835, 9830, 9804, 9800, 9804, 9780, 9756, 9698, 9981, 9904, 9858, 9841, 9811, 9759, 9706, 9652, 9582, 9503, 9446, 9402, 0, +RawData_Avg_High_Tx14=9963, 9930, 9897, 9871, 9855, 9850, 9820, 9816, 9819, 9796, 9774, 9723, 10050, 9931, 9878, 9952, 9898, 9819, 9742, 9665, 9572, 9466, 9391, 9320, 0, +RawData_Max_High_Tx1=13481, 13358, 13317, 13443, 13413, 13331, 13327, 13284, 13236, 13225, 13224, 13347, 13031, 13078, 13061, 13009, 12999, 12969, 12976, 12989, 12988, 13005, 13039, 13068, 0, +RawData_Max_High_Tx2=13509, 13463, 13444, 13417, 13394, 13347, 13342, 13298, 13240, 13227, 13208, 13230, 13051, 13101, 13074, 13028, 13011, 12989, 12989, 13016, 13007, 13030, 13061, 13090, 0, +RawData_Max_High_Tx3=13510, 13470, 13459, 13394, 13371, 13350, 13321, 13288, 13246, 13212, 13185, 13188, 13070, 13107, 13081, 13038, 13016, 13001, 12995, 13009, 13008, 13039, 13051, 13084, 13309, +RawData_Max_High_Tx4=13468, 13458, 13448, 13390, 13371, 13336, 13323, 13289, 13252, 13220, 13185, 13171, 13069, 13099, 13081, 13051, 13031, 13008, 13000, 13015, 13009, 13035, 13042, 13053, 0, +RawData_Max_High_Tx5=13463, 13456, 13440, 13381, 13360, 13301, 13289, 13275, 13240, 13211, 13193, 13173, 13076, 13109, 13078, 13063, 13045, 13018, 13022, 13022, 13007, 13019, 13030, 13026, 0, +RawData_Max_High_Tx6=13471, 13477, 13435, 13394, 13358, 13306, 13300, 13275, 13240, 13217, 13208, 13176, 13101, 13112, 13101, 13078, 13058, 13035, 13051, 13041, 13034, 13059, 13061, 13054, 0, +RawData_Max_High_Tx7=13477, 13471, 13455, 13408, 13363, 13338, 13312, 13292, 13259, 13231, 13209, 13159, 13151, 13126, 13128, 13095, 13076, 13063, 13051, 13057, 13059, 13084, 13074, 13054, 12622, +RawData_Max_High_Tx8=13460, 13437, 13410, 13370, 13329, 13316, 13284, 13261, 13247, 13208, 13176, 13128, 13158, 13131, 13136, 13100, 13089, 13061, 13063, 13054, 13050, 13053, 13032, 12997, 0, +RawData_Max_High_Tx9=13427, 13405, 13385, 13352, 13321, 13304, 13274, 13239, 13239, 13200, 13169, 13123, 13198, 13166, 13159, 13123, 13103, 13074, 13070, 13047, 13034, 13018, 12974, 12924, 0, +RawData_Max_High_Tx10=13412, 13397, 13379, 13344, 13332, 13317, 13281, 13235, 13231, 13204, 13180, 13128, 13265, 13211, 13201, 13167, 13144, 13127, 13078, 13041, 13020, 12977, 12930, 12865, 0, +RawData_Max_High_Tx11=13393, 13390, 13358, 13311, 13317, 13305, 13265, 13228, 13224, 13194, 13165, 13099, 13327, 13265, 13234, 13184, 13167, 13140, 13085, 13032, 12995, 12934, 12884, 12806, 0, +RawData_Max_High_Tx12=13398, 13392, 13365, 13315, 13312, 13298, 13269, 13243, 13246, 13203, 13171, 13096, 13392, 13308, 13263, 13209, 13180, 13155, 13090, 13030, 12974, 12896, 12839, 12779, 12842, +RawData_Max_High_Tx13=13401, 13370, 13352, 13297, 13277, 13270, 13235, 13230, 13235, 13203, 13170, 13092, 13474, 13370, 13308, 13285, 13244, 13174, 13103, 13030, 12935, 12829, 12752, 12692, 0, +RawData_Max_High_Tx14=13450, 13405, 13360, 13325, 13304, 13297, 13257, 13251, 13255, 13224, 13194, 13126, 13567, 13406, 13335, 13435, 13362, 13255, 13151, 13047, 12922, 12779, 12677, 12582, 0, +RawData_Min_High_Tx1=6491, 6432, 6413, 6473, 6459, 6419, 6417, 6396, 6374, 6369, 6368, 6427, 6275, 6298, 6289, 6265, 6259, 6245, 6248, 6255, 6254, 6263, 6279, 6292, 0, +RawData_Min_High_Tx2=6505, 6483, 6474, 6461, 6450, 6427, 6424, 6404, 6376, 6369, 6360, 6370, 6285, 6309, 6296, 6274, 6265, 6255, 6255, 6268, 6263, 6274, 6289, 6304, 0, +RawData_Min_High_Tx3=6506, 6486, 6481, 6450, 6439, 6428, 6415, 6398, 6378, 6362, 6349, 6350, 6294, 6311, 6299, 6278, 6268, 6261, 6257, 6265, 6264, 6279, 6285, 6300, 6409, +RawData_Min_High_Tx4=6486, 6480, 6476, 6448, 6439, 6422, 6415, 6399, 6382, 6366, 6349, 6343, 6293, 6307, 6299, 6285, 6275, 6264, 6260, 6267, 6265, 6277, 6280, 6285, 0, +RawData_Min_High_Tx5=6483, 6480, 6472, 6443, 6434, 6405, 6399, 6393, 6376, 6361, 6353, 6343, 6296, 6313, 6298, 6291, 6281, 6268, 6270, 6270, 6263, 6269, 6274, 6272, 0, +RawData_Min_High_Tx6=6487, 6489, 6469, 6450, 6432, 6408, 6404, 6393, 6376, 6365, 6360, 6344, 6309, 6314, 6309, 6298, 6288, 6277, 6285, 6279, 6276, 6289, 6289, 6286, 0, +RawData_Min_High_Tx7=6489, 6487, 6479, 6456, 6435, 6422, 6410, 6400, 6385, 6371, 6361, 6337, 6333, 6320, 6322, 6305, 6296, 6291, 6285, 6287, 6289, 6300, 6296, 6286, 6078, +RawData_Min_High_Tx8=6482, 6471, 6458, 6438, 6419, 6412, 6396, 6385, 6379, 6360, 6344, 6322, 6336, 6323, 6326, 6308, 6303, 6289, 6291, 6286, 6284, 6285, 6276, 6259, 0, +RawData_Min_High_Tx9=6465, 6455, 6445, 6430, 6415, 6406, 6392, 6375, 6375, 6356, 6341, 6319, 6356, 6340, 6337, 6319, 6309, 6296, 6294, 6283, 6276, 6268, 6248, 6224, 0, +RawData_Min_High_Tx10=6458, 6451, 6443, 6426, 6420, 6413, 6395, 6373, 6371, 6358, 6346, 6322, 6387, 6361, 6357, 6341, 6330, 6321, 6298, 6279, 6270, 6249, 6226, 6195, 0, +RawData_Min_High_Tx11=6449, 6448, 6432, 6409, 6413, 6407, 6387, 6370, 6368, 6354, 6339, 6307, 6417, 6387, 6372, 6348, 6341, 6328, 6301, 6276, 6257, 6228, 6204, 6166, 0, +RawData_Min_High_Tx12=6452, 6448, 6435, 6411, 6410, 6404, 6389, 6377, 6378, 6357, 6343, 6306, 6448, 6408, 6387, 6361, 6346, 6335, 6304, 6274, 6248, 6210, 6183, 6153, 6184, +RawData_Min_High_Tx13=6453, 6438, 6430, 6403, 6393, 6390, 6373, 6370, 6373, 6357, 6342, 6304, 6488, 6438, 6408, 6397, 6378, 6344, 6309, 6274, 6229, 6177, 6140, 6112, 0, +RawData_Min_High_Tx14=6476, 6455, 6434, 6417, 6406, 6403, 6383, 6381, 6383, 6368, 6354, 6320, 6533, 6456, 6421, 6469, 6434, 6383, 6333, 6283, 6222, 6153, 6105, 6058, 0, +Panel_Differ_Avg_Tx1=822, 831, 834, 849, 850, 849, 853, 859, 862, 871, 878, 901, 730, 746, 753, 765, 775, 790, 804, 824, 839, 860, 884, 896, 0, +Panel_Differ_Avg_Tx2=820, 835, 839, 844, 846, 847, 851, 856, 860, 867, 873, 888, 769, 785, 794, 806, 817, 832, 847, 868, 886, 907, 932, 945, 0, +Panel_Differ_Avg_Tx3=795, 810, 814, 817, 819, 820, 823, 830, 833, 840, 845, 859, 770, 786, 795, 807, 818, 833, 847, 868, 885, 907, 931, 945, 986, +Panel_Differ_Avg_Tx4=782, 798, 802, 804, 807, 808, 812, 818, 822, 828, 832, 844, 781, 797, 805, 818, 829, 845, 859, 880, 898, 920, 944, 955, 0, +Panel_Differ_Avg_Tx5=764, 780, 784, 786, 788, 790, 793, 799, 803, 810, 815, 827, 787, 801, 810, 824, 835, 852, 866, 887, 903, 924, 949, 960, 0, +Panel_Differ_Avg_Tx6=751, 767, 770, 773, 774, 776, 778, 785, 789, 796, 801, 812, 794, 809, 818, 832, 843, 860, 875, 896, 912, 934, 959, 969, 0, +Panel_Differ_Avg_Tx7=733, 749, 752, 756, 757, 758, 760, 766, 770, 777, 782, 791, 799, 812, 822, 836, 846, 864, 877, 899, 916, 939, 963, 972, 935, +Panel_Differ_Avg_Tx8=727, 741, 744, 747, 749, 752, 753, 760, 765, 770, 773, 785, 814, 826, 838, 851, 863, 880, 894, 916, 933, 955, 979, 988, 0, +Panel_Differ_Avg_Tx9=720, 735, 738, 741, 743, 746, 748, 754, 759, 765, 768, 778, 831, 843, 854, 868, 879, 896, 911, 931, 949, 969, 991, 998, 0, +Panel_Differ_Avg_Tx10=715, 729, 732, 737, 739, 742, 743, 748, 754, 759, 764, 773, 849, 861, 871, 885, 896, 914, 925, 945, 963, 981, 1003, 1010, 0, +Panel_Differ_Avg_Tx11=709, 722, 726, 730, 732, 735, 737, 743, 747, 754, 758, 766, 867, 878, 887, 901, 912, 931, 941, 959, 976, 993, 1015, 1021, 0, +Panel_Differ_Avg_Tx12=696, 710, 713, 717, 720, 723, 724, 730, 735, 741, 745, 753, 880, 889, 898, 912, 922, 941, 952, 971, 985, 1002, 1024, 1031, 951, +Panel_Differ_Avg_Tx13=699, 713, 716, 719, 721, 724, 726, 733, 738, 744, 748, 756, 906, 915, 923, 937, 948, 964, 975, 993, 1005, 1019, 1040, 1048, 0, +Panel_Differ_Avg_Tx14=697, 710, 712, 716, 718, 721, 722, 729, 735, 741, 745, 753, 930, 936, 943, 969, 977, 990, 998, 1014, 1023, 1036, 1053, 1058, 0, +Panel_Differ_Max_Tx1=1109, 1121, 1125, 1146, 1147, 1146, 1151, 1159, 1163, 1175, 1185, 1216, 985, 1007, 1016, 1032, 1046, 1066, 1085, 1112, 1132, 1161, 1193, 1209, 0, +Panel_Differ_Max_Tx2=1107, 1127, 1132, 1139, 1142, 1143, 1148, 1155, 1161, 1170, 1178, 1198, 1038, 1059, 1071, 1088, 1102, 1123, 1143, 1171, 1196, 1224, 1258, 1275, 0, +Panel_Differ_Max_Tx3=1073, 1093, 1098, 1102, 1105, 1107, 1111, 1120, 1124, 1134, 1140, 1159, 1039, 1061, 1073, 1089, 1104, 1124, 1143, 1171, 1194, 1224, 1256, 1275, 1331, +Panel_Differ_Max_Tx4=1055, 1077, 1082, 1085, 1089, 1090, 1096, 1104, 1109, 1117, 1123, 1139, 1054, 1075, 1086, 1104, 1119, 1140, 1159, 1188, 1212, 1242, 1274, 1289, 0, +Panel_Differ_Max_Tx5=1031, 1053, 1058, 1061, 1063, 1066, 1070, 1078, 1084, 1093, 1100, 1116, 1062, 1081, 1093, 1112, 1127, 1150, 1169, 1197, 1219, 1247, 1281, 1296, 0, +Panel_Differ_Max_Tx6=1013, 1035, 1039, 1043, 1044, 1047, 1050, 1059, 1065, 1074, 1081, 1096, 1071, 1092, 1104, 1123, 1138, 1161, 1181, 1209, 1231, 1260, 1294, 1308, 0, +Panel_Differ_Max_Tx7=989, 1011, 1015, 1020, 1021, 1023, 1026, 1034, 1039, 1048, 1055, 1067, 1078, 1096, 1109, 1128, 1142, 1166, 1183, 1213, 1236, 1267, 1300, 1312, 1262, +Panel_Differ_Max_Tx8=981, 1000, 1004, 1008, 1011, 1015, 1016, 1026, 1032, 1039, 1043, 1059, 1098, 1115, 1131, 1148, 1165, 1188, 1206, 1236, 1259, 1289, 1321, 1333, 0, +Panel_Differ_Max_Tx9=972, 992, 996, 1000, 1003, 1007, 1009, 1017, 1024, 1032, 1036, 1050, 1121, 1138, 1152, 1171, 1186, 1209, 1229, 1256, 1281, 1308, 1337, 1347, 0, +Panel_Differ_Max_Tx10=965, 984, 988, 994, 997, 1001, 1003, 1009, 1017, 1024, 1031, 1043, 1146, 1162, 1175, 1194, 1209, 1233, 1248, 1275, 1300, 1324, 1354, 1363, 0, +Panel_Differ_Max_Tx11=957, 974, 980, 985, 988, 992, 994, 1003, 1008, 1017, 1023, 1034, 1170, 1185, 1197, 1216, 1231, 1256, 1270, 1294, 1317, 1340, 1370, 1378, 0, +Panel_Differ_Max_Tx12=939, 958, 962, 967, 972, 976, 977, 985, 992, 1000, 1005, 1016, 1188, 1200, 1212, 1231, 1244, 1270, 1285, 1310, 1329, 1352, 1382, 1391, 1283, +Panel_Differ_Max_Tx13=943, 962, 966, 970, 973, 977, 980, 989, 996, 1004, 1009, 1020, 1223, 1235, 1246, 1264, 1279, 1301, 1316, 1340, 1356, 1375, 1404, 1414, 0, +Panel_Differ_Max_Tx14=940, 958, 961, 966, 969, 973, 974, 984, 992, 1000, 1005, 1016, 1255, 1263, 1273, 1308, 1318, 1336, 1347, 1368, 1381, 1398, 1421, 1428, 0, +Panel_Differ_Min_Tx1=535, 541, 543, 552, 553, 552, 555, 559, 561, 567, 571, 586, 475, 485, 490, 498, 504, 514, 523, 536, 546, 559, 575, 583, 0, +Panel_Differ_Min_Tx2=533, 543, 546, 549, 550, 551, 554, 557, 559, 564, 568, 578, 500, 511, 517, 524, 532, 541, 551, 565, 576, 590, 606, 615, 0, +Panel_Differ_Min_Tx3=517, 527, 530, 532, 533, 533, 535, 540, 542, 546, 550, 559, 501, 511, 517, 525, 532, 542, 551, 565, 576, 590, 606, 615, 641, +Panel_Differ_Min_Tx4=509, 519, 522, 523, 525, 526, 528, 532, 535, 539, 541, 549, 508, 519, 524, 532, 539, 550, 559, 572, 584, 598, 614, 621, 0, +Panel_Differ_Min_Tx5=497, 507, 510, 511, 513, 514, 516, 520, 522, 527, 530, 538, 512, 521, 527, 536, 543, 554, 563, 577, 587, 601, 617, 624, 0, +Panel_Differ_Min_Tx6=489, 499, 501, 503, 504, 505, 506, 511, 513, 518, 521, 528, 517, 526, 532, 541, 548, 559, 569, 583, 593, 608, 624, 630, 0, +Panel_Differ_Min_Tx7=477, 487, 489, 492, 493, 493, 494, 498, 501, 506, 509, 515, 520, 528, 535, 544, 550, 562, 571, 585, 596, 611, 626, 632, 608, +Panel_Differ_Min_Tx8=473, 482, 484, 486, 487, 489, 490, 494, 498, 501, 503, 511, 530, 537, 545, 554, 561, 572, 582, 596, 607, 621, 637, 643, 0, +Panel_Differ_Min_Tx9=468, 478, 480, 482, 483, 485, 487, 491, 494, 498, 500, 506, 541, 548, 556, 565, 572, 583, 593, 606, 617, 630, 645, 649, 0, +Panel_Differ_Min_Tx10=465, 474, 476, 480, 481, 483, 483, 487, 491, 494, 497, 503, 552, 560, 567, 576, 583, 595, 602, 615, 626, 638, 652, 657, 0, +Panel_Differ_Min_Tx11=461, 470, 472, 475, 476, 478, 480, 483, 486, 491, 493, 498, 564, 571, 577, 586, 593, 606, 612, 624, 635, 646, 660, 664, 0, +Panel_Differ_Min_Tx12=453, 462, 464, 467, 468, 470, 471, 475, 478, 482, 485, 490, 572, 578, 584, 593, 600, 612, 619, 632, 641, 652, 666, 671, 619, +Panel_Differ_Min_Tx13=455, 464, 466, 468, 469, 471, 472, 477, 480, 484, 487, 492, 589, 595, 600, 610, 617, 627, 634, 646, 654, 663, 676, 682, 0, +Panel_Differ_Min_Tx14=454, 462, 463, 466, 467, 469, 470, 474, 478, 482, 485, 490, 605, 609, 613, 630, 636, 644, 649, 660, 665, 674, 685, 688, 0, diff --git a/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0xd0.ini b/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0xd0.ini new file mode 100644 index 0000000000000..48201e86b19d1 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/ito_cfg/Conf_MultipleTest_d2_0xd0.ini @@ -0,0 +1,307 @@ +[Valid_File] +OnlyMultipleTest=1 +[Interface] +IC_Type=FT5435 +Normalize_Type=1 +Interface_Type=0 +Slave_Addr=0x70 +Freq_Index=2 +Phase_Pola=-1 +Max_Points=10 +iRotationDegree=0 +isReversed=0 +ixMaxPixel=1080 +iyMaxPixel=1920 +[Config] +Run_Mode=0 +Read_Bytes=256 +Write_Bytes=128 +Test_Way=0 +Handle_SN=0 +SN_Length=18 +SN_AutoTest=1 +SKey_Index=0 +SKeyValue=13 +TP_AutoTest=0 +TP_AutoTest_Time=0 +TP_ReplaceTP=0 +TP_ReplaceTP_Time=0 +TP_Always_Replace=0 +TP_Always_Replace_Time=0 +Store_Result=0 +Auto_Switch=0 +Continue_Test_After_Fail=0 +CB_Test_Mode=1 +Tip_After_TestNG=0 +Show_Res=0 +Check_Mode=0 +Non_Common_GND=0 +Output_LevelSignal=0 +Output_NgSignal=0 +Input_LevelSignal=0 +Reverse_Time=0 +Switch_Protocol=0 +CLB_Other_Return=0 +Count_Result=0 +Count_Result_Type=0 +Full_Screen=0 +Impulsing=0 +Use_LockDown=0 +Break_Test_After_Fail=0 +Light_Up=0 +TP_Stop=0 +SetCheckFwFileName=0 +SetFwChecksum=0 +[Android_Terminal] +I2C_Interface=0 +I2C_Index=0 +RW_Byte=1 +CustomConfPath=0 +AutoSave=1 +ResultPath= +[OnLine_Setting] +IPAddress=127.0.0.1 +TCPPort=5555 +[TestItem] +FW_VERSION_TEST=0 +FACTORY_ID_TEST=0 +IC_VERSION_TEST=0 +PROJECT_CODE_TEST=0 +LCM_ID_TEST=0 +PANEL_ID_TEST=0 +RAWDATA_TEST=1 +ADC_DETECT_TEST=0 +PANEL_DIFFER_TEST=1 +PANEL_DIFFER_UNIFORMITY_TEST=0 +SCAP_CB_TEST=1 +SCAP_RAWDATA_TEST=1 +CHANNEL_NUM_TEST=0 +INT_PIN_TEST=0 +RESET_PIN_TEST=0 +NOISE_TEST=0 +WEAK_SHORT_CIRCUIT_TEST=0 +UNIFORMITY_TEST=0 +CM_TEST=0 +RAWDATA_MARGIN_TEST=0 +TE_TEST=0 +SITO_RAWDATA_UNIFORMITY_TEST=0 +PATTERN_TEST=0 +GPIO_TEST=0 +LCD_NOISE_TEST=0 +FPC_OPEN_TEST=0 +VIRTUAL_BUTTON_TEST=0 +ONELINE_TEST=0 +DIAGONAL_TEST=0 +FREEPAINT_TEST=0 +SPECIAL_BUTTON_TEST=0 +HOME_KEY_TEST=0 +LINEARITY_TEST=0 +CIRCLE_TEST=0 +SQUARE_TEST=0 +KEY_TEST=0 +PRESS_CHANNEL_TEST=0 +SREF_OPEN_TEST=0 +[Basic_Threshold] +FW_VER_VALUE=255 +Factory_ID_Number=255 +IC_Version=0 +Project_Code= +Ori_ProjectCode=0 +LCM_ID=1 +PANEL_ID=255 +UniformityTest_Check_Rx=0 +UniformityTest_Check_Tx=0 +RawDataTest_Low_Min=7000 +RawDataTest_Low_Max=11000 +RawDataTest_High_Min=6000 +RawDataTest_High_Max=13000 +RawDataTest_NonCommonGND=0 +RawDataTest_LowFreq=1 +RawDataTest_HighFreq=1 +SCapCbTest_OFF_Min=0 +SCapCbTest_OFF_Max=250 +SCapCbTest_ON_Min=0 +SCapCbTest_ON_Max=250 +ScapCBTest_SetWaterproof_OFF=1 +ScapCBTest_SetWaterproof_ON=1 +SCapCBTest_LetTx_Disable=0 +ScapCBTest_SpecialMode_Off=0 +SCapCbTest_MaxNum_Off=5 +SCapCbTest_ContinuousNum_Off=3 +SCapRawDataTest_OFF_Min=2000 +SCapRawDataTest_OFF_Max=20000 +SCapRawDataTest_ON_Min=2000 +SCapRawDataTest_ON_Max=20000 +SCapRawDataTest_SetWaterproof_OFF=1 +SCapRawDataTest_SetWaterproof_ON=1 +SCapRawDataTest_LetTx_Disable=0 +PanelDifferTest_Min=400 +PanelDifferTest_Max=1400 +Distance_Diagonal=50 +Type_Diagonal=2 +MaxNG_Diagonal=0 +LimitTime_Diagonal=0 +LinearityCheck_Diagonal=1 +LimitTime_HomeKey=10 +HomeKey_LeftChannel=0 +HomeKey_RightChannel=0 +HomeKey_TopChannel=0 +HomeKey_BottonChannel=0 +HomeKey_Hole=0 +SET_TOUCH_THRESHOLD_INCELL=0 +Key_Div_Number_Incell=1 +Preserved_key_threshold_Incell=4 +SET_TOUCH_THRESHOLD_INCELL2=0 +Key_Div_Number_Incell2=1 +Preserved_key_threshold_Incell2=4 +Preserved_key_threshold_Dynamic=1 +CIRCLE_TEST_MAX_NG=0 +CIRCLE_TEST_LIMITE_TIME=0 +CIRCLE_TEST_BOARDER=360 +CIRCLE_TEST_EDGE=20 +CIRCLE_TEST_TRACK=10 +CIRCLE_TEST_CENTER1=270 +CIRCLE_TEST_CENTER2=120 +CIRCLE_TEST_LINEARITY=35 +CIRCLE_TEST_SPLITS=10 +SET_TOUCH_THRESHOLD=0 +Key_Div_Number=1 +Preserved_key_threshold=800 +1_key_threshold=800 +2_key_threshold=800 +3_key_threshold=800 +4_key_threshold=800 +Key_Threshold=800 +KEY_TEST_MAX_NG=0 +KEY_TEST_LIMITE_TIME=0 +KEY_TEST_KEY_NUM=21 +PressChannelTest_Min=5000 +Press_Test_LimitedTime=0 +Continue_Diagonal=0 +[INVALID_NODE] +InvalidNode[1][25]=0 +InvalidNode[2][25]=0 +InvalidNode[3][25]=2 +InvalidNode[4][25]=0 +InvalidNode[5][25]=0 +InvalidNode[6][25]=0 +InvalidNode[7][25]=2 +InvalidNode[8][25]=0 +InvalidNode[9][25]=0 +InvalidNode[10][25]=0 +InvalidNode[11][25]=0 +InvalidNode[12][25]=2 +InvalidNode[13][25]=0 +InvalidNode[14][25]=0 +[SiuParam] +Check_Siu_Version=0 +Siu_MainVersion=0 +Siu_SubVersion=0 +Check_Set_IICVol=0 +IIC_Vol_Type=0 +IIC_Vdd_Type=0 +Check_Iovcc=0 +Iovcc_Vol_Type=0 +Iovcc_Current_Type=0 +Iovcc_Min_Hole=0 +Iovcc_Max_Hole=50 +Check_Vdd=0 +Vdd_Vol_Type=0 +Check_Normal=0 +Check_Sleep=0 +Vdd_Normal_Min=0 +Vdd_Normal_Max=500 +Vdd_Sleep_Min=0 +Vdd_Sleep_Max=150 +Check_Standby=0 +Standby_Vol_Type=0 +Vdd_Standby_Min=0 +Vdd_Standby_Max=150 +[SpecialSet] +RawData_Avg_High_Tx1=9971, 9891, 9871, 9960, 9932, 9891, 9871, 9841, 9816, 9794, 9784, 9938, 9651, 9692, 9678, 9646, 9640, 9632, 9631, 9630, 9628, 9636, 9644, 9661, 0, +RawData_Avg_High_Tx2=9998, 9969, 9949, 9940, 9922, 9893, 9873, 9844, 9820, 9791, 9765, 9801, 9655, 9692, 9680, 9653, 9648, 9641, 9639, 9641, 9645, 9649, 9660, 9671, 0, +RawData_Avg_High_Tx3=10018, 9986, 9964, 9931, 9915, 9891, 9867, 9843, 9821, 9792, 9765, 9782, 9676, 9696, 9680, 9655, 9654, 9647, 9643, 9646, 9649, 9656, 9667, 9685, 9420, +RawData_Avg_High_Tx4=9988, 9972, 9949, 9916, 9904, 9876, 9857, 9835, 9811, 9790, 9759, 9758, 9658, 9686, 9676, 9655, 9653, 9651, 9650, 9651, 9653, 9662, 9677, 9680, 0, +RawData_Avg_High_Tx5=9990, 9971, 9953, 9919, 9899, 9882, 9856, 9838, 9812, 9796, 9769, 9759, 9672, 9696, 9682, 9667, 9663, 9660, 9661, 9662, 9662, 9671, 9684, 9689, 0, +RawData_Avg_High_Tx6=9980, 9964, 9941, 9907, 9889, 9867, 9844, 9827, 9805, 9793, 9769, 9746, 9685, 9697, 9685, 9675, 9666, 9663, 9662, 9663, 9664, 9670, 9677, 9684, 0, +RawData_Avg_High_Tx7=9972, 9959, 9937, 9904, 9882, 9859, 9834, 9821, 9802, 9788, 9763, 9732, 9713, 9710, 9697, 9682, 9675, 9669, 9662, 9662, 9662, 9662, 9669, 9674, 9041, +RawData_Avg_High_Tx8=9971, 9955, 9935, 9900, 9883, 9856, 9841, 9824, 9808, 9791, 9770, 9730, 9742, 9727, 9724, 9700, 9694, 9684, 9672, 9666, 9662, 9652, 9650, 9650, 0, +RawData_Avg_High_Tx9=9963, 9944, 9926, 9891, 9872, 9848, 9833, 9818, 9802, 9785, 9767, 9720, 9777, 9753, 9748, 9717, 9708, 9695, 9680, 9664, 9653, 9638, 9620, 9607, 0, +RawData_Avg_High_Tx10=9954, 9938, 9920, 9887, 9868, 9846, 9834, 9818, 9804, 9785, 9770, 9714, 9824, 9786, 9776, 9741, 9727, 9708, 9685, 9661, 9641, 9615, 9584, 9559, 0, +RawData_Avg_High_Tx11=9930, 9918, 9904, 9868, 9850, 9833, 9820, 9806, 9789, 9774, 9757, 9694, 9868, 9821, 9800, 9764, 9741, 9717, 9685, 9655, 9623, 9585, 9543, 9504, 0, +RawData_Avg_High_Tx12=9925, 9925, 9910, 9877, 9861, 9850, 9833, 9816, 9796, 9785, 9765, 9689, 9936, 9872, 9837, 9802, 9765, 9733, 9692, 9653, 9611, 9560, 9511, 9464, 9218, +RawData_Avg_High_Tx13=9908, 9902, 9889, 9859, 9846, 9837, 9821, 9802, 9783, 9771, 9757, 9668, 9996, 9915, 9875, 9845, 9792, 9748, 9695, 9641, 9585, 9517, 9448, 9381, 0, +RawData_Avg_High_Tx14=9899, 9891, 9884, 9857, 9848, 9843, 9826, 9805, 9787, 9775, 9764, 9669, 10072, 9944, 9887, 9949, 9871, 9796, 9720, 9638, 9554, 9461, 9362, 9266, 0, +RawData_Max_High_Tx1=13460, 13352, 13325, 13446, 13408, 13352, 13325, 13285, 13251, 13221, 13208, 13416, 13028, 13084, 13065, 13022, 13014, 13003, 13001, 13000, 12997, 13008, 13019, 13042, 0, +RawData_Max_High_Tx2=13497, 13458, 13431, 13419, 13394, 13355, 13328, 13289, 13257, 13217, 13182, 13231, 13034, 13084, 13068, 13031, 13024, 13015, 13012, 13015, 13020, 13026, 13041, 13055, 0, +RawData_Max_High_Tx3=13524, 13481, 13451, 13406, 13385, 13352, 13320, 13288, 13258, 13219, 13182, 13205, 13062, 13089, 13068, 13034, 13032, 13023, 13018, 13022, 13026, 13035, 13050, 13074, 12717, +RawData_Max_High_Tx4=13483, 13462, 13431, 13386, 13370, 13332, 13306, 13277, 13244, 13216, 13174, 13173, 13038, 13076, 13062, 13034, 13031, 13028, 13027, 13028, 13031, 13043, 13063, 13068, 0, +RawData_Max_High_Tx5=13486, 13460, 13436, 13390, 13363, 13340, 13305, 13281, 13246, 13224, 13188, 13174, 13057, 13089, 13070, 13050, 13045, 13041, 13042, 13043, 13043, 13055, 13073, 13080, 0, +RawData_Max_High_Tx6=13473, 13451, 13420, 13374, 13350, 13320, 13289, 13266, 13236, 13220, 13188, 13157, 13074, 13090, 13074, 13061, 13049, 13045, 13043, 13045, 13046, 13054, 13063, 13073, 0, +RawData_Max_High_Tx7=13462, 13444, 13414, 13370, 13340, 13309, 13275, 13258, 13232, 13213, 13180, 13138, 13112, 13108, 13090, 13070, 13061, 13053, 13043, 13043, 13043, 13043, 13053, 13059, 12205, +RawData_Max_High_Tx8=13460, 13439, 13412, 13365, 13342, 13305, 13285, 13262, 13240, 13217, 13189, 13135, 13151, 13131, 13127, 13095, 13086, 13073, 13057, 13049, 13043, 13030, 13027, 13027, 0, +RawData_Max_High_Tx9=13450, 13424, 13400, 13352, 13327, 13294, 13274, 13254, 13232, 13209, 13185, 13122, 13198, 13166, 13159, 13117, 13105, 13088, 13068, 13046, 13031, 13011, 12987, 12969, 0, +RawData_Max_High_Tx10=13437, 13416, 13392, 13347, 13321, 13292, 13275, 13254, 13235, 13209, 13189, 13113, 13262, 13211, 13197, 13150, 13131, 13105, 13074, 13042, 13015, 12980, 12938, 12904, 0, +RawData_Max_High_Tx11=13405, 13389, 13370, 13321, 13297, 13274, 13257, 13238, 13215, 13194, 13171, 13086, 13321, 13258, 13230, 13181, 13150, 13117, 13074, 13034, 12991, 12939, 12883, 12830, 0, +RawData_Max_High_Tx12=13398, 13398, 13378, 13333, 13312, 13297, 13274, 13251, 13224, 13209, 13182, 13080, 13413, 13327, 13279, 13232, 13182, 13139, 13084, 13031, 12974, 12906, 12839, 12776, 12444, +RawData_Max_High_Tx13=13375, 13367, 13350, 13309, 13292, 13279, 13258, 13232, 13207, 13190, 13171, 13051, 13494, 13385, 13331, 13290, 13219, 13159, 13088, 13015, 12939, 12847, 12754, 12664, 0, +RawData_Max_High_Tx14=13363, 13352, 13343, 13306, 13294, 13288, 13265, 13236, 13212, 13196, 13181, 13053, 13597, 13424, 13347, 13431, 13325, 13224, 13122, 13011, 12897, 12772, 12638, 12509, 0, +RawData_Min_High_Tx1=6482, 6430, 6417, 6474, 6456, 6430, 6417, 6397, 6381, 6367, 6360, 6460, 6274, 6300, 6291, 6270, 6266, 6261, 6261, 6260, 6259, 6264, 6269, 6280, 0, +RawData_Min_High_Tx2=6499, 6480, 6467, 6461, 6450, 6431, 6418, 6399, 6383, 6365, 6348, 6371, 6276, 6300, 6292, 6275, 6272, 6267, 6266, 6267, 6270, 6272, 6279, 6287, 0, +RawData_Min_High_Tx3=6512, 6491, 6477, 6456, 6445, 6430, 6414, 6398, 6384, 6365, 6348, 6359, 6290, 6303, 6292, 6276, 6276, 6271, 6268, 6270, 6272, 6277, 6284, 6296, 6123, +RawData_Min_High_Tx4=6493, 6482, 6467, 6446, 6438, 6420, 6408, 6393, 6378, 6364, 6344, 6343, 6278, 6296, 6290, 6276, 6275, 6274, 6273, 6274, 6275, 6281, 6291, 6292, 0, +RawData_Min_High_Tx5=6494, 6482, 6470, 6448, 6435, 6424, 6407, 6395, 6378, 6368, 6350, 6344, 6287, 6303, 6294, 6284, 6281, 6279, 6280, 6281, 6281, 6287, 6295, 6298, 0, +RawData_Min_High_Tx6=6487, 6477, 6462, 6440, 6428, 6414, 6399, 6388, 6374, 6366, 6350, 6335, 6296, 6304, 6296, 6289, 6283, 6281, 6281, 6281, 6282, 6286, 6291, 6295, 0, +RawData_Min_High_Tx7=6482, 6474, 6460, 6438, 6424, 6409, 6393, 6384, 6372, 6363, 6346, 6326, 6314, 6312, 6304, 6294, 6289, 6285, 6281, 6281, 6281, 6281, 6285, 6289, 5877, +RawData_Min_High_Tx8=6482, 6471, 6458, 6435, 6424, 6407, 6397, 6386, 6376, 6365, 6351, 6325, 6333, 6323, 6321, 6305, 6302, 6295, 6287, 6283, 6281, 6274, 6273, 6273, 0, +RawData_Min_High_Tx9=6476, 6464, 6452, 6430, 6417, 6402, 6392, 6382, 6372, 6361, 6349, 6318, 6356, 6340, 6337, 6317, 6311, 6302, 6292, 6282, 6275, 6265, 6253, 6245, 0, +RawData_Min_High_Tx10=6471, 6460, 6448, 6427, 6415, 6400, 6393, 6382, 6373, 6361, 6351, 6315, 6386, 6361, 6355, 6332, 6323, 6311, 6296, 6280, 6267, 6250, 6230, 6214, 0, +RawData_Min_High_Tx11=6455, 6447, 6438, 6415, 6403, 6392, 6383, 6374, 6363, 6354, 6343, 6302, 6415, 6384, 6370, 6347, 6332, 6317, 6296, 6276, 6255, 6231, 6203, 6178, 0, +RawData_Min_High_Tx12=6452, 6452, 6442, 6421, 6410, 6403, 6392, 6381, 6368, 6361, 6348, 6298, 6459, 6417, 6395, 6372, 6348, 6327, 6300, 6275, 6248, 6214, 6183, 6152, 5992, +RawData_Min_High_Tx13=6441, 6437, 6428, 6409, 6400, 6395, 6384, 6372, 6359, 6352, 6343, 6285, 6498, 6445, 6419, 6400, 6365, 6337, 6302, 6267, 6231, 6187, 6142, 6098, 0, +RawData_Min_High_Tx14=6435, 6430, 6425, 6408, 6402, 6398, 6387, 6374, 6362, 6354, 6347, 6285, 6547, 6464, 6427, 6467, 6417, 6368, 6318, 6265, 6211, 6150, 6086, 6023, 0, +Panel_Differ_Avg_Tx1=772, 784, 786, 798, 801, 802, 808, 814, 821, 831, 836, 865, 669, 682, 693, 706, 721, 737, 753, 772, 793, 814, 839, 859, 0, +Panel_Differ_Avg_Tx2=765, 780, 783, 787, 791, 792, 798, 805, 811, 821, 825, 843, 699, 713, 725, 739, 754, 771, 789, 809, 831, 854, 879, 901, 0, +Panel_Differ_Avg_Tx3=734, 749, 751, 753, 757, 759, 765, 771, 778, 786, 790, 806, 699, 712, 723, 738, 754, 770, 788, 808, 830, 853, 879, 902, 941, +Panel_Differ_Avg_Tx4=719, 734, 736, 738, 742, 743, 749, 755, 762, 771, 774, 789, 709, 722, 734, 749, 766, 783, 801, 822, 843, 867, 893, 915, 0, +Panel_Differ_Avg_Tx5=703, 718, 720, 722, 726, 728, 733, 739, 746, 755, 759, 772, 719, 731, 743, 759, 775, 793, 811, 832, 854, 878, 905, 926, 0, +Panel_Differ_Avg_Tx6=688, 703, 705, 706, 710, 712, 717, 723, 730, 739, 743, 755, 728, 740, 752, 769, 785, 803, 821, 842, 864, 888, 915, 937, 0, +Panel_Differ_Avg_Tx7=669, 684, 686, 687, 691, 693, 698, 704, 710, 720, 723, 734, 734, 746, 758, 774, 790, 807, 826, 847, 869, 893, 919, 942, 903, +Panel_Differ_Avg_Tx8=663, 678, 680, 681, 685, 686, 692, 698, 704, 713, 717, 727, 753, 763, 776, 792, 809, 826, 845, 866, 888, 912, 938, 960, 0, +Panel_Differ_Avg_Tx9=656, 671, 673, 674, 678, 679, 685, 691, 698, 706, 710, 720, 772, 782, 795, 811, 827, 845, 863, 884, 906, 930, 955, 976, 0, +Panel_Differ_Avg_Tx10=650, 663, 665, 667, 671, 672, 678, 684, 691, 699, 704, 712, 791, 800, 813, 829, 846, 863, 882, 902, 923, 946, 971, 991, 0, +Panel_Differ_Avg_Tx11=643, 658, 659, 661, 664, 667, 672, 678, 685, 693, 697, 706, 811, 820, 833, 849, 865, 883, 900, 921, 942, 964, 988, 1006, 0, +Panel_Differ_Avg_Tx12=634, 648, 651, 652, 656, 658, 663, 669, 676, 684, 688, 695, 829, 837, 849, 865, 881, 898, 915, 935, 955, 976, 1000, 1018, 921, +Panel_Differ_Avg_Tx13=633, 648, 650, 651, 655, 658, 663, 669, 675, 684, 688, 694, 858, 864, 876, 893, 907, 924, 941, 959, 979, 999, 1021, 1037, 0, +Panel_Differ_Avg_Tx14=631, 644, 647, 649, 653, 656, 661, 667, 673, 682, 686, 691, 887, 889, 900, 926, 938, 953, 967, 984, 1001, 1019, 1038, 1051, 0, +Panel_Differ_Max_Tx1=1042, 1058, 1061, 1077, 1081, 1082, 1090, 1098, 1108, 1121, 1128, 1167, 903, 920, 935, 953, 973, 994, 1016, 1042, 1070, 1098, 1132, 1159, 0, +Panel_Differ_Max_Tx2=1032, 1053, 1057, 1062, 1067, 1069, 1077, 1086, 1094, 1108, 1113, 1138, 943, 962, 978, 997, 1017, 1040, 1065, 1092, 1121, 1152, 1186, 1216, 0, +Panel_Differ_Max_Tx3=990, 1011, 1013, 1016, 1021, 1024, 1032, 1040, 1050, 1061, 1066, 1088, 943, 961, 976, 996, 1017, 1039, 1063, 1090, 1120, 1151, 1186, 1217, 1270, +Panel_Differ_Max_Tx4=970, 990, 993, 996, 1001, 1003, 1011, 1019, 1028, 1040, 1044, 1065, 957, 974, 990, 1011, 1034, 1057, 1081, 1109, 1138, 1170, 1205, 1235, 0, +Panel_Differ_Max_Tx5=949, 969, 972, 974, 980, 982, 989, 997, 1007, 1019, 1024, 1042, 970, 986, 1003, 1024, 1046, 1070, 1094, 1123, 1152, 1185, 1221, 1250, 0, +Panel_Differ_Max_Tx6=928, 949, 951, 953, 958, 961, 967, 976, 985, 997, 1003, 1019, 982, 999, 1015, 1038, 1059, 1084, 1108, 1136, 1166, 1198, 1235, 1264, 0, +Panel_Differ_Max_Tx7=903, 923, 926, 927, 932, 935, 942, 950, 958, 972, 976, 990, 990, 1007, 1023, 1044, 1066, 1089, 1115, 1143, 1173, 1205, 1240, 1271, 1219, +Panel_Differ_Max_Tx8=895, 915, 918, 919, 924, 926, 934, 942, 950, 962, 967, 981, 1016, 1030, 1047, 1069, 1092, 1115, 1140, 1169, 1198, 1231, 1266, 1296, 0, +Panel_Differ_Max_Tx9=885, 905, 908, 909, 915, 916, 924, 932, 942, 953, 958, 972, 1042, 1055, 1073, 1094, 1116, 1140, 1165, 1193, 1223, 1255, 1289, 1317, 0, +Panel_Differ_Max_Tx10=877, 895, 897, 900, 905, 907, 915, 923, 932, 943, 950, 961, 1067, 1080, 1097, 1119, 1142, 1165, 1190, 1217, 1246, 1277, 1310, 1337, 0, +Panel_Differ_Max_Tx11=868, 888, 889, 892, 896, 900, 907, 915, 924, 935, 940, 953, 1094, 1107, 1124, 1146, 1167, 1192, 1215, 1243, 1271, 1301, 1333, 1358, 0, +Panel_Differ_Max_Tx12=855, 874, 878, 880, 885, 888, 895, 903, 912, 923, 928, 938, 1119, 1129, 1146, 1167, 1189, 1212, 1235, 1262, 1289, 1317, 1350, 1374, 1243, +Panel_Differ_Max_Tx13=854, 874, 877, 878, 884, 888, 895, 903, 911, 923, 928, 936, 1158, 1166, 1182, 1205, 1224, 1247, 1270, 1294, 1321, 1348, 1378, 1399, 0, +Panel_Differ_Max_Tx14=851, 869, 873, 876, 881, 885, 892, 900, 908, 920, 926, 932, 1197, 1200, 1215, 1250, 1266, 1286, 1305, 1328, 1351, 1375, 1401, 1418, 0, +Panel_Differ_Min_Tx1=502, 510, 511, 519, 521, 522, 526, 530, 534, 541, 544, 563, 435, 444, 451, 459, 469, 480, 490, 502, 516, 530, 546, 559, 0, +Panel_Differ_Min_Tx2=498, 507, 509, 512, 515, 515, 519, 524, 528, 534, 537, 548, 455, 464, 472, 481, 491, 502, 513, 526, 541, 556, 572, 586, 0, +Panel_Differ_Min_Tx3=478, 487, 489, 490, 493, 494, 498, 502, 506, 511, 514, 524, 455, 463, 470, 480, 491, 501, 513, 526, 540, 555, 572, 587, 612, +Panel_Differ_Min_Tx4=468, 478, 479, 480, 483, 483, 487, 491, 496, 502, 504, 513, 461, 470, 478, 487, 498, 509, 521, 535, 548, 564, 581, 595, 0, +Panel_Differ_Min_Tx5=457, 467, 468, 470, 472, 474, 477, 481, 485, 491, 494, 502, 468, 476, 483, 494, 504, 516, 528, 541, 556, 571, 589, 602, 0, +Panel_Differ_Min_Tx6=448, 457, 459, 459, 462, 463, 467, 470, 475, 481, 483, 491, 474, 481, 489, 500, 511, 522, 534, 548, 562, 578, 595, 610, 0, +Panel_Differ_Min_Tx7=435, 445, 446, 447, 450, 451, 454, 458, 462, 468, 470, 478, 478, 485, 493, 504, 514, 525, 537, 551, 565, 581, 598, 613, 587, +Panel_Differ_Min_Tx8=431, 441, 442, 443, 446, 446, 450, 454, 458, 464, 467, 473, 490, 496, 505, 515, 526, 537, 550, 563, 578, 593, 610, 624, 0, +Panel_Differ_Min_Tx9=427, 437, 438, 439, 441, 442, 446, 450, 454, 459, 462, 468, 502, 509, 517, 528, 538, 550, 561, 575, 589, 605, 621, 635, 0, +Panel_Differ_Min_Tx10=423, 431, 433, 434, 437, 437, 441, 445, 450, 455, 458, 463, 515, 520, 529, 539, 550, 561, 574, 587, 600, 615, 632, 645, 0, +Panel_Differ_Min_Tx11=418, 428, 429, 430, 432, 434, 437, 441, 446, 451, 454, 459, 528, 533, 542, 552, 563, 574, 585, 599, 613, 627, 643, 654, 0, +Panel_Differ_Min_Tx12=413, 422, 424, 424, 427, 428, 431, 435, 440, 445, 448, 452, 539, 545, 552, 563, 573, 584, 595, 608, 621, 635, 650, 662, 599, +Panel_Differ_Min_Tx13=412, 422, 423, 424, 426, 428, 431, 435, 439, 445, 448, 452, 558, 562, 570, 581, 590, 601, 612, 624, 637, 650, 664, 675, 0, +Panel_Differ_Min_Tx14=411, 419, 421, 422, 425, 427, 430, 434, 438, 444, 446, 450, 577, 578, 585, 602, 610, 620, 629, 640, 651, 663, 675, 684, 0, +[COM_Setting] +COM_ID=0 +BaudRate=115200 diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT3C47.c b/drivers/input/touchscreen/ft5435/lib/Config_FT3C47.c new file mode 100644 index 0000000000000..35e56052d2c5f --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT3C47.c @@ -0,0 +1,625 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT3C47.c +* +* Author: Software Development Team, AE +* +* Created: 2015-12-02 +* +* Abstract: Set Config for FT3C47 +* +************************************************************************/ +#include +#include +#include "Config_FT3C47.h" +#include "ini.h" +#include "Global.h" + + +struct stCfg_FT3C47_TestItem g_stCfg_FT3C47_TestItem; +struct stCfg_FT3C47_BasicThreshold g_stCfg_FT3C47_BasicThreshold; + +void OnInit_FT3C47_TestItem(char *strIniFile) +{ + char str[512]; + + + GetPrivateProfileString("TestItem", "FW_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.FW_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FACTORY_ID_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.FACTORY_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PROJECT_CODE_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.PROJECT_CODE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "IC_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.IC_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "LCM_ID_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.LCM_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT3C47_TestItem.RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "ADC_DETECT_TEST", "1", str, strIniFile); + g_stCfg_FT3C47_TestItem.ADC_DETECT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SCAP_CB_TEST", "1", str, strIniFile); + g_stCfg_FT3C47_TestItem.SCAP_CB_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SCAP_RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT3C47_TestItem.SCAP_RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNEL_NUM_TEST", "1", str, strIniFile); + g_stCfg_FT3C47_TestItem.CHANNEL_NUM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "INT_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.INT_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RESET_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.RESET_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "NOISE_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.NOISE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "WEAK_SHORT_CIRCUIT_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.WEAK_SHORT_CIRCUIT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CM_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.CM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_MARGIN_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.RAWDATA_MARGIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PANEL_DIFFER_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.PANEL_DIFFER_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PANEL_DIFFER_UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.PANEL_DIFFER_UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "TE_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.TE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SITO_RAWDATA_UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.SITO_RAWDATA_UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PATTERN_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.PATTERN_TEST = atoi(str); + + + + GetPrivateProfileString("TestItem", "FORCETOUCH_CHANNEL_NUM_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.FORCETOUCH_CHANNEL_NUM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FORCETOUCH_RAWDATA_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.FORCETOUCH_RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FORCETOUCH_CB_TEST", "0", str, strIniFile); + g_stCfg_FT3C47_TestItem.FORCETOUCH_CB_TEST = atoi(str); +} +void OnInit_FT3C47_BasicThreshold(char *strIniFile) +{ + char str[512]; + + + + GetPrivateProfileString("Basic_Threshold", "FW_VER_VALUE", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.FW_VER_VALUE = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Factory_ID_Number", "255", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Factory_ID_Number = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Project_Code", " ", str, strIniFile); + + sprintf(g_stCfg_FT3C47_BasicThreshold.Project_Code, "%s", str); + + + GetPrivateProfileString("Basic_Threshold", "IC_Version", "3", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.IC_Version = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "LCM_ID", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.LCM_ID = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Min", "3000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawDataTest_low_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Max", "15000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawDataTest_Low_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Min", "3000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawDataTest_high_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Max", "15000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawDataTest_high_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_LowFreq", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawDataTest_SetLowFreq = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_HighFreq", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawDataTest_SetHighFreq = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "Adc_Detect_Max", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.AdcDetect_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Min", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Max", "240", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_OFF_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Min", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Max", "240", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ScapCBTest_SetWaterproof_OFF", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_SetWaterproof_OFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ScapCBTest_SetWaterproof_ON", "240", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_SetWaterproof_ON = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapCBTest_LetTx_Disable", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapCbTest_LetTx_Disable = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Min", "5000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Max", "8500", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_OFF_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Min", "5000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Max", "8500", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_SetWaterproof_OFF", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_SetWaterproof_OFF = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_SetWaterproof_ON", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_SetWaterproof_ON = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_LetTx_Disable", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_LetTx_Disable = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Mapping", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bChannelTestMapping = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_NoMapping", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bChannelTestNoMapping = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_TxNum", "13", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ChannelNumTest_TxNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_RxNum", "24", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ChannelNumTest_RxNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Tx_NP_Num", "13", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ChannelNumTest_TxNpNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Rx_NP_Num", "24", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ChannelNumTest_RxNpNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ResetPinTest_RegAddr", "136", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ResetPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "IntPinTest_RegAddr", "79", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.IntPinTest_RegAddr = atoi(str); + GetPrivateProfileString("Basic_Threshold", "IntPinTest_TestNum", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.IntPinTest_TestNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Max", "20", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Frames", "32", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_Frames = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Time", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_Time = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_SampeMode", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_SampeMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_NoiseMode", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_NoiseMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_ShowTip", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_ShowTip = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_GloveMode", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bNoiseTest_GloveMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_RawdataMin", "5000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_RawdataMin = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "GloveNoiseTest_Coefficient", "100", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.GloveNoiseTest_Coefficient = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "Set_Frequency", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Set_Frequency = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseThreshold_Choose", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bNoiseThreshold_Choose = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Threshold", "50", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_Threshold = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_MinNGFrame", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.NoiseTest_MinNgFrame = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "WeakShortTest_CG", "2000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.WeakShortTest_CG = atoi(str); + GetPrivateProfileString("Basic_Threshold", "WeakShortTest_CC", "2000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.WeakShortTest_CC = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Uniformity_CheckTx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Uniformity_CheckRx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_MinMax", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Uniformity_CheckMinMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Tx_Hole", "20", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Uniformity_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Rx_Hole", "20", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Uniformity_Rx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_MinMax_Hole", "70", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.Uniformity_MinMax_Hole = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "CMTest_Check_Min", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.CMTest_CheckMin = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Check_Max", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.CMTest_CheckMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Min_Hole", "0.5", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.CMTest_MinHole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Max_Hole", "5", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.CMTest_MaxHole = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawdataMarginTest_Min", "10", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawdataMarginTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawdataMarginTest_Max", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.RawdataMarginTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PanelDifferTest_Min", "150", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDifferTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDifferTest_Max", "1000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDifferTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDiffer_UniformityTest_Check_Tx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDiffer_UniformityTest_Check_Rx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_MinMax", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDiffer_UniformityTest_Check_MinMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Tx_Hole", "20", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDiffer_UniformityTest_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Rx_Hole", "20", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDiffer_UniformityTest_Rx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_MinMax_Hole", "70", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.PanelDiffer_UniformityTest_MinMax_Hole = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SITO_RawdtaUniformityTest_Check_Tx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SITO_RawdtaUniformityTest_Check_Rx = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Tx_Hole", "10", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SITO_RawdtaUniformityTest_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Rx_Hole", "10", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.SITO_RawdtaUniformityTest_Rx_Hole = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_00", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bPattern00 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_FF", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bPatternFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_55", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bPattern55 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_AA", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bPatternAA = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_BIN", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.bPatternBin = atoi(str); + + + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_ChannelNumTest_ChannelNum", "10", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_ChannelNumTest_ChannelNum = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_OFF_Min", "3000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_OFF_Max", "15000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_OFF_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_ON_Min", "3000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_ON_Max", "15000", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_SetWaterproof_OFF", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_SetWaterproof_OFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_SetWaterproof_ON", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_SetWaterproof_ON = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_OFF_Min", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCbTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_OFF_Max", "240", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCbTest_OFF_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_ON_Min", "0", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCbTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_ON_Max", "240", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCbTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_ScapCBTest_SetWaterproof_OFF", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCBTest_SetWaterproof_OFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_ScapCBTest_SetWaterproof_ON", "1", str, strIniFile); + g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCBTest_SetWaterproof_ON = atoi(str); + +} + +void SetTestItem_FT3C47() +{ + + g_TestItemNum = 0; + + + + if (g_stCfg_FT3C47_TestItem.RESET_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_RESET_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.FACTORY_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_FACTORY_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.PROJECT_CODE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_PROJECT_CODE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.FW_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_FW_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.LCM_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_LCM_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.IC_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_IC_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_ENTER_FACTORY_MODE; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + + if (g_stCfg_FT3C47_TestItem.TE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_TE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.CHANNEL_NUM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_CHANNEL_NUM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.NOISE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_NOISE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.SITO_RAWDATA_UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_SITO_RAWDATA_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.CM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_CM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.ADC_DETECT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_ADCDETECT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.SCAP_CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_SCAP_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.SCAP_RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_SCAP_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.RAWDATA_MARGIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_RAWDATA_MARGIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.WEAK_SHORT_CIRCUIT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_WEAK_SHORT_CIRCUIT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.PANEL_DIFFER_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_PANELDIFFER_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + if (g_stCfg_FT3C47_TestItem.PANEL_DIFFER_UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_PANELDIFFER_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.INT_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_INT_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.FORCETOUCH_RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_FORCE_TOUCH_SCAP_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].ItemType = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT3C47_TestItem.FORCETOUCH_CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT3C47_FORCE_TOUCH_SCAP_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].ItemType = RESULT_NULL; + g_TestItemNum++; + } +} + + diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT3C47.h b/drivers/input/touchscreen/ft5435/lib/Config_FT3C47.h new file mode 100644 index 0000000000000..b9166c88382c2 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT3C47.h @@ -0,0 +1,222 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT3C47.h +* +* Author: Software Development Team, AE +* +* Created: 2015-12-02 +* +* Abstract: Set Config for FT3C47 +* +************************************************************************/ +#ifndef _CONFIG_FT3C47_H +#define _CONFIG_FT3C47_H + +#include "test_lib.h" + +/*----------------------------------------------- +FT3C47ºÍFT3C47ÊÇͬһϵÁÐоƬ +FT5422\FT3C47ÊÇÄÚ²¿Ñз¢Ê¹ÓÃоƬ´úºÅ +FT3C47ÊÇÊг¡Ê¹ÓÃоƬ´úºÅ +------------------------------------------------*/ +struct stCfg_FT3C47_TestItem +{ + bool FW_VERSION_TEST; + bool FACTORY_ID_TEST; + bool PROJECT_CODE_TEST; + bool IC_VERSION_TEST; + bool RAWDATA_TEST; + bool ADC_DETECT_TEST; + bool SCAP_CB_TEST; + bool SCAP_RAWDATA_TEST; + bool CHANNEL_NUM_TEST; + bool INT_PIN_TEST; + bool RESET_PIN_TEST; + bool NOISE_TEST; + bool WEAK_SHORT_CIRCUIT_TEST; + bool UNIFORMITY_TEST; + bool CM_TEST; + + bool RAWDATA_MARGIN_TEST; + bool PANEL_DIFFER_TEST; + bool PANEL_DIFFER_UNIFORMITY_TEST; + + bool LCM_ID_TEST; + + bool TE_TEST; + bool SITO_RAWDATA_UNIFORMITY_TEST; + bool PATTERN_TEST; + + bool FORCETOUCH_CHANNEL_NUM_TEST; + bool FORCETOUCH_RAWDATA_TEST; + bool FORCETOUCH_CB_TEST; + bool FORCETOUCH_WEAK_SHORT_CIRCUIT_TEST; + bool FORCETOUCH_FLATNESS_TEST; +}; + +struct stCfg_FT3C47_BasicThreshold +{ + BYTE FW_VER_VALUE; + BYTE Factory_ID_Number; + char Project_Code[32]; + BYTE IC_Version; + BYTE LCM_ID; + int RawDataTest_low_Min; + int RawDataTest_Low_Max; + int RawDataTest_high_Min; + int RawDataTest_high_Max; + BYTE RawDataTest_SetLowFreq; + BYTE RawDataTest_SetHighFreq; + int AdcDetect_Max; + + int SCapCbTest_OFF_Min; + int SCapCbTest_OFF_Max; + int SCapCbTest_ON_Min; + int SCapCbTest_ON_Max; + bool SCapCbTest_LetTx_Disable; + BYTE SCapCbTest_SetWaterproof_OFF; + BYTE SCapCbTest_SetWaterproof_ON; + + int SCapRawDataTest_OFF_Min; + int SCapRawDataTest_OFF_Max; + int SCapRawDataTest_ON_Min; + int SCapRawDataTest_ON_Max; + bool SCapRawDataTest_LetTx_Disable; + BYTE SCapRawDataTest_SetWaterproof_OFF; + BYTE SCapRawDataTest_SetWaterproof_ON; + bool bChannelTestMapping; + bool bChannelTestNoMapping; + BYTE ChannelNumTest_TxNum; + BYTE ChannelNumTest_RxNum; + BYTE ChannelNumTest_TxNpNum; + BYTE ChannelNumTest_RxNpNum; + BYTE ResetPinTest_RegAddr; + BYTE IntPinTest_RegAddr; + BYTE IntPinTest_TestNum; + int NoiseTest_Max; + int GloveNoiseTest_Coefficient; + int NoiseTest_Frames; + int NoiseTest_Time; + BYTE NoiseTest_SampeMode; + BYTE NoiseTest_NoiseMode; + BYTE NoiseTest_ShowTip; + bool bNoiseTest_GloveMode; + int NoiseTest_RawdataMin; + unsigned char Set_Frequency; + bool bNoiseThreshold_Choose; + int NoiseTest_Threshold; + int NoiseTest_MinNgFrame; + + int WeakShortTest_CG; + int WeakShortTest_CC; + + bool Uniformity_CheckTx; + bool Uniformity_CheckRx; + bool Uniformity_CheckMinMax; + int Uniformity_Tx_Hole; + int Uniformity_Rx_Hole; + int Uniformity_MinMax_Hole; + bool CMTest_CheckMin; + bool CMTest_CheckMax; + int CMTest_MinHole; + int CMTest_MaxHole; + + int RawdataMarginTest_Min; + int RawdataMarginTest_Max; + + int PanelDifferTest_Min; + int PanelDifferTest_Max; + + bool PanelDiffer_UniformityTest_Check_Tx; + bool PanelDiffer_UniformityTest_Check_Rx; + bool PanelDiffer_UniformityTest_Check_MinMax; + int PanelDiffer_UniformityTest_Tx_Hole; + int PanelDiffer_UniformityTest_Rx_Hole; + int PanelDiffer_UniformityTest_MinMax_Hole; + + bool SITO_RawdtaUniformityTest_Check_Tx; + bool SITO_RawdtaUniformityTest_Check_Rx; + int SITO_RawdtaUniformityTest_Tx_Hole; + int SITO_RawdtaUniformityTest_Rx_Hole; + + bool bPattern00; + bool bPatternFF; + bool bPattern55; + bool bPatternAA; + bool bPatternBin; + + int ForceTouch_ChannelNumTest_ChannelNum; + + int ForceTouch_SCapRawDataTest_OFF_Min; + int ForceTouch_SCapRawDataTest_OFF_Max; + int ForceTouch_SCapRawDataTest_ON_Min; + int ForceTouch_SCapRawDataTest_ON_Max; + BYTE ForceTouch_SCapRawDataTest_SetWaterproof_OFF; + BYTE ForceTouch_SCapRawDataTest_SetWaterproof_ON; + + int ForceTouch_SCapCbTest_OFF_Min; + int ForceTouch_SCapCbTest_OFF_Max; + int ForceTouch_SCapCbTest_ON_Min; + int ForceTouch_SCapCbTest_ON_Max; + BYTE ForceTouch_SCapCBTest_SetWaterproof_OFF; + BYTE ForceTouch_SCapCBTest_SetWaterproof_ON; + + int ForceTouch_WeakShortTest_CG; + int ForceTouch_WeakShortTest_CC; + bool bForceTouch_WeakShortTest_CapShortTest; + + int ForceTouch_FlatnessTest_Differ_Threshold; + int ForceTouch_FlatnessTest_Differ_Coefficient; + bool ForceTouch_FlatnessTest_Differ_Threshold_Check; + bool ForceTouch_FlatnessTest_Differ_Coefficient_Check; + +}; +enum enumTestItem_FT3C47 +{ + Code_FT3C47_ENTER_FACTORY_MODE, + Code_FT3C47_DOWNLOAD, + Code_FT3C47_UPGRADE, + Code_FT3C47_FACTORY_ID_TEST, + Code_FT3C47_PROJECT_CODE_TEST, + Code_FT3C47_FW_VERSION_TEST, + Code_FT3C47_IC_VERSION_TEST, + Code_FT3C47_RAWDATA_TEST, + Code_FT3C47_ADCDETECT_TEST, + Code_FT3C47_SCAP_CB_TEST, + Code_FT3C47_SCAP_RAWDATA_TEST, + Code_FT3C47_CHANNEL_NUM_TEST, + Code_FT3C47_INT_PIN_TEST, + Code_FT3C47_RESET_PIN_TEST, + Code_FT3C47_NOISE_TEST, + Code_FT3C47_WEAK_SHORT_CIRCUIT_TEST, + Code_FT3C47_UNIFORMITY_TEST, + Code_FT3C47_CM_TEST, + Code_FT3C47_RAWDATA_MARGIN_TEST, + Code_FT3C47_WRITE_CONFIG, + Code_FT3C47_PANELDIFFER_TEST, + Code_FT3C47_PANELDIFFER_UNIFORMITY_TEST, + Code_FT3C47_LCM_ID_TEST, + Code_FT3C47_JUDEG_NORMALIZE_TYPE, + Code_FT3C47_TE_TEST, + Code_FT3C47_SITO_RAWDATA_UNIFORMITY_TEST, + Code_FT3C47_PATTERN_TEST, + + Code_FT3C47_GPIO_TEST, + Code_FT3C47_LCD_NOISE_TEST, + Code_FT3C47_FORCE_TOUCH_CHANNEL_NUM_TEST, + Code_FT3C47_FORCE_TOUCH_SCAP_RAWDATA_TEST, + Code_FT3C47_FORCE_TOUCH_SCAP_CB_TEST, + Code_FT3C47_FORCE_TOUCH_WEAK_SHORT_CIRCUIT_TEST, + Code_FT3C47_FORCE_TOUCH_FLATNESS_TEST, +}; + +extern struct stCfg_FT3C47_TestItem g_stCfg_FT3C47_TestItem; +extern struct stCfg_FT3C47_BasicThreshold g_stCfg_FT3C47_BasicThreshold; + +void OnInit_FT3C47_TestItem(char *strIniFile); +void OnInit_FT3C47_BasicThreshold(char *strIniFile); +void SetTestItem_FT3C47(void); + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT5822.c b/drivers/input/touchscreen/ft5435/lib/Config_FT5822.c new file mode 100644 index 0000000000000..1788fd055b9f0 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT5822.c @@ -0,0 +1,510 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT5X46.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Config for FT5X46\FT5X46i\FT5526\FT3X17\FT5436\FT3X27\FT5526i\FT5416\FT5426\FT5435 +* +************************************************************************/ +#include +#include +#include "Config_FT5822.h" +#include "ini.h" +#include "Global.h" + + +struct stCfg_FT5822_TestItem g_stCfg_FT5822_TestItem; +struct stCfg_FT5822_BasicThreshold g_stCfg_FT5822_BasicThreshold; + +void OnInit_FT5822_TestItem(char *strIniFile) +{ + char str[512]; + + + GetPrivateProfileString("TestItem", "FW_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.FW_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FACTORY_ID_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.FACTORY_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PROJECT_CODE_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.PROJECT_CODE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "IC_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.IC_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "LCM_ID_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.LCM_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT5822_TestItem.RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "ADC_DETECT_TEST", "1", str, strIniFile); + g_stCfg_FT5822_TestItem.ADC_DETECT_TEST = atoi(str); + + GetPrivateProfileString("TestItem", "SCAP_CB_TEST", "1", str, strIniFile); + g_stCfg_FT5822_TestItem.SCAP_CB_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SCAP_RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT5822_TestItem.SCAP_RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNEL_NUM_TEST", "1", str, strIniFile); + g_stCfg_FT5822_TestItem.CHANNEL_NUM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "INT_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.INT_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RESET_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.RESET_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "NOISE_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.NOISE_TEST = atoi(str); + + GetPrivateProfileString("TestItem", "WEAK_SHORT_CIRCUIT_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.WEAK_SHORT_CIRCUIT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CM_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.CM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_MARGIN_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.RAWDATA_MARGIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PANEL_DIFFER_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.PANEL_DIFFER_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PANEL_DIFFER_UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.PANEL_DIFFER_UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "TE_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.TE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SITO_RAWDATA_UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.SITO_RAWDATA_UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PATTERN_TEST", "0", str, strIniFile); + g_stCfg_FT5822_TestItem.PATTERN_TEST = atoi(str); +} + +void OnInit_FT5822_BasicThreshold(char *strIniFile) +{ + char str[512] = {0}; + + + + GetPrivateProfileString("Basic_Threshold", "FW_VER_VALUE", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.FW_VER_VALUE = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Factory_ID_Number", "255", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Factory_ID_Number = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Project_Code", " ", str, strIniFile); + + sprintf(g_stCfg_FT5822_BasicThreshold.Project_Code, "%s", str); + + + GetPrivateProfileString("Basic_Threshold", "IC_Version", "3", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.IC_Version = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "LCM_ID", "1", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.LCM_ID = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Min", "3000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawDataTest_low_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Max", "15000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawDataTest_Low_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Min", "3000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawDataTest_high_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Max", "15000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawDataTest_high_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_LowFreq", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawDataTest_SetLowFreq = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_HighFreq", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawDataTest_SetHighFreq = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "Adc_Detect_Max", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.AdcDetect_Max = atoi(str); + + g_stCfg_FT5822_BasicThreshold.SCapCbTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Max", "240", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapCbTest_OFF_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Min", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapCbTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Max", "240", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapCbTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ScapCBTest_SetWaterproof_OFF", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapCbTest_SetWaterproof_OFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ScapCBTest_SetWaterproof_ON", "240", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapCbTest_SetWaterproof_ON = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Min", "5000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Max", "8500", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_OFF_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Min", "5000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Max", "8500", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_SetWaterproof_OFF", "1", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_SetWaterproof_OFF = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_SetWaterproof_ON", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_SetWaterproof_ON = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Mapping", "1", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.bChannelTestMapping = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_NoMapping", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.bChannelTestNoMapping = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_TxNum", "13", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.ChannelNumTest_TxNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_RxNum", "24", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.ChannelNumTest_RxNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Tx_NP_Num", "13", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.ChannelNumTest_TxNpNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Rx_NP_Num", "24", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.ChannelNumTest_RxNpNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ResetPinTest_RegAddr", "136", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.ResetPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "IntPinTest_RegAddr", "79", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.IntPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Max", "20", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Frames", "32", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_Frames = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Time", "1", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_Time = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_SampeMode", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_SampeMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_NoiseMode", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_NoiseMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_ShowTip", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_ShowTip = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_GloveMode", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.bNoiseTest_GloveMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_RawdataMin", "5000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.NoiseTest_RawdataMin = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "GloveNoiseTest_Coefficient", "100", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.GloveNoiseTest_Coefficient = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "WeakShortTest_CG", "2000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.WeakShortTest_CG = atoi(str); + GetPrivateProfileString("Basic_Threshold", "WeakShortTest_CC", "2000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.WeakShortTest_CC = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Uniformity_CheckTx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Uniformity_CheckRx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_MinMax", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Uniformity_CheckMinMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Tx_Hole", "20", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Uniformity_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Rx_Hole", "20", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Uniformity_Rx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_MinMax_Hole", "70", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.Uniformity_MinMax_Hole = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "CMTest_Check_Min", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.CMTest_CheckMin = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Check_Max", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.CMTest_CheckMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Min_Hole", "0.5", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.CMTest_MinHole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Max_Hole", "5", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.CMTest_MaxHole = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawdataMarginTest_Min", "10", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawdataMarginTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawdataMarginTest_Max", "1", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.RawdataMarginTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PanelDifferTest_Min", "150", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDifferTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDifferTest_Max", "1000", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDifferTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDiffer_UniformityTest_Check_Tx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDiffer_UniformityTest_Check_Rx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_MinMax", "0", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDiffer_UniformityTest_Check_MinMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Tx_Hole", "20", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDiffer_UniformityTest_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Rx_Hole", "20", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDiffer_UniformityTest_Rx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_MinMax_Hole", "70", str, strIniFile); + g_stCfg_FT5822_BasicThreshold.PanelDiffer_UniformityTest_MinMax_Hole = atoi(str); +} + +void SetTestItem_FT5822() +{ + + g_TestItemNum = 0; + + + + if (g_stCfg_FT5822_TestItem.RESET_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_RESET_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.FACTORY_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_FACTORY_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.PROJECT_CODE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_PROJECT_CODE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.FW_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_FW_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.LCM_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_LCM_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.IC_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_IC_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_ENTER_FACTORY_MODE; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + + if (g_stCfg_FT5822_TestItem.TE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_TE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.CHANNEL_NUM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_CHANNEL_NUM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.NOISE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_NOISE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.SITO_RAWDATA_UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_SITO_RAWDATA_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.CM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_CM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.ADC_DETECT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_ADCDETECT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.SCAP_CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_SCAP_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.SCAP_RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_SCAP_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.RAWDATA_MARGIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_RAWDATA_MARGIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.WEAK_SHORT_CIRCUIT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_WEAK_SHORT_CIRCUIT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.PANEL_DIFFER_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_PANELDIFFER_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + if (g_stCfg_FT5822_TestItem.PANEL_DIFFER_UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_PANELDIFFER_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5822_TestItem.INT_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5822_INT_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } +} + + diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT5822.h b/drivers/input/touchscreen/ft5435/lib/Config_FT5822.h new file mode 100644 index 0000000000000..4bbf4aa962cdb --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT5822.h @@ -0,0 +1,189 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT5822.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-23 +* +* Abstract: Set Config for FT5X46\FT5X46i\FT5526\FT3X17\FT5436\FT3X27\FT5526i\FT5416\FT5426\FT5435 +* +************************************************************************/ +#ifndef _CONFIG_FT5822_H +#define _CONFIG_FT5822_H + +#include "test_lib.h" + +struct stCfg_FT5822_TestItem +{ + bool FW_VERSION_TEST; + bool FACTORY_ID_TEST; + bool PROJECT_CODE_TEST; + bool IC_VERSION_TEST; + bool RAWDATA_TEST; + bool ADC_DETECT_TEST; + bool SCAP_CB_TEST; + bool SCAP_RAWDATA_TEST; + bool CHANNEL_NUM_TEST; + bool INT_PIN_TEST; + bool RESET_PIN_TEST; + bool NOISE_TEST; + bool WEAK_SHORT_CIRCUIT_TEST; + bool UNIFORMITY_TEST; + bool CM_TEST; + + bool RAWDATA_MARGIN_TEST; + bool PANEL_DIFFER_TEST; + bool PANEL_DIFFER_UNIFORMITY_TEST; + + bool LCM_ID_TEST; + + bool TE_TEST; + bool SITO_RAWDATA_UNIFORMITY_TEST; + bool PATTERN_TEST; +}; +struct stCfg_FT5822_BasicThreshold +{ + BYTE FW_VER_VALUE; + BYTE Factory_ID_Number; + char Project_Code[32]; + BYTE IC_Version; + BYTE LCM_ID; + int RawDataTest_low_Min; + int RawDataTest_Low_Max; + int RawDataTest_high_Min; + int RawDataTest_high_Max; + BYTE RawDataTest_SetLowFreq; + BYTE RawDataTest_SetHighFreq; + int AdcDetect_Max; + + + + + int SCapCbTest_OFF_Min; + int SCapCbTest_OFF_Max; + int SCapCbTest_ON_Min; + int SCapCbTest_ON_Max; + bool SCapCbTest_LetTx_Disable; + BYTE SCapCbTest_SetWaterproof_OFF; + BYTE SCapCbTest_SetWaterproof_ON; + + + + int SCapRawDataTest_OFF_Min; + int SCapRawDataTest_OFF_Max; + int SCapRawDataTest_ON_Min; + int SCapRawDataTest_ON_Max; + bool SCapRawDataTest_LetTx_Disable; + BYTE SCapRawDataTest_SetWaterproof_OFF; + BYTE SCapRawDataTest_SetWaterproof_ON; + bool bChannelTestMapping; + bool bChannelTestNoMapping; + BYTE ChannelNumTest_TxNum; + BYTE ChannelNumTest_RxNum; + BYTE ChannelNumTest_TxNpNum; + BYTE ChannelNumTest_RxNpNum; + BYTE ResetPinTest_RegAddr; + BYTE IntPinTest_RegAddr; + BYTE IntPinTest_TestNum; + int NoiseTest_Max; + int GloveNoiseTest_Coefficient; + int NoiseTest_Frames; + int NoiseTest_Time; + BYTE NoiseTest_SampeMode; + BYTE NoiseTest_NoiseMode; + BYTE NoiseTest_ShowTip; + bool bNoiseTest_GloveMode; + int NoiseTest_RawdataMin; + unsigned char Set_Frequency; + bool bNoiseThreshold_Choose; + int NoiseTest_Threshold; + int NoiseTest_MinNgFrame; + + + + + + + + + + int WeakShortTest_CG; + int WeakShortTest_CC; + + bool Uniformity_CheckTx; + bool Uniformity_CheckRx; + bool Uniformity_CheckMinMax; + int Uniformity_Tx_Hole; + int Uniformity_Rx_Hole; + int Uniformity_MinMax_Hole; + bool CMTest_CheckMin; + bool CMTest_CheckMax; + int CMTest_MinHole; + int CMTest_MaxHole; + + int RawdataMarginTest_Min; + int RawdataMarginTest_Max; + + int PanelDifferTest_Min; + int PanelDifferTest_Max; + + bool PanelDiffer_UniformityTest_Check_Tx; + bool PanelDiffer_UniformityTest_Check_Rx; + bool PanelDiffer_UniformityTest_Check_MinMax; + int PanelDiffer_UniformityTest_Tx_Hole; + int PanelDiffer_UniformityTest_Rx_Hole; + int PanelDiffer_UniformityTest_MinMax_Hole; + + bool SITO_RawdtaUniformityTest_Check_Tx; + bool SITO_RawdtaUniformityTest_Check_Rx; + int SITO_RawdtaUniformityTest_Tx_Hole; + int SITO_RawdtaUniformityTest_Rx_Hole; + + bool bPattern00; + bool bPatternFF; + bool bPattern55; + bool bPatternAA; + bool bPatternBin; +}; +enum enumTestItem_FT5822 +{ + Code_FT5822_ENTER_FACTORY_MODE, + Code_FT5822_DOWNLOAD, + Code_FT5822_UPGRADE, + Code_FT5822_FACTORY_ID_TEST, + Code_FT5822_PROJECT_CODE_TEST, + Code_FT5822_FW_VERSION_TEST, + Code_FT5822_IC_VERSION_TEST, + Code_FT5822_RAWDATA_TEST, + Code_FT5822_ADCDETECT_TEST, + Code_FT5822_SCAP_CB_TEST, + Code_FT5822_SCAP_RAWDATA_TEST, + Code_FT5822_CHANNEL_NUM_TEST, + Code_FT5822_INT_PIN_TEST, + Code_FT5822_RESET_PIN_TEST, + Code_FT5822_NOISE_TEST, + Code_FT5822_WEAK_SHORT_CIRCUIT_TEST, + Code_FT5822_UNIFORMITY_TEST, + Code_FT5822_CM_TEST, + Code_FT5822_RAWDATA_MARGIN_TEST, + Code_FT5822_WRITE_CONFIG, + Code_FT5822_PANELDIFFER_TEST, + Code_FT5822_PANELDIFFER_UNIFORMITY_TEST, + Code_FT5822_LCM_ID_TEST, + Code_FT5822_JUDEG_NORMALIZE_TYPE, + Code_FT5822_TE_TEST, + Code_FT5822_SITO_RAWDATA_UNIFORMITY_TEST, + Code_FT5822_PATTERN_TEST, +}; + +extern struct stCfg_FT5822_TestItem g_stCfg_FT5822_TestItem; +extern struct stCfg_FT5822_BasicThreshold g_stCfg_FT5822_BasicThreshold; + +void OnInit_FT5822_TestItem(char *strIniFile); +void OnInit_FT5822_BasicThreshold(char *strIniFile); +void SetTestItem_FT5822(void); + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT5X46.c b/drivers/input/touchscreen/ft5435/lib/Config_FT5X46.c new file mode 100644 index 0000000000000..9564afd01ea44 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT5X46.c @@ -0,0 +1,556 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT5X46.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Config for FT5X46\FT5X46i\FT5526\FT3X17\FT5436\FT3X27\FT5526i\FT5416\FT5426\FT5435 +* +************************************************************************/ +#include +#include +#include "Config_FT5X46.h" +#include "ini.h" +#include "Global.h" + + +struct stCfg_FT5X22_TestItem g_stCfg_FT5X22_TestItem; +struct stCfg_FT5X22_BasicThreshold g_stCfg_FT5X22_BasicThreshold; + +void OnInit_FT5X22_TestItem(char *strIniFile) +{ + char str[512]; + + + GetPrivateProfileString("TestItem", "FW_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.FW_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FACTORY_ID_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.FACTORY_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PROJECT_CODE_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.PROJECT_CODE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "IC_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.IC_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "LCM_ID_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.LCM_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT5X22_TestItem.RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "ADC_DETECT_TEST", "1", str, strIniFile); + g_stCfg_FT5X22_TestItem.ADC_DETECT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SCAP_CB_TEST", "1", str, strIniFile); + g_stCfg_FT5X22_TestItem.SCAP_CB_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SCAP_RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT5X22_TestItem.SCAP_RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNEL_NUM_TEST", "1", str, strIniFile); + g_stCfg_FT5X22_TestItem.CHANNEL_NUM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "INT_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.INT_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RESET_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.RESET_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "NOISE_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.NOISE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "WEAK_SHORT_CIRCUIT_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.WEAK_SHORT_CIRCUIT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CM_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.CM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_MARGIN_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.RAWDATA_MARGIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PANEL_DIFFER_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.PANEL_DIFFER_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PANEL_DIFFER_UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.PANEL_DIFFER_UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "TE_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.TE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SITO_RAWDATA_UNIFORMITY_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.SITO_RAWDATA_UNIFORMITY_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PATTERN_TEST", "0", str, strIniFile); + g_stCfg_FT5X22_TestItem.PATTERN_TEST = atoi(str); +} +void OnInit_FT5X22_BasicThreshold(char *strIniFile) +{ + char str[512]; + + + + GetPrivateProfileString("Basic_Threshold", "FW_VER_VALUE", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.FW_VER_VALUE = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Factory_ID_Number", "255", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Factory_ID_Number = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Project_Code", " ", str, strIniFile); + + sprintf(g_stCfg_FT5X22_BasicThreshold.Project_Code, "%s", str); + + + GetPrivateProfileString("Basic_Threshold", "IC_Version", "3", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.IC_Version = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "LCM_ID", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.LCM_ID = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Min", "3000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawDataTest_low_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Max", "15000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawDataTest_Low_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Min", "3000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawDataTest_high_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Max", "15000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawDataTest_high_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_LowFreq", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawDataTest_SetLowFreq = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_HighFreq", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawDataTest_SetHighFreq = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "Adc_Detect_Max", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.AdcDetect_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Min", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Max", "240", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_OFF_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Min", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Max", "240", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ScapCBTest_SetWaterproof_OFF", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_SetWaterproof_OFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ScapCBTest_SetWaterproof_ON", "240", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_SetWaterproof_ON = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapCBTest_LetTx_Disable", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapCbTest_LetTx_Disable = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Min", "5000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_OFF_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Max", "8500", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_OFF_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Min", "5000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_ON_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Max", "8500", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_ON_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_SetWaterproof_OFF", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_SetWaterproof_OFF = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_SetWaterproof_ON", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_SetWaterproof_ON = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_LetTx_Disable", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_LetTx_Disable = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Mapping", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bChannelTestMapping = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_NoMapping", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bChannelTestNoMapping = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_TxNum", "13", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.ChannelNumTest_TxNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_RxNum", "24", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.ChannelNumTest_RxNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Tx_NP_Num", "13", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.ChannelNumTest_TxNpNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_Rx_NP_Num", "24", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.ChannelNumTest_RxNpNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ResetPinTest_RegAddr", "136", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.ResetPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "IntPinTest_RegAddr", "79", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.IntPinTest_RegAddr = atoi(str); + GetPrivateProfileString("Basic_Threshold", "IntPinTest_TestNum", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.IntPinTest_TestNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Max", "20", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Frames", "32", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_Frames = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Time", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_Time = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_SampeMode", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_SampeMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_NoiseMode", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_NoiseMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_ShowTip", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_ShowTip = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_GloveMode", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bNoiseTest_GloveMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_RawdataMin", "5000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_RawdataMin = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "GloveNoiseTest_Coefficient", "100", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.GloveNoiseTest_Coefficient = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "Set_Frequency", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Set_Frequency = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseThreshold_Choose", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bNoiseThreshold_Choose = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Threshold", "50", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_Threshold = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_MinNGFrame", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.NoiseTest_MinNgFrame = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "WeakShortTest_CG", "2000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.WeakShortTest_CG = atoi(str); + GetPrivateProfileString("Basic_Threshold", "WeakShortTest_CC", "2000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.WeakShortTest_CC = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Uniformity_CheckTx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Uniformity_CheckRx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Check_MinMax", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Uniformity_CheckMinMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Tx_Hole", "20", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Uniformity_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_Rx_Hole", "20", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Uniformity_Rx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "UniformityTest_MinMax_Hole", "70", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.Uniformity_MinMax_Hole = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "CMTest_Check_Min", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.CMTest_CheckMin = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Check_Max", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.CMTest_CheckMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Min_Hole", "0.5", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.CMTest_MinHole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CMTest_Max_Hole", "5", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.CMTest_MaxHole = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawdataMarginTest_Min", "10", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawdataMarginTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawdataMarginTest_Max", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.RawdataMarginTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PanelDifferTest_Min", "150", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDifferTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDifferTest_Max", "1000", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDifferTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDiffer_UniformityTest_Check_Tx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDiffer_UniformityTest_Check_Rx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Check_MinMax", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDiffer_UniformityTest_Check_MinMax = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Tx_Hole", "20", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDiffer_UniformityTest_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_Rx_Hole", "20", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDiffer_UniformityTest_Rx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PanelDiffer_UniformityTest_MinMax_Hole", "70", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.PanelDiffer_UniformityTest_MinMax_Hole = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Check_Tx", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SITO_RawdtaUniformityTest_Check_Tx = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Check_Rx", "0", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SITO_RawdtaUniformityTest_Check_Rx = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Tx_Hole", "10", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SITO_RawdtaUniformityTest_Tx_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SITO_RawdataUniformityTest_Rx_Hole", "10", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.SITO_RawdtaUniformityTest_Rx_Hole = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_00", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bPattern00 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_FF", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bPatternFF = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_55", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bPattern55 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_AA", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bPatternAA = atoi(str); + GetPrivateProfileString("Basic_Threshold", "PramTest_Check_BIN", "1", str, strIniFile); + g_stCfg_FT5X22_BasicThreshold.bPatternBin = atoi(str); +} + +void SetTestItem_FT5X22() +{ + + g_TestItemNum = 0; + + + + if (g_stCfg_FT5X22_TestItem.RESET_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_RESET_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.FACTORY_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_FACTORY_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.PROJECT_CODE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_PROJECT_CODE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.FW_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_FW_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.LCM_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_LCM_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.IC_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_IC_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_ENTER_FACTORY_MODE; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + + if (g_stCfg_FT5X22_TestItem.TE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_TE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.CHANNEL_NUM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_CHANNEL_NUM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.NOISE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_NOISE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.SITO_RAWDATA_UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_SITO_RAWDATA_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.CM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_CM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.ADC_DETECT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_ADCDETECT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.SCAP_CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_SCAP_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.SCAP_RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_SCAP_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.RAWDATA_MARGIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_RAWDATA_MARGIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.WEAK_SHORT_CIRCUIT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_WEAK_SHORT_CIRCUIT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.PANEL_DIFFER_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_PANELDIFFER_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + if (g_stCfg_FT5X22_TestItem.PANEL_DIFFER_UNIFORMITY_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_PANELDIFFER_UNIFORMITY_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT5X22_TestItem.INT_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT5X22_INT_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } +} + + diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT5X46.h b/drivers/input/touchscreen/ft5435/lib/Config_FT5X46.h new file mode 100644 index 0000000000000..83ec8118f9ebc --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT5X46.h @@ -0,0 +1,186 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT5X46.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Config for FT5X46\FT5X46i\FT5526\FT3X17\FT5436\FT3X27\FT5526i\FT5416\FT5426\FT5435 +* +************************************************************************/ +#ifndef _CONFIG_FT5X46_H +#define _CONFIG_FT5X46_H + +#include "test_lib.h" + +/*----------------------------------------------- +FT5X46ºÍFT5X22ÊÇͬһϵÁÐоƬ +FT5422\FT5X22ÊÇÄÚ²¿Ñз¢Ê¹ÓÃоƬ´úºÅ +FT5X46ÊÇÊг¡Ê¹ÓÃоƬ´úºÅ +------------------------------------------------*/ +struct stCfg_FT5X22_TestItem +{ + bool FW_VERSION_TEST; + bool FACTORY_ID_TEST; + bool PROJECT_CODE_TEST; + bool IC_VERSION_TEST; + bool RAWDATA_TEST; + bool ADC_DETECT_TEST; + bool SCAP_CB_TEST; + bool SCAP_RAWDATA_TEST; + bool CHANNEL_NUM_TEST; + bool INT_PIN_TEST; + bool RESET_PIN_TEST; + bool NOISE_TEST; + bool WEAK_SHORT_CIRCUIT_TEST; + bool UNIFORMITY_TEST; + bool CM_TEST; + + bool RAWDATA_MARGIN_TEST; + bool PANEL_DIFFER_TEST; + bool PANEL_DIFFER_UNIFORMITY_TEST; + + bool LCM_ID_TEST; + + bool TE_TEST; + bool SITO_RAWDATA_UNIFORMITY_TEST; + bool PATTERN_TEST; +}; +struct stCfg_FT5X22_BasicThreshold +{ + BYTE FW_VER_VALUE; + BYTE Factory_ID_Number; + char Project_Code[32]; + BYTE IC_Version; + BYTE LCM_ID; + int RawDataTest_low_Min; + int RawDataTest_Low_Max; + int RawDataTest_high_Min; + int RawDataTest_high_Max; + BYTE RawDataTest_SetLowFreq; + BYTE RawDataTest_SetHighFreq; + int AdcDetect_Max; + + + + + int SCapCbTest_OFF_Min; + int SCapCbTest_OFF_Max; + int SCapCbTest_ON_Min; + int SCapCbTest_ON_Max; + bool SCapCbTest_LetTx_Disable; + BYTE SCapCbTest_SetWaterproof_OFF; + BYTE SCapCbTest_SetWaterproof_ON; + + + + int SCapRawDataTest_OFF_Min; + int SCapRawDataTest_OFF_Max; + int SCapRawDataTest_ON_Min; + int SCapRawDataTest_ON_Max; + bool SCapRawDataTest_LetTx_Disable; + BYTE SCapRawDataTest_SetWaterproof_OFF; + BYTE SCapRawDataTest_SetWaterproof_ON; + bool bChannelTestMapping; + bool bChannelTestNoMapping; + BYTE ChannelNumTest_TxNum; + BYTE ChannelNumTest_RxNum; + BYTE ChannelNumTest_TxNpNum; + BYTE ChannelNumTest_RxNpNum; + BYTE ResetPinTest_RegAddr; + BYTE IntPinTest_RegAddr; + BYTE IntPinTest_TestNum; + int NoiseTest_Max; + int GloveNoiseTest_Coefficient; + int NoiseTest_Frames; + int NoiseTest_Time; + BYTE NoiseTest_SampeMode; + BYTE NoiseTest_NoiseMode; + BYTE NoiseTest_ShowTip; + bool bNoiseTest_GloveMode; + int NoiseTest_RawdataMin; + unsigned char Set_Frequency; + bool bNoiseThreshold_Choose; + int NoiseTest_Threshold; + int NoiseTest_MinNgFrame; + + int WeakShortTest_CG; + int WeakShortTest_CC; + + bool Uniformity_CheckTx; + bool Uniformity_CheckRx; + bool Uniformity_CheckMinMax; + int Uniformity_Tx_Hole; + int Uniformity_Rx_Hole; + int Uniformity_MinMax_Hole; + bool CMTest_CheckMin; + bool CMTest_CheckMax; + int CMTest_MinHole; + int CMTest_MaxHole; + + int RawdataMarginTest_Min; + int RawdataMarginTest_Max; + + int PanelDifferTest_Min; + int PanelDifferTest_Max; + + bool PanelDiffer_UniformityTest_Check_Tx; + bool PanelDiffer_UniformityTest_Check_Rx; + bool PanelDiffer_UniformityTest_Check_MinMax; + int PanelDiffer_UniformityTest_Tx_Hole; + int PanelDiffer_UniformityTest_Rx_Hole; + int PanelDiffer_UniformityTest_MinMax_Hole; + + bool SITO_RawdtaUniformityTest_Check_Tx; + bool SITO_RawdtaUniformityTest_Check_Rx; + int SITO_RawdtaUniformityTest_Tx_Hole; + int SITO_RawdtaUniformityTest_Rx_Hole; + + bool bPattern00; + bool bPatternFF; + bool bPattern55; + bool bPatternAA; + bool bPatternBin; +}; +enum enumTestItem_FT5X22 +{ + Code_FT5X22_ENTER_FACTORY_MODE, + Code_FT5X22_DOWNLOAD, + Code_FT5X22_UPGRADE, + Code_FT5X22_FACTORY_ID_TEST, + Code_FT5X22_PROJECT_CODE_TEST, + Code_FT5X22_FW_VERSION_TEST, + Code_FT5X22_IC_VERSION_TEST, + Code_FT5X22_RAWDATA_TEST, + Code_FT5X22_ADCDETECT_TEST, + Code_FT5X22_SCAP_CB_TEST, + Code_FT5X22_SCAP_RAWDATA_TEST, + Code_FT5X22_CHANNEL_NUM_TEST, + Code_FT5X22_INT_PIN_TEST, + Code_FT5X22_RESET_PIN_TEST, + Code_FT5X22_NOISE_TEST, + Code_FT5X22_WEAK_SHORT_CIRCUIT_TEST, + Code_FT5X22_UNIFORMITY_TEST, + Code_FT5X22_CM_TEST, + Code_FT5X22_RAWDATA_MARGIN_TEST, + Code_FT5X22_WRITE_CONFIG, + Code_FT5X22_PANELDIFFER_TEST, + Code_FT5X22_PANELDIFFER_UNIFORMITY_TEST, + Code_FT5X22_LCM_ID_TEST, + Code_FT5X22_JUDEG_NORMALIZE_TYPE, + Code_FT5X22_TE_TEST, + Code_FT5X22_SITO_RAWDATA_UNIFORMITY_TEST, + Code_FT5X22_PATTERN_TEST, +}; + +extern struct stCfg_FT5X22_TestItem g_stCfg_FT5X22_TestItem; +extern struct stCfg_FT5X22_BasicThreshold g_stCfg_FT5X22_BasicThreshold; + +void OnInit_FT5X22_TestItem(char *strIniFile); +void OnInit_FT5X22_BasicThreshold(char *strIniFile); +void SetTestItem_FT5X22(void); + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT6X36.c b/drivers/input/touchscreen/ft5435/lib/Config_FT6X36.c new file mode 100644 index 0000000000000..e8f06d6be2e25 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT6X36.c @@ -0,0 +1,647 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT6X36.c +* +* Author: Software Development Team, AE +* +* Created: 2015-10-08 +* +* Abstract: Set Config for FT6X36/FT3X07/FT6416/FT6426 +* +************************************************************************/ +#include +#include +#include "Config_FT6X36.h" +#include "ini.h" +#include "Global.h" + + +struct stCfg_FT6X36_TestItem g_stCfg_FT6X36_TestItem; +struct stCfg_FT6X36_BasicThreshold g_stCfg_FT6X36_BasicThreshold; + + +void OnInit_FT6X36_TestItem(char *strIniFile) +{ + char str[512] = {0}; + + + GetPrivateProfileString("TestItem", "FW_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.FW_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FACTORY_ID_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.FACTORY_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PROJECT_CODE_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.PROJECT_CODE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "IC_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.IC_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNEL_NUM_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.CHANNEL_NUM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNEL_SHORT_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.CHANNEL_SHORT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "INT_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.INT_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RESET_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.RESET_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "NOISE_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.NOISE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CB_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.CB_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "DELTA_CB_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.DELTA_CB_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNELS_DEVIATION_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.CHANNELS_DEVIATION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "TWO_SIDES_DEVIATION_TEST", "1", str, strIniFile); + g_stCfg_FT6X36_TestItem.TWO_SIDES_DEVIATION_TEST = atoi(str); + + + + GetPrivateProfileString("TestItem", "FPC_SHORT_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.FPC_SHORT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FPC_OPEN_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.FPC_OPEN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SREF_OPEN_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.SREF_OPEN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "TE_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.TE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CB_DEVIATION_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.CB_DEVIATION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "DIFFER_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.DIFFER_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "WEAK_SHORT_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.WEAK_SHORT_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "DIFFER_TEST2", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.DIFFER_TEST2 = atoi(str); + + + GetPrivateProfileString("TestItem", "K1_DIFFER_TEST", "0", str, strIniFile); + g_stCfg_FT6X36_TestItem.K1_DIFFER_TEST = atoi(str); +} + +void OnInit_FT6X36_BasicThreshold(char *strIniFile) +{ + char str[512] = {0}; + + + + GetPrivateProfileString("Basic_Threshold", "FW_VER_VALUE", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FW_VER_VALUE = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Factory_ID_Number", "255", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.Factory_ID_Number = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Project_Code", " ", str, strIniFile); + + sprintf(g_stCfg_FT6X36_BasicThreshold.Project_Code, "%s", str); + + + GetPrivateProfileString("Basic_Threshold", "IC_Version", "3", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.IC_Version = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Min", "13000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.RawDataTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Max", "17000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.RawDataTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_ChannelNum", "22", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelNumTest_ChannelNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_KeyNum", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelNumTest_KeyNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelShortTest_K1", "255", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelShortTest_K1 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelShortTest_K2", "255", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelShortTest_K2 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelShortTest_CB", "255", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelShortTest_CB = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ResetPinTest_RegAddr", "136", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ResetPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "IntPinTest_RegAddr", "175", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.IntPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Max", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.NoiseTest_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Frames", "32", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.NoiseTest_Frames = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Time", "1", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.NoiseTest_Time = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_SampeMode", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.NoiseTest_SampeMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_NoiseMode", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.NoiseTest_NoiseMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_ShowTip", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.NoiseTest_ShowTip = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "CbTest_Min", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.CbTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CbTest_Max", "250", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.CbTest_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Base", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Base = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Differ_Max", "50", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Differ_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Include_Key_Test", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Include_Key_Test = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Key_Differ_Max", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Key_Differ_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Deviation_S1", "15", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S1 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Deviation_S2", "15", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S2 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Deviation_S3", "12", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S3 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Deviation_S4", "12", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S4 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Deviation_S5", "12", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S5 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Deviation_S6", "12", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S6 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Set_Critical", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Set_Critical = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Critical_S1", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S1 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Critical_S2", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S2 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Critical_S3", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S3 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Critical_S4", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S4 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Critical_S5", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S5 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DeltaCbTest_Critical_S6", "20", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S6 = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Deviation_S1", "8", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S1 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Deviation_S2", "8", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S2 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Deviation_S3", "8", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S3 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Deviation_S4", "8", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S4 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Deviation_S5", "8", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S5 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Deviation_S6", "8", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S6 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Set_Critical", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Set_Critical = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Critical_S1", "13", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S1 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Critical_S2", "13", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S2 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Critical_S3", "13", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S3 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Critical_S4", "13", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S4 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Critical_S5", "13", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S5 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ChannelsDeviationTest_Critical_S6", "13", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S6 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Deviation_S1", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S1 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Deviation_S2", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S2 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Deviation_S3", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S3 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Deviation_S4", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S4 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Deviation_S5", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S5 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Deviation_S6", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S6 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Set_Critical", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Set_Critical = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Critical_S1", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S1 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Critical_S2", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S2 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Critical_S3", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S3 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Critical_S4", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S4 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Critical_S5", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S5 = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "TwoSidesDeviationTest_Critical_S6", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S6 = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "FPCShortTest_Min_CB", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCShort_CB_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "FPCShortTest_Max_CB", "1015", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCShort_CB_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "FPCShortTest_Min_RawData", "5000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCShort_RawData_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "FPCShortTest_Max_RawData", "50000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCShort_RawData_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "FPCOpenTest_Min_CB", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCOpen_CB_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "FPCOpenTest_Max_CB", "1015", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCOpen_CB_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "FPCOpenTest_Min_RawData", "5000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCOpen_RawData_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "FPCOpenTest_Max_RawData", "50000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.FPCOpen_RawData_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "SREFOpen_Test_Hole", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.SREFOpen_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SREFOpen_Test_Hole_Base1", "50", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.SREFOpen_Hole_Base1 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SREFOpen_Test_Hole_Base2", "50", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.SREFOpen_Hole_Base2 = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "CBDeviationTest_Hole", "50", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.CBDeviationTest_Hole = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "DifferTest_Ave_Hole", "500", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.Differ_Ave_Hole = atoi(str); + GetPrivateProfileString("Basic_Threshold", "DifferTest_Max_Hole", "500", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.Differ_Max_Hole = atoi(str); + + + + GetPrivateProfileString("Basic_Threshold", "Weak_Short_Hole", "500", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.WeakShortThreshold = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_H_Min", "20000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DifferTest2_Data_H_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_H_Max", "24000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DifferTest2_Data_H_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_M_Min", "7100", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DifferTest2_Data_M_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_M_Max", "7300", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DifferTest2_Data_M_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_L_Min", "14000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DifferTest2_Data_L_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_L_Max", "16000", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.DifferTest2_Data_L_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_H", "1", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.bDifferTest2_Data_H = atoi(str); + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_M", "1", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.bDifferTest2_Data_M = atoi(str); + GetPrivateProfileString("Basic_Threshold", "DifferTest2_Data_L", "1", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.bDifferTest2_Data_L = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_StartK1", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_StartK1 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_EndK1", "25", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_EndK1 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_MinHole_STC2", "0", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_MinHold2 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_MaxHole_STC2", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_MaxHold2 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_MinHole_STC4", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_MinHold4 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_MaxHole_STC4", "10", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_MaxHold4 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_Deviation2", "1", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_Deviation2 = atoi(str); + GetPrivateProfileString("Basic_Threshold", "K1DifferTest_Deviation4", "5", str, strIniFile); + g_stCfg_FT6X36_BasicThreshold.K1DifferTest_Deviation4 = atoi(str); +} + +void SetTestItem_FT6X36() +{ + + g_TestItemNum = 0; + + + if (g_stCfg_FT6X36_TestItem.FACTORY_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_FACTORY_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.PROJECT_CODE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_PROJECT_CODE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.FW_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_FW_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.IC_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_IC_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_ENTER_FACTORY_MODE; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + + + if (g_stCfg_FT6X36_TestItem.CHANNEL_NUM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_CHANNEL_NUM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.DIFFER_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_DIFFER_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.DIFFER_TEST2 == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_DIFFER_TEST2; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.CB_DEVIATION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_CB_DEVIATION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.FPC_SHORT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_FPC_SHORT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.FPC_OPEN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_FPC_OPEN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.DELTA_CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_DELTA_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.CHANNELS_DEVIATION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_CHANNELS_DEVIATION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.TWO_SIDES_DEVIATION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_TWO_SIDES_DEVIATION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.CHANNEL_SHORT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_CHANNEL_SHORT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.SREF_OPEN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_SREF_OPEN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.NOISE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_NOISE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.WEAK_SHORT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_WEAK_SHORT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.K1_DIFFER_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_K1_DIFFER_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.RESET_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_RESET_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + if (g_stCfg_FT6X36_TestItem.INT_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_INT_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT6X36_TestItem.TE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT6X36_TE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + +} + diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT6X36.h b/drivers/input/touchscreen/ft5435/lib/Config_FT6X36.h new file mode 100644 index 0000000000000..c8b274cf4de9d --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT6X36.h @@ -0,0 +1,190 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT6X36.h +* +* Author: Software Development Team, AE +* +* Created: 2015-10-08 +* +* Abstract: Set Config for FT6X36/FT3X07/FT6416/FT6426 +* +************************************************************************/ +#ifndef _CONFIG_FT6X36_H +#define _CONFIG_FT6X36_H + +#include "test_lib.h" + +/*----------------------------------------------- +FT6X36 +------------------------------------------------*/ +struct stCfg_FT6X36_TestItem +{ + bool FW_VERSION_TEST; + bool FACTORY_ID_TEST; + bool PROJECT_CODE_TEST; + bool IC_VERSION_TEST; + bool RAWDATA_TEST; + bool CHANNEL_NUM_TEST; + bool CHANNEL_SHORT_TEST; + bool INT_PIN_TEST; + bool RESET_PIN_TEST; + bool NOISE_TEST; + bool CB_TEST; + bool DELTA_CB_TEST; + bool CHANNELS_DEVIATION_TEST; + bool TWO_SIDES_DEVIATION_TEST; + bool FPC_SHORT_TEST; + bool FPC_OPEN_TEST; + bool SREF_OPEN_TEST; + bool TE_TEST; + bool CB_DEVIATION_TEST; + bool DIFFER_TEST; + bool WEAK_SHORT_TEST; + bool DIFFER_TEST2; + bool K1_DIFFER_TEST; +}; + +struct stCfg_FT6X36_BasicThreshold +{ + BYTE FW_VER_VALUE; + BYTE Factory_ID_Number; + char Project_Code[32]; + BYTE IC_Version; + int RawDataTest_Min; + int RawDataTest_Max; + BYTE ChannelNumTest_ChannelNum; + BYTE ChannelNumTest_KeyNum; + int ChannelShortTest_K1; + int ChannelShortTest_K2; + int ChannelShortTest_CB; + BYTE ResetPinTest_RegAddr; + BYTE IntPinTest_RegAddr; + int WeakShortThreshold; + int NoiseTest_Max; + int NoiseTest_Frames; + int NoiseTest_Time; + BYTE NoiseTest_SampeMode; + BYTE NoiseTest_NoiseMode; + BYTE NoiseTest_ShowTip; + int FPCShort_CB_Min; + int FPCShort_CB_Max; + int FPCShort_RawData_Min; + int FPCShort_RawData_Max; + int FPCOpen_CB_Min; + int FPCOpen_CB_Max; + int FPCOpen_RawData_Min; + int FPCOpen_RawData_Max; + int SREFOpen_Hole_Base1; + int SREFOpen_Hole_Base2; + int SREFOpen_Hole; + int CBDeviationTest_Hole; + int Differ_Ave_Hole; + int Differ_Max_Hole; + int CbTest_Min; + int CbTest_Max; + int DeltaCbTest_Base; + int DeltaCbTest_Differ_Max; + bool DeltaCbTest_Include_Key_Test; + int DeltaCbTest_Key_Differ_Max; + int DeltaCbTest_Deviation_S1; + int DeltaCbTest_Deviation_S2; + int DeltaCbTest_Deviation_S3; + int DeltaCbTest_Deviation_S4; + int DeltaCbTest_Deviation_S5; + int DeltaCbTest_Deviation_S6; + bool DeltaCbTest_Set_Critical; + int DeltaCbTest_Critical_S1; + int DeltaCbTest_Critical_S2; + int DeltaCbTest_Critical_S3; + int DeltaCbTest_Critical_S4; + int DeltaCbTest_Critical_S5; + int DeltaCbTest_Critical_S6; + + int ChannelsDeviationTest_Deviation_S1; + int ChannelsDeviationTest_Deviation_S2; + int ChannelsDeviationTest_Deviation_S3; + int ChannelsDeviationTest_Deviation_S4; + int ChannelsDeviationTest_Deviation_S5; + int ChannelsDeviationTest_Deviation_S6; + bool ChannelsDeviationTest_Set_Critical; + int ChannelsDeviationTest_Critical_S1; + int ChannelsDeviationTest_Critical_S2; + int ChannelsDeviationTest_Critical_S3; + int ChannelsDeviationTest_Critical_S4; + int ChannelsDeviationTest_Critical_S5; + int ChannelsDeviationTest_Critical_S6; + + int TwoSidesDeviationTest_Deviation_S1; + int TwoSidesDeviationTest_Deviation_S2; + int TwoSidesDeviationTest_Deviation_S3; + int TwoSidesDeviationTest_Deviation_S4; + int TwoSidesDeviationTest_Deviation_S5; + int TwoSidesDeviationTest_Deviation_S6; + bool TwoSidesDeviationTest_Set_Critical; + int TwoSidesDeviationTest_Critical_S1; + int TwoSidesDeviationTest_Critical_S2; + int TwoSidesDeviationTest_Critical_S3; + int TwoSidesDeviationTest_Critical_S4; + int TwoSidesDeviationTest_Critical_S5; + int TwoSidesDeviationTest_Critical_S6; + + int DifferTest2_Data_H_Min; + int DifferTest2_Data_H_Max; + int DifferTest2_Data_M_Min; + int DifferTest2_Data_M_Max; + int DifferTest2_Data_L_Min; + int DifferTest2_Data_L_Max; + bool bDifferTest2_Data_H; + bool bDifferTest2_Data_M; + bool bDifferTest2_Data_L; + int K1DifferTest_StartK1; + int K1DifferTest_EndK1; + int K1DifferTest_MinHold2; + int K1DifferTest_MaxHold2; + int K1DifferTest_MinHold4; + int K1DifferTest_MaxHold4; + int K1DifferTest_Deviation2; + int K1DifferTest_Deviation4; +}; + +enum enumTestItem_FT6X36 +{ + Code_FT6X36_ENTER_FACTORY_MODE, + Code_FT6X36_DOWNLOAD, + Code_FT6X36_UPGRADE, + Code_FT6X36_FACTORY_ID_TEST, + Code_FT6X36_PROJECT_CODE_TEST, + Code_FT6X36_FW_VERSION_TEST, + Code_FT6X36_IC_VERSION_TEST, + Code_FT6X36_RAWDATA_TEST, + Code_FT6X36_CHANNEL_NUM_TEST, + Code_FT6X36_CHANNEL_SHORT_TEST, + Code_FT6X36_INT_PIN_TEST, + Code_FT6X36_RESET_PIN_TEST, + Code_FT6X36_NOISE_TEST, + Code_FT6X36_CB_TEST, + Code_FT6X36_DELTA_CB_TEST, + Code_FT6X36_CHANNELS_DEVIATION_TEST, + Code_FT6X36_TWO_SIDES_DEVIATION_TEST, + Code_FT6X36_FPC_SHORT_TEST, + Code_FT6X36_FPC_OPEN_TEST, + Code_FT6X36_SREF_OPEN_TEST, + Code_FT6X36_TE_TEST, + Code_FT6X36_CB_DEVIATION_TEST, + Code_FT6X36_WRITE_CONFIG, + Code_FT6X36_DIFFER_TEST, + Code_FT6X36_WEAK_SHORT_TEST, + Code_FT6X36_DIFFER_TEST2, + Code_FT6X36_K1_DIFFER_TEST, +}; + +extern struct stCfg_FT6X36_TestItem g_stCfg_FT6X36_TestItem; +extern struct stCfg_FT6X36_BasicThreshold g_stCfg_FT6X36_BasicThreshold; + +void OnInit_FT6X36_TestItem(char *strIniFile); +void OnInit_FT6X36_BasicThreshold(char *strIniFile); +void SetTestItem_FT6X36(void); + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT8606.c b/drivers/input/touchscreen/ft5435/lib/Config_FT8606.c new file mode 100644 index 0000000000000..b74a41dce4b39 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT8606.c @@ -0,0 +1,266 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT8606.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Config for FT8606 +* +************************************************************************/ +#include +#include +#include "Config_FT8606.h" +#include "ini.h" +#include "Global.h" + +struct stCfg_FT8606_TestItem g_stCfg_FT8606_TestItem; +struct stCfg_FT8606_BasicThreshold g_stCfg_FT8606_BasicThreshold; + +void OnInit_FT8606_BasicThreshold(char *strIniFile) +{ + char str[512]; + + GetPrivateProfileString("Basic_Threshold", "FW_VER_VALUE", "0", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.FW_VER_VALUE = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Factory_ID_Number", "255", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.Factory_ID_Number = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "Project_Code", " ", str, strIniFile); + + sprintf(g_stCfg_FT8606_BasicThreshold.Project_Code, "%s", str); + + + GetPrivateProfileString("Basic_Threshold", "IC_Version", "3", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.IC_Version = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Min", "5000", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.RawDataTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Max", "11000", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.RawDataTest_Max = atoi(str); + + + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_ChannelX", "15", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelXNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_ChannelY", "24", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelYNum = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ChannelNumTest_KeyNum", "0", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.ChannelNumTest_KeyNum = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ResetPinTest_RegAddr", "136", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.ResetPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "IntPinTest_RegAddr", "175", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.IntPinTest_RegAddr = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Coefficient", "50", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.NoiseTest_Coefficient = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Frames", "32", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.NoiseTest_Frames = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_Time", "1", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.NoiseTest_Time = atoi(str); + GetPrivateProfileString("Basic_Threshold", "NoiseTest_SampeMode", "0", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.NoiseTest_SampeMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_NoiseMode", "0", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.NoiseTest_NoiseMode = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "NoiseTest_ShowTip", "0", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.NoiseTest_ShowTip = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "CBTest_Min", "3", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.CbTest_Min = atoi(str); + GetPrivateProfileString("Basic_Threshold", "CBTest_Max", "100", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.CbTest_Max = atoi(str); + + GetPrivateProfileString("Basic_Threshold", "ShortCircuit_CBMax", "120", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.ShortTest_Max = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ShortCircuit_K2Value", "150", str, strIniFile); + g_stCfg_FT8606_BasicThreshold.ShortTest_K2Value = atoi(str); + + + +} + +void OnInit_FT8606_TestItem(char *strIniFile) +{ + char str[512]; + + + + + GetPrivateProfileString("TestItem", "FW_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.FW_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "FACTORY_ID_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.FACTORY_ID_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "PROJECT_CODE_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.PROJECT_CODE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "IC_VERSION_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.IC_VERSION_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RAWDATA_TEST", "1", str, strIniFile); + g_stCfg_FT8606_TestItem.RAWDATA_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CHANNEL_NUM_TEST", "1", str, strIniFile); + g_stCfg_FT8606_TestItem.CHANNEL_NUM_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "INT_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.INT_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "RESET_PIN_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.RESET_PIN_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "NOISE_TEST", "0", str, strIniFile); + g_stCfg_FT8606_TestItem.NOISE_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "CB_TEST", "1", str, strIniFile); + g_stCfg_FT8606_TestItem.CB_TEST = atoi(str); + + + GetPrivateProfileString("TestItem", "SHORT_CIRCUIT_TEST", "1", str, strIniFile); + g_stCfg_FT8606_TestItem.SHORT_TEST = atoi(str); + + + +} + +void SetTestItem_FT8606() +{ + g_TestItemNum = 0; + + + if (g_stCfg_FT8606_TestItem.FACTORY_ID_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_FACTORY_ID_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.PROJECT_CODE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_PROJECT_CODE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.FW_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_FW_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.IC_VERSION_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_IC_VERSION_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_ENTER_FACTORY_MODE; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + + + if (g_stCfg_FT8606_TestItem.CHANNEL_NUM_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_CHANNEL_NUM_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.SHORT_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_SHORT_CIRCUIT_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.CB_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_CB_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.NOISE_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_NOISE_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.RAWDATA_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_RAWDATA_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + + if (g_stCfg_FT8606_TestItem.RESET_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_RESET_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + + if (g_stCfg_FT8606_TestItem.INT_PIN_TEST == 1) + { + g_stTestItem[0][g_TestItemNum].ItemCode = Code_FT8606_INT_PIN_TEST; + + g_stTestItem[0][g_TestItemNum].TestNum = g_TestItemNum; + g_stTestItem[0][g_TestItemNum].TestResult = RESULT_NULL; + g_TestItemNum++; + } + +} + diff --git a/drivers/input/touchscreen/ft5435/lib/Config_FT8606.h b/drivers/input/touchscreen/ft5435/lib/Config_FT8606.h new file mode 100644 index 0000000000000..5ffafa6460ceb --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Config_FT8606.h @@ -0,0 +1,94 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Config_FT8606.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Config for FT8606 +* +************************************************************************/ +#ifndef _CONFIG_FT8606_H +#define _CONFIG_FT8606_H + +#include "test_lib.h" + + +struct stCfg_FT8606_TestItem +{ + bool FW_VERSION_TEST; + bool FACTORY_ID_TEST; + bool PROJECT_CODE_TEST; + bool IC_VERSION_TEST; + bool RAWDATA_TEST; + bool CHANNEL_NUM_TEST; + bool INT_PIN_TEST; + bool RESET_PIN_TEST; + bool NOISE_TEST; + bool CB_TEST; + bool SHORT_TEST; + +}; +struct stCfg_FT8606_BasicThreshold +{ + BYTE FW_VER_VALUE; + BYTE Factory_ID_Number; + char Project_Code[32]; + BYTE IC_Version; + int RawDataTest_Min; + int RawDataTest_Max; + BYTE ChannelNumTest_ChannelXNum; + BYTE ChannelNumTest_ChannelYNum; + BYTE ChannelNumTest_KeyNum; + BYTE ResetPinTest_RegAddr; + BYTE IntPinTest_RegAddr; + int NoiseTest_Coefficient; + int NoiseTest_Frames; + int NoiseTest_Time; + BYTE NoiseTest_SampeMode; + BYTE NoiseTest_NoiseMode; + BYTE NoiseTest_ShowTip; + int CbTest_Min; + int CbTest_Max; + int ShortTest_Max; + int ShortTest_K2Value; + +}; + + +enum enumTestItem_FT8606 +{ + Code_FT8606_ENTER_FACTORY_MODE, + Code_FT8606_DOWNLOAD, + Code_FT8606_UPGRADE, + Code_FT8606_FACTORY_ID_TEST, + Code_FT8606_PROJECT_CODE_TEST, + Code_FT8606_FW_VERSION_TEST, + Code_FT8606_IC_VERSION_TEST, + Code_FT8606_RAWDATA_TEST, + Code_FT8606_CHANNEL_NUM_TEST, + + Code_FT8606_INT_PIN_TEST, + Code_FT8606_RESET_PIN_TEST, + Code_FT8606_NOISE_TEST, + Code_FT8606_CB_TEST, + + Code_FT8606_WRITE_CONFIG, + + Code_FT8606_SHORT_CIRCUIT_TEST, +}; + + + + +extern struct stCfg_FT8606_TestItem g_stCfg_FT8606_TestItem; +extern struct stCfg_FT8606_BasicThreshold g_stCfg_FT8606_BasicThreshold; + +void OnInit_FT8606_TestItem(char *strIniFile); +void OnInit_FT8606_BasicThreshold(char *strIniFile); +void SetTestItem_FT8606(void); + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/DetailThreshold.c b/drivers/input/touchscreen/ft5435/lib/DetailThreshold.c new file mode 100644 index 0000000000000..ae29e744909ae --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/DetailThreshold.c @@ -0,0 +1,1208 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: DetailThreshold.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Detail Threshold for all IC +* +************************************************************************/ +#include +#include + +#include "ini.h" +#include "DetailThreshold.h" +#include "test_lib.h" +#include "Global.h" + +struct stCfg_MCap_DetailThreshold g_stCfg_MCap_DetailThreshold; +struct stCfg_SCap_DetailThreshold g_stCfg_SCap_DetailThreshold; + + +void set_max_channel_num(void) +{ + switch(g_ScreenSetParam.iSelectedIC>>4) + { + case IC_FT5822>>4: + g_ScreenSetParam.iUsedMaxTxNum = TX_NUM_MAX; + g_ScreenSetParam.iUsedMaxRxNum = RX_NUM_MAX; + break; + default: + g_ScreenSetParam.iUsedMaxTxNum = 30; + g_ScreenSetParam.iUsedMaxRxNum = 30; + break; + } + +} +void OnInit_SCap_DetailThreshold(char *strIniFile) +{ + OnGetTestItemParam("RawDataTest_Max", strIniFile, 12500); + memcpy(g_stCfg_SCap_DetailThreshold.RawDataTest_Max, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("RawDataTest_Min", strIniFile, 16500); + memcpy(g_stCfg_SCap_DetailThreshold.RawDataTest_Min, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("CiTest_Max", strIniFile, 5); + memcpy(g_stCfg_SCap_DetailThreshold.CiTest_Max, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("CiTest_Min", strIniFile, 250); + memcpy(g_stCfg_SCap_DetailThreshold.CiTest_Min, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("DeltaCiTest_Base", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.DeltaCiTest_Base, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("DeltaCiTest_AnotherBase1", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.DeltaCiTest_AnotherBase1, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("DeltaCiTest_AnotherBase2", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.DeltaCiTest_AnotherBase2, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + OnGetTestItemParam("NoiseTest_Max", strIniFile, 20); + memcpy(g_stCfg_SCap_DetailThreshold.NoiseTest_Max, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + OnGetTestItemParam("CiDeviation_Base", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.CiDeviationTest_Base, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + OnGetTestItemParam("DeltaCxTest_Sort", strIniFile, 1); + memcpy(g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + OnGetTestItemParam("DeltaCxTest_Area", strIniFile, 1); + memcpy(g_stCfg_SCap_DetailThreshold.DeltaCxTest_Area, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + + OnGetTestItemParam("CbTest_Max", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.CbTest_Max, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + OnGetTestItemParam("CbTest_Min", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.CbTest_Min, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + OnGetTestItemParam("DeltaCbTest_Base", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.DeltaCbTest_Base, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + OnGetTestItemParam("DifferTest_Base", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.DifferTest_Base, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + OnGetTestItemParam("CBDeviation_Base", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.CBDeviationTest_Base, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); + + + OnGetTestItemParam("K1DifferTest_Base", strIniFile, 0); + memcpy(g_stCfg_SCap_DetailThreshold.K1DifferTest_Base, g_stCfg_SCap_DetailThreshold.TempData, MAX_CHANNEL_NUM*sizeof(int)); +} + +void OnGetTestItemParam(char *strItemName, char *strIniFile, int iDefautValue) +{ + + char strValue[800]; + char str_tmp[128]; + int iValue = 0; + int dividerPos = 0; + int index = 0; + int i = 0, j = 0, k = 0; + memset(g_stCfg_SCap_DetailThreshold.TempData, 0, sizeof(g_stCfg_SCap_DetailThreshold.TempData)); + sprintf(str_tmp, "%d", iDefautValue); + GetPrivateProfileString("Basic_Threshold", strItemName, str_tmp, strValue, strIniFile); + iValue = atoi(strValue); + for (i = 0; i < MAX_CHANNEL_NUM; i++) + { + g_stCfg_SCap_DetailThreshold.TempData[i] = iValue; + } + + dividerPos = GetPrivateProfileString("SpecialSet", strItemName, "", strValue, strIniFile); + + if (dividerPos > 0) + { + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_SCap_DetailThreshold.TempData[k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + + + + + + } +} +void OnInit_MCap_DetailThreshold(char *strIniFile) +{ + set_max_channel_num(); + + OnInit_InvalidNode(strIniFile); + OnInit_DThreshold_RawDataTest(strIniFile); + OnInit_DThreshold_SCapRawDataTest(strIniFile); + OnInit_DThreshold_SCapCbTest(strIniFile); + + OnInit_DThreshold_ForceTouch_SCapRawDataTest(strIniFile); + OnInit_DThreshold_ForceTouch_SCapCbTest(strIniFile); + + OnInit_DThreshold_RxLinearityTest(strIniFile); + OnInit_DThreshold_TxLinearityTest(strIniFile); +} +void OnInit_InvalidNode(char *strIniFile) +{ + + char str[MAX_PATH] = {0}, strTemp[MAX_PATH] = {0}; + int i = 0, j = 0; + + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + sprintf(strTemp, "InvalidNode[%d][%d]", (i+1), (j+1)); + + GetPrivateProfileString("INVALID_NODE", strTemp, "1", str, strIniFile); + if (atoi(str) == 0) + { + g_stCfg_MCap_DetailThreshold.InvalidNode[i][j] = 0; + } + else if (atoi(str) == 2) + { + g_stCfg_MCap_DetailThreshold.InvalidNode[i][j] = 2; + } + else + g_stCfg_MCap_DetailThreshold.InvalidNode[i][j] = 1; + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + sprintf(strTemp, "InvalidNodeS[%d][%d]", (i+1), (j+1)); + GetPrivateProfileString("INVALID_NODES", strTemp, "1", str, strIniFile); + if (atoi(str) == 0) + { + g_stCfg_MCap_DetailThreshold.InvalidNode_SC[i][j] = 0; + } + else if (atoi(str) == 2) + { + g_stCfg_MCap_DetailThreshold.InvalidNode_SC[i][j] = 2; + } + else + g_stCfg_MCap_DetailThreshold.InvalidNode_SC[i][j] = 1; + } + + } +} + +void OnInit_DThreshold_RawDataTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue, MinValue; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Max", "10000", str, strIniFile); + MaxValue = atoi(str); + + + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Max[i][j] = MaxValue; + } + } + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "RawData_Max_Tx%d", (i + 1)); + + dividerPos = GetPrivateProfileString("SpecialSet", str, "111", strTemp, strIniFile); + + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + + } + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Min", "7000", str, strIniFile); + MinValue = atoi(str); + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Min[i][j] = MinValue; + } + } + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "RawData_Min_Tx%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Max", "15000", str, strIniFile); + MaxValue = atoi(str); + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Low_Max[i][j] = MaxValue; + } + } + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "RawData_Max_Low_Tx%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Low_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_Low_Min", "3000", str, strIniFile); + MinValue = atoi(str); + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Low_Min[i][j] = MinValue; + } + } + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "RawData_Min_Low_Tx%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_Low_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Max", "15000", str, strIniFile); + MaxValue = atoi(str); + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[i][j] = MaxValue; + } + } + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "RawData_Max_High_Tx%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + GetPrivateProfileString("Basic_Threshold", "RawDataTest_High_Min", "3000", str, strIniFile); + MinValue = atoi(str); + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[i][j] = MinValue; + } + } + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "RawData_Min_High_Tx%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } +} +void OnInit_DThreshold_SCapRawDataTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue, MinValue; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Min", "150", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_OFF_Max", "1000", str, strIniFile); + MaxValue = atoi(str); + + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapRawData_OFF_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapRawData_OFF_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Min", "150", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapRawDataTest_ON_Max", "1000", str, strIniFile); + MaxValue = atoi(str); + + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapRawData_ON_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapRawData_ON_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } +} +void OnInit_DThreshold_SCapCbTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue, MinValue; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Min", "0", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_ON_Max", "240", str, strIniFile); + MaxValue = atoi(str); + + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapCB_ON_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapCB_ON_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Min", "0", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "SCapCbTest_OFF_Max", "240", str, strIniFile); + MaxValue = atoi(str); + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapCB_OFF_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ScapCB_OFF_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + +} + +void OnInit_DThreshold_RxLinearityTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue = 0; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + GetPrivateProfileString("Basic_Threshold", "RxLinearityTest_Max", "50", str, strIniFile); + MaxValue = atoi(str); + + + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.RxLinearityTest_Max[i][j] = MaxValue; + } + } + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "Rx_Linearity_Max_Tx%d", (i + 1)); + + dividerPos = GetPrivateProfileString("SpecialSet", str, "111", strTemp, strIniFile); + + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.RxLinearityTest_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + + } +} + +void OnInit_DThreshold_TxLinearityTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue = 0; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + GetPrivateProfileString("Basic_Threshold", "TxLinearityTest_Max", "50", str, strIniFile); + MaxValue = atoi(str); + + + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.TxLinearityTest_Max[i][j] = MaxValue; + } + } + + for (i = 0; i < g_ScreenSetParam.iUsedMaxTxNum; i++) + { + sprintf(str, "Tx_Linearity_Max_Tx%d", (i + 1)); + + dividerPos = GetPrivateProfileString("SpecialSet", str, "111", strTemp, strIniFile); + + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.TxLinearityTest_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + + } +} + +void OnInit_DThreshold_ForceTouch_SCapRawDataTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue, MinValue; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_OFF_Min", "150", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_OFF_Max", "1000", str, strIniFile); + MaxValue = atoi(str); + + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapRawData_OFF_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapRawData_OFF_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_ON_Min", "150", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapRawDataTest_ON_Max", "1000", str, strIniFile); + MaxValue = atoi(str); + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapRawData_ON_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapRawData_ON_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + +} + +void OnInit_DThreshold_ForceTouch_SCapCbTest(char *strIniFile) +{ + char str[128], strTemp[MAX_PATH], strValue[MAX_PATH]; + int MaxValue, MinValue; + int dividerPos = 0; + char str_tmp[128]; + int index = 0; + int k = 0, i = 0, j = 0; + + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_ON_Min", "0", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_ON_Max", "240", str, strIniFile); + MaxValue = atoi(str); + + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapCB_ON_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapCB_ON_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; printk("%s\r\n", strTemp); + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_OFF_Min", "0", str, strIniFile); + MinValue = atoi(str); + GetPrivateProfileString("Basic_Threshold", "ForceTouch_SCapCbTest_OFF_Max", "240", str, strIniFile); + MaxValue = atoi(str); + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Max[i][j] = MaxValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapCB_OFF_Max_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Max[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + + for (i = 0; i < 2; i++) + { + for (j = 0; j < g_ScreenSetParam.iUsedMaxRxNum; j++) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Min[i][j] = MinValue; + } + } + for (i = 0; i < 2; i++) + { + sprintf(str, "ForceTouch_ScapCB_OFF_Min_%d", (i + 1)); + dividerPos = GetPrivateProfileString("SpecialSet", str, "NULL", strTemp, strIniFile); + sprintf(strValue, "%s", strTemp); + if (0 == dividerPos) continue; + index = 0; + k = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + for (j = 0; j < dividerPos; j++) + { + if (',' == strValue[j]) + { + g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Min[i][k] = (short)(atoi(str_tmp)); + index = 0; + memset(str_tmp, 0x00, sizeof(str_tmp)); + k++; + } + else + { + if (' ' == strValue[j]) + continue; + str_tmp[index] = strValue[j]; + index++; + } + } + } + +} + diff --git a/drivers/input/touchscreen/ft5435/lib/DetailThreshold.h b/drivers/input/touchscreen/ft5435/lib/DetailThreshold.h new file mode 100644 index 0000000000000..da05a5c3aa6ba --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/DetailThreshold.h @@ -0,0 +1,120 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: DetailThreshold.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: Set Detail Threshold for all IC +* +************************************************************************/ + +#ifndef _DETAIL_THRESHOLD_H +#define _DETAIL_THRESHOLD_H + +#define TX_NUM_MAX 50 +#define RX_NUM_MAX 50 +#define MAX_PATH 256 + +#define BUFFER_LENGTH 512 +#define MAX_TEST_ITEM 100 +#define MAX_GRAPH_ITEM 20 +#define MAX_CHANNEL_NUM 144 + +#define FORCETOUCH_ROW 2 + +struct stCfg_MCap_DetailThreshold +{ + unsigned char InvalidNode[TX_NUM_MAX][RX_NUM_MAX]; + unsigned char InvalidNode_SC[TX_NUM_MAX][RX_NUM_MAX]; + + int RawDataTest_Min[TX_NUM_MAX][RX_NUM_MAX]; + int RawDataTest_Max[TX_NUM_MAX][RX_NUM_MAX]; + int RawDataTest_Low_Min[TX_NUM_MAX][RX_NUM_MAX]; + int RawDataTest_Low_Max[TX_NUM_MAX][RX_NUM_MAX]; + int RawDataTest_High_Min[TX_NUM_MAX][RX_NUM_MAX]; + int RawDataTest_High_Max[TX_NUM_MAX][RX_NUM_MAX]; + + + + + int RxLinearityTest_Max[TX_NUM_MAX][RX_NUM_MAX]; + int TxLinearityTest_Max[TX_NUM_MAX][RX_NUM_MAX]; + + + + + int SCapRawDataTest_ON_Max[TX_NUM_MAX][RX_NUM_MAX]; + int SCapRawDataTest_ON_Min[TX_NUM_MAX][RX_NUM_MAX]; + int SCapRawDataTest_OFF_Max[TX_NUM_MAX][RX_NUM_MAX]; + int SCapRawDataTest_OFF_Min[TX_NUM_MAX][RX_NUM_MAX]; + short SCapCbTest_ON_Max[TX_NUM_MAX][RX_NUM_MAX]; + short SCapCbTest_ON_Min[TX_NUM_MAX][RX_NUM_MAX]; + short SCapCbTest_OFF_Max[TX_NUM_MAX][RX_NUM_MAX]; + short SCapCbTest_OFF_Min[TX_NUM_MAX][RX_NUM_MAX]; + + int ForceTouch_SCapRawDataTest_ON_Max[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapRawDataTest_ON_Min[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapRawDataTest_OFF_Max[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapRawDataTest_OFF_Min[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapCbTest_ON_Max[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapCbTest_ON_Min[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapCbTest_OFF_Max[FORCETOUCH_ROW][RX_NUM_MAX]; + int ForceTouch_SCapCbTest_OFF_Min[FORCETOUCH_ROW][RX_NUM_MAX]; + + + + int NoistTest_Coefficient[TX_NUM_MAX][RX_NUM_MAX]; + + +}; + +struct stCfg_SCap_DetailThreshold +{ + int TempData[MAX_CHANNEL_NUM]; + int RawDataTest_Max[MAX_CHANNEL_NUM]; + int RawDataTest_Min[MAX_CHANNEL_NUM]; + int CiTest_Max[MAX_CHANNEL_NUM]; + int CiTest_Min[MAX_CHANNEL_NUM]; + int DeltaCiTest_Base[MAX_CHANNEL_NUM]; + int DeltaCiTest_AnotherBase1[MAX_CHANNEL_NUM]; + int DeltaCiTest_AnotherBase2[MAX_CHANNEL_NUM]; + int CiDeviationTest_Base[MAX_CHANNEL_NUM]; + + int NoiseTest_Max[MAX_CHANNEL_NUM]; + int DeltaCxTest_Sort[MAX_CHANNEL_NUM]; + int DeltaCxTest_Area[MAX_CHANNEL_NUM]; + + int CbTest_Max[MAX_CHANNEL_NUM]; + int CbTest_Min[MAX_CHANNEL_NUM]; + int DeltaCbTest_Base[MAX_CHANNEL_NUM]; + int DifferTest_Base[MAX_CHANNEL_NUM]; + int CBDeviationTest_Base[MAX_CHANNEL_NUM]; + int K1DifferTest_Base[MAX_CHANNEL_NUM]; + +}; + + + + +void OnInit_MCap_DetailThreshold(char *strIniFile); +void OnInit_SCap_DetailThreshold(char *strIniFile); + +void OnInit_InvalidNode(char *strIniFile); +void OnGetTestItemParam(char *strItemName, char *strIniFile, int iDefautValue); +void OnInit_DThreshold_RawDataTest(char *strIniFile); +void OnInit_DThreshold_SCapRawDataTest(char *strIniFile); +void OnInit_DThreshold_SCapCbTest(char *strIniFile); + +void OnInit_DThreshold_ForceTouch_SCapRawDataTest(char *strIniFile); +void OnInit_DThreshold_ForceTouch_SCapCbTest(char *strIniFile); + +void OnInit_DThreshold_RxLinearityTest(char *strIniFile); +void OnInit_DThreshold_TxLinearityTest(char *strIniFile); + +void set_max_channel_num(void); + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Global.c b/drivers/input/touchscreen/ft5435/lib/Global.c new file mode 100644 index 0000000000000..647a44160b7f6 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Global.c @@ -0,0 +1,346 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Global.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: global function for test +* +************************************************************************/ + +#include +#include +#include + +#include + +#include "ini.h" +#include "Global.h" + +#include "test_lib.h" + +#define DEVIDE_MODE_ADDR 0x00 + +struct StruScreenSeting g_ScreenSetParam; +struct stTestItem g_stTestItem[1][MAX_TEST_ITEM]; + +int g_TestItemNum = 0; +char g_strIcName[20] = {0}; + +int GetPrivateProfileString(char *section, char *ItemName, char *defaultvalue, char *returnValue, char *IniFile){ + char value[512] = {0}; + int len = 0; + + if (NULL == returnValue) + { + printk("[FTS] returnValue==NULL in function %s.", __func__); + return 0; + } + + if (ini_get_key(IniFile, section, ItemName, value) < 0) + { + if (NULL != defaultvalue) memcpy(value, defaultvalue, strlen(defaultvalue)); + sprintf(returnValue, "%s", value); + return 0; + } else { + len = sprintf(returnValue, "%s", value); + } + + return len; +} + +void focal_msleep(int ms) +{ + msleep(ms); +} +void SysDelay(int ms) +{ + msleep(ms); +} +int focal_abs(int value) +{ + if (value < 0) + value = 0 - value; + + return value; +} + +unsigned char get_ic_code(char *strIcName) +{ + + if (strncmp(strIcName, "FT5X36", 6) == 0) return IC_FT5X36; + if (strncmp(strIcName, "FT5X36i", 7) == 0) return IC_FT5X36i; + if (strncmp(strIcName, "FT3X16", 6) == 0) return IC_FT3X16; + if (strncmp(strIcName, "FT3X26", 6) == 0) return IC_FT3X26; + + if (strncmp(strIcName, "FT5X46", 6) == 0) return IC_FT5X46; + if (strncmp(strIcName, "FT5X46i", 7) == 0) return IC_FT5X46i; + if (strncmp(strIcName, "FT5526", 6) == 0) return IC_FT5526; + if (strncmp(strIcName, "FT3X17", 6) == 0) return IC_FT3X17; + if (strncmp(strIcName, "FT5436", 6) == 0) return IC_FT5436; + if (strncmp(strIcName, "FT3X27", 6) == 0) return IC_FT3X27; + if (strncmp(strIcName, "FT5526i", 7) == 0) return IC_FT5526I; + if (strncmp(strIcName, "FT5416", 6) == 0) return IC_FT5416; + if (strncmp(strIcName, "FT5426", 6) == 0) return IC_FT5426; + if (strncmp(strIcName, "FT5435", 6) == 0) return IC_FT5435; + + if (strncmp(strIcName, "FT6X06", 6) == 0) return IC_FT6X06; + if (strncmp(strIcName, "FT3X06", 6) == 0) return IC_FT3X06; + + if (strncmp(strIcName, "FT6X36", 6) == 0) return IC_FT6X36; + if (strncmp(strIcName, "FT3X07", 6) == 0) return IC_FT3X07; + if (strncmp(strIcName, "FT6416", 6) == 0) return IC_FT6416; + if (strncmp(strIcName, "FT6336G/U", 9) == 0) return IC_FT6426; + + if (strncmp(strIcName, "FT5X16", 6) == 0) return IC_FT5X16; + if (strncmp(strIcName, "FT5X12", 6) == 0) return IC_FT5X12; + + if (strncmp(strIcName, "FT5506", 6) == 0) return IC_FT5506; + if (strncmp(strIcName, "FT5606", 6) == 0) return IC_FT5606; + if (strncmp(strIcName, "FT5816", 6) == 0) return IC_FT5816; + + if (strncmp(strIcName, "FT5822", 6) == 0) return IC_FT5822; + if (strncmp(strIcName, "FT5626", 6) == 0) return IC_FT5626; + if (strncmp(strIcName, "FT5726", 6) == 0) return IC_FT5726; + if (strncmp(strIcName, "FT5826B", 7) == 0) return IC_FT5826B; + if (strncmp(strIcName, "FT5826S", 7) == 0) return IC_FT5826S; + + if (strncmp(strIcName, "FT5306", 6) == 0) return IC_FT5306; + if (strncmp(strIcName, "FT5406", 6) == 0) return IC_FT5406; + + if (strncmp(strIcName, "FT8606", 6) == 0) return IC_FT8606; + + + if (strncmp(strIcName, "FT8606", 6) == 0) return IC_FT8606; + + if (strncmp(strIcName, "FT3C47U", 7) == 0) return IC_FT3C47U; + + return 0xff; +} + + +void get_ic_name(unsigned char ucIcCode, char *strIcName) +{ + if (NULL == strIcName)return; + + sprintf(strIcName, "%s", "NA");/*if can't find IC , set 'NA'*/ + + if (ucIcCode == IC_FT5X36)sprintf(strIcName, "%s", "FT5X36"); + if (ucIcCode == IC_FT5X36i)sprintf(strIcName, "%s", "FT5X36i"); + if (ucIcCode == IC_FT3X16)sprintf(strIcName, "%s", "FT3X16"); + if (ucIcCode == IC_FT3X26)sprintf(strIcName, "%s", "FT3X26"); + + if (ucIcCode == IC_FT5X46)sprintf(strIcName, "%s", "FT5X22"); + if (ucIcCode == IC_FT5X46) sprintf(strIcName, "%s", "FT5X46"); + if (ucIcCode == IC_FT5X46i) sprintf(strIcName, "%s", "FT5X46i"); + if (ucIcCode == IC_FT5526) sprintf(strIcName, "%s", "FT5526"); + if (ucIcCode == IC_FT3X17) sprintf(strIcName, "%s", "FT3X17"); + if (ucIcCode == IC_FT5436) sprintf(strIcName, "%s", "FT5436"); + if (ucIcCode == IC_FT3X27) sprintf(strIcName, "%s", "FT3X27"); + if (ucIcCode == IC_FT5526I) sprintf(strIcName, "%s", "FT5526i"); + if (ucIcCode == IC_FT5416) sprintf(strIcName, "%s", "FT5416"); + if (ucIcCode == IC_FT5426) sprintf(strIcName, "%s", "FT5426"); + if (ucIcCode == IC_FT5435) sprintf(strIcName, "%s", "FT5435"); + + if (ucIcCode == IC_FT6X06)sprintf(strIcName, "%s", "FT6X06"); + if (ucIcCode == IC_FT3X06)sprintf(strIcName, "%s", "FT3X06"); + + if (ucIcCode == IC_FT6X36)sprintf(strIcName, "%s", "FT6X36"); + if (ucIcCode == IC_FT3X07)sprintf(strIcName, "%s", "FT3X07"); + if (ucIcCode == IC_FT6416)sprintf(strIcName, "%s", "FT6416"); + if (ucIcCode == IC_FT6426)sprintf(strIcName, "%s", "FT6336G/U"); + + if (ucIcCode == IC_FT5X16)sprintf(strIcName, "%s", "FT5X16"); + if (ucIcCode == IC_FT5X12)sprintf(strIcName, "%s", "FT5X12"); + + if (ucIcCode == IC_FT5506)sprintf(strIcName, "%s", "FT5506"); + if (ucIcCode == IC_FT5606)sprintf(strIcName, "%s", "FT5606"); + if (ucIcCode == IC_FT5816)sprintf(strIcName, "%s", "FT5816"); + + if (ucIcCode == IC_FT5822)sprintf(strIcName, "%s", "FT5822"); + if (ucIcCode == IC_FT5626)sprintf(strIcName, "%s", "FT5626"); + if (ucIcCode == IC_FT5726)sprintf(strIcName, "%s", "FT5726"); + if (ucIcCode == IC_FT5826B)sprintf(strIcName, "%s", "FT5826B"); + if (ucIcCode == IC_FT5826S)sprintf(strIcName, "%s", "FT5826S"); + + if (ucIcCode == IC_FT5306)sprintf(strIcName, "%s", "FT5306"); + if (ucIcCode == IC_FT5406)sprintf(strIcName, "%s", "FT5406"); + + if (ucIcCode == IC_FT8606)sprintf(strIcName, "%s", "FT8606"); + + + if (ucIcCode == IC_FT3C47U) sprintf(strIcName, "%s", "FT3C47U"); + + return ; +} +void OnInit_InterfaceCfg(char *strIniFile) +{ + char str[128]; + + + GetPrivateProfileString("Interface", "IC_Type", "FT5X36", str, strIniFile); + g_ScreenSetParam.iSelectedIC = get_ic_code(str); + + + GetPrivateProfileString("Interface", "Normalize_Type", 0, str, strIniFile); + g_ScreenSetParam.isNormalize = atoi(str); + +} +/************************************************************************ +* Name: ReadReg(Same function name as FT_MultipleTest) +* Brief: Read Register +* Input: RegAddr +* Output: RegData +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +int ReadReg(unsigned char RegAddr, unsigned char *RegData) +{ + int iRet; + + if (NULL == fts_i2c_read_test) + { + printk("[focal] %s fts_i2c_read_test == NULL \n", __func__); + return (ERROR_CODE_INVALID_COMMAND); + } + iRet = fts_i2c_read_test(&RegAddr, 1, RegData, 1); + + if (iRet >= 0) + return (ERROR_CODE_OK); + else + return (ERROR_CODE_COMM_ERROR); +} +/************************************************************************ +* Name: WriteReg(Same function name as FT_MultipleTest) +* Brief: Write Register +* Input: RegAddr, RegData +* Output: null +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +int WriteReg(unsigned char RegAddr, unsigned char RegData) +{ + int iRet; + unsigned char cmd[2] = {0}; + + if (NULL == fts_i2c_write_test) + { + printk("[focal] %s fts_i2c_write_test == NULL \n", __func__); + return (ERROR_CODE_INVALID_COMMAND); + } + + cmd[0] = RegAddr; + cmd[1] = RegData; + iRet = fts_i2c_write_test(cmd, 2); + + if (iRet >= 0) + return (ERROR_CODE_OK); + else + return (ERROR_CODE_COMM_ERROR); +} +/************************************************************************ +* Name: Comm_Base_IIC_IO(Same function name as FT_MultipleTest) +* Brief: Write/Read Data by IIC +* Input: pWriteBuffer, iBytesToWrite, iBytesToRead +* Output: pReadBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char Comm_Base_IIC_IO(unsigned char *pWriteBuffer, int iBytesToWrite, unsigned char *pReadBuffer, int iBytesToRead) +{ + int iRet; + + if (NULL == fts_i2c_read_test) + { + printk("[focal] %s fts_i2c_read_test == NULL \n", __func__); + return (ERROR_CODE_INVALID_COMMAND); + } + + iRet = fts_i2c_read_test(pWriteBuffer, iBytesToWrite, pReadBuffer, iBytesToRead); + + if (iRet >= 0) + return (ERROR_CODE_OK); + else + return (ERROR_CODE_COMM_ERROR); +} +/************************************************************************ +* Name: EnterWork(Same function name as FT_MultipleTest) +* Brief: Enter Work Mode +* Input: null +* Output: null +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char EnterWork(void) +{ + unsigned char RunState = 0; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState); + if (ReCode == ERROR_CODE_OK) + { + if (((RunState>>4)&0x07) == 0x00) + { + ReCode = ERROR_CODE_OK; + } + else + { + ReCode = WriteReg(DEVIDE_MODE_ADDR, 0); + if (ReCode == ERROR_CODE_OK) + { + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState); + if (ReCode == ERROR_CODE_OK) + { + if (((RunState>>4)&0x07) == 0x00) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + } + } + } + + return ReCode; + +} +/************************************************************************ +* Name: EnterFactory +* Brief: enter Fcatory Mode +* Input: null +* Output: null +* Return: Comm Code. Code = 0 is OK, else fail. +***********************************************************************/ +unsigned char EnterFactory(void) +{ + unsigned char RunState = 0; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState); + if (ReCode == ERROR_CODE_OK) + { + if (((RunState>>4)&0x07) == 0x04) + { + ReCode = ERROR_CODE_OK; + } + else + { + ReCode = WriteReg(DEVIDE_MODE_ADDR, 0x40); + if (ReCode == ERROR_CODE_OK) + { + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RunState); + if (ReCode == ERROR_CODE_OK) + { + if (((RunState>>4)&0x07) == 0x04) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + else + printk("EnterFactory read DEVIDE_MODE_ADDR error 3.\n"); + } + else + printk("EnterFactory write DEVIDE_MODE_ADDR error 2.\n"); + } + } + else + printk("EnterFactory read DEVIDE_MODE_ADDR error 1.\n"); + + return ReCode; +} + diff --git a/drivers/input/touchscreen/ft5435/lib/Global.h b/drivers/input/touchscreen/ft5435/lib/Global.h new file mode 100644 index 0000000000000..3c6f24241b030 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Global.h @@ -0,0 +1,158 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Global.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: global function for test +* +************************************************************************/ +#ifndef _GLOBAL_H +#define _GLOBAL_H + +#include +#include "DetailThreshold.h" + +/*----------------------------------------------------------- +Error Code for Comm +-----------------------------------------------------------*/ +#define ERROR_CODE_OK 0x00 +#define ERROR_CODE_CHECKSUM_ERROR 0x01 +#define ERROR_CODE_INVALID_COMMAND 0x02 +#define ERROR_CODE_INVALID_PARAM 0x03 +#define ERROR_CODE_IIC_WRITE_ERROR 0x04 +#define ERROR_CODE_IIC_READ_ERROR 0x05 +#define ERROR_CODE_WRITE_USB_ERROR 0x06 +#define ERROR_CODE_WAIT_RESPONSE_TIMEOUT 0x07 +#define ERROR_CODE_PACKET_RE_ERROR 0x08 +#define ERROR_CODE_NO_DEVICE 0x09 +#define ERROR_CODE_WAIT_WRITE_TIMEOUT 0x0a +#define ERROR_CODE_READ_USB_ERROR 0x0b +#define ERROR_CODE_COMM_ERROR 0x0c +#define ERROR_CODE_ALLOCATE_BUFFER_ERROR 0x0d +#define ERROR_CODE_DEVICE_OPENED 0x0e +#define ERROR_CODE_DEVICE_CLOSED 0x0f + +/*----------------------------------------------------------- +Test Status +-----------------------------------------------------------*/ +#define RESULT_NULL 0 +#define RESULT_PASS 1 +#define RESULT_NG 2 +#define RESULT_TESTING 3 +#define RESULT_TBD 4 +#define RESULT_REPLACE 5 +#define RESULT_CONNECTING 6 + +/*----------------------------------------------------------- +IC ¶ÔÓ¦Â룬ÿһ¿ÅIC´úÂëÊÇ8 bit£¬¸ßËÄλ´ú±íÏàͬϵÁУ¬µÍËÄλÇø±ð¾ßÌåIC +-----------------------------------------------------------*/ +enum IC_Type +{ + IC_FT5X36 = 0x10, + IC_FT5X36i = 0x11, + IC_FT3X16 = 0x12, + IC_FT3X26 = 0x13, + + IC_FT5X46 = 0x21, + IC_FT5X46i = 0x22, + IC_FT5526 = 0x23, + IC_FT3X17 = 0x24, + IC_FT5436 = 0x25, + IC_FT3X27 = 0x26, + IC_FT5526I = 0x27, + IC_FT5416 = 0x28, + IC_FT5426 = 0x29, + IC_FT5435 = 0x2A, + IC_FT6X06 = 0x30, + IC_FT3X06 = 0x31, + IC_FT6X36 = 0x40, + IC_FT3X07 = 0x41, + IC_FT6416 = 0x42, + IC_FT6426 = 0x43, + IC_FT5X16 = 0x50, + IC_FT5X12 = 0x51, + IC_FT5506 = 0x60, + IC_FT5606 = 0x61, + IC_FT5816 = 0x62, + IC_FT5822 = 0x70, + IC_FT5626 = 0x71, + IC_FT5726 = 0x72, + IC_FT5826B = 0x73, + IC_FT5826S = 0x74, + IC_FT5306 = 0x80, + IC_FT5406 = 0x81, + IC_FT8606 = 0x90, + IC_FT8716 = 0xA0, + IC_FT3C47U = 0xB0, +}; +#define MAX_IC_TYPE 32 + +struct StruScreenSeting +{ + int iSelectedIC; + int iTxNum; + int iRxNum; + int isNormalize; + int iUsedMaxTxNum; + int iUsedMaxRxNum; + + unsigned char iChannelsNum; + unsigned char iKeyNum; + +}; + +struct stTestItem +{ + unsigned char ItemType; + unsigned char TestNum; + unsigned char TestResult; + unsigned char ItemCode; +}; + +enum NORMALIZE_Type +{ + Overall_Normalize = 0, + Auto_Normalize = 1, +}; + +enum PROOF_TYPE +{ + Proof_Normal, + Proof_Level0, + Proof_NoWaterProof, +}; + +extern struct stCfg_MCap_DetailThreshold g_stCfg_MCap_DetailThreshold; +extern struct stCfg_SCap_DetailThreshold g_stCfg_SCap_DetailThreshold; + +extern struct StruScreenSeting g_ScreenSetParam; +extern struct stTestItem g_stTestItem[1][MAX_TEST_ITEM]; + +extern int g_TestItemNum;/*test item num*/ +extern char g_strIcName[20];/*IC Name*/ + + +int GetPrivateProfileString(char *section, char *ItemName, char *defaultvalue, char *returnValue, char *IniFile); +void focal_msleep(int ms); +void SysDelay(int ms); +int focal_abs(int value); +unsigned char get_ic_code(char *strIcName); +void get_ic_name(unsigned char ucIcCode, char *strIcName); + +void OnInit_InterfaceCfg(char *strIniFile); + +int ReadReg(unsigned char RegAddr, unsigned char *RegData); +int WriteReg(unsigned char RegAddr, unsigned char RegData); +unsigned char Comm_Base_IIC_IO(unsigned char *pWriteBuffer, int iBytesToWrite, unsigned char *pReadBuffer, int iBytesToRead); + +unsigned char EnterWork(void); +unsigned char EnterFactory(void); + + + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Makefile b/drivers/input/touchscreen/ft5435/lib/Makefile new file mode 100644 index 0000000000000..9b1c9feb84b64 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Makefile @@ -0,0 +1,23 @@ +# Linux driver folder +ccflags-y += -I$(srctree)/drivers/input/touchscreen/mediatek/ft3427_zaw875/include/ +ccflags-y += -I$(srctree)/drivers/input/touchscreen/mediatek/ft5346/ +ccflags-y += -I$(srctree)/drivers/input/touchscreen/mediatek/ft3427_zaw875/include/$(CONFIG_FT5X0X_FIRMWARE)/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/ +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/ +ccflags-y += -I$(srctree)/drivers/input/touchscreen/mediatek/ft5346/include/ + + +obj-y += Config_FT5822.o +obj-y += Config_FT5X46.o +obj-y += Config_FT8606.o +obj-y += Config_FT6X36.o +obj-y += Config_FT3C47.o +obj-y += DetailThreshold.o +obj-y += Global.o ini.o +obj-y += Test_FT5822.o +obj-y += Test_FT5X46.o +obj-y += Test_FT8606.o +obj-y += Test_FT6X36.o +obj-y += Test_FT3C47.o +obj-y += test_lib.o + diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT3C47.c b/drivers/input/touchscreen/ft5435/lib/Test_FT3C47.c new file mode 100644 index 0000000000000..0ee85a09b4d2d --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT3C47.c @@ -0,0 +1,2471 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT3C47.c +* +* Author: Software Development Team, AE +* +* Created: 2015-12-02 +* +* Abstract: test item for FT3C47 +* +************************************************************************/ + +/******************************************************************************* +* Included header files +*******************************************************************************/ +#include +#include +#include + +#include "Global.h" +#include "DetailThreshold.h" +#include "Test_FT3C47.h" +#include "Config_FT3C47.h" + + +/******************************************************************************* +* Private constant and macro definitions using #define +*******************************************************************************/ +#define IC_TEST_VERSION "Test version: V1.0.0--2015-12-02, (sync version of FT_MultipleTest: V2.8.0.4 ------ 2015-11-30)" + + +#define DEVIDE_MODE_ADDR 0x00 +#define REG_LINE_NUM 0x01 +#define REG_TX_NUM 0x02 +#define REG_RX_NUM 0x03 +#define REG_PATTERN_3C47 0x53 +#define REG_MAPPING_SWITCH 0x54 +#define REG_TX_NOMAPPING_NUM 0x55 +#define REG_RX_NOMAPPING_NUM 0x56 +#define REG_NORMALIZE_TYPE 0x16 +#define REG_ScCbBuf0 0x4E +#define REG_ScWorkMode 0x44 +#define REG_ScCbAddrR 0x45 +#define REG_RawBuf0 0x36 +#define REG_WATER_CHANNEL_SELECT 0x09 + +#define REG_REAL_TX_NUM 0XEB +#define REG_REAL_RX_NUM 0XEC + +/******************************************************************************* +* Private enumerations, structures and unions using typedef +*******************************************************************************/ +enum WaterproofType +{ + WT_NeedProofOnTest, + WT_NeedProofOffTest, + WT_NeedTxOnVal, + WT_NeedRxOnVal, + WT_NeedTxOffVal, + WT_NeedRxOffVal, +}; +/******************************************************************************* +* Static variables +*******************************************************************************/ + +static int m_RawData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_iTempRawData[TX_NUM_MAX * RX_NUM_MAX] = {0}; +static unsigned char m_ucTempData[TX_NUM_MAX * RX_NUM_MAX*2] = {0}; +static bool m_bV3TP; + +static unsigned char m_iAllTx; +static unsigned char m_iAllRx; +static int m_iForceTouchTx; +static int m_iForceTouchRx; + + +static char g_pStoreAllData[1024*80] = {0}; +static char *g_pTmpBuff; +static char *g_pStoreMsgArea; +static int g_lenStoreMsgArea; +static char *g_pMsgAreaLine2; +static int g_lenMsgAreaLine2; +static char *g_pStoreDataArea; +static int g_lenStoreDataArea; +static unsigned char m_ucTestItemCode; +static int m_iStartLine; +static int m_iTestDataCount; + +/******************************************************************************* +* Global variable or extern global variabls/functions +*******************************************************************************/ + + +/******************************************************************************* +* Static function prototypes +*******************************************************************************/ + +static int StartScan(void); +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer); +static unsigned char GetPanelRows(unsigned char *pPanelRows); +static unsigned char GetPanelCols(unsigned char *pPanelCols); +static unsigned char GetTxSC_CB(unsigned char index, unsigned char *pcbValue); + +static unsigned char GetRawData(void); +static unsigned char GetChannelNum(void); + +static void InitTest(void); +static void FinishTest(void); +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount); +static void InitStoreParamOfTestData(void); +static void MergeAllTestData(void); + +static void AllocateMemory(void); +static void FreeMemory(void); +static void ShowRawData(void); +static boolean GetTestCondition(int iTestType, unsigned char ucChannelValue); + +static unsigned char GetChannelNumNoMapping(void); +static unsigned char SwitchToNoMapping(void); + + +/************************************************************************ +* Name: FT3C47_StartTest +* Brief: Test entry. Determine which test item to test +* Input: none +* Output: none +* Return: Test Result, PASS or FAIL +***********************************************************************/ +boolean FT3C47_StartTest() +{ + bool bTestResult = true; + bool bTempResult = 1; + unsigned char ReCode = 0; + unsigned char ucDevice = 0; + int iItemCount = 0; + + + InitTest(); + + + if (0 == g_TestItemNum) + bTestResult = false; + + for (iItemCount = 0; iItemCount < g_TestItemNum; iItemCount++) + { + m_ucTestItemCode = g_stTestItem[ucDevice][iItemCount].ItemCode; + + + if (Code_FT3C47_ENTER_FACTORY_MODE == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_EnterFactoryMode(); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + break; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + /*if(Code_FT3C47_CHANNEL_NUM_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_ChannelsTest(&bTempResult); + if(ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + } + }*/ + + + if (Code_FT3C47_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_RawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + + if (Code_FT3C47_SCAP_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_SCapCbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT3C47_SCAP_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_SCapRawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT3C47_FORCE_TOUCH_SCAP_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_ForceTouch_SCapCbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT3C47_FORCE_TOUCH_SCAP_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT3C47_TestItem_ForceTouch_SCapRawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + } + + + FinishTest(); + + + return bTestResult; +} +/************************************************************************ +* Name: InitTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitTest(void) +{ + AllocateMemory(); + InitStoreParamOfTestData(); + printk("[focal] %s \n", IC_TEST_VERSION); +} +/************************************************************************ +* Name: FinishTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FinishTest(void) +{ + MergeAllTestData(); + FreeMemory(); +} +/************************************************************************ +* Name: FT3C47_get_test_data +* Brief: get data of test result +* Input: none +* Output: pTestData, the returned buff +* Return: the length of test data. if length > 0, got data;else ERR. +***********************************************************************/ +int FT3C47_get_test_data(char *pTestData) +{ + if (NULL == pTestData) + { + printk("[focal] %s pTestData == NULL \n", __func__); + return -EPERM; + } + memcpy(pTestData, g_pStoreAllData, (g_lenStoreMsgArea+g_lenStoreDataArea)); + return (g_lenStoreMsgArea+g_lenStoreDataArea); +} + +/************************************************************************ +* Name: FT3C47_TestItem_EnterFactoryMode +* Brief: Check whether TP can enter Factory Mode, and do some thing +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT3C47_TestItem_EnterFactoryMode(void) +{ + unsigned char ReCode = ERROR_CODE_INVALID_PARAM; + int iRedo = 5; + int i ; + unsigned char chPattern = 0; + + SysDelay(150); + for (i = 1; i <= iRedo; i++) + { + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter factory mode...\n"); + if (i < iRedo) + { + SysDelay(50); + continue; + } + } + else + { + break; + } + + } + SysDelay(300); + + + if (ReCode != ERROR_CODE_OK) + { + return ReCode; + } + + ReCode = GetChannelNum(); + + ReCode = ReadReg(REG_PATTERN_3C47, &chPattern); + if (chPattern == 1) + { + m_bV3TP = true; + } + else + { + m_bV3TP = false; + } + + return ReCode; +} +/************************************************************************ +* Name: FT3C47_TestItem_RawDataTest +* Brief: TestItem: RawDataTest. Check if MCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT3C47_TestItem_RawDataTest(bool *bTestResult) +{ + unsigned char ReCode = 0; + bool btmpresult = true; + int RawDataMin; + int RawDataMax; + unsigned char ucFre; + unsigned char strSwitch = 0; + unsigned char OriginValue = 0xff; + int index = 0; + int iRow, iCol; + int iValue = 0; + + + printk("\n\n==============================Test Item: -------- Raw Data Test \n\n"); + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &strSwitch); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (strSwitch != 0) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Write REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + } + + ReCode = ReadReg(REG_NORMALIZE_TYPE, &OriginValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (g_ScreenSetParam.isNormalize == Auto_Normalize) + { + if (OriginValue != 1) + { + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x01); + if (ReCode != ERROR_CODE_OK) + { + printk("\n write REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + printk("\n=========Set Frequecy High\n"); + ReCode = WriteReg(0x0A, 0x81); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Set Frequecy High error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + printk("\n=========FIR State: ON\n"); + ReCode = WriteReg(0xFB, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("\n FIR State: ON error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + goto TEST_ERR; + } + + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + } + else + { + if (OriginValue != 0) + { + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x00); + if (ReCode != ERROR_CODE_OK) + { + printk("\n write REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + ReCode = ReadReg(0x0A, &ucFre); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read frequency error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + if (g_stCfg_FT3C47_BasicThreshold.RawDataTest_SetLowFreq) + { + printk("\n=========Set Frequecy Low\n"); + ReCode = WriteReg(0x0A, 0x80); + if (ReCode != ERROR_CODE_OK) + { + printk("\n write frequency error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + printk("\n=========FIR State: OFF\n"); + ReCode = WriteReg(0xFB, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("\n FIR State: OFF error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + SysDelay(100); + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + goto TEST_ERR; + } + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + } + + + if (g_stCfg_FT3C47_BasicThreshold.RawDataTest_SetHighFreq) + { + + printk("\n=========Set Frequecy High\n"); + ReCode = WriteReg(0x0A, 0x81); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Set Frequecy High error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + printk("\n=========FIR State: OFF\n"); + ReCode = WriteReg(0xFB, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("\n FIR State: OFF error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + SysDelay(100); + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 2); + } + + } + + + + ReCode = WriteReg(REG_NORMALIZE_TYPE, OriginValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Write REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (m_bV3TP) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, strSwitch); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Write REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + return ReCode; + +} +/************************************************************************ +* Name: FT3C47_TestItem_SCapRawDataTest +* Brief: TestItem: SCapRawDataTest. Check if SCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT3C47_TestItem_SCapRawDataTest(bool *bTestResult) +{ + int i = 0; + int RawDataMin = 0; + int RawDataMax = 0; + int Value = 0; + boolean bFlag = true; + unsigned char ReCode = 0; + boolean btmpresult = true; + int iMax = 0; + int iMin = 0; + int iAvg = 0; + int ByteNum = 0; + unsigned char wc_value = 0; + unsigned char ucValue = 0; + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: -------- Scap RawData Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to read REG_WATER_CHANNEL_SELECT. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = SwitchToNoMapping(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to SwitchToNoMapping. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData! \n"); + goto TEST_ERR; + } + for (i = 0; i < 3; i++) + { + memset(m_iTempRawData, 0, sizeof(m_iTempRawData)); + + ByteNum = (m_iAllTx + m_iAllRx)*2; + ReCode = ReadRawData(0, 0xAC, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to ReadRawData water! \n"); + goto TEST_ERR; + } + + memcpy(m_RawData[0+g_ScreenSetParam.iTxNum], m_iTempRawData, sizeof(int)*g_ScreenSetParam.iRxNum); + memcpy(m_RawData[1+g_ScreenSetParam.iTxNum], m_iTempRawData + m_iAllRx, sizeof(int)*g_ScreenSetParam.iTxNum); + + ByteNum = (m_iAllTx + m_iAllRx)*2; + ReCode = ReadRawData(0, 0xAB, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to ReadRawData no water! \n"); + goto TEST_ERR; + } + memcpy(m_RawData[2+g_ScreenSetParam.iTxNum], m_iTempRawData, sizeof(int)*g_ScreenSetParam.iRxNum); + memcpy(m_RawData[3+g_ScreenSetParam.iTxNum], m_iTempRawData + m_iAllRx, sizeof(int)*g_ScreenSetParam.iTxNum); + } + + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_SetWaterproof_ON && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_ON_Min; + RawDataMax = g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_ON_Max; + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[1][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[1][i]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap RawData in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_SetWaterproof_OFF && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_OFF_Min; + RawDataMax = g_stCfg_FT3C47_BasicThreshold.SCapRawDataTest_OFF_Max; + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[1][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[1][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap RawData in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &ucValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (0 != ucValue) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + SysDelay(10); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + ReCode = GetChannelNum(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n GetChannelNum error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//SCap RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//SCap RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + * bTestResult = false; + printk("\n\n//SCap RawData Test is NG!\n"); + return ReCode; +} + +/************************************************************************ +* Name: FT3C47_TestItem_SCapCbTest +* Brief: TestItem: SCapCbTest. Check if SCAP Cb is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT3C47_TestItem_SCapCbTest(bool *bTestResult) +{ + int i, /* j, iOutNum, */index, Value, CBMin, CBMax; + boolean bFlag = true; + unsigned char ReCode; + boolean btmpresult = true; + int iMax, iMin, iAvg; + unsigned char wc_value = 0; + unsigned char ucValue = 0; + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: ----- Scap CB Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_WATER_CHANNEL_SELECT error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + bFlag = SwitchToNoMapping(); + if (bFlag) + { + printk("Failed to SwitchToNoMapping! ReCode = %d. \n", ReCode); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData!ReCode = %d. \n", ReCode); + goto TEST_ERR; + } + + + for (i = 0; i < 3; i++) + { + memset(m_RawData, 0, sizeof(m_RawData)); + memset(m_ucTempData, 0, sizeof(m_ucTempData)); + + ReCode = WriteReg(REG_ScWorkMode, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("Get REG_ScWorkMode Failed!\n"); + goto TEST_ERR; + } + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("StartScan Failed!\n"); + goto TEST_ERR; + } + + ReCode = WriteReg(REG_ScCbAddrR, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Write REG_ScCbAddrR Failed!\n"); + goto TEST_ERR; + } + + ReCode = GetTxSC_CB(m_iAllTx + m_iAllRx + 128, m_ucTempData); + if (ReCode != ERROR_CODE_OK) + { + printk("GetTxSC_CB Failed!\n"); + goto TEST_ERR; + } + + for (index = 0; index < g_ScreenSetParam.iRxNum; ++index) + { + m_RawData[0 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index]; + } + for (index = 0; index < g_ScreenSetParam.iTxNum; ++index) + { + m_RawData[1 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index + m_iAllRx]; + } + + ReCode = WriteReg(REG_ScWorkMode, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Get REG_ScWorkMode Failed!\n"); + goto TEST_ERR; + } + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("StartScan Failed!\n"); + goto TEST_ERR; + } + + ReCode = WriteReg(REG_ScCbAddrR, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Write REG_ScCbAddrR Failed!\n"); + goto TEST_ERR; + } + + ReCode = GetTxSC_CB(m_iAllTx + m_iAllRx + 128, m_ucTempData); + if (ReCode != ERROR_CODE_OK) + { + printk("GetTxSC_CB Failed!\n"); + goto TEST_ERR; + } + for (index = 0; index < g_ScreenSetParam.iRxNum; ++index) + { + m_RawData[2 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index]; + } + for (index = 0; index < g_ScreenSetParam.iTxNum; ++index) + { + m_RawData[3 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index + m_iAllRx]; + } + + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Get SCap CB!\n"); + } + } + + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.SCapCbTest_SetWaterproof_ON && bFlag) + { + printk("SCapCbTest in WaterProof On Mode: \n"); + + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("SCap CB_Rx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("SCap CB_Tx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[1][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[1][i]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap CB in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.SCapCbTest_SetWaterproof_OFF && bFlag) + { + printk("SCapCbTest in WaterProof OFF Mode: \n"); + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("SCap CB_Rx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("SCap CB_Tx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[1][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[1][i]; + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap CB in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &ucValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (0 != ucValue) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + SysDelay(10); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + ReCode = GetChannelNum(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n GetChannelNum error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//SCap CB Test Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//SCap CB Test Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//SCap CB Test Test is NG!\n"); + return ReCode; +} + +/************************************************************************ +* Name: GetPanelRows(Same function name as FT_MultipleTest) +* Brief: Get row of TP +* Input: none +* Output: pPanelRows +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelRows(unsigned char *pPanelRows) +{ + return ReadReg(REG_TX_NUM, pPanelRows); +} + +/************************************************************************ +* Name: GetPanelCols(Same function name as FT_MultipleTest) +* Brief: get column of TP +* Input: none +* Output: pPanelCols +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelCols(unsigned char *pPanelCols) +{ + return ReadReg(REG_RX_NUM, pPanelCols); +} +/************************************************************************ +* Name: StartScan(Same function name as FT_MultipleTest) +* Brief: Scan TP, do it before read Raw Data +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static int StartScan(void) +{ + unsigned char RegVal = 0; + unsigned char times = 0; + const unsigned char MaxTimes = 20; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + RegVal |= 0x80; + ReCode = WriteReg(DEVIDE_MODE_ADDR, RegVal); + if (ReCode == ERROR_CODE_OK) + { + while(times++ < MaxTimes) + { + SysDelay(8); + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + if ((RegVal>>7) == 0) break; + } + else + { + printk("StartScan read DEVIDE_MODE_ADDR error.\n"); + break; + } + } + if (times < MaxTimes) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + else + printk("StartScan write DEVIDE_MODE_ADDR error.\n"); + } + else + printk("StartScan read DEVIDE_MODE_ADDR error.\n"); + return ReCode; + +} +/************************************************************************ +* Name: ReadRawData(Same function name as FT_MultipleTest) +* Brief: read Raw Data +* Input: Freq(No longer used, reserved), LineNum, ByteNum +* Output: pRevBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer) +{ + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + unsigned char I2C_wBuffer[3]; + int i, iReadNum; + unsigned short BytesNumInTestMode1 = 0; + + + + + iReadNum = ByteNum/342; + + if (0 != (ByteNum%342)) iReadNum++; + + if (ByteNum <= 342) + { + BytesNumInTestMode1 = ByteNum; + } + else + { + BytesNumInTestMode1 = 342; + } + + ReCode = WriteReg(REG_LINE_NUM, LineNum); + + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to write REG_LINE_NUM! \n"); + goto READ_ERR; + } + + + I2C_wBuffer[0] = REG_RawBuf0; + if (ReCode == ERROR_CODE_OK) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, m_ucTempData, BytesNumInTestMode1); + if (ReCode != ERROR_CODE_OK) + { + printk("read rawdata Comm_Base_IIC_IO Failed!1 \n"); + goto READ_ERR; + } + } + + for (i = 1; i < iReadNum; i++) + { + if (ReCode != ERROR_CODE_OK) break; + + if (i == iReadNum-1) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, m_ucTempData+342*i, ByteNum-342*i); + if (ReCode != ERROR_CODE_OK) + { + printk("read rawdata Comm_Base_IIC_IO Failed!2 \n"); + goto READ_ERR; + } + } + else + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, m_ucTempData+342*i, 342); + + if (ReCode != ERROR_CODE_OK) + { + printk("read rawdata Comm_Base_IIC_IO Failed!3 \n"); + goto READ_ERR; + } + } + + } + + if (ReCode == ERROR_CODE_OK) + { + for (i = 0; i < (ByteNum>>1); i++) + { + pRevBuffer[i] = (m_ucTempData[i<<1]<<8)+m_ucTempData[(i<<1)+1]; + + + + } + } + +READ_ERR: + return ReCode; + +} +/************************************************************************ +* Name: GetTxSC_CB(Same function name as FT_MultipleTest) +* Brief: get CB of Tx SCap +* Input: index +* Output: pcbValue +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char GetTxSC_CB(unsigned char index, unsigned char *pcbValue) +{ + unsigned char ReCode = ERROR_CODE_OK; + unsigned char wBuffer[4]; + + if (index < 128) + { + *pcbValue = 0; + WriteReg(REG_ScCbAddrR, index); + ReCode = ReadReg(REG_ScCbBuf0, pcbValue); + } + else + { + WriteReg(REG_ScCbAddrR, 0); + wBuffer[0] = REG_ScCbBuf0; + ReCode = Comm_Base_IIC_IO(wBuffer, 1, pcbValue, index-128); + + } + + return ReCode; +} + + + +/************************************************************************ +* Name: AllocateMemory +* Brief: Allocate pointer Memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void AllocateMemory(void) +{ + + g_pStoreMsgArea = NULL; + if (NULL == g_pStoreMsgArea) + g_pStoreMsgArea = kmalloc(1024*80, GFP_ATOMIC); + g_pMsgAreaLine2 = NULL; + if (NULL == g_pMsgAreaLine2) + g_pMsgAreaLine2 = kmalloc(1024*80, GFP_ATOMIC); + g_pStoreDataArea = NULL; + if (NULL == g_pStoreDataArea) + g_pStoreDataArea = kmalloc(1024*80, GFP_ATOMIC); + /*g_pStoreAllData =NULL; + if(NULL == g_pStoreAllData) + g_pStoreAllData = kmalloc(1024*8, GFP_ATOMIC); + g_pTmpBuff =NULL;*/ + if (NULL == g_pTmpBuff) + g_pTmpBuff = kmalloc(1024*16, GFP_ATOMIC); + +} +/************************************************************************ +* Name: FreeMemory +* Brief: Release pointer memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FreeMemory(void) +{ + + if (NULL != g_pStoreMsgArea) + kfree(g_pStoreMsgArea); + + if (NULL != g_pMsgAreaLine2) + kfree(g_pMsgAreaLine2); + + if (NULL != g_pStoreDataArea) + kfree(g_pStoreDataArea); + + /*if(NULL == g_pStoreAllData) + kfree(g_pStoreAllData);*/ + + if (NULL != g_pTmpBuff) + kfree(g_pTmpBuff); +} + +/************************************************************************ +* Name: InitStoreParamOfTestData +* Brief: Init store param of test data +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitStoreParamOfTestData(void) +{ + + + g_lenStoreMsgArea = 0; + + g_lenStoreMsgArea += sprintf(g_pStoreMsgArea, "ECC, 85, 170, IC Name, %s, IC Code, %x\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + + + g_lenMsgAreaLine2 = 0; + + + + g_lenStoreDataArea = 0; + m_iStartLine = 11; + + m_iTestDataCount = 0; +} +/************************************************************************ +* Name: MergeAllTestData +* Brief: Merge All Data of test result +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void MergeAllTestData(void) +{ + int iLen = 0; + + + iLen = sprintf(g_pTmpBuff, "TestItem, %d, ", m_iTestDataCount); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pMsgAreaLine2, g_lenMsgAreaLine2); + g_lenStoreMsgArea+=g_lenMsgAreaLine2; + + + iLen = sprintf(g_pTmpBuff, "\n\n\n\n\n\n\n\n\n"); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreAllData, g_pStoreMsgArea, g_lenStoreMsgArea); + + + if (0 != g_lenStoreDataArea) + { + memcpy(g_pStoreAllData+g_lenStoreMsgArea, g_pStoreDataArea, g_lenStoreDataArea); + } + + printk("[focal] %s lenStoreMsgArea=%d, lenStoreDataArea = %d\n", __func__, g_lenStoreMsgArea, g_lenStoreDataArea); +} + + +/************************************************************************ +* Name: Save_Test_Data +* Brief: Storage format of test data +* Input: int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount +* Output: none +* Return: none +***********************************************************************/ +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount) +{ + int iLen = 0; + int i = 0, j = 0; + + + iLen = sprintf(g_pTmpBuff, "NA, %d, %d, %d, %d, %d, ", \ + m_ucTestItemCode, Row, Col, m_iStartLine, ItemCount); + memcpy(g_pMsgAreaLine2+g_lenMsgAreaLine2, g_pTmpBuff, iLen); + g_lenMsgAreaLine2 += iLen; + + m_iStartLine += Row; + m_iTestDataCount++; + + + for (i = 0+iArrayIndex; i < Row+iArrayIndex; i++) + { + for (j = 0; j < Col; j++) + { + if (j == (Col -1)) + iLen = sprintf(g_pTmpBuff, "%d, \n", iData[i][j]); + else + iLen = sprintf(g_pTmpBuff, "%d, ", iData[i][j]); + + memcpy(g_pStoreDataArea+g_lenStoreDataArea, g_pTmpBuff, iLen); + g_lenStoreDataArea += iLen; + } + } + +} + +/************************************************************************ +* Name: GetChannelNum +* Brief: Get Channel Num(Tx and Rx) +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNum(void) +{ + unsigned char ReCode = 0; + unsigned char rBuffer[1] = {0}; + + unsigned char TxNum = 0; + unsigned char RxNum = 0; + + + ReCode = GetPanelRows(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iTxNum = rBuffer[0]; + if (g_ScreenSetParam.iTxNum > g_ScreenSetParam.iUsedMaxTxNum) + { + printk("Failed to get Tx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iTxNum, g_ScreenSetParam.iUsedMaxTxNum); + return ERROR_CODE_INVALID_PARAM; + } + } + else + { + printk("Failed to get Tx number\n"); + } + + + + ReCode = GetPanelCols(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iRxNum = rBuffer[0]; + if (g_ScreenSetParam.iRxNum > g_ScreenSetParam.iUsedMaxRxNum) + { + printk("Failed to get Rx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iRxNum, g_ScreenSetParam.iUsedMaxRxNum); + return ERROR_CODE_INVALID_PARAM; + } + } + else + { + printk("Failed to get Rx number\n"); + } + + + + + ReCode = ReadReg(REG_REAL_RX_NUM, &RxNum); + if (ReCode == ERROR_CODE_OK) + { + m_iForceTouchRx = RxNum - g_ScreenSetParam.iRxNum; + } + else + { + printk("Failed to get real Rx number\r\n"); + } + + + ReCode = ReadReg(REG_REAL_TX_NUM, &TxNum); + if (ReCode == ERROR_CODE_OK) + { + m_iForceTouchTx = TxNum - g_ScreenSetParam.iTxNum; + } + else + { + printk("Failed to get real Tx number\r\n"); + } + + m_iAllTx = TxNum; + m_iAllRx = RxNum; + + return ReCode; + +} +/************************************************************************ +* Name: GetRawData +* Brief: Get Raw Data of MCAP +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetRawData(void) +{ + unsigned char ReCode = ERROR_CODE_OK; + int iRow = 0; + int iCol = 0; + + + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter Factory Mode...\n"); + return ReCode; + } + + + + if (0 == (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)) + { + ReCode = GetChannelNum(); + if (ERROR_CODE_OK != ReCode) + { + printk("Error Channel Num...\n"); + return ERROR_CODE_INVALID_PARAM; + } + } + + + printk("Start Scan ...\n"); + ReCode = StartScan(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Scan ...\n"); + return ReCode; + } + + + memset(m_RawData, 0, sizeof(m_RawData)); + ReCode = ReadRawData(1, 0xAA, (g_ScreenSetParam.iTxNum * g_ScreenSetParam.iRxNum)*2, m_iTempRawData); + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + m_RawData[iRow][iCol] = m_iTempRawData[iRow*g_ScreenSetParam.iRxNum + iCol]; + } + } + return ReCode; +} +/************************************************************************ +* Name: ShowRawData +* Brief: Show RawData +* Input: none +* Output: none +* Return: none. +***********************************************************************/ +static void ShowRawData(void) +{ + int iRow, iCol; + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + printk("\nTx%2d: ", iRow+1); + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + printk("%5d ", m_RawData[iRow][iCol]); + } + } +} + +/************************************************************************ +* Name: GetChannelNumNoMapping +* Brief: get Tx&Rx num from other Register +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNumNoMapping(void) +{ + unsigned char ReCode; + unsigned char rBuffer[1]; + + + printk("Get Tx Num...\n"); + ReCode = ReadReg(REG_TX_NOMAPPING_NUM, rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iTxNum = rBuffer[0]; + } + else + { + printk("Failed to get Tx number\n"); + } + + + printk("Get Rx Num...\n"); + ReCode = ReadReg(REG_RX_NOMAPPING_NUM, rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iRxNum = rBuffer[0]; + } + else + { + printk("Failed to get Rx number\n"); + } + + return ReCode; +} +/************************************************************************ +* Name: SwitchToNoMapping +* Brief: If it is V3 pattern, Get Tx/Rx Num again +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char SwitchToNoMapping(void) +{ + unsigned char chPattern = -1; + unsigned char ReCode = ERROR_CODE_OK; + unsigned char RegData = -1; + ReCode = ReadReg(REG_PATTERN_3C47, &chPattern); + if (ReCode != ERROR_CODE_OK) + { + printk("Switch To NoMapping Failed!\n"); + goto READ_ERR; + } + + if (1 == chPattern) + { + RegData = -1; + ReCode = ReadReg(REG_MAPPING_SWITCH, &RegData); + if (ReCode != ERROR_CODE_OK) + { + printk("read REG_MAPPING_SWITCH Failed!\n"); + goto READ_ERR; + } + + if (1 != RegData) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("write REG_MAPPING_SWITCH Failed!\n"); + goto READ_ERR; + } + focal_msleep(20); + ReCode = GetChannelNumNoMapping(); + + if (ReCode != ERROR_CODE_OK) + { + printk("GetChannelNumNoMapping Failed!\n"); + goto READ_ERR; + } + } + } + +READ_ERR: + return ReCode; +} +/************************************************************************ +* Name: GetTestCondition +* Brief: Check whether Rx or TX need to test, in Waterproof ON/OFF Mode. +* Input: none +* Output: none +* Return: true: need to test; false: Not tested. +***********************************************************************/ +static boolean GetTestCondition(int iTestType, unsigned char ucChannelValue) +{ + boolean bIsNeeded = false; + switch(iTestType) + { + case WT_NeedProofOnTest: + bIsNeeded = !(ucChannelValue & 0x20); + break; + case WT_NeedProofOffTest: + bIsNeeded = !(ucChannelValue & 0x80); + break; + case WT_NeedTxOnVal: + bIsNeeded = !(ucChannelValue & 0x40) || !(ucChannelValue & 0x04); + break; + case WT_NeedRxOnVal: + bIsNeeded = !(ucChannelValue & 0x40) || (ucChannelValue & 0x04); + break; + case WT_NeedTxOffVal: + bIsNeeded = (0x00 == (ucChannelValue & 0x03)) || (0x02 == (ucChannelValue & 0x03)); + break; + case WT_NeedRxOffVal: + bIsNeeded = (0x01 == (ucChannelValue & 0x03)) || (0x02 == (ucChannelValue & 0x03)); + break; + default:break; + } + return bIsNeeded; +} + + +/************************************************************************ +* Name: FT3C47_TestItem_ForceTouch_SCapRawDataTest +* Brief: TestItem: ForceTouch_SCapRawDataTest. Check if ForceTouch_SCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT3C47_TestItem_ForceTouch_SCapRawDataTest(bool *bTestResult) +{ + int i = 0; + int RawDataMin = 0; + int RawDataMax = 0; + int Value = 0; + boolean bFlag = true; + unsigned char ReCode = 0; + boolean btmpresult = true; + int iMax = 0; + int iMin = 0; + int iAvg = 0; + int ByteNum = 0; + unsigned char wc_value = 0; + + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: -------- Force Touch Scap RawData Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to read REG_WATER_CHANNEL_SELECT. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData! \n"); + goto TEST_ERR; + } + for (i = 0; i < 3; i++) + { + memset(m_iTempRawData, 0, sizeof(m_iTempRawData)); + + + ByteNum = (m_iAllTx+ m_iAllRx)*2; + ReCode = ReadRawData(0, 0xAC, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to ReadRawData water! \n"); + goto TEST_ERR; + } + + memcpy(m_RawData[0+g_ScreenSetParam.iTxNum], m_iTempRawData+g_ScreenSetParam.iRxNum, sizeof(int)*m_iForceTouchRx); + memcpy(m_RawData[1+g_ScreenSetParam.iTxNum], m_iTempRawData +m_iAllRx+g_ScreenSetParam.iTxNum, sizeof(int)*m_iForceTouchTx); + + + ByteNum = (m_iAllTx+ m_iAllRx)*2; + ReCode = ReadRawData(0, 0xAB, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to ReadRawData no water! \n"); + goto TEST_ERR; + } + memcpy(m_RawData[2+g_ScreenSetParam.iTxNum], m_iTempRawData+g_ScreenSetParam.iRxNum, sizeof(int)*m_iForceTouchRx); + memcpy(m_RawData[3+g_ScreenSetParam.iTxNum], m_iTempRawData +m_iAllRx+g_ScreenSetParam.iTxNum, sizeof(int)*m_iForceTouchTx); + } + + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_SetWaterproof_ON && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_ON_Min; + RawDataMax = g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_ON_Max; + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < m_iForceTouchRx; i++) + { + + RawDataMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < m_iForceTouchTx; i++) + { + + RawDataMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Min[0][i+m_iForceTouchRx]; + RawDataMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_ON_Max[0][i+m_iForceTouchRx]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("Force Touch SCap RawData in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = m_iForceTouchTx > m_iForceTouchRx?m_iForceTouchTx:m_iForceTouchRx; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_SetWaterproof_OFF && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_OFF_Min; + RawDataMax = g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapRawDataTest_OFF_Max; + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < m_iForceTouchRx; i++) + { + + RawDataMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < m_iForceTouchTx; i++) + { + + + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + RawDataMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Min[0][i+m_iForceTouchRx]; + RawDataMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapRawDataTest_OFF_Max[0][i+m_iForceTouchRx]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("Force Touch SCap RawData in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = m_iForceTouchTx > m_iForceTouchRx?m_iForceTouchTx:m_iForceTouchRx; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + /*if(m_bV3TP) + { + ReCode = ReadReg( REG_MAPPING_SWITCH, &ucValue ); + if(ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (0 !=ucValue ) + { + ReCode = WriteReg( REG_MAPPING_SWITCH, 0 ); + SysDelay(10); + if( ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + //Ö»ÓÐ×ÔÈݲŻáʹÓÃMappingÇ°µÄ£¬ËùÒԸòâÊÔÏî½áÊøÒÔºó£¬ÐèҪתµ½Mappingºó + ReCode = GetChannelNum(); + if(ReCode != ERROR_CODE_OK) + { + printk("\n GetChannelNum error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + }*/ + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//Force Touch SCap RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//Force Touch SCap RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + * bTestResult = false; + printk("\n\n//Force Touch SCap RawData Test is NG!\n"); + return ReCode; +} + + +/************************************************************************ +* Name: FT3C47_TestItem_ForceTouch_SCapCbTest +* Brief: TestItem: ForceTouch_SCapCbTest. Check if ForceTouch_SCAP Cb is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT3C47_TestItem_ForceTouch_SCapCbTest(bool *bTestResult) +{ + int i, /* j, iOutNum, */index, Value, CBMin, CBMax; + boolean bFlag = true; + unsigned char ReCode; + boolean btmpresult = true; + int iMax, iMin, iAvg; + unsigned char wc_value = 0; + + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: ----- Force Touch Scap CB Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_WATER_CHANNEL_SELECT error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData!ReCode = %d. \n", ReCode); + goto TEST_ERR; + } + + + for (i = 0; i < 3; i++) + { + memset(m_RawData, 0, sizeof(m_RawData)); + memset(m_ucTempData, 0, sizeof(m_ucTempData)); + + ReCode = WriteReg(REG_ScWorkMode, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("Get REG_ScWorkMode Failed!\n"); + goto TEST_ERR; + } + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("StartScan Failed!\n"); + goto TEST_ERR; + } + + ReCode = WriteReg(REG_ScCbAddrR, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Write REG_ScCbAddrR Failed!\n"); + goto TEST_ERR; + } + + ReCode = GetTxSC_CB(m_iAllTx + m_iAllRx + 128, m_ucTempData); + if (ReCode != ERROR_CODE_OK) + { + printk("GetTxSC_CB Failed!\n"); + goto TEST_ERR; + } + + for (index = g_ScreenSetParam.iRxNum; index < m_iAllRx; ++index) + { + m_RawData[0 + g_ScreenSetParam.iTxNum][index-g_ScreenSetParam.iRxNum] = m_ucTempData[index]; + } + for (index = m_iAllRx+ g_ScreenSetParam.iTxNum; index < m_iAllTx + m_iAllRx; ++index) + { + m_RawData[1 + g_ScreenSetParam.iTxNum][index-m_iAllRx-g_ScreenSetParam.iTxNum] = m_ucTempData[index]; + } + + ReCode = WriteReg(REG_ScWorkMode, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Get REG_ScWorkMode Failed!\n"); + goto TEST_ERR; + } + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("StartScan Failed!\n"); + goto TEST_ERR; + } + + ReCode = WriteReg(REG_ScCbAddrR, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Write REG_ScCbAddrR Failed!\n"); + goto TEST_ERR; + } + + ReCode = GetTxSC_CB(m_iAllTx + m_iAllRx + 128, m_ucTempData); + if (ReCode != ERROR_CODE_OK) + { + printk("GetTxSC_CB Failed!\n"); + goto TEST_ERR; + } + + for (index = g_ScreenSetParam.iRxNum; index < m_iAllRx; ++index) + { + m_RawData[0 + g_ScreenSetParam.iTxNum][index-g_ScreenSetParam.iRxNum] = m_ucTempData[index]; + } + for (index = m_iAllRx+ g_ScreenSetParam.iTxNum; index < m_iAllTx + m_iAllRx; ++index) + { + m_RawData[1 + g_ScreenSetParam.iTxNum][index-m_iAllRx-g_ScreenSetParam.iTxNum] = m_ucTempData[index]; + } + + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Get SCap CB!\n"); + } + } + + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCBTest_SetWaterproof_ON && bFlag) + { + printk("Force Touch SCapCbTest in WaterProof On Mode: \n"); + + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("Force Touch SCap CB_Rx: \n"); + for (i = 0; bFlag && i < m_iForceTouchRx; i++) + { + + CBMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("Force Touch SCap CB_Tx: \n"); + for (i = 0; bFlag && i < m_iForceTouchTx; i++) + { + + CBMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Min[0][i+m_iForceTouchRx]; + CBMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_ON_Max[0][i+m_iForceTouchRx]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("Force Touch SCap CB in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = m_iForceTouchTx > m_iForceTouchRx?m_iForceTouchTx:m_iForceTouchRx; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT3C47_BasicThreshold.ForceTouch_SCapCBTest_SetWaterproof_OFF && bFlag) + { + printk("Force Touch SCapCbTest in WaterProof OFF Mode: \n"); + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("Force Touch SCap CB_Rx: \n"); + for (i = 0; bFlag && i < m_iForceTouchRx; i++) + { + + CBMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("Force Touch SCap CB_Tx: \n"); + for (i = 0; bFlag && i < m_iForceTouchTx; i++) + { + + + CBMin = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Min[0][i+m_iForceTouchRx]; + CBMax = g_stCfg_MCap_DetailThreshold.ForceTouch_SCapCbTest_OFF_Max[0][i+m_iForceTouchRx]; + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("Force Touch SCap CB in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = m_iForceTouchTx > m_iForceTouchRx?m_iForceTouchTx:m_iForceTouchRx; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + /*if(m_bV3TP) + { + ReCode = ReadReg( REG_MAPPING_SWITCH, &ucValue ); + if(ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (0 != ucValue ) + { + ReCode = WriteReg( REG_MAPPING_SWITCH, 0 ); + SysDelay(10); + if( ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + //Ö»ÓÐ×ÔÈݲŻáʹÓÃMappingÇ°µÄ£¬ËùÒԸòâÊÔÏî½áÊøÒÔºó£¬ÐèҪתµ½Mappingºó + ReCode = GetChannelNum(); + if(ReCode != ERROR_CODE_OK) + { + printk("\n GetChannelNum error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + }*/ + + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//Force Touch SCap CB Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//Force Touch SCap CB Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//Force Touch SCap CB Test is NG!\n"); + return ReCode; +} + + diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT3C47.h b/drivers/input/touchscreen/ft5435/lib/Test_FT3C47.h new file mode 100644 index 0000000000000..7d78ca30540de --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT3C47.h @@ -0,0 +1,34 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT3C47.h +* +* Author: Software Development Team, AE +* +* Created: 2015-12-02 +* +* Abstract: test item for FT3C47 +* +************************************************************************/ +#ifndef _TEST_FT3C47_H +#define _TEST_FT3C47_H + +#include "test_lib.h" + +boolean FT3C47_StartTest(void); +int FT3C47_get_test_data(char *pTestData); + +unsigned char FT3C47_TestItem_EnterFactoryMode(void); +unsigned char FT3C47_TestItem_RawDataTest(bool *bTestResult); + +unsigned char FT3C47_TestItem_SCapRawDataTest(bool *bTestResult); +unsigned char FT3C47_TestItem_SCapCbTest(bool *bTestResult); + +unsigned char FT3C47_TestItem_ForceTouch_SCapRawDataTest(bool *bTestResult); +unsigned char FT3C47_TestItem_ForceTouch_SCapCbTest(bool *bTestResult); + +boolean GetWaterproofMode(int iTestType, unsigned char ucChannelValue); + + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT5822.c b/drivers/input/touchscreen/ft5435/lib/Test_FT5822.c new file mode 100644 index 0000000000000..5e81159b0106a --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT5822.c @@ -0,0 +1,1833 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT5822.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test item for FT5822\FT5626\FT5726\FT5826B +* +************************************************************************/ + +/******************************************************************************* +* Included header files +*******************************************************************************/ +#include +#include +#include + +#include "Global.h" +#include "DetailThreshold.h" +#include "Test_FT5822.h" +#include "Config_FT5822.h" + + +/******************************************************************************* +* Private constant and macro definitions using #define +*******************************************************************************/ +#define IC_TEST_VERSION "Test version: V1.0.0--2015-07-30, (sync version of FT_MultipleTest: V2.7.0.3--2015-07-13)" + + +#define DEVIDE_MODE_ADDR 0x00 +#define REG_LINE_NUM 0x01 +#define REG_TX_NUM 0x02 +#define REG_RX_NUM 0x03 +#define REG_PATTERN_5422 0x53 +#define REG_MAPPING_SWITCH 0x54 +#define REG_TX_NOMAPPING_NUM 0x55 +#define REG_RX_NOMAPPING_NUM 0x56 +#define REG_NORMALIZE_TYPE 0x16 +#define REG_ScCbBuf0 0x4E +#define REG_ScWorkMode 0x44 +#define REG_ScCbAddrR 0x45 +#define REG_RawBuf0 0x36 +#define REG_WATER_CHANNEL_SELECT 0x09 + +#define REG_FREQUENCY 0x0A +#define REG_FIR 0XFB + +#define MIN_HOLE_LEVEL (-1) +#define MAX_HOLE_LEVEL 0x7F + +/******************************************************************************* +* Private enumerations, structures and unions using typedef +*******************************************************************************/ +enum WaterproofType +{ + WT_NeedProofOnTest, + WT_NeedProofOffTest, + WT_NeedTxOnVal, + WT_NeedRxOnVal, + WT_NeedTxOffVal, + WT_NeedRxOffVal, +}; +/******************************************************************************* +* Static variables +*******************************************************************************/ + +static int m_RawData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_iTempRawData[TX_NUM_MAX * RX_NUM_MAX] = {0}; +static unsigned char m_ucTempData[TX_NUM_MAX * RX_NUM_MAX*2] = {0}; +static bool m_bV3TP; +static int RxLinearity[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int TxLinearity[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; + + + +static char g_pStoreAllData[1024*80] = {0}; +static char *g_pTmpBuff; +static char *g_pStoreMsgArea; +static int g_lenStoreMsgArea; +static char *g_pMsgAreaLine2; +static int g_lenMsgAreaLine2; +static char *g_pStoreDataArea; +static int g_lenStoreDataArea; +static unsigned char m_ucTestItemCode; +static int m_iStartLine; +static int m_iTestDataCount; + +/******************************************************************************* +* Global variable or extern global variabls/functions +*******************************************************************************/ + + +/******************************************************************************* +* Static function prototypes +*******************************************************************************/ + +static int StartScan(void); +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer); +static unsigned char GetPanelRows(unsigned char *pPanelRows); +static unsigned char GetPanelCols(unsigned char *pPanelCols); +static unsigned char GetTxSC_CB(unsigned char index, unsigned char *pcbValue); + +static unsigned char GetRawData(void); +static unsigned char GetChannelNum(void); + +static void InitTest(void); +static void FinishTest(void); +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount); +static void InitStoreParamOfTestData(void); +static void MergeAllTestData(void); + +static void AllocateMemory(void); +static void FreeMemory(void); +static void ShowRawData(void); +static boolean GetTestCondition(int iTestType, unsigned char ucChannelValue); + +static unsigned char GetChannelNumNoMapping(void); +static unsigned char SwitchToNoMapping(void); + +/************************************************************************ +* Name: FT5822_StartTest +* Brief: Test entry. Determine which test item to test +* Input: none +* Output: none +* Return: Test Result, PASS or FAIL +***********************************************************************/ +boolean FT5822_StartTest() +{ + bool bTestResult = true; + bool bTempResult = 1; + unsigned char ReCode = 0; + unsigned char ucDevice = 0; + int iItemCount = 0; + + + InitTest(); + + + if (0 == g_TestItemNum) + bTestResult = false; + + for (iItemCount = 0; iItemCount < g_TestItemNum; iItemCount++) + { + m_ucTestItemCode = g_stTestItem[ucDevice][iItemCount].ItemCode; + + + if (Code_FT5822_ENTER_FACTORY_MODE == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5822_TestItem_EnterFactoryMode(); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + break; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + /*if(Code_FT5822_CHANNEL_NUM_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5822_TestItem_ChannelsTest(&bTempResult); + if(ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + } + }*/ + + + if (Code_FT5822_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5822_TestItem_RawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + + if (Code_FT5822_SCAP_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5822_TestItem_SCapCbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT5822_SCAP_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5822_TestItem_SCapRawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT5822_UNIFORMITY_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5822_TestItem_UniformityTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + } + + + FinishTest(); + + + return bTestResult; +} +/************************************************************************ +* Name: InitTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitTest(void) +{ + AllocateMemory(); + InitStoreParamOfTestData(); + printk("[focal] %s \n", IC_TEST_VERSION); +} +/************************************************************************ +* Name: FinishTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FinishTest(void) +{ + MergeAllTestData(); + FreeMemory(); +} +/************************************************************************ +* Name: FT5822_get_test_data +* Brief: get data of test result +* Input: none +* Output: pTestData, the returned buff +* Return: the length of test data. if length > 0, got data;else ERR. +***********************************************************************/ +int FT5822_get_test_data(char *pTestData) +{ + if (NULL == pTestData) + { + printk("[focal] %s pTestData == NULL \n", __func__); + return -EPERM; + } + memcpy(pTestData, g_pStoreAllData, (g_lenStoreMsgArea+g_lenStoreDataArea)); + return (g_lenStoreMsgArea+g_lenStoreDataArea); + + +} + +/************************************************************************ +* Name: FT5822_TestItem_EnterFactoryMode +* Brief: Check whether TP can enter Factory Mode, and do some thing +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5822_TestItem_EnterFactoryMode(void) +{ + unsigned char ReCode = ERROR_CODE_INVALID_PARAM; + int iRedo = 5; + int i ; + unsigned char chPattern = 0; + + SysDelay(150); + for (i = 1; i <= iRedo; i++) + { + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter factory mode...\n"); + if (i < iRedo) + { + SysDelay(50); + continue; + } + } + else + { + break; + } + + } + SysDelay(300); + + + if (ReCode != ERROR_CODE_OK) + { + return ReCode; + } + + ReCode = GetChannelNum(); + + ReCode = ReadReg(REG_PATTERN_5422, &chPattern); + if (chPattern == 1) + { + m_bV3TP = true; + } + else + { + m_bV3TP = false; + } + + return ReCode; +} +/************************************************************************ +* Name: FT5822_TestItem_RawDataTest +* Brief: TestItem: RawDataTest. Check if MCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5822_TestItem_RawDataTest(bool *bTestResult) +{ + unsigned char ReCode = 0; + bool btmpresult = true; + int RawDataMin; + int RawDataMax; + unsigned char ucFre; + unsigned char strSwitch = 0; + unsigned char OriginValue = 0xff; + int index = 0; + int iRow, iCol; + int iValue = 0; + + + printk("\n\n==============================Test Item: -------- Raw Data Test \n\n"); + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &strSwitch); + if (strSwitch != 0) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + } + + ReCode = ReadReg(REG_NORMALIZE_TYPE, &OriginValue); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + + + if (g_ScreenSetParam.isNormalize == Auto_Normalize) + { + if (OriginValue != 1) + { + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x01); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + + printk("\n=========Set Frequecy High\n"); + ReCode = WriteReg(0x0A, 0x81); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + + printk("\n=========FIR State: ON\n"); + ReCode = WriteReg(0xFB, 1); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + goto TEST_ERR; + } + + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + } + else + { + if (OriginValue != 0) + { + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x00); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + + ReCode = ReadReg(0x0A, &ucFre); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + + + if (g_stCfg_FT5822_BasicThreshold.RawDataTest_SetLowFreq) + { + printk("\n=========Set Frequecy Low\n"); + ReCode = WriteReg(0x0A, 0x80); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + + printk("\n=========FIR State: OFF\n"); + ReCode = WriteReg(0xFB, 0); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + SysDelay(100); + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + goto TEST_ERR; + } + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + } + + + if (g_stCfg_FT5822_BasicThreshold.RawDataTest_SetHighFreq) + { + + printk("\n=========Set Frequecy High\n"); + ReCode = WriteReg(0x0A, 0x81); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + + printk("\n=========FIR State: OFF\n"); + ReCode = WriteReg(0xFB, 0); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + SysDelay(100); + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 2); + } + + } + + + + ReCode = WriteReg(REG_NORMALIZE_TYPE, OriginValue); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + + if (m_bV3TP) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, strSwitch); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + return ReCode; + +} +/************************************************************************ +* Name: FT5822_TestItem_SCapRawDataTest +* Brief: TestItem: SCapRawDataTest. Check if SCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5822_TestItem_SCapRawDataTest(bool *bTestResult) +{ + int i = 0; + int RawDataMin = 0; + int RawDataMax = 0; + int Value = 0; + boolean bFlag = true; + unsigned char ReCode = 0; + boolean btmpresult = true; + int iMax = 0; + int iMin = 0; + int iAvg = 0; + int ByteNum = 0; + unsigned char wc_value = 0; + unsigned char ucValue = 0; + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: -------- Scap RawData Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + ReCode = SwitchToNoMapping(); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData! \n"); + goto TEST_ERR; + } + for (i = 0; i < 3; i++) + { + memset(m_iTempRawData, 0, sizeof(m_iTempRawData)); + + ByteNum = (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)*2; + ReCode = ReadRawData(0, 0xAC, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + memcpy(m_RawData[0+g_ScreenSetParam.iTxNum], m_iTempRawData, sizeof(int)*g_ScreenSetParam.iRxNum); + memcpy(m_RawData[1+g_ScreenSetParam.iTxNum], m_iTempRawData + g_ScreenSetParam.iRxNum, sizeof(int)*g_ScreenSetParam.iTxNum); + + ByteNum = (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)*2; + ReCode = ReadRawData(0, 0xAB, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + memcpy(m_RawData[2+g_ScreenSetParam.iTxNum], m_iTempRawData, sizeof(int)*g_ScreenSetParam.iRxNum); + memcpy(m_RawData[3+g_ScreenSetParam.iTxNum], m_iTempRawData + g_ScreenSetParam.iRxNum, sizeof(int)*g_ScreenSetParam.iTxNum); + } + + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_SetWaterproof_ON && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_ON_Min; + RawDataMax = g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_ON_Max; + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[1][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[1][i]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap RawData in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_SetWaterproof_OFF && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_OFF_Min; + RawDataMax = g_stCfg_FT5822_BasicThreshold.SCapRawDataTest_OFF_Max; + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[1][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[1][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap RawData in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &ucValue); + if (0 != ucValue) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + SysDelay(10); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + GetChannelNum(); + } + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//SCap RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//SCap RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + * bTestResult = false; + printk("\n\n//SCap RawData Test is NG!\n"); + return ReCode; +} + +/************************************************************************ +* Name: FT5822_TestItem_SCapCbTest +* Brief: TestItem: SCapCbTest. Check if SCAP Cb is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5822_TestItem_SCapCbTest(bool *bTestResult) +{ + int i, /* j, iOutNum, */index, Value, CBMin, CBMax; + boolean bFlag = true; + unsigned char ReCode; + boolean btmpresult = true; + int iMax, iMin, iAvg; + unsigned char wc_value = 0; + unsigned char ucValue = 0; + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: ----- Scap CB Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + bFlag = SwitchToNoMapping(); + if (bFlag) + { + printk("Failed to SwitchToNoMapping! \n"); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData! \n"); + goto TEST_ERR; + } + + + for (i = 0; i < 3; i++) + { + memset(m_RawData, 0, sizeof(m_RawData)); + memset(m_ucTempData, 0, sizeof(m_ucTempData)); + + ReCode = WriteReg(REG_ScWorkMode, 1); + ReCode = StartScan(); + ReCode = WriteReg(REG_ScCbAddrR, 0); + ReCode = GetTxSC_CB(g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum + 128, m_ucTempData); + for (index = 0; index < g_ScreenSetParam.iRxNum; ++index) + { + m_RawData[0 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index]; + } + for (index = 0; index < g_ScreenSetParam.iTxNum; ++index) + { + m_RawData[1 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index + g_ScreenSetParam.iRxNum]; + } + + ReCode = WriteReg(REG_ScWorkMode, 0); + ReCode = StartScan(); + ReCode = WriteReg(REG_ScCbAddrR, 0); + ReCode = GetTxSC_CB(g_ScreenSetParam.iRxNum + g_ScreenSetParam.iTxNum + 128, m_ucTempData); + for (index = 0; index < g_ScreenSetParam.iRxNum; ++index) + { + m_RawData[2 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index]; + } + for (index = 0; index < g_ScreenSetParam.iTxNum; ++index) + { + m_RawData[3 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index + g_ScreenSetParam.iRxNum]; + } + + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Get SCap CB!\n"); + } + } + + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT5822_BasicThreshold.SCapCbTest_SetWaterproof_ON && bFlag) + { + printk("SCapCbTest in WaterProof On Mode: \n"); + + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("SCap CB_Rx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("SCap CB_Tx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[1][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[1][i]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap CB in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT5822_BasicThreshold.SCapCbTest_SetWaterproof_OFF && bFlag) + { + printk("SCapCbTest in WaterProof OFF Mode: \n"); + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("SCap CB_Rx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("SCap CB_Tx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[1][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[1][i]; + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap CB in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &ucValue); + if (0 != ucValue) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + SysDelay(10); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + GetChannelNum(); + } + + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//SCap CB Test Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//SCap CB Test Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//SCap CB Test Test is NG!\n"); + return ReCode; +} + +/************************************************************************ +* Name: GetPanelRows(Same function name as FT_MultipleTest) +* Brief: Get row of TP +* Input: none +* Output: pPanelRows +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelRows(unsigned char *pPanelRows) +{ + return ReadReg(REG_TX_NUM, pPanelRows); +} + +/************************************************************************ +* Name: GetPanelCols(Same function name as FT_MultipleTest) +* Brief: get column of TP +* Input: none +* Output: pPanelCols +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelCols(unsigned char *pPanelCols) +{ + return ReadReg(REG_RX_NUM, pPanelCols); +} +/************************************************************************ +* Name: StartScan(Same function name as FT_MultipleTest) +* Brief: Scan TP, do it before read Raw Data +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static int StartScan(void) +{ + unsigned char RegVal = 0; + unsigned char times = 0; + const unsigned char MaxTimes = 20; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + RegVal |= 0x80; + ReCode = WriteReg(DEVIDE_MODE_ADDR, RegVal); + if (ReCode == ERROR_CODE_OK) + { + while(times++ < MaxTimes) + { + SysDelay(8); + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + if ((RegVal>>7) == 0) break; + } + else + { + break; + } + } + if (times < MaxTimes) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + } + return ReCode; + +} +/************************************************************************ +* Name: ReadRawData(Same function name as FT_MultipleTest) +* Brief: read Raw Data +* Input: Freq(No longer used, reserved), LineNum, ByteNum +* Output: pRevBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer) +{ + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + unsigned char I2C_wBuffer[3]; + int i, iReadNum; + unsigned short BytesNumInTestMode1 = 0; + + + + + iReadNum = ByteNum/342; + + if (0 != (ByteNum%342)) iReadNum++; + + if (ByteNum <= 342) + { + BytesNumInTestMode1 = ByteNum; + } + else + { + BytesNumInTestMode1 = 342; + } + + ReCode = WriteReg(REG_LINE_NUM, LineNum); + + + + I2C_wBuffer[0] = REG_RawBuf0; + if (ReCode == ERROR_CODE_OK) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, m_ucTempData, BytesNumInTestMode1); + } + + for (i = 1; i < iReadNum; i++) + { + if (ReCode != ERROR_CODE_OK) break; + + if (i == iReadNum-1) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, m_ucTempData+342*i, ByteNum-342*i); + } + else + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, m_ucTempData+342*i, 342); + } + + } + + if (ReCode == ERROR_CODE_OK) + { + for (i = 0; i < (ByteNum>>1); i++) + { + pRevBuffer[i] = (m_ucTempData[i<<1]<<8)+m_ucTempData[(i<<1)+1]; + + } + } + + return ReCode; + +} +/************************************************************************ +* Name: GetTxSC_CB(Same function name as FT_MultipleTest) +* Brief: get CB of Tx SCap +* Input: index +* Output: pcbValue +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char GetTxSC_CB(unsigned char index, unsigned char *pcbValue) +{ + unsigned char ReCode = ERROR_CODE_OK; + unsigned char wBuffer[4]; + + if (index < 128) + { + *pcbValue = 0; + WriteReg(REG_ScCbAddrR, index); + ReCode = ReadReg(REG_ScCbBuf0, pcbValue); + } + else + { + WriteReg(REG_ScCbAddrR, 0); + wBuffer[0] = REG_ScCbBuf0; + ReCode = Comm_Base_IIC_IO(wBuffer, 1, pcbValue, index-128); + + } + + return ReCode; +} + + + +/************************************************************************ +* Name: AllocateMemory +* Brief: Allocate pointer Memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void AllocateMemory(void) +{ + + g_pStoreMsgArea = NULL; + if (NULL == g_pStoreMsgArea) + g_pStoreMsgArea = kmalloc(1024*8, GFP_ATOMIC); + g_pMsgAreaLine2 = NULL; + if (NULL == g_pMsgAreaLine2) + g_pMsgAreaLine2 = kmalloc(1024*8, GFP_ATOMIC); + g_pStoreDataArea = NULL; + if (NULL == g_pStoreDataArea) + g_pStoreDataArea = kmalloc(1024*80, GFP_ATOMIC); + /*g_pStoreAllData =NULL; + if(NULL == g_pStoreAllData) + g_pStoreAllData = kmalloc(1024*8, GFP_ATOMIC); + g_pTmpBuff =NULL;*/ + if (NULL == g_pTmpBuff) + g_pTmpBuff = kmalloc(1024*16, GFP_ATOMIC); + +} +/************************************************************************ +* Name: FreeMemory +* Brief: Release pointer memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FreeMemory(void) +{ + + if (NULL != g_pStoreMsgArea) + kfree(g_pStoreMsgArea); + + if (NULL != g_pMsgAreaLine2) + kfree(g_pMsgAreaLine2); + + if (NULL != g_pStoreDataArea) + kfree(g_pStoreDataArea); + + /*if(NULL == g_pStoreAllData) + kfree(g_pStoreAllData);*/ + + if (NULL != g_pTmpBuff) + kfree(g_pTmpBuff); +} + +/************************************************************************ +* Name: InitStoreParamOfTestData +* Brief: Init store param of test data +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitStoreParamOfTestData(void) +{ + + + g_lenStoreMsgArea = 0; + + g_lenStoreMsgArea += sprintf(g_pStoreMsgArea, "ECC, 85, 170, IC Name, %s, IC Code, %x\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + + + + g_lenMsgAreaLine2 = 0; + + + + g_lenStoreDataArea = 0; + m_iStartLine = 11; + + m_iTestDataCount = 0; +} +/************************************************************************ +* Name: MergeAllTestData +* Brief: Merge All Data of test result +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void MergeAllTestData(void) +{ + int iLen = 0; + + + iLen = sprintf(g_pTmpBuff, "TestItem, %d, ", m_iTestDataCount); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pMsgAreaLine2, g_lenMsgAreaLine2); + g_lenStoreMsgArea+=g_lenMsgAreaLine2; + + + iLen = sprintf(g_pTmpBuff, "\n\n\n\n\n\n\n\n\n"); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreAllData, g_pStoreMsgArea, g_lenStoreMsgArea); + + + if (0 != g_lenStoreDataArea) + { + memcpy(g_pStoreAllData+g_lenStoreMsgArea, g_pStoreDataArea, g_lenStoreDataArea); + } + + printk("[focal] %s lenStoreMsgArea=%d, lenStoreDataArea = %d\n", __func__, g_lenStoreMsgArea, g_lenStoreDataArea); +} + + +/************************************************************************ +* Name: Save_Test_Data +* Brief: Storage format of test data +* Input: int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount +* Output: none +* Return: none +***********************************************************************/ +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount) +{ + int iLen = 0; + int i = 0, j = 0; + + + iLen = sprintf(g_pTmpBuff, "NA, %d, %d, %d, %d, %d, ", \ + m_ucTestItemCode, Row, Col, m_iStartLine, ItemCount); + memcpy(g_pMsgAreaLine2+g_lenMsgAreaLine2, g_pTmpBuff, iLen); + g_lenMsgAreaLine2 += iLen; + + m_iStartLine += Row; + m_iTestDataCount++; + + + for (i = 0+iArrayIndex; i < Row+iArrayIndex; i++) + { + for (j = 0; j < Col; j++) + { + if (j == (Col -1)) + iLen = sprintf(g_pTmpBuff, "%d, \n", iData[i][j]); + else + iLen = sprintf(g_pTmpBuff, "%d, ", iData[i][j]); + + memcpy(g_pStoreDataArea+g_lenStoreDataArea, g_pTmpBuff, iLen); + g_lenStoreDataArea += iLen; + } + } + +} + +/************************************************************************ +* Name: GetChannelNum +* Brief: Get Channel Num(Tx and Rx) +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNum(void) +{ + unsigned char ReCode; + unsigned char rBuffer[1]; + + + ReCode = GetPanelRows(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iTxNum = rBuffer[0]; + if (g_ScreenSetParam.iTxNum+4 > g_ScreenSetParam.iUsedMaxTxNum) + { + printk("Failed to get Tx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iTxNum, g_ScreenSetParam.iUsedMaxTxNum); + return ERROR_CODE_INVALID_PARAM; + } + + } + else + { + printk("Failed to get Tx number\n"); + } + + + + ReCode = GetPanelCols(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iRxNum = rBuffer[0]; + if (g_ScreenSetParam.iRxNum > g_ScreenSetParam.iUsedMaxRxNum) + { + printk("Failed to get Rx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iRxNum, g_ScreenSetParam.iUsedMaxRxNum); + return ERROR_CODE_INVALID_PARAM; + } + + } + else + { + printk("Failed to get Rx number\n"); + } + + return ReCode; + +} +/************************************************************************ +* Name: GetRawData +* Brief: Get Raw Data of MCAP +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetRawData(void) +{ + unsigned char ReCode = ERROR_CODE_OK; + int iRow = 0; + int iCol = 0; + + + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter Factory Mode...\n"); + return ReCode; + } + + + + if (0 == (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)) + { + ReCode = GetChannelNum(); + if (ERROR_CODE_OK != ReCode) + { + printk("Error Channel Num...\n"); + return ERROR_CODE_INVALID_PARAM; + } + } + + + printk("Start Scan ...\n"); + ReCode = StartScan(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Scan ...\n"); + return ReCode; + } + + + memset(m_RawData, 0, sizeof(m_RawData)); + ReCode = ReadRawData(1, 0xAA, (g_ScreenSetParam.iTxNum * g_ScreenSetParam.iRxNum)*2, m_iTempRawData); + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + m_RawData[iRow][iCol] = m_iTempRawData[iRow*g_ScreenSetParam.iRxNum + iCol]; + } + } + return ReCode; +} +/************************************************************************ +* Name: ShowRawData +* Brief: Show RawData +* Input: none +* Output: none +* Return: none. +***********************************************************************/ +static void ShowRawData(void) +{ + int iRow, iCol; + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + printk("\nTx%2d: ", iRow+1); + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + printk("%5d ", m_RawData[iRow][iCol]); + } + } +} + +/************************************************************************ +* Name: GetChannelNumNoMapping +* Brief: get Tx&Rx num from other Register +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNumNoMapping(void) +{ + unsigned char ReCode; + unsigned char rBuffer[1]; + + + printk("Get Tx Num...\n"); + ReCode = ReadReg(REG_TX_NOMAPPING_NUM, rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iTxNum = rBuffer[0]; + } + else + { + printk("Failed to get Tx number\n"); + } + + + printk("Get Rx Num...\n"); + ReCode = ReadReg(REG_RX_NOMAPPING_NUM, rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iRxNum = rBuffer[0]; + } + else + { + printk("Failed to get Rx number\n"); + } + + return ReCode; +} +/************************************************************************ +* Name: SwitchToNoMapping +* Brief: If it is V3 pattern, Get Tx/Rx Num again +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char SwitchToNoMapping(void) +{ + unsigned char chPattern = -1; + unsigned char ReCode = ERROR_CODE_OK; + unsigned char RegData = -1; + ReCode = ReadReg(REG_PATTERN_5422, &chPattern); + + if (1 == chPattern) + { + RegData = -1; + ReCode = ReadReg(REG_MAPPING_SWITCH, &RegData); + if (1 != RegData) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 1); + focal_msleep(20); + GetChannelNumNoMapping(); + } + } + + if (ReCode != ERROR_CODE_OK) + { + printk("Switch To NoMapping Failed!\n"); + } + return ReCode; +} +/************************************************************************ +* Name: GetTestCondition +* Brief: Check whether Rx or TX need to test, in Waterproof ON/OFF Mode. +* Input: none +* Output: none +* Return: true: need to test; false: Not tested. +***********************************************************************/ +static boolean GetTestCondition(int iTestType, unsigned char ucChannelValue) +{ + boolean bIsNeeded = false; + switch(iTestType) + { + case WT_NeedProofOnTest: + bIsNeeded = !(ucChannelValue & 0x20); + break; + case WT_NeedProofOffTest + bIsNeeded = !(ucChannelValue & 0x80); + break; + case WT_NeedTxOnVal: + bIsNeeded = !(ucChannelValue & 0x40) || !(ucChannelValue & 0x04); + break; + case WT_NeedRxOnVal: + bIsNeeded = !(ucChannelValue & 0x40) || (ucChannelValue & 0x04); + break; + case WT_NeedTxOffVal: + bIsNeeded = (0x00 == (ucChannelValue & 0x03)) || (0x02 == (ucChannelValue & 0x03)); + break; + case WT_NeedRxOffVal: + bIsNeeded = (0x01 == (ucChannelValue & 0x03)) || (0x02 == (ucChannelValue & 0x03)); + break; + default:break; + } + return bIsNeeded; +} + + +unsigned char FT5822_TestItem_UniformityTest(bool *bTestResult) +{ + unsigned char ReCode = ERROR_CODE_OK; + bool btmpresult = true; + unsigned char ucFre = 0; + unsigned char FirValue = 0; + + + + int iMin = 100000; + int iMax = -100000; + int iDeviation = 0; + int iRow = 0; + int iCol = 0; + int iUniform = 0; + int index = 0; + + printk("\n\n==============================Test Item: --------RawData Uniformity Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_END; + } + + ReCode = ReadReg(REG_FREQUENCY, &ucFre); + if (ReCode != ERROR_CODE_OK) + { + goto TEST_END; + } + + ReCode = WriteReg(REG_FREQUENCY, 0x81); + SysDelay(100); + if (ReCode != ERROR_CODE_OK) + { + goto TEST_END; + } + + ReCode = ReadReg(REG_FIR, &FirValue); + if (ReCode != ERROR_CODE_OK) + { + goto TEST_END; + } + + + ReCode = WriteReg(REG_FIR, 0); + SysDelay(100); + if (ReCode != ERROR_CODE_OK) + { + goto TEST_END; + } + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (g_stCfg_FT5822_BasicThreshold.Uniformity_CheckTx) + { + printk("\n\n=========Check Tx Linearity \n\n"); + + memset(TxLinearity, 0, sizeof(TxLinearity)); + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; ++iRow) + { + for (iCol = 1; iCol < g_ScreenSetParam.iRxNum; ++iCol) + { + iDeviation = focal_abs(m_RawData[iRow][iCol] - m_RawData[iRow][iCol-1]); + iMax = m_RawData[iRow][iCol] > m_RawData[iRow][iCol-1] ?m_RawData[iRow][iCol]:m_RawData[iRow][iCol-1] ; + iMax = iMax ? iMax : 1; + TxLinearity[iRow][iCol] = 100 * iDeviation / iMax; + } + } + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; ++iRow) + { + for (iCol = 1; iCol < g_ScreenSetParam.iRxNum; ++iCol) + { + if (0 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol]) continue; + if (2 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol]) continue; + + if (TxLinearity[iRow][iCol] < MIN_HOLE_LEVEL || + TxLinearity[iRow][iCol] > g_stCfg_FT5822_BasicThreshold.Uniformity_Tx_Hole) + { + printk("Tx Linearity Out Of Range, TX=%d, RX=%d, TxLinearity=%d, Tx_Hole=%d.\n", iCol, iRow, TxLinearity[iRow][iCol], g_stCfg_FT5822_BasicThreshold.Uniformity_Tx_Hole); + + btmpresult = false; + } + } + } + + Save_Test_Data(TxLinearity, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + + } + + if (g_stCfg_FT5822_BasicThreshold.Uniformity_CheckRx) + { + printk("\n\n=========Check Rx Linearity \n\n"); + + for (iRow = 1; iRow < g_ScreenSetParam.iTxNum; ++iRow) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; ++iCol) + { + iDeviation = focal_abs(m_RawData[iRow][iCol] - m_RawData[iRow-1][iCol]); + iMax = m_RawData[iRow][iCol] > m_RawData[iRow-1][iCol] ?m_RawData[iRow][iCol] : m_RawData[iRow-1][iCol] ; + iMax = iMax ? iMax : 1; + RxLinearity[iRow][iCol] = 100 * iDeviation / iMax; + } + } + + for (iRow = 1; iRow < g_ScreenSetParam.iTxNum; ++iRow) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; ++iCol) + { + if (0 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol]) continue; + if (2 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol]) continue; + + if (RxLinearity[iRow][iCol] < MIN_HOLE_LEVEL || + RxLinearity[iRow][iCol] > g_stCfg_FT5822_BasicThreshold.Uniformity_Rx_Hole) + { + printk("Rx Linearity Out Of Range, TX=%d, RX=%d, RxLinearity=%d, Rx_Hole=%d.\n", iCol, iRow, RxLinearity[iRow][iCol], g_stCfg_FT5822_BasicThreshold.Uniformity_Rx_Hole); + + btmpresult = false; + } + } + } + + Save_Test_Data(RxLinearity, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 2); + + } + + if (g_stCfg_FT5822_BasicThreshold.Uniformity_CheckMinMax) + { + printk("\n\n=========Check Min/Max \n\n"); + iMin = 100000; + iMax = -100000; + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; ++iRow) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; ++iCol) + { + if (0 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol]){ + continue; + } + if (2 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol]){ + continue; + } + if (iMin > m_RawData[iRow][iCol]) iMin = m_RawData[iRow][iCol] ; + if (iMax < m_RawData[iRow][iCol]) iMax = m_RawData[iRow][iCol] ; + } + } + iMax = !iMax ? 1 : iMax; + iUniform = 100 * focal_abs(iMin) / focal_abs(iMax); + + printk("\n\n Min: %d, Max: %d, , Get Value of Min/Max: %d.\n", iMin, iMax, iUniform); + + if (iUniform < g_stCfg_FT5822_BasicThreshold.Uniformity_MinMax_Hole) + { + btmpresult = false; + printk("\n\n MinMax Out Of Range, Set Value: %d.\n", g_stCfg_FT5822_BasicThreshold.Uniformity_MinMax_Hole); + } + } + + ReCode = WriteReg(REG_FREQUENCY, ucFre); + SysDelay(100); + if (ReCode != ERROR_CODE_OK) + { + goto TEST_END; + } + ReCode = WriteReg(REG_FIR, FirValue); + SysDelay(100); + if (ReCode != ERROR_CODE_OK) + { + goto TEST_END; + } + + +TEST_END: + + if (btmpresult && ReCode == ERROR_CODE_OK) + { + *bTestResult = true; + printk("\n\n\n\n//Uniformity Test is OK!\n\n"); + } + else + { + *bTestResult = false; + printk("\n\n\n\n//Uniformity Test is NG!\n\n"); + } + return ReCode; +} + diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT5822.h b/drivers/input/touchscreen/ft5435/lib/Test_FT5822.h new file mode 100644 index 0000000000000..62e99f4da5a98 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT5822.h @@ -0,0 +1,33 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT5822.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-23 +* +* Abstract: test item for FT5822\FT5626\FT5726\FT5826B +* +************************************************************************/ +#ifndef _TEST_FT5822_H +#define _TEST_FT5822_H + +#include "test_lib.h" + +boolean FT5822_StartTest(void); +int FT5822_get_test_data(char *pTestData); + +unsigned char FT5822_TestItem_EnterFactoryMode(void); +unsigned char FT5822_TestItem_RawDataTest(bool *bTestResult); + +unsigned char FT5822_TestItem_SCapRawDataTest(bool *bTestResult); +unsigned char FT5822_TestItem_SCapCbTest(bool *bTestResult); + +unsigned char FT5822_TestItem_UniformityTest(bool *bTestResult); + +boolean GetWaterproofMode(int iTestType, unsigned char ucChannelValue); + + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT5X46.c b/drivers/input/touchscreen/ft5435/lib/Test_FT5X46.c new file mode 100644 index 0000000000000..f9b49cf535597 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT5X46.c @@ -0,0 +1,1869 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT5X46.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test item for FT5X46\FT5X46i\FT5526\FT3X17\FT5436\FT3X27\FT5526i\FT5416\FT5426\FT5435 +* +************************************************************************/ + +/******************************************************************************* +* Included header files +*******************************************************************************/ +#include +#include +#include + +#include "Global.h" +#include "DetailThreshold.h" +#include "Test_FT5X46.h" +#include "Config_FT5X46.h" + + +/******************************************************************************* +* Private constant and macro definitions using #define +*******************************************************************************/ +#define IC_TEST_VERSION "Test version: V1.1.0--2015-10-22, (sync version of FT_MultipleTest: V2.7.0.3--2015-07-13)" + + +#define DEVIDE_MODE_ADDR 0x00 +#define REG_LINE_NUM 0x01 +#define REG_TX_NUM 0x02 +#define REG_RX_NUM 0x03 +#define REG_PATTERN_5422 0x53 +#define REG_MAPPING_SWITCH 0x54 +#define REG_TX_NOMAPPING_NUM 0x55 +#define REG_RX_NOMAPPING_NUM 0x56 +#define REG_NORMALIZE_TYPE 0x16 +#define REG_ScCbBuf0 0x4E +#define REG_ScWorkMode 0x44 +#define REG_ScCbAddrR 0x45 +#define REG_RawBuf0 0x36 +#define REG_WATER_CHANNEL_SELECT 0x09 + +/******************************************************************************* +* Private enumerations, structures and unions using typedef +*******************************************************************************/ +enum WaterproofType +{ + WT_NeedProofOnTest, + WT_NeedProofOffTest, + WT_NeedTxOnVal, + WT_NeedRxOnVal, + WT_NeedTxOffVal, + WT_NeedRxOffVal, +}; +/******************************************************************************* +* Static variables +*******************************************************************************/ + +static int m_RawData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_iTempRawData[TX_NUM_MAX * RX_NUM_MAX] = {0}; +static unsigned char m_ucTempData[TX_NUM_MAX * RX_NUM_MAX*2] = {0}; +static bool m_bV3TP; + + +static char g_pStoreAllData[1024*80] = {0}; +static char *g_pTmpBuff; +static char *g_pStoreMsgArea; +static int g_lenStoreMsgArea; +static char *g_pMsgAreaLine2; +static int g_lenMsgAreaLine2; +static char *g_pStoreDataArea; +static int g_lenStoreDataArea; +static unsigned char m_ucTestItemCode; +static int m_iStartLine; +static int m_iTestDataCount; + +/******************************************************************************* +* Global variable or extern global variabls/functions +*******************************************************************************/ + + +/******************************************************************************* +* Static function prototypes +*******************************************************************************/ + +static int StartScan(void); +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer); +static unsigned char GetPanelRows(unsigned char *pPanelRows); +static unsigned char GetPanelCols(unsigned char *pPanelCols); +static unsigned char GetTxSC_CB(unsigned char index, unsigned char *pcbValue); + +static unsigned char GetRawData(void); +static unsigned char GetChannelNum(void); + +static int InitTest(void); +static void FinishTest(void); +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount); +static void InitStoreParamOfTestData(void); +static void MergeAllTestData(void); + +static int AllocateMemory(void); + +static void ShowRawData(void); +static boolean GetTestCondition(int iTestType, unsigned char ucChannelValue); + +static unsigned char GetChannelNumNoMapping(void); +static unsigned char SwitchToNoMapping(void); + + +/************************************************************************ +* Name: FT5X46_StartTest +* Brief: Test entry. Determine which test item to test +* Input: none +* Output: none +* Return: Test Result, PASS or FAIL +***********************************************************************/ +boolean FT5X46_StartTest() +{ + bool bTestResult = true; + bool bTempResult = 1; + unsigned char ReCode = 0; + unsigned char ucDevice = 0; + int iItemCount = 0; + + + if (InitTest() < 0) + { + bTestResult = false; + return bTestResult; + } + + + if (0 == g_TestItemNum) + bTestResult = false; + + for (iItemCount = 0; iItemCount < g_TestItemNum; iItemCount++) + { + m_ucTestItemCode = g_stTestItem[ucDevice][iItemCount].ItemCode; + + + if (Code_FT5X22_ENTER_FACTORY_MODE == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5X46_TestItem_EnterFactoryMode(); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + break; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + /*if(Code_FT5X22_CHANNEL_NUM_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5X46_TestItem_ChannelsTest(&bTempResult); + if(ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + } + }*/ + + + if (Code_FT5X22_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5X46_TestItem_RawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + + if (Code_FT5X22_SCAP_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5X46_TestItem_SCapCbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT5X22_SCAP_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT5X46_TestItem_SCapRawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + } + + + FinishTest(); + + + return bTestResult; +} +/************************************************************************ +* Name: InitTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static int InitTest(void) +{ + if (AllocateMemory() < 0) + { + return -EPERM; + } + InitStoreParamOfTestData(); + printk("[focal] %s \n", IC_TEST_VERSION); + return 1; +} +/************************************************************************ +* Name: FinishTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FinishTest(void) +{ + MergeAllTestData(); + +} +/************************************************************************ +* Name: FT5X46_get_test_data +* Brief: get data of test result +* Input: none +* Output: pTestData, the returned buff +* Return: the length of test data. if length > 0, got data;else ERR. +***********************************************************************/ +int FT5X46_get_test_data(char *pTestData) +{ + if (NULL == pTestData) + { + printk("[focal] %s pTestData == NULL \n", __func__); + return -EPERM; + } + memcpy(pTestData, g_pStoreAllData, (g_lenStoreMsgArea+g_lenStoreDataArea)); + return (g_lenStoreMsgArea+g_lenStoreDataArea); +} + +/************************************************************************ +* Name: FT5X46_TestItem_EnterFactoryMode +* Brief: Check whether TP can enter Factory Mode, and do some thing +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5X46_TestItem_EnterFactoryMode(void) +{ + unsigned char ReCode = ERROR_CODE_INVALID_PARAM; + int iRedo = 5; + int i ; + unsigned char chPattern = 0; + + SysDelay(150); + for (i = 1; i <= iRedo; i++) + { + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter factory mode...\n"); + if (i < iRedo) + { + SysDelay(50); + continue; + } + } + else + { + printk("Succeed to Enter factory mode...\n"); + break; + } + + } + SysDelay(300); + + + if (ReCode != ERROR_CODE_OK) + { + return ReCode; + } + + ReCode = GetChannelNum(); + + ReCode = ReadReg(REG_PATTERN_5422, &chPattern); + if (chPattern == 1) + { + m_bV3TP = true; + } + else + { + m_bV3TP = false; + } + + return ReCode; +} +/************************************************************************ +* Name: FT5X46_TestItem_RawDataTest +* Brief: TestItem: RawDataTest. Check if MCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5X46_TestItem_RawDataTest(bool *bTestResult) +{ + unsigned char ReCode = 0; + bool btmpresult = true; + int RawDataMin; + int RawDataMax; + unsigned char ucFre; + unsigned char strSwitch = 0; + unsigned char OriginValue = 0xff; + int index = 0; + int iRow, iCol; + int iValue = 0; + + + printk("\n\n==============================Test Item: -------- Raw Data Test \n\n"); + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &strSwitch); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (strSwitch != 0) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Write REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + } + + ReCode = ReadReg(REG_NORMALIZE_TYPE, &OriginValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (g_ScreenSetParam.isNormalize == Auto_Normalize) + { + if (OriginValue != 1) + { + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x01); + if (ReCode != ERROR_CODE_OK) + { + printk("\n write REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + printk("\n=========Set Frequecy High\n"); + ReCode = WriteReg(0x0A, 0x81); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Set Frequecy High error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + printk("\n=========FIR State: ON\n"); + ReCode = WriteReg(0xFB, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("\n FIR State: ON error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + goto TEST_ERR; + } + + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + } + else + { + if (OriginValue != 0) + { + ReCode = WriteReg(REG_NORMALIZE_TYPE, 0x00); + if (ReCode != ERROR_CODE_OK) + { + printk("\n write REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + ReCode = ReadReg(0x0A, &ucFre); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read frequency error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + if (g_stCfg_FT5X22_BasicThreshold.RawDataTest_SetLowFreq) + { + printk("\n=========Set Frequecy Low\n"); + ReCode = WriteReg(0x0A, 0x80); + if (ReCode != ERROR_CODE_OK) + { + printk("\n write frequency error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + printk("\n=========FIR State: OFF\n"); + ReCode = WriteReg(0xFB, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("\n FIR State: OFF error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + SysDelay(100); + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + goto TEST_ERR; + } + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 1); + } + + + if (g_stCfg_FT5X22_BasicThreshold.RawDataTest_SetHighFreq) + { + + printk("\n=========Set Frequecy High\n"); + ReCode = WriteReg(0x0A, 0x81); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Set Frequecy High error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + printk("\n=========FIR State: OFF\n"); + ReCode = WriteReg(0xFB, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("\n FIR State: OFF error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + SysDelay(100); + + for (index = 0; index < 3; ++index) + { + ReCode = GetRawData(); + } + + if (ReCode != ERROR_CODE_OK) + { + printk("\nGet Rawdata failed, Error Code: 0x%x", ReCode); + if (ReCode != ERROR_CODE_OK)goto TEST_ERR; + } + ShowRawData(); + + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_High_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + + Save_Test_Data(m_RawData, 0, g_ScreenSetParam.iTxNum, g_ScreenSetParam.iRxNum, 2); + } + + } + + + + ReCode = WriteReg(REG_NORMALIZE_TYPE, OriginValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Write REG_NORMALIZE_TYPE error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (m_bV3TP) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, strSwitch); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Write REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + return ReCode; + +} +/************************************************************************ +* Name: FT5X46_TestItem_SCapRawDataTest +* Brief: TestItem: SCapRawDataTest. Check if SCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5X46_TestItem_SCapRawDataTest(bool *bTestResult) +{ + int i = 0; + int RawDataMin = 0; + int RawDataMax = 0; + int Value = 0; + boolean bFlag = true; + unsigned char ReCode = 0; + boolean btmpresult = true; + int iMax = 0; + int iMin = 0; + int iAvg = 0; + int ByteNum = 0; + unsigned char wc_value = 0; + unsigned char ucValue = 0; + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: -------- Scap RawData Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to read REG_WATER_CHANNEL_SELECT. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = SwitchToNoMapping(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to SwitchToNoMapping. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData! \n"); + goto TEST_ERR; + } + for (i = 0; i < 3; i++) + { + memset(m_iTempRawData, 0, sizeof(m_iTempRawData)); + + ByteNum = (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)*2; + ReCode = ReadRawData(0, 0xAC, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to ReadRawData water! \n"); + goto TEST_ERR; + } + + memcpy(m_RawData[0+g_ScreenSetParam.iTxNum], m_iTempRawData, sizeof(int)*g_ScreenSetParam.iRxNum); + memcpy(m_RawData[1+g_ScreenSetParam.iTxNum], m_iTempRawData + g_ScreenSetParam.iRxNum, sizeof(int)*g_ScreenSetParam.iTxNum); + + ByteNum = (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)*2; + ReCode = ReadRawData(0, 0xAB, ByteNum, m_iTempRawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to ReadRawData no water! \n"); + goto TEST_ERR; + } + memcpy(m_RawData[2+g_ScreenSetParam.iTxNum], m_iTempRawData, sizeof(int)*g_ScreenSetParam.iRxNum); + memcpy(m_RawData[3+g_ScreenSetParam.iTxNum], m_iTempRawData + g_ScreenSetParam.iRxNum, sizeof(int)*g_ScreenSetParam.iTxNum); + } + + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_SetWaterproof_ON && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_ON_Min; + RawDataMax = g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_ON_Max; + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-ON:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Min[1][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_ON_Max[1][i]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap RawData in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_SetWaterproof_OFF && bFlag) + { + iCount = 0; + RawDataMin = g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_OFF_Min; + RawDataMax = g_stCfg_FT5X22_BasicThreshold.SCapRawDataTest_OFF_Max; + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("Judge Rx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[0][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("Judge Tx in Waterproof-OFF:\n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + RawDataMin = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Min[1][i]; + RawDataMax = g_stCfg_MCap_DetailThreshold.SCapRawDataTest_OFF_Max[1][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > RawDataMax || Value < RawDataMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, RawDataMin, RawDataMax); + } + iCount++; + } + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap RawData in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &ucValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (0 != ucValue) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + SysDelay(10); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + ReCode = GetChannelNum(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n GetChannelNum error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//SCap RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//SCap RawData Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + * bTestResult = false; + printk("\n\n//SCap RawData Test is NG!\n"); + return ReCode; +} + +/************************************************************************ +* Name: FT5X46_TestItem_SCapCbTest +* Brief: TestItem: SCapCbTest. Check if SCAP Cb is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT5X46_TestItem_SCapCbTest(bool *bTestResult) +{ + int i, /* j, iOutNum, */index, Value, CBMin, CBMax; + boolean bFlag = true; + unsigned char ReCode; + boolean btmpresult = true; + int iMax, iMin, iAvg; + unsigned char wc_value = 0; + unsigned char ucValue = 0; + int iCount = 0; + int ibiggerValue = 0; + + printk("\n\n==============================Test Item: ----- Scap CB Test \n\n"); + + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n\n// Failed to Enter factory Mode. Error Code: %d", ReCode); + goto TEST_ERR; + } + + + ReCode = ReadReg(REG_WATER_CHANNEL_SELECT, &wc_value); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_WATER_CHANNEL_SELECT error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + + bFlag = SwitchToNoMapping(); + if (bFlag) + { + printk("Failed to SwitchToNoMapping! ReCode = %d. \n", ReCode); + goto TEST_ERR; + } + + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Scan SCap RawData!ReCode = %d. \n", ReCode); + goto TEST_ERR; + } + + + for (i = 0; i < 3; i++) + { + memset(m_RawData, 0, sizeof(m_RawData)); + memset(m_ucTempData, 0, sizeof(m_ucTempData)); + + ReCode = WriteReg(REG_ScWorkMode, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("Get REG_ScWorkMode Failed!\n"); + goto TEST_ERR; + } + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("StartScan Failed!\n"); + goto TEST_ERR; + } + + ReCode = WriteReg(REG_ScCbAddrR, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Write REG_ScCbAddrR Failed!\n"); + goto TEST_ERR; + } + + ReCode = GetTxSC_CB(g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum + 128, m_ucTempData); + if (ReCode != ERROR_CODE_OK) + { + printk("GetTxSC_CB Failed!\n"); + goto TEST_ERR; + } + + for (index = 0; index < g_ScreenSetParam.iRxNum; ++index) + { + m_RawData[0 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index]; + } + for (index = 0; index < g_ScreenSetParam.iTxNum; ++index) + { + m_RawData[1 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index + g_ScreenSetParam.iRxNum]; + } + + ReCode = WriteReg(REG_ScWorkMode, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Get REG_ScWorkMode Failed!\n"); + goto TEST_ERR; + } + + ReCode = StartScan(); + if (ReCode != ERROR_CODE_OK) + { + printk("StartScan Failed!\n"); + goto TEST_ERR; + } + + ReCode = WriteReg(REG_ScCbAddrR, 0); + if (ReCode != ERROR_CODE_OK) + { + printk("Write REG_ScCbAddrR Failed!\n"); + goto TEST_ERR; + } + + ReCode = GetTxSC_CB(g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum + 128, m_ucTempData); + if (ReCode != ERROR_CODE_OK) + { + printk("GetTxSC_CB Failed!\n"); + goto TEST_ERR; + } + for (index = 0; index < g_ScreenSetParam.iRxNum; ++index) + { + m_RawData[2 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index]; + } + for (index = 0; index < g_ScreenSetParam.iTxNum; ++index) + { + m_RawData[3 + g_ScreenSetParam.iTxNum][index] = m_ucTempData[index + g_ScreenSetParam.iRxNum]; + } + + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Get SCap CB!\n"); + } + } + + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + + + bFlag = GetTestCondition(WT_NeedProofOnTest, wc_value); + if (g_stCfg_FT5X22_BasicThreshold.SCapCbTest_SetWaterproof_ON && bFlag) + { + printk("SCapCbTest in WaterProof On Mode: \n"); + + iMax = -m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[0+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOnVal, wc_value); + if (bFlag) + printk("SCap CB_Rx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[0][i]; + Value = m_RawData[0+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOnVal, wc_value); + if (bFlag) + printk("SCap CB_Tx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Min[1][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_ON_Max[1][i]; + Value = m_RawData[1+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap CB in Waterproof-ON, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+0, 2, ibiggerValue, 1); + } + + bFlag = GetTestCondition(WT_NeedProofOffTest, wc_value); + if (g_stCfg_FT5X22_BasicThreshold.SCapCbTest_SetWaterproof_OFF && bFlag) + { + printk("SCapCbTest in WaterProof OFF Mode: \n"); + iMax = -m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iMin = 2 * m_RawData[2+g_ScreenSetParam.iTxNum][0]; + iAvg = 0; + Value = 0; + iCount = 0; + + + bFlag = GetTestCondition(WT_NeedRxOffVal, wc_value); + if (bFlag) + printk("SCap CB_Rx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iRxNum; i++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[0][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[0][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[0][i]; + Value = m_RawData[2+g_ScreenSetParam.iTxNum][i]; + iAvg += Value; + + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + + bFlag = GetTestCondition(WT_NeedTxOffVal, wc_value); + if (bFlag) + printk("SCap CB_Tx: \n"); + for (i = 0; bFlag && i < g_ScreenSetParam.iTxNum; i++) + { + + if (g_stCfg_MCap_DetailThreshold.InvalidNode_SC[1][i] == 0) continue; + CBMin = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Min[1][i]; + CBMax = g_stCfg_MCap_DetailThreshold.SCapCbTest_OFF_Max[1][i]; + Value = m_RawData[3+g_ScreenSetParam.iTxNum][i]; + + iAvg += Value; + if (iMax < Value) iMax = Value; + if (iMin > Value) iMin = Value; + if (Value > CBMax || Value < CBMin) + { + btmpresult = false; + printk("Failed. Num = %d, Value = %d, range = (%d, %d):\n", i+1, Value, CBMin, CBMax); + } + iCount++; + } + + if (0 == iCount) + { + iAvg = 0; + iMax = 0; + iMin = 0; + } + else + iAvg = iAvg/iCount; + + printk("SCap CB in Waterproof-OFF, Max : %d, Min: %d, Deviation: %d, Average: %d\n", iMax, iMin, iMax - iMin, iAvg); + + ibiggerValue = g_ScreenSetParam.iTxNum > g_ScreenSetParam.iRxNum?g_ScreenSetParam.iTxNum:g_ScreenSetParam.iRxNum; + Save_Test_Data(m_RawData, g_ScreenSetParam.iTxNum+2, 2, ibiggerValue, 2); + } + + if (m_bV3TP) + { + ReCode = ReadReg(REG_MAPPING_SWITCH, &ucValue); + if (ReCode != ERROR_CODE_OK) + { + printk("\n Read REG_MAPPING_SWITCH error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + + if (0 != ucValue) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 0); + SysDelay(10); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to switch mapping type!\n "); + btmpresult = false; + } + } + + ReCode = GetChannelNum(); + if (ReCode != ERROR_CODE_OK) + { + printk("\n GetChannelNum error. Error Code: %d\n", ReCode); + goto TEST_ERR; + } + } + + + + if (btmpresult) + { + *bTestResult = true; + printk("\n\n//SCap CB Test Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//SCap CB Test Test is NG!\n"); + } + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//SCap CB Test Test is NG!\n"); + return ReCode; +} + +/************************************************************************ +* Name: GetPanelRows(Same function name as FT_MultipleTest) +* Brief: Get row of TP +* Input: none +* Output: pPanelRows +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelRows(unsigned char *pPanelRows) +{ + return ReadReg(REG_TX_NUM, pPanelRows); +} + +/************************************************************************ +* Name: GetPanelCols(Same function name as FT_MultipleTest) +* Brief: get column of TP +* Input: none +* Output: pPanelCols +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelCols(unsigned char *pPanelCols) +{ + return ReadReg(REG_RX_NUM, pPanelCols); +} +/************************************************************************ +* Name: StartScan(Same function name as FT_MultipleTest) +* Brief: Scan TP, do it before read Raw Data +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static int StartScan(void) +{ + unsigned char RegVal = 0; + unsigned char times = 0; + const unsigned char MaxTimes = 250; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + RegVal |= 0x80; + ReCode = WriteReg(DEVIDE_MODE_ADDR, RegVal); + if (ReCode == ERROR_CODE_OK) + { + while(times++ < MaxTimes) + { + SysDelay(16); + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + if ((RegVal>>7) == 0) break; + } + else + { + printk("StartScan read DEVIDE_MODE_ADDR error.\n"); + break; + } + } + if (times < MaxTimes) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + else + printk("StartScan write DEVIDE_MODE_ADDR error.\n"); + } + else + printk("StartScan read DEVIDE_MODE_ADDR error.\n"); + return ReCode; + +} +/************************************************************************ +* Name: ReadRawData(Same function name as FT_MultipleTest) +* Brief: read Raw Data +* Input: Freq(No longer used, reserved), LineNum, ByteNum +* Output: pRevBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer) +{ + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + unsigned char I2C_wBuffer[3]; + int i, iReadNum; + unsigned short BytesNumInTestMode1 = 0; + + + + + iReadNum = ByteNum/342; + + if (0 != (ByteNum%342)) iReadNum++; + + if (ByteNum <= 342) + { + BytesNumInTestMode1 = ByteNum; + } + else + { + BytesNumInTestMode1 = 342; + } + + ReCode = WriteReg(REG_LINE_NUM, LineNum); + + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to write REG_LINE_NUM! \n"); + goto READ_ERR; + } + + + I2C_wBuffer[0] = REG_RawBuf0; + if (ReCode == ERROR_CODE_OK) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, m_ucTempData, BytesNumInTestMode1); + if (ReCode != ERROR_CODE_OK) + { + printk("read rawdata Comm_Base_IIC_IO Failed!1 \n"); + goto READ_ERR; + } + } + + for (i = 1; i < iReadNum; i++) + { + if (ReCode != ERROR_CODE_OK) break; + + if (i == iReadNum-1) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, m_ucTempData+342*i, ByteNum-342*i); + if (ReCode != ERROR_CODE_OK) + { + printk("read rawdata Comm_Base_IIC_IO Failed!2 \n"); + goto READ_ERR; + } + } + else + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, m_ucTempData+342*i, 342); + + if (ReCode != ERROR_CODE_OK) + { + printk("read rawdata Comm_Base_IIC_IO Failed!3 \n"); + goto READ_ERR; + } + } + + } + + if (ReCode == ERROR_CODE_OK) + { + for (i = 0; i < (ByteNum>>1); i++) + { + pRevBuffer[i] = (m_ucTempData[i<<1]<<8)+m_ucTempData[(i<<1)+1]; + + } + } + +READ_ERR: + return ReCode; + +} +/************************************************************************ +* Name: GetTxSC_CB(Same function name as FT_MultipleTest) +* Brief: get CB of Tx SCap +* Input: index +* Output: pcbValue +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char GetTxSC_CB(unsigned char index, unsigned char *pcbValue) +{ + unsigned char ReCode = ERROR_CODE_OK; + unsigned char wBuffer[4]; + + if (index < 128) + { + *pcbValue = 0; + WriteReg(REG_ScCbAddrR, index); + ReCode = ReadReg(REG_ScCbBuf0, pcbValue); + } + else + { + WriteReg(REG_ScCbAddrR, 0); + wBuffer[0] = REG_ScCbBuf0; + ReCode = Comm_Base_IIC_IO(wBuffer, 1, pcbValue, index-128); + + } + + return ReCode; +} + + + +/************************************************************************ +* Name: AllocateMemory +* Brief: Allocate pointer Memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static char pStoreMsgArea[1024 * 80] ; +static char pMsgAreaLine2[1024 * 80] ; +static char pStoreDataArea[1024 * 80]; +static char pTmpBuff[1024 * 16] ; + +static int AllocateMemory(void) +{ + + printk("AllocateMemory changed\n"); + g_pStoreMsgArea = NULL; + if (NULL == g_pStoreMsgArea) + { + memset(pStoreMsgArea, 0, sizeof(pStoreMsgArea)); + g_pStoreMsgArea = pStoreMsgArea;; + if (g_pStoreMsgArea == NULL) + { + printk("lancelot g_pStoreMsgArea malloc error.\n"); + goto ERR_0; + } + } + g_pMsgAreaLine2 = NULL; + if (NULL == g_pMsgAreaLine2) + { + memset(pMsgAreaLine2, 0, sizeof(pMsgAreaLine2)); + g_pMsgAreaLine2 = pMsgAreaLine2; + if (g_pMsgAreaLine2 == NULL) + { + printk("lancelot g_pMsgAreaLine2 malloc error.\n"); + goto ERR_1; + } + } + g_pStoreDataArea = NULL; + if (NULL == g_pStoreDataArea) + { + memset(pStoreDataArea, 0, sizeof(pStoreDataArea)); + g_pStoreDataArea = pStoreDataArea; + if (g_pStoreDataArea == NULL) + { + printk("lancelot g_pStoreDataArea malloc error.\n"); + goto ERR_2; + } + } + + g_pTmpBuff = NULL; + if (NULL == g_pTmpBuff) + { + memset(pTmpBuff, 0, sizeof(pTmpBuff)); + g_pTmpBuff = pTmpBuff; + if (g_pTmpBuff == NULL) + { + printk("lancelot g_pTmpBuff malloc error.\n"); + goto ERR_3; + } + } + + return 1; + +ERR_3: + g_pStoreDataArea = NULL; + printk("pTmpBuff fail\n"); +ERR_2: + g_pMsgAreaLine2 = NULL; + printk("pStoreDataArea fail\n"); +ERR_1: + g_pStoreMsgArea = NULL; + printk("pMsgAreaLine fail\n"); + +ERR_0: + printk("pStoreMsgArea fail\n"); + + + return -EPERM; + +} +/************************************************************************ +* Name: FreeMemory +* Brief: Release pointer memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +/* +static void FreeMemory(void) +{ + //Release buff + if(NULL != g_pStoreMsgArea) + kfree(g_pStoreMsgArea); + + if(NULL != g_pMsgAreaLine2) + kfree(g_pMsgAreaLine2); + + if(NULL != g_pStoreDataArea) + kfree(g_pStoreDataArea); + + + if(NULL != g_pTmpBuff) + kfree(g_pTmpBuff); +} +*/ +/************************************************************************ +* Name: InitStoreParamOfTestData +* Brief: Init store param of test data +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitStoreParamOfTestData(void) +{ + + + g_lenStoreMsgArea = 0; + + g_lenStoreMsgArea += sprintf(g_pStoreMsgArea, "ECC, 85, 170, IC Name, %s, IC Code, %x\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + + + g_lenMsgAreaLine2 = 0; + + + + g_lenStoreDataArea = 0; + m_iStartLine = 11; + + m_iTestDataCount = 0; +} +/************************************************************************ +* Name: MergeAllTestData +* Brief: Merge All Data of test result +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void MergeAllTestData(void) +{ + int iLen = 0; + + + iLen = sprintf(g_pTmpBuff, "TestItem, %d, ", m_iTestDataCount); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pMsgAreaLine2, g_lenMsgAreaLine2); + g_lenStoreMsgArea+=g_lenMsgAreaLine2; + + + iLen = sprintf(g_pTmpBuff, "\n\n\n\n\n\n\n\n\n"); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreAllData, g_pStoreMsgArea, g_lenStoreMsgArea); + + + if (0 != g_lenStoreDataArea) + { + memcpy(g_pStoreAllData+g_lenStoreMsgArea, g_pStoreDataArea, g_lenStoreDataArea); + } + + printk("[focal] %s lenStoreMsgArea=%d, lenStoreDataArea = %d\n", __func__, g_lenStoreMsgArea, g_lenStoreDataArea); +} + + +/************************************************************************ +* Name: Save_Test_Data +* Brief: Storage format of test data +* Input: int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount +* Output: none +* Return: none +***********************************************************************/ +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount) +{ + int iLen = 0; + int i = 0, j = 0; + + + iLen = sprintf(g_pTmpBuff, "NA, %d, %d, %d, %d, %d, ", \ + m_ucTestItemCode, Row, Col, m_iStartLine, ItemCount); + memcpy(g_pMsgAreaLine2+g_lenMsgAreaLine2, g_pTmpBuff, iLen); + g_lenMsgAreaLine2 += iLen; + + m_iStartLine += Row; + m_iTestDataCount++; + + + for (i = 0+iArrayIndex; i < Row+iArrayIndex; i++) + { + for (j = 0; j < Col; j++) + { + if (j == (Col -1)) + iLen = sprintf(g_pTmpBuff, "%d, \n", iData[i][j]); + else + iLen = sprintf(g_pTmpBuff, "%d, ", iData[i][j]); + + memcpy(g_pStoreDataArea+g_lenStoreDataArea, g_pTmpBuff, iLen); + g_lenStoreDataArea += iLen; + } + } + +} + +/************************************************************************ +* Name: GetChannelNum +* Brief: Get Channel Num(Tx and Rx) +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNum(void) +{ + unsigned char ReCode; + unsigned char rBuffer[1]; + + + ReCode = GetPanelRows(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iTxNum = rBuffer[0]; + if (g_ScreenSetParam.iTxNum > g_ScreenSetParam.iUsedMaxTxNum) + { + printk("Failed to get Tx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iTxNum, g_ScreenSetParam.iUsedMaxTxNum); + return ERROR_CODE_INVALID_PARAM; + } + } + else + { + printk("Failed to get Tx number\n"); + } + + + + ReCode = GetPanelCols(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iRxNum = rBuffer[0]; + if (g_ScreenSetParam.iRxNum > g_ScreenSetParam.iUsedMaxRxNum) + { + printk("Failed to get Rx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iRxNum, g_ScreenSetParam.iUsedMaxRxNum); + return ERROR_CODE_INVALID_PARAM; + } + } + else + { + printk("Failed to get Rx number\n"); + } + + return ReCode; + +} +/************************************************************************ +* Name: GetRawData +* Brief: Get Raw Data of MCAP +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetRawData(void) +{ + unsigned char ReCode = ERROR_CODE_OK; + int iRow = 0; + int iCol = 0; + + + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter Factory Mode...\n"); + return ReCode; + } + + + + if (0 == (g_ScreenSetParam.iTxNum + g_ScreenSetParam.iRxNum)) + { + ReCode = GetChannelNum(); + if (ERROR_CODE_OK != ReCode) + { + printk("Error Channel Num...\n"); + return ERROR_CODE_INVALID_PARAM; + } + } + + + printk("Start Scan ...\n"); + ReCode = StartScan(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Scan ...\n"); + return ReCode; + } + + + memset(m_RawData, 0, sizeof(m_RawData)); + ReCode = ReadRawData(1, 0xAA, (g_ScreenSetParam.iTxNum * g_ScreenSetParam.iRxNum)*2, m_iTempRawData); + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + m_RawData[iRow][iCol] = m_iTempRawData[iRow*g_ScreenSetParam.iRxNum + iCol]; + } + } + return ReCode; +} +/************************************************************************ +* Name: ShowRawData +* Brief: Show RawData +* Input: none +* Output: none +* Return: none. +***********************************************************************/ +static void ShowRawData(void) +{ + int iRow, iCol; + + for (iRow = 0; iRow < g_ScreenSetParam.iTxNum; iRow++) + { + printk("\nTx%2d: ", iRow+1); + for (iCol = 0; iCol < g_ScreenSetParam.iRxNum; iCol++) + { + printk("%5d ", m_RawData[iRow][iCol]); + } + } +} + +/************************************************************************ +* Name: GetChannelNumNoMapping +* Brief: get Tx&Rx num from other Register +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNumNoMapping(void) +{ + unsigned char ReCode; + unsigned char rBuffer[1]; + + + printk("Get Tx Num...\n"); + ReCode = ReadReg(REG_TX_NOMAPPING_NUM, rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iTxNum = rBuffer[0]; + } + else + { + printk("Failed to get Tx number\n"); + } + + + printk("Get Rx Num...\n"); + ReCode = ReadReg(REG_RX_NOMAPPING_NUM, rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iRxNum = rBuffer[0]; + } + else + { + printk("Failed to get Rx number\n"); + } + + return ReCode; +} +/************************************************************************ +* Name: SwitchToNoMapping +* Brief: If it is V3 pattern, Get Tx/Rx Num again +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char SwitchToNoMapping(void) +{ + unsigned char chPattern = -1; + unsigned char ReCode = ERROR_CODE_OK; + unsigned char RegData = -1; + ReCode = ReadReg(REG_PATTERN_5422, &chPattern); + if (ReCode != ERROR_CODE_OK) + { + printk("Switch To NoMapping Failed!\n"); + goto READ_ERR; + } + + if (1 == chPattern) + { + RegData = -1; + ReCode = ReadReg(REG_MAPPING_SWITCH, &RegData); + if (ReCode != ERROR_CODE_OK) + { + printk("read REG_MAPPING_SWITCH Failed!\n"); + goto READ_ERR; + } + + if (1 != RegData) + { + ReCode = WriteReg(REG_MAPPING_SWITCH, 1); + if (ReCode != ERROR_CODE_OK) + { + printk("write REG_MAPPING_SWITCH Failed!\n"); + goto READ_ERR; + } + focal_msleep(20); + ReCode = GetChannelNumNoMapping(); + + if (ReCode != ERROR_CODE_OK) + { + printk("GetChannelNumNoMapping Failed!\n"); + goto READ_ERR; + } + } + } + +READ_ERR: + return ReCode; +} +/************************************************************************ +* Name: GetTestCondition +* Brief: Check whether Rx or TX need to test, in Waterproof ON/OFF Mode. +* Input: none +* Output: none +* Return: true: need to test; false: Not tested. +***********************************************************************/ +static boolean GetTestCondition(int iTestType, unsigned char ucChannelValue) +{ + boolean bIsNeeded = false; + switch(iTestType) + { + case WT_NeedProofOnTest: + bIsNeeded = !(ucChannelValue & 0x20); + break; + case WT_NeedProofOffTest: + bIsNeeded = !(ucChannelValue & 0x80); + break; + case WT_NeedTxOnVal: + bIsNeeded = !(ucChannelValue & 0x40) || !(ucChannelValue & 0x04); + break; + case WT_NeedRxOnVal: + bIsNeeded = !(ucChannelValue & 0x40) || (ucChannelValue & 0x04); + break; + case WT_NeedTxOffVal: + bIsNeeded = (0x00 == (ucChannelValue & 0x03)) || (0x02 == (ucChannelValue & 0x03)); + break; + case WT_NeedRxOffVal: + bIsNeeded = (0x01 == (ucChannelValue & 0x03)) || (0x02 == (ucChannelValue & 0x03)); + break; + default:break; + } + return bIsNeeded; +} + + diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT5X46.h b/drivers/input/touchscreen/ft5435/lib/Test_FT5X46.h new file mode 100644 index 0000000000000..eb0f7358ad49d --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT5X46.h @@ -0,0 +1,31 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT5X46.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test item for FT5X46\FT5X46i\FT5526\FT3X17\FT5436\FT3X27\FT5526i\FT5416\FT5426\FT5435 +* +************************************************************************/ +#ifndef _TEST_FT5X46_H +#define _TEST_FT5X46_H + +#include "test_lib.h" + +boolean FT5X46_StartTest(void); +int FT5X46_get_test_data(char *pTestData); + +unsigned char FT5X46_TestItem_EnterFactoryMode(void); +unsigned char FT5X46_TestItem_RawDataTest(bool *bTestResult); + +unsigned char FT5X46_TestItem_SCapRawDataTest(bool *bTestResult); +unsigned char FT5X46_TestItem_SCapCbTest(bool *bTestResult); + +boolean GetWaterproofMode(int iTestType, unsigned char ucChannelValue); + + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT6X36.c b/drivers/input/touchscreen/ft5435/lib/Test_FT6X36.c new file mode 100644 index 0000000000000..98ce3d021e099 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT6X36.c @@ -0,0 +1,2509 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT6X36.c +* +* Author: Software Development Team, AE +* +* Created: 2015-10-08 +* +* Abstract: test item for FT6X36/FT3X07/FT6416/FT6426 +* +************************************************************************/ + +/******************************************************************************* +* Included header files +*******************************************************************************/ +#include +#include +#include + +#include "Global.h" +#include "DetailThreshold.h" +#include "Test_FT6X36.h" +#include "Config_FT6X36.h" + + +/******************************************************************************* +* Private constant and macro definitions using #define +*******************************************************************************/ +#define IC_TEST_VERSION "Test version: V1.0.0--2015-10-08, (sync version of FT_MultipleTest: V2.7.0.3--2015-07-13)" + + +#define DEVIDE_MODE_ADDR 0x00 +#define REG_LINE_NUM 0x01 +#define REG_TX_NUM 0x02 +#define REG_RX_NUM 0x03 +#define REG_PATTERN_5422 0x53 +#define REG_MAPPING_SWITCH 0x54 +#define REG_TX_NOMAPPING_NUM 0x55 +#define REG_RX_NOMAPPING_NUM 0x56 +#define REG_NORMALIZE_TYPE 0x16 +#define REG_ScCbBuf0 0x4E +#define REG_ScWorkMode 0x44 +#define REG_ScCbAddrR 0x45 +#define REG_RawBuf0 0x36 +#define REG_WATER_CHANNEL_SELECT 0x09 + + +#define C6208_SCAN_ADDR 0x08 + +#define C6X36_CHANNEL_NUM 0x0A +#define C6X36_KEY_NUM 0x0B + +#define C6X36_CB_ADDR_W 0x32/*0x32*/ +#define C6X36_CB_ADDR_R 0x33/*0x32*/ +#define C6X36_CB_BUF 0x39/*0x33*/ +#define C6X36_RAWDATA_ADDR 0x34/*0x34*/ +#define C6X36_RAWDATA_BUF 0x35 + +#define C6206_FACTORY_TEST_MODE 0xAE +#define C6206_FACTORY_TEST_STATUS 0xAD + +#define MAX_SCAP_CHANNEL_NUM 144 +#define MAX_SCAP_KEY_NUM 8 + +/******************************************************************************* +* Private enumerations, structures and unions using typedef +*******************************************************************************/ +enum WaterproofType +{ + WT_NeedProofOnTest, + WT_NeedProofOffTest, + WT_NeedTxOnVal, + WT_NeedRxOnVal, + WT_NeedTxOffVal, + WT_NeedRxOffVal, +}; +/******************************************************************************* +* Static variables +*******************************************************************************/ + +static int m_RawData[MAX_SCAP_CHANNEL_NUM] = {0}; + +static unsigned char m_ucTempData[MAX_SCAP_CHANNEL_NUM*2] = {0}; + +static int m_CbData[MAX_SCAP_CHANNEL_NUM] = {0}; +static int m_TempCbData[MAX_SCAP_CHANNEL_NUM] = {0}; +static int m_DeltaCbData[MAX_SCAP_CHANNEL_NUM] = {0}; +static int m_DeltaCb_DifferData[MAX_SCAP_CHANNEL_NUM] = {0}; + + + +static char g_pStoreAllData[1024*80] = {0}; +static char *g_pTmpBuff; +static char *g_pStoreMsgArea; +static int g_lenStoreMsgArea; +static char *g_pMsgAreaLine2; +static int g_lenMsgAreaLine2; +static char *g_pStoreDataArea; +static int g_lenStoreDataArea; +static unsigned char m_ucTestItemCode; +static int m_iStartLine; +static int m_iTestDataCount; + +/******************************************************************************* +* Global variable or extern global variabls/functions +*******************************************************************************/ + + +/******************************************************************************* +* Static function prototypes +*******************************************************************************/ + +static int StartScan(void); +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer); +static unsigned char GetPanelChannels(unsigned char *pPanelRows); +static unsigned char GetPanelKeys(unsigned char *pPanelCols); + +static unsigned char GetRawData(void); +static unsigned char GetChannelNum(void); + +static void InitTest(void); +static void FinishTest(void); +static void Save_Test_Data(int iData[MAX_SCAP_CHANNEL_NUM], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount); +static void InitStoreParamOfTestData(void); +static void MergeAllTestData(void); + +static void AllocateMemory(void); +static void FreeMemory(void); +static void ShowRawData(void); + +/************************************************************************ +* Name: FT6X36_StartTest +* Brief: Test entry. Determine which test item to test +* Input: none +* Output: none +* Return: Test Result, PASS or FAIL +***********************************************************************/ +boolean FT6X36_StartTest() +{ + bool bTestResult = true; + bool bTempResult = 1; + unsigned char ReCode = 0; + unsigned char ucDevice = 0; + int iItemCount = 0; + + + InitTest(); + + + if (0 == g_TestItemNum) + bTestResult = false; + + for (iItemCount = 0; iItemCount < g_TestItemNum; iItemCount++) + { + m_ucTestItemCode = g_stTestItem[ucDevice][iItemCount].ItemCode; + + + if (Code_FT6X36_ENTER_FACTORY_MODE == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_EnterFactoryMode(); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + break; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + /*if(Code_FT6X36_CHANNEL_NUM_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_ChannelsTest(&bTempResult); + if(ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + } + }*/ + + + if (Code_FT6X36_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_RawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + + if (Code_FT6X36_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_CbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT6X36_DELTA_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_DeltaCbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT6X36_CHANNELS_DEVIATION_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_ChannelsDeviationTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT6X36_TWO_SIDES_DEVIATION_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_TwoSidesDeviationTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + /*if(Code_FT6X36_NOISE_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT6X36_TestItem_SCapRawDataTest(&bTempResult); + if(ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + }*/ + + } + + + FinishTest(); + + + return bTestResult; +} +/************************************************************************ +* Name: InitTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitTest(void) +{ + AllocateMemory(); + InitStoreParamOfTestData(); + printk("[focal] %s \n", IC_TEST_VERSION); +} +/************************************************************************ +* Name: FinishTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FinishTest(void) +{ + MergeAllTestData(); + FreeMemory(); +} +/************************************************************************ +* Name: FT6X36_get_test_data +* Brief: get data of test result +* Input: none +* Output: pTestData, the returned buff +* Return: the length of test data. if length > 0, got data;else ERR. +***********************************************************************/ +int FT6X36_get_test_data(char *pTestData) +{ + if (NULL == pTestData) + { + printk("[focal] %s pTestData == NULL \n", __func__); + return -EPERM; + } + memcpy(pTestData, g_pStoreAllData, (g_lenStoreMsgArea+g_lenStoreDataArea)); + return (g_lenStoreMsgArea+g_lenStoreDataArea); +} + +/************************************************************************ +* Name: FT6X36_TestItem_EnterFactoryMode +* Brief: Check whether TP can enter Factory Mode, and do some thing +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT6X36_TestItem_EnterFactoryMode(void) +{ + unsigned char ReCode = ERROR_CODE_INVALID_PARAM; + int iRedo = 5; + int i ; + + SysDelay(150); + for (i = 1; i <= iRedo; i++) + { + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter factory mode...\n"); + if (i < iRedo) + { + SysDelay(50); + continue; + } + } + else + { + break; + } + + } + SysDelay(300); + + if (ReCode != ERROR_CODE_OK) + { + return ReCode; + } + + ReCode = GetChannelNum(); + + return ReCode; +} + +/************************************************************************ +* Name: GetPanelChannels(Same function name as FT_MultipleTest GetChannelNum) +* Brief: Get row of TP +* Input: none +* Output: pPanelChannels +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelChannels(unsigned char *pPanelChannels) +{ + return ReadReg(C6X36_CHANNEL_NUM, pPanelChannels); +} + +/************************************************************************ +* Name: GetPanelKeys(Same function name as FT_MultipleTest GetKeyNum) +* Brief: get column of TP +* Input: none +* Output: pPanelKeys +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetPanelKeys(unsigned char *pPanelKeys) +{ + return ReadReg(C6X36_KEY_NUM, pPanelKeys); +} +/************************************************************************ +* Name: StartScan(Same function name as FT_MultipleTest) +* Brief: Scan TP, do it before read Raw Data +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static int StartScan(void) +{ + unsigned char RegVal = 0x01; + unsigned int times = 0; + const unsigned int MaxTimes = 500/*20*/; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + ReCode = ReadReg(C6208_SCAN_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + RegVal = 0x01; + ReCode = WriteReg(C6208_SCAN_ADDR, RegVal); + if (ReCode == ERROR_CODE_OK) + { + while(times++ < MaxTimes) + { + SysDelay(8); + ReCode = ReadReg(C6208_SCAN_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + if (RegVal == 0) + { + + break; + } + } + else + { + break; + } + } + if (times < MaxTimes) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + } + + return ReCode; + +} +/************************************************************************ +* Name: ReadRawData(Same function name as FT_MultipleTest) +* Brief: read Raw Data +* Input: Freq(No longer used, reserved), LineNum, ByteNum +* Output: pRevBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer) +{ + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + unsigned char I2C_wBuffer[3]; + unsigned short BytesNumInTestMode1 = 0; + + int i = 0; + + BytesNumInTestMode1 = ByteNum; + + + I2C_wBuffer[0] = C6X36_RAWDATA_ADDR; + I2C_wBuffer[1] = 0; + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 2, NULL, 0); + + if ((ReCode == ERROR_CODE_OK)) + { + if (ReCode == ERROR_CODE_OK) + { + I2C_wBuffer[0] = C6X36_RAWDATA_BUF; + + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, m_ucTempData, BytesNumInTestMode1); + + } + } + + + if (ReCode == ERROR_CODE_OK) + { + for (i = 0; i < (ByteNum>>1); i++) + { + pRevBuffer[i] = (m_ucTempData[i<<1]<<8)+m_ucTempData[(i<<1)+1]; + } + } + + return ReCode; + +} + + +/************************************************************************ +* Name: AllocateMemory +* Brief: Allocate pointer Memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void AllocateMemory(void) +{ + + g_pStoreMsgArea = NULL; + if (NULL == g_pStoreMsgArea) + g_pStoreMsgArea = kmalloc(1024*80, GFP_ATOMIC); + g_pMsgAreaLine2 = NULL; + if (NULL == g_pMsgAreaLine2) + g_pMsgAreaLine2 = kmalloc(1024*80, GFP_ATOMIC); + g_pStoreDataArea = NULL; + if (NULL == g_pStoreDataArea) + g_pStoreDataArea = kmalloc(1024*80, GFP_ATOMIC); + /*g_pStoreAllData =NULL; + if(NULL == g_pStoreAllData) + g_pStoreAllData = kmalloc(1024*8, GFP_ATOMIC); + g_pTmpBuff =NULL;*/ + if (NULL == g_pTmpBuff) + g_pTmpBuff = kmalloc(1024*16, GFP_ATOMIC); + +} +/************************************************************************ +* Name: FreeMemory +* Brief: Release pointer memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FreeMemory(void) +{ + + if (NULL != g_pStoreMsgArea) + kfree(g_pStoreMsgArea); + + if (NULL != g_pMsgAreaLine2) + kfree(g_pMsgAreaLine2); + + if (NULL != g_pStoreDataArea) + kfree(g_pStoreDataArea); + + /*if(NULL == g_pStoreAllData) + kfree(g_pStoreAllData);*/ + + if (NULL != g_pTmpBuff) + kfree(g_pTmpBuff); +} + +/************************************************************************ +* Name: InitStoreParamOfTestData +* Brief: Init store param of test data +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitStoreParamOfTestData(void) +{ + + + g_lenStoreMsgArea = 0; + + g_lenStoreMsgArea += sprintf(g_pStoreMsgArea, "ECC, 85, 170, IC Name, %s, IC Code, %x\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + + + g_lenMsgAreaLine2 = 0; + + + + g_lenStoreDataArea = 0; + m_iStartLine = 11; + + m_iTestDataCount = 0; +} +/************************************************************************ +* Name: MergeAllTestData +* Brief: Merge All Data of test result +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void MergeAllTestData(void) +{ + int iLen = 0; + + + iLen = sprintf(g_pTmpBuff, "TestItem, %d, ", m_iTestDataCount); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pMsgAreaLine2, g_lenMsgAreaLine2); + g_lenStoreMsgArea+=g_lenMsgAreaLine2; + + + iLen = sprintf(g_pTmpBuff, "\n\n\n\n\n\n\n\n\n"); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreAllData, g_pStoreMsgArea, g_lenStoreMsgArea); + + + if (0 != g_lenStoreDataArea) + { + memcpy(g_pStoreAllData+g_lenStoreMsgArea, g_pStoreDataArea, g_lenStoreDataArea); + } + + printk("[focal] %s lenStoreMsgArea=%d, lenStoreDataArea = %d\n", __func__, g_lenStoreMsgArea, g_lenStoreDataArea); +} + + +/************************************************************************ +* Name: Save_Test_Data +* Brief: Storage format of test data +* Input: int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount +* Output: none +* Return: none +***********************************************************************/ +static void Save_Test_Data(int iData[MAX_SCAP_CHANNEL_NUM], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount) +{ + int iLen = 0; + int i = 0, j = 0; + + + iLen = sprintf(g_pTmpBuff, "NA, %d, %d, %d, %d, %d, ", \ + m_ucTestItemCode, Row, Col, m_iStartLine, ItemCount); + memcpy(g_pMsgAreaLine2+g_lenMsgAreaLine2, g_pTmpBuff, iLen); + g_lenMsgAreaLine2 += iLen; + + m_iStartLine += Row; + m_iTestDataCount++; + + + for (i = 0+iArrayIndex; i < Row+iArrayIndex; i++) + { + for (j = 0; j < Col; j++) + { + if (j == (Col -1)) + iLen = sprintf(g_pTmpBuff, "%d, \n", iData[j]); + else + iLen = sprintf(g_pTmpBuff, "%d, ", iData[j]); + + memcpy(g_pStoreDataArea+g_lenStoreDataArea, g_pTmpBuff, iLen); + g_lenStoreDataArea += iLen; + } + } + +} + +/************************************************************************ +* Name: GetChannelNum +* Brief: Get Channel Num(Tx and Rx) +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNum(void) +{ + unsigned char ReCode; + unsigned char rBuffer[1]; + + + ReCode = GetPanelChannels(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iChannelsNum = rBuffer[0]; + /*if(g_ScreenSetParam.iTxNum > g_ScreenSetParam.iUsedMaxTxNum) + { + printk("Failed to get Tx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iTxNum, g_ScreenSetParam.iUsedMaxTxNum); + return ERROR_CODE_INVALID_PARAM; + }*/ + } + else + { + printk("Failed to get channel number\n"); + } + + + + ReCode = GetPanelKeys(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + g_ScreenSetParam.iKeyNum = rBuffer[0]; + /*if(g_ScreenSetParam.iRxNum > g_ScreenSetParam.iUsedMaxRxNum) + { + printk("Failed to get Rx number, Get num = %d, UsedMaxNum = %d\n", + g_ScreenSetParam.iRxNum, g_ScreenSetParam.iUsedMaxRxNum); + return ERROR_CODE_INVALID_PARAM; + }*/ + } + else + { + printk("Failed to get Rx number\n"); + } + + return ReCode; + +} + +/************************************************************************ +* Name: GetRawData +* Brief: get panel rawdata by read rawdata function +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char GetRawData(void) +{ + + + int readlen = 0; + unsigned char ReCode = ERROR_CODE_OK; + + + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter Factory Mode...\n"); + return ReCode; + } + + + if (0 == (g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum)) + { + ReCode = GetChannelNum(); + if (ERROR_CODE_OK != ReCode) + { + printk("Error Channel Num...\n"); + return ERROR_CODE_INVALID_PARAM; + } + } + + + printk("Start Scan ...\n"); + ReCode = StartScan(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Scan ...\n"); + return ReCode; + } + + memset(m_RawData, 0, sizeof(m_RawData)); + + + readlen = g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; + if (readlen <= 0 || readlen >= MAX_SCAP_CHANNEL_NUM) return ERROR_CODE_INVALID_PARAM; + + + ReCode = ReadRawData(3, 0, readlen * 2, m_RawData); + if (ReCode != ERROR_CODE_OK) + { + printk("Failed to Read RawData...\n"); + return ReCode; + } + + return ReCode; + +} + +/************************************************************************ +* Name: ShowRawData +* Brief: Show RawData +* Input: none +* Output: none +* Return: none. +***********************************************************************/ +static void ShowRawData(void) +{ + int iChannelsNum = 0, iKeyNum = 0; + + + printk("\nChannels: "); + for (iChannelsNum = 0; iChannelsNum < g_ScreenSetParam.iChannelsNum; iChannelsNum++) + { + printk("%5d ", m_RawData[iChannelsNum]); + } + + printk("\nKeys: "); + for (iKeyNum = 0; iKeyNum < g_ScreenSetParam.iKeyNum; iKeyNum++) + { + printk("%5d ", m_RawData[g_ScreenSetParam.iChannelsNum+iKeyNum]); + } + + printk("\n\n\n\n"); +} + +/************************************************************************ +* Name: FT6X36_TestItem_RawDataTest +* Brief: TestItem: RawDataTest. Check if SCAP RawData is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT6X36_TestItem_RawDataTest(bool *bTestResult) +{ + int i = 0; + + unsigned char ReCode = ERROR_CODE_OK; + bool btmpresult = true; + int RawDataMin = 0, RawDataMax = 0; + + int iNgNum = 0; + int iMax = 0, iMin = 0, iAvg = 0; + + RawDataMin = g_stCfg_FT6X36_BasicThreshold.RawDataTest_Min; + RawDataMax = g_stCfg_FT6X36_BasicThreshold.RawDataTest_Max; + + printk("\r\n\r\n==============================Test Item: -------- RawData Test \r\n"); + + for (i = 0; i < 3; i++) + { + ReCode = WriteReg(C6206_FACTORY_TEST_MODE, Proof_Normal); + if (ERROR_CODE_OK == ReCode) + ReCode = StartScan(); + if (ERROR_CODE_OK == ReCode)break; + } + + ReCode = GetRawData(); + + if (ReCode == ERROR_CODE_OK) + { + printk("\r\n//======= Test Data: "); + ShowRawData(); + } + else + { + printk("\r\nRawData Test is Error. Failed to get Raw Data!!"); + btmpresult = false; + goto TEST_END; + } + + iNgNum = 0; + iMax = m_RawData[0]; + iMin = m_RawData[0]; + iAvg = 0; + + for (i = 0; i < g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; i++) + { + RawDataMin = g_stCfg_SCap_DetailThreshold.RawDataTest_Min[i]; + RawDataMax = g_stCfg_SCap_DetailThreshold.RawDataTest_Max[i]; + if (m_RawData[i] < RawDataMin || m_RawData[i] > RawDataMax) + { + btmpresult = false; + + if (iNgNum == 0) printk("\r\n//======= NG Data: \r\n"); + + if (i < g_ScreenSetParam.iChannelsNum) + printk("Ch_%02d: %d Set_Range=(%d, %d) , ", i+1, m_RawData[i], RawDataMin, RawDataMax); + else + printk("Key_%d: %d Set_Range=(%d, %d) , ", i+1 - g_ScreenSetParam.iChannelsNum, m_RawData[i], RawDataMin, RawDataMax); + if (iNgNum % 6 == 0) + { + printk("\r\n"); + } + + iNgNum++; + } + + iAvg += m_RawData[i]; + if (iMax < m_RawData[i])iMax = m_RawData[i]; + if (iMin > m_RawData[i])iMin = m_RawData[i]; + + } + + iAvg /= g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; + printk("\r\n\r\n// Max Raw Value: %d, Min Raw Value: %d, Deviation Value: %d, Average Value: %d", iMax, iMin, iMax - iMin, iAvg); + + Save_Test_Data(m_RawData, 0, 1, g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum, 1); + +TEST_END: + if (btmpresult) + { + * bTestResult = true; + printk("\r\n\r\n//RawData Test is OK!\r\n"); + } + else + { + * bTestResult = false; + printk("\r\n\r\n//RawData Test is NG!\r\n"); + } + return ReCode; +} + +/************************************************************************ +* Name: FT6X36_TestItem_CbTest +* Brief: TestItem: CB Test. Check if SCAP CB is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT6X36_TestItem_CbTest(bool *bTestResult) +{ + int readlen = 0; + + bool btmpresult = true; + int iCbMin = 0, iCbMax = 0; + unsigned char chOldMode = 0; + + + unsigned char ReCode = ERROR_CODE_OK; + BYTE pReadData[300] = {0}; + unsigned char I2C_wBuffer[1]; + + int iNgNum = 0; + int iMax = 0, iMin = 0, iAvg = 0; + + int i = 0; + + memset(m_CbData, 0, sizeof(m_CbData)); + readlen = g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; + + printk("\r\n\r\n==============================Test Item: -------- CB Test"); + + iCbMin = g_stCfg_FT6X36_BasicThreshold.CbTest_Min; + iCbMax = g_stCfg_FT6X36_BasicThreshold.CbTest_Max; + + ReCode = ReadReg(C6206_FACTORY_TEST_MODE, &chOldMode); + + for (i = 0; i < 3; i++) + { + ReCode = WriteReg(C6206_FACTORY_TEST_MODE, Proof_NoWaterProof); + if (ERROR_CODE_OK == ReCode) + ReCode = StartScan(); + if (ERROR_CODE_OK == ReCode)break; + } + + if ((ERROR_CODE_OK != ReCode)/* || (1 != WaterProofResult)*/) + { + btmpresult = false; + printk("\r\n\r\n//========= CB test Failed!"); + } + else + { + printk("\r\n\r\nGet Proof_NoWaterProof CB Data..."); + + + I2C_wBuffer[0] = 0x39; + ReCode = WriteReg(0x33, 0); + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, pReadData, readlen * 2); + + for (i = 0; i < readlen; i++) + { + m_TempCbData[i] = (unsigned short)(pReadData[i*2] << 8 | pReadData[i*2+1]); + + if (i == 0) + { + printk("\r\n\r\n//======= CB Data: "); + printk("\r\nLeft Channel: "); + } + else if (i * 2 == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nRight Channel: "); + } + else if (i == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nKey: "); + } + printk("%3d ", m_TempCbData[i]); + + } + } + printk("\r\n\r\n"); + + printk("Proof_Level0 CB Test...\r\n"); + for (i = 0; i < 3; i++) + { + ReCode = WriteReg(C6206_FACTORY_TEST_MODE, Proof_Level0); + if (ERROR_CODE_OK == ReCode) + ReCode = StartScan(); + if (ERROR_CODE_OK == ReCode)break; + } + if ((ERROR_CODE_OK != ReCode)/* || (1 != WaterProofResult)*/) + { + btmpresult = false; + printk("\r\n\r\n//========= CB test Failed!"); + } + else + { + printk("\r\n\r\nGet Proof_Level0 CB Data..."); + + + + ·ÀË®CB + I2C_wBuffer[0] = 0x39; + ReCode = WriteReg(0x33, 0); + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, pReadData, readlen * 2); + + for (i = 0; i < readlen; i++) + { + m_CbData[i] = (unsigned short)(pReadData[i*2] << 8 | pReadData[i*2+1]); + + } + + ReCode = WriteReg(C6206_FACTORY_TEST_MODE, chOldMode); + + iNgNum = 0; + iMax = m_TempCbData[0]; + iMin = m_TempCbData[0]; + iAvg = 0; + + for (i = 0; i < g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; i++) + { + + iCbMin = g_stCfg_SCap_DetailThreshold.CbTest_Min[i]; + iCbMax = g_stCfg_SCap_DetailThreshold.CbTest_Max[i]; + + if (m_TempCbData[i] < iCbMin || m_TempCbData[i] > iCbMax) + { + if (iNgNum == 0) + { + printk("\r\n//======= NG Data: \r\n"); + } + btmpresult = false; + if (i < g_ScreenSetParam.iChannelsNum) + printk("Ch_%02d: %d Set_Range=(%d, %d) , ", i+1, m_TempCbData[i], iCbMin, iCbMax); + else + printk("Key_%d: %d Set_Range=(%d, %d), ", i+1 - g_ScreenSetParam.iChannelsNum, m_TempCbData[i], iCbMin, iCbMax); + if (iNgNum % 6 == 0) + { + printk("\r\n"); + } + + iNgNum++; + } + + iAvg += m_TempCbData[i]; + if (iMax < m_TempCbData[i])iMax = m_TempCbData[i]; + if (iMin > m_TempCbData[i])iMin = m_TempCbData[i]; + + } + + iAvg /= g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; + printk("\r\n\r\n// Max CB Value: %d, Min CB Value: %d, Deviation Value: %d, Average Value: %d", iMax, iMin, iMax - iMin, iAvg); + + if (btmpresult) + { + printk("\r\n\r\n//CB Test is OK!\r\n"); + * bTestResult = 1; + } + else + { + printk("\r\n\r\n//CB Test is NG!\r\n"); + * bTestResult = 0; + } + } + + Save_Test_Data(m_TempCbData, 0, 1, g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum, 1); + + return ReCode; + +} + +/************************************************************************ +* Name: FT6X36_TestItem_DeltaCbTest +* Brief: TestItem: Delta CB Test. Check if SCAP Delta CB is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT6X36_TestItem_DeltaCbTest(unsigned char *bTestResult) +{ + bool btmpresult = true; + int readlen = g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; + int i = 0; + + int Delta_Ci_Differ = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S1; + int Delta_Ci_Differ_S2 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S2; + int Delta_Ci_Differ_S3 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S3; + int Delta_Ci_Differ_S4 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S4; + int Delta_Ci_Differ_S5 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S5; + int Delta_Ci_Differ_S6 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S6; + + int Delta_Min = 0, Delta_Max = 0; + + int Critical_Delta_S1 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S1; + int Critical_Delta_S2 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S2; + int Critical_Delta_S3 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S3; + int Critical_Delta_S4 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S4; + int Critical_Delta_S5 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S5; + int Critical_Delta_S6 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S6; + + bool bUseCriticalValue = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Set_Critical; + + bool bCriticalResult = false; + + + + int Sort1Min, Sort2Min, Sort3Min, Sort4Min, Sort5Min, Sort6Min; + int Sort1Max, Sort2Max, Sort3Max, Sort4Max, Sort5Max, Sort6Max; + int Sort1Min_ChNum, Sort2Min_ChNum, Sort3Min_ChNum, Sort4Min_ChNum, Sort5Min_ChNum, Sort6Min_ChNum; + int Sort1Max_ChNum, Sort2Max_ChNum, Sort3Max_ChNum, Sort4Max_ChNum, Sort5Max_ChNum, Sort6Max_ChNum; + bool bUseSort1 = false; + bool bUseSort2 = false; + bool bUseSort3 = false; + bool bUseSort4 = false; + bool bUseSort5 = false; + bool bUseSort6 = false; + + int Num = 0; + + int Key_Delta_Max = 0; + int SetKeyMax = 0; + int set_Delta_Cb_Max = 0; + + printk("\r\n\r\n==============================Test Item: -------- Delta CB Test "); + + for (i = 0; i < readlen; i++) + { + m_DeltaCbData[i] = m_TempCbData[i] - m_CbData[i]; + if (i == 0) + { + printk("\r\n\r\n//======= Delta CB Data: "); + printk("\r\nLeft Channel: "); + } + else if (i * 2 == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nRight Channel: "); + } + else if (i == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nKey: "); + } + printk("%3d ", m_DeltaCbData[i]); + + } + printk("\r\n\r\n"); + + + for (i = 0; i < readlen; i++) + { + m_DeltaCb_DifferData[i] = m_DeltaCbData[i] - g_stCfg_SCap_DetailThreshold.DeltaCbTest_Base[i]; + + if (i == 0) + { + printk("\r\n\r\n//======= Differ Data of Delta CB: "); + printk("\r\nLeft Channel: "); + } + else if (i * 2 == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nRight Channel: "); + } + else if (i == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nKey: "); + } + printk("%3d ", m_DeltaCb_DifferData[i]); + } + printk("\r\n\r\n"); + + Delta_Ci_Differ = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S1; + Delta_Ci_Differ_S2 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S2; + Delta_Ci_Differ_S3 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S3; + Delta_Ci_Differ_S4 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S4; + Delta_Ci_Differ_S5 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S5; + Delta_Ci_Differ_S6 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Deviation_S6; + + Delta_Min = 0; + Delta_Max = 0; + + Critical_Delta_S1 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S1; + Critical_Delta_S2 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S2; + Critical_Delta_S3 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S3; + Critical_Delta_S4 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S4; + Critical_Delta_S5 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S5; + Critical_Delta_S6 = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Critical_S6; + + bUseCriticalValue = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Set_Critical; + + bCriticalResult = false; + + + + bUseSort1 = false; + bUseSort2 = false; + bUseSort3 = false; + bUseSort4 = false; + bUseSort5 = false; + bUseSort6 = false; + + Num = 0; + + Sort1Min_ChNum = Sort2Min_ChNum = Sort3Min_ChNum = Sort4Min_ChNum = Sort5Min_ChNum = Sort6Min_ChNum = 0; + Sort1Max_ChNum = Sort2Max_ChNum = Sort3Max_ChNum = Sort4Max_ChNum = Sort5Max_ChNum = Sort6Max_ChNum = 0; + + Sort1Min = Sort2Min = Sort3Min = Sort4Min = Sort5Min = Sort6Min = 1000; + Sort1Max = Sort2Max = Sort3Max = Sort4Max = Sort5Max = Sort6Max = -1000; + + for (i = 0; i < g_ScreenSetParam.iChannelsNum/*readlen*/; i++) + { + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 1) + { + bUseSort1 = true; + if (m_DeltaCb_DifferData[i] < Sort1Min) + { + Sort1Min = m_DeltaCb_DifferData[i]; + Sort1Min_ChNum = i; + } + if (m_DeltaCb_DifferData[i] > Sort1Max) + { + Sort1Max = m_DeltaCb_DifferData[i]; + Sort1Max_ChNum = i; + } + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 2) + { + bUseSort2 = true; + if (m_DeltaCb_DifferData[i] < Sort2Min) + { + Sort2Min = m_DeltaCb_DifferData[i]; + Sort2Min_ChNum = i; + } + if (m_DeltaCb_DifferData[i] > Sort2Max) + { + Sort2Max = m_DeltaCb_DifferData[i]; + Sort2Max_ChNum = i; + } + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 3) + { + bUseSort3 = true; + if (m_DeltaCb_DifferData[i] < Sort3Min) + { + Sort3Min = m_DeltaCb_DifferData[i]; + Sort3Min_ChNum = i; + } + if (m_DeltaCb_DifferData[i] > Sort3Max) + { + Sort3Max = m_DeltaCb_DifferData[i]; + Sort3Max_ChNum = i; + } + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 4) + { + bUseSort4 = true; + if (m_DeltaCb_DifferData[i] < Sort4Min) + { + Sort4Min = m_DeltaCb_DifferData[i]; + Sort4Min_ChNum = i; + } + if (m_DeltaCb_DifferData[i] > Sort4Max) + { + Sort4Max = m_DeltaCb_DifferData[i]; + Sort4Max_ChNum = i; + } + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 5) + { + bUseSort5 = true; + if (m_DeltaCb_DifferData[i] < Sort5Min) + { + Sort5Min = m_DeltaCb_DifferData[i]; + Sort5Min_ChNum = i; + } + if (m_DeltaCb_DifferData[i] > Sort5Max) + { + Sort5Max = m_DeltaCb_DifferData[i]; + Sort5Max_ChNum = i; + } + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 6) + { + bUseSort6 = true; + if (m_DeltaCb_DifferData[i] < Sort6Min) + { + Sort6Min = m_DeltaCb_DifferData[i]; + Sort6Min_ChNum = i; + } + if (m_DeltaCb_DifferData[i] > Sort6Max) + { + Sort6Max = m_DeltaCb_DifferData[i]; + Sort6Max_ChNum = i; + } + } + + + } + if (bUseSort1) + { + if (Delta_Ci_Differ <= Sort1Max - Sort1Min) + { + if (bUseCriticalValue) + { + if (Sort1Max - Sort1Min >= Critical_Delta_S1) + { + btmpresult = false; + } + else + { + if (focal_abs(Sort1Max) > focal_abs(Sort1Min)) + Num = Sort1Max_ChNum; + else + Num = Sort1Min_ChNum; + + + bCriticalResult = true; + } + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Critical Deviation of Sort1: %d", + Sort1Max, Sort1Min, Sort1Max - Sort1Min, Critical_Delta_S1); + } + else + { + btmpresult = false; + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort1: %d", + Sort1Max, Sort1Min, Sort1Max - Sort1Min, Delta_Ci_Differ); + } + } + else + { + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort1: %d", + Sort1Max, Sort1Min, Sort1Max - Sort1Min, Delta_Ci_Differ); + } + + printk("\r\nMax Deviation,Sort1: %d, ", Sort1Max - Sort1Min); + } + if (bUseSort2) + { + + if (Delta_Ci_Differ_S2 <= Sort2Max - Sort2Min) + { + if (bUseCriticalValue) + { + if (Sort2Max - Sort2Min >= Critical_Delta_S2) + { + btmpresult = false; + } + else + { + if (focal_abs(Sort2Max) > focal_abs(Sort2Min)) + Num = Sort2Max_ChNum; + else + Num = Sort2Min_ChNum; + + bCriticalResult = true; + } + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Critical Deviation of Sort2: %d", + Sort2Max, Sort2Min, Sort2Max - Sort2Min, Critical_Delta_S2); + } + else + { + btmpresult = false; + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort2: %d", + Sort2Max, Sort2Min, Sort2Max - Sort2Min, Delta_Ci_Differ_S2); + } + } + else + { + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort2: %d", + Sort2Max, Sort2Min, Sort2Max - Sort2Min, Delta_Ci_Differ_S2); + } + + printk("\r\nSort2: %d, ", Sort2Max - Sort2Min); + } + if (bUseSort3) + { + + if (Delta_Ci_Differ_S3 <= Sort3Max - Sort3Min) + { + if (bUseCriticalValue) + { + if (Sort3Max - Sort3Min >= Critical_Delta_S3) + { + btmpresult = false; + } + else + { + if (focal_abs(Sort3Max) > focal_abs(Sort3Min)) + Num = Sort3Max_ChNum; + else + Num = Sort3Min_ChNum; + + bCriticalResult = true; + } + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Critical Deviation of Sort3: %d", + Sort3Max, Sort3Min, Sort3Max - Sort3Min, Critical_Delta_S3); + } + else + { + btmpresult = false; + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort3: %d", + Sort3Max, Sort3Min, Sort3Max - Sort3Min, Delta_Ci_Differ_S3); + + } + } + else + { + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort3: %d", + Sort3Max, Sort3Min, Sort3Max - Sort3Min, Delta_Ci_Differ_S3); + + } + printk("\r\nSort3: %d, ", Sort3Max - Sort3Min); + } + if (bUseSort4) + { + if (Delta_Ci_Differ_S4 <= Sort4Max - Sort4Min) + { + if (bUseCriticalValue) + { + if (Sort4Max - Sort4Min >= Critical_Delta_S4) + { + btmpresult = false; + } + else + { + if (focal_abs(Sort4Max) > focal_abs(Sort4Min)) + Num = Sort4Max_ChNum; + else + Num = Sort4Min_ChNum; + + bCriticalResult = true; + } + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Critical Deviation of Sort4: %d", + Sort4Max, Sort4Min, Sort4Max - Sort4Min, Critical_Delta_S4); + + } + else + { + btmpresult = false; + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort4: %d", + Sort4Max, Sort4Min, Sort4Max - Sort4Min, Delta_Ci_Differ_S4); + + } + } + else + { + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort4: %d", + Sort4Max, Sort4Min, Sort4Max - Sort4Min, Delta_Ci_Differ_S4); + + } + printk("\r\nSort4: %d, ", Sort4Max - Sort4Min); + } + if (bUseSort5) + { + if (Delta_Ci_Differ_S5 <= Sort5Max - Sort5Min) + { + if (bUseCriticalValue) + { + if (Sort5Max - Sort5Min >= Critical_Delta_S5) + { + btmpresult = false; + } + else + { + if (focal_abs(Sort5Max) > focal_abs(Sort5Min)) + Num = Sort5Max_ChNum; + else + Num = Sort5Min_ChNum; + + bCriticalResult = true; + } + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Critical Deviation of Sort5: %d", + Sort5Max, Sort5Min, Sort5Max - Sort5Min, Critical_Delta_S5); + + } + else + { + btmpresult = false; + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort5: %d", + Sort5Max, Sort5Min, Sort5Max - Sort5Min, Delta_Ci_Differ_S5); + + } + } + else + { + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort5: %d", + Sort5Max, Sort5Min, Sort5Max - Sort5Min, Delta_Ci_Differ_S5); + + } + printk("\r\nSort5: %d, ", Sort5Max - Sort5Min); + } + if (bUseSort6) + { + if (Delta_Ci_Differ_S6 <= Sort6Max - Sort6Min) + { + if (bUseCriticalValue) + { + if (Sort6Max - Sort6Min >= Critical_Delta_S6) + { + btmpresult = false; + } + else + { + if (focal_abs(Sort6Max) > focal_abs(Sort6Min)) + Num = Sort6Max_ChNum; + else + Num = Sort6Min_ChNum; + + bCriticalResult = true; + } + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Critical Deviation of Sort6: %d", + Sort6Max, Sort6Min, Sort6Max - Sort6Min, Critical_Delta_S6); + } + else + { + btmpresult = false; + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort6: %d", + Sort6Max, Sort6Min, Sort6Max - Sort6Min, Delta_Ci_Differ_S6); + + } + } + else + { + printk("\r\n\r\n// Condition1: Max of Delta CB_Differ: %d, Min of Delta CB_Differ: %d, Get Deviation: %d, Set Deviation of Sort6: %d", + Sort6Max, Sort6Min, Sort6Max - Sort6Min, Delta_Ci_Differ_S6); + + } + printk("\r\nSort6: %d, ", Sort6Max - Sort6Min); + } + + Delta_Min = Delta_Max = focal_abs(m_DeltaCb_DifferData[0]); + for (i = 1; i < g_ScreenSetParam.iChannelsNum/*readlen*/; i++) + { + if (focal_abs(m_DeltaCb_DifferData[i]) < Delta_Min) + { + Delta_Min = focal_abs(m_DeltaCb_DifferData[i]); + } + if (focal_abs(m_DeltaCb_DifferData[i]) > Delta_Max) + { + Delta_Max = focal_abs(m_DeltaCb_DifferData[i]); + } + } + + set_Delta_Cb_Max = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Differ_Max; + if (set_Delta_Cb_Max < focal_abs(Delta_Max)) + { + btmpresult = false; + } + printk("\r\n\r\n// Condition2: Get Max Differ Data of Delta_CB(abs): %d, Set Max Differ Data of Delta_CB(abs): %d", Delta_Max, set_Delta_Cb_Max); + + + if (g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Include_Key_Test) + { + + SetKeyMax = g_stCfg_FT6X36_BasicThreshold.DeltaCbTest_Key_Differ_Max; + + Key_Delta_Max = focal_abs(m_DeltaCb_DifferData[g_ScreenSetParam.iChannelsNum]); + for (i = g_ScreenSetParam.iChannelsNum; i < g_ScreenSetParam.iChannelsNum + g_ScreenSetParam.iKeyNum; i++) + { + if (focal_abs(m_DeltaCb_DifferData[i]) > Key_Delta_Max) + { + Key_Delta_Max = focal_abs(m_DeltaCb_DifferData[i]); + } + } + if (SetKeyMax <= Key_Delta_Max) + { + btmpresult = false; + } + printk("\r\n\r\n// Condition3: Include Key Test, Get Max Key Data: %d, Set Max Key Data: %d", Key_Delta_Max, SetKeyMax); + } + + printk("\r\nMax Differ Data of Delta_CB(abs): %d ", Delta_Max); + + if (bCriticalResult && btmpresult) + { + printk("\r\n\r\nDelta CB Test has Critical Result(TBD)!"); + } + + if (btmpresult) + { + printk("\r\n\r\n//Delta CB Test is OK!\r\n"); + + if (bCriticalResult) + * bTestResult = 2; + else + * bTestResult = 1; + } + else + { + printk("\r\n\r\n//Delta CB Test is NG!\r\n"); + * bTestResult = 0; + } + + Save_Test_Data(m_DeltaCbData, 0, 1, g_ScreenSetParam.iChannelsNum+g_ScreenSetParam.iKeyNum, 1); + Save_Test_Data(m_DeltaCb_DifferData, 0, 1, g_ScreenSetParam.iChannelsNum+g_ScreenSetParam.iKeyNum, 2); + return 0; +} + +/************************************************************************ +* Name: FT6X36_TestItem_ChannelsDeviationTest +* Brief: TestItem: Channels Deviation Test. Check if Channels Deviation is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT6X36_TestItem_ChannelsDeviationTest(unsigned char *bTestResult) +{ + + + bool btmpresult = true; + int i = 0; + + int DeviationMax_S1 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S1; + int DeviationMax_S2 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S2; + int DeviationMax_S3 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S3; + int DeviationMax_S4 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S4; + int DeviationMax_S5 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S5; + int DeviationMax_S6 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S6; + + int Delta_Min = 0, Delta_Max = 0; + + int Critical_Channel_S1 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S1; + int Critical_Channel_S2 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S2; + int Critical_Channel_S3 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S3; + int Critical_Channel_S4 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S4; + int Critical_Channel_S5 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S5; + int Critical_Channel_S6 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S6; + + bool bUseCriticalValue = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Set_Critical; + + bool bCriticalResult = false; + + + int Sort1LastNum = 0xFFFF, Sort2LastNum = 0xFFFF, Sort3LastNum = 0xFFFF, Sort4LastNum = 0xFFFF, Sort5LastNum = 0xFFFF, Sort6LastNum = 0xFFFF; + int GetDeviation; + bool bFirstUseSort1 = true; + bool bFirstUseSort2 = true; + bool bFirstUseSort3 = true; + bool bFirstUseSort4 = true; + bool bFirstUseSort5 = true; + bool bFirstUseSort6 = true; + + int MaxDev_AllS1 = 0, MaxDev_AllS2 = 0, MaxDev_AllS3 = 0, MaxDev_AllS4 = 0, MaxDev_AllS5 = 0, MaxDev_AllS6 = 0; + + printk("\r\n\r\n==============================Test Item: -------- Channels Deviation Test "); + + for (i = 0; i < g_ScreenSetParam.iChannelsNum; i++) + { + m_DeltaCb_DifferData[i] = m_DeltaCbData[i] - g_stCfg_SCap_DetailThreshold.DeltaCbTest_Base[i]; + if (i == 0) + { + printk("\r\n\r\n//======= Differ Data of Delta CB: "); + printk("\r\nLeft Channel: "); + } + else if (i * 2 == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nRight Channel: "); + } + else if (i == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nKey: "); + } + printk("%3d ", m_DeltaCb_DifferData[i]); + } + + printk("\r\n"); + + DeviationMax_S1 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S1; + DeviationMax_S2 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S2; + DeviationMax_S3 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S3; + DeviationMax_S4 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S4; + DeviationMax_S5 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S5; + DeviationMax_S6 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Deviation_S6; + + Delta_Min = 0; + Delta_Max = 0; + + Critical_Channel_S1 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S1; + Critical_Channel_S2 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S2; + Critical_Channel_S3 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S3; + Critical_Channel_S4 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S4; + Critical_Channel_S5 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S5; + Critical_Channel_S6 = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Critical_S6; + + bUseCriticalValue = g_stCfg_FT6X36_BasicThreshold.ChannelsDeviationTest_Set_Critical; + + bCriticalResult = false; + + + Sort1LastNum = 0xFFFF; + Sort2LastNum = 0xFFFF; + Sort3LastNum = 0xFFFF; + Sort4LastNum = 0xFFFF; + Sort5LastNum = 0xFFFF; + Sort6LastNum = 0xFFFF; + GetDeviation = 0; + bFirstUseSort1 = true; + bFirstUseSort2 = true; + bFirstUseSort3 = true; + bFirstUseSort4 = true; + bFirstUseSort5 = true; + bFirstUseSort6 = true; + + MaxDev_AllS1 = 0; + MaxDev_AllS2 = 0; + MaxDev_AllS3 = 0; + MaxDev_AllS4 = 0; + MaxDev_AllS5 = 0; + MaxDev_AllS6 = 0; + + for (i = 0; i < g_ScreenSetParam.iChannelsNum/*readlen*/; i++) + { + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 1) + { + if (bFirstUseSort1) + { + bFirstUseSort1 = false; + } + else + { + if (Sort1LastNum + 1 == i) + { + + if (Sort1LastNum <= g_ScreenSetParam.iChannelsNum/2 - 1 && i >= g_ScreenSetParam.iChannelsNum/2) + { + Sort1LastNum = i; + continue; + } + else if (Sort1LastNum <= g_ScreenSetParam.iChannelsNum/4 - 1 && i >= g_ScreenSetParam.iChannelsNum/4) + { + Sort1LastNum = i; + continue; + } + else if (Sort1LastNum <= g_ScreenSetParam.iChannelsNum * 3/4 - 1 && i >= g_ScreenSetParam.iChannelsNum * 3/4) + { + Sort1LastNum = i; + continue; + } + else + { + GetDeviation = focal_abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[Sort1LastNum]); + if (GetDeviation >= DeviationMax_S1) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_Channel_S1) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation 0f Sort1: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, Critical_Channel_S1); + + } + else + { + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation 0f Sort1: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, DeviationMax_S1); + + } + } + if (MaxDev_AllS1 < GetDeviation) + MaxDev_AllS1 = GetDeviation; + } + } + + } + Sort1LastNum = i; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 2) + { + if (bFirstUseSort2) + { + bFirstUseSort2 = false; + } + else + { + if (Sort2LastNum + 1 == i) + { + if (Sort2LastNum <= g_ScreenSetParam.iChannelsNum/2 - 1 && i >= g_ScreenSetParam.iChannelsNum/2) + { + Sort2LastNum = i; + continue; + } + else if (Sort2LastNum <= g_ScreenSetParam.iChannelsNum/4 - 1 && i >= g_ScreenSetParam.iChannelsNum/4) + { + Sort2LastNum = i; + continue; + } + else if (Sort2LastNum <= g_ScreenSetParam.iChannelsNum * 3/4 - 1 && i >= g_ScreenSetParam.iChannelsNum * 3/4) + { + Sort2LastNum = i; + continue; + } + GetDeviation = focal_abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[Sort2LastNum]); + if (GetDeviation >= DeviationMax_S2) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_Channel_S2) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation 0f Sort2: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, Critical_Channel_S2); + + } + else + { + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort2: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, DeviationMax_S2); + + } + } + if (MaxDev_AllS2 < GetDeviation) + MaxDev_AllS2 = GetDeviation; + } + + } + Sort2LastNum = i; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 3) + { + if (bFirstUseSort3) + { + bFirstUseSort3 = false; + } + else + { + if (Sort3LastNum + 1 == i) + { + if (Sort3LastNum <= g_ScreenSetParam.iChannelsNum/2 - 1 && i >= g_ScreenSetParam.iChannelsNum/2) + { + Sort3LastNum = i; + continue; + } + else if (Sort3LastNum <= g_ScreenSetParam.iChannelsNum/4 - 1 && i >= g_ScreenSetParam.iChannelsNum/4) + { + Sort3LastNum = i; + continue; + } + else if (Sort3LastNum <= g_ScreenSetParam.iChannelsNum * 3/4 - 1 && i >= g_ScreenSetParam.iChannelsNum * 3/4) + { + Sort3LastNum = i; + continue; + } + GetDeviation = focal_abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[Sort3LastNum]); + if (GetDeviation >= DeviationMax_S3) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_Channel_S3) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation 0f Sort3: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, Critical_Channel_S3); + + } + else + { + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort3: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, DeviationMax_S3); + + } + } + if (MaxDev_AllS3 < GetDeviation) + MaxDev_AllS3 = GetDeviation; + } + } + Sort3LastNum = i; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 4) + { + if (bFirstUseSort4) + { + bFirstUseSort4 = false; + } + else + { + if (Sort4LastNum + 1 == i) + { + if (Sort4LastNum <= g_ScreenSetParam.iChannelsNum/2 - 1 && i >= g_ScreenSetParam.iChannelsNum/2) + { + Sort4LastNum = i; + continue; + } + else if (Sort4LastNum <= g_ScreenSetParam.iChannelsNum/4 - 1 && i >= g_ScreenSetParam.iChannelsNum/4) + { + Sort4LastNum = i; + continue; + } + else if (Sort4LastNum <= g_ScreenSetParam.iChannelsNum * 3/4 - 1 && i >= g_ScreenSetParam.iChannelsNum * 3/4) + { + Sort4LastNum = i; + continue; + } + GetDeviation = focal_abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[Sort4LastNum]); + if (GetDeviation >= DeviationMax_S4) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_Channel_S4) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation 0f Sort4: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, Critical_Channel_S4); + + } + else + { + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort4: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, DeviationMax_S4); + + } + } + if (MaxDev_AllS4 < GetDeviation) + MaxDev_AllS4 = GetDeviation; + } + } + Sort4LastNum = i; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 5) + { + if (bFirstUseSort5) + { + bFirstUseSort5 = false; + } + else + { + if (Sort5LastNum + 1 == i) + { + if (Sort5LastNum <= g_ScreenSetParam.iChannelsNum/2 - 1 && i >= g_ScreenSetParam.iChannelsNum/2) + { + Sort5LastNum = i; + continue; + } + else if (Sort5LastNum <= g_ScreenSetParam.iChannelsNum/4 - 1 && i >= g_ScreenSetParam.iChannelsNum/4) + { + Sort5LastNum = i; + continue; + } + else if (Sort5LastNum <= g_ScreenSetParam.iChannelsNum * 3/4 - 1 && i >= g_ScreenSetParam.iChannelsNum * 3/4) + { + Sort5LastNum = i; + continue; + } + GetDeviation = focal_abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[Sort5LastNum]); + if (GetDeviation >= DeviationMax_S5) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_Channel_S5) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation 0f Sort5: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, Critical_Channel_S5); + + } + else + { + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort5: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, DeviationMax_S5); + + } + } + if (MaxDev_AllS5 < GetDeviation) + MaxDev_AllS5 = GetDeviation; + } + } + Sort5LastNum = i; + } + + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 6) + { + if (bFirstUseSort6) + { + bFirstUseSort6 = false; + } + else + { + if (Sort6LastNum + 1 == i) + { + if (Sort6LastNum <= g_ScreenSetParam.iChannelsNum/2 - 1 && i >= g_ScreenSetParam.iChannelsNum/2) + { + Sort6LastNum = i; + continue; + } + else if (Sort6LastNum <= g_ScreenSetParam.iChannelsNum/4 - 1 && i >= g_ScreenSetParam.iChannelsNum/4) + { + Sort6LastNum = i; + continue; + } + else if (Sort6LastNum <= g_ScreenSetParam.iChannelsNum * 3/4 - 1 && i >= g_ScreenSetParam.iChannelsNum * 3/4) + { + Sort6LastNum = i; + continue; + } + GetDeviation = focal_abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[Sort6LastNum]); + if (GetDeviation >= DeviationMax_S6) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_Channel_S6) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation 0f Sort6: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, Critical_Channel_S6); + + } + else + { + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort6: %d", + i-1 + 1, m_DeltaCb_DifferData[i-1], i + 1, m_DeltaCb_DifferData[i], GetDeviation, DeviationMax_S6); + + } + } + if (MaxDev_AllS6 < GetDeviation) + MaxDev_AllS6 = GetDeviation; + } + } + Sort6LastNum = i; + } + } + if (!bFirstUseSort1) + { + printk("\r\n\r\nGet max deviation of Sort1: %d, Set max deviation of Sort1: %d", MaxDev_AllS1, DeviationMax_S1); + + } + if (!bFirstUseSort2) + { + printk("\r\n\r\nGet max deviation of Sort2: %d, Set max deviation of Sort2: %d", MaxDev_AllS2, DeviationMax_S2); + + } + if (!bFirstUseSort3) + { + printk("\r\n\r\nGet max deviation of Sort3: %d, Set max deviation of Sort3: %d", MaxDev_AllS3, DeviationMax_S3); + + } + if (!bFirstUseSort4) + { + printk("\r\n\r\nGet max deviation of Sort4: %d, Set max deviation of Sort4: %d", MaxDev_AllS4, DeviationMax_S4); + + } + if (!bFirstUseSort5) + { + printk("\r\n\r\nGet max deviation of Sort5: %d, Set max deviation of Sort5: %d", MaxDev_AllS5, DeviationMax_S5); + + } + if (!bFirstUseSort6) + { + printk("\r\n\r\nGet max deviation of Sort6: %d, Set max deviation of Sort6: %d", MaxDev_AllS6, DeviationMax_S6); + + } + + printk("\r\n\r\nMax Deviation, "); + if (!bFirstUseSort1) + { + printk("Sort1: %d, ", MaxDev_AllS1); + } + if (!bFirstUseSort2) + { + printk("Sort2: %d, ", MaxDev_AllS2); + } + if (!bFirstUseSort3) + { + printk("Sort3: %d, ", MaxDev_AllS3); + } + if (!bFirstUseSort4) + { + printk("Sort4: %d, ", MaxDev_AllS4); + } + if (!bFirstUseSort5) + { + printk("Sort5: %d, ", MaxDev_AllS5); + } + if (!bFirstUseSort6) + { + printk("Sort6: %d, ", MaxDev_AllS6); + } + + if (bCriticalResult && btmpresult) + { + printk("\r\n\r\nChannels Deviation Test has Critical Result(TBD)!"); + } + + if (btmpresult) + { + printk("\r\n\r\n//Channels Deviation Test is OK!\r\n"); + * bTestResult = true; + if (bCriticalResult) + * bTestResult = 2; + else + * bTestResult = true; + } + else + { + * bTestResult = false; + printk("\r\n\r\n//Channels Deviation Test is NG!\r\n"); + } + + return 0; +} + +/************************************************************************ +* Name: FT6X36_TestItem_TwoSidesDeviationTest +* Brief: TestItem: Two Sides Deviation Test. Check if Two Sides Deviation is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT6X36_TestItem_TwoSidesDeviationTest(unsigned char *bTestResult) +{ + + + bool btmpresult = true; + int i = 0; + + int DeviationMax = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S1; + int DeviationMax_S2 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S2; + int DeviationMax_S3 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S3; + int DeviationMax_S4 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S4; + int DeviationMax_S5 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S5; + int DeviationMax_S6 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S6; + + int Critical_TwoSides_S1 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S1; + int Critical_TwoSides_S2 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S2; + int Critical_TwoSides_S3 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S3; + int Critical_TwoSides_S4 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S4; + int Critical_TwoSides_S5 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S5; + int Critical_TwoSides_S6 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S6; + + bool bUseCriticalValue = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Set_Critical; + + bool bCriticalResult = false; + + + bool bUseSort1 = false; + bool bUseSort2 = false; + bool bUseSort3 = false; + bool bUseSort4 = false; + bool bUseSort5 = false; + bool bUseSort6 = false; + + int DevMax_AllS1 = 0, DevMax_AllS2 = 0, DevMax_AllS3 = 0, DevMax_AllS4 = 0, DevMax_AllS5 = 0, DevMax_AllS6 = 0; + + int GetDeviation = 0; + + printk("\r\n\r\n==============================Test Item: -------- Two Sides Deviation Test "); + + for (i = 0; i < g_ScreenSetParam.iChannelsNum; i++) + { + m_DeltaCb_DifferData[i] = m_DeltaCbData[i] - g_stCfg_SCap_DetailThreshold.DeltaCbTest_Base[i]; + if (i == 0) + { + printk("\r\n\r\n//======= Differ Data of Delta CB: "); + printk("\r\nLeft Channel: "); + } + else if (i * 2 == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nRight Channel: "); + } + else if (i == g_ScreenSetParam.iChannelsNum) + { + printk("\r\nKey: "); + } + printk("%3d ", m_DeltaCb_DifferData[i]); + } + + printk("\r\n"); + + DeviationMax = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S1; + DeviationMax_S2 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S2; + DeviationMax_S3 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S3; + DeviationMax_S4 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S4; + DeviationMax_S5 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S5; + DeviationMax_S6 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Deviation_S6; + + Critical_TwoSides_S1 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S1; + Critical_TwoSides_S2 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S2; + Critical_TwoSides_S3 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S3; + Critical_TwoSides_S4 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S4; + Critical_TwoSides_S5 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S5; + Critical_TwoSides_S6 = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Critical_S6; + + bUseCriticalValue = g_stCfg_FT6X36_BasicThreshold.TwoSidesDeviationTest_Set_Critical; + + bCriticalResult = false; + + bUseSort1 = false; + bUseSort2 = false; + bUseSort3 = false; + bUseSort4 = false; + bUseSort5 = false; + bUseSort6 = false; + + DevMax_AllS1 = 0; + DevMax_AllS2 = 0; + DevMax_AllS3 = 0; + DevMax_AllS4 = 0; + DevMax_AllS5 = 0; + DevMax_AllS6 = 0; + + GetDeviation = 0; + + for (i = 0; i < g_ScreenSetParam.iChannelsNum/2; i++) + { + GetDeviation = abs(m_DeltaCb_DifferData[i] - m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2]); + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 1) + { + bUseSort1 = true; + if (GetDeviation >= DeviationMax) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_TwoSides_S1) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation of Sort1: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, Critical_TwoSides_S1); + + } + else + { + + + + + + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort1: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, DeviationMax); + + } + } + if (DevMax_AllS1 < GetDeviation) + DevMax_AllS1 = GetDeviation; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 2) + { + bUseSort2 = true; + if (GetDeviation >= DeviationMax_S2) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_TwoSides_S2) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation of Sort2: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, Critical_TwoSides_S2); + + } + else + { + + + + + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort2: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, DeviationMax_S2); + + } + } + if (DevMax_AllS2 < GetDeviation) + DevMax_AllS2 = GetDeviation; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 3) + { + bUseSort3 = true; + if (GetDeviation >= DeviationMax_S3) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_TwoSides_S3) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation of Sort3: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, Critical_TwoSides_S3); + + } + else + { + + + + + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort3: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, DeviationMax_S3); + + } + } + if (DevMax_AllS3 < GetDeviation) + DevMax_AllS3 = GetDeviation; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 4) + { + bUseSort4 = true; + if (GetDeviation >= DeviationMax_S4) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_TwoSides_S4) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation of Sort4: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, Critical_TwoSides_S4); + + } + else + { + + + + + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort4: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, DeviationMax_S4); + + } + } + if (DevMax_AllS4 < GetDeviation) + DevMax_AllS4 = GetDeviation; + } + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 5) + { + bUseSort5 = true; + if (GetDeviation >= DeviationMax_S5) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_TwoSides_S5) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation of Sort5: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, Critical_TwoSides_S5); + + } + else + { + + + + + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort5: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, DeviationMax_S5); + + } + } + if (DevMax_AllS5 < GetDeviation) + DevMax_AllS5 = GetDeviation; + } + + + if (g_stCfg_SCap_DetailThreshold.DeltaCxTest_Sort[i] == 6) + { + bUseSort6 = true; + if (GetDeviation >= DeviationMax_S6) + { + if (bUseCriticalValue) + { + if (GetDeviation >= Critical_TwoSides_S6) + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Critical Deviation of Sort6: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, Critical_TwoSides_S6); + + } + else + { + + + + + + bCriticalResult = true; + } + } + else + { + btmpresult = false; + printk("\r\nCh_%2d, Value: %2d, Ch_%2d, Value: %2d, Deviation: %d, Set Max Deviation of Sort6: %d", + i + 1, m_DeltaCb_DifferData[i], i + g_ScreenSetParam.iChannelsNum/2, m_DeltaCb_DifferData[i + g_ScreenSetParam.iChannelsNum/2], GetDeviation, DeviationMax_S6); + + } + } + if (DevMax_AllS6 < GetDeviation) + DevMax_AllS6 = GetDeviation; + } + + } + if (bUseSort1) + { + printk("\r\n\r\nGet Max Deviation of Sort1: %d, Set Max Deviation of Sort1: %d", DevMax_AllS1, DeviationMax); + + } + if (bUseSort2) + { + printk("\r\n\r\nGet Max Deviation of Sort2: %d, Set Max Deviation of Sort2: %d", DevMax_AllS2, DeviationMax_S2); + + } + if (bUseSort3) + { + printk("\r\n\r\nGet Max Deviation of Sort3: %d, Set Max Deviation of Sort3: %d", DevMax_AllS3, DeviationMax_S3); + + } + if (bUseSort4) + { + printk("\r\n\r\nGet Max Deviation of Sort4: %d, Set Max Deviation of Sort4: %d", DevMax_AllS4, DeviationMax_S4); + + } + if (bUseSort5) + { + printk("\r\n\r\nGet Max Deviation of Sort5: %d, Set Max Deviation of Sort5: %d", DevMax_AllS5, DeviationMax_S5); + + } + if (bUseSort6) + { + printk("\r\n\r\nGet Max Deviation of Sort6: %d, Set Max Deviation of Sort6: %d", DevMax_AllS6, DeviationMax_S6); + + } + + printk("\r\nMax Deviation, "); + if (bUseSort1) + { + printk("Sort1: %d, ", DevMax_AllS1); + + } + if (bUseSort2) + { + printk("Sort2: %d, ", DevMax_AllS2); + + } + if (bUseSort3) + { + printk("Sort3: %d, ", DevMax_AllS3); + + } + if (bUseSort4) + { + printk("Sort4: %d, ", DevMax_AllS4); + + } + if (bUseSort5) + { + printk("Sort5: %d, ", DevMax_AllS5); + + } + if (bUseSort6) + { + printk("Sort6: %d, ", DevMax_AllS6); + + } + + if (bCriticalResult && btmpresult) + { + printk("\r\n\r\nTwo Sides Deviation Test has Critical Result(TBD)!"); + } + + if (btmpresult) + { + printk("\r\n\r\n//Two Sides Deviation Test is OK!\r\n"); + if (bCriticalResult) + * bTestResult = 2; + else + * bTestResult = true; + } + else + { + * bTestResult = false; + printk("\r\n\r\n//Two Sides Deviation Test is NG!\r\n"); + } + + return 0; +} diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT6X36.h b/drivers/input/touchscreen/ft5435/lib/Test_FT6X36.h new file mode 100644 index 0000000000000..161dda3324d25 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT6X36.h @@ -0,0 +1,33 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT6X36.h +* +* Author: Software Development Team, AE +* +* Created: 2015-10-08 +* +* Abstract: test item for FT6X36/FT3X07/FT6416/FT6426 +* +************************************************************************/ +#ifndef _TEST_FT6X36_H +#define _TEST_FT6X36_H + +#include "test_lib.h" + +boolean FT6X36_StartTest(void); +int FT6X36_get_test_data(char *pTestData); + +unsigned char FT6X36_TestItem_EnterFactoryMode(void); +unsigned char FT6X36_TestItem_RawDataTest(bool *bTestResult); + +unsigned char FT6X36_TestItem_CbTest(bool *bTestResult); +unsigned char FT6X36_TestItem_DeltaCbTest(unsigned char *bTestResult); +unsigned char FT6X36_TestItem_ChannelsDeviationTest(unsigned char *bTestResult); +unsigned char FT6X36_TestItem_TwoSidesDeviationTest(unsigned char *bTestResult); + +boolean GetWaterproofMode(int iTestType, unsigned char ucChannelValue); + + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT8606.c b/drivers/input/touchscreen/ft5435/lib/Test_FT8606.c new file mode 100644 index 0000000000000..d38469a027e86 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT8606.c @@ -0,0 +1,1416 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT8606.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test item for FT8606 +* +************************************************************************/ + +/******************************************************************************* +* Included header files +*******************************************************************************/ +#include +#include +#include + +#include "Global.h" +#include "Test_FT8606.h" +#include "DetailThreshold.h" +#include "Config_FT8606.h" + + +/******************************************************************************* +* Private constant and macro definitions using #define +*******************************************************************************/ +#define IC_TEST_VERSION "Test version: V1.0.0--2015-07-30, (sync version of FT_MultipleTest: V2.7.0.3--2015-07-13)" + +#define MAX_NOISE_FRAMES 32 + +#define DEVIDE_MODE_ADDR 0x00 +#define REG_LINE_NUM 0x01 +#define REG_TX_NUM 0x02 +#define REG_RX_NUM 0x03 +#define FT_8606_LEFT_KEY_REG 0X1E +#define FT_8606_RIGHT_KEY_REG 0X1F + +#define REG_CbAddrH 0x18 +#define REG_CbAddrL 0x19 +#define REG_OrderAddrH 0x1A +#define REG_OrderAddrL 0x1B + +#define REG_RawBuf0 0x6A +#define REG_RawBuf1 0x6B +#define REG_OrderBuf0 0x6C +#define REG_CbBuf0 0x6E + +#define REG_K1Delay 0x31 +#define REG_K2Delay 0x32 +#define REG_SCChannelCf 0x34 + +#define pre 1 + + +/******************************************************************************* +* Private enumerations, structures and unions using typedef +*******************************************************************************/ +struct structSCapConfEx +{ + unsigned char ChannelXNum; + unsigned char ChannelYNum; + unsigned char KeyNum; + unsigned char KeyNumTotal; + bool bLeftKey1; + bool bLeftKey2; + bool bLeftKey3; + bool bRightKey1; + bool bRightKey2; + bool bRightKey3; +}; +struct structSCapConfEx g_stSCapConfEx; + +enum NOISE_TYPE +{ + NT_AvgData = 0, + NT_MaxData = 1, + NT_MaxDevication = 2, + NT_DifferData = 3, +}; + +/******************************************************************************* +* Static variables +*******************************************************************************/ + +static int m_RawData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_NoiseData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_CBData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_AvgData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static int m_iTempData[TX_NUM_MAX][RX_NUM_MAX] = {{0, 0}}; +static BYTE m_ucTempData[TX_NUM_MAX * RX_NUM_MAX*2] = {0}; +static int m_iTempRawData[TX_NUM_MAX * RX_NUM_MAX] = {0}; +static int m_TempNoiseData[MAX_NOISE_FRAMES][RX_NUM_MAX * TX_NUM_MAX] = {{0, 0}}; + + + +static char g_pStoreAllData[1024*80] = {0}; +static char *g_pTmpBuff; +static char *g_pStoreMsgArea; +static int g_lenStoreMsgArea; +static char *g_pMsgAreaLine2; +static int g_lenMsgAreaLine2; +static char *g_pStoreDataArea; +static int g_lenStoreDataArea; +static unsigned char m_ucTestItemCode; +static int m_iStartLine; +static int m_iTestDataCount; + +/******************************************************************************* +* Global variable or extern global variabls/functions +*******************************************************************************/ + + +/******************************************************************************* +* Static function prototypes +*******************************************************************************/ + + +static int StartScan(void); +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer); +static unsigned char GetPanelRows(unsigned char *pPanelRows); +static unsigned char GetPanelCols(unsigned char *pPanelCols); +static unsigned char GetTxRxCB(unsigned short StartNodeNo, unsigned short ReadNum, unsigned char *pReadBuffer); + +static unsigned char GetRawData(void); +static unsigned char GetChannelNum(void); + + +static void InitTest(void); +static void FinishTest(void); +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount); +static void InitStoreParamOfTestData(void); +static void MergeAllTestData(void); + +static void AllocateMemory(void); +static void FreeMemory(void); +static unsigned int SqrtNew(unsigned int n) ; + +/************************************************************************ +* Name: FT5X46_StartTest +* Brief: Test entry. Determine which test item to test +* Input: none +* Output: none +* Return: Test Result, PASS or FAIL +***********************************************************************/ +boolean FT8606_StartTest() +{ + bool bTestResult = true, bTempResult = 1; + unsigned char ReCode; + unsigned char ucDevice = 0; + int iItemCount = 0; + + + + InitTest(); + + + if (0 == g_TestItemNum) + bTestResult = false; + + for (iItemCount = 0; iItemCount < g_TestItemNum; iItemCount++) + { + m_ucTestItemCode = g_stTestItem[ucDevice][iItemCount].ItemCode; + + + if (Code_FT8606_ENTER_FACTORY_MODE == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT8606_TestItem_EnterFactoryMode(); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + break; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + if (Code_FT8606_CHANNEL_NUM_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT8606_TestItem_ChannelsTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + break; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + + } + + + + + if (Code_FT8606_RAWDATA_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT8606_TestItem_RawDataTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + + if (Code_FT8606_NOISE_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + + ReCode = FT8606_TestItem_NoiseTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + + + + if (Code_FT8606_CB_TEST == g_stTestItem[ucDevice][iItemCount].ItemCode + ) + { + ReCode = FT8606_TestItem_CbTest(&bTempResult); + if (ERROR_CODE_OK != ReCode || (!bTempResult)) + { + bTestResult = false; + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_NG; + } + else + g_stTestItem[ucDevice][iItemCount].TestResult = RESULT_PASS; + } + + } + + + FinishTest(); + + + return bTestResult; + +} +/************************************************************************ +* Name: InitTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitTest(void) +{ + AllocateMemory(); + InitStoreParamOfTestData(); + + g_stSCapConfEx.ChannelXNum = 0; + g_stSCapConfEx.ChannelYNum = 0; + g_stSCapConfEx.KeyNum = 0; + g_stSCapConfEx.KeyNumTotal = 6; + + printk("[focal] %s \n", IC_TEST_VERSION); +} +/************************************************************************ +* Name: FinishTest +* Brief: Init all param before test +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FinishTest(void) +{ + MergeAllTestData(); + FreeMemory(); +} +/************************************************************************ +* Name: FT8606_get_test_data +* Brief: get data of test result +* Input: none +* Output: pTestData, the returned buff +* Return: the length of test data. if length > 0, got data;else ERR. +***********************************************************************/ +int FT8606_get_test_data(char *pTestData) +{ + if (NULL == pTestData) + { + printk("[focal] %s pTestData == NULL \n", __func__); + return -EPERM; + } + memcpy(pTestData, g_pStoreAllData, (g_lenStoreMsgArea+g_lenStoreDataArea)); + return (g_lenStoreMsgArea+g_lenStoreDataArea); +} + + +/************************************************************************ +* Name: AllocateMemory +* Brief: Allocate pointer Memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void AllocateMemory(void) +{ + + g_pStoreMsgArea = NULL; + if (NULL == g_pStoreMsgArea) + g_pStoreMsgArea = kmalloc(1024*80, GFP_ATOMIC); + g_pMsgAreaLine2 = NULL; + if (NULL == g_pMsgAreaLine2) + g_pMsgAreaLine2 = kmalloc(1024*80, GFP_ATOMIC); + g_pStoreDataArea = NULL; + if (NULL == g_pStoreDataArea) + g_pStoreDataArea = kmalloc(1024*80, GFP_ATOMIC); + /*g_pStoreAllData =NULL; + if(NULL == g_pStoreAllData) + g_pStoreAllData = kmalloc(1024*8, GFP_ATOMIC); + g_pTmpBuff =NULL;*/ + if (NULL == g_pTmpBuff) + g_pTmpBuff = kmalloc(1024*16, GFP_ATOMIC); + +} +/************************************************************************ +* Name: FreeMemory +* Brief: Release pointer memory +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void FreeMemory(void) +{ + + if (NULL != g_pStoreMsgArea) + kfree(g_pStoreMsgArea); + + if (NULL != g_pMsgAreaLine2) + kfree(g_pMsgAreaLine2); + + if (NULL != g_pStoreDataArea) + kfree(g_pStoreDataArea); + + /*if(NULL == g_pStoreAllData) + kfree(g_pStoreAllData);*/ + + if (NULL != g_pTmpBuff) + kfree(g_pTmpBuff); +} + +/************************************************************************ +* Name: InitStoreParamOfTestData +* Brief: Init store param of test data +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void InitStoreParamOfTestData(void) +{ + g_lenStoreMsgArea = 0; + + g_lenStoreMsgArea += sprintf(g_pStoreMsgArea, "ECC, 85, 170, IC Name, %s, IC Code, %x\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + + + + g_lenMsgAreaLine2 = 0; + + + + g_lenStoreDataArea = 0; + m_iStartLine = 11; + + m_iTestDataCount = 0; +} +/************************************************************************ +* Name: MergeAllTestData +* Brief: Merge All Data of test result +* Input: none +* Output: none +* Return: none +***********************************************************************/ +static void MergeAllTestData(void) +{ + int iLen = 0; + + + iLen = sprintf(g_pTmpBuff, "TestItem, %d, ", m_iTestDataCount); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pMsgAreaLine2, g_lenMsgAreaLine2); + g_lenStoreMsgArea+=g_lenMsgAreaLine2; + + + iLen = sprintf(g_pTmpBuff, "\n\n\n\n\n\n\n\n\n"); + memcpy(g_pStoreMsgArea+g_lenStoreMsgArea, g_pTmpBuff, iLen); + g_lenStoreMsgArea+=iLen; + + + memcpy(g_pStoreAllData, g_pStoreMsgArea, g_lenStoreMsgArea); + + + if (0 != g_lenStoreDataArea) + { + memcpy(g_pStoreAllData+g_lenStoreMsgArea, g_pStoreDataArea, g_lenStoreDataArea); + } + + printk("[focal] %s lenStoreMsgArea=%d, lenStoreDataArea = %d\n", __func__, g_lenStoreMsgArea, g_lenStoreDataArea); +} + + +/************************************************************************ +* Name: Save_Test_Data +* Brief: Storage format of test data +* Input: int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount +* Output: none +* Return: none +***********************************************************************/ +static void Save_Test_Data(int iData[TX_NUM_MAX][RX_NUM_MAX], int iArrayIndex, unsigned char Row, unsigned char Col, unsigned char ItemCount) +{ + int iLen = 0; + int i = 0, j = 0; + + + iLen = sprintf(g_pTmpBuff, "NA, %d, %d, %d, %d, %d, ", \ + m_ucTestItemCode, Row, Col, m_iStartLine, ItemCount); + memcpy(g_pMsgAreaLine2+g_lenMsgAreaLine2, g_pTmpBuff, iLen); + g_lenMsgAreaLine2 += iLen; + + m_iStartLine += Row; + m_iTestDataCount++; + + + for (i = 0+iArrayIndex; i < Row+iArrayIndex; i++) + { + for (j = 0; j < Col; j++) + { + if (j == (Col -1)) + iLen = sprintf(g_pTmpBuff, "%d, \n", iData[i][j]); + else + iLen = sprintf(g_pTmpBuff, "%d, ", iData[i][j]); + + memcpy(g_pStoreDataArea+g_lenStoreDataArea, g_pTmpBuff, iLen); + g_lenStoreDataArea += iLen; + } + } + +} + + +/************************************************************************ +* Name: StartScan(Same function name as FT_MultipleTest) +* Brief: Scan TP, do it before read Raw Data +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static int StartScan(void) +{ + unsigned char RegVal = 0x00; + unsigned char times = 0; + const unsigned char MaxTimes = 20; + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + + + + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + RegVal |= 0x80; + ReCode = WriteReg(DEVIDE_MODE_ADDR, RegVal); + if (ReCode == ERROR_CODE_OK) + { + while(times++ < MaxTimes) + { + SysDelay(8); + ReCode = ReadReg(DEVIDE_MODE_ADDR, &RegVal); + if (ReCode == ERROR_CODE_OK) + { + if ((RegVal>>7) == 0) break; + } + else + { + break; + } + } + if (times < MaxTimes) ReCode = ERROR_CODE_OK; + else ReCode = ERROR_CODE_COMM_ERROR; + } + } + return ReCode; + +} +/************************************************************************ +* Name: ReadRawData(Same function name as FT_MultipleTest) +* Brief: read Raw Data +* Input: Freq(No longer used, reserved), LineNum, ByteNum +* Output: pRevBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char ReadRawData(unsigned char Freq, unsigned char LineNum, int ByteNum, int *pRevBuffer) +{ + unsigned char ReCode = ERROR_CODE_COMM_ERROR; + unsigned char I2C_wBuffer[3] = {0}; + unsigned char pReadData[ByteNum]; + + int i, iReadNum; + unsigned short BytesNumInTestMode1 = 0; + + iReadNum = ByteNum/342; + + if (0 != (ByteNum%342)) iReadNum++; + + if (ByteNum <= 342) + { + BytesNumInTestMode1 = ByteNum; + } + else + { + BytesNumInTestMode1 = 342; + } + + ReCode = WriteReg(REG_LINE_NUM, LineNum); + + + + I2C_wBuffer[0] = REG_RawBuf0; + if (ReCode == ERROR_CODE_OK) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(I2C_wBuffer, 1, pReadData, BytesNumInTestMode1); + } + + for (i = 1; i < iReadNum; i++) + { + if (ReCode != ERROR_CODE_OK) break; + + if (i == iReadNum-1) + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, pReadData+342*i, ByteNum-342*i); + } + else + { + focal_msleep(10); + ReCode = Comm_Base_IIC_IO(NULL, 0, pReadData+342*i, 342); + } + + } + + if (ReCode == ERROR_CODE_OK) + { + for (i = 0; i < (ByteNum>>1); i++) + { + pRevBuffer[i] = (pReadData[i<<1]<<8)+pReadData[(i<<1)+1]; + + + } + } + + + return ReCode; + +} +/************************************************************************ +* Name: GetTxRxCB(Same function name as FT_MultipleTest) +* Brief: get CB of Tx/Rx +* Input: StartNodeNo, ReadNum +* Output: pReadBuffer +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetTxRxCB(unsigned short StartNodeNo, unsigned short ReadNum, unsigned char *pReadBuffer) +{ + unsigned char ReCode = ERROR_CODE_OK; + unsigned short usReturnNum = 0; + unsigned short usTotalReturnNum = 0; + unsigned char wBuffer[4]; + int i, iReadNum; + + iReadNum = ReadNum/342; + + if (0 != (ReadNum%342)) iReadNum++; + + wBuffer[0] = REG_CbBuf0; + + usTotalReturnNum = 0; + + for (i = 1; i <= iReadNum; i++) + { + if (i*342 > ReadNum) + usReturnNum = ReadNum - (i-1)*342; + else + usReturnNum = 342; + + wBuffer[1] = (StartNodeNo+usTotalReturnNum) >>8; + wBuffer[2] = (StartNodeNo+usTotalReturnNum)&0xff; + + ReCode = WriteReg(REG_CbAddrH, wBuffer[1]); + ReCode = WriteReg(REG_CbAddrL, wBuffer[2]); + + ReCode = Comm_Base_IIC_IO(wBuffer, 1, pReadBuffer+usTotalReturnNum, usReturnNum); + + usTotalReturnNum += usReturnNum; + + if (ReCode != ERROR_CODE_OK)return ReCode; + + + } + + return ReCode; +} + + +static unsigned char GetPanelRows(unsigned char *pPanelRows) +{ + return ReadReg(REG_TX_NUM, pPanelRows); +} + + +static unsigned char GetPanelCols(unsigned char *pPanelCols) +{ + return ReadReg(REG_RX_NUM, pPanelCols); +} + + + + + + +/************************************************************************ +* Name: FT8606_TestItem_EnterFactoryMode +* Brief: Check whether TP can enter Factory Mode, and do some thing +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT8606_TestItem_EnterFactoryMode(void) +{ + + unsigned char ReCode = ERROR_CODE_INVALID_PARAM; + int iRedo = 5; + int i ; + SysDelay(150); + printk("Enter factory mode...\n"); + for (i = 1; i <= iRedo; i++) + { + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter factory mode...\n"); + if (i < iRedo) + { + SysDelay(50); + continue; + } + } + else + { + + } + + } + SysDelay(300); + + if (ReCode == ERROR_CODE_OK) + { + ReCode = GetChannelNum(); + } + return ReCode; +} +/************************************************************************ +* Name: GetChannelNum +* Brief: Get Num of Ch_X, Ch_Y and key +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetChannelNum(void) +{ + unsigned char ReCode; + + int i ; + unsigned char rBuffer[1]; + + + + for (i = 0; i < 3; i++) + { + ReCode = GetPanelRows(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + if (0 < rBuffer[0] && rBuffer[0] < 80) + { + g_stSCapConfEx.ChannelXNum = rBuffer[0]; + if (g_stSCapConfEx.ChannelXNum > g_ScreenSetParam.iUsedMaxTxNum) + { + printk("Failed to get Channel X number, Get num = %d, UsedMaxNum = %d\n", + g_stSCapConfEx.ChannelXNum, g_ScreenSetParam.iUsedMaxTxNum); + return ERROR_CODE_INVALID_PARAM; + } + break; + } + else + { + SysDelay(150); + continue; + } + } + else + { + printk("Failed to get Channel X number\n"); + SysDelay(150); + } + } + + + for (i = 0; i < 3; i++) + { + ReCode = GetPanelCols(rBuffer); + if (ReCode == ERROR_CODE_OK) + { + if (0 < rBuffer[0] && rBuffer[0] < 80) + { + g_stSCapConfEx.ChannelYNum = rBuffer[0]; + if (g_stSCapConfEx.ChannelYNum > g_ScreenSetParam.iUsedMaxRxNum) + { + printk("Failed to get Channel Y number, Get num = %d, UsedMaxNum = %d\n", + g_stSCapConfEx.ChannelYNum, g_ScreenSetParam.iUsedMaxRxNum); + return ERROR_CODE_INVALID_PARAM; + } + break; + } + else + { + SysDelay(150); + continue; + } + } + else + { + printk("Failed to get Channel Y number\n"); + SysDelay(150); + } + } + + + for (i = 0; i < 3; i++) + { + unsigned char regData = 0; + g_stSCapConfEx.KeyNum = 0; + ReCode = ReadReg(FT_8606_LEFT_KEY_REG, ®Data); + if (ReCode == ERROR_CODE_OK) + { + if (((regData >> 0) & 0x01)) { g_stSCapConfEx.bLeftKey1 = true; ++g_stSCapConfEx.KeyNum; } + if (((regData >> 1) & 0x01)) { g_stSCapConfEx.bLeftKey2 = true; ++g_stSCapConfEx.KeyNum; } + if (((regData >> 2) & 0x01)) { g_stSCapConfEx.bLeftKey3 = true; ++g_stSCapConfEx.KeyNum; } + } + else + { + printk("Failed to get Key number\n"); + SysDelay(150); + continue; + } + ReCode = ReadReg(FT_8606_RIGHT_KEY_REG, ®Data); + if (ReCode == ERROR_CODE_OK) + { + if (((regData >> 0) & 0x01)) {g_stSCapConfEx.bRightKey1 = true; ++g_stSCapConfEx.KeyNum; } + if (((regData >> 1) & 0x01)) {g_stSCapConfEx.bRightKey2 = true; ++g_stSCapConfEx.KeyNum; } + if (((regData >> 2) & 0x01)) {g_stSCapConfEx.bRightKey3 = true; ++g_stSCapConfEx.KeyNum; } + break; + } + else + { + printk("Failed to get Key number\n"); + SysDelay(150); + continue; + } + } + + + + printk("CH_X = %d, CH_Y = %d, Key = %d\n", g_stSCapConfEx.ChannelXNum , g_stSCapConfEx.ChannelYNum, g_stSCapConfEx.KeyNum); + return ReCode; +} +/************************************************************************ +* Name: FT8606_TestItem_ChannelsTest +* Brief: Check whether TP can enter Factory Mode, and do some thing +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT8606_TestItem_ChannelsTest(bool *bTestResult) +{ + unsigned char ReCode; + + printk("\n\n==============================Test Item: -------- Channel Test \n"); + + ReCode = GetChannelNum(); + if (ReCode == ERROR_CODE_OK) + { + if ((g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelXNum == g_stSCapConfEx.ChannelXNum) + && (g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelYNum == g_stSCapConfEx.ChannelYNum) + && (g_stCfg_FT8606_BasicThreshold.ChannelNumTest_KeyNum == g_stSCapConfEx.KeyNum)) + { + * bTestResult = true; + printk("\n\nGet channels: (CHx: %d, CHy: %d, Key: %d), Set channels: (CHx: %d, CHy: %d, Key: %d)", + g_stSCapConfEx.ChannelXNum, g_stSCapConfEx.ChannelYNum, g_stSCapConfEx.KeyNum, + g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelXNum, g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelYNum, g_stCfg_FT8606_BasicThreshold.ChannelNumTest_KeyNum); + + printk("\n//Channel Test is OK!"); + } + else + { + * bTestResult = false; + printk("\n\nGet channels: (CHx: %d, CHy: %d, Key: %d), Set channels: (CHx: %d, CHy: %d, Key: %d)", + g_stSCapConfEx.ChannelXNum, g_stSCapConfEx.ChannelYNum, g_stSCapConfEx.KeyNum, + g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelXNum, g_stCfg_FT8606_BasicThreshold.ChannelNumTest_ChannelYNum, g_stCfg_FT8606_BasicThreshold.ChannelNumTest_KeyNum); + + printk("\n//Channel Test is NG!"); + } + } + return ReCode; +} +/************************************************************************ +* Name: GetRawData +* Brief: Get Raw Data of VA area and Key area +* Input: none +* Output: none +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +static unsigned char GetRawData(void) +{ + int ReCode = ERROR_CODE_OK; + int iRow, iCol; + + + ReCode = EnterFactory(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Enter Factory Mode...\n"); + return ReCode; + } + + + + if (0 == (g_stSCapConfEx.ChannelXNum + g_stSCapConfEx.ChannelYNum)) + { + ReCode = GetChannelNum(); + if (ERROR_CODE_OK != ReCode) + { + printk("Error Channel Num...\n"); + return ERROR_CODE_INVALID_PARAM; + } + } + + + + ReCode = StartScan(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Scan ...\n"); + return ReCode; + } + + + + + memset(m_RawData, 0, sizeof(m_RawData)); + memset(m_iTempRawData, 0, sizeof(m_iTempRawData)); + ReCode = ReadRawData(0, 0xAD, g_stSCapConfEx.ChannelXNum * g_stSCapConfEx.ChannelYNum * 2, m_iTempRawData); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Get RawData\n"); + return ReCode; + } + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum; ++iRow) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; ++iCol) + { + m_RawData[iRow][iCol] = m_iTempRawData[iRow * g_stSCapConfEx.ChannelYNum + iCol]; + } + } + + + memset(m_iTempRawData, 0, sizeof(m_iTempRawData)); + ReCode = ReadRawData(0, 0xAE, g_stSCapConfEx.KeyNum * 2, m_iTempRawData); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to Get RawData\n"); + return ReCode; + } + + for (iCol = 0; iCol < g_stSCapConfEx.KeyNum; ++iCol) + { + m_RawData[g_stSCapConfEx.ChannelXNum][iCol] = m_iTempRawData[iCol]; + } + + return ReCode; + +} +/************************************************************************ +* Name: FT8606_TestItem_RawDataTest +* Brief: TestItem: RawDataTest. Check if MCAP RawData is within the range. +* Input: bTestResult +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT8606_TestItem_RawDataTest(bool *bTestResult) +{ + unsigned char ReCode; + bool btmpresult = true; + + int RawDataMin; + int RawDataMax; + int iValue = 0; + int i = 0; + int iRow, iCol; + + printk("\n\n==============================Test Item: -------- Raw Data Test\n\n"); + + + + for (i = 0 ; i < 3; i++) + ReCode = GetRawData(); + if (ERROR_CODE_OK != ReCode) + { + printk("Failed to get Raw Data!! Error Code: %d\n", ReCode); + return ReCode; + } + + + + printk("\nVA Channels: "); + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum; iRow++) + { + printk("\nCh_%02d: ", iRow+1); + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + printk("%5d, ", m_RawData[iRow][iCol]); + } + } + printk("\nKeys: "); + for (iCol = 0; iCol < g_stSCapConfEx.KeyNum; iCol++) + { + printk("%5d, ", m_RawData[g_stSCapConfEx.ChannelXNum][iCol]); + } + + + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum; iRow++) + { + + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + } + + iRow = g_stSCapConfEx.ChannelXNum; + for (iCol = 0; iCol < g_stSCapConfEx.KeyNum; iCol++) + { + if (g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol] == 0)continue; + RawDataMin = g_stCfg_MCap_DetailThreshold.RawDataTest_Min[iRow][iCol]; + RawDataMax = g_stCfg_MCap_DetailThreshold.RawDataTest_Max[iRow][iCol]; + iValue = m_RawData[iRow][iCol]; + if (iValue < RawDataMin || iValue > RawDataMax) + { + btmpresult = false; + printk("rawdata test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, iValue, RawDataMin, RawDataMax); + } + } + + + Save_Test_Data(m_RawData, 0, g_stSCapConfEx.ChannelXNum+1, g_stSCapConfEx.ChannelYNum, 1); + + if (btmpresult) + { + * bTestResult = true; + printk("\n\n//RawData Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//RawData Test is NG!\n"); + } + return ReCode; +} +/************************************************************************ +* Name: SqrtNew +* Brief: calculate sqrt of input. +* Input: unsigned int n +* Output: none +* Return: sqrt of n. +***********************************************************************/ +static unsigned int SqrtNew(unsigned int n) +{ + unsigned int val = 0, last = 0; + unsigned char i = 0;; + + if (n < 6) + { + if (n < 2) + { + return n; + } + return n/2; + } + val = n; + i = 0; + while (val > 1) + { + val >>= 1; + i++; + } + val <<= (i >> 1); + val = (val + val + val) >> 1; + do + { + last = val; + val = ((val + n/val) >> 1); + }while(focal_abs(val-last) > pre); + return val; +} +/************************************************************************ +* Name: FT8606_TestItem_NoiseTest +* Brief: TestItem: NoiseTest. Check if MCAP Noise is within the range. +* Input: bTestResult +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT8606_TestItem_NoiseTest(bool *bTestResult) +{ + unsigned char ReCode; + unsigned char chNoiseValue = 0xff; + bool btmpresult = true; + + int iNoiseFrames = 0; + int i, iRow, iCol; + int iValue = 0; + int iMinValue = 0, iMaxValue = 0; + int n, temp; + + int *pTempNext = NULL; + int *pTempPrev = NULL; + + + printk("\n\n==============================Test Item: -------- Noise Test \n\n"); + + iNoiseFrames = g_stCfg_FT8606_BasicThreshold.NoiseTest_Frames; + if (iNoiseFrames > MAX_NOISE_FRAMES) + iNoiseFrames = MAX_NOISE_FRAMES; + + + + for (i = 0; i < 3; i++) + { + ReCode = GetRawData(); + } + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + memset(m_TempNoiseData, 0, sizeof(m_TempNoiseData)); + memset(m_NoiseData, 0, sizeof(m_NoiseData)); + for (i = 0; i < iNoiseFrames; i++) + { + ReCode = GetRawData(); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + m_TempNoiseData[i][iRow*g_stSCapConfEx.ChannelYNum + iCol] = m_RawData[iRow][iCol]; + } + } + + } + + + memset(m_NoiseData, 0, sizeof(m_NoiseData)); + + for (i = 0; i < iNoiseFrames; i++) + { + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + iValue = m_TempNoiseData[i][iRow*g_stSCapConfEx.ChannelYNum + iCol]; + m_NoiseData[iRow][iCol] += iValue; + } + } + } + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + m_AvgData[iRow][iCol] = m_NoiseData[iRow][iCol] / iNoiseFrames; + } + } + + + if (NT_AvgData == g_stCfg_FT8606_BasicThreshold.NoiseTest_NoiseMode) + { + + + memset(m_NoiseData, 0, sizeof(m_NoiseData)); + for (i = 0; i < iNoiseFrames; i++) + { + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + iValue = m_TempNoiseData[i][iRow*g_stSCapConfEx.ChannelYNum + iCol]; + m_NoiseData[iRow][iCol] += (iValue -m_AvgData[iRow][iCol])*(iValue -m_AvgData[iRow][iCol]); + } + } + } + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + m_NoiseData[iRow][iCol] = SqrtNew(m_NoiseData[iRow][iCol] / iNoiseFrames); + } + } + + } + else if (NT_MaxData == g_stCfg_FT8606_BasicThreshold.NoiseTest_NoiseMode) + { + + memset(m_NoiseData, 0, sizeof(m_NoiseData)); + for (i = 0; i < iNoiseFrames; i++) + { + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + iValue = focal_abs(m_TempNoiseData[i][iRow*g_stSCapConfEx.ChannelYNum + iCol]); + iValue = focal_abs(iValue - m_AvgData[iRow][iCol]); + if (iValue > m_NoiseData[iRow][iCol]) + m_NoiseData[iRow][iCol] = iValue; + } + } + } + } + else if (NT_MaxDevication == g_stCfg_FT8606_BasicThreshold.NoiseTest_NoiseMode) + { + + memset(m_iTempData, 0xffff, sizeof(m_iTempData)); + memset(m_NoiseData, 0, sizeof(m_NoiseData)); + for (i = 0; i < iNoiseFrames; i++) + { + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + iValue = m_TempNoiseData[i][iRow*g_stSCapConfEx.ChannelYNum + iCol]; + if (iValue < m_iTempData[iRow][iCol]) + m_iTempData[iRow][iCol] = iValue; + if (iValue > m_NoiseData[iRow][iCol]) + m_NoiseData[iRow][iCol] = iValue; + } + } + } + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + m_NoiseData[iRow][iCol] -= m_iTempData[iRow][iCol]; + } + } + + } + else if (NT_DifferData == g_stCfg_FT8606_BasicThreshold.NoiseTest_NoiseMode) + { + + memset(m_NoiseData, 0, sizeof(m_NoiseData)); + for (n = 1; n < iNoiseFrames; n++) + { + pTempNext = m_TempNoiseData[n]; + pTempPrev = m_TempNoiseData[n - 1]; + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + + + temp = focal_abs(pTempNext[iRow*g_stSCapConfEx.ChannelYNum+iCol] - pTempPrev[iRow*g_stSCapConfEx.ChannelYNum+iCol]); + + if (m_NoiseData[iRow][iCol] < temp) + m_NoiseData[iRow][iCol] = temp; + } + } + } + /* + for(iRow = 0; iRow < g_stSCapConfEx.ChannelXNum + 1; iRow++) + { + for(iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + m_NoiseData[iRow][iCol] /= iNoiseFrames; + } + } + */ + } + + + + printk("\nVA Channels: "); + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum; iRow++) + { + printk("\nCh_%02d: ", iRow+1); + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + printk("%5d, ", m_NoiseData[iRow][iCol]); + } + } + printk("\nKeys: "); + for (iCol = 0; iCol < g_stSCapConfEx.KeyNum; iCol++) + { + printk("%5d, ", m_NoiseData[g_stSCapConfEx.ChannelXNum][iCol]); + } + + + SysDelay(150); + ReCode = EnterWork(); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + SysDelay(50); + + ReCode = ReadReg(0x80, &chNoiseValue); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + ReCode = EnterFactory(); + if (ReCode != ERROR_CODE_OK) goto TEST_ERR; + + + + iMinValue = 0; + iMaxValue = g_stCfg_FT8606_BasicThreshold.NoiseTest_Coefficient * chNoiseValue * 32 / 100; + printk("\n"); + for (iRow = 0; iRow < (g_stSCapConfEx.ChannelXNum + 1); iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + if ((0 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol])) + { + continue; + } + if (iRow >= g_stSCapConfEx.ChannelXNum && iCol >= g_stSCapConfEx.KeyNum) + { + continue; + } + + + if (m_NoiseData[iRow][iCol] < iMinValue || m_NoiseData[iRow][iCol] > iMaxValue) + { + btmpresult = false; + printk("noise test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, m_NoiseData[iRow][iCol], iMinValue, iMaxValue); + } + } + printk("\n"); + } + + + + + Save_Test_Data(m_NoiseData, 0, g_stSCapConfEx.ChannelXNum+1, g_stSCapConfEx.ChannelYNum, 1); + + if (btmpresult) + { + * bTestResult = true; + printk("\n\n//Noise Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//Noise Test is NG!\n"); + } + + return ReCode; +TEST_ERR: + + * bTestResult = false; + printk("\n\n//Noise Test is NG!\n"); + return ReCode; +} +/************************************************************************ +* Name: FT8606_TestItem_CbTest +* Brief: TestItem: Cb Test. Check if Cb is within the range. +* Input: none +* Output: bTestResult, PASS or FAIL +* Return: Comm Code. Code = 0x00 is OK, else fail. +***********************************************************************/ +unsigned char FT8606_TestItem_CbTest(bool *bTestResult) +{ + bool btmpresult = true; + unsigned char ReCode = ERROR_CODE_OK; + int iRow = 0; + int iCol = 0; + int iMaxValue = 0; + int iMinValue = 0; + + printk("\n\n==============================Test Item: -------- CB Test\n\n"); + + ReCode = GetTxRxCB(0, (short)(g_stSCapConfEx.ChannelXNum * g_stSCapConfEx.ChannelYNum + g_stSCapConfEx.KeyNum), m_ucTempData); + + ReCode = GetTxRxCB(0, (short)(g_stSCapConfEx.ChannelXNum * g_stSCapConfEx.ChannelYNum + g_stSCapConfEx.KeyNum), m_ucTempData); + if (ERROR_CODE_OK != ReCode) + { + btmpresult = false; + printk("Failed to get CB value...\n"); + goto TEST_ERR; + } + + memset(m_CBData, 0, sizeof(m_CBData)); + + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum; ++iRow) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; ++iCol) + { + m_CBData[iRow][iCol] = m_ucTempData[ iRow * g_stSCapConfEx.ChannelYNum + iCol ]; + } + } + + for (iCol = 0; iCol < g_stSCapConfEx.KeyNum; ++iCol) + { + m_CBData[g_stSCapConfEx.ChannelXNum][iCol] = m_ucTempData[ g_stSCapConfEx.ChannelXNum*g_stSCapConfEx.ChannelYNum + iCol ]; + } + + + + + printk("\nVA Channels: "); + for (iRow = 0; iRow < g_stSCapConfEx.ChannelXNum; iRow++) + { + printk("\nCh_%02d: ", iRow+1); + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + printk("%3d, ", m_CBData[iRow][iCol]); + } + } + printk("\nKeys: "); + for (iCol = 0; iCol < g_stSCapConfEx.KeyNum; iCol++) + { + printk("%3d, ", m_CBData[g_stSCapConfEx.ChannelXNum][iCol]); + } + + iMinValue = g_stCfg_FT8606_BasicThreshold.CbTest_Min; + iMaxValue = g_stCfg_FT8606_BasicThreshold.CbTest_Max; + for (iRow = 0; iRow < (g_stSCapConfEx.ChannelXNum + 1); iRow++) + { + for (iCol = 0; iCol < g_stSCapConfEx.ChannelYNum; iCol++) + { + if ((0 == g_stCfg_MCap_DetailThreshold.InvalidNode[iRow][iCol])) + { + continue; + } + if (iRow >= g_stSCapConfEx.ChannelXNum && iCol >= g_stSCapConfEx.KeyNum) + { + continue; + } + + if (focal_abs(m_CBData[iRow][iCol]) < iMinValue || focal_abs(m_CBData[iRow][iCol]) > iMaxValue) + { + btmpresult = false; + printk("CB test failure. Node=(%d, %d), Get_value=%d, Set_Range=(%d, %d) \n", \ + iRow+1, iCol+1, m_CBData[iRow][iCol], iMinValue, iMaxValue); + } + } + } + + + Save_Test_Data(m_CBData, 0, g_stSCapConfEx.ChannelXNum+1, g_stSCapConfEx.ChannelYNum, 1); + + if (btmpresult) + { + * bTestResult = true; + printk("\n\n//CB Test is OK!\n"); + } + else + { + * bTestResult = false; + printk("\n\n//CB Test is NG!\n"); + } + + return ReCode; + +TEST_ERR: + + * bTestResult = false; + printk("\n\n//CB Test is NG!\n"); + return ReCode; +} diff --git a/drivers/input/touchscreen/ft5435/lib/Test_FT8606.h b/drivers/input/touchscreen/ft5435/lib/Test_FT8606.h new file mode 100644 index 0000000000000..fdc4cfb922e77 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/Test_FT8606.h @@ -0,0 +1,30 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_FT8606.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test item for FT8606 +* +************************************************************************/ +#ifndef _TEST_FT8606_H +#define _TEST_FT8606_H + +#include "test_lib.h" + +boolean FT8606_StartTest(void); +int FT8606_get_test_data(char *pTestData); + +unsigned char FT8606_TestItem_RawDataTest(bool *bTestResult); +unsigned char FT8606_TestItem_ChannelsTest(bool *bTestResult); +unsigned char FT8606_TestItem_NoiseTest(bool *bTestResult); +unsigned char FT8606_TestItem_CbTest(bool *bTestResult); +unsigned char FT8606_TestItem_EnterFactoryMode(void); + + + +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/ini.c b/drivers/input/touchscreen/ft5435/lib/ini.c new file mode 100644 index 0000000000000..e092624995fd0 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/ini.c @@ -0,0 +1,534 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: ini.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: parsing function of INI file +* +************************************************************************/ +#include +#include +#include + +#include "ini.h" + + +char CFG_SSL = '['; /* Ïî±êÖ¾·ûSection Symbol --¿É¸ù¾ÝÌØÊâÐèÒª½øÐж¨Òå¸ü¸Ä£¬Èç { }µÈ*/ +char CFG_SSR = ']'; /* Ïî±êÖ¾·ûSection Symbol --¿É¸ù¾ÝÌØÊâÐèÒª½øÐж¨Òå¸ü¸Ä£¬Èç { }µÈ*/ +char CFG_NIS = ':'; /* name Óë index Ö®¼äµÄ·Ö¸ô·û */ +char CFG_NTS = '#'; /* ×¢ÊÍ·û*/ +char CFG_EQS = '='; /*µÈºÅ*/ + +ST_INI_FILE_DATA g_st_ini_file_data[MAX_KEY_NUM]; +int g_used_key_num = 0; + +char *ini_str_trim_r(char *buf); +char *ini_str_trim_l(char *buf); +static int ini_file_get_line(char *filedata, char *buffer, int maxlen); + +static long atol(char *nptr); + + +/* Works only for digits and letters, but small and fast */ +#define TOLOWER(x) ((x) | 0x20) + +int fts_strncmp(const char *cs, const char *ct, size_t count) +{ + unsigned char c1 = 0, c2 = 0; + + while (count) { + c1 = TOLOWER(*cs++); + c2 = TOLOWER(*ct++); + if (c1 != c2) + return c1 < c2 ? -1 : 1; + if (!c1) + break; + count--; + } + return 0; +} + +/************************************************************* +Function: »ñµÃkeyµÄÖµ +Input: char * filedata¡¡Îļþ£»char * section¡¡ÏîÖµ£»char * key¡¡¼üÖµ +Output: char * value¡¡keyµÄÖµ +Return: 0 SUCCESS + -1 δÕÒµ½section + -2 δÕÒµ½key + -10 Îļþ´ò¿ªÊ§°Ü + -12 ¶ÁÈ¡Îļþʧ°Ü + -14 Îļþ¸ñʽ´íÎó + -22 ³¬³ö»º³åÇø´óС +Note: +*************************************************************/ +int ini_get_key(char *filedata, char *section, char *key, char *value) +{ + int i = 0; + int ret = -2; + for (i = 0; i < g_used_key_num; i++) + { + if (fts_strncmp(section, g_st_ini_file_data[i].pSectionName, + g_st_ini_file_data[i].iSectionNameLen) != 0) + continue; + + if (fts_strncmp(key, g_st_ini_file_data[i].pKeyName, strlen(key)) == 0) + + { + memcpy(value, g_st_ini_file_data[i].pKeyValue, g_st_ini_file_data[i].iKeyValueLen); + ret = 0; + break; + } + } + + return ret; +} +/************************************************************* +Function: »ñµÃËùÓÐsection +Input: char *filename¡¡Îļþ,int max ×î´ó¿É·µ»ØµÄsectionµÄ¸öÊý +Output: char *sections[]¡¡´æ·ÅsectionÃû×Ö +Return: ·µ»Øsection¸öÊý¡£Èô³ö´í£¬·µ»Ø¸ºÊý¡£ + -10 Îļþ´ò¿ª³ö´í + -12 Îļþ¶ÁÈ¡´íÎó + -14 Îļþ¸ñʽ´íÎó +Note: +*************************************************************/ +int ini_get_sections(char *filedata, unsigned char *sections[], int max) +{ + + char buf1[MAX_CFG_BUF + 1]; + int n, n_sections = 0, ret; + int dataoff = 0; + + + + + while(1) {/*ËÑÕÒÏîsection */ + ret = CFG_ERR_READ_FILE; + n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF); + dataoff += n; + if (n < -1) + goto cfg_scts_end; + if (n < 0) + break;/* Îļþβ */ + n = strlen(ini_str_trim_l(ini_str_trim_r(buf1))); + if (n == 0 || buf1[0] == CFG_NTS) + continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */ + ret = CFG_ERR_FILE_FORMAT; + if (n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR))) + goto cfg_scts_end; + if (buf1[0] == CFG_SSL) { + if (max != 0){ + buf1[n-1] = 0x00; + strcpy((char *)sections[n_sections], buf1+1); + if (n_sections>=max) + break; /* ³¬¹ý¿É·µ»Ø×î´ó¸öÊý */ + } + n_sections++; + } + + } + ret = n_sections; +cfg_scts_end: + + + return ret; +} + + +/************************************************************* +Function: È¥³ý×Ö·û´®ÓұߵĿÕ×Ö·û +Input: char * buf ×Ö·û´®Ö¸Õë +Output: +Return: ×Ö·û´®Ö¸Õë +Note: +*************************************************************/ +char *ini_str_trim_r(char *buf) +{ + int len, i; + char tmp[512]; + + memset(tmp, 0, sizeof(tmp)); + len = strlen(buf); + + + memset(tmp, 0x00, len); + for (i = 0; i < len; i++) { + if (buf[i] != ' ') + break; + } + if (i < len) { + strncpy(tmp, (buf+i), (len-i)); + } + strncpy(buf, tmp, len); + + return buf; +} + +/************************************************************* +Function: È¥³ý×Ö·û´®×ó±ßµÄ¿Õ×Ö·û +Input: char * buf ×Ö·û´®Ö¸Õë +Output: +Return: ×Ö·û´®Ö¸Õë +Note: +*************************************************************/ +char *ini_str_trim_l(char *buf) +{ + int len, i; + char tmp[512]; + + memset(tmp, 0, sizeof(tmp)); + len = strlen(buf); + + + memset(tmp, 0x00, len); + + for (i = 0; i < len; i++) { + if (buf[len-i-1] != ' ') + break; + } + if (i < len) { + strncpy(tmp, buf, len-i); + } + strncpy(buf, tmp, len); + + return buf; +} +/************************************************************* +Function: ´ÓÎļþÖжÁÈ¡Ò»ÐÐ +Input: FILE *fp Îļþ¾ä±ú£»int maxlen »º³åÇø×î´ó³¤¶È +Output: char *buffer Ò»ÐÐ×Ö·û´® +Return: >0 ʵ¼Ê¶ÁµÄ³¤¶È + -1 Îļþ½áÊø + -2 ¶ÁÎļþ³ö´í +Note: +*************************************************************/ +static int ini_file_get_line(char *filedata, char *buffer, int maxlen) +{ + int i = 0; + int j = 0; + int iRetNum = -1; + char ch1 = '\0'; + + for (i = 0, j = 0; i < maxlen; j++) { + ch1 = filedata[j]; + iRetNum = j+1; + if (ch1 == '\n' || ch1 == '\r') + { + ch1 = filedata[j+1]; + if (ch1 == '\n' || ch1 == '\r') + { + iRetNum++; + } + + break; + }else if (ch1 == 0x00) + { + iRetNum = -1; + break; + } + else + { + buffer[i++] = ch1; /* ºöÂԻسµ·û */ + } + } + buffer[i] = '\0'; + + return iRetNum; + + /*for(i=0, j=0; i= n) + return 0; + + if(buf[i] == '=') + return -1; + + k1 = i; + for(i++; i < n; i++) + if(buf[i] == '=') + break; + + if(i >= n) + return -2; + k2 = i; + + for(i++; i < n; i++) + if(buf[i] != ' ' && buf[i] != '\t') + break; + + buf[k2] = '\0'; + + *key = buf + k1; + *val = buf + i; + return 1; +}*/ + +int my_atoi(const char *str) +{ + int result = 0; + int signal = 1; /* ĬÈÏΪÕýÊý */ + if ((*str>='0' && *str<='9') || *str == '-' || *str == '+') { + if (*str == '-' || *str == '+') { + if (*str == '-') + signal = -1; /*ÊäÈ븺Êý*/ + str++; + } + } + else + return 0; + /*¿ªÊ¼×ª»»*/ + while(*str>='0' && *str<='9') + result = result*10 + (*str++ - '0'); + + return signal*result; +} + +int isspace(int x) +{ + if (x == ' ' || x == '\t' || x == '\n' || x == '\f' || x == '\b' || x == '\r') + return 1; + else + return 0; +} + +int isdigit(int x) +{ + if (x<='9' && x>='0') + return 1; + else + return 0; + +} + +static long atol(char *nptr) +{ + int c; /* current char */ + long total; /* current total */ + int sign; /* if ''-'', then negative, otherwise positive */ + /* skip whitespace */ + while (isspace((int)(unsigned char)*nptr)) + ++nptr; + c = (int)(unsigned char)*nptr++; + sign = c; /* save sign indication */ + if (c == '-' || c == '+') + c = (int)(unsigned char)*nptr++; /* skip sign */ + total = 0; + while (isdigit(c)) { + total = 10 * total + (c - '0'); /* accumulate digit */ + c = (int)(unsigned char)*nptr++; /* get next char */ + } + if (sign == '-') + return -total; + else + return total; /* return result, negated if necessary */ +} +/*** +*int atoi(char *nptr) - Convert string to long +* +*Purpose: +* Converts ASCII string pointed to by nptr to binary. +* Overflow is not detected. Because of this, we can just use +* atol(). +* +*Entry: +* nptr = ptr to string to convert +* +*Exit: +* return int value of the string +* +*Exceptions: +* None - overflow is not detected. +* +*******************************************************************************/ +int atoi(char *nptr) +{ + return (int)atol(nptr); +} + +int init_key_data(void) +{ + int i = 0; + + g_used_key_num = 0; + + for (i = 0; i < MAX_KEY_NUM; i++) + { + memset(g_st_ini_file_data[i].pSectionName, 0, MAX_KEY_NAME_LEN); + memset(g_st_ini_file_data[i].pKeyName, 0, MAX_KEY_NAME_LEN); + memset(g_st_ini_file_data[i].pKeyValue, 0, MAX_KEY_VALUE_LEN); + g_st_ini_file_data[i].iSectionNameLen = 0; + g_st_ini_file_data[i].iKeyNameLen = 0; + g_st_ini_file_data[i].iKeyValueLen = 0; + } + + return 1; +} + +/************************************************************* +Function:¶ÁÈ¡ËùÓеIJÎÊý¼°ÆäÖµµ½½á¹¹ÌåÀï +Return: ·µ»Økey¸öÊý¡£Èô³ö´í£¬·µ»Ø¸ºÊý¡£ + -10 Îļþ´ò¿ª³ö´í + -12 Îļþ¶ÁÈ¡´íÎó + -14 Îļþ¸ñʽ´íÎó +Note: +*************************************************************/ +int ini_get_key_data(char *filedata) +{ + + char buf1[MAX_CFG_BUF + 1] = {0}; + int n = 0; + int ret = 0; + int dataoff = 0; + int iEqualSign = 0; + int i = 0; + char tmpSectionName[MAX_CFG_BUF + 1] = {0}; + + + + + init_key_data();/*init*/ + + g_used_key_num = 0; + while(1) {/*ËÑÕÒÏîsection */ + ret = CFG_ERR_READ_FILE; + n = ini_file_get_line(filedata+dataoff, buf1, MAX_CFG_BUF); + + if (n < -1) + goto cfg_scts_end; + if (n < 0) + break;/* Îļþβ */ + + dataoff += n; + + n = strlen(ini_str_trim_l(ini_str_trim_r(buf1))); + if (n == 0 || buf1[0] == CFG_NTS) + continue; /* ¿ÕÐÐ »ò ×¢ÊÍÐÐ */ + ret = CFG_ERR_FILE_FORMAT; + + if (n > 2 && ((buf1[0] == CFG_SSL && buf1[n-1] != CFG_SSR))) + { + printk("Bad Section:%s\n\n", buf1); + goto cfg_scts_end; + } + + + if (buf1[0] == CFG_SSL) { + g_st_ini_file_data[g_used_key_num].iSectionNameLen = n-2; + if (MAX_KEY_NAME_LEN < g_st_ini_file_data[g_used_key_num].iSectionNameLen) + { + ret = CFG_ERR_OUT_OF_LEN; + printk("MAX_KEY_NAME_LEN: CFG_ERR_OUT_OF_LEN\n\n"); + goto cfg_scts_end; + } + + buf1[n-1] = 0x00; + strcpy((char *)tmpSectionName, buf1+1); + + + continue; + } + + + strcpy(g_st_ini_file_data[g_used_key_num].pSectionName, tmpSectionName); + g_st_ini_file_data[g_used_key_num].iSectionNameLen = strlen(tmpSectionName); + + iEqualSign = 0; + for (i = 0; i < n; i++) + { + if (buf1[i] == CFG_EQS) + { + iEqualSign = i; + break; + } + } + if (0 == iEqualSign) + continue; + /*µÈºÅÇ°Ò»¶Î¸³¸ø¼üÃû*/ + g_st_ini_file_data[g_used_key_num].iKeyNameLen = iEqualSign; + if (MAX_KEY_NAME_LEN < g_st_ini_file_data[g_used_key_num].iKeyNameLen) + { + ret = CFG_ERR_OUT_OF_LEN; + printk("MAX_KEY_NAME_LEN: CFG_ERR_OUT_OF_LEN\n\n"); + goto cfg_scts_end; + } + memcpy(g_st_ini_file_data[g_used_key_num].pKeyName, + buf1, g_st_ini_file_data[g_used_key_num].iKeyNameLen); + + /*µÈºÅºóÒ»¶Î¸³¸ø¼üÖµ*/ + g_st_ini_file_data[g_used_key_num].iKeyValueLen = n-iEqualSign-1; + if (MAX_KEY_VALUE_LEN < g_st_ini_file_data[g_used_key_num].iKeyValueLen) + { + ret = CFG_ERR_OUT_OF_LEN; + printk("MAX_KEY_VALUE_LEN: CFG_ERR_OUT_OF_LEN\n\n"); + goto cfg_scts_end; + } + memcpy(g_st_ini_file_data[g_used_key_num].pKeyValue, + buf1+ iEqualSign+1, g_st_ini_file_data[g_used_key_num].iKeyValueLen); + + + ret = g_used_key_num; + + /*printk("Param Name = %s, Value = %s\n", + g_st_ini_file_data[g_used_key_num].pKeyName, + g_st_ini_file_data[g_used_key_num].pKeyValue + );*/ + + g_used_key_num++;/*²ÎÊý¸öÊýÀÛ¼Ó*/ + if (MAX_KEY_NUM < g_used_key_num) + { + ret = CFG_ERR_TOO_MANY_KEY_NUM; + printk("MAX_KEY_NUM: CFG_ERR_TOO_MANY_KEY_NUM\n\n"); + goto cfg_scts_end; + } + } + +cfg_scts_end: + + return ret; +} + diff --git a/drivers/input/touchscreen/ft5435/lib/ini.h b/drivers/input/touchscreen/ft5435/lib/ini.h new file mode 100644 index 0000000000000..d54a5faee17bd --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/ini.h @@ -0,0 +1,83 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: ini.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: parsing function of INI file +* +************************************************************************/ +#ifndef INI_H +#define INI_H + +#define MAX_KEY_NUM 300 +#define MAX_KEY_NAME_LEN 50 +#define MAX_KEY_VALUE_LEN 360 + +#define MAX_CFG_BUF 480 +#define SUCCESS 0 +/* return value */ +#define CFG_OK SUCCESS +#define CFG_SECTION_NOT_FOUND -1 +#define CFG_KEY_NOT_FOUND -2 +#define CFG_ERR -10 + +#define CFG_ERR_OPEN_FILE -10 +#define CFG_ERR_CREATE_FILE -11 +#define CFG_ERR_READ_FILE -12 +#define CFG_ERR_WRITE_FILE -13 +#define CFG_ERR_FILE_FORMAT -14 +#define CFG_ERR_TOO_MANY_KEY_NUM -15 +#define CFG_ERR_OUT_OF_LEN -16 + +#define CFG_ERR_EXCEED_BUF_SIZE -22 + +#define COPYF_OK SUCCESS +#define COPYF_ERR_OPEN_FILE -10 +#define COPYF_ERR_CREATE_FILE -11 +#define COPYF_ERR_READ_FILE -12 +#define COPYF_ERR_WRITE_FILE -13 + +#define FOCAL_DBG +#ifdef FOCAL_DBG +#define FTS_DBG(fmt, args...) printk("[FTS]" fmt, ## args) +#else +#define FTS_DBG(fmt, args...) do{}while(0) +#endif + + +struct ini_key_location { + int ini_section_line_no; + int ini_key_line_no; + int ini_key_lines; +}; + +typedef struct _ST_INI_FILE_DATA +{ + char pSectionName[MAX_KEY_NAME_LEN]; + char pKeyName[MAX_KEY_NAME_LEN]; + char pKeyValue[MAX_KEY_VALUE_LEN]; + int iSectionNameLen; + int iKeyNameLen; + int iKeyValueLen; +}ST_INI_FILE_DATA; + + + +int ini_get_key(char *filedata, char *section, char *key, char *value); +int ini_get_sections(char *filedata, unsigned char *sections[], int max); + +int ini_split_section(char *section, char **name, char **index); + + +int atoi(char *nptr); +char *ini_str_trim_r(char *buf); +char *ini_str_trim_l(char *buf); + +int init_key_data(void); +int ini_get_key_data(char *filedata); +#endif diff --git a/drivers/input/touchscreen/ft5435/lib/test_lib.c b/drivers/input/touchscreen/ft5435/lib/test_lib.c new file mode 100644 index 0000000000000..fdb8638673474 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/test_lib.c @@ -0,0 +1,222 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)??All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_lib.c +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test entry for all IC +* +************************************************************************/ +#include +#include +#include +#include + +#include "test_lib.h" +#include "Global.h" +#include "Config_FT8606.h" +#include "Test_FT8606.h" +#include "Config_FT5X46.h" +#include "Test_FT5X46.h" +#include "Config_FT5822.h" +#include "Test_FT5822.h" + +#include "Config_FT6X36.h" +#include "Test_FT6X36.h" + +#include "Config_FT3C47.h" +#include "Test_FT3C47.h" + +#include "ini.h" + +#define FTS_DRIVER_LIB_INFO "Test_Lib_Version V1.4.0 2015-12-03" + +FTS_I2C_READ_FUNCTION fts_i2c_read_test; +FTS_I2C_WRITE_FUNCTION fts_i2c_write_test; + +char *g_testparamstring = NULL; + + +int init_i2c_read_func(FTS_I2C_READ_FUNCTION fpI2C_Read) +{ + fts_i2c_read_test = fpI2C_Read; + return 0; +} + +int init_i2c_write_func(FTS_I2C_WRITE_FUNCTION fpI2C_Write) +{ + fts_i2c_write_test = fpI2C_Write; + return 0; +} + +/************************************************************************ +* Name: set_param_data +* Brief: load Config. Set IC series, init test items, init basic threshold, int detailThreshold, and set order of test items +* Input: TestParamData, from ini file. +* Output: none +* Return: 0. No sense, just according to the old format. +***********************************************************************/ +int set_param_data(char *TestParamData) +{ + + + printk("Enter set_param_data \n"); + g_testparamstring = TestParamData; + ini_get_key_data(g_testparamstring); + + OnInit_InterfaceCfg(g_testparamstring); + + /*Get IC Name*/ + get_ic_name(g_ScreenSetParam.iSelectedIC, g_strIcName); + + if (IC_FT5X46>>4 == g_ScreenSetParam.iSelectedIC>>4) + { + OnInit_FT5X22_TestItem(g_testparamstring); + OnInit_FT5X22_BasicThreshold(g_testparamstring); + OnInit_MCap_DetailThreshold(g_testparamstring); + SetTestItem_FT5X22(); + } + else if (IC_FT8606>>4 == g_ScreenSetParam.iSelectedIC>>4) + { + OnInit_FT8606_TestItem(g_testparamstring); + OnInit_FT8606_BasicThreshold(g_testparamstring); + OnInit_MCap_DetailThreshold(g_testparamstring); + SetTestItem_FT8606(); + } + else if (IC_FT5822>>4 == g_ScreenSetParam.iSelectedIC>>4) + { + OnInit_FT5822_TestItem(g_testparamstring); + OnInit_FT5822_BasicThreshold(g_testparamstring); + OnInit_MCap_DetailThreshold(g_testparamstring); + SetTestItem_FT5822(); + } + else if (IC_FT6X36>>4 == g_ScreenSetParam.iSelectedIC>>4) + { + OnInit_FT6X36_TestItem(g_testparamstring); + OnInit_FT6X36_BasicThreshold(g_testparamstring); + OnInit_SCap_DetailThreshold(g_testparamstring); + SetTestItem_FT6X36(); + } + else if (IC_FT3C47U>>4 == g_ScreenSetParam.iSelectedIC>>4) + { + OnInit_FT3C47_TestItem(g_testparamstring); + OnInit_FT3C47_BasicThreshold(g_testparamstring); + OnInit_MCap_DetailThreshold(g_testparamstring); + SetTestItem_FT3C47(); + } + + return 0; +} + +/************************************************************************ +* Name: start_test_tp +* Brief: Test entry. Select test items based on IC series +* Input: none +* Output: none +* Return: Test Result, PASS or FAIL +***********************************************************************/ + +boolean start_test_tp(void) +{ + boolean bTestResult = false; + printk("[focal] %s \n", FTS_DRIVER_LIB_INFO); + printk("[focal] %s start \n", __func__); + printk("IC_%s Test\n", g_strIcName); + + switch(g_ScreenSetParam.iSelectedIC>>4) + { + case IC_FT8606>>4: + bTestResult = FT8606_StartTest(); + break; + case IC_FT5X46>>4: + bTestResult = FT5X46_StartTest(); + break; + case IC_FT5822>>4: + bTestResult = FT5822_StartTest(); + break; + case IC_FT6X36>>4: + bTestResult = FT6X36_StartTest(); + break; + case IC_FT3C47U>>4: + bTestResult = FT3C47_StartTest(); + break; + default: + printk("[focal] Error IC, IC Name: %s, IC Code: %d\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + break; + } + + EnterWork(); + return bTestResult; +} +/************************************************************************ +* Name: get_test_data +* Brief: Get test data based on IC series +* Input: none +* Output: pTestData, External application for memory, buff size >= 1024*8 +* Return: the length of test data. if length > 0, got data;else ERR. +***********************************************************************/ +int get_test_data(char *pTestData) +{ + int iLen = 0; + printk("[focal] %s start \n", __func__); + switch(g_ScreenSetParam.iSelectedIC>>4) + { + case IC_FT8606>>4: + iLen = FT8606_get_test_data(pTestData); + break; + case IC_FT5X46>>4: + iLen = FT5X46_get_test_data(pTestData); + break; + case IC_FT5822>>4: + iLen = FT5822_get_test_data(pTestData); + break; + case IC_FT6X36>>4: + iLen = FT6X36_get_test_data(pTestData); + break; + case IC_FT3C47U>>4: + iLen = FT3C47_get_test_data(pTestData); + break; + default: + printk("[focal] Error IC, IC Name: %s, IC Code: %d\n", g_strIcName, g_ScreenSetParam.iSelectedIC); + break; + } + + + return iLen; +} +/************************************************************************ +* Name: free_test_param_data +* Brief: release printer memory +* Input: none +* Output: none +* Return: none. +***********************************************************************/ +void free_test_param_data(void) +{ + if (g_testparamstring) + + + g_testparamstring = NULL; +} + +/************************************************************************ +* Name: show_lib_ver +* Brief: get lib version +* Input: none +* Output: pLibVer +* Return: the length of lib version. +***********************************************************************/ +int show_lib_ver(char *pLibVer) +{ + int num_read_chars = 0; + + num_read_chars = snprintf(pLibVer, 128, "%s \n", FTS_DRIVER_LIB_INFO); + + return num_read_chars; +} + + diff --git a/drivers/input/touchscreen/ft5435/lib/test_lib.h b/drivers/input/touchscreen/ft5435/lib/test_lib.h new file mode 100644 index 0000000000000..dfcfd10483987 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/lib/test_lib.h @@ -0,0 +1,44 @@ +/************************************************************************ +* Copyright (C) 2012-2015, Focaltech Systems (R)£¬All Rights Reserved. +* Copyright (C) 2019 XiaoMi, Inc. +* +* File Name: Test_lib.h +* +* Author: Software Development Team, AE +* +* Created: 2015-07-14 +* +* Abstract: test entry for all IC +* +************************************************************************/ +#ifndef _TEST_LIB_H +#define _TEST_LIB_H + +#define boolean unsigned char +#define bool unsigned char +#define BYTE unsigned char +#define false 0 +#define true 1 + + +typedef int (*FTS_I2C_READ_FUNCTION)(unsigned char *, int , unsigned char *, int); +typedef int (*FTS_I2C_WRITE_FUNCTION)(unsigned char *, int); + +extern FTS_I2C_READ_FUNCTION fts_i2c_read_test; +extern FTS_I2C_WRITE_FUNCTION fts_i2c_write_test; + +extern int init_i2c_read_func(FTS_I2C_READ_FUNCTION fpI2C_Read); +extern int init_i2c_write_func(FTS_I2C_WRITE_FUNCTION fpI2C_Write); + + +int set_param_data(char *TestParamData); +boolean start_test_tp(void); +int get_test_data(char *pTestData); + +void free_test_param_data(void); +int show_lib_ver(char *pLibVer); + + + + +#endif diff --git a/drivers/input/touchscreen/ft5435/mcap_test_lib.h b/drivers/input/touchscreen/ft5435/mcap_test_lib.h new file mode 100644 index 0000000000000..7c01b2b2047c9 --- /dev/null +++ b/drivers/input/touchscreen/ft5435/mcap_test_lib.h @@ -0,0 +1,28 @@ +#ifndef _FOCAL_MCAPTESTLIB_H +#define _FOCAL_MCAPTESTLIB_H + +#define boolean unsigned char +#define bool unsigned char +#define BYTE unsigned char +#define false 0 +#define true 1 + + +typedef int (*FTS_I2C_READ_FUNCTION)(unsigned char *, int , unsigned char *, int); +typedef int (*FTS_I2C_WRITE_FUNCTION)(unsigned char *, int); + +extern FTS_I2C_READ_FUNCTION fts_i2c_read_test; +extern FTS_I2C_WRITE_FUNCTION fts_i2c_write_test; + +extern int init_i2c_read_func(FTS_I2C_READ_FUNCTION fpI2C_Read); +extern int init_i2c_write_func(FTS_I2C_WRITE_FUNCTION fpI2C_Write); + + +int set_param_data(char *TestParamData); +boolean start_test_tp(void); +int get_test_data(char *pTestData); + +void free_test_param_data(void); +int show_lib_ver(char *pLibVer); + +#endif diff --git a/drivers/input/touchscreen/ft5446/Kconfig b/drivers/input/touchscreen/ft5446/Kconfig new file mode 100644 index 0000000000000..5250c897b2c29 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/Kconfig @@ -0,0 +1,16 @@ +# +# Focaltech Touchscreen driver configuration +# + +config TOUCHSCREEN_FT5446 + bool "Focaltech Touchscreen" + depends on I2C + default n + help + Say Y here if you have Focaltech touch panel. + If unsure, say N. + +config TOUCHSCREEN_FTS_DIRECTORY + string "Focaltech ts directory name" + default "focaltech_touch" + depends on TOUCHSCREEN_FTS diff --git a/drivers/input/touchscreen/ft5446/Makefile b/drivers/input/touchscreen/ft5446/Makefile new file mode 100644 index 0000000000000..dae95c2610dd4 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the focaltech touchscreen drivers. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_FT5446) += focaltech_core.o +obj-$(CONFIG_TOUCHSCREEN_FT5446) += focaltech_i2c.o diff --git a/drivers/input/touchscreen/ft5446/focaltech_common.h b/drivers/input/touchscreen/ft5446/focaltech_common.h new file mode 100644 index 0000000000000..290a5a51bf3b1 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/focaltech_common.h @@ -0,0 +1,137 @@ +/* + * + * FocalTech fts TouchScreen driver. + * + * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/***************************************************************************** +* +* File Name: focaltech_common.h +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-16 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +#ifndef __LINUX_FOCALTECH_COMMON_H__ +#define __LINUX_FOCALTECH_COMMON_H__ + +#include "focaltech_config.h" + +/***************************************************************************** +* Macro definitions using #define +*****************************************************************************/ +#define FTS_DRIVER_VERSION "Focaltech V2.0 20170919" + +#define BYTE_OFF_0(x) (u8)((x) & 0xFF) +#define BYTE_OFF_8(x) (u8)((x >> 8) & 0xFF) +#define BYTE_OFF_16(x) (u8)((x >> 16) & 0xFF) +#define BYTE_OFF_24(x) (u8)((x >> 24) & 0xFF) +#define FLAGBIT(x) (0x00000001 << (x)) +#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x)) + +#define FLAG_ICSERIALS_LEN 8 +#define FLAG_HID_BIT 10 +#define FLAG_IDC_BIT 11 + +#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1)) +#define IC_TO_SERIALS(x) ((x) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1)) +#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT)) +#define FTS_HID_SUPPORTTED ((FTS_CHIP_TYPE & FLAGBIT(FLAG_HID_BIT)) == FLAGBIT(FLAG_HID_BIT)) + +#define FTS_CHIP_TYPE_MAPPING {{0x02, 0x54, 0x22, 0x54, 0x22, 0x00, 0x00, 0x54, 0x2C}} + +#define I2C_BUFFER_LENGTH_MAXINUM 256 +#define FILE_NAME_LENGTH 128 +#define ENABLE 1 +#define DISABLE 0 +#define VALID 1 +#define INVALID 0 +#define FTS_CMD_START1 0x55 +#define FTS_CMD_START2 0xAA +#define FTS_CMD_READ_ID 0x90 +/*register address*/ +#define FTS_REG_CHIP_ID 0xA3 +#define FTS_REG_CHIP_ID2 0x9F + +#define FTS_REG_FW_VER 0xA6 + + +#define FTS_SYSFS_ECHO_ON(buf) (buf[0] == '1') +#define FTS_SYSFS_ECHO_OFF(buf) (buf[0] == '0') + +#define kfree_safe(pbuf) do {\ + if (pbuf) {\ + kfree(pbuf);\ + pbuf = NULL;\ + }\ +} while(0) + +/***************************************************************************** +* Alternative mode (When something goes wrong, the modules may be able to solve the problem.) +*****************************************************************************/ +/* + * point report check + * default: disable + */ +#define FTS_POINT_REPORT_CHECK_EN 0 + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +struct ft_chip_t { + u64 type; + u8 chip_idh; + u8 chip_idl; + u8 rom_idh; + u8 rom_idl; + u8 pb_idh; + u8 pb_idl; + u8 bl_idh; + u8 bl_idl; +}; + +struct ts_ic_info { + bool is_incell; + bool hid_supported; + struct ft_chip_t ids; +}; + +/***************************************************************************** +* DEBUG function define here +*****************************************************************************/ +#if FTS_DEBUG_EN +#define FTS_DEBUG_LEVEL 1 +#if (FTS_DEBUG_LEVEL == 2) +#define FTS_DEBUG(fmt, args...) printk("[FTS][%s]"fmt"\n", __func__, ##args) +#else +#define FTS_DEBUG(fmt, args...) printk("[FTS]"fmt"\n", ##args) +#endif +#define FTS_FUNC_ENTER() printk("[FTS]%s: Enter\n", __func__) +#define FTS_FUNC_EXIT() printk("[FTS]%s: Exit(%d)\n", __func__, __LINE__) +#else /* #if FTS_DEBUG_EN*/ +#define FTS_DEBUG(fmt, args...) +#define FTS_FUNC_ENTER() +#define FTS_FUNC_EXIT() +#endif + +#define FTS_INFO(fmt, args...) printk(KERN_INFO "[FTS][Info]"fmt"\n", ##args) +#define FTS_ERROR(fmt, args...) printk(KERN_ERR "[FTS][Error]"fmt"\n", ##args) + +#endif /* __LINUX_FOCALTECH_COMMON_H__ */ diff --git a/drivers/input/touchscreen/ft5446/focaltech_config.h b/drivers/input/touchscreen/ft5446/focaltech_config.h new file mode 100644 index 0000000000000..528611fee3937 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/focaltech_config.h @@ -0,0 +1,62 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/************************************************************************ +* +* File Name: focaltech_config.h +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: global configurations +* +* Version: v1.0 +* +************************************************************************/ +#ifndef _LINUX_FOCLATECH_CONFIG_H_ +#define _LINUX_FOCLATECH_CONFIG_H_ + +/**************************************************/ +/****** G: A, I: B, S: C, U: D ******************/ +/****** chip type defines, do not modify *********/ + +#define _FT5446 0x54460402 + +/*************************************************/ + +/* + * choose your ic chip type of focaltech + */ +#define FTS_CHIP_TYPE _FT5446 + +/******************* Enables *********************/ +/*********** 1 to enable, 0 to disable ***********/ + +/* + * show debug log info + * enable it for debug, disable it for release + */ +#define FTS_DEBUG_EN 1 + +/* + * Linux MultiTouch Protocol + * 1: Protocol B(default), 0: Protocol A + */ +#define FTS_MT_PROTOCOL_B_EN 1 + +#endif /* _LINUX_FOCLATECH_CONFIG_H_ */ diff --git a/drivers/input/touchscreen/ft5446/focaltech_core.c b/drivers/input/touchscreen/ft5446/focaltech_core.c new file mode 100644 index 0000000000000..b80a7471f6836 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/focaltech_core.c @@ -0,0 +1,1504 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/***************************************************************************** +* +* File Name: focaltech_core.c +* +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: entrance for focaltech ts driver +* +* Version: V1.0 +* +*****************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" +#include +#if defined(CONFIG_FB) +#include +#include +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#define FTS_SUSPEND_LEVEL 1 /* Early-suspend level */ +#endif +/*Add by HQ-zmc [Date: 2018-01-24 09:12:34]*/ + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define FTS_DRIVER_NAME "fts_ts" +#define INTERVAL_READ_REG 100 +#define TIMEOUT_READ_REG 200 + +#define FTS_VTG_MIN_UV 2600000 +#define FTS_VTG_MAX_UV 3300000 +#define FTS_I2C_VTG_MIN_UV 1800000 +#define FTS_I2C_VTG_MAX_UV 1800000 + + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +struct fts_ts_data *fts_data; + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ +static int fts_ts_suspend(struct device *dev); +static int fts_ts_resume(struct device *dev); + +/*Add by HQ-zmc [Date: 2018-02-12 14:44:52]*/ +static int D1S_LCD_VENDOR; + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +extern bool lcm_ffbm_mode; +#endif + +/************************************************************************ +* Name: get_lcd_vendor +* Brief: get lcd vendor from lockdown val[1] +* Input: +* Output: +* Date: Add by HQ-zmc [Date: 2018-02-12 14:45:42] +***********************************************************************/ +int *get_lcd_vendor(void){ + return &D1S_LCD_VENDOR; +} + +/************************************************************************ +* Name: fts_get_chip_types +* Brief: verity chip id and get chip type data +* Input: +* Output: +* Return: return 0 if success, otherwise return error code +***********************************************************************/ +static int fts_get_chip_types( + struct fts_ts_data *ts_data, + u8 id_h, u8 id_l, bool fw_valid) +{ + int i = 0; + struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING; + u32 ctype_entries = sizeof(ctype) / sizeof(struct ft_chip_t); + + if ((0x0 == id_h) || (0x0 == id_l)) { + FTS_ERROR("id_h/id_l is 0"); + return -EINVAL; + } + + FTS_DEBUG("verify id:0x%02x%02x", id_h, id_l); + for (i = 0; i < ctype_entries; i++) { + if (VALID == fw_valid) { + if ((id_h == ctype[i].chip_idh) && (id_l == ctype[i].chip_idl)) + break; + } else { + if (((id_h == ctype[i].rom_idh) && (id_l == ctype[i].rom_idl)) + || ((id_h == ctype[i].pb_idh) && (id_l == ctype[i].pb_idl)) + || ((id_h == ctype[i].bl_idh) && (id_l == ctype[i].bl_idl))) + break; + } + } + + if (i >= ctype_entries) { + return -ENODATA; + } + + ts_data->ic_info.ids = ctype[i]; + return 0; +} + +/***************************************************************************** +* Name: fts_get_ic_information +* Brief: +* Input: +* Output: +* Return: return 0 if success, otherwise return error code +*****************************************************************************/ +int fts_get_ic_information(struct fts_ts_data *ts_data) +{ + int ret = 0; + int cnt = 0; + u8 chip_id[2] = { 0 }; + u8 id_cmd[4] = { 0 }; + struct i2c_client *client = ts_data->client; + + do { + ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id[0]); + ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID2, &chip_id[1]); + if ((ret < 0) || (0x0 == chip_id[0]) || (0x0 == chip_id[1])) { + FTS_DEBUG("i2c read error, read:0x%02x%02x", chip_id[0], chip_id[1]); + } else { + ret = fts_get_chip_types(ts_data, chip_id[0], chip_id[1], VALID); + if (!ret) + break; + else + FTS_DEBUG("TP not ready, read:0x%02x%02x", chip_id[0], chip_id[1]); + } + + cnt++; + msleep(INTERVAL_READ_REG); + } while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG); + + if ((cnt * INTERVAL_READ_REG) >= TIMEOUT_READ_REG) { + FTS_INFO("fw is invalid, need read boot id"); +#if FTS_HID_SUPPORTTED + fts_i2c_hid2std(client); +#endif + id_cmd[0] = FTS_CMD_START1; + id_cmd[1] = FTS_CMD_START2; + ret = fts_i2c_write(client, id_cmd, 2); + if (ret < 0) { + FTS_ERROR("start cmd write fail"); + return ret; + } + id_cmd[0] = FTS_CMD_READ_ID; + id_cmd[1] = id_cmd[2] = id_cmd[3] = 0x00; + ret = fts_i2c_read(client, id_cmd, 4, chip_id, 2); + if ((ret < 0) || (0x0 == chip_id[0]) || (0x0 == chip_id[1])) { + FTS_ERROR("read boot id fail"); + return -EIO; + } + ret = fts_get_chip_types(ts_data, chip_id[0], chip_id[1], INVALID); + if (ret < 0) { + FTS_ERROR("can't get ic informaton"); + return ret; + } + } + + ts_data->ic_info.is_incell = FTS_CHIP_IDC; + ts_data->ic_info.hid_supported = FTS_HID_SUPPORTTED; + FTS_INFO("get ic information, chip id = 0x%02x%02x", + ts_data->ic_info.ids.chip_idh, ts_data->ic_info.ids.chip_idl); + + return 0; +} + +/***************************************************************************** +* Name: fts_reset_proc +* Brief: Execute reset operation +* Input: hdelayms - delay time unit:ms +* Output: +* Return: +*****************************************************************************/ +int fts_reset_proc(int hdelayms) +{ + FTS_FUNC_ENTER(); + gpio_direction_output(fts_data->pdata->reset_gpio, 0); + msleep(20); + gpio_direction_output(fts_data->pdata->reset_gpio, 1); + if (hdelayms) { + msleep(hdelayms); + } + + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_irq_disable +* Brief: disable irq +* Input: +* Output: +* Return: +*****************************************************************************/ +void fts_irq_disable(void) +{ + unsigned long irqflags; + + FTS_FUNC_ENTER(); + spin_lock_irqsave(&fts_data->irq_lock, irqflags); + + if (!fts_data->irq_disabled) { + disable_irq_nosync(fts_data->irq); + fts_data->irq_disabled = true; + } + + spin_unlock_irqrestore(&fts_data->irq_lock, irqflags); + FTS_FUNC_EXIT(); +} + +/***************************************************************************** +* Name: fts_irq_enable +* Brief: enable irq +* Input: +* Output: +* Return: +*****************************************************************************/ +void fts_irq_enable(void) +{ + unsigned long irqflags = 0; + + FTS_FUNC_ENTER(); + spin_lock_irqsave(&fts_data->irq_lock, irqflags); + + if (fts_data->irq_disabled) { + enable_irq(fts_data->irq); + fts_data->irq_disabled = false; + } + + spin_unlock_irqrestore(&fts_data->irq_lock, irqflags); + FTS_FUNC_EXIT(); +} + + +/***************************************************************************** +* Power Control +*****************************************************************************/ +static int fts_power_source_init(struct fts_ts_data *data) +{ + int ret = 0; + + FTS_FUNC_ENTER(); + + data->vdd = regulator_get(&data->client->dev, "vdd"); + if (IS_ERR(data->vdd)) { + ret = PTR_ERR(data->vdd); + FTS_ERROR("get vdd regulator failed,ret=%d", ret); + return ret; + } + + if (regulator_count_voltages(data->vdd) > 0) { + ret = regulator_set_voltage(data->vdd, FTS_VTG_MIN_UV, FTS_VTG_MAX_UV); + if (ret) { + FTS_ERROR("vdd regulator set_vtg failed ret=%d", ret); + goto err_set_vtg_vdd; + } + } + + data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c"); + if (IS_ERR(data->vcc_i2c)) { + ret = PTR_ERR(data->vcc_i2c); + FTS_ERROR("ret vcc_i2c regulator failed,ret=%d", ret); + goto err_get_vcc; + } + + if (regulator_count_voltages(data->vcc_i2c) > 0) { + ret = regulator_set_voltage(data->vcc_i2c, FTS_I2C_VTG_MIN_UV, FTS_I2C_VTG_MAX_UV); + if (ret) { + FTS_ERROR("vcc_i2c regulator set_vtg failed ret=%d", ret); + goto err_set_vtg_vcc; + } + } + + FTS_FUNC_EXIT(); + return 0; + +err_set_vtg_vcc: + regulator_put(data->vcc_i2c); +err_get_vcc: + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FTS_VTG_MAX_UV); +err_set_vtg_vdd: + regulator_put(data->vdd); + + FTS_FUNC_EXIT(); + return ret; +} + +static int fts_power_source_release(struct fts_ts_data *data) +{ + if (regulator_count_voltages(data->vdd) > 0) + regulator_set_voltage(data->vdd, 0, FTS_VTG_MAX_UV); + regulator_put(data->vdd); + + if (regulator_count_voltages(data->vcc_i2c) > 0) + regulator_set_voltage(data->vcc_i2c, 0, FTS_I2C_VTG_MAX_UV); + regulator_put(data->vcc_i2c); + + return 0; +} + +static int fts_power_source_ctrl(struct fts_ts_data *data, int enable) +{ + int ret = 0; + + FTS_FUNC_ENTER(); + if (enable) { + ret = regulator_enable(data->vdd); + if (ret) { + FTS_ERROR("enable vdd regulator failed,ret=%d", ret); + } + + ret = regulator_enable(data->vcc_i2c); + if (ret) { + FTS_ERROR("enable vcc_i2c regulator failed,ret=%d", ret); + } + } else { + ret = regulator_disable(data->vdd); + if (ret) { + FTS_ERROR("disable vdd regulator failed,ret=%d", ret); + } + ret = regulator_disable(data->vcc_i2c); + if (ret) { + FTS_ERROR("disable vcc_i2c regulator failed,ret=%d", ret); + } + } + + FTS_FUNC_EXIT(); + return ret; +} + + +/***************************************************************************** +* Name: fts_pinctrl_init +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_pinctrl_init(struct fts_ts_data *ts) +{ + int ret = 0; + struct i2c_client *client = ts->client; + + ts->pinctrl = devm_pinctrl_get(&client->dev); + if (IS_ERR_OR_NULL(ts->pinctrl)) { + FTS_ERROR("Failed to get pinctrl, please check dts"); + ret = PTR_ERR(ts->pinctrl); + goto err_pinctrl_get; + } + + ts->pins_active = pinctrl_lookup_state(ts->pinctrl, "pmx_ts_active"); + if (IS_ERR_OR_NULL(ts->pins_active)) { + FTS_ERROR("Pin state[active] not found"); + ret = PTR_ERR(ts->pins_active); + goto err_pinctrl_lookup; + } + + ts->pins_suspend = pinctrl_lookup_state(ts->pinctrl, "pmx_ts_suspend"); + if (IS_ERR_OR_NULL(ts->pins_suspend)) { + FTS_ERROR("Pin state[suspend] not found"); + ret = PTR_ERR(ts->pins_suspend); + goto err_pinctrl_lookup; + } + + ts->pins_release = pinctrl_lookup_state(ts->pinctrl, "pmx_ts_release"); + if (IS_ERR_OR_NULL(ts->pins_release)) { + FTS_ERROR("Pin state[release] not found"); + ret = PTR_ERR(ts->pins_release); + } + + return 0; +err_pinctrl_lookup: + if (ts->pinctrl) { + devm_pinctrl_put(ts->pinctrl); + } +err_pinctrl_get: + ts->pinctrl = NULL; + ts->pins_release = NULL; + ts->pins_suspend = NULL; + ts->pins_active = NULL; + return ret; +} + +static int fts_pinctrl_select_normal(struct fts_ts_data *ts) +{ + int ret = 0; + + if (ts->pinctrl && ts->pins_active) { + ret = pinctrl_select_state(ts->pinctrl, ts->pins_active); + if (ret < 0) { + FTS_ERROR("Set normal pin state error:%d", ret); + } + } + + return ret; +} + + + + + + + + + + + + + + + +static int fts_pinctrl_select_release(struct fts_ts_data *ts) +{ + int ret = 0; + + if (ts->pinctrl) { + if (IS_ERR_OR_NULL(ts->pins_release)) { + devm_pinctrl_put(ts->pinctrl); + ts->pinctrl = NULL; + } else { + ret = pinctrl_select_state(ts->pinctrl, ts->pins_release); + if (ret < 0) + FTS_ERROR("Set gesture pin state error:%d", ret); + } + } + + return ret; +} + + + + +/***************************************************************************** +* Reprot related +*****************************************************************************/ +/************************************************************************ + * Name: fts_input_report_key + * Brief: report key event + * Input: events info + * Output: + * Return: return 0 if success + ***********************************************************************/ +static int fts_input_report_key(struct fts_ts_data *data, int index) +{ + u32 ik; + int id = data->events[index].id; + int x = data->events[index].x; + int y = data->events[index].y; + int flag = data->events[index].flag; + u32 key_num = data->pdata->key_number; + + if (!KEY_EN(data)) { + return -EINVAL; + } + for (ik = 0; ik < key_num; ik++) { + if (TOUCH_IN_KEY(x, data->pdata->key_x_coords[ik])) { + if (EVENT_DOWN(flag)) { + data->key_down = true; + input_report_key(data->input_dev, data->pdata->keys[ik], 1); + FTS_DEBUG("Key%d(%d, %d) DOWN!", ik, x, y); + } else { + data->key_down = false; + input_report_key(data->input_dev, data->pdata->keys[ik], 0); + FTS_DEBUG("Key%d(%d, %d) Up!", ik, x, y); + } + return 0; + } + } + + FTS_ERROR("invalid touch for key, [%d](%d, %d)", id, x, y); + return -EINVAL; +} + +/*Modifiy by HQ-zmc [Date: 2018-03-26 11:31:37]*/ +static bool p_down[10] = {0}; + +#if FTS_MT_PROTOCOL_B_EN +static int fts_input_report_b(struct fts_ts_data *data) +{ + int i = 0; + int uppoint = 0; + int touchs = 0; + bool va_reported = false; + u32 max_touch_num = data->pdata->max_touch_number; + u32 key_y_coor = data->pdata->key_y_coord; + struct ts_event *events = data->events; + + for (i = 0; i < data->touch_point; i++) { + if (KEY_EN(data) && TOUCH_IS_KEY(events[i].y, key_y_coor)) { + fts_input_report_key(data, i); + continue; + } + + if (events[i].id >= max_touch_num) + break; + + va_reported = true; + input_mt_slot(data->input_dev, events[i].id); + + if (EVENT_DOWN(events[i].flag)) { + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, true); + + if (events[i].p <= 0) { + events[i].p = 0x3f; + } + input_report_abs(data->input_dev, ABS_MT_PRESSURE, events[i].p); + + if (events[i].area <= 0) { + events[i].area = 0x09; + } + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, events[i].area); + input_report_abs(data->input_dev, ABS_MT_POSITION_X, events[i].x); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, events[i].y); + + touchs |= BIT(events[i].id); + data->touchs |= BIT(events[i].id); + + /*Modifiy by HQ-zmc [Date: 2018-03-26 14:13:47]*/ + if (!p_down[events[i].id]){ + FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!", events[i].id, events[i].x, + events[i].y, events[i].p, events[i].area); + p_down[events[i].id] = true; + } + } else { + uppoint++; + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false); + data->touchs &= ~BIT(events[i].id); + /*Modifiy by HQ-zmc [Date: 2018-03-26 14:13:53]*/ + FTS_DEBUG("[B]P%d(%d, %d) UP!", events[i].id, events[i].x, events[i].y); + p_down[events[i].id] = false; + } + } + + if (unlikely(data->touchs ^ touchs)) { + for (i = 0; i < max_touch_num; i++) { + if (BIT(i) & (data->touchs ^ touchs)) { + FTS_DEBUG("[B]P%d UP!", i); + va_reported = true; + input_mt_slot(data->input_dev, i); + input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false); + } + } + } + data->touchs = touchs; + + if (va_reported) { + /* touchs==0, there's no point but key */ + if (EVENT_NO_DOWN(data) || (!touchs)) { + + input_report_key(data->input_dev, BTN_TOUCH, 0); + } else { + input_report_key(data->input_dev, BTN_TOUCH, 1); + } + } + + input_sync(data->input_dev); + return 0; +} + +#else +static int fts_input_report_a(struct fts_ts_data *data) +{ + int i = 0; + int touchs = 0; + bool va_reported = false; + u32 key_y_coor = data->pdata->key_y_coord; + struct ts_event *events = data->events; + + for (i = 0; i < data->touch_point; i++) { + if (KEY_EN(data) && TOUCH_IS_KEY(events[i].y, key_y_coor)) { + fts_input_report_key(data, i); + continue; + } + + va_reported = true; + if (EVENT_DOWN(events[i].flag)) { + input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, events[i].id); + + if (events[i].p <= 0) { + events[i].p = 0x3f; + } + input_report_abs(data->input_dev, ABS_MT_PRESSURE, events[i].p); + if (events[i].area <= 0) { + events[i].area = 0x09; + } + input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, events[i].area); + + input_report_abs(data->input_dev, ABS_MT_POSITION_X, events[i].x); + input_report_abs(data->input_dev, ABS_MT_POSITION_Y, events[i].y); + + input_mt_sync(data->input_dev); + + FTS_DEBUG("[A]P%d(%d, %d)[p:%d,tm:%d] DOWN!", events[i].id, events[i].x, + events[i].y, events[i].p, events[i].area); + touchs++; + } + } + + /* last point down, current no point but key */ + if (data->touchs && !touchs) { + va_reported = true; + } + data->touchs = touchs; + + if (va_reported) { + if (EVENT_NO_DOWN(data)) { + FTS_DEBUG("[A]Points All Up!"); + input_report_key(data->input_dev, BTN_TOUCH, 0); + input_mt_sync(data->input_dev); + } else { + input_report_key(data->input_dev, BTN_TOUCH, 1); + } + } + + input_sync(data->input_dev); + return 0; +} +#endif + +/***************************************************************************** +* Name: fts_read_touchdata +* Brief: +* Input: +* Output: +* Return: return 0 if succuss +*****************************************************************************/ +static int fts_read_touchdata(struct fts_ts_data *data) +{ + int ret = 0; + int i = 0; + u8 pointid; + int base; + struct ts_event *events = data->events; + int max_touch_num = data->pdata->max_touch_number; + u8 *buf = data->point_buf; + + + data->point_num = 0; + data->touch_point = 0; + + memset(buf, 0xFF, data->pnt_buf_size); + buf[0] = 0x00; + + ret = fts_i2c_read(data->client, buf, 1, buf, data->pnt_buf_size); + if (ret < 0) { + FTS_ERROR("read touchdata failed, ret:%d", ret); + return ret; + } + data->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F; + if (data->point_num > max_touch_num) { + FTS_INFO("invalid point_num(%d)", data->point_num); + return -EIO; + } + + for (i = 0; i < max_touch_num; i++) { + base = FTS_ONE_TCH_LEN * i; + + pointid = (buf[FTS_TOUCH_ID_POS + base]) >> 4; + if (pointid >= FTS_MAX_ID) + break; + else if (pointid >= max_touch_num) { + FTS_ERROR("ID(%d) beyond max_touch_number", pointid); + return -EINVAL; + } + + data->touch_point++; + + events[i].x = ((buf[FTS_TOUCH_X_H_POS + base] & 0x0F) << 8) + + (buf[FTS_TOUCH_X_L_POS + base] & 0xFF); + events[i].y = ((buf[FTS_TOUCH_Y_H_POS + base] & 0x0F) << 8) + + (buf[FTS_TOUCH_Y_L_POS + base] & 0xFF); + events[i].flag = buf[FTS_TOUCH_EVENT_POS + base] >> 6; + events[i].id = buf[FTS_TOUCH_ID_POS + base] >> 4; + events[i].area = buf[FTS_TOUCH_AREA_POS + base] >> 4; + events[i].p = buf[FTS_TOUCH_PRE_POS + base]; + + if (EVENT_DOWN(events[i].flag) && (data->point_num == 0)) { + FTS_INFO("abnormal touch data from fw"); + return -EIO; + } + } + if (data->touch_point == 0) { + FTS_INFO("no touch point information"); + return -EIO; + } + + return 0; +} + +/***************************************************************************** +* Name: fts_report_event +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_report_event(struct fts_ts_data *data) +{ +#if FTS_MT_PROTOCOL_B_EN + fts_input_report_b(data); +#else + fts_input_report_a(data); +#endif +} + +/***************************************************************************** +* Name: fts_ts_interrupt +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static irqreturn_t fts_ts_interrupt(int irq, void *data) +{ + int ret = 0; + struct fts_ts_data *ts_data = (struct fts_ts_data *)data; + + if (!ts_data) { + FTS_ERROR("[INTR]: Invalid fts_ts_data"); + return IRQ_HANDLED; + } + + + ret = fts_read_touchdata(ts_data); + if (ret == 0) { + mutex_lock(&ts_data->report_mutex); + fts_report_event(ts_data); + mutex_unlock(&ts_data->report_mutex); + } + + return IRQ_HANDLED; +} + +/***************************************************************************** +* Name: fts_irq_registration +* Brief: +* Input: +* Output: +* Return: return 0 if succuss, otherwise return error code +*****************************************************************************/ +static int fts_irq_registration(struct fts_ts_data *ts_data) +{ + int ret = 0; + struct fts_ts_platform_data *pdata = ts_data->pdata; + + ts_data->irq = gpio_to_irq(pdata->irq_gpio); + FTS_INFO("irq in ts_data:%d irq in client:%d", ts_data->irq, ts_data->client->irq); + if (ts_data->irq != ts_data->client->irq) + FTS_ERROR("IRQs are inconsistent, please check & in DTS"); + + if (0 == pdata->irq_gpio_flags) + pdata->irq_gpio_flags = IRQF_TRIGGER_FALLING; + FTS_INFO("irq flag:%x", pdata->irq_gpio_flags); + ret = request_threaded_irq(ts_data->irq, NULL, fts_ts_interrupt, + pdata->irq_gpio_flags | IRQF_ONESHOT, + ts_data->client->name, ts_data); + + return ret; +} + +/***************************************************************************** +* Name: fts_input_init +* Brief: input device init +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_input_init(struct fts_ts_data *ts_data) +{ + int ret = 0; + int key_num = 0; + struct fts_ts_platform_data *pdata = ts_data->pdata; + struct input_dev *input_dev; + int point_num; + + FTS_FUNC_ENTER(); + + input_dev = input_allocate_device(); + if (!input_dev) { + FTS_ERROR("Failed to allocate memory for input device"); + return -ENOMEM; + } + + /* Init and register Input device */ + input_dev->name = FTS_DRIVER_NAME; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &ts_data->client->dev; + + input_set_drvdata(input_dev, ts_data); + + __set_bit(EV_SYN, input_dev->evbit); + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + + if (pdata->have_key) { + FTS_INFO("set key capabilities"); + for (key_num = 0; key_num < pdata->key_number; key_num++) + input_set_capability(input_dev, EV_KEY, pdata->keys[key_num]); + } + +#if FTS_MT_PROTOCOL_B_EN + input_mt_init_slots(input_dev, pdata->max_touch_number, INPUT_MT_DIRECT); +#else + input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 0x0f, 0, 0); +#endif + input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, pdata->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, pdata->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0); + + point_num = pdata->max_touch_number; + ts_data->pnt_buf_size = point_num * FTS_ONE_TCH_LEN + 3; + ts_data->point_buf = (u8 *)kzalloc(ts_data->pnt_buf_size, GFP_KERNEL); + if (!ts_data->point_buf) { + FTS_ERROR("failed to alloc memory for point buf!"); + ret = -ENOMEM; + goto err_point_buf; + } + + ts_data->events = (struct ts_event *)kzalloc(point_num * sizeof(struct ts_event), GFP_KERNEL); + if (!ts_data->events) { + + FTS_ERROR("failed to alloc memory for point events!"); + ret = -ENOMEM; + goto err_event_buf; + } + + + ret = input_register_device(input_dev); + if (ret) { + FTS_ERROR("Input device registration failed"); + goto err_input_reg; + } + + ts_data->input_dev = input_dev; + + FTS_FUNC_EXIT(); + return 0; + +err_input_reg: + kfree_safe(ts_data->events); + +err_event_buf: + kfree_safe(ts_data->point_buf); + +err_point_buf: + input_set_drvdata(input_dev, NULL); + input_free_device(input_dev); + input_dev = NULL; + + FTS_FUNC_EXIT(); + return ret; +} + + +/***************************************************************************** +* Name: fts_gpio_configure +* Brief: Configure IRQ&RESET GPIO +* Input: +* Output: +* Return: return 0 if succuss +*****************************************************************************/ +static int fts_gpio_configure(struct fts_ts_data *data) +{ + int ret = 0; + + FTS_FUNC_ENTER(); + /* request irq gpio */ + if (gpio_is_valid(data->pdata->irq_gpio)) { + ret = gpio_request(data->pdata->irq_gpio, "fts_irq_gpio"); + if (ret) { + FTS_ERROR("[GPIO]irq gpio request failed"); + goto err_irq_gpio_req; + } + + ret = gpio_direction_input(data->pdata->irq_gpio); + if (ret) { + FTS_ERROR("[GPIO]set_direction for irq gpio failed"); + goto err_irq_gpio_dir; + } + } + + /* request reset gpio */ + if (gpio_is_valid(data->pdata->reset_gpio)) { + ret = gpio_request(data->pdata->reset_gpio, "fts_reset_gpio"); + if (ret) { + FTS_ERROR("[GPIO]reset gpio request failed"); + goto err_irq_gpio_dir; + } + + ret = gpio_direction_output(data->pdata->reset_gpio, 1); + if (ret) { + FTS_ERROR("[GPIO]set_direction for reset gpio failed"); + goto err_reset_gpio_dir; + } + } + + FTS_FUNC_EXIT(); + return 0; + +err_reset_gpio_dir: + if (gpio_is_valid(data->pdata->reset_gpio)) + gpio_free(data->pdata->reset_gpio); +err_irq_gpio_dir: + if (gpio_is_valid(data->pdata->irq_gpio)) + gpio_free(data->pdata->irq_gpio); +err_irq_gpio_req: + FTS_FUNC_EXIT(); + return ret; +} + +/***************************************************************************** +* Name: fts_get_dt_coords +* Brief: +* Input: +* Output: +* Return: return 0 if succuss, otherwise return error code +*****************************************************************************/ +static int fts_get_dt_coords(struct device *dev, char *name, + struct fts_ts_platform_data *pdata) +{ + int ret = 0; + u32 coords[FTS_COORDS_ARR_SIZE] = { 0 }; + struct property *prop; + struct device_node *np = dev->of_node; + int coords_size; + + prop = of_find_property(np, name, NULL); + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + + coords_size = prop->length / sizeof(u32); + if (coords_size != FTS_COORDS_ARR_SIZE) { + FTS_ERROR("invalid:%s, size:%d", name, coords_size); + return -EINVAL; + } + + ret = of_property_read_u32_array(np, name, coords, coords_size); + if (ret && (ret != -EINVAL)) { + FTS_ERROR("Unable to read %s", name); + return -ENODATA; + } + + if (!strcmp(name, "focaltech,display-coords")) { + pdata->x_min = coords[0]; + pdata->y_min = coords[1]; + pdata->x_max = coords[2]; + pdata->y_max = coords[3]; + } else { + FTS_ERROR("unsupported property %s", name); + return -EINVAL; + } + + FTS_INFO("display x(%d %d) y(%d %d)", pdata->x_min, pdata->x_max, + pdata->y_min, pdata->y_max); + return 0; +} + +/***************************************************************************** +* Name: fts_parse_dt +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata) +{ + int ret = 0; + struct device_node *np = dev->of_node; + u32 temp_val; + + FTS_FUNC_ENTER(); + + ret = fts_get_dt_coords(dev, "focaltech,display-coords", pdata); + if (ret < 0) + FTS_ERROR("Unable to get display-coords"); + + /* key */ + pdata->have_key = of_property_read_bool(np, "focaltech,have-key"); + if (pdata->have_key) { + ret = of_property_read_u32(np, "focaltech,key-number", &pdata->key_number); + if (ret) + FTS_ERROR("Key number undefined!"); + + ret = of_property_read_u32_array(np, "focaltech,keys", + pdata->keys, pdata->key_number); + if (ret) + FTS_ERROR("Keys undefined!"); + else if (pdata->key_number > FTS_MAX_KEYS) + pdata->key_number = FTS_MAX_KEYS; + + ret = of_property_read_u32(np, "focaltech,key-y-coord", &pdata->key_y_coord); + if (ret) + FTS_ERROR("Key Y Coord undefined!"); + + ret = of_property_read_u32_array(np, "focaltech,key-x-coords", + pdata->key_x_coords, pdata->key_number); + if (ret) + FTS_ERROR("Key X Coords undefined!"); + + FTS_INFO("VK(%d): (%d, %d, %d), [%d, %d, %d][%d]", + pdata->key_number, pdata->keys[0], pdata->keys[1], pdata->keys[2], + pdata->key_x_coords[0], pdata->key_x_coords[1], pdata->key_x_coords[2], + pdata->key_y_coord); + } + + /* reset, irq gpio info */ + pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio", 0, &pdata->reset_gpio_flags); + if (pdata->reset_gpio < 0) + FTS_ERROR("Unable to get reset_gpio"); + + pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio", 0, &pdata->irq_gpio_flags); + if (pdata->irq_gpio < 0) + FTS_ERROR("Unable to get irq_gpio"); + + ret = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val); + if (0 == ret) { + if (temp_val < 2) + pdata->max_touch_number = 2; + else if (temp_val > FTS_MAX_POINTS_SUPPORT) + pdata->max_touch_number = FTS_MAX_POINTS_SUPPORT; + else + pdata->max_touch_number = temp_val; + } else { + FTS_ERROR("Unable to get max-touch-number"); + pdata->max_touch_number = FTS_MAX_POINTS_SUPPORT; + } + + FTS_INFO("max touch number:%d, irq gpio:%d, reset gpio:%d", + pdata->max_touch_number, pdata->irq_gpio, pdata->reset_gpio); + + FTS_FUNC_EXIT(); + return 0; +} + +#if defined(CONFIG_FB) +/***************************************************************************** +* Name: fb_notifier_callback +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct fts_ts_data *fts_data = + container_of(self, struct fts_ts_data, fb_notif); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && + fts_data && fts_data->client) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) + fts_ts_resume(&fts_data->client->dev); + else if (*blank == FB_BLANK_POWERDOWN) + fts_ts_suspend(&fts_data->client->dev); + } + + return 0; +} +#elif defined(CONFIG_HAS_EARLYSUSPEND) +/***************************************************************************** +* Name: fts_ts_early_suspend +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_ts_early_suspend(struct early_suspend *handler) +{ + struct fts_ts_data *data = container_of(handler, + struct fts_ts_data, + early_suspend); + + fts_ts_suspend(&data->client->dev); +} + +/***************************************************************************** +* Name: fts_ts_late_resume +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void fts_ts_late_resume(struct early_suspend *handler) +{ + struct fts_ts_data *data = container_of(handler, + struct fts_ts_data, + early_suspend); + + fts_ts_resume(&data->client->dev); +} +#endif + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-01-02 17:12:58 + * @input: ts_data + * @output: ret + * ============================ + */ + + + +int fts_5446_enable_charger_mode = 0; + + +/***************************************************************************** +* Name: fts_ts_probe +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = 0; + struct fts_ts_platform_data *pdata; + struct fts_ts_data *ts_data; + + FTS_FUNC_ENTER(); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + FTS_ERROR("I2C not supported"); + return -ENODEV; + } + + if (client->dev.of_node) { + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + FTS_ERROR("Failed to allocate memory for platform data"); + return -ENOMEM; + } + ret = fts_parse_dt(&client->dev, pdata); + if (ret) + FTS_ERROR("[DTS]DT parsing failed"); + } else { + pdata = client->dev.platform_data; + } + + if (!pdata) { + FTS_ERROR("no ts platform data found"); + return -EINVAL; + } + + ts_data = devm_kzalloc(&client->dev, sizeof(*ts_data), GFP_KERNEL); + if (!ts_data) { + FTS_ERROR("Failed to allocate memory for fts_data"); + return -ENOMEM; + } + + fts_data = ts_data; + ts_data->client = client; + ts_data->pdata = pdata; + i2c_set_clientdata(client, ts_data); + + ts_data->ts_workqueue = create_singlethread_workqueue("fts_wq"); + if (NULL == ts_data->ts_workqueue) { + FTS_ERROR("failed to create fts workqueue"); + } + + spin_lock_init(&ts_data->irq_lock); + mutex_init(&ts_data->report_mutex); + + ret = fts_input_init(ts_data); + if (ret) { + FTS_ERROR("fts input initialize fail"); + goto err_input_init; + } + + + ret = fts_power_source_init(ts_data); + if (ret) { + FTS_ERROR("fail to get vdd/vcc_i2c regulator"); + goto err_power_init; + } + ret = fts_power_source_ctrl(ts_data, ENABLE); + if (ret) { + FTS_ERROR("fail to enable vdd/vcc_i2c regulator"); + goto err_power_ctrl; + } + + + ret = fts_pinctrl_init(ts_data); + if (0 == ret) { + fts_pinctrl_select_normal(ts_data); + } + + + + ret = fts_gpio_configure(ts_data); + if (ret) { + FTS_ERROR("[GPIO]Failed to configure the gpios"); + goto err_gpio_config; + } + + fts_reset_proc(200); + ret = fts_get_ic_information(ts_data); + if (ret) { + FTS_ERROR("not focal IC, unregister driver"); + goto err_irq_req; + } + + ret = fts_irq_registration(ts_data); + if (ret) { + FTS_ERROR("request irq failed"); + goto err_irq_req; + } + +#if defined(CONFIG_FB) + ts_data->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts_data->fb_notif); + if (ret) { + FTS_ERROR("[FB]Unable to register fb_notifier: %d", ret); + } +#elif defined(CONFIG_HAS_EARLYSUSPEND) + ts_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + FTS_SUSPEND_LEVEL; + ts_data->early_suspend.suspend = fts_ts_early_suspend; + ts_data->early_suspend.resume = fts_ts_late_resume; + register_early_suspend(&ts_data->early_suspend); +#endif + + FTS_FUNC_EXIT(); + return 0; + +err_irq_req: + if (gpio_is_valid(pdata->reset_gpio)) + gpio_free(pdata->reset_gpio); + if (gpio_is_valid(pdata->irq_gpio)) + gpio_free(pdata->irq_gpio); +err_gpio_config: + + + fts_pinctrl_select_release(ts_data); + + fts_power_source_ctrl(ts_data, DISABLE); +err_power_ctrl: + fts_power_source_release(ts_data); +err_power_init: + + kfree_safe(ts_data->point_buf); + kfree_safe(ts_data->events); + input_unregister_device(ts_data->input_dev); +err_input_init: + if (ts_data->ts_workqueue) + destroy_workqueue(ts_data->ts_workqueue); + devm_kfree(&client->dev, ts_data); + + FTS_FUNC_EXIT(); + return ret; +} + +/***************************************************************************** +* Name: fts_ts_remove +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_ts_remove(struct i2c_client *client) +{ + struct fts_ts_data *ts_data = i2c_get_clientdata(client); + + FTS_FUNC_ENTER(); + +#if defined(CONFIG_FB) + if (fb_unregister_client(&ts_data->fb_notif)) + FTS_ERROR("Error occurred while unregistering fb_notifier."); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&ts_data->early_suspend); +#endif + + free_irq(client->irq, ts_data); + input_unregister_device(ts_data->input_dev); + + if (gpio_is_valid(ts_data->pdata->reset_gpio)) + gpio_free(ts_data->pdata->reset_gpio); + + if (gpio_is_valid(ts_data->pdata->irq_gpio)) + gpio_free(ts_data->pdata->irq_gpio); + + if (ts_data->ts_workqueue) + destroy_workqueue(ts_data->ts_workqueue); + + + + fts_pinctrl_select_release(ts_data); + + fts_power_source_ctrl(ts_data, DISABLE); + fts_power_source_release(ts_data); + + + kfree_safe(ts_data->point_buf); + kfree_safe(ts_data->events); + + devm_kfree(&client->dev, ts_data); + + FTS_FUNC_EXIT(); + return 0; +} + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static int fts_ts_pm_suspend(struct device *dev){ + FTS_FUNC_ENTER(); + if (lcm_ffbm_mode){ + fts_ts_suspend(dev); + } + else{ + FTS_INFO("We are not in ffbm mode\n"); + } + FTS_FUNC_EXIT(); + return 0; +} + +static int fts_ts_pm_resume(struct device *dev){ + FTS_FUNC_ENTER(); + if (lcm_ffbm_mode){ + fts_ts_resume(dev); + } + else{ + FTS_INFO("We are not in ffbm mode\n"); + } + FTS_FUNC_EXIT(); + return 0; +} +#endif + +/***************************************************************************** +* Name: fts_ts_suspend +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_ts_suspend(struct device *dev) +{ + struct fts_ts_data *ts_data = dev_get_drvdata(dev); + + FTS_FUNC_ENTER(); + if (ts_data->suspended) { + FTS_INFO("Already in suspend state"); + return 0; + } + + fts_irq_disable(); + ts_data->suspended = true; + FTS_FUNC_EXIT(); + return 0; +} + +/***************************************************************************** +* Name: fts_ts_resume +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int fts_ts_resume(struct device *dev) +{ + struct fts_ts_data *ts_data = dev_get_drvdata(dev); + + FTS_FUNC_ENTER(); + if (!ts_data->suspended) { + FTS_DEBUG("Already in awake state"); + return 0; + } + + + fts_power_source_ctrl(ts_data, ENABLE); + fts_pinctrl_select_normal(ts_data); + + if (!ts_data->ic_info.is_incell) { + fts_reset_proc(200); + } + + + fts_irq_enable(); + + + ts_data->suspended = false; + + FTS_FUNC_EXIT(); + return 0; +} + + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-01-15 11:28:54 + * @input: + * @output: + * ============================ + */ +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static const struct dev_pm_ops ft5446_dev_pm_ops = { + .suspend = fts_ts_pm_suspend, + .resume = fts_ts_pm_resume, +}; +#endif + + +/***************************************************************************** +* I2C Driver +*****************************************************************************/ +static const struct i2c_device_id fts_ts_id[] = { + {FTS_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, fts_ts_id); + +static struct of_device_id fts_match_table[] = { + { .compatible = "focaltech,5446", }, + { }, +}; + +static struct i2c_driver fts_ts_driver = { + .probe = fts_ts_probe, + .remove = fts_ts_remove, + .driver = { + .name = FTS_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = fts_match_table, + #if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) + .pm = &ft5446_dev_pm_ops, + #endif + }, + .id_table = fts_ts_id, +}; + +/***************************************************************************** +* Name: fts_ts_init +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static int __init fts_ts_init(void) +{ + int ret = 0; + + FTS_FUNC_ENTER(); + ret = i2c_add_driver(&fts_ts_driver); + if (ret != 0) { + FTS_ERROR("Focaltech touch screen driver init failed!"); + } + FTS_FUNC_EXIT(); + return ret; +} + +/***************************************************************************** +* Name: fts_ts_exit +* Brief: +* Input: +* Output: +* Return: +*****************************************************************************/ +static void __exit fts_ts_exit(void) +{ + i2c_del_driver(&fts_ts_driver); +} + +module_init(fts_ts_init); +module_exit(fts_ts_exit); + +MODULE_AUTHOR("FocalTech Driver Team"); +MODULE_DESCRIPTION("FocalTech Touchscreen Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/ft5446/focaltech_core.h b/drivers/input/touchscreen/ft5446/focaltech_core.h new file mode 100644 index 0000000000000..1260ff92ff56e --- /dev/null +++ b/drivers/input/touchscreen/ft5446/focaltech_core.h @@ -0,0 +1,185 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +/***************************************************************************** +* +* File Name: focaltech_core.h + +* Author: Focaltech Driver Team +* +* Created: 2016-08-08 +* +* Abstract: +* +* Reference: +* +*****************************************************************************/ + +#ifndef __LINUX_FOCALTECH_CORE_H__ +#define __LINUX_FOCALTECH_CORE_H__ +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "focaltech_common.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define FTS_MAX_POINTS_SUPPORT 10 /* constant value, can't be changed */ +#define FTS_MAX_KEYS 4 +#define FTS_KEY_WIDTH 50 +#define FTS_ONE_TCH_LEN 6 + +#define FTS_MAX_ID 0x0A +#define FTS_TOUCH_X_H_POS 3 +#define FTS_TOUCH_X_L_POS 4 +#define FTS_TOUCH_Y_H_POS 5 +#define FTS_TOUCH_Y_L_POS 6 +#define FTS_TOUCH_PRE_POS 7 +#define FTS_TOUCH_AREA_POS 8 +#define FTS_TOUCH_POINT_NUM 2 +#define FTS_TOUCH_EVENT_POS 3 +#define FTS_TOUCH_ID_POS 5 +#define FTS_COORDS_ARR_SIZE 4 + +#define FTS_TOUCH_DOWN 0 +#define FTS_TOUCH_UP 1 +#define FTS_TOUCH_CONTACT 2 +#define EVENT_DOWN(flag) ((FTS_TOUCH_DOWN == flag) || (FTS_TOUCH_CONTACT == flag)) +#define EVENT_UP(flag) (FTS_TOUCH_UP == flag) +#define EVENT_NO_DOWN(data) (!data->point_num) +#define KEY_EN(data) (data->pdata->have_key) +#define TOUCH_IS_KEY(y, key_y) (y == key_y) +#define TOUCH_IN_RANGE(val, key_val, half) ((val > (key_val - half)) && (val < (key_val + half))) +#define TOUCH_IN_KEY(x, key_x) TOUCH_IN_RANGE(x, key_x, FTS_KEY_WIDTH) + +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ +struct fts_ts_platform_data { + u32 irq_gpio; + u32 irq_gpio_flags; + u32 reset_gpio; + u32 reset_gpio_flags; + bool have_key; + u32 key_number; + u32 keys[FTS_MAX_KEYS]; + u32 key_y_coord; + u32 key_x_coords[FTS_MAX_KEYS]; + u32 x_max; + u32 y_max; + u32 x_min; + u32 y_min; + u32 max_touch_number; +}; + +struct ts_event { + int x; /*x coordinate */ + int y; /*y coordinate */ + int p; /* pressure */ + int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */ + int id; /*touch ID */ + int area; +}; + +struct fts_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + struct fts_ts_platform_data *pdata; + struct ts_ic_info ic_info; + struct workqueue_struct *ts_workqueue; + struct regulator *vdd; + struct regulator *vcc_i2c; + spinlock_t irq_lock; + struct mutex report_mutex; + int irq; + bool suspended; + bool irq_disabled; + /* multi-touch */ + struct ts_event *events; + u8 *point_buf; + int pnt_buf_size; + int touchs; + bool key_down; + int touch_point; + int point_num; + + struct pinctrl *pinctrl; + struct pinctrl_state *pins_active; + struct pinctrl_state *pins_suspend; + struct pinctrl_state *pins_release; + +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif +}; + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ +extern struct fts_ts_data *fts_data; + +/* i2c communication*/ +int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue); +int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue); +int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen); +int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen); +void fts_i2c_hid2std(struct i2c_client *client); +int fts_i2c_init(void); +int fts_i2c_exit(void); + + + +void fts_irq_disable(void); +void fts_irq_enable(void); + + +#endif /* __LINUX_FOCALTECH_CORE_H__ */ diff --git a/drivers/input/touchscreen/ft5446/focaltech_i2c.c b/drivers/input/touchscreen/ft5446/focaltech_i2c.c new file mode 100644 index 0000000000000..3b5c9ec98a511 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/focaltech_i2c.c @@ -0,0 +1,242 @@ +/* + * + * FocalTech TouchScreen driver. + * + * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/************************************************************************ +* +* File Name: focaltech_i2c.c +* +* Author: fupeipei +* +* Created: 2016-08-04 +* +* Abstract: i2c communication with TP +* +* Version: v1.0 +* +* Revision History: +* v1.0: +* First release. By fupeipei 2016-08-04 +************************************************************************/ + +/***************************************************************************** +* Included header files +*****************************************************************************/ +#include "focaltech_core.h" + +/***************************************************************************** +* Private constant and macro definitions using #define +*****************************************************************************/ +#define I2C_RETRY_NUMBER 3 +/***************************************************************************** +* Private enumerations, structures and unions using typedef +*****************************************************************************/ + +/***************************************************************************** +* Static variables +*****************************************************************************/ +static DEFINE_MUTEX(i2c_rw_access); + +/***************************************************************************** +* Global variable or extern global variabls/functions +*****************************************************************************/ + +/***************************************************************************** +* Static function prototypes +*****************************************************************************/ + +/***************************************************************************** +* functions body +*****************************************************************************/ + +/************************************************************************ +* Name: fts_i2c_read +* Brief: i2c read +* Input: i2c info, write buf, write len, read buf, read len +* Output: get data in the 3rd buf +* Return: fail <0 +***********************************************************************/ +int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen, char *readbuf, int readlen) +{ + int ret = 0; + int i = 0; + + mutex_lock(&i2c_rw_access); + + if (readlen > 0) { + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + for (i = 0; i < I2C_RETRY_NUMBER; i++) { + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret < 0) { + FTS_ERROR("[IIC]: i2c_transfer(write) error, ret=%d!!", ret); + } else + break; + } + } else { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = readlen, + .buf = readbuf, + }, + }; + for (i = 0; i < I2C_RETRY_NUMBER; i++) { + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) { + FTS_ERROR("[IIC]: i2c_transfer(read) error, ret=%d!!", ret); + } else + break; + } + } + } + + mutex_unlock(&i2c_rw_access); + return ret; +} + +/************************************************************************ +* Name: fts_i2c_write +* Brief: i2c write +* Input: i2c info, write buf, write len +* Output: no +* Return: fail <0 +***********************************************************************/ +int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen) +{ + int ret = 0; + int i = 0; + + mutex_lock(&i2c_rw_access); + if (writelen > 0) { + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = writelen, + .buf = writebuf, + }, + }; + for (i = 0; i < I2C_RETRY_NUMBER; i++) { + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret < 0) { + FTS_ERROR("%s: i2c_transfer(write) error, ret=%d", __func__, ret); + } else + break; + } + } + mutex_unlock(&i2c_rw_access); + + return ret; +} + +/************************************************************************ +* Name: fts_i2c_write_reg +* Brief: write register +* Input: i2c info, reg address, reg value +* Output: no +* Return: fail <0 +***********************************************************************/ +int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue) +{ + u8 buf[2] = {0}; + + buf[0] = regaddr; + buf[1] = regvalue; + return fts_i2c_write(client, buf, sizeof(buf)); +} + +/************************************************************************ +* Name: fts_i2c_read_reg +* Brief: read register +* Input: i2c info, reg address, reg value +* Output: get reg value +* Return: fail <0 +***********************************************************************/ +int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue) +{ + return fts_i2c_read(client, ®addr, 1, regvalue, 1); +} + +/************************************************************************ +* HID to standard I2C +***********************************************************************/ +void fts_i2c_hid2std(struct i2c_client *client) +{ + int ret = 0; + u8 buf[3] = {0xeb, 0xaa, 0x09}; + + ret = fts_i2c_write(client, buf, 3); + if (ret < 0) + FTS_ERROR("hid2std cmd write fail"); + else { + msleep(10); + buf[0] = buf[1] = buf[2] = 0; + ret = fts_i2c_read(client, NULL, 0, buf, 3); + if (ret < 0) + FTS_ERROR("hid2std cmd read fail"); + else if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2])) { + FTS_DEBUG("hidi2c change to stdi2c successful"); + } else { + FTS_ERROR("hidi2c change to stdi2c fail"); + } + } +} + +/************************************************************************ +* Name: fts_i2c_init +* Brief: fts i2c init +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_i2c_init(void) +{ + FTS_FUNC_ENTER(); + + FTS_FUNC_EXIT(); + return 0; +} +/************************************************************************ +* Name: fts_i2c_exit +* Brief: fts i2c exit +* Input: +* Output: +* Return: +***********************************************************************/ +int fts_i2c_exit(void) +{ + FTS_FUNC_ENTER(); + + FTS_FUNC_EXIT(); + return 0; +} + diff --git a/drivers/input/touchscreen/ft5446/include/firmware/D1S_1_FT5446_Ofilm_HuaXing_V0C_D01_20180711_app.i b/drivers/input/touchscreen/ft5446/include/firmware/D1S_1_FT5446_Ofilm_HuaXing_V0C_D01_20180711_app.i new file mode 100644 index 0000000000000..4c0f14cef5638 --- /dev/null +++ b/drivers/input/touchscreen/ft5446/include/firmware/D1S_1_FT5446_Ofilm_HuaXing_V0C_D01_20180711_app.i @@ -0,0 +1,3324 @@ +0x2, 0x19,0x22,0x2, 0xc5,0x93,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x49,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x58,0xb1,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x70,0x2e,0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x70,0x4a,0x2, 0x28,0x77,0x32,0x32,0x2, 0x0, 0x4a,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0x2, 0x2e,0xe0,0xff,0xff,0x2, 0x0, 0x5a,0xf5,0xfd, +0xe5,0xfe,0x22,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xd, 0x7e,0xf, 0x3c,0x2, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x3c,0x12,0x7e,0x73,0x3c,0x12,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xc, 0x80,0x2, 0xc2,0xc, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x72,0x8e,0x7e,0x1f,0x3c,0x2, 0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x3c,0x2, 0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x3c,0x6, 0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x3c,0xe, 0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x3c,0xc, 0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x3c,0x2d,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x68,0xc6,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x18,0xae,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18,0x92,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x18, +0xae,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18,0x4b,0x61,0x3f,0x7e,0x34,0x18,0x82,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x18,0x92,0x61,0x3f,0x7e,0x34,0x18,0x82,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x18,0x1b,0x61,0x3f,0x7e,0x34,0x17,0xff,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x18,0x2f,0x61,0x3f,0x7e,0x34,0x18,0x73,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18, +0x5a,0x61,0x3f,0x7e,0x34,0x18,0xae,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18,0x92,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x18,0xd2,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x18,0xd3,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3c,0x2, 0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x3c, +0x2, 0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x3c,0x2, 0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x1a,0x30,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x3c,0x3c,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x3c,0x3c,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3c,0x3c,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x3c,0x3c,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3c,0x3c,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3c,0x3c,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x3c,0x2d,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x3b,0xfa,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x3c, +0x2d,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x3b,0xfa,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x3c,0x2d,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x3c,0x2d,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x3c,0x2d,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x3c,0x2, 0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x16,0xe6,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x3c,0x2, 0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x16,0xe6,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x16,0xe6,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x3c,0x2, 0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x3c,0x3c,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0x3c,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x3c,0x3c,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x3c,0x3c,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xb2,0x86,0x22,0xff,0xff, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x3c,0x3c,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x3c,0x3c, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x3c,0x3c, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x3c,0x3c,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3c,0x29,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3c, +0x29,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x3c,0x29,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x3c,0x29,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x3b,0xfa,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x3b,0xfa,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x3b,0xfa,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x3b,0xfa,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x3c,0x2, 0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x3c,0x2, 0x79,0x11,0x0, 0x90,0x7e,0x1f,0x3c, +0x2, 0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x3c,0x2, 0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x3c,0x2, 0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x3c,0x2, 0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x3c,0x2, 0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x3c,0x2, 0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x3c, +0x2, 0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x3c,0x2, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x3c,0x2, 0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x3c,0x2, 0x79,0x32,0x0, 0x40,0x7e,0x2f,0x3c,0x2, 0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x3c,0x2, 0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x16,0xe6,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x16,0xe6,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0x3c, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x3c,0x3c,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x3c,0x29,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x3c,0x29,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x3c,0x29,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1c,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x3c,0x3c, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0x3c,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x3c,0x3c,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x3c, +0x3c,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x3c,0x3c,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x3c,0x2, 0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x3c,0x2, 0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x3c,0x2, 0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x3c,0x2, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x3c,0x2, 0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x3c,0x2, 0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x3c,0x3c,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x3c,0x3c,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x3c,0x3c,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x3c,0x3c,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x3c,0x3c,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x3c,0x3c,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3c,0x2d,0x79,0x30, +0x0, 0xe, 0xc2,0x1b,0xe4,0x7a,0xb3,0x3c,0x28,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x3b,0xfa,0x1b,0x1a,0x10,0x7e,0xf, 0x3b,0xfa,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x3c, +0x2d,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x3c, +0x2d,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x3c,0x3c,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x3c,0x3c,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x3c,0x3c,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x3c,0x3c,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x3c,0x3c,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x3c, +0x3c,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x3c,0x3c,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1c,0x7e,0xf, 0x3c,0x3c,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x3c,0x3c,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x17,0x85,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x17,0x18,0x7d,0x1e,0x12,0x17,0x32,0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x3c,0x2, 0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1b,0x7e,0xf, 0x3c,0x2d,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x3c,0x28,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x3c,0x2d,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x72,0x8e,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x3b,0xfa,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x3b,0xfa,0x1b,0x1a,0x10,0x7e,0xf, 0x3c,0x2, 0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xd, 0xe4,0x7a,0xb3,0x3c,0x12,0x7e,0x1f,0x3b,0xfa, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x3c,0x29,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x3c,0x29,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x3c,0x29,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x3c,0x2, 0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3c,0x2, 0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x3c,0x29,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x3c,0x29,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x3c,0x3c,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x3c,0x3c,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x19,0xe1,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x19,0xe2,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x3b,0xfa,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x3b,0xfa,0x1b,0x1a,0x10,0x7e, +0x1f,0x3b,0xfa,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x3c,0x2, 0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x3c,0x2d,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x3b,0xfa,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x3b,0xfa,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x3c, +0x2, 0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x3c,0x2, 0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x3c,0x2, 0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x3b,0xfa,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x2, 0x16,0x51,0x6e,0x0, 0x80,0x7c,0xb1,0x33,0x7c, +0xb0,0x33,0x68,0xd, 0x4, 0x68,0xef,0x7c,0xb5,0x33,0x7c,0xb4,0x33,0x78,0x3, 0x7f, +0x10,0x22,0x4, 0x68,0xe1,0x7d,0x50,0x92,0xf7,0x7d,0x45,0x7d,0x51,0xbf,0x21,0x40, +0x6, 0x7c,0x80,0x7f,0x1, 0x7f,0x12,0x12,0x16,0x14,0x7e,0xa1,0xd0,0x5c,0xb0,0x4, +0x78,0x3, 0x20,0xd5,0xc1,0x7c,0xb0,0x4, 0x78,0x7, 0x50,0x2, 0xb2,0xd5,0x2, 0x16, +0x59,0x92,0xd5,0xbe,0x80,0xff,0x68,0xf6,0x7c,0xb8,0x9c,0xb0,0x6c,0x0, 0x60,0x2a, +0xb4,0x18,0x5, 0x7c,0x41,0x2, 0x16,0x2d,0x50,0xfb,0x80,0x3, 0x2f,0x0, 0x4, 0x7c, +0x9b,0x5e,0x90,0x7, 0x78,0xf6,0x30,0xe4,0x6, 0x7c,0x43,0x7d,0x10,0x6d,0x0, 0x30, +0xe3,0x8, 0x7c,0x43,0x7c,0x32,0x7c,0x21,0xa, 0x0, 0x30,0xf5,0x19,0x9f,0x10,0x78, +0xe, 0x22,0x2, 0x16,0x56,0x1b,0x80,0x68,0xf9,0x2f,0x11,0x50,0x2, 0xb, 0x70,0x7c, +0xb5,0x30,0xe7,0xf1,0x80,0x1b,0x2d,0x31,0x7c,0xb5,0xa5,0x39,0x7c,0x5b,0x50,0x11, +0xb, 0x80,0x78,0x3, 0x2, 0x16,0x59,0x1e,0x34,0x13,0x50,0x3, 0x4e,0x60,0x80,0x1a, +0x2b,0x2, 0x16,0x2d,0x74,0xf8,0x6c,0xaa,0x6e,0x40,0x80,0x6e,0x0, 0x80,0xbe,0xb0, +0xff,0x68,0x27,0x7c,0x83,0x7c,0x97,0x5c,0x3b,0x5c,0x7b,0xbf,0x10,0x68,0x2a,0xf4, +0x40,0xd, 0x7c,0x38,0x2d,0x15,0xf4,0x5c,0x3b,0x50,0xf, 0xb, 0x4, 0x80,0xb, 0x7c, +0x79,0x2d,0x35,0xf4,0x5c,0x7b,0x50,0x2, 0xb, 0x24,0xbf,0x10,0x68,0xb, 0x7c,0xb0, +0x20,0xe7,0x6, 0x7c,0xb4,0x20,0xe7,0x1, 0xb3,0x22,0x7e,0xa0,0x20,0x80,0xc, 0x7e, +0xa0,0x10,0x80,0x5, 0x7e,0xa0,0x8, 0x6c,0x55,0x6d,0x33,0x33,0x92,0xd5,0x50,0xa, +0x6e,0x34,0xff,0xff,0x6e,0x24,0xff,0xff,0xb, 0x1c,0xa5,0xec,0x33,0x40,0x6, 0x2f, +0x11,0xd5,0xf0,0xf6,0x22,0x7c,0xba,0x24,0x7e,0xa2,0xd5,0x13,0x7c,0x76,0x7c,0x65, +0xa5,0xcc,0x92,0xe7,0x7c,0x5b,0x22,0x7c,0xb5,0x33,0x7c,0xb4,0x33,0x92,0xd5,0x4e, +0x50,0x80,0x24,0x81,0x40,0x3, 0x9f,0x11,0x22,0x7c,0x45,0x7c,0x56,0x7c,0x67,0x6c, +0x77,0x24,0xe0,0x50,0xe, 0x7e,0x1c,0xff,0xff,0x22,0x1e,0x34,0x1e,0x24,0x50,0x3, +0x4e,0x60,0x80,0x4, 0x78,0xf4,0x30,0xd5,0xa, 0x6e,0x34,0xff,0xff,0x6e,0x24,0xff, +0xff,0xb, 0x1c,0x22,0x7c,0xb5,0xa2,0xe7,0xd2,0xe7,0x7c,0x1b,0x7c,0xb4,0x33,0x40, +0x9, 0x68,0xd, 0xb4,0xff,0xb, 0xa5,0xbd,0xff,0x3, 0x2, 0x16,0x51,0x2, 0x16,0x59, +0x22,0x7c,0xb, 0x24,0x81,0xc2,0xe0,0xf5,0x82,0xf4,0x4, 0x2c,0xb0,0x7c,0x2b,0xc3, +0x13,0x7c,0x4b,0x7c,0xb5,0x92,0xe7,0x7c,0x5b,0x7f,0x41,0x7c,0xb6,0xa2,0xe7,0x7c, +0xb1,0xa5,0xba,0x7f,0x2, 0xc3,0x13,0x34,0x0, 0x94,0x0, 0x7c,0x2b,0x7e,0xa0,0x91, +0xa4,0x7c,0xba,0x13,0xf4,0x94,0xfe,0xac,0xb2,0x33,0x7c,0xba,0x33,0x24,0x8c,0xd3, +0x13,0x7c,0x5b,0xe4,0x92,0xe7,0x7c,0x6b,0x6c,0x77,0x7e,0x40,0x3f,0x75,0x83,0x2, +0x7f,0x51,0x7f,0x1, 0x7f,0x14,0x12,0x16,0x65,0x7f,0x5, 0x12,0x14,0xc, 0x9e,0x24, +0x0, 0x80,0xd5,0x83,0xeb,0x7e,0x1, 0x82,0x6c,0x11,0xe, 0x4, 0x1e,0x4, 0x2d,0x20, +0x5e,0x40,0x7f,0x22,0x2d,0x0, 0x92,0xd5,0xe, 0x10,0x4e,0x10,0x80,0x7d,0x42,0x2d, +0x44,0x50,0x2, 0xb2,0xd5,0x4e,0x50,0x80,0x6c,0x44,0x7c,0xb8,0x22,0x2c,0x44,0x50, +0x12,0xb, 0x1c,0x7e,0x40,0x0, 0x5e,0x50,0x7f,0xbe,0x18,0x0, 0x0, 0x78,0x4, 0xb, +0x80,0x68,0x16,0xa2,0xd5,0x7c,0xb8,0x13,0x7c,0x4b,0x7c,0xb5,0x92,0xe7,0x7c,0x5b, +0x22,0x7e,0x1c,0xff,0xff,0x22,0x9f,0x11,0x22,0x7e,0x24,0xff,0x80,0x20,0xd5,0x2, +0x6c,0x45,0x6d,0x33,0x22,0xbe,0x24,0xff,0xff,0x68,0x6, 0xbe,0x4, 0xff,0xff,0x78, +0x3, 0x2, 0x16,0x51,0x12,0x16,0x14,0x5c,0xb0,0x4, 0x68,0xf5,0x7c,0xb8,0xa5,0x48, +0x68,0xef,0x7c,0xb8,0x70,0x3, 0x9f,0x11,0x22,0xa5,0xb8,0x0, 0x3, 0x2, 0x16,0x59, +0x2e,0x0, 0x81,0x50,0x7, 0x9c,0x80,0x38,0x7, 0x2, 0x16,0x56,0x9c,0x80,0x50,0xed, +0xa, 0x51,0xc2,0xe7,0x4d,0x51,0x78,0x3, 0x2, 0x16,0x43,0x7e,0x54,0x0, 0x80,0x7e, +0x90,0x1a,0x6c,0x0, 0x80,0x6, 0x1b,0x90,0x68,0x14,0x2f,0x11,0xbf,0x10,0x40,0x4, +0x9f,0x10,0x4c,0xab,0x3, 0x30,0xe7,0xee,0xca,0xa8,0x6c,0xaa,0x80,0xe8,0xda,0x39, +0xda,0x58,0x7c,0x4a,0xbe,0x50,0x80,0x50,0xa, 0x1b,0x80,0x68,0xbc,0x2f,0x11,0x50, +0x2, 0xb, 0x70,0x2, 0x16,0x2d,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, 0xb2,0xd5,0x6e, +0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e,0x34,0xff,0xff, +0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d,0x32,0x30,0xd5, +0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d,0x2, 0x7d,0x21, +0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31,0xad,0x10,0x2d, +0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78,0x27,0x8d,0x31, +0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11,0x2d,0x44,0x50, +0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78,0xed,0x7f,0x1, +0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, 0x2f,0x0, 0x40, +0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d,0x23,0x7d,0x31, +0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2,0xd5,0x9f,0x22, +0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22,0x9f,0x21,0x7f, +0x12,0x12,0x17,0x34,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12,0x17,0x34,0x30, +0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1a,0x1e, +0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1e, +0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, 0x1c,0xb, 0x14, +0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x22,0x0, +0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, +0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, +0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x0, +0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15, +0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e,0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, +0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, +0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21, +0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, +0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, +0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21, +0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10,0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c, +0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c,0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, +0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, 0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, +0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10,0x19,0x13,0x1c,0x10,0x14,0x1a,0x10, +0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15,0x73,0x23,0x1c,0x74,0x23,0x1c,0x75, +0xe, 0x1c,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x3c,0x40,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0xc2,0xe, 0x75,0x1b,0x0, 0x75,0x1c,0x0, 0xc2,0xf, 0xc2, +0x10,0xc2,0x12,0x75,0x1d,0x0, 0x75,0x1e,0x0, 0xc2,0x14,0xc2,0x15,0x75,0x1f,0x0, +0xc2,0x16,0x75,0x68,0x0, 0xc2,0x17,0xc2,0x18,0xc2,0xa, 0x75,0x69,0x64,0xc2,0x19, +0xc2,0x1a,0x75,0x6a,0x0, 0xd2,0x5, 0xd2,0x6, 0xd2,0x7, 0xd2,0x1b,0xc2,0xc, 0xd2, +0xd, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x1a,0x72,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a, +0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0, +0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80,0xdf,0x2, 0x27,0xfe,0x0, 0x0, 0x0, +0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd,0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, +0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, 0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, +0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, 0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, +0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94,0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55, +0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31,0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c, +0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11,0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80, +0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, 0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d, +0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d,0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22, +0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44,0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78, +0xf5,0x22,0x3c,0x1, 0x32,0x1, 0x1e,0x2, 0xf6,0x4, 0xe7,0x5, 0xce,0x6, 0xc2,0x7, +0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff,0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, +0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, 0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d, +0x32,0x22,0x0, 0x4, 0x37,0xf2,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xff,0x1, 0x0, +0x1, 0x24,0xca,0x1, 0x0, 0x1, 0x3a,0xf0,0x0, 0x0, 0x2, 0x3b,0x42,0x0, 0x0, 0x0, +0x2, 0x3b,0x44,0x0, 0x0, 0x0, 0x1, 0x3b,0x46,0x0, 0x0, 0x1, 0x3a,0x7f,0xff,0x0, +0x1, 0x3b,0xd0,0x0, 0x0, 0x1, 0x3b,0xd1,0x0, 0x0, 0x1, 0x33,0xff,0x0, 0x0, 0x2, +0x32,0x67,0x0, 0x0, 0x0, 0x1, 0x32,0x96,0x0, 0x0, 0x1, 0x33,0x73,0x0, 0x0, 0x1, +0x33,0x74,0x0, 0x0, 0x1, 0x33,0x75,0x0, 0x0, 0x1, 0x38,0xfa,0x0, 0x0, 0x3c,0x39, +0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x39, +0x7f,0xff,0x0, 0x2, 0x39,0x80,0x0, 0x0, 0x0, 0x2, 0x39,0x82,0x0, 0x0, 0x0, 0x1, +0x39,0xfd,0x1, 0x0, 0x2, 0x3a,0x0, 0x0, 0x0, 0x0, 0x1, 0x34,0x88,0x0, 0x0, 0x1, +0x34,0x89,0x0, 0x0, 0x1, 0x34,0x8a,0x0, 0x0, 0x1, 0x3a,0x4, 0x1, 0x0, 0x1, 0x3a, +0x7e,0x0, 0x0, 0x1, 0x34,0x4f,0x0, 0x0, 0x6, 0x33,0xf9,0x30,0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x3c,0x37,0x0, 0x0, 0x1, 0x3c,0x38,0x0, 0x0, 0x1, 0x3c,0x39,0x0, +0x0, 0x1, 0x3c,0x3a,0x0, 0x0, 0x1, 0x3c,0x3b,0x0, 0x0, 0x1, 0x0, 0x6b,0x0, 0x0, +0x1, 0x2, 0xdc,0x0, 0x0, 0x1, 0x2, 0xdf,0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, +0x4, 0x33,0x9e,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3c,0x31,0x0, 0x0, 0x1, 0x3c,0x32, +0x0, 0x0, 0x2, 0x3c,0x33,0x0, 0x0, 0x0, 0x1, 0x3c,0x35,0x64,0x0, 0x1, 0x3c,0x36, +0x0, 0x0, 0x1, 0x3c,0x40,0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, +0x0, 0x1, 0x3, 0xf2,0x0, 0x0, 0x2, 0x2a,0x97,0x2a,0x9d,0x0, 0x1, 0x2e,0x5d,0x2, +0x0, 0x1, 0x2e,0x86,0x0, 0x0, 0x4, 0x3c,0x29,0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x3c, +0x2d,0x0, 0x0, 0x64,0x0, 0x0, 0x4, 0x3b,0xfa,0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x3b, +0xfe,0x0, 0x0, 0x68,0xc0,0x0, 0x4, 0x3c,0x2, 0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x3c, +0x13,0x0, 0x0, 0x40,0x0, 0x0, 0x4, 0x3c,0x3c,0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x4, +0xe2,0x0, 0xc, 0x3, 0x52,0x3, 0xe8,0x0, 0xc, 0x2, 0x94,0x3, 0x6b,0x0, 0xc, 0x1, +0xf4,0x2, 0x71,0x0, 0xa, 0x1, 0x77,0x1, 0x77,0x0, 0x8, 0x0, 0xdc,0x0, 0xb4,0x0, +0x6, 0x0, 0x4b,0x0, 0x64,0x0, 0x6, 0x0, 0x0, 0x0, 0xe, 0x1c,0x23,0x3, 0xe8,0x0, +0x78,0x2, 0x58,0x0, 0x50,0x0, 0x0, 0x0, 0x1e,0x12,0x36,0xcb,0x12,0x1c,0xb9,0x12, +0x1c,0x84,0x12,0x1d,0x5e,0x2, 0x1c,0x48,0x12,0x1c,0x59,0x7e,0xb3,0x29,0xfc,0x12, +0x46,0xf3,0x74,0x1, 0x7a,0xb3,0x3a,0x8, 0x22,0x12,0xae,0xea,0x74,0x1, 0x7a,0xb3, +0x3a,0x4, 0x22,0x12,0x1c,0xf0,0x12,0x3f,0x95,0x12,0x28,0x20,0x12,0x36,0xcb,0x12, +0x1c,0xf0,0x12,0x1c,0xb9,0x12,0x48,0x53,0x12,0x1c,0x84,0x12,0x1d,0x5e,0x12,0x1d, +0x8e,0x2, 0x1c,0x48,0x12,0x28,0x69,0x12,0x1c,0xd6,0x2, 0x1c,0x8d,0x7e,0x34,0x0, +0x3, 0x6d,0x22,0x2, 0x1c,0x96,0x7d,0x43,0x7e,0xa3,0x34,0x38,0xbe,0xa0,0x5, 0x50, +0x16,0x7e,0x70,0x4, 0xac,0x7a,0x59,0x43,0x34,0x3b,0x59,0x23,0x34,0x3d,0x7c,0xba, +0x4, 0x7a,0xb3,0x34,0x38,0xc3,0x22,0xd3,0x22,0x12,0x88,0x3, 0x12,0x6b,0xa5,0x2, +0x1c,0xc2,0x30,0x12,0x10,0x12,0xb0,0x17,0x50,0x3, 0x12,0x46,0x55,0x12,0x6b,0x21, +0x12,0xad,0x31,0xc2,0x12,0x22,0x6d,0x33,0x7e,0x24,0x6, 0x48,0x12,0x1c,0x96,0x7e, +0x34,0x0, 0x1, 0x7e,0x24,0x6, 0xa8,0x2, 0x1c,0x96,0x74,0x1, 0x7a,0xb3,0x3a,0xf5, +0x7e,0x34,0xd, 0xac,0x6d,0x22,0x7a,0x27,0x3c,0x17,0x7a,0x37,0x3c,0x19,0x22,0xca, +0xf8,0x7e,0xf3,0x3a,0xf5,0xbe,0xf0,0x5, 0x78,0xb, 0x74,0x1, 0x7a,0xb3,0x3a,0xf5, +0x12,0x0, 0xa, 0x80,0x40,0xbe,0xf0,0x4, 0x78,0xd, 0x12,0x1c,0xea,0xe4,0x7a,0xb3, +0x29,0xef,0x12,0x88,0x3, 0x80,0x2e,0xbe,0xf0,0x6, 0x78,0x13,0x12,0x1c,0xea,0x12, +0x44,0xa1,0xe4,0x7a,0xb3,0x2a,0xb, 0x12,0x6b,0xa5,0x12,0xcf,0x50,0x80,0x16,0xbe, +0xf0,0x7, 0x78,0x17,0x12,0x1c,0xea,0x12,0x77,0xdb,0x50,0xfb,0x12,0x6b,0xcb,0x12, +0x1c,0xc2,0x12,0x1d,0x5e,0x74,0x2, 0x7a,0xb3,0x3a,0xf5,0xda,0xf8,0x22,0xe4,0x7a, +0xb3,0x34,0x3a,0x7a,0xb3,0x34,0x39,0x12,0x72,0x41,0xb4,0x1, 0x4, 0x74,0x1, 0x80, +0x2, 0x74,0x3, 0x7a,0xb3,0x34,0x3a,0x22,0x12,0x48,0x53,0x12,0xce,0xb8,0x7a,0x37, +0x3c,0x33,0x12,0x1c,0xf0,0x12,0x1c,0xb9,0x12,0x1d,0x5e,0x2, 0x1d,0x8e,0x74,0xc, +0x7a,0xb3,0x32,0x3d,0xe4,0x7a,0xb3,0x32,0x3e,0x7e,0x8, 0x32,0x3f,0x74,0xc, 0x12, +0x1e,0xb6,0x7e,0x8, 0x32,0x49,0x12,0xce,0xf8,0x7e,0x8, 0x32,0x69,0x12,0x1e,0xb6, +0x6d,0x33,0x7a,0x37,0x32,0x80,0x22,0xca,0x3b,0x12,0x77,0xdb,0x50,0xfb,0x7e,0xf3, +0x29,0xfc,0x7c,0xbf,0x12,0xaa,0x86,0x12,0xab,0x6d,0x7e,0xb3,0x2a,0xc, 0xf5,0x28, +0x7e,0xc3,0x2a,0xd, 0x7e,0xb3,0x3a,0xa7,0xb4,0x1, 0xf, 0x12,0x45,0x9f,0x7e,0xb3, +0x15,0xa1,0x70,0x6, 0x12,0x1d,0x5e,0xc3,0xc1,0xb3,0x12,0x1e,0xbd,0x3e,0x34,0xca, +0x39,0x7e,0x18,0x6, 0x48,0x7e,0x8, 0x4, 0x60,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x1e, +0xbd,0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0xa8,0x7e,0x8, 0x4, 0x0, 0x12,0x1a,0xb, +0x1b,0xfd,0x7e,0xb3,0x3a,0xa7,0xb4,0x3, 0x7, 0x12,0x7e,0x3b,0x7a,0x37,0x3b,0x38, +0x74,0x1, 0x7a,0xb3,0x15,0xa0,0x12,0x1c,0xb9,0x12,0x7e,0xab,0x12,0x41,0xd3,0xe4, +0x12,0x13,0xde,0x12,0x1d,0x5e,0x7e,0x8, 0x4, 0x60,0x7a,0xd, 0x29,0x7e,0x18,0x5, +0xe0,0x7e,0xb3,0x2a,0x5f,0x12,0x88,0xee,0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29,0x7e, +0x18,0x5, 0x80,0x7e,0xb3,0x24,0xc4,0x12,0x88,0xee,0x7e,0xd3,0x2a,0xc, 0x7e,0xe3, +0x2a,0xd, 0xe5,0x28,0x7a,0xb3,0x2a,0xc, 0x7a,0xc3,0x2a,0xd, 0x7e,0x34,0x7, 0x1a, +0x7e,0x4, 0xc, 0xd8,0x7d,0x20,0x7d,0x10,0x12,0x77,0xec,0x7a,0xd3,0x2a,0xc, 0x7a, +0xe3,0x2a,0xd, 0x7c,0xbf,0x12,0xaa,0x26,0x12,0xa4,0xcb,0x7e,0xb3,0x3c,0x36,0x4, +0x7a,0xb3,0x3c,0x36,0x7e,0x73,0x3c,0x36,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64,0x7a, +0xb3,0x3c,0x36,0x7e,0xb3,0x15,0xa0,0x60,0x9, 0x7e,0xb3,0x15,0xa1,0x60,0x3, 0xd3, +0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e,0x34,0x0, 0xa, 0x2, 0x1a,0x30,0x7e,0x73,0x29, +0x61,0xa, 0x27,0x7e,0x73,0x29,0x60,0xa, 0x37,0x2d,0x32,0x22,0x12,0x48,0x8, 0x7e, +0xb3,0x3a,0xa7,0xb4,0x3, 0x66,0x12,0xc7,0x49,0x12,0x3c,0x94,0x12,0x3f,0xfe,0x7e, +0xb3,0x3a,0xf1,0x30,0xe7,0xe9,0x12,0x1d,0xb7,0x12,0x1e,0xbd,0x3e,0x34,0xca,0x39, +0x7e,0x18,0x4, 0x0, 0x7e,0x8, 0x4, 0xc0,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x1e,0xbd, +0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x60,0x7e,0x8, 0x5, 0x20,0x12,0x1a,0xb, 0x1b, +0xfd,0x7e,0xb3,0x2a,0xa, 0xb4,0x1, 0x12,0x12,0x65,0xff,0x12,0x59,0xa2,0x12,0x6c, +0x1b,0x12,0x97,0x8, 0x12,0x1f,0x4c,0x12,0x48,0xc1,0x12,0x48,0x5e,0x12,0xb0,0xa8, +0x7e,0xb3,0x3a,0xf1,0x54,0x7f,0x7a,0xb3,0x3a,0xf1,0x80,0x93,0x12,0x77,0xe6,0x2, +0x1f,0x42,0x7e,0xb3,0x3a,0xee,0x70,0x3, 0x12,0xa5,0xdf,0x22,0x12,0xa1,0x68,0x12, +0x5e,0x1b,0x12,0x21,0x65,0x12,0x87,0x52,0x12,0x5e,0x1b,0x12,0xba,0xb1,0x12,0x5e, +0x1b,0x12,0x27,0x6e,0x12,0x5e,0x1b,0x12,0x91,0x3d,0x12,0x5e,0x1b,0x12,0x55,0x2e, +0x12,0xa3,0x3e,0x12,0xa0,0x5a,0x12,0x9f,0xc2,0x12,0x5e,0x1b,0x12,0x86,0x51,0x12, +0x5e,0x1b,0x2, 0x1f,0x85,0xca,0x3b,0x75,0x24,0x0, 0x6c,0xcc,0x6c,0xdd,0x7e,0xc4, +0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x39,0x43,0x7e,0x8, 0x39,0x7, 0x12,0x1a,0xb, 0x1b, +0xfd,0x7e,0xf3,0x27,0x58,0xa, 0xcf,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x25,0xce,0x7e, +0x8, 0x1e,0x44,0x12,0x1a,0xb, 0x1b,0xfd,0x6c,0x88,0x6c,0xee,0x2, 0x20,0x5a,0x7e, +0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99,0x80,0x4c,0x74,0x2, 0xac,0xb9,0x9, 0xb5, +0x1e,0x44,0xbe,0xb0,0xff,0x68,0x3d,0x7c,0xb9,0x12,0x5e,0xc, 0x60,0x36,0x74,0x2, +0xac,0xb9,0x9, 0x75,0x1e,0x45,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x39,0x44, +0x12,0x27,0xf7,0x7d,0x13,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1e,0x44,0xa, 0x27,0x74, +0x2, 0xac,0xbe,0x9, 0x75,0x39,0x43,0x12,0x27,0xf7,0x2d,0x13,0xbd,0xc1,0x28,0x4, +0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9,0x38,0xb0,0xbe,0xc0,0xff,0x68,0x39,0x7e, +0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x1e,0x44,0x9, 0x73,0x1e,0x45,0x12,0x21,0x5e,0xbe, +0x37,0x29,0x47,0x48,0x23,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0x53,0x1e,0x44,0x74,0x2, +0xac,0xbd,0x19,0x55,0x1e,0x80,0x9, 0x53,0x1e,0x45,0x19,0x55,0x1e,0x81,0x74,0xff, +0x19,0xb3,0x1e,0x44,0xb, 0x80,0xb, 0xd0,0xb, 0xe0,0x7e,0x73,0x38,0xf9,0xbc,0x7e, +0x28,0x3, 0x2, 0x1f,0xbf,0x7c,0xe8,0x80,0x6d,0x6d,0xdd,0x7e,0x80,0xff,0x6c,0x99, +0x80,0x3c,0x7c,0xb9,0x12,0x5e,0xc, 0x60,0x33,0x12,0xce,0xda,0xbe,0xb0,0xff,0x68, +0x2b,0x9, 0x73,0x1e,0x45,0x12,0x27,0x58,0x7f,0x71,0xb, 0x7a,0x50,0xbe,0x54,0x0, +0x0, 0x58,0x5, 0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0,0xbd,0xcd,0x8, 0xd, 0x12, +0xce,0xda,0xf5,0x24,0x9, 0xc3,0x1e,0x45,0x7d,0xdc,0x7c,0x89,0xb, 0x90,0xbc,0xf9, +0x38,0xc0,0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74,0x2, 0xac,0xbd,0x19,0x75, +0x1e,0x80,0x19,0xc5,0x1e,0x81,0x7e,0xa0,0xff,0x7e,0x70,0x2, 0xac,0x78,0x19,0xa3, +0x1e,0x44,0xb, 0xd0,0xb, 0xe0,0xbe,0xe0,0xa, 0x40,0x8e,0x90,0x60,0x9a,0xe4,0x93, +0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x1e,0x80,0x7e,0x8, 0x1e,0x44,0x12, +0x1a,0xb, 0x1b,0xfd,0x7c,0xfd,0x7e,0x8, 0x39,0x43,0x7e,0x34,0x0, 0x14,0x74,0xff, +0x12,0x1a,0x30,0xbe,0xf0,0x0, 0x28,0x38,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18, +0x1e,0x44,0x7e,0x8, 0x25,0xce,0x12,0x1a,0xb, 0x1b,0xfd,0xa, 0x3f,0x3e,0x34,0xca, +0x39,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0x39,0x43,0x12,0x1a,0xb, 0x1b,0xfd,0x6c,0xee, +0x80,0xa, 0x7c,0xbe,0x7e,0x70,0x1, 0x12,0x5f,0x5a,0xb, 0xe0,0xbc,0xfe,0x38,0xf2, +0x7a,0xf3,0x38,0xf9,0x7a,0xf3,0x27,0x58,0x7e,0x73,0x27,0x58,0xbe,0x70,0xa, 0x28, +0x6, 0x74,0xa, 0x7a,0xb3,0x27,0x58,0xda,0x3b,0x22,0x7c,0xb9,0x7c,0x78,0x12,0x27, +0x58,0xb, 0x1a,0x30,0x22,0xca,0x79,0x75,0x25,0x0, 0x7e,0xb3,0x27,0x58,0x70,0x7, +0xe4,0x7a,0xb3,0x38,0xfa,0x41,0x75,0x75,0x24,0xff,0x7e,0xe0,0xff,0x6c,0xff,0x6c, +0x88,0x6c,0x99,0x80,0x39,0x6c,0xaa,0x80,0x2b,0x7c,0xb9,0x7c,0x7a,0x12,0x21,0x5e, +0xbe,0x34,0x0, 0xc8,0x8, 0x1c,0x5, 0x25,0xbc,0x9e,0x50,0x2, 0x7c,0xe9,0xbe,0xa1, +0x24,0x50,0x3, 0x7a,0xa1,0x24,0xbc,0x98,0x28,0x2, 0x7c,0x89,0xbc,0xaf,0x28,0x2, +0x7c,0xfa,0xb, 0xa0,0x7e,0xb3,0x29,0x5d,0xbc,0xba,0x38,0xcd,0xb, 0x90,0x7e,0xb3, +0x29,0x5c,0xbc,0xb9,0x38,0xbf,0xa, 0x2e,0xa, 0x38,0x9d,0x32,0x7c,0x67,0xe5,0x24, +0xa, 0x2b,0xa, 0x5f,0x9d,0x52,0x7c,0x7b,0x7e,0x27,0x27,0x5e,0xbe,0x24,0x2, 0xbc, +0x58,0x6e,0xbe,0x24,0x1, 0x2c,0x8, 0x68,0xbe,0x60,0x6, 0x40,0x63,0xbe,0x60,0x7, +0x38,0x5e,0xbe,0x70,0x6, 0x40,0x59,0xbe,0x70,0x7, 0x38,0x54,0x7c,0xbe,0x7e,0x71, +0x24,0x12,0x24,0x2f,0x58,0x4a,0x7c,0xb8,0x7e,0x71,0x24,0x12,0x24,0x2f,0x58,0x40, +0x7c,0xbe,0x12,0x24,0x2d,0x58,0x39,0x7c,0xb8,0x12,0x24,0x2d,0x58,0x32,0xa, 0x28, +0xa, 0x3e,0x2d,0x32,0x7e,0x14,0x0, 0x2, 0x7d,0x21,0x12,0x16,0xe6,0x7c,0xb7,0xca, +0xb8,0xa, 0x2f,0xe5,0x24,0xa, 0x3b,0x2d,0x32,0x7d,0x21,0x12,0x16,0xe6,0xda,0xb8, +0x12,0x24,0x2f,0x58,0xb, 0xe5,0x25,0xbe,0xb0,0xe, 0x40,0x4, 0x74,0x64,0x80,0xa, +0x7e,0xb3,0x38,0xfa,0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x38,0xfa,0x7e,0xb3, +0x38,0xfa,0x60,0x11,0x6c,0x99,0x80,0x5, 0x12,0x5f,0xf3,0xb, 0x90,0x7e,0x73,0x27, +0x58,0xbc,0x79,0x38,0xf3,0xda,0x79,0x22,0xca,0x79,0x7c,0xa6,0x7c,0x67,0x7c,0x7b, +0x7e,0xe0,0xff,0x75,0x3f,0xff,0xc2,0x0, 0xc2,0x1, 0xc2,0x2, 0xc2,0x3, 0xc2,0x4, +0x7e,0xe4,0x1, 0x2c,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x6, 0x12,0xc5,0x3e,0xc3,0x81, +0x2a,0xbe,0xa0,0x0, 0x40,0x5, 0xbe,0xa0,0xa, 0x28,0x3, 0xc3,0x81,0x2a,0x7e,0x30, +0x3, 0x7e,0x50,0x5, 0xac,0x5a,0x19,0x32,0x32,0xe, 0x7d,0xfe,0x12,0xc5,0x82,0x28, +0x4, 0x19,0xb2,0x32,0xe, 0x12,0xc5,0x8a,0x7a,0x71,0x39,0x7c,0xf6,0xc2,0x2, 0xc2, +0x3, 0x7c,0x87,0x85,0x39,0x3a,0x80,0xa, 0x12,0x27,0x39,0xbd,0x3f,0x8, 0x8, 0x7a, +0x81,0x3a,0x12,0x27,0xe5,0x58,0xf1,0x7e,0x81,0x39,0x85,0x39,0x3b,0x80,0xa, 0x12, +0x27,0x39,0xbd,0x3f,0x8, 0x8, 0x7a,0x81,0x3b,0x12,0xce,0xe, 0x48,0xf1,0x75,0x3e, +0x0, 0x7e,0x73,0x29,0x5c,0x7c,0xb7,0x14,0xbe,0xb1,0x3b,0x78,0xc, 0xd2,0x3, 0xa, +0xe7,0x1b,0xe4,0x7d,0x3e,0x7c,0xe7,0x80,0x8, 0xe5,0x3a,0x70,0x4, 0xd2,0x2, 0x6c, +0xee,0x7c,0x9f,0x7a,0xf1,0x3c,0x20,0x3, 0xf, 0x30,0x2, 0x37,0x80,0xa, 0x7c,0xbe, +0x12,0x27,0x12,0x8, 0x8, 0x7a,0x91,0x3c,0x12,0x27,0xee,0x58,0xf1,0x7c,0x9f,0x7a, +0xf1,0x3d,0x80,0xa, 0x7c,0xbe,0x12,0x27,0x12,0x8, 0x8, 0x7a,0x91,0x3d,0x12,0xce, +0x1e,0x48,0xf1,0xe5,0x3c,0xa, 0x3b,0xe5,0x3d,0xa, 0xeb,0x9d,0xe3,0x7d,0x3e,0x7c, +0xb7,0xf5,0x3e,0xc2,0x0, 0xc2,0x1, 0x7c,0x9f,0x7a,0xf1,0x3c,0x80,0x8, 0x12,0x27, +0x10,0x8, 0x8, 0x7a,0x91,0x3c,0x12,0x27,0xee,0x58,0xf3,0x7c,0x9f,0x7a,0xf1,0x3d, +0x80,0x8, 0x12,0x27,0x10,0x8, 0x8, 0x7a,0x91,0x3d,0x12,0xce,0x1e,0x48,0xf3,0x75, +0x40,0x0, 0xe5,0x3c,0x70,0x6, 0xd2,0x0, 0xf5,0x3f,0x80,0x18,0x7e,0x73,0x29,0x5d, +0x7c,0xb7,0x14,0xbe,0xb1,0x3d,0x78,0xc, 0xd2,0x1, 0xa, 0xe7,0x1b,0xe4,0x7d,0x3e, +0x7c,0xb7,0xf5,0x3f,0x7e,0x81,0x39,0x85,0x39,0x3a,0x20,0x0, 0xd, 0x30,0x1, 0x32, +0x80,0x8, 0x12,0x27,0x49,0x8, 0x8, 0x7a,0x81,0x3a,0x12,0x27,0xe5,0x58,0xf3,0x7e, +0x81,0x39,0x85,0x39,0x3b,0x80,0x8, 0x12,0x27,0x49,0x8, 0x8, 0x7a,0x81,0x3b,0x12, +0xce,0xe, 0x48,0xf3,0xe5,0x3a,0xa, 0x2b,0xe5,0x3b,0xa, 0x3b,0x9d,0x32,0x7c,0xb7, +0xf5,0x40,0x7e,0x70,0x5, 0xac,0x7a,0x9, 0xb3,0x32,0xe, 0xbe,0xb1,0x3e,0x40,0x19, +0xbe,0xb1,0x40,0x50,0x2, 0x80,0x12,0x9, 0xb3,0x32,0xd, 0x60,0x16,0x20,0x3, 0x9, +0x20,0x2, 0x6, 0x20,0x0, 0x3, 0x30,0x1, 0xa, 0x74,0x1, 0x19,0xb3,0x32,0xd, 0xd2, +0x4, 0x80,0x5, 0xe4,0x19,0xb3,0x32,0xd, 0xa2,0x4, 0xda,0x79,0x22,0x7c,0x7f,0x12, +0x21,0x5e,0xbe,0x34,0x0, 0x0, 0x22,0xca,0x3b,0x6d,0xee,0x7e,0xc3,0x29,0x5b,0x7e, +0xd3,0x29,0x5a,0x7e,0xb3,0x3a,0xd0,0xb4,0x1, 0x3, 0xe4,0xa1,0x60,0x7e,0xb3,0x27, +0x58,0x70,0x2, 0x81,0xd4,0x7e,0xb3,0x28,0xf5,0x60,0x2, 0x80,0x77,0x7e,0xa3,0x25, +0xce,0x7e,0x73,0x25,0xcf,0x7a,0x71,0x24,0x6c,0xee,0x6d,0xff,0x6c,0xff,0xa, 0x47, +0x80,0x1c,0x12,0x27,0x2d,0x8, 0x1d,0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba, +0x14,0x12,0x27,0x1d,0x12,0x27,0x40,0x58,0x3, 0x12,0x27,0x1a,0x1b,0x44,0xbe,0x44, +0x0, 0x0, 0x58,0xde,0xe5,0x24,0xa, 0x4b,0x80,0x1a,0x12,0x27,0x2d,0x8, 0x21,0xb, +0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x27,0x1d,0x12,0x27,0x40,0x58, +0x3, 0x12,0x27,0x1a,0x7d,0x24,0xb, 0x24,0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48,0xda, +0xbe,0xe0,0x2, 0x50,0x2, 0x80,0xd, 0xa, 0x2f,0x7d,0x3f,0x12,0x16,0xe6,0xbe,0x34, +0x0, 0x3c,0x8, 0x7, 0xe4,0x7a,0xb3,0x33,0x74,0xa1,0x60,0x6d,0xdd,0xbe,0xa0,0x0, +0x28,0x8, 0x7c,0xba,0x14,0x12,0x27,0x27,0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, 0xca, +0xbd,0xc3,0x58,0x8, 0x7c,0xba,0x4, 0x12,0x27,0x27,0x2d,0xd3,0x7e,0x70,0x8, 0x80, +0x25,0x7e,0x50,0x2, 0xac,0x57,0x7d,0xc2,0x2e,0xc4,0x1a,0x42,0x7d,0x1c,0x12,0xcf, +0x0, 0x1a,0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x1a,0x43,0x7d,0x2c,0x12, +0x71,0x43,0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xd3,0x7c,0xba, +0x12,0x27,0x27,0x12,0x1a,0x62,0xbe,0x34,0x7, 0xd0,0x8, 0x4, 0x2e,0xe4,0x0, 0x28, +0xbe,0xe4,0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x33,0x74,0xa, 0x3b, +0xbd,0x3e,0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x33,0x74,0x7e,0xb3,0x33,0x74, +0xda,0x3b,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70,0x7c,0xe7,0x7c, +0xdb,0x7e,0xc0,0x4, 0x7e,0xb3,0x29,0x5a,0xf5,0x27,0x7e,0xb3,0x29,0x5b,0xf5,0x26, +0x7e,0xd4,0x0, 0x78,0x6c,0xff,0x12,0x27,0x54,0x7f,0x1, 0x7e,0xc7,0x27,0x5e,0xbe, +0xc4,0x5, 0xdc,0x8, 0x6, 0x2e,0xd4,0x0, 0xc8,0x80,0x22,0xbe,0xc4,0x4, 0xb0,0x8, +0x6, 0x2e,0xd4,0x0, 0x96,0x80,0x16,0xbe,0xc4,0x3, 0x84,0x8, 0x6, 0x2e,0xd4,0x0, +0x64,0x80,0xa, 0xbe,0xc4,0x2, 0x58,0x8, 0x4, 0x2e,0xd4,0x0, 0x32,0xe5,0x27,0x12, +0x9d,0x5c,0x58,0xf, 0xe5,0x26,0x12,0xcf,0x36,0x58,0x8, 0x4c,0xee,0x68,0x4, 0x4c, +0xdd,0x78,0x3, 0x4e,0xf0,0x10,0xb, 0xa, 0x20,0xbd,0x2d,0x8, 0x8, 0xbe,0xc4,0x3, +0x20,0x8, 0x2, 0xc1,0xcf,0x7d,0x3d,0xe, 0x34,0xbd,0x23,0x8, 0x8, 0xbe,0xc4,0x3, +0x20,0x58,0x2, 0xc1,0xcf,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, +0x48,0x11,0x7e,0xb3,0x29,0x5a,0xbc,0xb8,0x8, 0x9, 0x12,0x27,0x6, 0x58,0x14,0xb, +0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8,0xbd, +0xc3,0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0xc1,0xcf,0x6c,0xaa,0x7c,0x8d, +0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x29,0x5a,0xbc,0xb8,0x8, +0x9, 0x12,0x27,0x6, 0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a,0x2c, +0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0, +0x2, 0x80,0x6c,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11, +0x7e,0xb3,0x29,0x5b,0xbc,0xb9,0x8, 0x9, 0x12,0x27,0x6, 0x58,0x14,0xb, 0xa0,0x80, +0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3,0x18, +0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x35,0x6c,0xaa,0x7c,0x9e,0x80,0x1c, +0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x29,0x5b,0xbc,0xb9,0x8, 0x9, 0x12, +0x27,0x6, 0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a,0x3e, +0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, 0x4c, +0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7,0x0, +0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe,0x40, +0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7,0x0, +0x3, 0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x12,0x21,0x5e,0xbd,0x3d,0x22, +0xe5,0x39,0x7c,0x79,0x12,0x21,0x5e,0xbd,0x3f,0x22,0x7c,0xba,0x4, 0x7c,0x79,0x12, +0x21,0x5e,0x2d,0xf3,0xb, 0xf0,0x22,0x7e,0x71,0x24,0x2, 0x21,0x5e,0x7c,0xba,0x7c, +0x79,0x12,0x21,0x5e,0xbe,0x34,0x0, 0x64,0x22,0x7c,0xb8,0x7c,0x7f,0x2, 0x21,0x5e, +0xa, 0x2d,0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0x7c,0xb8,0x7e,0x71,0x3f,0x12,0x21, +0x5e,0xbd,0x3f,0x22,0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x29,0x5b,0xac,0x1b,0x3e,0x4, +0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10,0x7e,0x1f,0x12,0x9a,0x2d,0x31,0x22,0xca,0xd8, +0xca,0x79,0x7e,0xf7,0x29,0x49,0x6c,0xff,0x80,0x1b,0x7c,0xbf,0x12,0x5e,0xc, 0x60, +0x12,0x12,0xce,0x52,0x7c,0xbe,0x7c,0x7d,0x12,0x21,0x5e,0x7d,0xe3,0xbd,0x4e,0x58, +0x2, 0x7d,0x4e,0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x38,0xdd,0xbe,0x70,0x2, +0x40,0x36,0x6c,0xff,0x80,0x26,0x12,0xce,0x52,0x12,0xa1,0x58,0xbc,0xbe,0x78,0x1a, +0x4c,0xdd,0x78,0x16,0x7c,0xbe,0x7c,0x7d,0x12,0x27,0xdd,0x58,0xd, 0x7e,0x57,0x27, +0x5e,0xbe,0x54,0x3, 0x20,0x8, 0x3, 0x12,0xa2,0x5e,0xb, 0xf0,0x7e,0x73,0x27,0x58, +0xbc,0x7f,0x38,0xd2,0x7a,0xf7,0x29,0x49,0xda,0x79,0xda,0xd8,0x22,0x12,0x21,0x5e, +0xbe,0x34,0x1, 0x2c,0x22,0x7c,0xb8,0x14,0x7c,0x8b,0xbe,0xb0,0x0, 0x22,0x7c,0xb9, +0x14,0x7c,0x9b,0xbe,0xb0,0x0, 0x22,0xa, 0x37,0x9d,0x32,0x2, 0x1a,0x62,0x12,0x3f, +0x95,0x12,0x68,0x4d,0x12,0x28,0x20,0x12,0x1c,0x39,0x7e,0xb3,0x3a,0xa7,0x24,0xfd, +0x68,0x9, 0xb, 0xb1,0x78,0xf4,0x12,0x2d,0x73,0x80,0xef,0x12,0x1e,0xcc,0x80,0xea, +0x12,0x63,0x13,0x12,0x42,0xab,0x12,0x0, 0x42,0x12,0xce,0x2e,0x7e,0x18,0x4, 0x0, +0x7a,0x1f,0x6, 0x44,0x7e,0xf, 0x6, 0x44,0x7e,0x1f,0x6, 0x40,0x12,0x6f,0x86,0x7e, +0x18,0x7, 0x1a,0x7a,0x1f,0x12,0x96,0x7e,0x18,0xc, 0xd8,0x7a,0x1f,0x12,0x9a,0x7e, +0xf, 0x12,0x9a,0x7e,0x1f,0x12,0x96,0x12,0x6a,0xfe,0x12,0x0, 0x46,0x12,0x58,0xdd, +0x12,0x6a,0x7d,0x12,0x28,0xcd,0x2, 0x28,0x69,0xe4,0x7a,0xb3,0x34,0x38,0x7a,0xb3, +0x34,0x39,0x7a,0xb3,0x34,0x3a,0x22,0x7e,0x34,0x0, 0xc8,0x7a,0x37,0x27,0x69,0x7e, +0x34,0x2, 0x8a,0x7a,0x37,0x27,0x6d,0x7e,0x34,0x0, 0x96,0x7a,0x37,0x27,0x6b,0x7e, +0x34,0x0, 0x64,0x7a,0x37,0x27,0x6f,0x7e,0x34,0x0, 0x50,0x7a,0x37,0x27,0x71,0x7e, +0x34,0x0, 0x2b,0x7a,0x37,0x27,0x73,0x7e,0x34,0x0, 0x4, 0x12,0xcf,0x2d,0x74,0x1, +0x7a,0xb3,0x27,0x79,0xe4,0x7a,0xb3,0x27,0x7c,0x12,0x28,0xc6,0x3e,0x34,0x7e,0x8, +0x24,0xcb,0xe4,0x2, 0x1a,0x30,0x90,0x60,0x9a,0x93,0xa, 0x3b,0x22,0x7e,0x8, 0x27, +0x82,0x7e,0x34,0x1, 0xe, 0x74,0xff,0x12,0x1a,0x30,0x12,0x9f,0x9f,0x7e,0x8, 0x28, +0x90,0x12,0x28,0xf0,0x7e,0x8, 0x28,0xf4,0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x1a,0x30, +0x6c,0xaa,0x74,0x3, 0x12,0x77,0xd1,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0xa, 0x12, +0x82,0xb5,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14,0x2d,0x31,0x79,0x41,0x0, 0x28, +0xe4,0xa, 0x4a,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0x46,0x7f,0x10,0x2d,0x34,0x39, +0xb1,0x0, 0x50,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xc8,0x22,0xca,0x3b,0x75,0x25,0x0, +0x75,0x26,0x0, 0x75,0x27,0x0, 0x75,0x28,0x0, 0x75,0x2b,0x3, 0x75,0x32,0x0, 0x75, +0x33,0x0, 0x7e,0x38,0x28,0x90,0x12,0xc5,0x3e,0x12,0xbf,0xe0,0x75,0x24,0x0, 0x12, +0xcf,0x47,0x60,0x3, 0x75,0x33,0x1, 0x5, 0x24,0xe5,0x24,0xb4,0xa, 0xf1,0x7e,0xb3, +0x28,0xfd,0x70,0x12,0x7e,0xb3,0x28,0xf9,0x70,0xc, 0x7e,0xb3,0x28,0xfa,0x70,0x6, +0xe5,0x33,0x70,0x2, 0xa1,0xf, 0x75,0x24,0x0, 0x12,0xcf,0x47,0x60,0x8, 0x2e,0x34, +0x29,0x0, 0x14,0x7a,0x39,0xb0,0x5, 0x24,0xe5,0x24,0xb4,0xa, 0xec,0x30,0x11,0x6, +0x7e,0x48,0x36,0xfc,0x80,0x4, 0x7e,0x48,0x36,0xbe,0x7f,0x4, 0x12,0x72,0x1a,0x7e, +0x73,0x28,0xf6,0x7a,0x4b,0x70,0x75,0x24,0x0, 0x81,0xb9,0xe5,0x24,0x12,0xc0,0x65, +0x12,0x2d,0x5d,0x9, 0xb5,0x27,0xe0,0xf5,0x2a,0x12,0xce,0x8b,0xf5,0x2b,0xe5,0x2a, +0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, 0x81,0xb7,0xe5,0x2b,0xb4,0x3, 0x7, 0x12,0xce, +0xad,0x70,0x2, 0x81,0xb7,0x7e,0x8, 0x0, 0x2b,0xe5,0x2a,0x12,0x9e,0xe0,0x50,0x7, +0x12,0xce,0xad,0x70,0x2, 0x81,0xb7,0x12,0x2d,0x5d,0x9, 0xb5,0x27,0xe1,0xf5,0x27, +0x12,0x2d,0x5d,0x9, 0xb5,0x27,0xe2,0xc4,0x54,0xf0,0xf5,0x28,0x7e,0x73,0x29,0x3a, +0xbe,0x71,0x2a,0x28,0x5a,0x7e,0xb3,0x28,0xfb,0x70,0x2e,0x75,0x39,0xf, 0x7e,0x8, +0x0, 0x27,0xe5,0x2a,0xa, 0x3b,0x2e,0x34,0x36,0xaa,0x6d,0x22,0x74,0x1, 0x12,0x79, +0x1a,0x75,0x39,0x20,0x7e,0x8, 0x0, 0x28,0xe5,0x2a,0xa, 0x3b,0x2e,0x34,0x36,0xb4, +0x6d,0x22,0x74,0x10,0x12,0x79,0x1a,0x80,0x3, 0x12,0xcd,0xe8,0xe5,0x2a,0xa, 0x3b, +0x7f,0x3, 0x2d,0x13,0x7e,0xb, 0xb0,0xb4,0x1, 0x15,0xe4,0x19,0xb3,0x36,0xaa,0x6c, +0xaa,0xe5,0x2a,0xa, 0x3b,0x19,0xa3,0x36,0xb4,0x75,0x27,0x0, 0x75,0x28,0x0, 0x7e, +0xb3,0x29,0x51,0xb4,0xff,0x12,0x75,0x27,0x0, 0x12,0x2d,0x5d,0x9, 0xb5,0x27,0xe0, +0xbe,0xb0,0xff,0x68,0x3, 0x75,0x27,0x1, 0x12,0x2d,0x5d,0x49,0x45,0x27,0xdc,0x7a, +0x45,0x2c,0x49,0x35,0x27,0xde,0x7a,0x35,0x2e,0xe5,0x2b,0xb4,0x1, 0x2, 0x80,0x2, +0x81,0x31,0x75,0x34,0x0, 0xe5,0x24,0xbe,0xb0,0x1, 0x38,0x14,0xe5,0x24,0xa, 0x3b, +0x6d,0x22,0x9d,0x23,0x7e,0x34,0x0, 0x9, 0xad,0x32,0x9, 0xb3,0x27,0xe9,0xf5,0x34, +0x6c,0xaa,0x7e,0x71,0x2a,0x74,0x5, 0xac,0x7b,0x19,0xa3,0x32,0xd, 0xe5,0x2a,0xa, +0x3b,0x2d,0x37,0x7d,0x26,0x39,0xa1,0x0, 0x3c,0x75,0x29,0x0, 0x7e,0x71,0x29,0x74, +0x9, 0xac,0x7b,0x9, 0xb3,0x37,0x98,0x54,0xf, 0xbe,0xb1,0x2a,0x78,0x1c,0x49,0x23, +0x37,0x94,0x7a,0x25,0x2c,0x49,0x23,0x37,0x96,0x7a,0x25,0x2e,0x9, 0xb3,0x27,0xe3, +0xf5,0x30,0x9, 0xb3,0x27,0xe4,0xf5,0x31,0x80,0x5, 0x12,0xcf,0xae,0x40,0xcd,0x75, +0x29,0x0, 0x12,0x2d,0x64,0x9, 0xb5,0x37,0x3e,0x54,0xf, 0xbe,0xb1,0x2a,0x68,0x5, +0x12,0xcf,0xae,0x40,0xed,0x7e,0x35,0x2c,0xbe,0x34,0x1, 0x2c,0x50,0x6, 0xbe,0x34, +0x0, 0xa, 0x38,0x25,0xbe,0x34,0x3, 0xc, 0x28,0x6, 0xbe,0x34,0x4, 0x2e,0x40,0x19, +0xe5,0x30,0xbe,0xb0,0x1, 0x28,0x12,0x7e,0x73,0x29,0x5c,0xa, 0x27,0x1b,0x25,0xe5, +0x30,0xa, 0x3b,0xbd,0x32,0x8, 0x2, 0x81,0x31,0x12,0x2d,0x64,0x49,0x25,0x37,0x3a, +0x7e,0x35,0x2c,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x14,0x18,0x2, 0x81,0x31, +0xe5,0x29,0xbe,0xb0,0xa, 0x40,0x2, 0x81,0x31,0x7e,0x73,0x28,0xf4,0xbe,0x70,0x2, +0x40,0x2, 0x81,0x31,0xe5,0x34,0x12,0xce,0x8b,0xbe,0xb0,0x1, 0x78,0x2, 0x81,0x31, +0x7e,0xa1,0x34,0x74,0x9, 0xa4,0x49,0x35,0x27,0xdc,0xbe,0x34,0x0, 0x1e,0x38,0x2, +0x81,0x31,0xbe,0x34,0x4, 0x1a,0x40,0x2, 0x81,0x31,0x7e,0xa1,0x34,0x74,0x5, 0xa4, +0x9, 0xb5,0x32,0xd, 0x60,0x2, 0x81,0x31,0x75,0x2b,0x2, 0x7e,0xb3,0x28,0xf4,0x4, +0x7a,0xb3,0x28,0xf4,0x12,0x2d,0x64,0x49,0x15,0x37,0x3a,0x7e,0x5, 0x2c,0x9d,0x1, +0x3e,0x4, 0x2e,0x5, 0x2c,0x7a,0x5, 0x35,0x49,0x45,0x37,0x3c,0x7e,0x15,0x2e,0x9d, +0x14,0x7d,0x41,0x2e,0x45,0x2e,0x7a,0x45,0x37,0xbe,0x4, 0x0, 0x0, 0x58,0xf, 0x6d, +0x0, 0x12,0xce,0x6c,0x7d,0x3, 0x2e,0x5, 0x2e,0x7a,0x5, 0x37,0x80,0x1e,0x7e,0x5, +0x35,0xbe,0x4, 0x4, 0x37,0x8, 0xf, 0x7e,0x4, 0x4, 0x37,0x12,0xce,0x6c,0x2e,0x35, +0x2e,0x7a,0x35,0x37,0x80,0x6, 0x7e,0x35,0x35,0x7a,0x35,0x2c,0x7e,0x35,0x37,0xbe, +0x34,0x0, 0x0, 0x58,0x7, 0x6d,0x22,0x7a,0x25,0x2e,0x80,0x12,0xbe,0x34,0x8, 0xe7, +0x8, 0x6, 0x7e,0x34,0x8, 0xe7,0x80,0x3, 0x7e,0x35,0x37,0x7a,0x35,0x2e,0x12,0xcd, +0xe8,0x7e,0x35,0x2c,0x5e,0x60,0xf, 0x7a,0x35,0x2c,0x7e,0x35,0x2e,0x5e,0x60,0xf, +0x7a,0x35,0x2e,0x7e,0x91,0x24,0x74,0x9, 0xac,0x9b,0x9, 0x74,0x27,0xe0,0xa, 0x57, +0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x7d,0x25,0x2e,0x25,0x2e,0x7a,0x25,0x2e,0xbe,0x70, +0xff,0x68,0x19,0xe5,0x2b,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x25,0x5, 0x26,0xe5,0x2b, +0xa, 0x5b,0x12,0xcf,0x69,0x7d,0x35,0x2e,0x35,0x2c,0x80,0x7, 0x7e,0x35,0x2c,0x2e, +0x34,0xc0,0x0, 0x7a,0x35,0x2c,0x7e,0x25,0x2c,0x12,0xcf,0xa6,0x7f,0x4, 0x2d,0x13, +0x79,0x20,0x0, 0x2, 0x7e,0x25,0x2e,0x7f,0x4, 0x2d,0x13,0x79,0x20,0x0, 0x4, 0xe5, +0x27,0x2d,0x39,0x7d,0x28,0x39,0xb1,0x0, 0x6, 0x7e,0xa1,0x28,0x12,0xcf,0xa6,0x2d, +0x39,0x39,0xa1,0x0, 0x7, 0x5, 0x32,0x5, 0x24,0x7e,0x73,0x29,0x3a,0xbe,0x71,0x24, +0x28,0x2, 0x21,0xab,0xe5,0x25,0x39,0xb4,0x0, 0x1, 0x7e,0xb3,0x3a,0xd0,0xb4,0x1, +0x9, 0x7e,0xb3,0x28,0xfa,0xb4,0x1, 0x19,0x80,0xf, 0xe5,0x26,0xbe,0xb0,0x0, 0x38, +0x6, 0x7e,0xb3,0x28,0xfa,0x60,0xa, 0xb2,0x11,0x12,0x70,0x51,0x74,0x1, 0x12,0x2d, +0x6b,0x7e,0xb3,0x28,0xf9,0x60,0x9, 0xe5,0x33,0x70,0x5, 0x7f,0x3, 0x12,0x28,0xf0, +0xe4,0x7a,0xb3,0x28,0xfd,0x7a,0xb3,0x28,0xf9,0x7a,0xb3,0x28,0xfa,0x80,0x9, 0x7f, +0x3, 0x12,0x28,0xf0,0xe4,0x12,0x2d,0x6b,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18, +0x37,0x94,0x7e,0x8, 0x37,0x3a,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x5a,0xca, +0x39,0x7e,0x18,0x27,0xdc,0x7e,0x8, 0x37,0x94,0x12,0x1a,0xb, 0x1b,0xfd,0xe5,0x26, +0x70,0x18,0x7e,0x8, 0x37,0x3a,0x7e,0x34,0x0, 0x5a,0x74,0xff,0x12,0x1a,0x30,0x7e, +0x8, 0x37,0x94,0x7e,0x34,0x0, 0x5a,0x12,0x1a,0x30,0xda,0x3b,0x22,0x7e,0xa1,0x24, +0x74,0x9, 0xa4,0x22,0x7e,0xa1,0x29,0x74,0x9, 0xa4,0x22,0x70,0x3, 0xd2,0x86,0x22, +0xc2,0x86,0x22,0x12,0x1d,0x78,0x12,0x70,0x1e,0x7e,0xb3,0x3a,0xa7,0xb4,0x1, 0x5b, +0x12,0xc7,0x49,0x12,0xcf,0x9f,0x12,0x90,0x8f,0x12,0x2e,0x5, 0x12,0x1d,0xb7,0x50, +0xe5,0x12,0x65,0xff,0x7e,0xb3,0x3a,0xa4,0xb4,0x1, 0x4, 0xe4,0x12,0x2d,0x6b,0x12, +0x59,0xa2,0x12,0x2d,0xed,0x40,0xcf,0x12,0x6c,0x1b,0x12,0x2d,0xed,0x40,0xc7,0x12, +0x97,0x8, 0x12,0x1f,0x4c,0x12,0x0, 0x66,0x12,0x82,0xd3,0x12,0x96,0xa5,0x12,0x7f, +0x45,0x12,0x57,0xa3,0x12,0x79,0x5c,0x12,0x98,0x34,0x12,0xcb,0xd9,0x12,0x29,0x2b, +0x12,0x57,0xfc,0x12,0x4e,0x48,0x12,0x4a,0xd6,0x80,0x9b,0x12,0x77,0xe6,0x2, 0x2d, +0xe1,0x7e,0xb3,0x3a,0xa4,0xb4,0x1, 0x4, 0xe4,0x2, 0x2d,0x6b,0x22,0xc2,0x0, 0x7e, +0xb3,0x15,0xa1,0x60,0x6, 0x7e,0xb3,0x15,0xa0,0x70,0x7, 0x12,0xbc,0xe8,0x28,0x2, +0xd2,0x0, 0xa2,0x0, 0x22,0x7e,0x34,0x3a,0x80,0x30,0x10,0x4d,0xc2,0x10,0x9, 0x53, +0x0, 0x2, 0xa, 0x25,0x12,0x2e,0x63,0x7a,0x27,0x29,0x3c,0x9, 0x53,0x0, 0x3, 0xa, +0x25,0x12,0x2e,0x63,0x7a,0x27,0x29,0x3e,0x9, 0x53,0x0, 0x4, 0xa, 0x25,0x12,0x2e, +0x63,0x7a,0x27,0x29,0x40,0x7e,0x39,0x50,0x12,0x2e,0x6c,0x7a,0x27,0x29,0x47,0x9, +0x53,0x0, 0x1, 0x12,0x2e,0x6c,0x7a,0x27,0x29,0x49,0x9, 0x73,0x0, 0x5, 0xa, 0x37, +0x12,0xce,0xd3,0x3e,0x34,0x7a,0x37,0x29,0x4f,0x22,0x7e,0x50,0x40,0xac,0x45,0x9e, +0x24,0x0, 0x40,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22,0xa, 0x25,0x3e,0x24, +0x3e,0x24,0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28,0xf, +0x74,0x1, 0x7a,0xb3,0x28,0xf9,0xe4,0x7a,0xb3,0x28,0xfb,0x7a,0xb3,0x28,0xfc,0x2, +0x9f,0xab,0xa5,0xbe,0x0, 0x1b,0x6c,0xaa,0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac,0x5a, +0x19,0x62,0x28,0x3a,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xf0,0x74,0x1, 0x7a,0xb3,0x28, +0xf8,0x6c,0xaa,0x80,0x26,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x27,0x82,0xb, 0x18, +0x20,0x12,0x2e,0x63,0x1b,0x18,0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x27,0x84, +0xb, 0x18,0x20,0x12,0x2e,0x63,0x1b,0x18,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xd6,0x22, +0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x29,0x5c,0xf5,0x29,0x7e,0xe3,0x29,0x5d,0x6c,0xdd, +0x7e,0xb3,0x15,0xa1,0xbe,0xb0,0x1, 0x68,0x11,0x60,0x3, 0x2, 0x30,0x13,0x7e,0xb3, +0x27,0x58,0xb4,0x1, 0x2, 0x80,0x3, 0x2, 0x30,0x13,0x6c,0xcc,0x2, 0x30,0x4, 0x7e, +0x70,0x2, 0xac,0x7c,0x9, 0xa3,0x25,0xce,0x7a,0xa1,0x27,0x9, 0xb3,0x25,0xcf,0xf5, +0x28,0x75,0x25,0x2, 0x75,0x26,0x2, 0x4c,0xaa,0x68,0xe, 0xe5,0x29,0xa, 0x2b,0x1b, +0x24,0xe5,0x27,0xa, 0x3b,0xbd,0x32,0x48,0x3, 0x75,0x25,0x1, 0xe5,0x28,0x60,0xc, +0xa, 0x2e,0x1b,0x24,0xe5,0x28,0xa, 0x3b,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, 0x75, +0x24,0x0, 0x80,0x5c,0xe5,0x24,0xbc,0xbc,0x68,0x54,0x7e,0x71,0x24,0x12,0xcf,0x1b, +0x9, 0x33,0x25,0xcf,0xa, 0x2a,0xe5,0x27,0x12,0xbc,0xd9,0xbe,0x34,0x0, 0x3, 0x18, +0x11,0x12,0xbc,0xd5,0xbe,0x34,0x0, 0x3, 0x18,0x8, 0x75,0x25,0x1, 0x75,0x26,0x1, +0x80,0x37,0xa, 0x2a,0xe5,0x27,0x12,0xbc,0xd9,0xbe,0x34,0x0, 0x4, 0x18,0x1f,0x12, +0xbc,0xd5,0xbe,0x34,0x0, 0x4, 0x18,0x16,0xe5,0x25,0xbe,0xb0,0x2, 0x28,0x3, 0x75, +0x25,0x2, 0xe5,0x26,0xbe,0xb0,0x2, 0x28,0x10,0x75,0x26,0x2, 0x80,0xb, 0x5, 0x24, +0x7e,0x23,0x27,0x58,0xbe,0x21,0x24,0x38,0x9b,0x12,0x9b,0x1d,0x50,0x2a,0x7e,0x73, +0x39,0x0, 0xbe,0x71,0x27,0x78,0x9, 0x7e,0x73,0x39,0x2, 0xbe,0x71,0x28,0x68,0x12, +0x7e,0x73,0x39,0x1, 0xbe,0x71,0x27,0x78,0xf, 0x7e,0x73,0x39,0x3, 0xbe,0x71,0x28, +0x78,0x6, 0x75,0x25,0x3, 0x75,0x26,0x3, 0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x3, 0x75, +0x28,0x0, 0xe5,0x25,0x7e,0x71,0x26,0x7c,0x6c,0x7c,0x5f,0x7c,0x4d,0x12,0x8a,0x29, +0xb, 0xf0,0xb, 0xc0,0x7e,0x73,0x27,0x58,0xbc,0x7c,0x28,0x3, 0x2, 0x2f,0xf, 0x7a, +0xf3,0x27,0x58,0xda,0x3b,0x22,0xca,0xf8,0x7c,0xab,0xbe,0xa0,0x34,0x38,0x2, 0x21, +0x27,0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x29,0xfd,0x41,0x3d,0xbe,0xa0,0x36,0x68, +0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0x8, +0x2e,0x37,0x37,0xf0,0x7e,0x39,0xb0,0xbe,0xa0,0x37,0x68,0x2, 0x41,0x3d,0x75,0x1a, +0x36,0x41,0x3d,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0,0x39,0x78,0x1b,0x7e,0xf3,0x3b, +0x15,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x15,0xbe,0xa0,0x39,0x78,0x3, 0x75,0x1a,0x38, +0xa, 0x3f,0x9, 0xb3,0x2a,0xe, 0x41,0x3d,0xbe,0xa0,0x3a,0x68,0x5, 0xbe,0xa0,0x3b, +0x78,0x1b,0x7e,0xf3,0x3b,0x17,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x17,0xbe,0xa0,0x3b, +0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2a,0x31,0x41,0x3d,0xbe,0xa0,0xfb, +0x78,0x6, 0x7e,0xb3,0x29,0xff,0x41,0x3d,0xbe,0xa0,0x5e,0x78,0x26,0x7e,0xf, 0x3b, +0xfa,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, +0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, 0x3, 0x7c,0xa7,0x4c,0xba,0x44, +0x80,0x41,0x3d,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0,0x3d,0x78,0x1b,0x7e,0xf3,0x3b, +0x19,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x19,0xbe,0xa0,0x3d,0x78,0x3, 0x75,0x1a,0x3c, +0xa, 0x3f,0x9, 0xb3,0x29,0x67,0x41,0x3d,0xbe,0xa0,0x3e,0x68,0x5, 0xbe,0xa0,0x3f, +0x78,0x1b,0x7e,0xf3,0x3b,0x1b,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x1b,0xbe,0xa0,0x3f, +0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x29,0x8a,0x41,0x3d,0xbe,0xa0,0x40, +0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x3a,0xf1,0x41,0x3d,0xbe, +0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e,0xf3,0x3b,0x36,0x7c,0xbf,0x4, +0x7a,0xb3,0x3b,0x36,0xbe,0xa0,0x4f,0x78,0x3, 0x75,0x1a,0x4e,0xa, 0x3f,0x2e,0x37, +0x37,0xee,0x7e,0x39,0xb0,0x41,0x3d,0xbe,0xa0,0x51,0x68,0x5, 0xbe,0xa0,0x52,0x78, +0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, 0xff,0x7e,0xb3,0x3b,0x41,0xa, +0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a,0xb3,0x3b,0x41,0xbe,0xa0,0x52, +0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0x41,0x3d,0xbe,0xa0,0x5c,0x68,0x5, 0xbe,0xa0, +0x5d,0x78,0x1a,0x7e,0xf3,0x3b,0xa, 0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0xa, 0xbe,0xa0, +0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0xb0,0x28,0x41,0x3d,0xbe,0xa0,0x60, +0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, 0xb3,0x3b,0xbb,0x80,0x7e,0xbe, +0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x75,0xbe,0xa0,0xf4,0x68,0x5, 0xbe,0xa0,0xf5, +0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a,0x25,0xa, 0x9, 0xb3,0x37,0xf6, +0xbe,0xa0,0xf5,0x78,0x58,0x75,0x1a,0xf4,0x80,0x53,0xbe,0xa0,0xf0,0x68,0x5, 0xbe, +0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5,0xe7,0x80,0x40,0xbe,0xa0,0xf2, +0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10,0x3e,0x14,0x7e,0x1f,0x37,0xf2, +0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, 0xa, 0x56,0x80,0x1f,0x7d,0x53, +0x80,0x1b,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80,0x12,0xbe,0xa0,0xf7,0x78,0x4, +0x74,0x50,0x80,0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4,0x80,0x1, 0xe4,0xda,0xf8,0x22, +0x7c,0x7b,0x6c,0xaa,0x12,0x35,0x2d,0x78,0x9, 0x7c,0xb7,0x12,0x70,0x70,0x7c,0xab, +0x80,0xa, 0xb4,0x4, 0x7, 0x7c,0xb7,0x12,0x30,0x16,0x7c,0xab,0x7c,0xba,0x22,0x30, +0x90,0x19,0xc2,0x90,0xe5,0x18,0x70,0x9, 0x75,0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80, +0x11,0x7e,0x71,0x91,0xe5,0x1a,0x12,0x32,0x8a,0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91, +0x5, 0x1a,0xe5,0x1a,0x12,0x32,0x40,0xf5,0x91,0x22,0x7c,0x6b,0x12,0x35,0x2d,0x78, +0x5, 0x7c,0xb6,0x2, 0x49,0xae,0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x32,0x9f,0x22,0xca, +0xf8,0x7c,0x6b,0xa5,0xbe,0x0, 0x9, 0x7c,0xb7,0x12,0x49,0xf9,0xd2,0x8, 0xa1,0x21, +0xa5,0xbe,0x1, 0x3d,0x7a,0x73,0x3a,0xf2,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf, +0xae,0x4, 0xd2,0x9, 0xa1,0x21,0xa5,0xbf,0xaa,0x5, 0x12,0x48,0x4a,0x80,0x1e,0xa5, +0xbf,0xab,0xa, 0x7e,0x34,0x5, 0x20,0x7a,0x37,0x37,0xf0,0x80,0x10,0xa5,0xbf,0xac, +0x2, 0x80,0x2, 0xa1,0x21,0x7e,0x34,0x4, 0xc0,0x7a,0x37,0x37,0xf0,0x6d,0x33,0x61, +0x9d,0xbe,0x60,0x4, 0x40,0x20,0xbe,0x60,0x8, 0x38,0x1b,0x12,0x35,0x24,0xa5,0xbe, +0x7, 0x7, 0x6d,0x33,0x7a,0x35,0xa, 0xa1,0x21,0xa5,0xbe,0x8, 0x2, 0x80,0x2, 0xa1, +0x21,0x12,0x7, 0xfb,0xa1,0x21,0xa5,0xbe,0xa, 0x9, 0x43,0xc, 0x20,0x7a,0x73,0x3a, +0xfb,0xa1,0x21,0xa5,0xbe,0xb, 0x8, 0x12,0x35,0x24,0x12,0x3e,0xd6,0xa1,0x21,0xbe, +0x60,0x1b,0x40,0x7, 0xbe,0x60,0x1c,0x38,0x2, 0x81,0xb9,0xbe,0x60,0x1e,0x40,0xd, +0xbe,0x60,0x23,0x38,0x8, 0x12,0x35,0x26,0x43,0xc, 0x40,0xa1,0x21,0xbe,0x60,0x15, +0x40,0x1a,0xbe,0x60,0x18,0x38,0x15,0x12,0x35,0x26,0xd2,0x8, 0xa5,0xbe,0x15,0x2, +0x80,0x2, 0xa1,0x21,0x74,0x7, 0x7a,0xb3,0x3a,0xf5,0xa1,0x21,0xa5,0xbe,0x19,0x7, +0xe4,0x7a,0xb3,0x3b,0xa, 0xa1,0x21,0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38, +0x2, 0x81,0xb9,0xa5,0xbe,0x2d,0x1b,0x12,0x35,0x26,0x20,0x9, 0x2, 0xa1,0x21,0x7e, +0x63,0x3b,0x1d,0x7c,0x46,0x6c,0x55,0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35,0x8, +0xa1,0x21,0xbe,0x60,0x2f,0x40,0xa, 0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, 0x81, +0xb9,0xa5,0xbe,0x34,0xf, 0x43,0xc, 0x10,0xbe,0x70,0x64,0x38,0x2, 0x81,0xb9,0x7e, +0x70,0x64,0x81,0xb9,0xbe,0x60,0x38,0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, 0x1, +0x7e,0xf3,0x3b,0x16,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x16,0xa, 0x2f,0x19,0x72,0x2a, +0xe, 0xa5,0xbe,0x39,0x2, 0x80,0x2, 0xa1,0x21,0x75,0x1a,0x38,0xa1,0x21,0xbe,0x60, +0x3a,0x68,0x4, 0xa5,0xbe,0x3b,0x21,0x43,0xc, 0x2, 0x7e,0xf3,0x3b,0x18,0x7c,0xbf, +0x4, 0x7a,0xb3,0x3b,0x18,0xa, 0x2f,0x19,0x72,0x2a,0x31,0xa5,0xbe,0x3b,0x2, 0x80, +0x2, 0xa1,0x21,0x75,0x1a,0x3a,0xa1,0x21,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, 0x7a, +0x73,0x29,0xff,0xa1,0x21,0xa5,0xbe,0x50,0x6, 0x7a,0x73,0x3b,0x41,0xa1,0x21,0xbe, +0x60,0x3c,0x68,0x4, 0xa5,0xbe,0x3d,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x3b,0x1a,0x7c, +0xbf,0x4, 0x7a,0xb3,0x3b,0x1a,0xa, 0x2f,0x19,0x72,0x29,0x67,0xa5,0xbe,0x3d,0x2, +0x80,0x2, 0xa1,0x21,0x75,0x1a,0x3c,0xa1,0x21,0xbe,0x60,0x3e,0x68,0x4, 0xa5,0xbe, +0x3f,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x3b,0x1c,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x1c, +0xa, 0x2f,0x19,0x72,0x29,0x8a,0xa5,0xbe,0x3f,0x2, 0x80,0x2, 0xa1,0x21,0x75,0x1a, +0x3e,0xa1,0x21,0xbe,0x60,0x40,0x40,0xd, 0xbe,0x60,0x42,0x38,0x8, 0x12,0x35,0x26, +0x75,0xd, 0x1, 0x80,0xa, 0xa5,0xbe,0x43,0xb, 0x12,0x35,0x26,0x75,0xd, 0x2, 0x12, +0x35,0x35,0x80,0x7d,0xa5,0xbe,0x44,0x8, 0x12,0x35,0x26,0x12,0x37,0x28,0x80,0x71, +0xbe,0x60,0x45,0x68,0x4, 0xa5,0xbe,0x46,0x5, 0x12,0x35,0x26,0x80,0x63,0xbe,0x60, +0x4e,0x68,0x4, 0xa5,0xbe,0x4f,0x20,0x43,0xd, 0x4, 0x7e,0xf3,0x3b,0x37,0x7c,0xbf, +0x4, 0x7a,0xb3,0x3b,0x37,0xa, 0x2f,0x2e,0x27,0x37,0xee,0x7a,0x29,0x70,0xa5,0xbe, +0x4f,0x3f,0x75,0x1a,0x4e,0x80,0x3a,0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31, +0xbe,0x60,0xf0,0x40,0x25,0xbe,0x60,0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c, +0xb7,0xa5,0xf7,0xa5,0xbe,0xf3,0x1a,0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e, +0x1f,0x37,0xf2,0x2d,0x30,0x1b,0x1a,0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71, +0xf, 0xda,0xf8,0x22,0xd2,0x8, 0xa, 0x26,0x19,0x72,0x3a,0xf1,0x22,0x7e,0xb3,0x3a, +0xf1,0xc4,0x54,0x7, 0x22,0x12,0x37,0xb9,0xb4,0x1, 0x14,0xca,0x39,0x7e,0x18,0x3b, +0x31,0x7e,0x8, 0x24,0xc2,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x37,0x1, 0x80,0x12,0xca, +0x39,0x7e,0x18,0x3b,0x31,0x7e,0x8, 0x2a,0x5d,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x37, +0x1f,0x2, 0x35,0x64,0x7a,0x1f,0x29,0xe9,0x7a,0xf, 0x29,0xe5,0x22,0x7a,0xb3,0x29, +0xed,0x70,0x14,0x12,0x37,0x1f,0x12,0x35,0x64,0x7e,0x18,0x5, 0xe0,0x7a,0x1f,0x6, +0x40,0x7e,0x18,0x4, 0x60,0x80,0x10,0xb4,0x1, 0x11,0x12,0x37,0x1, 0x12,0x35,0x64, +0x12,0xce,0x2e,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0x44,0x22,0x74,0x1, 0x12,0x0, +0x1e,0xe4,0x12,0x35,0x6d,0x12,0x35,0xb4,0xe4,0x12,0x0, 0x1e,0x74,0x1, 0x12,0x35, +0x6d,0x2, 0x35,0xb4,0xca,0x3b,0x7e,0xd3,0x29,0x60,0x7e,0xc3,0x29,0x61,0x7e,0x8, +0x1e,0x54,0x12,0x71,0xc2,0x7e,0x8, 0x1e,0x9a,0x7e,0x34,0x0, 0x46,0x12,0x1a,0x30, +0x7e,0x8, 0x1e,0xe0,0x12,0xce,0xf8,0x7e,0x8, 0x1e,0xea,0x12,0x1e,0xb6,0x7e,0xf3, +0x29,0xe9,0x7e,0x18,0x29,0xc9,0x7a,0x1d,0x24,0x7e,0x18,0x1e,0xe0,0x7a,0x1d,0x28, +0x7c,0xbd,0x7c,0x7c,0x7e,0x8, 0x29,0xa6,0x12,0xc9,0x50,0x6c,0xee,0x80,0x2b,0xa, +0x3e,0x9, 0xa3,0x29,0xc9,0xa, 0x3a,0x2e,0x34,0x19,0xc5,0x12,0x5e,0x88,0x7c,0xab, +0xbe,0xa0,0x1c,0x50,0x13,0xa, 0x3e,0x12,0x36,0xc3,0xa, 0x4a,0x19,0xb4,0x1e,0x54, +0x7e,0xb3,0x29,0xe8,0x19,0xb4,0x1e,0x9a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee, +0x80,0x24,0xa, 0x3e,0x9, 0xa3,0x29,0xa6,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, +0x3c,0x2d,0x32,0x12,0x36,0xc3,0xa, 0x4a,0x19,0xb4,0x1e,0x70,0x7e,0xb3,0x29,0xe8, +0x19,0xb4,0x1e,0xb6,0xb, 0xe0,0xbc,0xde,0x38,0xd8,0x7e,0xb3,0x29,0xea,0x7e,0x8, +0x1e,0xf4,0x60,0x9, 0x7e,0x18,0x1e,0xe0,0x12,0xc7,0xe2,0x80,0x3, 0x12,0xc8,0xf6, +0x6c,0xee,0x7e,0x18,0x1e,0xf4,0x7a,0x1f,0x1e,0x44,0x74,0x2, 0xac,0xbe,0x49,0x35, +0x1e,0xe0,0x7a,0x37,0x1e,0x48,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1e,0xea,0x7a,0x37, +0x1e,0x4a,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1e,0x54,0x6d,0x22,0x7a,0x1f,0x1e, +0x4c,0x7e,0x70,0xe, 0xac,0x7e,0x2e,0x34,0x1e,0x9a,0x7a,0x1f,0x1e,0x50,0x7e,0x8, +0x1e,0x44,0x7c,0xbf,0x7c,0x7e,0x12,0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2, +0xda,0x3b,0x22,0x2e,0x37,0x29,0xeb,0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x3a, +0xa7,0x12,0xaf,0x37,0x12,0x13,0xf5,0x12,0xc8,0x6a,0xe4,0x12,0xa, 0x66,0x7e,0x24, +0x3, 0xd4,0x12,0x48,0x31,0x74,0x1, 0x12,0x35,0x6d,0x12,0x89,0x46,0x7e,0x34,0xd0, +0xc, 0x12,0x1, 0xe, 0x12,0x35,0x9c,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13, +0x1, 0x7e,0x1f,0x24,0xc6,0x7e,0xf, 0x24,0xc2,0x22,0x7a,0xb3,0x29,0xed,0x70,0x5, +0x12,0x37,0x1f,0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x37,0x1, 0x12,0x35,0x64,0x22,0x7e, +0x1f,0x2a,0x61,0x7e,0xf, 0x2a,0x5d,0x22,0x12,0x37,0xb9,0xb4,0x1, 0x17,0xca,0x39, +0x7e,0x18,0x24,0xc2,0x7e,0x8, 0x3b,0x31,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x48,0x41, +0x12,0x37,0x1, 0x80,0x1a,0xca,0x39,0x7e,0x18,0x2a,0x5d,0x7e,0x8, 0x3b,0x31,0x12, +0x1a,0xb, 0x1b,0xfd,0x7e,0x37,0x2a,0x63,0x7a,0x37,0x37,0xee,0x12,0x37,0x1f,0x2, +0x35,0x64,0xe5,0xd, 0x60,0x52,0xe5,0xd, 0x30,0xe0,0x6, 0x53,0xd, 0xfe,0x12,0x3f, +0xf0,0xe5,0xd, 0x30,0xe1,0x14,0x53,0xd, 0xfd,0x7e,0xb3,0x3b,0x35,0x70,0x4, 0x74, +0x1, 0x80,0x1, 0xe4,0x12,0xcf,0x59,0x12,0x71,0x4c,0xe5,0xd, 0x30,0xe2,0x29,0x53, +0xd, 0xfb,0xe4,0x7a,0xb3,0x3b,0x36,0x7e,0xb3,0x3b,0x35,0x70,0xa, 0x74,0x1, 0x12, +0x0, 0x1e,0x12,0x37,0x1f,0x80,0x7, 0xe4,0x12,0x0, 0x1e,0x12,0x37,0x1, 0x12,0x35, +0x64,0x7e,0xb3,0x29,0xe9,0x2, 0x38,0x99,0x22,0x7e,0xb3,0x3b,0x35,0x7e,0x34,0x0, +0x4, 0x22,0x7c,0x96,0x7c,0xa7,0x12,0x35,0x6d,0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, +0x12,0x3f,0x4b,0x7c,0xb9,0x12,0x0, 0x1e,0x2, 0x37,0xdb,0xca,0x3b,0x7e,0xe3,0x29, +0x61,0x7e,0xf3,0x29,0xe7,0x74,0x1, 0x7a,0xb3,0x29,0xe7,0x12,0x3f,0xf0,0x12,0xcf, +0x3f,0x12,0x1e,0xbd,0x7e,0x17,0x29,0xeb,0x6d,0x0, 0x12,0x1a,0x30,0x7e,0xd0,0x7, +0x12,0x3c,0x94,0x6c,0xcc,0x80,0x1f,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e, +0x34,0x14,0x78,0xfb,0x7c,0x67,0xa, 0x2c,0x2e,0x27,0x29,0xeb,0x7e,0x29,0x70,0x4c, +0x76,0x7a,0x29,0x70,0xb, 0xc0,0x12,0x39,0x1b,0xa, 0x3c,0xbd,0x32,0x48,0xd8,0x12, +0x39,0xa8,0x30,0x1b,0xfd,0x12,0xce,0xee,0x7e,0xb3,0x29,0x60,0x7c,0x7e,0x12,0x89, +0x5e,0x6c,0xcc,0x80,0x2a,0x74,0x2, 0xac,0xbc,0x49,0x35,0x6, 0x48,0xbe,0x34,0x15, +0x40,0x50,0x1a,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb, +0x7c,0xb7,0x64,0xff,0xa, 0x2c,0x2e,0x27,0x29,0xeb,0x12,0x5f,0x7f,0xb, 0xc0,0x12, +0x39,0x1b,0xa, 0x3c,0xbd,0x32,0x48,0xcd,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0x81,0x12, +0x39,0x2a,0x74,0x2, 0x12,0xcf,0x59,0x12,0x38,0x99,0x74,0x2, 0x12,0x0, 0x1e,0x7a, +0xf3,0x29,0xe7,0x12,0x3f,0xf0,0xda,0x3b,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x24, +0x2, 0x12,0x71,0xc2,0x7e,0xa3,0x29,0x60,0x7e,0x73,0x29,0x61,0x6c,0xee,0x80,0x1d, +0xa, 0x2e,0x9, 0x62,0x29,0xc9,0xa, 0x26,0x12,0x71,0x3f,0x7c,0x6b,0xbe,0x60,0x1c, +0x50,0x9, 0xa, 0x2e,0x12,0x39,0x11,0x19,0xb2,0x24,0x2, 0xb, 0xe0,0xbc,0x7e,0x38, +0xdf,0x6c,0xee,0x80,0x1a,0xa, 0x2e,0x9, 0x62,0x29,0xa6,0xbe,0x60,0x23,0x50,0xd, +0xa, 0x1e,0xa, 0x27,0x2d,0x21,0x12,0x39,0x11,0x19,0xb2,0x24,0x1e,0xb, 0xe0,0xbc, +0xae,0x38,0xe2,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x24,0x2, 0x6d,0x0, +0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79, +0x22,0x2e,0x27,0x29,0xeb,0x7e,0x29,0xb0,0xa, 0x26,0x22,0x7e,0x73,0x29,0x61,0xa, +0x37,0x7e,0x53,0x29,0x60,0xa, 0x25,0x2d,0x23,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf0, +0xa, 0x74,0x1, 0x7a,0xb3,0x29,0xe7,0x12,0x1e,0xbd,0x7c,0xe7,0x80,0x5d,0x12,0x3c, +0x94,0x12,0x39,0xa8,0x30,0x1b,0xfd,0x12,0xce,0xee,0x12,0x89,0x56,0x6c,0xdd,0x80, +0x3d,0x7e,0x50,0x2, 0xac,0x5d,0x49,0x32,0x6, 0x48,0xbe,0x34,0x14,0x78,0x50,0x14, +0xa, 0x1d,0x2e,0x17,0x29,0xeb,0x7e,0x19,0xb0,0xbe,0xb0,0x0, 0x28,0x1e,0x14,0x7a, +0x19,0xb0,0x80,0x18,0xbe,0x34,0x19,0x28,0x28,0x10,0xa, 0x3d,0x12,0x36,0xc3,0xbe, +0xb0,0xff,0x68,0x8, 0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b,0xe0,0xb, 0xd0,0x12,0x39, +0x1b,0xa, 0x3d,0xbd,0x32,0x48,0xba,0x4c,0xee,0x68,0x8, 0x7c,0xaf,0x1b,0xf0,0x4c, +0xaa,0x78,0x9b,0xda,0x79,0xda,0xd8,0x22,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x29, +0xe9,0x12,0x38,0x99,0x74,0x2, 0x12,0x0, 0x1e,0x74,0x5, 0x7e,0x70,0x9b,0x12,0x13, +0x2c,0x12,0x39,0xcb,0x7e,0xb3,0x29,0xe9,0x2, 0xe, 0x94,0x6c,0xaa,0x80,0x22,0xa, +0x3a,0x9, 0x73,0x29,0xc9,0x2e,0x34,0x19,0xc5,0x12,0x5e,0x88,0x7c,0x7b,0xa, 0x47, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0xf, 0x3b,0xfa,0x2d,0x12,0x79,0x40,0x0, 0x48,0xb, +0xa0,0x7e,0x63,0x29,0x61,0xbc,0x6a,0x38,0xd6,0x22,0xca,0x3b,0x7e,0xb3,0x3a,0xa5, +0xb4,0x1, 0x2, 0x80,0x2, 0x61,0x4a,0x6c,0xcc,0x6c,0xdd,0x7e,0xb3,0x3a,0xd0,0xb4, +0x1, 0x8, 0x7e,0xe0,0x10,0x7e,0xf0,0x32,0x80,0x6, 0x7e,0xe0,0x6, 0x7e,0xf0,0x1e, +0x12,0x90,0x8a,0x7d,0xf3,0x12,0x77,0xdb,0x50,0xfb,0x74,0x1, 0x7a,0xb3,0x3b,0x96, +0x12,0x35,0x6d,0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x3f,0x4b,0x12,0xcf, +0x3f,0x7e,0xe7,0x29,0xfa,0x7a,0xe5,0x25,0x7e,0xb3,0x29,0xe7,0xf5,0x24,0x74,0x4, +0x7a,0xb3,0x29,0xe7,0x7e,0xe7,0x29,0xfa,0x5e,0xe4,0x0, 0x3f,0x7a,0xe7,0x29,0xfa, +0x7e,0xb3,0x29,0xe7,0x12,0x89,0x66,0x7c,0x7b,0x74,0x6, 0xac,0x7b,0x12,0xcf,0x89, +0x7d,0x23,0x7d,0x3f,0x12,0x59,0x99,0xad,0x32,0x7a,0x37,0x29,0xf4,0x12,0x3f,0xf0, +0x61,0x2b,0x12,0x3c,0x94,0x30,0x10,0x2, 0x61,0x31,0x7c,0xbe,0x12,0x90,0xd4,0x12, +0x39,0xb9,0xc2,0x0, 0x80,0x2f,0x80,0x7, 0x12,0x3f,0xf7,0xe4,0x12,0x4d,0xd8,0x20, +0x93,0xf6,0x30,0x1b,0x1d,0x20,0x0, 0x1a,0xd2,0x1, 0x12,0x3b,0x4d,0x12,0x3b,0xa2, +0xd2,0x0, 0x12,0x3b,0x67,0x68,0x6, 0x7e,0xb3,0x3b,0x95,0x60,0xe, 0xc2,0x1, 0x12, +0x3b,0x4d,0x12,0x3b,0x72,0x30,0x1b,0xd7,0x30,0x1a,0xd4,0xd2,0x1, 0x12,0x3b,0x4d, +0xe4,0x12,0x13,0xde,0xb, 0xc0,0x12,0x3b,0xa2,0x12,0x90,0xde,0x7e,0xa3,0x3b,0x95, +0x4c,0xaa,0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x3b,0x96,0x4c,0xaa,0x68,0xb, 0x7e,0xb3, +0x3a,0xd0,0x70,0x5, 0xe4,0x7a,0xb3,0x3b,0x95,0x12,0x3b,0x67,0x78,0x18,0x7e,0xb3, +0x3b,0x95,0x60,0x12,0xe4,0x7a,0xb3,0x3b,0x95,0x7a,0xb3,0x28,0xf4,0x7a,0xb3,0x28, +0xf5,0x7e,0xd0,0x1, 0x80,0x1b,0x12,0x3b,0x67,0x68,0x10,0x7e,0xb3,0x3b,0x95,0x70, +0xa, 0x7e,0xd0,0x1, 0xe4,0x7a,0xb3,0x3a,0xa5,0x80,0x6, 0xbc,0xfc,0x28,0x2, 0x41, +0x82,0xe4,0x7a,0xb3,0x29,0xf1,0x7e,0x35,0x25,0x7a,0x37,0x29,0xfa,0xe5,0x24,0x7a, +0xb3,0x29,0xe7,0x4c,0xdd,0x68,0x3, 0x12,0x1d,0x5e,0xda,0x3b,0x22,0x30,0x1, 0x6, +0x12,0x3f,0xe3,0x2, 0x13,0x96,0x12,0xcf,0x90,0xc2,0x2, 0x2, 0x3b,0x5e,0xa9,0xd0, +0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22,0x7e,0x73,0x3c,0x28,0xa, 0x37,0x5e,0x34,0x0, +0x2, 0x22,0x30,0x1b,0x5, 0xc2,0x1, 0x12,0x3b,0x4d,0xa9,0xd1,0xcd,0xa9,0xc5,0xea, +0x30,0x1a,0x3, 0x20,0x1b,0x14,0x12,0x3f,0xf7,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74, +0x2, 0x12,0x4d,0xd8,0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x1, 0x2, +0x3b,0x4d,0xca,0x3b,0x7e,0x8, 0x1e,0x44,0x12,0x77,0xb6,0x7e,0x1f,0x3c,0x29,0x7a, +0x1d,0x27,0x7e,0xb3,0x29,0x61,0xf5,0x2e,0x7e,0xb3,0x3b,0x96,0xb4,0x1, 0x6, 0x7e, +0x38,0x3b,0x98,0x80,0x4, 0x7e,0x38,0x5, 0x80,0x6d,0x33,0x7a,0x35,0x2b,0x74,0x2, +0x12,0x0, 0x1e,0x7e,0xb3,0x3b,0x97,0x70,0xe, 0x7e,0xb3,0x3b,0x95,0x70,0x8, 0x74, +0x1, 0x7a,0xb3,0x3b,0x97,0x81,0x67,0x7e,0xb3,0x3b,0x97,0x70,0x6, 0x74,0x1, 0x7a, +0xb3,0x3b,0x97,0x7e,0xb3,0x3b,0x96,0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80,0x6, 0x12, +0xce,0x44,0x12,0xcd,0xfd,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18,0x75,0x2d, +0x0, 0x80,0xc, 0x12,0xce,0x44,0x3e,0x24,0x3e,0x24,0x1e,0x24,0x12,0xcd,0xfd,0xe5, +0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e,0x34,0x0, 0xc8,0x7a,0x35,0x2f,0x7e,0x18,0x1e, +0x44,0x7f,0x1, 0x12,0x66,0x6a,0x75,0x2d,0x0, 0x80,0x10,0x12,0xce,0x37,0xbe,0x35, +0x2b,0x8, 0x6, 0x12,0xce,0x37,0x7a,0x35,0x2b,0x5, 0x2d,0xe5,0x2e,0xbe,0xb1,0x2d, +0x38,0xe9,0x12,0xcf,0x97,0x40,0x25,0x7e,0xb3,0x3b,0x96,0xb4,0x1, 0x1e,0x5, 0x1d, +0xe5,0x1d,0xbe,0xb0,0xa, 0x40,0x15,0x75,0x1d,0x0, 0xe5,0x2e,0xa, 0x3b,0x3e,0x34, +0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, 0x12,0x1a,0xb, 0x1b,0xfd,0x74,0x2, 0x12,0x0, +0x1e,0x12,0xcf,0x97,0x50,0xb, 0x74,0x2, 0x7a,0xb3,0x3c,0x28,0xe4,0x7a,0xb3,0x3b, +0x97,0xda,0x3b,0x22,0x7e,0x34,0x3, 0xe8,0x2, 0x1c,0xf4,0xca,0xd8,0xca,0x79,0x7d, +0xd3,0x90,0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90,0x60,0x51,0xe4,0x93,0x7c,0x8b,0xa, +0x38,0xa, 0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c,0x7c,0xe7,0x12,0x3c,0x94,0xa9,0xd0, +0xc4,0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x0, 0x6e,0x7c,0x8b,0x74,0x7, 0x7e,0x70,0xf, +0x12,0x3e,0xcc,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x3b,0xfe,0x79,0x51,0x0, 0x6, 0x7e, +0x54,0x0, 0x80,0x7e,0x1f,0x3b,0xfe,0x79,0x51,0x0, 0x8, 0x7e,0x54,0x0, 0xc, 0x7e, +0x1f,0x3b,0xfe,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, 0x2, 0x78,0x7, 0x12,0x3e,0x6c, +0x44,0x1, 0x80,0x1c,0x12,0x3e,0x6c,0x44,0x8, 0x1b,0x1a,0x50,0x4d,0xdd,0x7e,0x1f, +0x3b,0xfe,0x78,0x7, 0x12,0x3e,0x70,0x54,0xfb,0x80,0x5, 0x12,0x3e,0x70,0x44,0x4, +0x1b,0x1a,0x50,0x7e,0x1f,0x3b,0xfa,0x69,0xe1,0x0, 0x84,0x69,0x51,0x0, 0x90,0x7d, +0xf5,0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a,0x50,0x7e,0xb3,0x3a,0xb1,0xbe, +0xb0,0x6, 0x40,0x3, 0xb4,0xff,0x11,0x12,0x3e,0x78,0x54,0xe6,0x1b,0x1a,0x50,0x12, +0x3e,0x78,0x4e,0x54,0x1, 0xa4,0x80,0xf, 0x12,0x3e,0x78,0x5e,0x54,0xfe,0xe6,0x1b, +0x1a,0x50,0x12,0x3e,0x78,0x44,0xa4,0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x21, +0x12,0x3e,0x6c,0x12,0xcf,0x61,0x12,0x3e,0x6c,0x44,0x50,0x1b,0x1a,0x50,0x7e,0x34, +0x0, 0x2, 0x12,0x3f,0x2c,0x12,0x48,0x9e,0x12,0x48,0x7b,0x7a,0x37,0x37,0xf6,0xc1, +0x28,0x6c,0xdd,0xc1,0x22,0x4c,0xdd,0x78,0x4, 0x6c,0x99,0x80,0x2b,0xbc,0xfd,0x40, +0x12,0xa, 0xcd,0x9, 0x9c,0x29,0xa5,0xbe,0x90,0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, +0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3,0x9, 0x9c,0x29,0xc8,0xbe,0x90,0x1c, +0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x12,0x3e,0x6c,0x12,0xcf,0x61,0xa, 0xc9, +0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x12,0x3e,0x6c,0x4d,0x5c,0x1b,0x1a,0x50, +0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, 0x80, +0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x3f,0x2c,0x12,0x48,0x9e,0xbe,0xd4,0x0, 0x1, 0x78, +0x10,0x12,0x48,0x9e,0x12,0x48,0x7b,0x74,0x2, 0xac,0xbd,0x59,0x35,0x37,0xf8,0x80, +0xf, 0x12,0x48,0x7b,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59,0x32,0x37,0xf8, +0xb, 0xd0,0xbc,0xed,0x28,0x2, 0xa1,0x95,0xa9,0xd5,0xcb,0x74,0x7, 0x7c,0x78,0x12, +0x3e,0xcc,0xa9,0xc0,0xc4,0x7e,0x1f,0x3b,0xfa,0x79,0xe1,0x0, 0x84,0x7e,0x1f,0x3b, +0xfa,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x3b,0xfe,0x79,0x30,0x0, 0x6, 0x7e, +0xf, 0x3b,0xfe,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x3b,0xfe,0x79,0x30,0x0, 0x10,0x7e, +0xf, 0x3b,0xfe,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x7e,0x1f,0x3b,0xfe, +0x2e,0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22,0x7e,0x1f,0x3b,0xfa,0x2e,0x34,0x0, 0x84, +0xb, 0x1a,0x50,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xa9,0xd5,0xcb,0x74,0x2, 0x7e, +0x70,0x3f,0x12,0x3e,0x84,0x74,0xf, 0x12,0x0, 0x6e,0x7c,0x7b,0x74,0xf, 0x5e,0x70, +0xfe,0x12,0x3e,0x84,0x74,0xc, 0x12,0x0, 0x6e,0x54,0x7f,0x68,0x8, 0x74,0xc, 0x7e, +0x70,0xf8,0x12,0x3e,0x84,0x7e,0x70,0x72,0x74,0xe, 0x12,0x3e,0x84,0x74,0x7, 0x12, +0x0, 0x6e,0x7c,0x7b,0x5e,0x70,0xfb,0x74,0x7, 0x2, 0x3e,0xcc,0x12,0x3e,0x84,0x75, +0xfd,0xff,0xa9,0xc5,0xcb,0x22,0xb2,0x82,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e, +0x24,0x0, 0x12,0x12,0x68,0xc6,0xe5,0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, +0x7e,0x71,0x27,0x12,0x3e,0x84,0x74,0xb, 0x7e,0x71,0x2f,0x12,0x3e,0x84,0x74,0xc, +0x7e,0x71,0x30,0x12,0x3e,0xcc,0x22,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x3e, +0x84,0x7a,0x61,0xfc,0x12,0x3e,0xcf,0x12,0xc6,0x3c,0xd2,0x0, 0x12,0xc6,0x28,0x12, +0x3f,0xe3,0x12,0x13,0xde,0x2, 0x13,0x96,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12, +0x7e,0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x3f,0x4b,0x7c,0x23,0x1b,0x30,0xa5,0xba, +0x0, 0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x7c,0xab,0x80,0xe, 0x7e, +0x70,0x3, 0x80,0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b, +0xa0,0xa5,0xbe,0x0, 0xea,0x22,0x12,0xcf,0x90,0xc2,0x0, 0x12,0xc6,0x33,0xc2,0x2, +0x12,0x3b,0x5e,0xc2,0x0, 0x12,0xc6,0x28,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x0, 0x6e, +0x7a,0x1b,0xb0,0x74,0xf, 0x6c,0x77,0x12,0x3e,0x84,0xe5,0xfc,0x7a,0xb, 0xb0,0x43, +0xfc,0x10,0x2, 0x3e,0xcf,0xe4,0x12,0xc5,0xee,0x12,0xc6,0xe4,0x12,0x3c,0x94,0x12, +0xc7,0x42,0x12,0x3e,0x8a,0x12,0xc5,0xe4,0x12,0xc6,0xfb,0x12,0x0, 0x9, 0x12,0xc7, +0x7, 0x12,0x71,0xcb,0x12,0xc7,0x17,0xd2,0xaf,0x12,0xc6,0x76,0x12,0x6a,0x1a,0x12, +0x3e,0xd9,0x12,0xc6,0x3c,0x7e,0x8, 0x3c,0x1b,0x12,0xc7,0x62,0x90,0x60,0x50,0xe4, +0x93,0xca,0xb8,0x90,0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24,0xff,0xff,0xda,0xb8, +0x2, 0x12,0x34,0xd2,0x2, 0x12,0x3b,0x5e,0x74,0x1, 0x22,0xd2,0x1, 0x2, 0x3b,0x4d, +0x7e,0x8, 0x29,0x5a,0x2, 0x5, 0xb4,0x74,0x81,0x7a,0xb3,0x3c,0x31,0x22,0x30,0x8, +0x3b,0xc2,0x8, 0x12,0x1c,0xff,0x7e,0x73,0x3a,0xf6,0x7a,0x73,0x29,0x3a,0x7e,0x73, +0x3a,0xf7,0x7a,0x73,0x2a,0xa, 0x7e,0x73,0x3a,0xf7,0x7a,0x73,0x29,0xee,0x7e,0xb3, +0x3a,0xf8,0x60,0x18,0x7e,0x34,0x0, 0x2, 0x12,0x3c,0x9b,0x7e,0x34,0x0, 0x1, 0x12, +0x3c,0x9b,0x6d,0x33,0x12,0x3c,0x9b,0xe4,0x7a,0xb3,0x3a,0xf8,0x12,0x37,0x62,0x2, +0x40,0x42,0xe5,0xc, 0x70,0x2, 0x21,0x64,0xe5,0xc, 0x30,0xe0,0x10,0x53,0xc, 0xfe, +0x12,0x41,0x65,0x12,0x6a,0xb5,0x7e,0x8, 0x29,0x5a,0x12,0x9, 0xa1,0xe5,0xc, 0x30, +0xe1,0x6, 0x53,0xc, 0xfd,0x12,0xc9,0x7, 0xe5,0xc, 0x30,0xe2,0x32,0x53,0xc, 0xfb, +0x7e,0xb3,0x29,0xff,0x60,0x9, 0x7e,0x8, 0x29,0x5a,0x12,0x6, 0xba,0x80,0xb, 0x7e, +0xb3,0x2a,0x52,0x7e,0x73,0x2a,0x51,0x12,0xb, 0xad,0x7e,0x73,0x29,0xff,0x2e,0x70, +0xff,0x92,0x1, 0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x29,0x64,0x12,0xb, 0x1e,0xe5, +0xc, 0x30,0xe3,0x4a,0x53,0xc, 0xf7,0x7e,0x73,0x3b,0x23,0x7a,0x73,0x29,0xfc,0x12, +0xaa,0x4, 0x7a,0xb3,0x0, 0x6b,0xbe,0xb0,0xff,0x68,0xb, 0x43,0xc, 0x20,0x7e,0x73, +0x0, 0x6b,0x7a,0x73,0x3a,0xfb,0x12,0x41,0xcb,0x12,0x47,0xcd,0x7e,0x73,0x3b,0x24, +0xbe,0x73,0x2a,0x4f,0x68,0x6, 0x7a,0x73,0x2a,0x4f,0xd2,0xf, 0x30,0xf, 0x9, 0xc2, +0xf, 0x12,0xaf,0x37,0xe4,0x12,0xa, 0x66,0x12,0x1c,0x59,0x12,0x46,0xef,0xe5,0xc, +0x30,0xe4,0xf, 0x53,0xc, 0xef,0x7e,0x43,0x3b,0x25,0x7e,0x50,0xa, 0xac,0x45,0x12, +0x48,0x31,0xe5,0xc, 0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e,0x73,0x3b,0x11,0xbe,0x70, +0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x3b,0x11,0xa9,0xd5,0xcb,0x74,0xe, 0x12,0x0, +0x6e,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63,0x3b,0x11,0xa, 0x26,0x2e,0x24,0x0, 0x3, +0x12,0x2e,0x63,0x7c,0x65,0x4c,0x76,0x74,0xe, 0x12,0x3e,0x84,0x12,0x0, 0x6e,0x12, +0x3e,0xcf,0x7e,0x73,0x3b,0x14,0x7a,0x73,0x2a,0x1, 0x7e,0x73,0x3b,0x13,0x7a,0x73, +0x2a,0xc, 0x12,0xcf,0x50,0xe5,0xc, 0x30,0xe5,0xa, 0x53,0xc, 0xdf,0x7e,0xb3,0x3a, +0xfb,0x2, 0x45,0xa, 0x22,0x12,0xcf,0x24,0x12,0xbf,0x83,0x90,0x60,0x50,0xe4,0x93, +0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x29,0x67,0x6d,0x0, 0x9, 0xb3,0x29,0x66,0x12,0x41, +0xae,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2a,0xe, 0x6d,0x0, 0x9, 0xb3,0x2a,0xd, 0x12, +0x41,0xae,0xa, 0x1b,0x2e,0x14,0x29,0x69,0x12,0x41,0xbb,0xe5,0x25,0x12,0x41,0xb2, +0xa, 0x1b,0x2e,0x14,0x2a,0x10,0x12,0x41,0xbb,0xe5,0x24,0x2, 0x1a,0x30,0x7e,0x34, +0x0, 0x2, 0x12,0x1a,0x30,0x90,0x60,0x50,0xe4,0x93,0x22,0x6d,0x0, 0x90,0x60,0x91, +0xe4,0x93,0xa, 0x3b,0x1b,0x35,0x22,0x7a,0xb3,0x29,0xfc,0x12,0x42,0x31,0x7a,0x37, +0x2a,0x8, 0x22,0x7e,0xa3,0x0, 0x6b,0xbe,0xa0,0xff,0x68,0x4c,0xbe,0xa3,0x2, 0xdc, +0x68,0x46,0x74,0x5, 0xa4,0x12,0x47,0xff,0x12,0x42,0x29,0x12,0x47,0xed,0x12,0x42, +0x29,0x12,0x47,0xe4,0x12,0xb0,0x17,0x50,0x9, 0x7e,0xb3,0x0, 0x6b,0x12,0xb0,0xef, +0x80,0x6, 0x12,0x42,0x29,0x12,0x47,0xdb,0x12,0x41,0xcb,0x7e,0x8, 0x29,0x5a,0x12, +0x3, 0x8b,0x7e,0x73,0x2a,0x1, 0xa, 0x37,0x7e,0xf, 0x3c,0x2, 0x79,0x30,0x0, 0x1a, +0x7e,0x73,0x0, 0x6b,0x7a,0x73,0x2, 0xdc,0x22,0x7e,0xa3,0x0, 0x6b,0x74,0x5, 0xa4, +0x22,0x7e,0x23,0x29,0xfc,0x7e,0x33,0x3b,0x22,0xac,0x23,0x2e,0x14,0x1, 0xf4,0xbe, +0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x29,0xfd,0xbe,0x14,0xf, +0x3c,0x40,0x4, 0x7e,0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x2, +0x74,0x1, 0x7a,0xb3,0x29,0xfd,0x7e,0x73,0x29,0xfd,0xbc,0x76,0x68,0x2, 0xd2,0xf, +0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e, +0x10,0x7, 0x7e,0x1f,0x3b,0xfa,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x3e,0x4, +0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, +0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, 0x17,0x85,0xca,0x79,0x90,0x60,0x50, +0xe4,0x93,0x7c,0xab,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e,0xb3,0x29,0x61,0xbc, +0xbe,0x28,0x4, 0x7c,0xfb,0x80,0x2, 0x7c,0xfe,0x7a,0xa3,0x29,0x5a,0x7a,0xe3,0x29, +0x5b,0x7a,0xa3,0x29,0x5e,0x7a,0xe3,0x29,0x5f,0x7a,0xa3,0x29,0x60,0x7a,0xe3,0x29, +0x61,0xe4,0x7a,0xb3,0x29,0x64,0x7a,0xa3,0x29,0x5c,0x7a,0xe3,0x29,0x5d,0x90,0x60, +0x91,0x93,0x7a,0xb3,0x29,0x65,0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x29,0x66,0xa, +0x3a,0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x29,0x67,0x12, +0x1a,0xb, 0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff, +0x7e,0x8, 0x29,0x8a,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e, +0x34,0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0xe, 0x12,0x1a,0xb, 0x1b,0xfd, +0x12,0x41,0x65,0x12,0x6a,0xb5,0x12,0x62,0xbc,0x74,0x1, 0x12,0x35,0x6d,0xe4,0x7a, +0xb3,0x29,0xee,0x7a,0xb3,0x29,0xef,0x12,0x64,0x1, 0x7a,0x37,0x29,0xfa,0x74,0x3, +0x7a,0xb3,0x29,0xf0,0xe4,0x7a,0xb3,0x29,0xf1,0x74,0x2, 0x7a,0xb3,0x29,0xf2,0x7e, +0x34,0x0, 0xc8,0x7a,0x37,0x29,0xf4,0x74,0x4, 0x7a,0xb3,0x29,0xf3,0x7e,0x34,0x0, +0xf, 0x7a,0x37,0x29,0xf6,0x7e,0x34,0x20,0x5f,0x7a,0x37,0x29,0xf8,0x74,0x20,0x7a, +0xb3,0x2a,0x4f,0x74,0x1, 0x7a,0xb3,0x29,0xfd,0x74,0x20,0x7a,0xb3,0x29,0xfe,0x74, +0x4, 0x7a,0xb3,0x2a,0x0, 0x74,0x1e,0x12,0x41,0xc7,0xe4,0x7a,0xb3,0x2a,0xa, 0x7a, +0xb3,0x2a,0xb, 0x7e,0x34,0x1, 0x90,0x7a,0x37,0x2a,0x6, 0x74,0x1, 0x7a,0xb3,0x29, +0xff,0x12,0x47,0xd4,0x74,0x30,0x7a,0xb3,0x2a,0xc, 0x6d,0x33,0x7a,0x37,0x2a,0x2, +0x7a,0x37,0x2a,0x4, 0x74,0x2, 0x7a,0xb3,0x2a,0x1, 0x7e,0x34,0x0, 0x30,0x7a,0x37, +0x2a,0x57,0x74,0x4, 0x7a,0xb3,0x2a,0x54,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2a,0x55, +0xe4,0x7a,0xb3,0x2a,0x53,0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x2a,0x59,0x74,0x1, 0x7a, +0xb3,0x2a,0x50,0x74,0x5, 0x7a,0xb3,0x2a,0x51,0xe4,0x7a,0xb3,0x2a,0x52,0x74,0x1, +0x7a,0xb3,0x2a,0x4d,0xe4,0x7a,0xb3,0x2a,0x4e,0x7e,0x34,0x19,0xad,0x7a,0x37,0x2a, +0x5b,0xa, 0x3e,0xca,0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a, +0x31,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x79,0x22,0x12,0x41,0xc7,0x30,0xf, 0xc, 0xc2, +0xf, 0x12,0xaf,0x37,0x30,0x0, 0x4, 0xe4,0x12,0xa, 0x66,0x30,0x0, 0x9, 0x12,0xae, +0xea,0x12,0x46,0xef,0x2, 0xaa,0xc4,0x22,0x7e,0xb, 0x70,0x7a,0x73,0x29,0xfc,0x29, +0x70,0x0, 0x4, 0x7a,0x73,0x2a,0x4f,0x29,0x70,0x0, 0x1, 0x7a,0x73,0x2a,0x1, 0x29, +0x70,0x0, 0x3, 0x7a,0x73,0x2a,0xd, 0x12,0x41,0xcb,0x7e,0x8, 0x29,0x5a,0x12,0x3, +0x8b,0xd2,0x0, 0xc2,0x1, 0x2, 0x44,0x88,0x30,0x0, 0x3, 0x12,0x45,0x96,0xa2,0x1, +0x92,0x2, 0x12,0x73,0x25,0x2, 0x44,0x98,0x7e,0x73,0x2a,0xd, 0x7a,0x73,0x3b,0x12, +0x22,0x12,0x47,0xd4,0x12,0xb0,0x17,0x50,0x9, 0xd2,0x0, 0xd2,0x1, 0x12,0x44,0x88, +0x80,0x15,0x74,0x1, 0x12,0x45,0xd9,0x7e,0x43,0x3b,0x10,0x7e,0x50,0x64,0xac,0x45, +0x12,0x89,0xad,0x7a,0xb3,0x2a,0xc, 0x12,0x44,0x98,0x12,0x47,0xf6,0x2, 0x45,0x96, +0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac,0xbf,0x12,0x47,0xff,0x12,0x47,0xed,0x12,0x47, +0xdb,0x12,0x47,0xe4,0x7a,0xf3,0x0, 0x6b,0x7c,0xbf,0x12,0xb0,0xef,0x12,0x41,0xcb, +0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x25,0xb, 0x12,0xaf,0x1c,0x12,0x1c,0x4b,0xe4,0x7a, +0xb3,0x15,0xa1,0x7a,0xb3,0x3a,0x7a,0xda,0xf8,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb, +0x7e,0xa0,0x4, 0xbe,0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff,0x80,0xb, 0x12, +0x45,0x72,0x38,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0x80,0x1a, +0xbe,0xd0,0x81,0x78,0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x45,0x72,0x40,0x4, +0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38,0x2, 0x6c,0xdd, +0x7c,0xbd,0x12,0x44,0xd0,0x12,0x45,0x96,0x12,0x47,0xf6,0x12,0x44,0x98,0x7e,0x73, +0x29,0xfc,0x7a,0x73,0x3b,0x23,0x12,0x48,0x38,0x7a,0xd3,0x3a,0xfb,0xda,0x79,0xda, +0xd8,0x22,0x7e,0x90,0x5, 0xac,0x9f,0x9, 0xb4,0x25,0x7, 0xbc,0xbe,0x22,0x7e,0x73, +0x29,0xfc,0x7a,0x73,0x3b,0x23,0x7e,0x73,0x2a,0xc, 0x7a,0x73,0x3b,0x13,0x7e,0x73, +0x2a,0xd, 0x7a,0x73,0x3b,0x12,0x7e,0x73,0x2a,0x1, 0x7a,0x73,0x3b,0x14,0x22,0x7e, +0xb3,0x3a,0x4, 0x60,0x6, 0x14,0x7a,0xb3,0x3a,0x4, 0x22,0x12,0xa7,0xc2,0x7e,0xb3, +0x3a,0x8b,0x70,0xe, 0x7e,0xb3,0x34,0x4f,0xb4,0x1, 0x7, 0xe4,0x12,0x44,0xd0,0x12, +0xac,0x79,0x12,0x47,0x91,0x12,0xa8,0xf6,0x7e,0xa3,0x3a,0x8b,0x7a,0xa3,0x34,0x4f, +0xbe,0xb0,0xff,0x68,0x3, 0x2, 0x44,0xd0,0x22,0xca,0x3b,0x7c,0xdb,0xe4,0x7a,0xb3, +0x2a,0x1, 0x12,0x47,0xcd,0x7e,0xc0,0xa, 0x12,0x73,0x16,0x30,0xd, 0xfd,0x74,0x1, +0x12,0x0, 0xe, 0x7e,0x1f,0x3c,0x13,0x12,0x90,0x2a,0x7d,0x73,0xbe,0x74,0xff,0xff, +0x78,0x9, 0x12,0x46,0x49,0x2e,0x34,0x0, 0x3, 0x80,0x18,0xbe,0x74,0x80,0x0, 0x28, +0x7, 0x12,0x46,0x49,0xb, 0x35,0x80,0xb, 0xbe,0x74,0x40,0x0, 0x28,0xc, 0x12,0x46, +0x49,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xbe,0xbe,0xd0,0x1, 0x78,0x9, 0x7e, +0x1f,0x3c,0x13,0x12,0x89,0xcc,0x7d,0x73,0x7e,0x1f,0x3c,0x2, 0x69,0x31,0x0, 0x1a, +0x7a,0x73,0x2a,0x1, 0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x3c,0x2, 0x2e,0x14,0x0, +0x1a,0xb, 0xa, 0x30,0x22,0xca,0xf8,0x6c,0xff,0x7e,0x73,0x0, 0x6b,0xbc,0x7f,0x68, +0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x46,0xcb,0xca,0x39,0x7e,0x30,0x38,0xac,0x3f, +0x12,0x46,0xe4,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39,0x7e,0x30, +0x50,0xac,0x3f,0x12,0x46,0xd9,0x12,0x1a,0xb, 0x1b,0xfd,0xb, 0xf0,0xbe,0xf0,0x4, +0x40,0xc7,0x7e,0x23,0x0, 0x6b,0x7e,0x30,0x5, 0xac,0x23,0x12,0x46,0xcb,0xca,0x39, +0x7e,0x23,0x0, 0x6b,0x7e,0x30,0x38,0xac,0x23,0x12,0x46,0xe4,0x12,0x1a,0xb, 0x1b, +0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39,0x7e,0x23,0x0, 0x6b,0x7e,0x30,0x50,0xac,0x23, +0x12,0x46,0xd9,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0xf8,0x22,0x2e,0x14,0x25,0x7, 0x6d, +0x0, 0x12,0x44,0x58,0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x1, 0x4c,0x6d,0x0, 0x7e, +0x18,0x2, 0x8c,0x22,0x2e,0x14,0x0, 0x6c,0x6d,0x0, 0x7e,0x18,0x34,0x0, 0x22,0x7e, +0xb3,0x29,0xfc,0xca,0x3b,0x7c,0xeb,0x6c,0xff,0x7e,0xc4,0x1, 0xf4,0x7e,0x73,0x3b, +0x22,0xa, 0xb7,0x7e,0xb3,0x29,0xfd,0xf5,0x34,0x75,0x35,0x4, 0xe4,0x7a,0xb3,0x3a, +0x10,0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d,0xac,0x6c,0xdd,0x7e,0xa3,0x3a,0x10,0xbe, +0xa1,0x35,0x40,0x2, 0x80,0x19,0xbe,0xa0,0x0, 0x28,0x19,0x74,0x5, 0xa4,0x9, 0x75, +0x25,0x7, 0xbc,0x7e,0x78,0xe, 0xe5,0x35,0x14,0xbe,0xb3,0x3a,0x10,0x78,0x5, 0xe4, +0x7a,0xb3,0x3a,0x10,0x7e,0xc3,0x3a,0x10,0x80,0x3a,0x7e,0xb3,0x3a,0x10,0x4, 0x7a, +0xb3,0x3a,0x10,0x74,0x5, 0xac,0xbc,0x9, 0x75,0x25,0x7, 0xbc,0x7e,0x68,0x23,0xa, +0xdd,0x19,0xcd,0x3a,0x14,0xa, 0x97,0xad,0x9b,0x2d,0x9c,0x7c,0xad,0xb, 0xd0,0x7c, +0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31,0x34,0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, +0x50,0x8, 0xb, 0xc0,0xe5,0x35,0xbc,0xbc,0x38,0xc0,0x7a,0xf3,0x3a,0x11,0xda,0x3b, +0x22,0x12,0xab,0xd9,0x2, 0x47,0x97,0x7e,0xb3,0x3a,0x7, 0x60,0xf, 0x74,0x1, 0x7a, +0xb3,0x3a,0xf, 0x7e,0xb3,0x3a,0x7d,0x70,0x3, 0x12,0xa7,0x99,0x7e,0xb3,0x3a,0xf, +0xb4,0x1, 0xc, 0x74,0x3, 0x7a,0xb3,0x32,0x7f,0x7e,0x34,0x14,0x0, 0x80,0x9, 0xe4, +0x7a,0xb3,0x32,0x7f,0x7e,0x34,0xa, 0x0, 0x7a,0x37,0x29,0x4f,0x22,0x7e,0x8, 0x29, +0x5a,0x2, 0xd, 0x72,0x74,0x40,0x7a,0xb3,0x2a,0xd, 0x22,0x9, 0x75,0x25,0x9, 0x7a, +0x73,0x2a,0xc, 0x22,0x9, 0x75,0x25,0xa, 0x7a,0x73,0x2a,0xd, 0x22,0x9, 0x75,0x25, +0x8, 0x7a,0x73,0x2a,0x1, 0x22,0x7e,0x73,0x2a,0xc, 0x7a,0x73,0x3b,0x13,0x22,0x9, +0x75,0x25,0x7, 0x7a,0x73,0x29,0xfc,0x22,0x12,0x48,0x4a,0x12,0x48,0x41,0x6d,0x33, +0x7a,0x35,0xa, 0x12,0x45,0x7e,0x12,0x48,0x38,0x74,0x50,0x7a,0xb3,0x3b,0x25,0x7e, +0x24,0x3, 0x20,0x12,0x48,0x31,0xe4,0x12,0x48,0x55,0x6d,0x33,0x7a,0x37,0x3c,0x33, +0x22,0x7d,0x32,0x74,0xfa,0x2, 0x12,0xd0,0x7e,0x73,0x2a,0x4f,0x7a,0x73,0x3b,0x24, +0x22,0x7e,0x37,0x24,0xc8,0x7a,0x37,0x37,0xee,0x22,0x7e,0x34,0xc, 0xd8,0x7a,0x37, +0x37,0xf0,0x22,0x74,0x1, 0x7a,0xb3,0x29,0xee,0x7a,0xb3,0x2a,0xa, 0x22,0xa2,0xc, +0xe4,0x33,0x7a,0xb3,0x3b,0x1f,0x7e,0x73,0x3b,0x23,0xbe,0x73,0x29,0xfc,0x68,0xa, +0xe5,0xc, 0x70,0x6, 0x12,0x45,0x7e,0x12,0x48,0x38,0x22,0x7e,0xf, 0x3b,0xfe,0x69, +0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74, +0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x7e,0x34, +0x0, 0x1, 0x7e,0xf, 0x3b,0xfe,0x79,0x30,0x0, 0x4, 0x7e,0xf, 0x3b,0xfe,0x69,0x30, +0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, 0x79,0x30,0x0, 0x12, +0x22,0xca,0xd8,0xca,0x79,0x7e,0x73,0x29,0x5b,0x7e,0xf3,0x29,0x5a,0xac,0xf7,0x7d, +0x37,0x3e,0x34,0x7e,0x8, 0x1e,0x44,0xe4,0x12,0x1a,0x30,0x7e,0xb3,0x3b,0xc, 0xb4, +0x1, 0x64,0x7e,0x73,0x3b,0xd, 0xbe,0x70,0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12, +0x3c,0x94,0x12,0x1d,0xb7,0x6d,0x33,0x80,0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33, +0xc, 0xd8,0x12,0x1a,0x62,0x7a,0x35,0x26,0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49, +0x21,0x1e,0x44,0xbe,0x25,0x26,0x58,0x7, 0x7e,0x25,0x26,0x59,0x21,0x1e,0x44,0xb, +0x34,0x7a,0x35,0x24,0xbe,0x75,0x24,0x38,0xd0,0xb, 0xd0,0x7e,0x73,0x3b,0xd, 0xbc, +0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0xc, +0xd8,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x24,0xab,0x68,0x10,0x24, +0xef,0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, 0x80,0x2d,0x7e, +0xb3,0x3, 0xff,0xb4,0x5, 0x2a,0x12,0x3f,0x28,0x12,0x4a,0x8e,0x2, 0x49,0x97,0x7e, +0xb3,0x3, 0xff,0xb4,0x5, 0x1a,0x12,0x3f,0x28,0x75,0xe9,0xff,0x22,0x7e,0xb3,0x3, +0xff,0xb4,0x5, 0xc, 0x12,0x3f,0x28,0x2, 0x49,0x91,0x74,0x1, 0x7a,0xb3,0x3, 0xff, +0x22,0x75,0xe7,0x6b,0x2, 0x49,0x97,0xe4,0x7e,0x34,0xd7,0xfc,0x7e,0x24,0x0, 0xff, +0x7a,0x1b,0xb0,0x7e,0x34,0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff,0x22,0x7c,0xa7, +0x7c,0x3b,0xa5,0xbb,0x0, 0x7, 0x7c,0xba,0x12,0x49,0xf9,0x80,0x2c,0xbe,0x30,0xeb, +0x68,0x4, 0xa5,0xbb,0xec,0x9, 0x7c,0xb3,0x7c,0x7a,0x12,0x4a,0x52,0x80,0x1a,0xbe, +0x30,0x80,0x40,0x15,0xbe,0x30,0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c,0x7a,0x12, +0x4a,0x24,0xa5,0xbb,0x8f,0x3, 0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c,0xba,0x2, +0x49,0x4b,0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7a,0xb3,0x3a,0xf1,0xc4,0x54,0x7, +0xbe,0xb0,0x4, 0x68,0x3, 0xb4,0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, +0x7, 0x74,0x1, 0x7a,0xb3,0x3a,0xa7,0x22,0x74,0x1, 0x7a,0xb3,0x3a,0xa7,0xe4,0x7a, +0xb3,0x3a,0xf1,0x22,0x7c,0x6b,0x2e,0x60,0xdd,0x68,0x26,0x2e,0x60,0xfd,0x68,0x21, +0x1b,0x61,0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b,0x61,0x68,0x15,0x1b,0x60,0x68,0x11, +0x2e,0x60,0xa, 0x78,0x4, 0x7a,0x73,0x3a,0x7f,0xa, 0x2b,0x19,0x72,0x3a,0x80,0xd2, +0x10,0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x33,0x7e,0x27,0x3b,0x44,0x4d,0x22, +0x78,0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x3b,0x44,0x15,0x1a, +0x7e,0x27,0x3b,0x44,0xbe,0x24,0x0, 0x1, 0x78,0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34, +0x0, 0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x3b,0x44,0x75,0x1a,0xea,0x22,0x7e,0x14, +0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50,0x79,0x30, +0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79,0x30,0x0, +0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, +0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, +0xe, 0x79,0x20,0x0, 0xc, 0x22,0x7e,0x8, 0x3b,0x48,0x12,0x4b,0xa, 0x7e,0x8, 0x3b, +0x50,0x12,0x4b,0xa, 0x12,0x4b,0x26,0x12,0x4b,0x1f,0x2, 0x4a,0xed,0x7e,0x37,0x3b, +0x48,0xbe,0x34,0x0, 0x0, 0x28,0x12,0x7e,0x73,0x3c,0x36,0xbe,0x70,0x5, 0x50,0x9, +0x7e,0xb3,0x3a,0xd0,0x70,0x3, 0x12,0x4b,0x2d,0x22,0xb, 0xa, 0x30,0xe5,0x6a,0xa, +0x2b,0xbd,0x32,0x28,0x4, 0x9d,0x32,0x80,0x2, 0x6d,0x33,0x1b,0xa, 0x30,0x22,0x7e, +0x8, 0x3, 0xfb,0x2, 0x4b,0xa, 0x7e,0x8, 0x2a,0x95,0x2, 0x4b,0xa, 0x6d,0x33,0x7a, +0x37,0x3b,0x93,0x74,0x1, 0x7a,0xb3,0x3a,0xa5,0x22,0x7e,0xb3,0x3a,0xa5,0x14,0x68, +0x5a,0x14,0x78,0x2, 0x61,0xda,0x14,0x68,0x6d,0x24,0x3, 0x68,0x2, 0x61,0xd2,0x12, +0x4b,0xe0,0x38,0x8, 0x30,0x13,0xf, 0x12,0x96,0x9, 0x68,0xa, 0x12,0xce,0xb8,0xe4, +0x7a,0xb3,0x3b,0x95,0x80,0x74,0x7e,0xb3,0x3a,0x86,0x30,0xe0,0x6d,0x7e,0x73,0x3a, +0x87,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x3a,0xd0,0xb4,0x1, 0xb, +0x7e,0x34,0x62,0x7b,0x12,0x4b,0xe8,0x2e,0x34,0x4, 0x0, 0xbe,0x37,0x3b,0x93,0x50, +0x49,0x12,0x4b,0x2d,0xe4,0x7a,0xb3,0x3b,0x97,0x80,0x3f,0x12,0x4b,0xe0,0x38,0x3, +0x30,0x13,0x32,0xe4,0x7a,0xb3,0x3a,0xa5,0x7e,0xb3,0x3b,0x95,0xb4,0x1, 0x3, 0x12, +0x4b,0x33,0xd2,0x1a,0x80,0x1f,0x74,0xff,0x7a,0xb3,0x3a,0x7f,0x12,0xcf,0x9f,0x12, +0x4e,0x1f,0x12,0x1c,0x63,0xe4,0x7a,0xb3,0x3a,0xa5,0x7a,0xb3,0x3c,0x36,0xd2,0x1a, +0x80,0x8, 0x12,0x4b,0x33,0xe4,0x7a,0xb3,0x3c,0x36,0x12,0x4d,0x43,0x2, 0x39,0xfa, +0x7e,0x73,0x28,0xf4,0xbe,0x70,0x0, 0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x22, +0xca,0xd8,0xca,0x79,0x6c,0xff,0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x28,0xf4, +0x7e,0xe3,0x28,0xf5,0x7e,0xb3,0x3, 0xf2,0x60,0x11,0x7e,0xc7,0x3, 0xfb,0x4d,0xcc, +0x78,0x2, 0x81,0xe4,0xbe,0xd0,0x1, 0x28,0x2, 0x81,0xe4,0xbe,0xd0,0x1, 0x78,0x1d, +0xbe,0xb0,0x4, 0x78,0x2, 0x81,0xe4,0x7e,0xe7,0x27,0xdc,0x7e,0xf7,0x27,0xde,0x7d, +0x3e,0x7d,0x2f,0x12,0x4e,0x68,0xbe,0xb0,0x1, 0x78,0x2, 0x81,0xe4,0x7e,0xa3,0x3, +0xf2,0x7c,0xba,0x14,0x68,0x29,0x14,0x68,0x54,0x14,0x68,0x23,0x14,0x78,0x2, 0x81, +0xe1,0xb, 0xb2,0x68,0x2, 0x81,0xe4,0xbe,0xd0,0x1, 0x68,0x2, 0x81,0xf3,0x4c,0xee, +0x68,0x2, 0x81,0xf3,0x74,0x1, 0x7a,0xb3,0x3, 0xf2,0x12,0x4c,0xfa,0x80,0x65,0x4c, +0xdd,0x78,0x1d,0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x3, 0xf2,0x7e,0x34, +0x62,0x7b,0x80,0x54,0x74,0x4, 0x7a,0xb3,0x3, 0xf2,0x7e,0x34,0x62,0x7f,0x80,0x48, +0x12,0x4d,0x3, 0x90,0x62,0x6e,0x12,0x4d,0xc, 0x68,0x49,0x80,0x56,0xbe,0xd0,0x1, +0x78,0x51,0x4c,0xee,0x78,0x4d,0x12,0x4d,0x3, 0x7e,0x34,0x62,0x77,0x12,0x4b,0xe8, +0x7e,0x14,0x62,0x7b,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7,0x3, +0xfb,0x40,0x21,0x90,0x62,0x6d,0x12,0x4d,0xc, 0x68,0x19,0x12,0x4c,0xfa,0x74,0x3, +0x7a,0xb3,0x3, 0xf2,0x7e,0x34,0x62,0x7b,0x12,0x4b,0xe8,0x7a,0x37,0x3, 0xfb,0x80, +0x12,0x7e,0xf0,0x24,0xe4,0x7a,0xb3,0x3, 0xf2,0x6d,0x33,0x7a,0x37,0x3, 0xfb,0x7c, +0xbf,0x80,0x2, 0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0x7a,0xe7,0x3, 0xf3,0x7a,0xf7, +0x3, 0xf5,0x22,0x7a,0xe7,0x3, 0xf7,0x7a,0xf7,0x3, 0xf9,0x22,0xe4,0x93,0xa, 0x3b, +0x12,0x4d,0x18,0xa, 0xdb,0x4d,0xdd,0x22,0x7d,0x13,0x3e,0x14,0x3e,0x14,0x3e,0x14, +0x7e,0x37,0x3, 0xf7,0x9e,0x37,0x3, 0xf3,0x12,0x1a,0x62,0xbd,0x31,0x38,0x12,0x7e, +0x37,0x3, 0xf9,0x9e,0x37,0x3, 0xf5,0x12,0x1a,0x62,0xbd,0x31,0x38,0x3, 0x74,0x1, +0x22,0xe4,0x22,0x74,0x1, 0x12,0x4d,0x62,0x20,0x1a,0x6, 0x12,0x4d,0x85,0x12,0x3f, +0xeb,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x6, 0x12,0x4d,0x6b,0x12,0x3f,0xeb,0xe4,0x2, +0x4d,0x62,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0xc6,0x1f,0x22,0x74,0xc8,0x7a,0xb3,0x3c, +0x35,0xc2,0x1a,0x80,0xa, 0x12,0x4d,0x9f,0x30,0x1a,0x4, 0x75,0xe9,0xff,0x22,0x12, +0x4d,0xd0,0x68,0xf1,0x22,0xd2,0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12,0x4d,0xd0,0x68, +0x7, 0xc2,0x0, 0xc2,0x1, 0x12,0x3b,0x4d,0x12,0x4d,0x9f,0x30,0x1a,0xeb,0x22,0x80, +0x1d,0x12,0x3f,0xf7,0x12,0x4d,0xd0,0x68,0x5, 0xc2,0x1, 0x12,0x3b,0x4d,0x7e,0xb3, +0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1a,0x15,0xe4,0x12,0x4d,0xd8,0x20,0x93, +0xe0,0x12,0x3f,0xf7,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x74,0x2, 0x2, 0x4d,0xd8,0x22, +0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x1, 0x22,0x7c,0xab,0x7e,0xb3,0x3c,0x31,0xb4,0x81, +0x38,0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2, +0xaf,0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0, +0x2, 0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1, +0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3c,0x31,0x22,0x12, +0x3f,0xf7,0x12,0x4e,0x3f,0x75,0xcd,0x0, 0xc2,0xce,0x12,0xcf,0x24,0x12,0x3f,0x66, +0x74,0x1, 0x12,0x4d,0xd8,0xd2,0xce,0xe5,0x25,0x7e,0x71,0x24,0x2, 0x3f,0x7, 0x12, +0x4d,0xd0,0x68,0xfb,0x20,0x93,0xfd,0x22,0x12,0x4b,0x3a,0x7e,0x73,0x3a,0x7f,0xbe, +0x70,0xff,0x68,0x13,0xbe,0x73,0x3a,0xa5,0x68,0xd, 0x7a,0x73,0x3a,0xa5,0x74,0xff, +0x7a,0xb3,0x3a,0x7f,0x2, 0x4b,0x3a,0x22,0x7d,0x13,0x7e,0x54,0x62,0x6f,0x12,0x4f, +0xac,0x50,0x21,0x7e,0x54,0x62,0x71,0x12,0x4f,0xac,0x28,0x18,0x7e,0x14,0x62,0x73, +0x12,0x4e,0x97,0xbd,0x32,0x50,0xd, 0x7e,0x14,0x62,0x75,0x12,0x4e,0x97,0xbd,0x32, +0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x22,0xca, +0xf8,0x7e,0xa3,0x28,0xf4,0x7e,0xb3,0x28,0xf5,0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0, +0x1, 0x38,0x1c,0x7e,0x47,0x27,0x5a,0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e, +0xf3,0x2e,0x5e,0x4c,0xff,0x68,0x17,0x7e,0x47,0x2a,0x95,0x4d,0x44,0x78,0xf, 0x12, +0xce,0xb8,0x74,0x1, 0x7a,0xb3,0x3b,0x95,0x7a,0xb3,0x3a,0xa5,0x80,0x35,0x4c,0xaa, +0x78,0x36,0xb4,0x1, 0x33,0x7e,0x37,0x2a,0x95,0x7a,0x37,0x2e,0x60,0x7e,0xb3,0x2e, +0x5e,0xb4,0x3, 0x1f,0x7e,0x37,0x2a,0x95,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, +0x7a,0xb3,0x2e,0x5e,0x7e,0x37,0x2e,0x76,0x7e,0x27,0x2e,0x78,0x12,0x4f,0xba,0xe1, +0xa9,0x80,0x0, 0x12,0xcd,0xd3,0xe1,0xa9,0x7e,0xc7,0x27,0xdc,0x7e,0xd7,0x27,0xde, +0x4c,0xff,0x78,0x19,0x70,0x57,0xbe,0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12, +0xcd,0x6e,0x12,0x4f,0xb6,0x74,0x1, 0x7a,0xb3,0x2e,0x5e,0x80,0x40,0xbe,0xf0,0x1, +0x78,0x2e,0x7e,0x27,0x2e,0x66,0x9e,0x27,0x2e,0x6e,0x7e,0x14,0x62,0xa1,0x12,0x4e, +0x97,0xbd,0x23,0x38,0x13,0x7e,0x27,0x2e,0x74,0x9e,0x27,0x2e,0x6c,0x7e,0x14,0x62, +0xa3,0x12,0x4e,0x97,0xbd,0x23,0x28,0x15,0x74,0x3, 0x7a,0xb3,0x2e,0x5e,0x80,0x5, +0xbe,0xf0,0x3, 0x78,0x8, 0x7a,0xc7,0x2e,0x76,0x7a,0xd7,0x2e,0x78,0x7e,0xb3,0x2e, +0x5e,0x60,0x26,0x7d,0x3c,0x7d,0x2d,0x7e,0x17,0x2a,0x99,0x7e,0x7, 0x2a,0x9b,0x12, +0xcd,0x52,0xa, 0x2b,0x7e,0x73,0x2e,0x5d,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x4f, +0xb6,0x7a,0xc7,0x2a,0x99,0x7a,0xd7,0x2a,0x9b,0xda,0xf8,0x22,0x7e,0x44,0x0, 0xff, +0xb, 0x2a,0x30,0xbd,0x31,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42,0x7d,0x13,0x7d,0x24, +0x12,0xcd,0x2d,0x7d,0x31,0x12,0xcc,0x31,0x2, 0x4f,0xcb,0x7e,0x3, 0x2e,0x86,0xbe, +0x0, 0xf0,0x50,0x3, 0x2, 0x50,0x62,0x80,0x7d,0x6c,0x99,0x7e,0xb3,0x2e,0x5d,0xbe, +0xb0,0x20,0x50,0x5, 0x4, 0x7a,0xb3,0x2e,0x5d,0x7e,0x1f,0x2a,0x9d,0x7a,0x1f,0x1e, +0x44,0x7e,0x80,0x1, 0x80,0x45,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2a,0x9d,0x49,0x25, +0x2a,0x9f,0x7e,0x17,0x1e,0x44,0x7e,0x7, 0x1e,0x46,0x12,0xcd,0x52,0x7c,0x1b,0x7e, +0x3, 0x2e,0x5d,0xbc,0x1, 0x38,0x22,0xb, 0x90,0x7e,0x70,0x4, 0xac,0x78,0x2e,0x34, +0x2a,0x9d,0x7e,0x14,0x1e,0x44,0x74,0x4, 0x12,0x50,0x63,0x7e,0x30,0x4, 0xac,0x39, +0x2e,0x14,0x2a,0x9d,0x74,0x4, 0x12,0x17,0xb9,0xb, 0x80,0x7e,0x3, 0x2e,0x86,0xbc, +0x8, 0x38,0xb3,0xa, 0x59,0xb, 0x54,0x7c,0xb, 0x7a,0x3, 0x2e,0x86,0x7e,0x3, 0x2e, +0x5d,0xbe,0x0, 0x20,0x50,0xc, 0x7e,0x3, 0x2e,0x86,0xbe,0x0, 0xec,0x40,0x3, 0x2, +0x4f,0xd9,0x22,0x12,0x17,0xb9,0x7e,0x34,0x1e,0x44,0x22,0xca,0x3b,0x7e,0x90,0x1, +0x7e,0xb3,0x28,0xf4,0xf5,0x2a,0x75,0x2b,0x0, 0x75,0x2c,0x0, 0x70,0x30,0x7e,0xf1, +0x2a,0x80,0x26,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x27,0x86,0x6d,0x22,0x74,0x2, +0xac,0xbf,0x59,0x25,0x32,0xf1,0x74,0xff,0x19,0xb3,0x32,0x9b,0x19,0xb3,0x33,0x13, +0xe4,0xa, 0x3f,0x19,0xb3,0x33,0x69,0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xd5,0xe5,0x1c, +0x60,0xb, 0x7e,0xa1,0x1c,0x74,0x14,0xa4,0xf5,0x2b,0x75,0x2c,0x14,0x7e,0xa3,0x3a, +0xf, 0x4c,0xaa,0x68,0x9, 0x75,0x2c,0x14,0xe5,0x2b,0x24,0x28,0xf5,0x2b,0xe5,0x1c, +0x70,0x1e,0x4c,0xaa,0x78,0x1a,0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x6, 0xe5,0x2b,0x1e, +0xb0,0xf5,0x2b,0xe5,0x2c,0xbe,0xb0,0x0, 0x28,0x6, 0xe5,0x2c,0x1e,0xb0,0xf5,0x2c, +0x75,0x1c,0x0, 0x6c,0xff,0x74,0x9, 0xac,0xbf,0x9, 0xe5,0x27,0x86,0x5e,0xe0,0xf, +0xbe,0xe0,0xa, 0x40,0x2, 0x61,0xf6,0xa, 0x3e,0x9, 0xa3,0x28,0x90,0x4c,0xaa,0x78, +0x17,0x74,0x1, 0x19,0xb3,0x33,0x69,0x19,0xb3,0x33,0x5, 0x6d,0x22,0x7e,0x30,0x2, +0xac,0x3e,0x59,0x21,0x32,0xf1,0x61,0xf6,0xbe,0xa0,0x1, 0x78,0x2, 0x61,0xd0,0x9, +0xb3,0x33,0x69,0xbe,0xb0,0x14,0x50,0x8, 0x2e,0x34,0x33,0x69,0x4, 0x7a,0x39,0xb0, +0x75,0x24,0x0, 0x12,0x57,0x80,0x9, 0x83,0x32,0x9b,0x7a,0x81,0x29,0xbc,0x8e,0x68, +0x2, 0x61,0xc3,0x49,0x23,0x32,0x97,0x74,0x9, 0xac,0xbf,0x12,0x7e,0x32,0x7a,0x35, +0x25,0x12,0x2d,0x5d,0x49,0x25,0x32,0x99,0x12,0x57,0x9a,0x9d,0x32,0x12,0x1a,0x62, +0x7a,0x35,0x27,0x7d,0x63,0x2e,0x65,0x25,0x7e,0x35,0x25,0xbe,0x34,0x0, 0x50,0x50, +0x38,0xe5,0x2a,0xb4,0x1, 0x33,0x7e,0xb3,0x15,0xa2,0x70,0x2d,0x7e,0x35,0x27,0xbe, +0x34,0x0, 0xc8,0x28,0x24,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xb3,0x27,0x89,0x9, 0x73, +0x27,0x8a,0x12,0x57,0x68,0x8, 0x12,0x12,0x57,0x80,0x9, 0xb3,0x32,0x9e,0x9, 0x73, +0x32,0x9f,0x12,0x57,0x68,0x8, 0x2, 0x61,0x36,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xa3, +0x27,0x89,0x4c,0xaa,0x78,0x16,0x7e,0x51,0x24,0x74,0x9, 0xac,0x5b,0x9, 0x82,0x32, +0x9e,0x7e,0xb3,0x29,0x5c,0x14,0xbc,0x8b,0x78,0x2, 0x61,0x36,0x12,0x55,0x26,0x78, +0xb, 0x12,0x2d,0x5d,0x9, 0xb5,0x32,0x9e,0x70,0x2, 0x61,0x36,0x7e,0x31,0x29,0x74, +0x2, 0xac,0x3b,0x49,0x21,0x32,0xf1,0xbe,0x24,0x0, 0x14,0x28,0x13,0xe5,0x29,0xa, +0x2b,0x9, 0x82,0x33,0x69,0xbe,0x80,0xa, 0x50,0x6, 0x74,0xa, 0x19,0xb2,0x33,0x69, +0xbe,0x64,0x0, 0xa, 0x50,0x10,0xe5,0x29,0xa, 0x2b,0x2e,0x24,0x33,0x69,0x7e,0x29, +0x80,0x1e,0x80,0x7a,0x29,0x80,0xe5,0x29,0xa, 0x2b,0x9, 0xb2,0x33,0x5, 0xb4,0x1, +0x14,0xbe,0x64,0x2, 0xbc,0x50,0xe, 0x59,0x61,0x32,0xf1,0x2e,0x24,0x33,0x5, 0x14, +0x7a,0x29,0xb0,0x61,0xf6,0xbe,0x64,0x0, 0x64,0x28,0x52,0x75,0x2d,0x0, 0x7e,0xa1, +0x2d,0x74,0x9, 0xa4,0x9, 0x85,0x33,0x13,0xbe,0x81,0x29,0x68,0x9, 0x5, 0x2d,0xe5, +0x2d,0xbe,0xb0,0xa, 0x40,0xe8,0x7e,0x51,0x2d,0x74,0x9, 0xac,0x5b,0x9, 0xb2,0x33, +0x13,0xbe,0xb0,0xff,0x68,0x2a,0x49,0x33,0x27,0x82,0x7a,0x35,0x2e,0x12,0x57,0x9a, +0x7a,0x35,0x30,0x49,0x32,0x33,0xf, 0x49,0x22,0x33,0x11,0x12,0x2d,0x5d,0x49,0x15, +0x32,0x97,0x49,0x5, 0x32,0x99,0x12,0x54,0x33,0x7c,0x9b,0x80,0x3, 0x7e,0x90,0x1, +0x4c,0x99,0x78,0x2, 0x61,0x36,0x7e,0xb3,0x28,0xfb,0xbe,0xb0,0x1, 0x78,0x2, 0x61, +0xf6,0x7e,0x51,0x29,0x74,0x2, 0xac,0x5b,0x49,0x32,0x32,0xf1,0x7d,0x13,0x2e,0x14, +0x1, 0x5e,0xbd,0x16,0x38,0xa, 0x7d,0x13,0x3e,0x14,0x3e,0x14,0xbd,0x16,0x28,0x32, +0xbe,0x34,0x0, 0x32,0x28,0xc, 0xbe,0x64,0x0, 0x32,0x28,0x6, 0x59,0x62,0x32,0xf1, +0x61,0xf6,0x7d,0x3, 0x2e,0x4, 0x0, 0x50,0xe5,0x2b,0xa, 0x1b,0x2d,0x10,0xbd,0x16, +0x50,0x10,0xe5,0x2c,0xa, 0x1b,0x7e,0x24,0x0, 0x50,0x9d,0x21,0xbd,0x32,0x28,0x2, +0x61,0xb7,0x7e,0x83,0x15,0xa2,0xbe,0x80,0x0, 0x28,0x2, 0x61,0xf6,0xbe,0x64,0x0, +0xe6,0x38,0x23,0xbe,0x34,0x0, 0xa, 0x50,0x6, 0xbe,0x64,0x0, 0x96,0x38,0x17,0xe5, +0x29,0xa, 0x3b,0x9, 0x83,0x33,0x69,0xbe,0x80,0x5, 0x40,0x2, 0x61,0xb7,0xbe,0x64, +0x0, 0x6e,0x38,0x2, 0x61,0xb7,0x74,0x1, 0xa, 0x3e,0x19,0xb3,0x28,0x90,0x7e,0xa0, +0x3, 0xe5,0x29,0xa, 0x3b,0x19,0xa3,0x28,0x9a,0x6c,0xaa,0xe5,0x29,0xa, 0x3b,0x19, +0xa3,0x33,0x69,0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x4f,0x15,0x2a,0x7e,0x70,0x9, 0xac, +0x7f,0x2e,0x34,0x27,0x82,0x7e,0x14,0x1e,0x44,0x74,0x9, 0x12,0x17,0xb9,0x7e,0x71, +0x2a,0x74,0x9, 0xac,0x7b,0x2e,0x34,0x27,0x82,0x12,0xce,0xe4,0x12,0x50,0x63,0x7e, +0x31,0x2a,0x74,0x9, 0xac,0x3b,0x2e,0x14,0x27,0x82,0x12,0x17,0xb9,0xe5,0x2a,0x7a, +0xb3,0x3b,0xd1,0x7e,0x34,0x7f,0xff,0x74,0x2, 0xac,0xbe,0x59,0x35,0x28,0xa4,0x74, +0x2, 0xac,0xbe,0x59,0x35,0x28,0xb8,0x1b,0xf0,0x6d,0x33,0x7e,0xa1,0x29,0x74,0x2, +0xa4,0x59,0x35,0x32,0xf1,0x80,0x3f,0x7e,0xa1,0x29,0x74,0x2, 0xa4,0x59,0x65,0x32, +0xf1,0x80,0x33,0x5, 0x24,0xe5,0x24,0xbe,0xb0,0xa, 0x50,0x2, 0x21,0x43,0x80,0x26, +0xe4,0xa, 0x3e,0x19,0xb3,0x33,0x69,0x6d,0x33,0x74,0x2, 0xac,0xbe,0x59,0x35,0x32, +0xf1,0x7e,0xa0,0xff,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x32,0x9b,0x7e,0x70,0x9, +0xac,0x7f,0x19,0xa3,0x33,0x13,0xb, 0xf0,0xbe,0xf0,0xa, 0x50,0x2, 0x1, 0xf5,0xe4, +0x7a,0xb3,0x15,0xa2,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x32,0x97,0x7e,0x8, +0x33,0xf, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x27, +0x82,0x7e,0x8, 0x32,0x97,0x12,0x1a,0xb, 0x1b,0xfd,0xe5,0x2a,0x7a,0xb3,0x28,0xf4, +0xda,0x3b,0x22,0xca,0x3b,0x7d,0xf0,0x7d,0x41,0x7d,0xe2,0x7d,0xd3,0x7e,0x75,0x2e, +0x7e,0x65,0x30,0x75,0x3e,0x1, 0x7d,0x1e,0x1a,0x2, 0x1a,0x0, 0x7d,0x3f,0x12,0x55, +0x14,0x7f,0x51,0x7d,0x1d,0x1a,0x2, 0x1a,0x0, 0x7d,0x34,0x12,0x55,0x14,0x2f,0x15, +0x7a,0x1d,0x32,0x12,0x55,0x1f,0x7d,0x36,0x12,0x55,0x14,0x7f,0x51,0x12,0x55,0xc, +0x2f,0x15,0x7a,0x1d,0x36,0x9d,0x74,0x9d,0x6f,0x9d,0x4d,0x9d,0xfe,0x12,0x55,0x1f, +0x7d,0x36,0x12,0x55,0x14,0x7f,0x71,0x12,0x55,0xc, 0x7f,0x21,0x2f,0x27,0x7e,0xd, +0x36,0x7e,0x1d,0x32,0x2f,0x1, 0x9f,0x2, 0x7a,0xd, 0x3a,0x12,0x57,0x5d,0x7a,0x1d, +0x32,0x7e,0x1d,0x36,0x12,0x57,0x5d,0x7a,0x1d,0x36,0x7e,0x7d,0x36,0xbe,0x78,0x0, +0x32,0x58,0x4, 0x74,0x1, 0x80,0x52,0x7e,0x1d,0x32,0x7f,0x7, 0x12,0x17,0x18,0x7f, +0x21,0x2f,0x22,0x7e,0x14,0x0, 0x64,0x7e,0x1d,0x3a,0x12,0x17,0x29,0x7f,0x2, 0x12, +0x17,0x85,0x7a,0x1d,0x3a,0xbe,0x18,0x0, 0x64,0x8, 0x9, 0x7e,0x8, 0x0, 0x64,0x7a, +0xd, 0x3a,0x80,0xd, 0xbe,0x1c,0xff,0x9c,0x58,0x7, 0x7e,0x1c,0xff,0x9c,0x7a,0x1d, +0x3a,0x7e,0x1d,0x3a,0xbe,0x18,0x0, 0x57,0x58,0xd, 0x2e,0x18,0x0, 0xa0,0x2f,0x11, +0xbf,0x71,0x8, 0x3, 0x75,0x3e,0x0, 0xe5,0x3e,0xda,0x3b,0x22,0x7d,0x14,0x1a,0x2, +0x1a,0x0, 0x7d,0x37,0x1a,0x26,0x1a,0x24,0x9f,0x10,0x7f,0x1, 0x2, 0x17,0x18,0x7d, +0x1f,0x1a,0x2, 0x1a,0x0, 0x22,0x7e,0xb3,0x29,0x5c,0x14,0xbc,0xab,0x22,0xca,0x79, +0x7e,0xc4,0x0, 0x7, 0x7e,0xb3,0x27,0x58,0x70,0x20,0x6d,0xcc,0x7a,0xc7,0x38,0xfe, +0x7a,0xc7,0x38,0xfc,0xc2,0x14,0x7e,0x8, 0x39,0x0, 0x7e,0x34,0x0, 0x4, 0x74,0xff, +0x12,0x1a,0x30,0xe4,0x7a,0xb3,0x38,0xfb,0xe1,0x1e,0x12,0x57,0x70,0x38,0x2, 0xc1, +0x6a,0x6c,0xee,0xc1,0x15,0x6c,0xff,0xc1,0x9, 0x12,0x57,0x21,0xa, 0x27,0xa, 0x3e, +0x9, 0x73,0x39,0x0, 0x12,0x57,0x2c,0x18,0x7d,0x12,0x57,0x3a,0xa, 0x27,0xa, 0x3e, +0x9, 0x73,0x39,0x2, 0x12,0x57,0x2c,0x18,0x6d,0x12,0x86,0x19,0x58,0x4, 0x7e,0xc4, +0x0, 0x6, 0x12,0x57,0x47,0x68,0x5, 0x12,0x55,0x26,0x78,0x4, 0x7e,0xc4,0x0, 0x6, +0xbd,0xc4,0x58,0x18,0x7e,0x34,0x1, 0x90,0x74,0x2, 0xac,0xbe,0x12,0x57,0x43,0x68, +0x5, 0x12,0x55,0x26,0x78,0x13,0x7e,0x34,0x3, 0x20,0x80,0xa, 0x7d,0x5c,0x1b,0x55, +0xbd,0x54,0x48,0x5, 0x6d,0x33,0x12,0x57,0x88,0x7e,0x70,0x2, 0xac,0x7e,0x49,0x53, +0x38,0xfc,0xbe,0x54,0x0, 0x0, 0x28,0x19,0x2e,0x34,0x38,0xfc,0x1b,0x54,0x1b,0x38, +0x50,0x12,0x57,0x21,0xa, 0x5e,0x12,0x57,0x36,0xa, 0x5e,0x19,0x75,0x39,0x2, 0x80, +0x22,0x12,0xce,0x5f,0x80,0x1d,0x7e,0xb3,0x27,0x58,0x14,0xbc,0xbf,0x78,0x8, 0x6d, +0x33,0x12,0x57,0x88,0x12,0xce,0x5f,0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x28, +0x2, 0xa1,0x69,0xb, 0xe0,0x7e,0x73,0x38,0xfb,0xbc,0x7e,0x28,0x2, 0xa1,0x65,0x7e, +0x57,0x38,0xfc,0x4d,0x55,0x78,0x29,0x12,0x57,0x91,0x28,0x24,0x7a,0x57,0x38,0xfc, +0x7e,0x73,0x39,0x1, 0x7a,0x73,0x39,0x0, 0x7e,0x73,0x39,0x3, 0x7a,0x73,0x39,0x2, +0x6d,0x55,0x7a,0x57,0x38,0xfe,0x74,0xff,0x7a,0xb3,0x39,0x1, 0x7a,0xb3,0x39,0x3, +0xe4,0x7a,0xb3,0x38,0xfb,0x7e,0x57,0x38,0xfc,0xbe,0x54,0x0, 0x0, 0x28,0x3, 0x12, +0x57,0x53,0x12,0x57,0x91,0x28,0x3, 0x12,0x57,0x53,0x7e,0x73,0x38,0xfb,0xbe,0x70, +0x2, 0x40,0x2, 0xe1,0xa, 0x7e,0x73,0x27,0x58,0xbe,0x73,0x38,0xfb,0x38,0x2, 0xe1, +0xa, 0x6c,0xff,0x80,0x7b,0x12,0x57,0x21,0xa, 0x27,0x7e,0x73,0x39,0x0, 0xa, 0x37, +0x12,0x57,0x2c,0x18,0x10,0x12,0x57,0x3a,0xa, 0x27,0x7e,0x73,0x39,0x2, 0xa, 0x37, +0x12,0x57,0x2c,0x8, 0x59,0x12,0x86,0x19,0x58,0x4, 0x7e,0xc4,0x0, 0x6, 0x12,0x57, +0x47,0x68,0x5, 0x12,0x55,0x26,0x78,0x4, 0x7e,0xc4,0x0, 0x5, 0xbd,0xc4,0x58,0x35, +0x7e,0x34,0x1, 0x90,0x12,0x57,0x78,0x12,0x57,0x43,0x68,0x5, 0x12,0x55,0x26,0x78, +0xb, 0x7e,0x34,0x3, 0x20,0x12,0x57,0x78,0x59,0x35,0x38,0xfc,0x12,0x57,0x21,0x7e, +0x63,0x38,0xfb,0xa, 0x56,0x12,0x57,0x36,0x7e,0x63,0x38,0xfb,0xa, 0x56,0x19,0x75, +0x39,0x2, 0x12,0x57,0x53,0x7e,0xb3,0x38,0xfb,0xbe,0xb0,0x2, 0x68,0xc, 0xb, 0xf0, +0x7e,0x73,0x27,0x58,0xbc,0x7f,0x28,0x2, 0xc1,0x85,0x12,0x57,0x70,0x28,0xd, 0x20, +0x14,0xc, 0xd2,0x14,0x74,0x14,0x7a,0xb3,0x32,0x3d,0x80,0x2, 0xc2,0x14,0xda,0x79, +0x22,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x25,0xce,0x22,0x1a,0x3b,0x9d,0x32,0x12,0x1a, +0x62,0xbe,0x34,0x0, 0x1, 0x22,0x19,0x75,0x39,0x0, 0x74,0x2, 0xac,0xbf,0x9, 0x75, +0x25,0xcf,0x22,0x59,0x35,0x38,0xfc,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xa3,0x25,0xce, +0x4c,0xaa,0x22,0x7e,0xb3,0x38,0xfb,0x4, 0x7a,0xb3,0x38,0xfb,0x22,0x7c,0xb4,0x12, +0x15,0xa, 0x12,0x15,0x84,0x2, 0x15,0x47,0x12,0x21,0x5e,0xbe,0x34,0x0, 0x96,0x22, +0x7e,0x73,0x38,0xfb,0xbe,0x70,0x0, 0x22,0x7e,0xa3,0x38,0xfb,0x74,0x2, 0xa4,0x22, +0x7e,0x71,0x24,0x74,0x9, 0xac,0x7b,0x22,0x74,0x2, 0xac,0xbe,0x59,0x35,0x38,0xfc, +0x22,0x7e,0x57,0x38,0xfe,0xbe,0x54,0x0, 0x0, 0x22,0x74,0x9, 0xac,0xbf,0x49,0x35, +0x27,0x84,0x22,0x7e,0xb3,0x3a,0xd0,0x70,0x3, 0x12,0x50,0x6b,0x2, 0x57,0xaf,0xca, +0x79,0x7e,0xf3,0x28,0xf4,0x7e,0xe3,0x28,0xf5,0x7c,0xbf,0x7c,0x7e,0x12,0x2e,0x73, +0x7c,0xbf,0x12,0x9d,0x65,0x4c,0xee,0x78,0x15,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e, +0x18,0x27,0x82,0x7e,0x8, 0x28,0x36,0x12,0x1a,0xb, 0x1b,0xfd,0x80,0xb, 0x7e,0xb3, +0x28,0xfb,0x70,0x5, 0x7c,0xbf,0x12,0x7d,0xac,0x7c,0xbf,0x12,0x9f,0x34,0xbe,0xf0, +0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xfd,0xda,0x79,0x22,0x6c,0x55,0x7e,0x63, +0x27,0x67,0xbe,0x60,0x3, 0x40,0x61,0x6c,0x44,0x6c,0x77,0x7e,0xa0,0xff,0x7e,0x30, +0xff,0x6c,0x22,0x80,0x27,0x7e,0x10,0x2, 0xac,0x12,0x9, 0xb0,0x25,0xce,0xbc,0xb7, +0x28,0x2, 0x7c,0x7b,0xbc,0xba,0x50,0x2, 0x7c,0xab,0x9, 0xb0,0x25,0xcf,0xbc,0xb4, +0x28,0x2, 0x7c,0x4b,0xbc,0xb3,0x50,0x2, 0x7c,0x3b,0xb, 0x20,0x7e,0xb3,0x27,0x58, +0xbc,0xb2,0x38,0xd1,0xa, 0x3, 0xb, 0x5, 0xa, 0x14,0xbd,0x10,0x18,0x11,0xa, 0xa, +0x2e,0x4, 0x0, 0x6, 0xa, 0x17,0xbd,0x10,0x48,0x5, 0x7e,0x50,0x64,0x80,0x10,0xbe, +0x50,0x0, 0x28,0xb, 0x1b,0x50,0x80,0x7, 0xbe,0x50,0x0, 0x28,0x2, 0x1b,0x50,0xbe, +0x50,0x0, 0x28,0x4, 0xd2,0xe, 0x80,0x2, 0xc2,0xe, 0x7a,0x63,0x27,0x68,0x7e,0x63, +0x28,0xf4,0x7a,0x63,0x28,0xf5,0xe4,0x7a,0xb3,0x28,0xf8,0x22,0x7e,0x37,0x3c,0x17, +0xb, 0x34,0x7a,0x37,0x3c,0x17,0x7e,0x37,0x3c,0x19,0xbe,0x37,0x3c,0x17,0x28,0x3, +0x2, 0x58,0xa7,0x22,0x2, 0x58,0x8c,0xe5,0x9a,0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf, +0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0, +0xd0,0xc0,0x83,0xc0,0x82,0x12,0x58,0xa4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, +0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x74,0xa, 0x7a, +0xb3,0x29,0x3a,0x74,0x10,0x7a,0xb3,0x29,0x3b,0x12,0x59,0x1e,0x7a,0x37,0x29,0x42, +0x74,0x28,0x7a,0xb3,0x29,0x46,0x12,0x5f,0x3c,0x7e,0x34,0x0, 0x64,0x7a,0x37,0x29, +0x4d,0xe4,0x7a,0xb3,0x29,0x51,0x74,0x4, 0x7a,0xb3,0x29,0x52,0x7a,0x37,0x29,0x53, +0x7e,0x34,0xa, 0x0, 0x7a,0x37,0x29,0x4f,0xe4,0x7a,0xb3,0x15,0xa2,0x22,0x7e,0x34, +0x0, 0xc8,0x7a,0x37,0x29,0x3c,0x7a,0x37,0x29,0x3e,0x7a,0x37,0x29,0x40,0x22,0x12, +0x5f,0x3c,0x2, 0x59,0x1e,0x12,0x59,0x2f,0x7e,0xb3,0x3a,0x8b,0xb4,0x1, 0x10,0x7e, +0x34,0x1, 0x2c,0x7a,0x37,0x29,0x47,0x7e,0x34,0x1, 0x18,0x7a,0x37,0x29,0x49,0x7e, +0xb3,0x27,0x7c,0xb4,0x1, 0x1b,0x7e,0x34,0x1, 0x90,0x7a,0x37,0x29,0x47,0x7e,0x24, +0x1, 0x2c,0x7a,0x27,0x29,0x49,0x7a,0x37,0x29,0x3c,0x7e,0x34,0x1, 0x7c,0x12,0x59, +0x26,0x7e,0xb3,0x28,0xf4,0x70,0x21,0x7e,0x27,0x29,0x47,0x7d,0x32,0x7e,0x14,0x0, +0x4, 0xad,0x13,0x7d,0x31,0x12,0x59,0x99,0xbe,0x34,0x0, 0x28,0x28,0x4, 0x7e,0x34, +0x0, 0x28,0x2d,0x32,0x7a,0x37,0x29,0x47,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e, +0x34,0x22,0x12,0x59,0x35,0xe4,0x7a,0xb3,0x3, 0xfd,0x2, 0x59,0xad,0xca,0x3b,0xe4, +0x7a,0xb3,0x27,0x67,0x12,0xca,0x99,0x7e,0xb3,0x15,0xa1,0xb4,0x1, 0x8, 0x7e,0x73, +0x27,0x58,0x7a,0x73,0x27,0x66,0x7e,0x18,0x4, 0xc0,0x7a,0x1f,0x6, 0x44,0x12,0xce, +0x2e,0x12,0x5b,0xf7,0x7e,0x73,0x25,0x59,0xbe,0x70,0x2, 0x50,0x2, 0x41,0x75,0x6c, +0xff,0x41,0x65,0xa, 0x5f,0xb, 0x54,0x7c,0xab,0x6c,0xee,0x80,0xc, 0xa, 0x3e,0x9, +0xb3,0x25,0x43,0xbc,0xbf,0x68,0xa, 0xb, 0xe0,0x7e,0xb3,0x25,0x59,0xbc,0xbe,0x38, +0xec,0x7e,0x33,0x25,0x59,0xbc,0x3e,0x68,0x5a,0x6c,0xee,0x80,0x12,0xa, 0x3e,0x9, +0x23,0x25,0x43,0xa, 0x22,0xa, 0x3f,0xb, 0x35,0xbd,0x23,0x68,0x6, 0xb, 0xe0,0xbc, +0x3e,0x38,0xea,0xbc,0x3e,0x78,0x4, 0xb, 0xf1,0x80,0x38,0x12,0x5d,0x83,0x7f,0x75, +0x1b,0xf5,0xb, 0x7a,0x30,0x7e,0xc4,0x0, 0x3, 0x12,0x5d,0x61,0xb, 0x5a,0x40,0xbd, +0x43,0x8, 0x20,0x69,0x5, 0x0, 0x2, 0x7d,0x30,0x12,0x5d,0x46,0xbd,0x43,0x8, 0x13, +0xb, 0x7a,0x40,0x2d,0x40,0x12,0x5b,0xeb,0xb, 0x1a,0x30,0x9d,0x43,0x12,0x5b,0xeb, +0x1b,0x1a,0x40,0xb, 0xf0,0x7e,0x23,0x29,0x5b,0xa, 0x22,0x1b,0x25,0xa, 0x3f,0xbd, +0x32,0x58,0x2, 0x21,0xe3,0x7e,0x73,0x25,0x58,0xbe,0x70,0x2, 0x50,0x2, 0x61,0x17, +0x6c,0xff,0x61,0xd, 0xa, 0x1f,0x7e,0x73,0x29,0x5b,0xa, 0x57,0x2d,0x51,0xb, 0x54, +0x7c,0xab,0x6c,0xee,0x80,0xc, 0xa, 0xe, 0x9, 0xb0,0x25,0x2f,0xbc,0xbf,0x68,0xa, +0xb, 0xe0,0x7e,0xb3,0x25,0x58,0xbc,0xbe,0x38,0xec,0x7e,0x13,0x25,0x58,0xbc,0x1e, +0x68,0x59,0x6c,0xee,0x80,0x12,0xa, 0x3e,0x9, 0x3, 0x25,0x2f,0xa, 0x20,0x7d,0x31, +0xb, 0x35,0xbd,0x23,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xea,0xbc,0x1e,0x78,0x4, +0xb, 0xf1,0x80,0x37,0x12,0x5d,0x83,0x7f,0x15,0x1b,0x35,0xb, 0x1a,0xf0,0x7e,0xc4, +0x0, 0x3, 0x7d,0x3f,0x12,0x5d,0x61,0xb, 0x5a,0xe0,0xbd,0xe3,0x8, 0x1d,0x69,0x45, +0x0, 0x2, 0x7d,0x34,0x12,0x5d,0x46,0xbd,0xe3,0x8, 0x10,0x2d,0x4f,0x12,0x5d,0x77, +0xb, 0x1a,0x30,0x9d,0x43,0x12,0x5d,0x77,0x1b,0x1a,0x40,0xb, 0xf0,0x7e,0x3, 0x29, +0x5a,0xbc,0xf, 0x28,0x2, 0x41,0x84,0x12,0x5b,0xf7,0x6c,0xff,0x80,0x43,0xa, 0x4f, +0x9, 0xb4,0x25,0x43,0x7c,0xab,0xbe,0xb0,0x2, 0x40,0x10,0x12,0x5d,0xdb,0x8, 0xb, +0x12,0x5d,0xc6,0x8, 0x6, 0x12,0x5f,0x2d,0x1b,0x1a,0x40,0xa, 0x3f,0x9, 0xb3,0x25, +0x43,0xa, 0x2b,0x7e,0xb3,0x29,0x5b,0xa, 0x3b,0x1b,0x35,0xbd,0x23,0x58,0x10,0x12, +0x5d,0xb1,0x8, 0xb, 0x12,0x5d,0x9f,0x8, 0x6, 0x12,0x5b,0xe7,0x1b,0x1a,0x10,0xb, +0xf0,0x7e,0xb3,0x25,0x59,0xbc,0xbf,0x38,0xb5,0x6c,0xff,0x80,0x4a,0xa, 0x4f,0x9, +0xb4,0x25,0x2f,0xa, 0x2b,0x12,0x77,0xaf,0x2d,0x32,0x7c,0xa7,0xbe,0xb0,0x2, 0x40, +0x10,0x12,0x5d,0xdb,0x8, 0xb, 0x12,0x5d,0xc6,0x8, 0x6, 0x12,0x5f,0x2d,0x1b,0x1a, +0x40,0xa, 0x3f,0x9, 0xb3,0x25,0x2f,0xa, 0x2b,0x7e,0xb3,0x29,0x5a,0xa, 0x3b,0x1b, +0x35,0xbd,0x23,0x58,0x10,0x12,0x5d,0xb1,0x8, 0xb, 0x12,0x5d,0x9f,0x8, 0x6, 0x12, +0x5b,0xe7,0x1b,0x1a,0x10,0xb, 0xf0,0x7e,0xb3,0x25,0x58,0xbc,0xbf,0x38,0xae,0x12, +0x5b,0xf7,0x12,0x64,0x53,0x7e,0xb3,0x15,0xa0,0xb4,0x1, 0x18,0x7e,0x73,0x25,0x57, +0x7a,0x73,0x25,0xc7,0x7e,0x73,0x25,0x59,0x7a,0x73,0x25,0xc9,0x7e,0x73,0x25,0x58, +0x7a,0x73,0x25,0xc8,0xda,0x3b,0x22,0x79,0x7, 0x0, 0x2, 0x7e,0x10,0x2, 0xac,0x1a, +0x7e,0x1f,0x6, 0x44,0x2d,0x30,0x22,0x7e,0x8, 0x25,0x5a,0x7e,0x34,0x0, 0x3, 0xe4, +0x12,0x1a,0x30,0x7e,0x8, 0x25,0x5d,0x7e,0x34,0x0, 0x3, 0x12,0x1a,0x30,0x7a,0xb3, +0x25,0x57,0x7a,0xb3,0x25,0x58,0x7a,0xb3,0x25,0x59,0x7a,0xb3,0x25,0xc4,0x7a,0xb3, +0x25,0xc5,0x7a,0xb3,0x25,0xc6,0x7e,0x18,0x25,0x43,0x12,0x5d,0x8f,0x6c,0x55,0x12, +0x5c,0xbd,0x7a,0xb3,0x25,0x59,0x7e,0x18,0x25,0x2f,0x12,0x5d,0xf3,0x6c,0x55,0x12, +0x5c,0xbd,0x7a,0xb3,0x25,0x58,0x6c,0x77,0x80,0x14,0x12,0x5d,0x4d,0x60,0x5, 0x3e, +0x24,0x14,0x78,0xfb,0x12,0x5d,0x56,0x2e,0x24,0x25,0x5a,0x12,0x5d,0x6c,0x7e,0x63, +0x25,0x58,0xbc,0x67,0x38,0xe4,0x6c,0x77,0x80,0x14,0x12,0x5d,0x4d,0x60,0x5, 0x3e, +0x24,0x14,0x78,0xfb,0x12,0x5d,0x56,0x2e,0x24,0x25,0x5d,0x12,0x5d,0x6c,0x7e,0xa3, +0x25,0x59,0xbc,0xa7,0x38,0xe4,0x7e,0xb3,0x25,0x58,0xa4,0x7a,0xb3,0x25,0x57,0x7e, +0x18,0x25,0xba,0x12,0x5d,0x8f,0x7e,0x50,0x1, 0x12,0x5c,0xbd,0x7a,0xb3,0x25,0xc6, +0x7e,0x18,0x25,0xb0,0x12,0x5d,0xf3,0x7e,0x50,0x1, 0x12,0x5c,0xbd,0x7c,0xab,0x7a, +0xa3,0x25,0xc5,0x7e,0xb3,0x25,0xc6,0xa4,0x7a,0xb3,0x25,0xc4,0x22,0xca,0x69,0xca, +0xf8,0x7c,0x4b,0x6c,0xaa,0x6d,0xff,0x6c,0xff,0x80,0x70,0x7e,0xd0,0x2, 0xac,0xdf, +0x7f,0x60,0x2d,0xd6,0xb, 0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, +0xe4,0xbd,0x3e,0x58,0x54,0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80, +0x1b,0x7c,0xb4,0x14,0xbc,0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d, +0xff,0x80,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, +0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x19, +0xbd,0xfe,0x18,0x15,0xa, 0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0, +0x90,0x60,0x9b,0xe4,0x93,0xbc,0xba,0x28,0x6, 0xb, 0xf0,0xbc,0x4f,0x38,0x8c,0x7c, +0xba,0xda,0xf8,0xda,0x69,0x22,0xad,0x3c,0x7d,0x2d,0x2, 0x16,0xe6,0x7c,0xb7,0x54, +0x7, 0x7e,0x24,0x0, 0x1, 0x22,0x7c,0xa5,0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b, +0x22,0xad,0x3c,0x7e,0xd4,0x0, 0x4, 0x7d,0x2d,0x2, 0x16,0xe6,0x7e,0x29,0x60,0x4c, +0x6a,0x7a,0x29,0x60,0xb, 0x70,0x22,0x7e,0xd0,0x2, 0xac,0xda,0x7e,0x1f,0x6, 0x44, +0x2d,0x36,0x22,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0x5f,0x6, 0x44,0x2d,0xb3,0x22,0x7a, +0x1d,0x24,0x7e,0xf, 0x6, 0x44,0x7e,0xb3,0x29,0x5b,0x7e,0x37,0x29,0x40,0x22,0x69, +0x17,0x0, 0x2, 0x7e,0x24,0x0, 0xa, 0x7d,0x31,0x12,0x16,0xe6,0x2d,0x31,0xbd,0x30, +0x22,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0x7f,0x6, 0x44,0x2d,0xf3,0xb, 0x7a,0x0, 0x69, +0x17,0x0, 0x4, 0xbd,0x10,0x22,0x1b,0x15,0xb, 0xa, 0x40,0x7e,0x24,0x0, 0xa, 0x7d, +0x34,0x12,0x16,0xe6,0x7d,0xe4,0x2d,0xe3,0xbd,0xef,0x22,0x7e,0x70,0x2, 0xac,0x7a, +0x7e,0xf, 0x6, 0x44,0x2d,0x13,0x7f,0x10,0x1b,0x36,0xb, 0x1a,0xe0,0xb, 0xa, 0xf0, +0xbd,0xef,0x22,0x7a,0x1d,0x24,0x7e,0xa3,0x29,0x5b,0x74,0x2, 0xa4,0x7e,0xf, 0x6, +0x44,0x2d,0x15,0x7e,0xb3,0x29,0x5a,0x7e,0x37,0x29,0x3e,0x22,0x7c,0x7b,0x12,0x5d, +0x5a,0x9, 0xa2,0x26,0x46,0x12,0x5e,0x7e,0x5c,0xba,0x22,0xca,0x79,0x6c,0xff,0x6c, +0xee,0x80,0x31,0x7c,0xbe,0x12,0x5e,0xc, 0x60,0x28,0x7e,0x34,0x0, 0x2, 0xca,0x39, +0xac,0x7e,0x2e,0x34,0x25,0xce,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x25, +0xce,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7c,0xbf,0x7e,0x70,0x1, 0x12,0x5f,0x5a, +0xb, 0xf0,0xb, 0xe0,0x12,0x5f,0xec,0x38,0xca,0x7a,0xf3,0x27,0x58,0xda,0x79,0x22, +0x7c,0x7b,0x12,0x5d,0x5a,0x9, 0xa2,0x25,0x5d,0x12,0x5e,0x7e,0x5c,0xba,0x22,0x7c, +0x7b,0x12,0x5d,0x5a,0x9, 0xa2,0x25,0x5a,0x12,0x5e,0x7e,0x5c,0xba,0x22,0x7c,0xb7, +0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93, +0x22,0xca,0xd8,0xca,0x79,0x6c,0xdd,0x6c,0xff,0x6c,0xee,0x80,0x30,0x7c,0xbe,0x12, +0x5e,0x6f,0x60,0x27,0x7e,0x34,0x0, 0x1, 0xca,0x39,0xa, 0x3e,0x2e,0x34,0x25,0x2f, +0x6d,0x22,0xa, 0x1d,0x2e,0x14,0x25,0x2f,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7c, +0xbd,0x7e,0x70,0x1, 0x6c,0x66,0x12,0x5f,0x88,0xb, 0xd0,0xb, 0xe0,0x7e,0x73,0x25, +0x58,0xbc,0x7e,0x38,0xc8,0x7a,0xd3,0x25,0x58,0x6c,0xee,0x80,0x31,0x7c,0xbe,0x12, +0x5e,0x60,0x60,0x28,0x7e,0x34,0x0, 0x1, 0xca,0x39,0xa, 0x3e,0x2e,0x34,0x25,0x43, +0x6d,0x22,0xa, 0x1f,0x2e,0x14,0x25,0x43,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7c, +0xbf,0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x5f,0x88,0xb, 0xf0,0xb, 0xe0,0x7e,0x73, +0x25,0x59,0xbc,0x7e,0x38,0xc7,0x7a,0xf3,0x25,0x59,0x7e,0x63,0x25,0x59,0x7e,0x73, +0x25,0x58,0xac,0x76,0x7a,0x73,0x25,0x57,0xda,0x79,0xda,0xd8,0x22,0x1b,0xa, 0xf0, +0x7e,0x30,0x2, 0xac,0x3a,0x7e,0x1f,0x6, 0x44,0x2d,0x31,0x22,0x7e,0x34,0x0, 0x96, +0x7a,0x37,0x29,0x47,0x7e,0x34,0x0, 0x82,0x7a,0x37,0x29,0x49,0x7e,0x34,0xff,0x6a, +0x7a,0x37,0x29,0x4b,0x22,0x7c,0xb3,0x7e,0x70,0x1, 0x12,0x5f,0xdd,0xa, 0x2b,0x2e, +0x24,0x0, 0x5e,0x12,0x71,0x43,0x7c,0x7b,0x4c,0x66,0x68,0x9, 0xa, 0x2a,0x2e,0x24, +0x26,0x46,0x2, 0x5f,0xd4,0x12,0x5f,0xcd,0x2e,0x24,0x26,0x46,0x2, 0x5f,0x7f,0x7e, +0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0x7c,0x56,0x12,0x5f,0xdd,0xa, 0x1b,0x2e, +0x14,0x0, 0x5e,0x12,0xcf,0x0, 0x7c,0x7b,0xa5,0xbd,0x0, 0x15,0x4c,0x66,0x68,0x8, +0xa, 0x2a,0x2e,0x24,0x25,0x5a,0x80,0x17,0x12,0x5f,0xcd,0x2e,0x24,0x25,0x5a,0x80, +0x18,0xa5,0xbd,0x1, 0x17,0x4c,0x66,0x68,0x9, 0xa, 0x2a,0x2e,0x24,0x25,0x5d,0x2, +0x5f,0xd4,0x12,0x5f,0xcd,0x2e,0x24,0x25,0x5d,0x12,0x5f,0x7f,0x22,0x7c,0xb7,0x64, +0xff,0xa, 0x2a,0x22,0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22,0x7c,0x67,0x7c, +0x7b,0xc4,0x23,0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x54,0x7, 0x22,0x7e,0x73,0x27,0x58, +0xbc,0x7e,0x22,0x7c,0xb9,0x6c,0x77,0x2, 0x5f,0x5a,0x74,0x1, 0x22,0xa2,0x16,0x22, +0x70,0x8f,0x0, 0xff,0x51,0xae,0x37,0xc8,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x34,0x42,0x31,0x1, 0xd1,0x53,0x34,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0xc, 0xf3,0x44,0x31,0x53,0x5f,0x68,0x75,0x61,0x78,0x69,0x6e,0x67,0x0, 0x0, 0x0, +0xd, 0x1b,0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11, +0x10,0xf, 0xe, 0x9, 0x1, 0xa, 0x2, 0xb, 0x3, 0xc, 0x4, 0xd, 0x5, 0x6, 0x7, 0x8, +0x0, 0x5, 0x0, 0x4, 0xff,0x14,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x28,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x19,0x1e,0x1, 0xf4,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x0, 0x4, 0x30,0x20,0x1, 0x20,0x2, 0x0, 0x0, +0x0, 0x0, 0x1, 0x90,0x40,0x40,0xd, 0x1b,0x28,0x11,0x10,0x6, 0x80,0x11,0x10,0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x49,0x49,0x2, 0x68,0x2, 0x7c,0x1, +0x52,0x1, 0x52,0x8, 0xe8,0x47,0x47,0x2, 0x4a,0x2, 0x36,0x1, 0x56,0x1, 0x57,0x0, +0x96,0x0, 0x82,0x0, 0x96,0x0, 0xc8,0x0, 0x64,0x0, 0xc8,0x0, 0xc8,0xa, 0x0, 0x0, +0xbe,0x6, 0x10,0x1e,0x32,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0xc, 0xf7,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x1, +0x0, 0x1, 0x54,0x1, 0x0, 0xc, 0x1, 0x51,0x1, 0x14,0x0, 0x37,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x96,0x2, 0x8a,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, +0xf0,0x0, 0x64,0x2, 0x58,0x0, 0xc8,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x2, 0x30,0x40, +0x20,0x13,0x2, 0x2d,0x40,0x20,0x2c,0x2, 0x34,0x40,0x20,0x32,0x2, 0x37,0x40,0x20, +0x1e,0x2, 0x30,0x40,0x20,0x1e,0x2, 0x30,0x40,0x20,0x1e,0x2, 0x30,0x40,0x20,0x1e, +0x2, 0x30,0x40,0x20,0x4, 0x5, 0x10,0x11,0x12,0x13,0x14,0x4, 0x0, 0x96,0x1, 0x90, +0x28,0x0, 0x78,0x1, 0x5e,0x0, 0x64,0x0, 0x64,0x0, 0x64,0x0, 0x64,0xb, 0xb8,0x8, +0x5, 0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20, +0x4, 0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, +0x90,0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, +0x50,0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x5, 0x0, +0x64,0x3, 0xd4,0x0, 0x50,0x8, 0x98,0x0, 0x23,0x1, 0xf4,0x1, 0xf4,0x3, 0x20,0x0, +0x14,0x0, 0x53,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x1, 0x1d,0x0, 0x3c,0x3, 0xe8,0x2, +0x3a,0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x8, 0xe8,0x0, +0x64,0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, +0x0, 0xc, 0xb, 0x5, 0x5, 0x8, 0x8, 0x6, 0x6, 0xc, 0x64,0xc8,0x7e,0x34,0x0, 0x4, +0xca,0x39,0x7e,0x34,0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x5d,0x12,0x1a, +0xb, 0x1b,0xfd,0x7e,0x34,0x29,0xa, 0x7a,0x37,0x2a,0x63,0xe4,0x7a,0xb3,0x2a,0x61, +0x7a,0xb3,0x2a,0x62,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x63,0xa, 0x7e,0x8, 0x24, +0xc2,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x2a,0x65,0x7a,0x37,0x24,0xc8,0xe4,0x7a, +0xb3,0x24,0xc6,0x74,0x1, 0x7a,0xb3,0x24,0xc7,0x22,0x7e,0x34,0x61,0x29,0x7e,0x24, +0x0, 0xff,0x22,0xe4,0x7a,0xb3,0x3a,0xf1,0x7a,0xb3,0x3a,0xf2,0x90,0x60,0x50,0x93, +0x7a,0xb3,0x3a,0xf3,0x90,0x60,0x51,0xe4,0x93,0x7a,0xb3,0x3a,0xf4,0xe4,0x7a,0xb3, +0x3a,0xf5,0x74,0xa, 0x7a,0xb3,0x3a,0xf6,0xe4,0x7a,0xb3,0x3a,0xf7,0x7a,0xb3,0x3a, +0xf8,0x74,0x1, 0x7a,0xb3,0x3a,0xfa,0x74,0x25,0x7a,0xb3,0x3a,0xfe,0x74,0x32,0x7a, +0xb3,0x3a,0xff,0x74,0x64,0x7a,0xb3,0x3b,0x10,0x74,0x4, 0x7a,0xb3,0x3b,0x11,0xe4, +0x7a,0xb3,0x3a,0xfd,0x74,0x30,0x7a,0xb3,0x3b,0x13,0x74,0x40,0x7a,0xb3,0x3b,0x12, +0x74,0x2, 0x7a,0xb3,0x3b,0x14,0x74,0x40,0x7a,0xb3,0x3b,0xf, 0xe4,0x7a,0xb3,0x3b, +0xa, 0x74,0xfa,0x7a,0xb3,0x3b,0x8, 0x74,0x1e,0x7a,0xb3,0x3b,0x9, 0x74,0x1, 0x7a, +0xb3,0x3b,0x7, 0x74,0xe, 0x7a,0xb3,0x3b,0x6, 0x74,0x1, 0x7a,0xb3,0x3b,0xb, 0xe4, +0x7a,0xb3,0x3b,0xc, 0x7a,0xb3,0x3b,0xd, 0x7e,0x8, 0x3b,0x15,0x7e,0x34,0x0, 0x2c, +0x12,0x1a,0x30,0x74,0x1, 0x7a,0xb3,0x3b,0x20,0x74,0xf4,0x7a,0xb3,0x3b,0x21,0x74, +0x19,0x7a,0xb3,0x3b,0x22,0x74,0x1e,0x7a,0xb3,0x3b,0x23,0x7e,0x34,0x0, 0x4, 0xca, +0x39,0x12,0x63,0xa, 0x7e,0x8, 0x3b,0x31,0x12,0x1a,0xb, 0x1b,0xfd,0x74,0x5, 0x7a, +0xb3,0x3b,0x3e,0x74,0x1, 0x7a,0xb3,0x3b,0x35,0x7e,0x34,0x0, 0x28,0xca,0x39,0x7e, +0x34,0x61,0xec,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x25,0x7, 0x12,0x1a,0xb, 0x1b,0xfd, +0x22,0x6d,0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2,0x29,0xc9,0x54,0x1, 0x78, +0x5, 0x4e,0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x29,0x61,0xbc, +0x5a,0x38,0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2,0x29,0xa6,0xbe,0xb0,0xd, +0x38,0x5, 0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60,0x8, 0x80, +0x3, 0x4e,0x60,0x50,0xb, 0xa0,0x12,0x64,0x4c,0x38,0xdc,0x22,0x7e,0xb3,0x29,0x60, +0xbc,0xba,0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab,0x7d,0x8b,0x6d,0x22,0x7d, +0x32,0x7d,0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, 0xc0,0x7e,0x8, 0x5, 0x20, +0xe4,0x7a,0xb3,0x7, 0x18,0x7a,0xb3,0x7, 0x19,0x7a,0xb3,0x25,0xca,0x7a,0xb3,0x25, +0xcc,0x7a,0xb3,0x25,0xcb,0x7a,0xb3,0x25,0xcd,0x6c,0xaa,0x80,0x5f,0x12,0x65,0xc8, +0xb, 0x6a,0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3,0x8, 0x2, 0x7d,0x3c,0x2d, +0x71,0x7d,0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d,0x9d,0x7e,0x67,0x29,0x40, +0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, 0x24,0x12,0x65,0xb5,0xb, +0x3a,0xd0,0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x25,0xcb,0x4, 0x7a,0xb3,0x25,0xcb,0x80, +0x19,0x12,0x65,0xbe,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff,0xb, 0xd4,0xbd,0xcd,0x58, +0x9, 0x7e,0xb3,0x25,0xcd,0x4, 0x7a,0xb3,0x25,0xcd,0xb, 0xa0,0x7e,0xb3,0x29,0x61, +0xbc,0xba,0x38,0x99,0x7a,0xa7,0x7, 0xe, 0x7a,0x37,0x7, 0x12,0xe5,0x24,0x7a,0xb3, +0x7, 0x19,0x7a,0x97,0x7, 0x16,0x12,0x65,0xad,0x2d,0xf5,0x6c,0xaa,0x80,0x50,0x12, +0x65,0xc8,0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d,0xbd,0xd2,0x8, 0x2, 0x7d, +0x2d,0x7e,0x67,0x29,0x3e,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xd7,0x8, 0x2, 0xb, +0x90,0x12,0x65,0xb5,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, 0x7e,0xb3,0x25,0xca,0x4, +0x7a,0xb3,0x25,0xca,0x80,0x17,0x12,0x65,0xbe,0xb, 0x3a,0xd0,0x6d,0x99,0x9d,0x9c, +0xbd,0xd9,0x58,0x9, 0x7e,0xb3,0x25,0xcc,0x4, 0x7a,0xb3,0x25,0xcc,0xb, 0xa0,0x12, +0x64,0x4c,0x38,0xab,0x7a,0x87,0x7, 0xc, 0x7a,0x27,0x7, 0x10,0x7a,0x93,0x7, 0x18, +0x12,0x65,0xad,0x2d,0x15,0x6c,0xaa,0x80,0x14,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70, +0x2d,0xf4,0xb, 0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x64,0x4c, +0x38,0xe7,0x7a,0xb7,0x7, 0x14,0xbd,0x8a,0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0x8, +0xbd,0x32,0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xa, 0xda,0x3b,0x22,0x7e,0xa3,0x29, +0x61,0x74,0x2, 0xa4,0x22,0x7e,0x74,0x62,0x27,0x7e,0x64,0x0, 0xff,0x22,0x7e,0xf0, +0x2, 0xac,0xfa,0x2d,0x7f,0x7d,0x6e,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x7f,0x67,0x2d, +0xd7,0x22,0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e, +0xd, 0x24,0x7f,0x13,0x12,0x66,0x6a,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x65,0xad, +0x7e,0xd, 0x24,0x2d,0x15,0x7f,0x13,0x2d,0x35,0x12,0x67,0x5d,0xda,0x3b,0x22,0x7e, +0x37,0x29,0x3c,0x1e,0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xc0,0x7e,0x18,0x4, 0x0, +0x12,0x65,0xd2,0x7e,0x37,0x27,0x6d,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x20, +0x7e,0x18,0x4, 0x60,0x12,0x65,0xd2,0x12,0x66,0x3e,0x2, 0x66,0x2d,0xe4,0x7a,0xb3, +0x3, 0xfe,0x7e,0xb3,0x27,0x7c,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xfe,0x22,0xca,0x3b, +0x7e,0xf3,0x29,0x5b,0x7e,0xe3,0x29,0x5c,0x7e,0xd3,0x29,0x5d,0x6c,0xcc,0x80,0x13, +0x7c,0x7c,0xac,0x7f,0x3e,0x34,0x7e,0xf, 0x12,0x9a,0x2d,0x13,0x7c,0xbd,0x12,0xa3, +0xb8,0xb, 0xc0,0xbc,0xec,0x38,0xe9,0xda,0x3b,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50, +0x7e,0x73,0x29,0x5b,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x1a, +0xb, 0x1b,0xfd,0x6c,0xdd,0x12,0x67,0x1f,0x7a,0xb3,0x1e,0x7c,0x6c,0xcc,0x80,0x45, +0x12,0x67,0xe, 0x78,0x3e,0x12,0x67,0x27,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x1a,0x62, +0x7d,0x13,0x7d,0x3e,0x12,0x1a,0x62,0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f, +0x8, 0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, +0x7d,0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1e,0x7c,0x4, 0x7a, +0xb3,0x1e,0x7c,0xb, 0xc0,0x7e,0x73,0x29,0x5d,0xbc,0x7c,0x38,0xb3,0x7e,0x73,0x1e, +0x7c,0x4c,0x77,0x68,0x1d,0x12,0x67,0x45,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80,0xa, +0x12,0x67,0xe, 0x78,0x3, 0x12,0x67,0x30,0xb, 0xc0,0x7e,0x73,0x29,0x5d,0xbc,0x7c, +0x38,0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0xc1,0x85,0xda,0x3b,0x22,0xa, 0xec, +0x9, 0x7e,0x29,0xc9,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22,0x7e, +0xf4,0x7f,0xff,0x9f,0x44,0xe4,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0x22, +0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d, +0x35,0x1b,0x1a,0xe0,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12,0x17,0x85,0x7d,0x73, +0x12,0x1a,0x62,0x7d,0xe3,0x7d,0x3f,0x12,0x1a,0x62,0xbd,0x3e,0x22,0xca,0x3b,0x7f, +0x61,0x7f,0x50,0x7e,0x14,0x1c,0x29,0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, +0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73,0x29,0x5a,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f, +0x16,0x7f,0x5, 0x12,0x1a,0xb, 0x1b,0xfd,0x6c,0xdd,0x12,0x67,0x1f,0x7a,0xb3,0x1e, +0x44,0x6c,0xcc,0x80,0x4a,0x12,0x68,0x3d,0x40,0x43,0x12,0x68,0x33,0x50,0x3e,0x12, +0x67,0x27,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x1a,0x62,0x7d,0x3, 0x7d,0x31,0x12,0x1a, +0x62,0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15,0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80, +0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26, +0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1e,0x44,0x4, 0x7a,0xb3,0x1e,0x44,0xb, 0xc0,0x7e, +0x73,0x29,0x5c,0xbc,0x7c,0x38,0xae,0x7e,0x73,0x1e,0x44,0x4c,0x77,0x68,0x37,0x12, +0x67,0x45,0x8, 0x2, 0x7d,0x7f,0xbe,0x75,0x2a,0x8, 0x5, 0x7e,0x75,0x2a,0x80,0xb, +0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e,0x6c,0xcc,0x80,0xf, 0x12, +0x68,0x3d,0x40,0x8, 0x12,0x68,0x33,0x50,0x3, 0x12,0x67,0x30,0xb, 0xc0,0x7e,0x73, +0x29,0x5c,0xbc,0x7c,0x38,0xe9,0xb, 0xd0,0xbe,0xd0,0x3, 0x50,0x3, 0x2, 0x67,0x8a, +0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d,0xa5,0xe7,0xbc,0xab,0x22,0xa, 0xec,0x9, +0xae,0x29,0xa6,0x7c,0x1d,0x2e,0x10,0x2c,0xa5,0xe7,0xbc,0xab,0x22,0x7e,0x54,0x0, +0x54,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69,0x22,0x0, 0x2, 0xb, 0x2a,0x10, +0x7a,0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34,0x0, 0x20,0x7e,0x8, 0x0, 0x24,0x7e,0x24, +0x0, 0x6, 0x12,0x68,0xc6,0x74,0x25,0x7a,0xb3,0x3a,0x80,0x74,0x20,0x7a,0xb3,0x3a, +0x81,0x74,0xc, 0x7a,0xb3,0x3a,0x82,0x7a,0xb3,0x3a,0x83,0x7a,0xb3,0x3a,0x84,0x74, +0xa0,0x7a,0xb3,0x3a,0x85,0x7e,0x34,0x0, 0x6a,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e, +0x24,0x0, 0xff,0x7e,0x8, 0x3a,0x86,0x12,0x1a,0xb, 0x1b,0xfd,0xe5,0x25,0x7a,0xb3, +0x3a,0xb1,0xe5,0x28,0x7a,0xb3,0x3a,0xa0,0xe4,0x7a,0xb3,0x3a,0xb4,0x7a,0xb3,0x3a, +0xb5,0x7a,0xb3,0x3a,0xb6,0x22,0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x6a,0x51,0x74, +0x2, 0x12,0x69,0x0, 0x7d,0xf3,0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x69, +0xbe,0x7a,0x45,0x36,0x7d,0x30,0x6d,0x22,0x7f,0x6, 0x12,0x69,0xd6,0x5e,0xf4,0xff, +0xfd,0x12,0x69,0xbe,0x2, 0x68,0xf7,0xa9,0xc5,0xca,0xe4,0x7a,0xb3,0x3c,0x40,0x22, +0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3,0x3c,0x40,0xb4,0xa5,0x46,0x12,0x69,0xc5, +0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0x12,0x69,0x5c,0xa9,0x36,0xb3,0xfc,0x12,0x69, +0x5c,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0x12, +0x69,0x5c,0xa9,0x36,0xb3,0xfc,0x12,0x69,0x5c,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3, +0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7e,0xa1,0xb5, +0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22,0xa9,0xc6,0xb3,0x75, +0xb5,0x0, 0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c,0x73,0x7d, +0x52,0x7c,0xab,0x7e,0xb3,0x3c,0x40,0xb4,0xa5,0x3c,0x12,0x69,0xc5,0x75,0xb5,0x1, +0xa9,0x36,0xb3,0xfc,0x12,0x69,0x5c,0xa9,0x36,0xb3,0xfc,0x12,0x69,0x5c,0xa9,0x36, +0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a, +0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3,0xfc, +0xa9,0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0x74,0x4, 0x7d,0x30,0x2, 0x69,0x67,0x74,0x2, +0x7d,0x3f,0x2, 0x69,0x67,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74,0x6, 0x12,0x69, +0x0, 0x7d,0x3, 0x6c,0x11,0x22,0x12,0x69,0xe4,0x7e,0x35,0x36,0x12,0x6a,0x61,0xa9, +0xd2,0xb4,0xd3,0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, 0x44,0xf5,0x39, +0x7f,0x21,0xf5,0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x6a,0xf, 0xe5,0x3a,0x12,0x6a, +0xf, 0xe5,0x39,0x12,0x6a,0xf, 0xe5,0x38,0x12,0x6a,0xf, 0xe4,0x2, 0x6a,0xf, 0xf5, +0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xd2,0xc8,0x43,0xed,0xf, 0xc2, +0xea,0x75,0xb3,0x13,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x12,0x6a,0x51,0xe4,0x12,0x6a, +0x34,0x2, 0x68,0xf7,0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0x69,0x0, 0x4c,0xff,0x78, +0x5, 0x5e,0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0x69,0x67,0xda,0xf8, +0x22,0xa9,0xd5,0xca,0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x3c,0x40, +0x22,0x6d,0x22,0x80,0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5, +0xb5,0x7a,0xb, 0xb0,0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22,0x7e,0x8, 0x25, +0x2f,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x1a,0x30,0x7e,0x8, 0x25,0x60,0x7e,0x34,0x0, +0xc8,0x74,0xff,0x12,0x1a,0x30,0x7e,0x8, 0x25,0x88,0x7e,0x34,0x0, 0xc8,0x12,0x1a, +0x30,0x90,0x60,0x9a,0xe4,0x93,0x7c,0x7b,0x74,0x9, 0xac,0x7b,0x7e,0x8, 0x26,0x4a, +0x74,0xff,0x2, 0x1a,0x30,0xca,0xf8,0x7e,0x73,0x29,0x65,0xa, 0x47,0x7e,0x73,0x29, +0x5e,0xa, 0x57,0x2d,0x54,0x7e,0xa3,0x29,0x60,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e, +0xf3,0x29,0x5f,0x7e,0xa3,0x29,0x61,0xbc,0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x1, +0x7e,0x8, 0x29,0xa6,0x7e,0x18,0x29,0x67,0x12,0xd, 0xd9,0x75,0x25,0x1, 0x7e,0x8, +0x29,0xc9,0x7e,0x18,0x29,0x8a,0x7c,0xbf,0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7f,0x60, +0x7e,0xa3,0x29,0x5a,0x7e,0xb3,0x29,0x5b,0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d, +0x3f,0xe4,0x12,0x1a,0x30,0x7f,0x6, 0x7d,0x3f,0x12,0x1a,0x30,0x7a,0xb3,0x15,0xa1, +0x22,0x7e,0xf, 0x12,0x9a,0x7e,0x18,0x7, 0x1a,0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30, +0x12,0x77,0xc7,0x7a,0x55,0x31,0x7e,0xb3,0x2a,0xa, 0xf5,0x2e,0xe4,0x7a,0xb3,0x2a, +0xa, 0x7f,0x3, 0x7e,0x1d,0x29,0x12,0x6a,0xfe,0x12,0x72,0xf9,0x12,0x47,0xcd,0x75, +0x2d,0x0, 0x12,0x73,0x16,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x6c,0x13,0x7e,0x14,0x40, +0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x77,0xec,0x12,0xac,0xea,0x6d,0x33,0x80,0x19,0x7e, +0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13, +0x12,0x89,0x4d,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35, +0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3, +0x2a,0xa, 0xda,0x3b,0x22,0x7e,0xb3,0x2a,0xb, 0x70,0x1f,0x12,0x3c,0x94,0x12,0x77, +0xdb,0x50,0xfb,0x12,0x6b,0x21,0x12,0x6b,0xcb,0x20,0x12,0x3, 0x12,0xad,0x31,0x74, +0x2, 0x7a,0xb3,0x2a,0xb, 0xe4,0x7a,0xb3,0x15,0xa1,0x22,0x12,0xb0,0x17,0x50,0x3, +0xd2,0x12,0x22,0xc2,0x12,0x22,0x12,0xa6,0x52,0x12,0x6b,0xdf,0x2, 0x6b,0xcb,0x7e, +0x8, 0x24,0x2, 0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x1a,0x30,0x12,0xa5,0x14,0x12,0xa5, +0xb, 0xa9,0xd1,0xcb,0x12,0x6c,0x13,0x7a,0x37,0x24,0x6, 0x7e,0x1f,0x3c,0x13,0x7a, +0x37,0x24,0x8, 0x7e,0x1f,0x12,0x96,0x7a,0x37,0x24,0xa, 0x6d,0x33,0x12,0xac,0x67, +0x2, 0xd, 0x7, 0x12,0x0, 0xe, 0x7e,0x1f,0x12,0x96,0x22,0x12,0x83,0x33,0x12,0x6c, +0x5e,0x12,0x6f,0xb4,0x7e,0xb3,0x3a,0xa5,0xb4,0x1, 0x7, 0x7e,0x34,0x0, 0x14,0x12, +0xcf,0x2d,0x7e,0xb3,0x33,0xff,0x60,0x7, 0x14,0x7a,0xb3,0x33,0xff,0x80,0x6, 0x7e, +0xb3,0x27,0x80,0x60,0x9, 0x12,0x6b,0xd6,0x12,0xaa,0xc4,0x12,0xbf,0xb7,0x7e,0xb3, +0x27,0x81,0x60,0x9, 0x12,0xca,0x14,0x12,0xa5,0x1d,0x2, 0xac,0x90,0x22,0xca,0xd8, +0xca,0x79,0x75,0x24,0x1, 0x7e,0xe4,0x7f,0xff,0x7d,0xfe,0x7e,0x34,0x80,0x0, 0x7d, +0x23,0x7e,0xa3,0x29,0x5c,0x7e,0x83,0x29,0x5d,0x7e,0x90,0x1, 0x80,0x17,0x12,0xbc, +0x4f,0xbd,0x1f,0x58,0x2, 0x7d,0xf1,0x12,0xbc,0x4f,0xbd,0x12,0x8, 0x5, 0xa, 0x19, +0x12,0xa7,0x19,0xb, 0x90,0xa, 0xa, 0x1b,0x4, 0xa, 0x19,0xbd,0x10,0x48,0xdf,0x7e, +0x90,0x1, 0x80,0x1b,0x12,0xce,0xc9,0xbd,0xfe,0x58,0x2, 0x7d,0xef,0x12,0xce,0xc9, +0xbd,0xf3,0x8, 0x9, 0x7e,0x70,0x2, 0xac,0x79,0x49,0x33,0x4, 0xc0,0xb, 0x90,0xa, +0x18,0x1b,0x14,0xa, 0xf9,0xbd,0xf1,0x48,0xdb,0xbd,0x32,0x58,0x6, 0x7d,0xf2,0x7d, +0x8f,0x80,0x2, 0x7d,0x83,0x7e,0xf4,0x0, 0x4, 0x7a,0xf7,0x27,0x75,0x7a,0xf7,0x27, +0x77,0x7e,0xd4,0x0, 0xc8,0x7e,0xb4,0x0, 0x96,0xe4,0x7a,0xb3,0x27,0x80,0x12,0x6f, +0xad,0x7e,0x34,0xfd,0xa8,0x7e,0x94,0xfe,0xd4,0x7e,0xb3,0x29,0x55,0xb4,0x1, 0x4, +0x7d,0xad,0x80,0x4, 0x7d,0xad,0x3e,0xa4,0x6c,0xdd,0x6c,0x99,0x80,0x2f,0x7e,0x50, +0x2, 0xac,0x59,0x9, 0xe2,0x25,0xce,0x9, 0xf2,0x25,0xcf,0x7e,0x50,0x2, 0xac,0x5f, +0x49,0x22,0x4, 0xc0,0xbd,0x2d,0x48,0x13,0xa, 0xfe,0x7e,0xb3,0x29,0x5b,0xa, 0x2b, +0x2d,0x2f,0x12,0xa7,0x21,0xbd,0x2d,0x48,0x2, 0xb, 0xd0,0xb, 0x90,0x12,0x86,0x12, +0x38,0xcc,0x7e,0xf7,0x7, 0xe, 0xbd,0xf3,0x58,0x14,0x7e,0xf7,0x7, 0xc, 0xbd,0xf9, +0x58,0xc, 0x12,0xce,0xa2,0x8, 0x39,0x12,0x5f,0xfa,0x60,0x34,0x80,0x2f,0x7e,0xf7, +0x29,0x47,0x3e,0xf4,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbe,0xf7,0x27,0x62,0x8, 0x20, +0x6d,0xff,0x9d,0xfd,0xbe,0xf7,0x7, 0xe, 0x8, 0x16,0x6d,0xff,0x9d,0xfa,0xbe,0xf7, +0x7, 0xc, 0x8, 0xc, 0x4c,0xdd,0x78,0x8, 0x12,0x5f,0xfa,0x60,0x3, 0x12,0xa5,0xe9, +0x12,0x5f,0xfa,0xa, 0xfb,0x4d,0xff,0x68,0x47,0x6d,0x33,0x9d,0x3d,0x12,0xcd,0xe1, +0xbe,0x37,0x7, 0xe, 0x18,0x6, 0xbe,0x37,0x7, 0xc, 0x8, 0x34,0x12,0xce,0xa2,0x8, +0x2f,0x7e,0x37,0x27,0x62,0x12,0x1a,0x62,0xbe,0x37,0x27,0x5e,0x8, 0x22,0x12,0x9d, +0x50,0x28,0x1d,0x7e,0xb3,0x27,0x59,0xbe,0xb0,0x1, 0x28,0x14,0x7e,0xf7,0x7, 0xa, +0xbd,0xfd,0x58,0xc, 0x12,0xa5,0xe9,0xe4,0x7a,0xb3,0x27,0x58,0x7a,0xb3,0x28,0xf4, +0x6c,0x99,0x80,0x3c,0x74,0x2, 0xac,0xb9,0x9, 0xe5,0x25,0xce,0x9, 0xf5,0x25,0xcf, +0x7e,0xa3,0x29,0x5c,0x6c,0x88,0x80,0x7, 0x12,0x27,0x39,0x2d,0xc3,0xb, 0x80,0xbc, +0xe8,0x38,0xf5,0xa, 0xfe,0xb, 0xf4,0x7d,0x3f,0x7c,0x87,0x80,0x7, 0x12,0x27,0x39, +0x2d,0xc3,0xb, 0x80,0xa, 0x3a,0x1b,0x34,0xa, 0xf8,0xbd,0xf3,0x48,0xef,0xb, 0x90, +0x12,0x86,0x12,0x38,0xbf,0x12,0xa6,0x91,0x40,0x5, 0xe4,0x7a,0xb3,0x27,0x7c,0x12, +0x96,0x1, 0x68,0x6, 0x7e,0xb3,0x3c,0x3a,0x60,0x7, 0xe4,0x7a,0xb3,0x27,0x81,0x80, +0x63,0x12,0x6f,0x7e,0x28,0x5, 0xe4,0x7a,0xb3,0x27,0x81,0x30,0x13,0x5, 0xe4,0x7a, +0xb3,0x27,0x81,0x12,0xa6,0xcf,0x50,0xa, 0x12,0x6f,0xad,0x12,0xa5,0x6e,0xf5,0x24, +0x80,0x17,0x7e,0xb3,0x25,0x58,0x70,0x11,0x7e,0xb3,0x25,0x59,0x70,0xb, 0x12,0x6f, +0x7e,0x28,0x6, 0x75,0x24,0x3, 0x12,0x6f,0xad,0xbe,0x84,0x5, 0xdc,0x8, 0x17,0x12, +0x6f,0x7e,0x28,0x12,0x6d,0xff,0x9d,0xfb,0xbe,0xf7,0x27,0x62,0x58,0x8, 0x12,0xa5, +0xd1,0xe4,0x7a,0xb3,0x27,0x81,0x7e,0xa1,0x24,0x74,0x4, 0xa4,0x7a,0x57,0x27,0x75, +0x7a,0x57,0x27,0x77,0x12,0x5f,0xfd,0x50,0xd, 0xe4,0x7a,0xb3,0x27,0x81,0x12,0x6f, +0x7e,0x28,0x3, 0x12,0xa5,0xd1,0x7e,0xf7,0x27,0x5e,0xbd,0xfb,0x8, 0x1d,0x7e,0x24, +0x0, 0x2, 0x7d,0x3b,0x12,0x16,0xe6,0x6d,0xff,0x9d,0xf3,0xbe,0xf7,0x27,0x62,0x58, +0xa, 0x12,0x5f,0xfd,0x50,0x5, 0xe4,0x7a,0xb3,0x27,0x81,0x12,0x9b,0x5d,0xb4,0x1, +0x5, 0xe4,0x7a,0xb3,0x27,0x81,0x7e,0xb3,0x25,0x58,0x60,0x8, 0x6d,0x33,0x9d,0x3d, +0xbd,0x3e,0x8, 0x32,0x7e,0xb3,0x25,0x59,0x70,0x2c,0x12,0x6f,0x7e,0x28,0x27,0x12, +0xcf,0x79,0x28,0x22,0x4c,0xdd,0x78,0x1e,0x7e,0x37,0x29,0x47,0x7d,0x23,0x3e,0x24, +0x6e,0x24,0xff,0xff,0xb, 0x24,0xbe,0x27,0x27,0x62,0x8, 0xa, 0x3e,0x34,0x3e,0x34, +0xbe,0x37,0x27,0x5e,0x38,0x9, 0x7e,0x73,0x34,0x88,0xbe,0x70,0x0, 0x28,0x1b,0x6c, +0x33,0x80,0xc, 0x7c,0xb3,0x12,0x96,0x11,0xac,0x73,0x12,0x96,0x23,0xb, 0x30,0x7e, +0x23,0x27,0x58,0xbc,0x23,0x38,0xec,0x12,0x5e,0x1b,0x12,0xa5,0xf8,0x7e,0xb3,0x34, +0x88,0xbe,0xb0,0x0, 0x28,0x23,0x14,0x7a,0xb3,0x34,0x88,0x70,0x1c,0xe4,0x7a,0xb3, +0x27,0x81,0x74,0x1, 0x7a,0xb3,0x27,0x80,0xe4,0x7a,0xb3,0x15,0xa1,0x7a,0xb3,0x15, +0xa0,0x7a,0xb3,0x27,0x58,0x7a,0xb3,0x25,0x57,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73, +0x27,0x58,0xbe,0x70,0x0, 0x22,0x7f,0x70,0x7e,0x33,0x29,0x61,0xa, 0x43,0x7e,0x33, +0x29,0x60,0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x15,0xa0,0x7f, +0x1, 0xa, 0x3a,0x12,0x1a,0x30,0x7f,0x7, 0xa, 0x3a,0x2, 0x1a,0x30,0x74,0x1, 0x7a, +0xb3,0x27,0x81,0x22,0x12,0xaf,0x47,0x60,0x17,0x12,0x6f,0xad,0x7e,0x37,0x27,0x75, +0x3e,0x34,0x7a,0x37,0x27,0x75,0x7e,0x37,0x27,0x77,0x3e,0x34,0x7a,0x37,0x27,0x77, +0x22,0x7e,0xa3,0x2e,0x86,0x7e,0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x3b,0x42, +0x40,0x39,0x7e,0x37,0x3b,0x42,0xb, 0x34,0x7a,0x37,0x3b,0x42,0xbe,0x34,0x0, 0x1, +0x78,0x5, 0x7e,0xb3,0x3a,0xd3,0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba,0x22, +0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x33,0xf9,0x22,0x9e, +0x34,0x0, 0x3, 0x2e,0x37,0x2a,0x97,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x7e,0xa3, +0x3a,0xf0,0x7c,0xba,0x4, 0x7a,0xb3,0x3a,0xf0,0x7a,0xa3,0x3a,0x91,0x22,0xca,0x7b, +0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82,0x12,0x32,0x5f,0xd0,0x82,0xd0, +0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32,0xa9,0xc0,0x93,0x75,0x18,0x0, +0x32,0x7e,0xb3,0x3b,0x46,0x4, 0x7a,0xb3,0x3b,0x46,0xe5,0x19,0xb4,0x1, 0x8, 0xe4, +0x7a,0xb3,0x3b,0x46,0x75,0x19,0x0, 0x7e,0x73,0x3b,0x46,0x7a,0x73,0x3a,0x8f,0x22, +0x70,0x5, 0x7e,0xb3,0x3a,0xf1,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x1b,0x0, 0x30, +0x11,0x6, 0x7e,0x18,0x36,0xbe,0x80,0x4, 0x7e,0x18,0x36,0xfc,0x7a,0x1d,0x14,0x80, +0x8, 0xbe,0xb0,0x5e,0x38,0x10,0x75,0x1b,0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d,0x31, +0x1b,0x34,0x7e,0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4,0xd3, +0x8, 0x6d,0x33,0x7a,0x37,0x3b,0x42,0x80,0x2, 0x15,0x1a,0x2, 0x6f,0xd1,0xbe,0xb0, +0xeb,0x68,0x3, 0xb4,0xec,0x3, 0x2, 0x71,0xd, 0xbe,0xb0,0x80,0x40,0xc, 0xbe,0xb0, +0xdf,0x38,0x7, 0xa, 0x3b,0x9, 0xb3,0x3a,0x0, 0x22,0xb4,0xfc,0x5, 0x7e,0xb3,0x3a, +0xa7,0x22,0xb4,0xfd,0x1d,0x6c,0xaa,0x7e,0xb3,0x27,0x7c,0x60,0x3, 0x4e,0xa0,0x1, +0x7e,0xb3,0x3a,0xf, 0x60,0x3, 0x4e,0xa0,0x2, 0x30,0x13,0x3, 0x4e,0xa0,0x8, 0x7c, +0xba,0x22,0xb4,0xfe,0x5, 0x7e,0xb3,0x29,0xfc,0x22,0x74,0xff,0x22,0xb4,0xeb,0x5, +0xe4,0x7a,0xb3,0x3b,0x47,0x7e,0x73,0x3b,0x47,0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12, +0x71,0x43,0x7c,0xab,0x7c,0xb7,0x4, 0x7a,0xb3,0x3b,0x47,0xb4,0x3, 0xb, 0xe4,0x7a, +0xb3,0x3b,0x47,0x6d,0x33,0x7a,0x37,0x3b,0x44,0x75,0x1a,0xeb,0x7c,0xba,0x22,0x2e, +0x24,0x19,0xc5,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0xca,0x79,0x7c,0xfb, +0x7e,0x8, 0x1e,0x44,0x12,0x71,0xc2,0x7e,0xa3,0x29,0x60,0x7e,0x63,0x29,0x61,0x6c, +0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x29,0xc9,0xbe,0x70,0x1c,0x50,0x11,0xa, 0x27, +0x12,0x71,0x3f,0x7c,0x7b,0x7e,0xb3,0x29,0xe8,0xa, 0x27,0x19,0xb2,0x1e,0x44,0xb, +0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17,0xa, 0x3e,0x9, 0x73,0x29,0xa6,0xbe, +0x70,0x23,0x50,0xa, 0x7e,0x63,0x29,0xe8,0xa, 0x27,0x19,0x62,0x1e,0x60,0xb, 0xe0, +0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x1e,0x44,0x6d, +0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda, +0x79,0x22,0x7e,0x34,0x0, 0x46,0x74,0x3f,0x2, 0x1a,0x30,0xe4,0x7a,0xb3,0x3a,0xf1, +0x7e,0x8, 0x36,0xbe,0x12,0x72,0x1a,0x7e,0x8, 0x36,0xfc,0x7e,0x34,0x0, 0x3e,0x12, +0x1a,0x30,0x7e,0x18,0x36,0xbe,0x7a,0x1d,0x14,0x12,0x71,0xfc,0x2, 0x71,0xef,0x75, +0x18,0x0, 0x75,0x1a,0x0, 0x7e,0xb3,0x3a,0xf1,0xf5,0x91,0x22,0x2, 0x71,0xff,0x90, +0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2,0xc9,0x54, +0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0x7e,0x34,0x0, 0x3e,0x74,0xff, +0x2, 0x1a,0x30,0x12,0x72,0xf9,0xe4,0x12,0x0, 0xe, 0x7e,0x8, 0x29,0x5a,0x2, 0xd, +0x72,0xb4,0x3, 0x5, 0x12,0x72,0x23,0x80,0x2, 0xe4,0x22,0x12,0x73,0x1a,0x74,0x1, +0x22,0x12,0x72,0xf0,0x38,0x2, 0xe4,0x22,0x12,0x72,0x86,0x49,0x55,0x34,0x3b,0xbe, +0xb0,0x2, 0x38,0x3, 0x2, 0x72,0x5a,0x2, 0x72,0x31,0x7e,0xd7,0x29,0xfa,0xbe,0xb0, +0x1, 0x28,0x2, 0xe4,0x22,0x12,0x73,0x2, 0x12,0x3f,0xf0,0x7a,0xd7,0x29,0xfa,0x7e, +0x73,0x29,0xe7,0xa, 0x37,0x3e,0x34,0x3e,0x34,0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, +0x12,0x39,0xb9,0x74,0x1, 0x22,0x7e,0xa3,0x34,0x39,0x74,0x4, 0xa4,0x22,0x30,0x1b, +0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12,0x13,0x2c,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x4f, +0x12,0x72,0x86,0x49,0x35,0x34,0x3b,0x49,0x15,0x34,0x3d,0x6d,0x0, 0xbe,0x8, 0x0, +0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15,0xbe,0x70,0x2, 0x38,0x10,0x74,0x2, 0x12, +0x0, 0x1e,0x7e,0xb3,0x29,0x60,0x7e,0x73,0x29,0x61,0x12,0x10,0xee,0x7e,0xb3,0x34, +0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12,0x72,0xf0,0x28,0xe, 0x12,0x72,0x41,0xb4,0x1, +0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x34,0x3a,0x22, +0x7e,0x73,0x34,0x38,0xbe,0x73,0x34,0x39,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, +0x0, 0x1e,0x7c,0xab,0x12,0x37,0xa, 0x7c,0xba,0x12,0x13,0xc7,0x2, 0x0, 0x1e,0x7e, +0x8, 0x29,0x5a,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x12, +0x13,0x2c,0x2, 0x0, 0x4e,0xca,0x3b,0x7e,0x34,0xff,0xff,0x7a,0x35,0x34,0x7e,0xb3, +0x3b,0x6, 0xf5,0x29,0x7e,0xb3,0x29,0x5a,0xf5,0x2a,0x7e,0xb3,0x29,0x5b,0xf5,0x2b, +0x7e,0xb3,0x29,0x5d,0xf5,0x2c,0x7e,0xb3,0x29,0x5c,0xf5,0x2d,0x7e,0x34,0x27,0x10, +0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30,0x12,0x73,0xf, 0x30,0xd, 0xfd, +0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x77,0xb6,0x6c,0xff,0x80,0x34, +0x9f,0x77,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b,0xac,0x1e,0x3e,0x4, 0x7e,0x30,0x2, +0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x30,0x12,0x75,0x83,0xe5, +0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x75,0x8a,0x74,0x2, 0xac,0xbf,0x59,0x35, +0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xc6,0x6c,0xff,0x80,0x72,0x9f,0x77, +0x6c,0xee,0x80,0x12,0x12,0x75,0xb4,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80, +0x14,0x78,0xf4,0x12,0x75,0x83,0xe5,0x29,0xbc,0xbe,0x38,0xe8,0xe5,0x29,0x12,0x75, +0x8a,0x74,0x4, 0xac,0xbf,0x59,0x35,0x2, 0x8c,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x32, +0x9f,0x77,0x7e,0xe1,0x29,0x80,0x12,0x12,0x75,0xb4,0x1e,0x34,0x1e,0x24,0x50,0x3, +0x4e,0x60,0x80,0x14,0x78,0xf4,0x12,0x75,0x83,0xe5,0x2c,0xbc,0xbe,0x38,0xe8,0xe5, +0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x75,0x8e, +0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x2, 0x8e,0xb, 0xf0, +0xe5,0x2d,0xbc,0xbf,0x38,0x88,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x78,0x0, 0x28, +0x12,0x75,0xac,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, 0x5f,0xad, +0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50, +0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59,0x25,0x34, +0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d,0x0, 0x12, +0x75,0xac,0x80,0x5c,0x74,0x4, 0xac,0xbf,0x49,0x25,0x2, 0x8c,0xa, 0x1f,0xad,0x13, +0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, +0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25,0x2, +0x8c,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49,0x25,0x2, 0x8e, +0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20, +0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x2, 0x8e,0xb, 0xf0, +0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73,0x3b,0x8, 0xa, 0x37,0x6d,0x22,0x74,0xc, +0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x17,0x32,0x7d,0xe3, +0x7a,0xe5,0x34,0x7e,0x73,0x3b,0x9, 0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14, +0x78,0xfb,0x7d,0x1f,0x12,0x17,0x32,0x7d,0x63,0x6c,0xff,0x80,0x20,0x74,0x2, 0xac, +0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x34, +0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc, +0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74,0x4, 0xac,0xbf,0x49,0x45,0x2, 0x8c,0xbe, +0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x2, 0x8c,0x80,0x8, 0xbd,0x46,0x50, +0x4, 0x59,0x65,0x2, 0x8c,0x49,0x45,0x2, 0x8e,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35, +0x34,0x59,0x35,0x2, 0x8e,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x2, 0x8e,0xb, +0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30,0x2, 0x6, 0x74,0x1, 0x7a,0xb3,0x2a,0xd, +0xda,0x3b,0x22,0x6d,0x22,0x2f,0x71,0xb, 0xe0,0x22,0xa, 0x1b,0x6d,0x0, 0x7f,0x17, +0x12,0x17,0x34,0x7f,0x71,0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d,0x22, +0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x17,0x32,0x7f,0x17,0x12,0x17, +0x34,0x6c,0xff,0x22,0x7e,0x11,0x2b,0xac,0x1f,0x3e,0x4, 0x7e,0x30,0x2, 0xac,0x3e, +0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20,0x7a,0x27,0x24,0x2, 0x74,0x2, +0xac,0xbe,0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, 0x22,0xca,0x3b,0x7a,0xd, 0x2e, +0x7c,0xcb,0x7e,0xb3,0x2a,0xa, 0xf5,0x32,0x7e,0xb3,0x29,0xfc,0xf5,0x33,0x7e,0xd3, +0x2a,0x1, 0x7e,0xe3,0x2a,0xc, 0x7e,0xf3,0x2a,0xd, 0x7e,0x34,0x0, 0x38,0xca,0x39, +0x7e,0x18,0x34,0x0, 0x7e,0x8, 0x24,0x2, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, +0x50,0xca,0x39,0x7e,0x18,0x2, 0x8c,0x7e,0x8, 0x24,0x3a,0x12,0x1a,0xb, 0x1b,0xfd, +0x7c,0xbc,0x12,0xb0,0xef,0x74,0x1, 0x7a,0xb3,0x2a,0xa, 0x74,0x5, 0xac,0xbc,0x12, +0x47,0xed,0x74,0x5, 0xac,0xbc,0x12,0x47,0xdb,0x74,0x5, 0xac,0xbc,0x12,0x47,0xe4, +0x74,0x5, 0xac,0xbc,0x9, 0x75,0x25,0xb, 0xbe,0x73,0x2a,0x4f,0x68,0x6, 0x7a,0x73, +0x2a,0x4f,0xd2,0xf, 0xc2,0x0, 0x12,0x77,0xbe,0x12,0x44,0x39,0x12,0x73,0xf, 0x30, +0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d,0x31,0x7e,0x2f,0x12, +0x96,0x7d,0x25,0x7e,0x4, 0xc, 0xd8,0x12,0x77,0xec,0x12,0x77,0xc7,0x7a,0x55,0x34, +0x7e,0xd, 0x2e,0x7e,0x18,0xc, 0xd8,0x12,0x77,0x1a,0x12,0x76,0xce,0xe5,0x32,0x7a, +0xb3,0x2a,0xa, 0xe5,0x33,0x7a,0xb3,0x29,0xfc,0x7a,0xd3,0x2a,0x1, 0x7a,0xe3,0x2a, +0xc, 0x7a,0xf3,0x2a,0xd, 0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x24,0x2, 0x7e, +0x8, 0x34,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39,0x7e,0x18, +0x24,0x3a,0x7e,0x8, 0x2, 0x8c,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x3b,0x22,0x90,0x60, +0x93,0xe4,0x93,0xa, 0xb, 0x7e,0x73,0x29,0x5e,0xa, 0x17,0x2d,0x10,0x12,0x77,0xaf, +0xad,0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f, +0x3c,0x13,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x12,0x9e, +0x9d,0xf, 0x59,0x4, 0x24,0x8a,0xb, 0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e, +0xf, 0x33,0x9e,0x7e,0x18,0x24,0x8a,0x2, 0x77,0x1a,0xca,0xf8,0x7f,0x71,0x6d,0xdd, +0x6c,0xaa,0x7e,0xf0,0x7f,0xc2,0x0, 0x6d,0x44,0x80,0x1e,0x7d,0xc4,0x3e,0xc4,0x7f, +0x17,0x2d,0x3c,0x12,0x77,0xa9,0xbd,0x3d,0x48,0xd, 0x7d,0x34,0x3e,0x34,0x2d,0x3f, +0x7d,0x2e,0x12,0x77,0xa9,0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4,0x38,0xdb, +0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60,0x5, 0xe, +0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35,0x34,0x7a, +0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35,0xb, 0x1a, +0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14,0x78,0xfb, +0x7c,0xb7,0x12,0x77,0xd3,0xb, 0x44,0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8,0xda,0xf8, +0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x1a,0x62,0x7e, +0xa3,0x29,0x5b,0xa, 0x3a,0x22,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x1a,0x30,0x74,0x5, +0xac,0xbc,0x9, 0xb5,0x25,0x7, 0x22,0x7e,0xa3,0x29,0x5b,0x7e,0xb3,0x29,0x5a,0xa4, +0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34,0x7a,0x1b,0xb0,0x22,0x7e,0xb3,0x34,0x3a,0xb4, +0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x12,0x77,0xdb,0x50,0xfb,0x22,0x7e,0xb3,0x29,0x5a, +0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7d,0xc0,0x7d,0xd1,0x7d,0xf2,0x7d,0xe3,0x12,0xb0, +0x17,0x50,0x66,0x6c,0xee,0x80,0x11,0x12,0x78,0xdf,0x12,0x78,0xec,0x7a,0x73,0x24, +0x8b,0x7e,0x34,0x34,0x0, 0x12,0x79,0x2, 0x7e,0x73,0x29,0x5c,0xbc,0x7e,0x38,0xe7, +0x6c,0xee,0x80,0x3f,0x12,0x78,0xdf,0x6c,0xdd,0x80,0x22,0x7e,0x73,0x3b,0x6, 0xbc, +0x7d,0x74,0x4, 0x28,0x8, 0xac,0xbe,0x49,0x35,0x2, 0x8c,0x80,0x6, 0xac,0xbe,0x49, +0x35,0x2, 0x8e,0x74,0x2, 0xac,0xbd,0x59,0x35,0x34,0x50,0xb, 0xd0,0x7e,0x73,0x29, +0x5d,0xbc,0x7d,0x38,0xd6,0x12,0x78,0xec,0x7a,0x73,0x24,0x8b,0x7e,0x34,0x34,0x50, +0x12,0x79,0x2, 0xbc,0xfe,0x38,0xbd,0x80,0x2c,0x7a,0xf3,0x24,0x8a,0x7e,0x73,0x29, +0x5d,0x7a,0x73,0x24,0x8b,0xe4,0x7a,0xb3,0x24,0x8d,0x74,0x6, 0x7a,0xb3,0x24,0x8c, +0x7a,0xd7,0x24,0x8e,0x7a,0xd7,0x24,0x92,0x7e,0x8, 0x24,0x8a,0x7e,0x73,0x2a,0xc, +0xa, 0x37,0x12,0xe, 0x37,0x7a,0xc7,0x24,0x92,0xe4,0x7a,0xb3,0x24,0x8c,0x7e,0x73, +0x29,0x5b,0x7a,0x73,0x24,0x8b,0x7a,0xf3,0x24,0x8a,0x7e,0xb3,0x2a,0xa, 0x70,0xf, +0xe4,0x7a,0xb3,0x24,0x8d,0x7a,0xd7,0x24,0x8e,0x7e,0x34,0x0, 0x20,0x80,0x10,0x74, +0x1, 0x7a,0xb3,0x24,0x8d,0x7a,0xe7,0x24,0x8e,0x7a,0xf7,0x24,0x90,0x6d,0x33,0x7a, +0x37,0x24,0x94,0x7e,0x8, 0x24,0x8a,0x12,0xd, 0x7, 0xda,0x79,0xda,0xd8,0x22,0x7e, +0x73,0x29,0x5b,0xac,0x7e,0x3e,0x34,0x7d,0xbd,0x2d,0xb3,0x22,0x74,0xc, 0x7a,0xb3, +0x24,0x8c,0x74,0x1, 0x7a,0xb3,0x24,0x8a,0xe4,0x7a,0xb3,0x24,0x8d,0x7e,0x73,0x29, +0x5b,0x22,0x7a,0x37,0x24,0x8e,0x7d,0x3b,0x7a,0x37,0x24,0x90,0x7a,0x37,0x24,0x92, +0x7e,0x8, 0x24,0x8a,0x12,0x7, 0x9b,0xb, 0xe0,0x22,0x7c,0x9b,0x7f,0x71,0x7e,0x7b, +0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a,0x7b,0x90,0x22,0xa, 0x28,0x7e,0xb, +0x80,0xa, 0x38,0x9d,0x32,0x12,0x1a,0x62,0xe5,0x39,0xa, 0x2b,0xbd,0x32,0x8, 0x15, +0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c,0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, +0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a,0xb, 0x70,0x22,0xca,0x69,0xca,0xf8, +0x7e,0xa3,0x28,0xf4,0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x28,0xf5,0xbe,0xb0,0x0, 0x28, +0x13,0x74,0x1, 0x7a,0xb3,0x28,0xf9,0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, 0x74,0x1, +0x7a,0xb3,0x28,0xfd,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x27,0x82,0x7e,0x8, +0x27,0xdc,0x12,0x1a,0xb, 0x1b,0xfd,0x6c,0xff,0x74,0x9, 0xac,0xbf,0x49,0x35,0x27, +0x82,0x12,0x7a,0x8b,0x74,0x9, 0xac,0xbf,0x59,0x35,0x27,0xdc,0x49,0x35,0x27,0x84, +0x12,0x7c,0x85,0x7e,0xd0,0x9, 0xac,0xdf,0x59,0x36,0x27,0xde,0x49,0x16,0x27,0xde, +0xbe,0x14,0x0, 0x5a,0x38,0x2, 0x41,0x7d,0xbe,0x14,0x0, 0x96,0x40,0x2, 0x41,0x7d, +0x49,0xf6,0x27,0xdc,0xbe,0xf4,0x1, 0x68,0x38,0x2, 0x41,0x7d,0xbe,0xf4,0x2, 0xd0, +0x40,0x2, 0x41,0x7d,0x7e,0x18,0x9, 0x3b,0x7a,0x1d,0x24,0x6d,0x0, 0x7e,0x18,0x0, +0x96,0x9f,0x10,0x7a,0x1d,0x2c,0xbe,0xf4,0x1, 0x68,0x28,0x10,0xbe,0xf4,0x1, 0xcc, +0x50,0xa, 0x7d,0x1f,0x6d,0x0, 0x9e,0x8, 0x1, 0x68,0x80,0x16,0xbe,0xf4,0x2, 0x6c, +0x28,0x31,0xbe,0xf4,0x2, 0xd0,0x50,0x2b,0x7d,0x3f,0x6d,0x22,0x7e,0x8, 0x2, 0xd0, +0x9f,0x1, 0x7a,0xd, 0x28,0x7e,0x1d,0x24,0x9e,0x18,0x4, 0x0, 0x7a,0x1d,0x24,0x12, +0x17,0x18,0x7e,0x14,0x0, 0x64,0x12,0x17,0x32,0x7a,0x1d,0x24,0x2e,0x18,0x4, 0x0, +0x7a,0x1d,0x24,0x7e,0xd, 0x24,0x7e,0x1d,0x2c,0x12,0x17,0x18,0x74,0xa, 0x1e,0x34, +0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7a,0x1d,0x2c,0xbe,0x18,0x0, +0x3c,0x28,0x7, 0x7e,0x18,0x0, 0x3c,0x7a,0x1d,0x2c,0x7e,0x1d,0x2c,0x7d,0x23,0x7e, +0x34,0x0, 0x96,0x9d,0x32,0x74,0x9, 0xac,0xbf,0x59,0x35,0x27,0xde,0xb, 0xf0,0xbe, +0xf0,0xa, 0x50,0x2, 0x21,0x99,0xda,0xf8,0xda,0x69,0x22,0x7d,0xd3,0x7e,0x44,0x4, +0x38,0x7e,0xa3,0x29,0x5c,0x74,0x40,0xa4,0x7d,0xb5,0x1b,0xb4,0xbe,0xd4,0x0, 0x3f, +0x38,0x29,0x7e,0xe4,0x0, 0x3f,0x9d,0xed,0x7e,0xf4,0x2, 0x68,0xad,0xef,0x7d,0x3f, +0x7d,0x2e,0x12,0x7b,0x57,0x7f,0x71,0xbe,0x78,0x0, 0x49,0x40,0x4, 0x7e,0x78,0x0, +0x49,0x7e,0x18,0x0, 0x49,0x9f,0x17,0x7f,0x71,0x80,0x7e,0x7d,0xcb,0x9e,0xc4,0x0, +0x3f,0xbd,0xcd,0x38,0x24,0x7d,0x5d,0x9d,0x5c,0x7e,0xf4,0x2, 0x7c,0xad,0xf5,0x7d, +0x3f,0x7d,0x2e,0x12,0x7b,0x57,0x7f,0x71,0xbe,0x78,0x0, 0x49,0x40,0x4, 0x7e,0x78, +0x0, 0x48,0x12,0x7c,0x7c,0x2f,0x71,0x80,0x50,0x7d,0xcb,0xb, 0xc4,0x1e,0xc4,0x7d, +0x5c,0x1b,0x54,0xbd,0x5d,0x40,0x6, 0x7d,0xf5,0x9d,0xfd,0x80,0x4, 0x7d,0xfd,0x9d, +0xfc,0x6d,0xee,0x7e,0x14,0x1, 0x52,0x12,0x7d,0x96,0x12,0x7b,0x57,0x7f,0x71,0xbd, +0x5d,0x7d,0x34,0x40,0x5, 0x12,0x7d,0x9e,0x80,0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71, +0xbe,0x78,0x0, 0x49,0x50,0x6, 0x7e,0x78,0x0, 0x49,0x80,0xd, 0x12,0x7c,0x7c,0x7d, +0x13,0x6d,0x0, 0xbf,0x70,0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22,0x9d,0x32,0x12,0x1a, +0x62,0x7d,0x13,0x7d,0x30,0xad,0x31,0x7c,0x76,0x7c,0x65,0xa, 0x24,0x22,0xca,0x79, +0x7c,0xe5,0x7c,0xfb,0x7e,0xe4,0xff,0xfc,0x7c,0xb4,0x12,0x7e,0xba,0x7d,0x3, 0x30, +0x14,0x2a,0x74,0x9, 0xac,0xbe,0x9, 0x75,0x27,0x89,0xbe,0x73,0x39,0x0, 0x78,0xa, +0x9, 0x65,0x27,0x8a,0xbe,0x63,0x39,0x2, 0x68,0x10,0xbe,0x73,0x39,0x1, 0x78,0xc, +0x9, 0x75,0x27,0x8a,0xbe,0x73,0x39,0x3, 0x78,0x2, 0x1e,0x4, 0x7e,0x70,0x9, 0xac, +0x7e,0x49,0x13,0x27,0x84,0xbe,0x14,0x2, 0x60,0x50,0x5, 0x12,0x7c,0x71,0x40,0xb, +0xbe,0x14,0x69,0xb0,0x28,0x1f,0x12,0x7c,0x71,0x28,0x1a,0x3e,0x4, 0xbe,0x14,0x2, +0x30,0x50,0x5, 0x12,0x7c,0x71,0x40,0xb, 0xbe,0x14,0x69,0xe0,0x28,0x7, 0x12,0x7c, +0x71,0x28,0x2, 0x3e,0x4, 0xbe,0x4, 0x1, 0x0, 0x28,0x4, 0x7e,0x4, 0x1, 0x0, 0x74, +0x9, 0xac,0xbf,0x49,0x25,0x28,0x36,0x49,0x33,0x27,0x82,0x12,0x7b,0x4c,0x7d,0x13, +0x5d,0x1e,0x7e,0x70,0x9, 0xac,0x7f,0x49,0xf3,0x28,0x36,0x74,0x9, 0xac,0xbe,0x49, +0x25,0x27,0x82,0xbd,0x2f,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x28,0x36,0x7d,0x2f,0x2d, +0x21,0x1b,0x58,0x20,0x80,0xd, 0xbd,0xf1,0x40,0x9, 0x2e,0x34,0x28,0x36,0x9d,0xf1, +0x1b,0x38,0xf0,0x74,0x9, 0xac,0xbf,0x49,0x25,0x28,0x38,0x74,0x9, 0xac,0xbe,0x49, +0x35,0x27,0x84,0x12,0x7b,0x4c,0x7d,0x13,0x5d,0x1e,0x7e,0x50,0x9, 0xac,0x5f,0x49, +0x32,0x28,0x38,0x74,0x9, 0xac,0xbe,0x49,0x5, 0x27,0x84,0xbd,0x3, 0x28,0xd, 0x7d, +0x2, 0x2e,0x4, 0x28,0x38,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x12,0xbd,0x31,0x40,0xe, +0x7e,0x50,0x9, 0xac,0x5f,0x2e,0x24,0x28,0x38,0x9d,0x31,0x1b,0x28,0x30,0xda,0x79, +0x22,0x74,0x9, 0xac,0xbf,0x49,0x25,0x28,0x38,0xbd,0x12,0x22,0x7d,0x34,0x6d,0x22, +0x9e,0x18,0x0, 0x49,0x22,0xca,0x3b,0x7d,0xb3,0x9f,0x77,0x7e,0xd4,0x8, 0xe8,0x7e, +0xa3,0x29,0x5d,0x74,0x40,0xa4,0x7d,0x95,0x1b,0x94,0xbe,0xb4,0x0, 0x3f,0x38,0x1f, +0x7e,0xe4,0x0, 0x3f,0x9d,0xeb,0x7e,0xf4,0x2, 0x4a,0x12,0x7d,0x80,0xbe,0x78,0x0, +0x47,0x40,0x4, 0x7e,0x78,0x0, 0x47,0x7e,0x18,0x0, 0x47,0x9f,0x17,0x7f,0x71,0x7d, +0xc9,0x9e,0xc4,0x0, 0x3f,0xbd,0xcb,0x38,0x3f,0x7d,0xf9,0x9e,0xf4,0x0, 0x40,0x7d, +0xeb,0x9d,0xef,0x7e,0xf4,0x2, 0x36,0x12,0x7d,0x80,0x7c,0xb4,0x12,0x15,0xa, 0x6d, +0x77,0x7e,0x64,0x42,0x8f,0x7f,0x3, 0x12,0x14,0xc4,0x40,0x4, 0x7e,0x78,0x0, 0x46, +0x7d,0x2d,0xe4,0x12,0x15,0xf, 0x7f,0x3, 0x12,0x14,0x9, 0x7f,0x1, 0x12,0x7d,0x8f, +0x12,0x14,0xc, 0x12,0x15,0x47,0x7f,0x71,0xbe,0xb4,0x0, 0x3f,0x28,0x6d,0xbd,0xcb, +0x28,0x69,0x7d,0xa9,0xb, 0xa4,0x1e,0xa4,0x7d,0xca,0x1b,0xc4,0xbd,0xcb,0x40,0xc, +0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x14,0x1, 0x56,0x80,0xa, 0x7d,0xfb,0x9d,0xfa, +0x6d,0xee,0x7e,0x14,0x1, 0x57,0x12,0x7d,0x96,0x12,0x7d,0x86,0xbd,0xcb,0x7d,0x3d, +0x40,0x5, 0x12,0x7d,0x9e,0x80,0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71,0xbe,0x78,0x0, +0x47,0x50,0x6, 0x7e,0x78,0x0, 0x47,0x80,0x22,0x7d,0x2d,0xe4,0x12,0x15,0xf, 0x6d, +0x11,0x7e,0x4, 0x42,0x8f,0x12,0x14,0x9, 0x7f,0x61,0x12,0x7d,0x8f,0x7f,0x6, 0x12, +0x14,0xc4,0x28,0x7, 0x7f,0x16,0x12,0x15,0x47,0x7f,0x71,0x7d,0x3f,0xda,0x3b,0x22, +0xad,0xef,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x7c,0x65,0x1a,0x24,0x7f,0x71,0x22,0x7f, +0x17,0x7c,0xb4,0x2, 0x15,0xa, 0x7f,0x17,0x12,0x17,0x29,0x7f,0x71,0x22,0x1e,0x34, +0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x22,0x2, 0x7b,0x5e,0xca,0x3b,0x7c,0xfb, +0x6c,0xee,0x80,0x6f,0x6c,0xdd,0x74,0x9, 0xac,0xbd,0x9, 0x45,0x28,0x3a,0x7e,0x70, +0x9, 0xac,0x7e,0x9, 0x53,0x27,0x86,0xbc,0x45,0x68,0x7, 0xb, 0xd0,0xbe,0xd0,0xa, +0x40,0xe4,0xbe,0xd0,0xa, 0x50,0x50,0x74,0x9, 0xac,0xbd,0x9, 0xc5,0x28,0x3a,0x49, +0x25,0x28,0x38,0x49,0x33,0x27,0x84,0x12,0x7e,0x2a,0x74,0x9, 0xac,0xbd,0x49,0x25, +0x28,0x36,0x74,0x9, 0xac,0xbe,0x12,0x7e,0x32,0x2d,0x31,0x7a,0x35,0x24,0xa, 0x3c, +0x9, 0xb3,0x28,0x90,0xb4,0x1, 0xe, 0x6d,0x33,0x74,0x2, 0xac,0xbc,0x59,0x35,0x32, +0x53,0x59,0x35,0x32,0x82,0x7e,0x35,0x24,0x7c,0xbd,0x7c,0x5e,0x7c,0x4c,0x12,0x7d, +0xa9,0xb, 0xe0,0xbc,0xfe,0x38,0x8d,0xda,0x3b,0x22,0x9d,0x32,0x12,0x1a,0x62,0x7d, +0x13,0x22,0x49,0x35,0x27,0x82,0x9d,0x32,0x2, 0x1a,0x62,0x6d,0x11,0xe4,0x12,0x0, +0x1e,0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x3c,0x29,0x2d,0xf0, +0x69,0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d,0x32,0x12,0x1a,0x62,0xbd,0x31,0x28, +0x16,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x3c,0x29,0x2d,0x13,0x69,0x20,0x1, 0x0, +0x69,0x30,0x0, 0x80,0x12,0x7e,0x2a,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x3c,0x29, +0x2d,0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff, +0x69,0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0, +0x7e,0xb3,0x29,0x61,0xbc,0xba,0x38,0x9d,0x7d,0x31,0x22,0x12,0x7e,0x3b,0xbe,0x34, +0x1, 0x90,0x28,0x3, 0xd2,0x16,0x22,0xc2,0x16,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3, +0x7e,0x17,0x29,0x4f,0xbd,0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22, +0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x17,0x32,0xbe,0x34,0x0, 0x10,0x50,0x4, 0x7e, +0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf,0x49,0x25,0x32,0x82,0xbd,0x2f,0x28,0x6, 0x49, +0x35,0x32,0x53,0x80,0x4, 0x59,0x35,0x32,0x53,0x59,0xf5,0x32,0x82,0xbe,0x34,0x1, +0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, 0x7e,0x10,0x9, 0xac,0x1f,0x49,0x10,0x27,0x82, +0xbe,0x14,0x4, 0x0, 0x40,0x20,0x7e,0x43,0x29,0x5c,0x12,0x2e,0x5a,0xbd,0x12,0x38, +0x15,0x49,0x10,0x27,0x84,0xbe,0x14,0x4, 0x0, 0x40,0xb, 0x7e,0x43,0x29,0x5d,0x12, +0x2e,0x5a,0xbd,0x12,0x28,0xc, 0x3e,0x34,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34, +0x1, 0x0, 0xda,0xf8,0x22,0xca,0xf8,0x7e,0x68,0x28,0x90,0x6c,0xaa,0x7e,0x70,0xff, +0x12,0x82,0xc9,0xe4,0xa, 0x4a,0x19,0xb4,0x1e,0x44,0x74,0xff,0x19,0xb4,0x1e,0x56, +0x19,0xb4,0x1e,0x60,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xe2,0x7e,0x73,0x28,0xf4,0xa5, +0xbf,0x0, 0x23,0x7e,0xb3,0x3b,0xd1,0x70,0x3, 0x2, 0x82,0x7, 0x6c,0xaa,0x7e,0x44, +0x7f,0xff,0x12,0x82,0xbf,0x79,0x40,0x0, 0x14,0x12,0x82,0xac,0xb, 0xa0,0xbe,0xa0, +0xa, 0x78,0xeb,0x2, 0x82,0x7, 0x7e,0xb3,0x3b,0xd1,0x70,0x3e,0xbe,0x70,0x0, 0x28, +0x39,0x6c,0xaa,0x80,0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x27,0x82,0x12,0x82, +0xbf,0x79,0x30,0x0, 0x14,0x49,0x34,0x27,0x84,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, +0x28,0x74,0x1, 0xa, 0x3a,0x19,0xb3,0x1e,0x44,0x19,0xa4,0x27,0x86,0xb, 0xa0,0x7e, +0xb3,0x28,0xf4,0xbc,0xba,0x38,0xce,0x2, 0x82,0x7, 0x6c,0xaa,0x12,0x82,0xb5,0x3e, +0x34,0x59,0x43,0x14,0x5e,0x59,0x43,0x14,0x60,0x59,0x43,0x14,0x86,0x59,0x43,0x14, +0x88,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xe4,0x7e,0xb3,0x3b,0xd1,0xbe,0xb3,0x28,0xf4, +0x28,0xd, 0xbe,0xb0,0x2, 0x40,0x8, 0x74,0x1, 0x7a,0xb3,0x3b,0xd0,0x80,0x5, 0xe4, +0x7a,0xb3,0x3b,0xd0,0x6c,0xaa,0x1, 0xcc,0x6c,0xff,0x7e,0x70,0x2, 0xac,0x7f,0x7f, +0x76,0x2d,0xf3,0x69,0x17,0x0, 0x14,0xbe,0x14,0x7f,0xff,0x78,0x2, 0x1, 0xc1,0xa, +0x2f,0x9, 0xb2,0x1e,0x60,0xb4,0xff,0x2, 0x80,0x2, 0x1, 0xc1,0x7e,0xb3,0x3b,0xd0, +0xb4,0x1, 0x61,0x49,0x3, 0x3b,0xd2,0xbe,0x4, 0x7f,0xff,0x68,0x57,0x49,0xb3,0x3b, +0xd2,0x69,0x7, 0x0, 0x14,0x7d,0x40,0x9d,0x4b,0x2d,0x40,0x49,0xb3,0x3b,0xe6,0x69, +0x7, 0x0, 0x28,0x7d,0x30,0x9d,0x3b,0x2d,0x30,0xbe,0x44,0x0, 0x20,0x58,0x4, 0x7e, +0x44,0x0, 0x20,0xbe,0x34,0x0, 0x20,0x58,0x4, 0x7e,0x34,0x0, 0x20,0x7e,0x3, 0x29, +0x5c,0x12,0x82,0xa2,0xbd,0x4, 0x58,0x2, 0x7d,0x40,0x7e,0x3, 0x29,0x5d,0x12,0x82, +0xa2,0xbd,0x3, 0x58,0x2, 0x7d,0x30,0x12,0x82,0x9a,0x59,0x40,0x14,0x5e,0x59,0x30, +0x14,0x60,0x80,0xf, 0x12,0x82,0x9a,0x59,0x10,0x14,0x5e,0x69,0x17,0x0, 0x28,0x59, +0x10,0x14,0x60,0xa, 0x1a,0x19,0xf1,0x1e,0x56,0x74,0x1, 0x19,0xb2,0x1e,0x60,0x80, +0x9, 0xb, 0xf0,0xbe,0xf0,0xa, 0x50,0x2, 0x1, 0x1a,0xb, 0xa0,0x7e,0xb3,0x3b,0xd1, +0xbc,0xba,0x28,0x2, 0x1, 0x18,0x6c,0xaa,0x12,0x82,0xbf,0x69,0x30,0x0, 0x14,0x59, +0x32,0x3b,0xd2,0x69,0x30,0x0, 0x28,0x59,0x32,0x3b,0xe6,0xb, 0xa0,0xbe,0xa0,0xa, +0x78,0xe6,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3,0x1e,0x56,0xb4,0xff,0x20,0x6c,0xff,0xa, +0x4f,0x9, 0xb4,0x1e,0x60,0xb4,0xff,0xe, 0xa, 0x3a,0x19,0xf3,0x1e,0x56,0x74,0x1, +0x19,0xb4,0x1e,0x60,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe2,0xb, 0xa0,0xbe, +0xa0,0xa, 0x78,0xd0,0x6c,0xaa,0x80,0x1e,0x7e,0x70,0x9, 0xac,0x7a,0x49,0x43,0x27, +0x82,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x59,0x42,0x14,0x86,0x49,0x33,0x27,0x84, +0x59,0x32,0x14,0x88,0xb, 0xa0,0x7e,0xb3,0x28,0xf4,0xbc,0xba,0x38,0xda,0x7e,0x34, +0x14,0x5e,0x7a,0x37,0x1e,0x50,0x7e,0x34,0x14,0x86,0x7a,0x37,0x1e,0x52,0x7e,0x34, +0x14,0xae,0x7a,0x37,0x1e,0x54,0x7e,0x73,0x3b,0xd1,0x7a,0x73,0x1e,0x4e,0x7e,0x73, +0x28,0xf4,0x7a,0x73,0x1e,0x4f,0x7e,0x8, 0x1e,0x4e,0x12,0x4, 0xad,0x6c,0xaa,0x80, +0x57,0x7e,0x70,0xff,0x6c,0xff,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12,0x14,0xae,0xa, +0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, 0x73,0x1e,0x56,0x80,0x7, 0xb, 0xf0,0xbe, +0xf0,0xa, 0x40,0xe2,0xbe,0x70,0xff,0x68,0x2d,0x12,0x82,0xc9,0x74,0x1, 0xa, 0x47, +0x19,0xb4,0x1e,0x44,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x24,0x27,0x82,0x7e,0x30,0x2, +0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20,0x0, 0x14,0x49,0x44,0x27,0x84,0x7e,0x50, +0x2, 0xac,0x57,0x12,0x82,0xac,0xb, 0xa0,0x7e,0x63,0x28,0xf4,0xbc,0x6a,0x38,0xa1, +0x6c,0xaa,0xa, 0x3a,0x9, 0xb3,0x1e,0x44,0xbe,0xb0,0x1, 0x68,0x13,0x12,0x82,0xb5, +0x7f,0x6, 0x2d,0x13,0x79,0x40,0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79,0x41,0x0, 0x28, +0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xdb,0x7e,0xf3,0x28,0xf4,0x7a,0xf3,0x3b,0xd1,0x6c, +0xaa,0xa, 0x3a,0x9, 0xb3,0x1e,0x44,0xb4,0x1, 0x2c,0x12,0x82,0x93,0x29,0xb1,0x0, +0xa, 0xb4,0x1, 0x6, 0x74,0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x82,0x93,0x29,0x31,0x0, +0xa, 0xa5,0xbb,0x3, 0x6, 0xe4,0x7a,0x1b,0xb0,0x80,0x38,0xa5,0xbb,0x0, 0x34,0x74, +0x2, 0x7a,0x1b,0xb0,0x80,0x2d,0x12,0x82,0x93,0x29,0xb1,0x0, 0xa, 0xbe,0xb0,0x2, +0x68,0x8, 0x60,0x6, 0x29,0xb1,0x0, 0x5a,0x70,0x14,0x74,0x1, 0x7a,0x1b,0xb0,0x7c, +0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1,0x27,0x86,0x80,0x5, 0x74,0x3, +0x7a,0x1b,0xb0,0x12,0x82,0x93,0x7e,0x1b,0xb0,0x39,0xb1,0x0, 0xa, 0xa, 0x3a,0x2d, +0x3d,0x29,0xb1,0x0, 0xa, 0x39,0xb1,0x0, 0x5a,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0x81, +0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c,0x22,0x7e,0x10,0x2, 0xac,0x1a,0x3e, +0x4, 0x22,0x7e,0x10,0x40,0xac,0x1, 0x9e,0x4, 0x0, 0x20,0x22,0x7f,0x6, 0x2d,0x12, +0x79,0x40,0x0, 0x28,0x22,0x7e,0x44,0x7f,0xff,0x7e,0x70,0x2, 0xac,0x7a,0x22,0x7e, +0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72, +0x27,0x86,0x22,0x2, 0x82,0xd6,0xca,0x79,0x6c,0xff,0x7e,0xd7,0x29,0x47,0x6c,0xee, +0x80,0x2f,0x7c,0xbe,0x12,0x83,0x21,0xbd,0x3d,0x48,0x24,0x7c,0xbe,0x12,0x5e,0xc, +0x60,0x1d,0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x26, +0x4a,0x6d,0x22,0x12,0xce,0xe4,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0xb, 0xf0,0xb, +0xe0,0x12,0x5f,0xec,0x38,0xcc,0x7a,0x73,0x27,0x67,0x7a,0xf3,0x28,0xf4,0xda,0x79, +0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xb3,0x25,0xce,0x9, 0x73,0x25,0xcf, +0x2, 0x21,0x5e,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x29,0x5b,0x7e,0x47,0x27,0x6d,0xe4, +0x7a,0xb3,0x27,0x7a,0x7e,0xb3,0x25,0xc4,0xbe,0xb0,0x0, 0x28,0x48,0x12,0xcf,0x79, +0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x26,0xa, 0x9, +0xe2,0x26,0xb, 0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12,0x4, 0xc0,0x6d,0x22,0x9e,0x27, +0x29,0x40,0xbd,0x12,0x58,0x19,0x12,0x84,0x4c,0x49,0x12,0x4, 0xc0,0x6d,0x22,0x9e, +0x27,0x29,0x3e,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x27,0x7a,0x80,0x6, 0xb, +0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x27,0x7b,0x7e,0xb3,0x25,0x57,0x70,0x40, +0x12,0x6f,0x7e,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e,0x50,0x2, 0xac,0x5f,0x9, 0xd2, +0x25,0xce,0x9, 0xe2,0x25,0xcf,0x12,0x84,0x4c,0x49,0x2, 0x5, 0x20,0x6d,0x11,0x9d, +0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e,0x49,0x20,0x5, 0x20,0xbd,0x21, +0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x27,0x7b,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc9, +0x12,0x84,0x55,0xe4,0x7a,0xb3,0x27,0x7d,0x12,0x96,0x1a,0xbe,0x37,0x27,0x73,0x28, +0x6, 0x74,0x1, 0x7a,0xb3,0x27,0x7d,0x74,0x1, 0x7a,0xb3,0x27,0x7e,0x6c,0xff,0x80, +0x1f,0x12,0x84,0x42,0x49,0x25,0x24,0xcb,0x7d,0x43,0x9d,0x42,0x7d,0x34,0x12,0x1a, +0x62,0xbe,0x37,0x27,0x71,0x8, 0x7, 0xe4,0x7a,0xb3,0x27,0x7e,0x80,0xa, 0xb, 0xf0, +0x7e,0x73,0x27,0x58,0xbc,0x7f,0x38,0xd9,0x6c,0xff,0x80,0x9, 0x12,0x84,0x42,0x59, +0x35,0x24,0xcb,0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x38,0xef,0xda,0x79,0xda, +0xd8,0x22,0x7c,0xbf,0x12,0x83,0x21,0x74,0x2, 0xac,0xbf,0x22,0xa, 0x1d,0xa, 0x2a, +0x2d,0x21,0x3e,0x24,0x22,0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6c,0xdd,0x7e,0x57,0x27, +0x6d,0x7d,0xf5,0x7e,0xe7,0x27,0x6b,0x7e,0x37,0x3b,0x50,0x4d,0x33,0x68,0x4, 0x7d, +0xf5,0xe, 0xf4,0x6c,0xff,0x7e,0xa3,0x29,0x5b,0x7c,0x8a,0x7e,0xb3,0x27,0x79,0x14, +0x68,0x21,0x14,0x68,0x14,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0x16,0x24,0x45,0x78, +0x10,0x7c,0xfa,0x7e,0x83,0x29,0x5a,0x80,0xa, 0x7e,0x73,0x29,0x5a,0x2c,0x87,0x80, +0x2, 0x6c,0x88,0x6c,0x99,0x80,0xf, 0x7c,0xb9,0x12,0x83,0x21,0xbe,0x34,0x2, 0x58, +0x8, 0x2, 0xb, 0xd0,0xb, 0x90,0x7e,0x33,0x27,0x58,0xbc,0x39,0x38,0xe9,0xbe,0xd0, +0x3, 0x40,0x2, 0xc1,0xd, 0x7e,0xa3,0x27,0x59,0xbe,0xa0,0x0, 0x38,0xb, 0xbe,0x30, +0x0, 0x28,0x37,0x7e,0xb3,0x25,0x57,0x70,0x31,0x6c,0x99,0x80,0x29,0xa, 0x29,0xa, +0x3f,0x2d,0x32,0x3e,0x34,0x49,0x23,0x5, 0x20,0xbd,0x2f,0x8, 0x17,0x49,0x3, 0x4, +0xc0,0xbd,0xe, 0x58,0xf, 0x6d,0x33,0x9d,0x3e,0x12,0xcd,0xe1,0xbd,0x3, 0x8, 0x4, +0xd2,0x0, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xd3,0x6d,0xee,0x9e,0xe7,0x29,0x3c, +0xbe,0xe7,0x7, 0x8, 0x8, 0x2, 0xc2,0x0, 0x30,0x0, 0x20,0x7e,0xb3,0x3c,0x3a,0x4, +0x7a,0xb3,0x3c,0x3a,0x7e,0x23,0x3c,0x3a,0xbe,0x20,0xa, 0x28,0x1d,0x74,0xa, 0x7a, +0xb3,0x3c,0x3a,0x74,0x1, 0x7a,0xb3,0x27,0x7c,0x80,0xf, 0x7e,0x23,0x3c,0x3a,0xbe, +0x20,0x0, 0x28,0x6, 0x1e,0x20,0x7a,0x23,0x3c,0x3a,0x6c,0xee,0xbe,0x30,0x0, 0x38, +0x5, 0xbe,0xa0,0x0, 0x28,0x60,0x7e,0xb3,0x27,0x7b,0xb4,0x1, 0x9, 0x7e,0xb3,0x27, +0x7e,0xbe,0xb0,0x1, 0x68,0x50,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x49,0x6c,0x99,0x80, +0x18,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x25,0xce,0x9, 0xd3,0x25,0xcf,0x7c,0xba, +0x7c,0x7d,0x12,0x57,0x68,0x18,0x7, 0xb, 0x90,0x12,0x86,0x12,0x38,0xe3,0x6c,0x99, +0x80,0x1c,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xa3,0x26,0xa, 0x9, 0xd3,0x26,0xb, 0x7c, +0xba,0x7c,0x7d,0x12,0x21,0x5e,0xbe,0x34,0xff,0x6a,0x48,0xa, 0xb, 0x90,0x7e,0xb3, +0x27,0x59,0xbc,0xb9,0x38,0xdc,0x6c,0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d,0x5e, +0x3e,0x54,0x49,0x55,0x5, 0x20,0xbd,0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, 0xb, +0x90,0xbc,0x89,0x38,0xe5,0x4c,0xee,0x78,0x25,0x7e,0xb3,0x3c,0x3b,0x4, 0x7a,0xb3, +0x3c,0x3b,0x7e,0x73,0x3c,0x3b,0xbe,0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3,0x3c, +0x3b,0x7e,0xb3,0x27,0x7c,0x60,0x2, 0xd2,0x18,0x12,0xb0,0xd, 0x80,0xf, 0x7e,0x73, +0x3c,0x3b,0xbe,0x70,0x0, 0x28,0x6, 0x1e,0x70,0x7a,0x73,0x3c,0x3b,0xda,0x79,0xda, +0xd8,0x22,0x7e,0xb3,0x27,0x58,0xbc,0xb9,0x22,0x7c,0xbf,0x12,0x86,0x2c,0x1a,0x4b, +0x7c,0xbf,0x12,0x83,0x21,0x7d,0xd3,0xbe,0xd4,0x2, 0x58,0x22,0xca,0xf8,0x7c,0xfb, +0x7e,0x70,0x2, 0x12,0xa2,0x79,0x7f,0x71,0x7c,0xbf,0x12,0x83,0x21,0x12,0x86,0x4a, +0x7f,0x17,0x12,0x17,0x85,0x7c,0xb7,0xda,0xf8,0x22,0x7d,0x13,0x1a,0x2, 0x1a,0x0, +0x22,0x7e,0xa3,0x27,0x58,0x4c,0xaa,0x78,0xc, 0x74,0xff,0x7a,0xb3,0x39,0x7f,0x6d, +0x33,0x7a,0x37,0x39,0x80,0x7e,0xb3,0x28,0xf5,0x70,0x5b,0xbe,0xa0,0x1, 0x78,0x56, +0xe4,0x12,0x83,0x21,0x7e,0x27,0x29,0x47,0x12,0xc8,0x39,0x2e,0x27,0x29,0x47,0xbd, +0x32,0x18,0x43,0x7e,0xa3,0x39,0x7f,0xbe,0xa0,0xff,0x78,0x15,0x7e,0x23,0x25,0xcf, +0x7a,0x23,0x39,0x7f,0x7e,0x30,0x2, 0xac,0x23,0x12,0x5f,0x35,0xb, 0x1a,0x30,0x80, +0x1c,0x7e,0xb3,0x25,0xcf,0xbe,0xb3,0x39,0x7f,0x78,0x1b,0x12,0xba,0x6a,0xb, 0x1a, +0x30,0x7e,0x27,0x39,0x80,0x2e,0x24,0x0, 0x14,0xbd,0x32,0x8, 0x9, 0x7a,0x37,0x39, +0x80,0xe4,0x7a,0xb3,0x27,0x58,0x22,0xca,0xd8,0xca,0x79,0x7e,0x74,0x3, 0x20,0x12, +0xa3,0x92,0x40,0x79,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x4, 0x7e,0x74,0x4, 0xb0,0x7e, +0x37,0x27,0x5e,0xbe,0x34,0x1, 0xc2,0x8, 0x64,0x6c,0xdd,0x80,0x58,0xc2,0x0, 0x7c, +0xbd,0x12,0x83,0x21,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xa2,0x79,0x7a, +0x35,0x24,0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x15,0x26,0x7d,0x31,0x3e,0x34,0x12, +0xcf,0x89,0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e,0x5, 0x28, +0xbe,0x5, 0x24,0x8, 0x8, 0xbe,0x14,0x0, 0xfa,0x58,0x2, 0xd2,0x0, 0x7c,0xbd,0x12, +0xbf,0x61,0x50,0x2, 0xc2,0x0, 0x30,0x0, 0xa, 0x7c,0xbd,0x12,0x96,0x11,0xac,0x7d, +0x12,0x96,0x23,0xb, 0xd0,0x7e,0x73,0x27,0x58,0xbc,0x7d,0x38,0xa0,0xda,0x79,0xda, +0xd8,0x22,0x12,0xa3,0x7b,0x12,0x93,0xba,0x12,0x86,0xc7,0x2, 0x87,0x5e,0xca,0x3b, +0x12,0x5e,0x1b,0x7e,0xb3,0x27,0x58,0x60,0x6, 0x7e,0xb3,0x39,0xfd,0x60,0x9, 0xe4, +0x7a,0xb3,0x39,0xff,0x7a,0xb3,0x39,0x84,0x7e,0xb3,0x39,0xfd,0x70,0x62,0x6c,0x99, +0x80,0x56,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x25,0xce,0x9, 0xf5,0x25,0xcf,0x7c,0xb9, +0x12,0xbf,0x61,0x40,0x41,0x6c,0xee,0x80,0x35,0x74,0x2, 0xac,0xbe,0x9, 0xd5,0x39, +0x85,0x9, 0xc5,0x39,0x86,0xa, 0x28,0xa, 0x3d,0x12,0xa1,0x50,0x78,0x1e,0xa, 0x2f, +0xa, 0x3c,0x12,0xa1,0x50,0x78,0x15,0x7c,0xb9,0x12,0x83,0x21,0xbe,0x34,0x3, 0x20, +0x58,0xa, 0x12,0x5f,0xf3,0x7c,0xb8,0x7c,0x7f,0x12,0x96,0x2b,0xb, 0xe0,0x7e,0x73, +0x39,0xff,0xbc,0x7e,0x38,0xc3,0xb, 0x90,0x7e,0x73,0x27,0x58,0xbc,0x79,0x38,0xa2, +0x7e,0x73,0x39,0x84,0x7a,0x73,0x39,0xff,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7e,0x18, +0x39,0xc1,0x7e,0x8, 0x39,0x85,0x12,0x1a,0xb, 0x1b,0xfd,0xe4,0x7a,0xb3,0x39,0xfd, +0xda,0x3b,0x22,0x7e,0xb3,0x29,0xef,0x70,0x41,0x12,0x77,0xdb,0x50,0xfb,0xe4,0x6c, +0x77,0x6c,0x66,0x12,0x37,0xc2,0x7e,0x8, 0x6, 0x48,0x7e,0x1f,0x6, 0x40,0x7e,0xb3, +0x2a,0x5f,0x12,0x88,0x4b,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, 0x12,0x37,0xc2, +0x7e,0x8, 0x6, 0xa8,0x7e,0x1f,0x6, 0x40,0x7e,0xb3,0x24,0xc4,0x12,0x88,0x4b,0x74, +0x2, 0x7a,0xb3,0x29,0xef,0xe4,0x7a,0xb3,0x15,0xa0,0x22,0xca,0xd8,0xca,0x79,0x7c, +0xfb,0x7f,0x51,0x7f,0x40,0x7f,0x15,0x12,0x6f,0x86,0x12,0x89,0x46,0x7e,0xe0,0x1, +0x12,0x39,0xb9,0x30,0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12,0x89,0x56, +0x6c,0xdd,0x80,0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a,0x20,0x74, +0x2, 0xac,0xbd,0x7f,0x5, 0x2d,0x15,0x12,0x89,0x4d,0xb, 0xd0,0x7e,0x73,0x29,0x61, +0xa, 0x7, 0x7e,0x63,0x29,0x60,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21,0x48,0xd4, +0x1b,0xe0,0x78,0xbc,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x29,0x60,0x12,0x88,0xb4,0xda, +0x79,0xda,0xd8,0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f,0x70,0x12,0x89,0x66,0x7c, +0xeb,0x6c,0xdd,0x80,0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x30, +0x6d,0x22,0x74,0x4, 0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e,0x6d,0x0, 0x12,0x17,0x34, +0x1b,0x6a,0x30,0xb, 0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79,0xda,0xd8,0x22,0xca,0x79, +0x7f,0x51,0x7f,0x40,0x7e,0xa3,0x29,0x61,0xa, 0x3a,0x7e,0xa3,0x29,0x60,0xa, 0x7a, +0x2d,0x73,0x7e,0xd, 0x29,0x7c,0x7f,0x12,0x88,0xb4,0xa, 0x3f,0x3e,0x34,0xca,0x39, +0x7e,0x1d,0x29,0x7f,0x4, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0xb3,0x29,0xee,0xb4,0x1, +0x22,0x6c,0xaa,0x80,0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d,0x13,0xb, 0xa, +0x20,0x7f,0x4, 0x2d,0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbc, +0xfa,0x38,0xe2,0xda,0x79,0x22,0x7e,0x8, 0x29,0x5a,0x2, 0x0, 0x2e,0xb, 0xa, 0x30, +0x2d,0x32,0x1b,0xa, 0x30,0x22,0x7e,0xb3,0x29,0x60,0x7e,0x73,0x29,0x61,0x12,0x10, +0xee,0x74,0x2, 0x2, 0x0, 0x1e,0x7c,0x7b,0xa5,0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe, +0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, +0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38, +0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e, +0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78,0xfb,0x7c,0xb9,0x22,0x7d,0x13,0x7d, +0x32,0x6d,0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x12,0x17,0x32,0x7d, +0x53,0xbe,0x54,0x0, 0xff,0x28,0x4, 0x7e,0x54,0x0, 0x40,0x22,0xca,0xf8,0x7e,0xf3, +0x29,0x5d,0x7a,0x37,0x1e,0x4a,0x7e,0x34,0x14,0xae,0x7a,0x37,0x1e,0x4c,0xe4,0x7a, +0xb3,0x1e,0x44,0x7a,0xb3,0x1e,0x45,0x7e,0x73,0x29,0x5c,0x7a,0x73,0x1e,0x46,0x7a, +0xf3,0x1e,0x47,0x7a,0xb3,0x1e,0x48,0x7a,0xb3,0x1e,0x49,0x7e,0x8, 0x1e,0x44,0x12, +0x8a,0x21,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x14,0xb0,0x2f,0x10,0x7e,0x33, +0x1e,0x46,0x6d,0x0, 0x12,0x17,0x34,0xa, 0x1f,0x6d,0x0, 0x12,0x17,0x34,0xda,0xf8, +0x22,0x12,0xc, 0x29,0x7e,0x37,0x14,0xae,0x22,0xca,0x3b,0x7a,0x41,0x2a,0x12,0x8e, +0xf3,0x74,0x9, 0xac,0xbf,0x7d,0x95,0x2e,0x94,0x26,0x4a,0x6d,0x88,0x7e,0xe7,0x29, +0x53,0xe4,0x39,0xb4,0x0, 0x6, 0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x25,0xce,0xf5, +0x35,0x9, 0xb3,0x25,0xcf,0xf5,0x36,0x7e,0x73,0x29,0x5b,0x7c,0x6d,0x7e,0x8, 0x0, +0x39,0x12,0x8c,0x79,0xf5,0x37,0xe5,0x35,0x7e,0x73,0x29,0x5a,0x7c,0x6c,0x7e,0x8, +0x0, 0x38,0x12,0x8c,0x79,0x7c,0xab,0xe5,0x38,0x7e,0x71,0x39,0x12,0x27,0x58,0x7d, +0xf3,0x7a,0xf5,0x41,0x7e,0xf4,0x14,0xae,0x7a,0xf5,0x43,0x85,0x38,0x3b,0x85,0x39, +0x3c,0x7a,0xa1,0x3d,0x85,0x37,0x3e,0x7e,0xb3,0x29,0x46,0xf5,0x3f,0x75,0x40,0x0, +0xe5,0x2a,0xb4,0x1, 0x8, 0xe5,0x3f,0x1e,0xb0,0x1e,0xb0,0xf5,0x3f,0x7e,0x8, 0x0, +0x3b,0x12,0x8a,0x21,0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x14,0xb0,0x6d,0xaa,0x2f,0x51, +0x7e,0x37,0x14,0xb2,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x14,0xb4,0x2f,0x10, +0x7a,0x1d,0x2b,0x7e,0x37,0x14,0xb6,0x6d,0x22,0x7d,0x3, 0x7e,0x37,0x14,0xb8,0x2f, +0x10,0x7a,0x1d,0x2f,0x7f,0x65,0xa, 0x4c,0xe5,0x35,0xa, 0x5b,0x9d,0x54,0xf5,0x33, +0x61,0xc9,0xa, 0x4d,0xe5,0x36,0xa, 0x5b,0x9d,0x54,0xf5,0x34,0x61,0xb3,0xe5,0x33, +0xbe,0xb0,0x0, 0x58,0x2, 0x61,0xb1,0x7e,0x73,0x29,0x5a,0xbe,0x71,0x33,0x18,0x2, +0x61,0xb1,0xe5,0x34,0xbe,0xb0,0x0, 0x58,0x2, 0x61,0xb1,0x7e,0x73,0x29,0x5b,0xbe, +0x71,0x34,0x18,0x2, 0x61,0xb1,0xe5,0x33,0x7e,0x71,0x34,0x12,0x21,0x5e,0x7e,0x53, +0x29,0x46,0xa, 0x25,0x7d,0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x8, 0x73,0xbd,0xef, +0x18,0xd, 0x7f,0x14,0x2e,0x34,0x0, 0x6, 0x7e,0x1b,0xb0,0x4, 0x7a,0x1b,0xb0,0xe5, +0x35,0xa, 0x2b,0xe5,0x33,0x12,0x57,0x2a,0x18,0xb, 0xe5,0x36,0xa, 0x2b,0xe5,0x34, +0x12,0x57,0x2a,0x8, 0x4c,0xe5,0x33,0x7e,0x71,0x34,0x7c,0x6e,0x12,0xc7,0x88,0xf5, +0x3a,0xb4,0x2, 0x6, 0x7d,0x3f,0xe, 0x34,0x9d,0xf3,0xe5,0x3a,0xbe,0xb0,0x2, 0x68, +0x5, 0xe5,0x3a,0xb4,0x1, 0x2b,0x12,0x8c,0x59,0xe5,0x33,0x12,0x8c,0x60,0x7e,0x1d, +0x2b,0x9f,0x10,0x7a,0x1d,0x2b,0x12,0x8c,0x59,0xe5,0x34,0x12,0x8c,0x60,0x7e,0x1d, +0x2f,0x9f,0x10,0x7a,0x1d,0x2f,0x12,0x8c,0x59,0x9f,0x51,0x1a,0x26,0x1a,0x24,0x9f, +0x61,0x5, 0x34,0xa, 0x2d,0xe5,0x36,0xa, 0x3b,0x2d,0x32,0x1a,0x27,0xe5,0x34,0x1a, +0x3b,0xbd,0x32,0x18,0x2, 0x41,0xfe,0x5, 0x33,0xa, 0x2c,0xe5,0x35,0xa, 0x3b,0x2d, +0x32,0x1a,0x37,0xe5,0x33,0x1a,0xfb,0xbd,0xf3,0x18,0x2, 0x41,0xf2,0xbe,0x58,0x0, +0x0, 0x78,0x2, 0xb, 0x5c,0xbe,0x68,0x0, 0x0, 0x78,0x2, 0xb, 0x6c,0x7e,0x1d,0x2b, +0x7f,0x5, 0x12,0x8c,0x6a,0x1b,0x4a,0x30,0x7e,0x1d,0x2f,0x7f,0x6, 0x12,0x8c,0x6a, +0x79,0x34,0x0, 0x2, 0x7e,0xb3,0x29,0x52,0x60,0xd, 0x1e,0xd4,0x1e,0xc4,0x50,0x4, +0x4e,0xd4,0x80,0x0, 0x14,0x78,0xf3,0xbe,0x68,0x0, 0x7f,0x28,0x4, 0x7e,0x68,0x0, +0x7f,0x7d,0x3d,0x39,0x74,0x0, 0x5, 0x74,0x9, 0xac,0xbe,0x9, 0x75,0x26,0x50,0x39, +0x74,0x0, 0x6, 0xbe,0x70,0xf, 0x28,0x6, 0x74,0xf, 0x39,0xb4,0x0, 0x6, 0x7e,0xa1, +0x35,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x26,0x51,0x7e,0xa1,0x36,0x7e,0x70,0x9, +0xac,0x7f,0x19,0xa3,0x26,0x52,0xda,0x3b,0x22,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x22, +0x1a,0x1b,0x1a,0x2, 0x12,0x17,0x18,0x7f,0x1, 0x22,0x74,0x6, 0x2f,0x11,0x14,0x78, +0xfb,0x12,0x17,0x34,0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c,0x87,0x7c, +0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38,0x14,0xa, +0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c,0xab,0xa, +0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, 0x54,0x7c, +0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53,0x7c,0xab, +0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22,0xca,0x3b,0x7f,0x40, +0x7e,0xe3,0x27,0x58,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, 0x3d,0x2d,0x39,0x7d, +0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, 0x70,0xbc,0x76,0x40, +0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d,0x39,0x7d,0x28,0x7e, +0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0xc1,0x7b,0x75,0x31,0x0, 0x6d,0x33,0x7a,0x35, +0x32,0x7a,0x35,0x34,0x9f,0x11,0x7a,0x1d,0x25,0x7a,0x1d,0x29,0x7e,0x18,0x1e,0x80, +0x7a,0x1d,0x2d,0x74,0xff,0x7e,0x34,0x1e,0x81,0x7e,0x24,0x0, 0x0, 0x7a,0x1b,0xb0, +0x7e,0x1d,0x2d,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x2d,0x39,0xb1,0x0, 0x3, 0x7e,0x1d, +0x2d,0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x2d,0x12,0x8e,0xa7,0x44,0x1, 0x7a,0x1b,0xb0, +0x75,0x24,0x0, 0xa1,0xeb,0x7e,0xa1,0x24,0x74,0x2, 0xa4,0x9, 0x95,0x25,0xce,0x9, +0x85,0x25,0xcf,0xe5,0x24,0xa, 0x5b,0x7f,0x14,0x2d,0x35,0x7e,0x1b,0x70,0xbc,0x7c, +0x78,0x77,0x5, 0x31,0x12,0x21,0x5a,0x7d,0x53,0x2e,0x55,0x32,0x7a,0x55,0x32,0x12, +0x21,0x5a,0x12,0x86,0x4a,0xa, 0x39,0x6d,0x22,0x12,0x17,0x18,0x12,0x8e,0x9a,0x12, +0x21,0x5a,0x12,0x86,0x4a,0xa, 0x38,0x6d,0x22,0x12,0x17,0x18,0x7f,0x1, 0x12,0x8e, +0x91,0x12,0x21,0x5a,0xbe,0x35,0x34,0x8, 0x6, 0x12,0x21,0x5a,0x7a,0x35,0x34,0x7e, +0x1d,0x2d,0x7e,0x1b,0x30,0xbc,0x39,0x28,0x3, 0x7a,0x1b,0x90,0x7e,0x1d,0x2d,0x29, +0x31,0x0, 0x2, 0xbc,0x39,0x50,0x4, 0x39,0x91,0x0, 0x2, 0x7e,0x1d,0x2d,0x29,0x31, +0x0, 0x1, 0xbc,0x38,0x28,0x4, 0x39,0x81,0x0, 0x1, 0x7e,0x1d,0x2d,0x29,0x31,0x0, +0x3, 0xbc,0x38,0x50,0x4, 0x39,0x81,0x0, 0x3, 0x5, 0x24,0xbe,0xe1,0x24,0x28,0x2, +0xa1,0x55,0xe5,0x31,0xbe,0xb0,0x0, 0x38,0x2, 0xc1,0x79,0x7e,0xd, 0x2d,0x12,0xbc, +0xfc,0x7e,0xf5,0x32,0x12,0x8c,0x59,0x7e,0x8, 0x0, 0x2, 0x12,0x17,0x85,0x12,0x8e, +0x9a,0x12,0x8e,0x91,0x12,0x55,0x1f,0x7e,0x1d,0x25,0x12,0x17,0x85,0x7a,0x1d,0x25, +0x12,0x55,0x1f,0x7e,0x1d,0x29,0x12,0x17,0x85,0x7a,0x1d,0x29,0x7e,0x2d,0x25,0x12, +0x8e,0x89,0x19,0xa3,0x3, 0x2, 0x7e,0x2d,0x29,0x12,0x8e,0x89,0x19,0xa3,0x3, 0x3, +0x7e,0x37,0x27,0x5e,0xbe,0x35,0x34,0x78,0xe, 0x7e,0x1d,0x25,0x7a,0x73,0x27,0x60, +0x7e,0x1d,0x29,0x7a,0x73,0x27,0x61,0x7e,0x37,0x3, 0x0, 0x4d,0x33,0x68,0x18,0x7e, +0x2d,0x25,0x7e,0x1d,0x29,0x12,0x21,0x5e,0x7e,0x25,0x34,0x7e,0x70,0x2, 0xac,0x7f, +0x2e,0x37,0x3, 0x0, 0x1b,0x38,0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, 0xa1, +0x9, 0x12,0x8e,0xaf,0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f, +0x22,0x7e,0x1d,0x29,0x2f,0x10,0x7a,0x1d,0x29,0x22,0x7f,0x1, 0x7e,0x1d,0x25,0x2f, +0x10,0x7a,0x1d,0x25,0x22,0x7f,0x16,0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x6c, +0xaa,0x12,0x8e,0xfc,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x7f, +0x1, 0x2e,0x14,0x0, 0x5, 0x7c,0xb8,0x54,0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29,0xb1, +0x0, 0x5, 0x30,0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, 0x7f, +0x1, 0xb, 0x16,0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e, +0x40,0xbf,0x22,0x7c,0xf5,0x7c,0xe6,0x7c,0xd7,0x7c,0xcb,0x22,0x7e,0x70,0x6, 0xac, +0x7a,0x2e,0x34,0x3, 0x3e,0x6d,0x22,0x22,0x6c,0xaa,0x12,0x8e,0xfc,0x12,0x8f,0x2a, +0x54,0xfe,0x12,0x8f,0x27,0x54,0x7, 0x12,0x8f,0x27,0x54,0xfb,0x7a,0xb, 0xb0,0xb, +0xa0,0xbe,0xa0,0x1e,0x40,0xe4,0x22,0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, 0x5, +0x7e,0xb, 0xb0,0x22,0xca,0x3b,0x12,0x8e,0xf3,0x75,0x65,0x0, 0x7e,0xa1,0x65,0x74, +0x6, 0xa4,0x12,0x8f,0xc1,0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc,0x12,0x8f,0xbb,0x50, +0x25,0x7f,0x7, 0x7c,0xbe,0x12,0x8f,0x83,0x50,0x1c,0x7f,0x7, 0x7c,0xbd,0x6c,0x77, +0x12,0x8f,0x86,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12,0x8f,0x86,0x50,0x6, +0x29,0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x65,0xe5,0x65,0xbe,0xb0,0x1e,0x40,0xbd,0xe4, +0xda,0x3b,0x22,0x7e,0x70,0x1, 0x7c,0x87,0x7c,0x9b,0x29,0xa0,0x0, 0x3, 0x29,0x60, +0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, 0x78,0x7, 0x29,0xa0,0x0, 0x2, 0x7e,0xb, +0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, 0x16,0xbd,0x1, 0x48,0xc, 0xa, 0x17,0xa, +0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3,0x22,0xc3,0x22,0x7e,0x70,0x1, 0x2, 0x8f, +0x86,0x7d,0xf5,0x2e,0xf4,0x3, 0x3e,0x6d,0xee,0x29,0xb7,0x0, 0x5, 0x22,0xca,0x3b, +0x7e,0xe3,0x27,0x58,0x6c,0xdd,0x6c,0xff,0x74,0x6, 0xac,0xbd,0x12,0x8f,0xc1,0x30, +0xe0,0x3d,0x6c,0xcc,0x80,0x2d,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x25,0xce,0x7a, +0xb3,0x1e,0x80,0x9, 0xa3,0x25,0xcf,0x7a,0xa3,0x1e,0x81,0x7f,0x7, 0x12,0x8f,0x83, +0x50,0xf, 0x7f,0x7, 0x7e,0xb3,0x1e,0x81,0x6c,0x77,0x12,0x8f,0x86,0x50,0x2, 0xb, +0xf0,0xb, 0xc0,0xbc,0xec,0x38,0xcf,0xbe,0xf0,0x2, 0x40,0x3, 0xd3,0x80,0x8, 0xb, +0xd0,0xbe,0xd0,0x1e,0x40,0xb0,0xc3,0xda,0x3b,0x22,0x7a,0x37,0x1e,0x48,0x7e,0x34, +0x14,0xb8,0x7a,0x37,0x1e,0x4c,0x7e,0x34,0x14,0xae,0x7a,0x37,0x1e,0x4a,0x7e,0x73, +0x29,0x5c,0x7a,0x73,0x1e,0x45,0x7e,0x73,0x29,0x5d,0x7a,0x73,0x1e,0x44,0x7e,0x37, +0x29,0x49,0x7a,0x37,0x1e,0x4e,0x7e,0x37,0x29,0x4b,0x7a,0x37,0x1e,0x50,0x7e,0x37, +0x29,0x4d,0x7a,0x37,0x1e,0x52,0x74,0x1, 0x7a,0xb3,0x1e,0x46,0x7a,0xb3,0x1e,0x47, +0x7e,0x8, 0x1e,0x44,0x7e,0x18,0x1e,0x54,0x12,0x8, 0x0, 0x7e,0x37,0x1e,0x5e,0x7e, +0x27,0x1e,0x5a,0xbd,0x23,0x28,0x2, 0x7d,0x32,0x22,0x7e,0x34,0x0, 0x5a,0x22,0x7e, +0xb3,0x3a,0xa5,0x70,0x2e,0x7e,0x73,0x3a,0x88,0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77, +0x7e,0xb3,0x3a,0xd0,0xb4,0x1, 0x3, 0x7e,0x70,0x6, 0xa, 0x37,0x2e,0x34,0xf, 0xf0, +0x12,0x5e,0x88,0x7c,0xab,0xe5,0x6a,0xa, 0x3b,0x2e,0x37,0x3b,0x93,0x7a,0x37,0x3b, +0x93,0x80,0xc, 0x7e,0xa3,0x3a,0x89,0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c, +0xba,0x2, 0x90,0xd4,0x75,0x6a,0x0, 0x7a,0xb3,0x3c,0x35,0xc2,0x1a,0x22,0x7e,0xb3, +0x3b,0x96,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x3b,0x96,0x22,0x7f,0x20, +0xc2,0x1, 0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x1a,0x62, +0x7c,0x27,0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x1a, +0x62,0x7c,0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x1a,0x62,0x7c,0x67,0x7c,0x72, +0xbc,0x32,0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, +0x7e,0x37,0x3b,0x48,0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0xca,0x3b,0xc2, +0x0, 0x6d,0x88,0x7e,0x64,0x0, 0x28,0x7e,0x37,0x27,0x5e,0xbe,0x34,0x5, 0xdc,0x8, +0x6, 0x2e,0x64,0x0, 0xa, 0x80,0x20,0xbe,0x34,0x4, 0xb0,0x8, 0x6, 0x2e,0x64,0x0, +0x5, 0x80,0x14,0xbe,0x34,0x3, 0x84,0x8, 0x6, 0x2e,0x64,0x0, 0x3, 0x80,0x8, 0xbe, +0x34,0x2, 0x58,0x8, 0x2, 0xb, 0x65,0x7a,0x87,0x3b,0x91,0xe4,0x7a,0xb3,0x1e,0x68, +0xe5,0x1e,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x1e,0x7e,0xb3,0x27,0x58,0x60,0xa, 0x7e, +0x87,0x7, 0xa, 0xbe,0x84,0x0, 0xc8,0x58,0xa, 0xc2,0x13,0x6d,0x88,0x7a,0x87,0x3b, +0x52,0x41,0x92,0x12,0x94,0x37,0x60,0xc, 0x7e,0x84,0x0, 0x64,0x7a,0x87,0x3b,0x48, +0x7a,0x67,0x3b,0x52,0x6c,0xff,0x80,0x7a,0xe4,0xa, 0x3f,0x19,0xb3,0x1e,0x44,0x12, +0x93,0x5, 0x9, 0xe3,0x25,0xcf,0x7e,0x8, 0x1e,0x62,0x7c,0x7e,0x12,0x94,0xe2,0x7d, +0x93,0x7e,0x87,0x3b,0x52,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x3b,0x52,0x7e,0x87,0x3b, +0x91,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x3b,0x91,0xe5,0x1e,0xbe,0xb0,0x5, 0x38,0x23, +0x7e,0x8, 0x3b,0x54,0xe5,0x24,0x7c,0x7e,0x12,0x93,0x2f,0x50,0x7, 0x12,0x92,0xfc, +0xd2,0x0, 0x80,0x2c,0x7e,0x8, 0x3b,0x54,0x7e,0x18,0x1e,0x62,0x12,0x93,0x88,0x50, +0x1f,0x80,0xd, 0xbd,0x69,0x38,0x19,0x7e,0x8, 0x1e,0x62,0x12,0x90,0xee,0x50,0x10, +0x12,0x92,0xfc,0x7e,0x8, 0x1e,0x68,0x7e,0x18,0x1e,0x62,0x12,0x96,0x46,0xd2,0x0, +0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x28,0x2, 0x21,0xb8,0x30,0x0, 0x39,0x6c, +0xff,0x80,0x22,0x12,0x93,0x5, 0x9, 0xe3,0x25,0xcf,0x7e,0x8, 0x1e,0x68,0x7c,0x7e, +0x12,0x93,0x2f,0x40,0x9, 0xa, 0x3f,0x9, 0xb3,0x1e,0x44,0xb4,0x1, 0x5, 0x7c,0xbf, +0x12,0x93,0x11,0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x38,0xd6,0x75,0x1e,0x0, +0x7e,0x34,0x0, 0x64,0x7a,0x37,0x3b,0x48,0x7e,0x63,0x1e,0x68,0x7e,0x70,0x6, 0xac, +0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1e,0x68,0x7e,0x8, 0x3b,0x54,0x12,0x1a,0xb, +0x1b,0xfd,0x7e,0x37,0x3b,0x48,0x4d,0x33,0x78,0x32,0x7e,0x37,0x3b,0x52,0xbd,0x36, +0x40,0x41,0x7d,0x36,0x1e,0x34,0xbe,0x37,0x3b,0x91,0x38,0x37,0x90,0x60,0x51,0x12, +0x92,0xf3,0x7e,0x73,0x25,0xcb,0xa, 0x37,0xbd,0x32,0x8, 0x27,0x90,0x60,0x50,0x12, +0x92,0xf3,0x7e,0x73,0x25,0xca,0xa, 0x37,0xbd,0x32,0x8, 0x17,0x6c,0xff,0x80,0x7, +0x7c,0xbf,0x12,0x93,0x11,0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x38,0xf1,0xd2, +0x0, 0x80,0x6, 0x6d,0x33,0x7a,0x37,0x3b,0x52,0xa2,0x0, 0x92,0x13,0x12,0x93,0x71, +0xda,0x3b,0x22,0xe4,0x93,0x7c,0x7b,0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, 0x8f, +0x19,0xb8,0x1e,0x44,0x22,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xb3,0x25,0xce,0xf5,0x24, +0x22,0x7c,0xab,0x7e,0xb3,0x27,0x7c,0x70,0x15,0x12,0x96,0x9, 0x68,0x10,0x7e,0xb3, +0x29,0x58,0xbe,0xb0,0x1, 0x68,0x7, 0x7c,0xba,0x6c,0x77,0x2, 0x5f,0x5a,0x22,0x7c, +0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac,0x5a,0x7f,0x70,0x2d,0xf2, +0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e,0x7b,0xb0,0xbc,0xb6,0x38, +0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7,0x0, 0x1, 0xbc,0xb7,0x38, +0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x38,0xc9,0xa2,0x1, +0x22,0x30,0x13,0x13,0x12,0x96,0x1, 0x68,0x6, 0x7e,0xb3,0x3c,0x3a,0x60,0x8, 0x7e, +0x34,0xb, 0xb8,0x7a,0x37,0x3b,0x50,0x22,0x7f,0x61,0x7f,0x50,0x7e,0x6b,0x90,0x80, +0x1f,0x29,0x86,0x0, 0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9,0x7c,0x78,0x12,0x93,0x2f, +0x50,0x2, 0xd3,0x22,0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc,0x78,0x50,0xe9,0xb, 0x90, +0x29,0x76,0x0, 0x2, 0xbc,0x79,0x50,0xd9,0xc3,0x22,0xca,0x3b,0x7e,0xf3,0x29,0x61, +0x12,0x5f,0xfd,0x40,0x6f,0x6d,0x33,0x9e,0x37,0x29,0x3c,0x3e,0x34,0xbe,0x37,0x7, +0x8, 0x18,0x61,0x7e,0xb3,0x15,0xa2,0x70,0x5b,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x54, +0x7e,0x37,0x29,0x3e,0x7a,0x35,0x26,0x7e,0x67,0x29,0x40,0x6c,0xee,0x80,0x40,0x7c, +0xbe,0x12,0x5e,0xc, 0x60,0x37,0x7e,0x70,0x2, 0xac,0x7e,0x12,0x93,0xa, 0x9, 0xa3, +0x25,0xcf,0x7a,0xa1,0x25,0x74,0x2, 0xa4,0x49,0x35,0x4, 0xc0,0xbd,0x36,0x48,0x13, +0xe5,0x24,0xa, 0x2b,0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xc0,0xbe,0x35, +0x26,0x58,0xa, 0x7c,0xbe,0x12,0x96,0x11,0xac,0x7e,0x12,0x96,0x23,0xb, 0xe0,0x12, +0x5f,0xec,0x38,0xbb,0xda,0x3b,0x22,0x6c,0xaa,0x7e,0x23,0x29,0x5b,0x7e,0x33,0x29, +0x5a,0xac,0x32,0x7e,0xe4,0x0, 0x3, 0x7d,0xf1,0x8d,0xfe,0x7d,0x3f,0x7e,0x4, 0x0, +0x6, 0x8d,0x10,0x7c,0x43,0x7e,0x7, 0x27,0x5e,0xbe,0x4, 0x5, 0x78,0x8, 0x12,0x7d, +0xef,0x2e,0xe4,0x0, 0xf, 0x7d,0x4e,0x7c,0x59,0x7d,0xe1,0x2e,0xe4,0x0, 0xc, 0x80, +0x16,0xbe,0x4, 0x3, 0xe8,0x8, 0x16,0x7d,0xef,0x2e,0xe4,0x0, 0xa, 0x7d,0x4e,0x7c, +0x59,0x7d,0xe1,0x2e,0xe4,0x0, 0x8, 0x7d,0x4e,0x7c,0xb9,0x80,0x18,0xbe,0x4, 0x3, +0x20,0x8, 0xe, 0x7d,0xf, 0x2e,0x4, 0x0, 0x6, 0x7c,0x51,0xb, 0x16,0x7c,0xb3,0x80, +0x4, 0x7c,0x57,0x7c,0xb4,0x12,0x96,0x1a,0xa, 0x45,0xbd,0x34,0x38,0x8, 0xa, 0x3b, +0xbe,0x37,0x27,0x5a,0x50,0x29,0x90,0x60,0x51,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e, +0xb3,0x25,0xcb,0xa, 0x3b,0xbd,0x32,0x8, 0x16,0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0, +0xa, 0x2b,0x7e,0xb3,0x25,0xca,0xa, 0x3b,0xbd,0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c, +0xba,0x22,0xca,0x3b,0x7c,0xc7,0x7c,0xfb,0x7f,0x40,0x6d,0xbb,0x7e,0xa3,0x29,0x5a, +0x7e,0x73,0x29,0x5b,0x4c,0xcc,0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14, +0xbc,0xbc,0x78,0x6, 0xa, 0x6c,0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0, +0x1, 0x80,0xb, 0x7c,0xba,0x14,0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, +0x7e,0x34,0x0, 0x6, 0xe4,0x12,0x1a,0x30,0x7e,0x73,0x29,0x5a,0xa, 0x37,0x1b,0x34, +0x7a,0x4b,0x70,0x7e,0x73,0x29,0x5b,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c, +0xec,0x80,0x1d,0x75,0x25,0x0, 0x7c,0xdf,0x80,0xb, 0x12,0x25,0x63,0x70,0xb, 0x5, +0x25,0xb, 0xb4,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf0,0xe5,0x25,0x60,0x7, 0x1b,0xe0, +0xbe,0xe0,0x0, 0x58,0xde,0x7c,0xec,0x80,0x26,0x75,0x25,0x0, 0x1a,0xaf,0xb, 0xa4, +0x7d,0x3a,0x7c,0xd7,0x80,0xb, 0x12,0x25,0x63,0x70,0xe, 0x5, 0x25,0xb, 0xb4,0xb, +0xd0,0x7e,0x73,0x29,0x5a,0xbc,0x7d,0x18,0xed,0xe5,0x25,0x60,0x7, 0x1b,0xe0,0xbe, +0xe0,0x0, 0x58,0xd5,0x12,0x95,0xf8,0x80,0x1d,0x75,0x25,0x0, 0x7c,0xdf,0x80,0xb, +0x12,0x25,0x63,0x70,0xb, 0x5, 0x25,0xb, 0xb4,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf0, +0xe5,0x25,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x29,0x5b,0xbc,0x7e,0x18,0xdb,0x12,0x95, +0xf8,0x80,0x22,0x75,0x25,0x0, 0x1a,0x6f,0xb, 0x64,0x80,0xb, 0x12,0x25,0x63,0x70, +0xe, 0x5, 0x25,0xb, 0xb4,0xb, 0xd0,0x7e,0x73,0x29,0x5a,0xbc,0x7d,0x18,0xed,0xe5, +0x25,0x60,0xa, 0xb, 0xe0,0x7e,0x73,0x29,0x5b,0xbc,0x7e,0x18,0xd6,0x7d,0x3b,0x39, +0x74,0x0, 0x5, 0x7d,0x3b,0xda,0x3b,0x22,0x1a,0xac,0xb, 0xa4,0x7d,0x3a,0x7c,0xe7, +0x22,0x7e,0xb3,0x27,0x7c,0xbe,0xb0,0x1, 0x22,0x7e,0xb3,0x3a,0xd0,0xbe,0xb0,0x1, +0x22,0x6c,0x77,0x12,0x5f,0x5a,0x7e,0x70,0x2, 0x22,0x7e,0x37,0x27,0x5c,0x2e,0x37, +0x27,0x5a,0x22,0x9, 0xb3,0x25,0xce,0x9, 0x73,0x25,0xcf,0x7c,0x6b,0x7e,0xa3,0x39, +0x84,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x39,0xc1,0x19,0x72,0x39,0xc2,0x7c,0xba, +0x4, 0x7a,0xb3,0x39,0x84,0x22,0x7f,0x60,0x7e,0x6b,0xa0,0xbe,0xa0,0xa, 0x50,0x1b, +0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, 0x2d,0x15,0xb, 0x14,0x12, +0x1a,0xb, 0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0,0x22,0x7e,0xa3,0x28,0xf5, +0xbe,0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x28,0xf4,0x50,0x19,0x7e,0xb3,0x28,0xfe,0xbe, +0xb3,0x33,0x75,0x28,0x14,0x7e,0xb3,0x33,0x75,0x4, 0x7a,0xb3,0x33,0x75,0x7a,0xa3, +0x28,0xf4,0x80,0x5, 0xe4,0x7a,0xb3,0x33,0x75,0x7e,0xb3,0x28,0xf4,0x70,0x5, 0xe4, +0x7a,0xb3,0x28,0xfd,0x22,0x12,0x96,0xab,0x2, 0x96,0x6c,0x7e,0xb3,0x28,0xf4,0x70, +0x2d,0x7e,0x73,0x28,0xf5,0xbe,0x70,0x0, 0x28,0x24,0x7e,0xb3,0x32,0x96,0x70,0x18, +0x12,0x96,0xe8,0x7e,0x73,0x28,0xf5,0x7a,0x73,0x28,0xf4,0x74,0x1, 0x7a,0xb3,0x28, +0xfb,0x7e,0xb3,0x32,0x96,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x32,0x96,0x22,0xe4,0x7a, +0xb3,0x32,0x96,0x7a,0xb3,0x28,0xfb,0x22,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e,0x18, +0x39,0x7, 0x7e,0x8, 0x39,0x43,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x73,0x27,0x68,0x7a, +0x73,0x38,0xf9,0x7a,0x73,0x27,0x67,0x22,0x12,0x97,0x13,0x12,0x24,0x37,0x7a,0xb3, +0x28,0xfe,0x22,0x7e,0xa3,0x27,0x58,0xe4,0x7a,0xb3,0x32,0x73,0x7e,0xb3,0x3a,0x8b, +0x60,0x4d,0x6c,0x33,0x80,0x42,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x25,0xcf,0x7e, +0x10,0x1, 0xbe,0x20,0x2, 0x28,0x35,0x6c,0x0, 0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e, +0x70,0x2, 0xac,0x70,0x9, 0x93,0x25,0xcf,0xa, 0x29,0xa, 0x32,0x12,0x57,0x2c,0x18, +0x2, 0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74,0x2, 0x7a,0xb3,0x32,0x73,0x80,0x6, +0xb, 0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc,0xa3,0x38,0xba,0x2, 0x97,0x70,0x22, +0xca,0xf8,0x7e,0x33,0x27,0x58,0x6c,0x22,0x80,0x3a,0x12,0xa3,0x72,0x9, 0x5, 0x25, +0xcf,0x7e,0xa0,0x1, 0x6c,0x99,0x80,0x26,0xbc,0x92,0x68,0x20,0x12,0xa2,0x6f,0x9, +0xf3,0x25,0xcf,0xa, 0x28,0xa, 0x31,0x12,0x57,0x2c,0x18,0xb, 0xa, 0x2f,0xa, 0x30, +0x12,0x57,0x2c,0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc,0x39, +0x38,0xd6,0xb, 0x20,0xbc,0x32,0x38,0xc2,0x7e,0xb3,0x33,0x73,0xbe,0xb0,0x0, 0x28, +0x12,0x14,0x7a,0xb3,0x33,0x73,0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c,0x7a, +0x37,0x29,0x47,0x7e,0xb3,0x3a,0x8b,0x70,0x58,0x7e,0xb3,0x3c,0x3a,0x70,0x52,0x7e, +0xb3,0x3a,0xf, 0x70,0x4c,0x7e,0x37,0x3b,0x52,0xbe,0x34,0x0, 0x14,0x50,0x42,0x7e, +0x37,0x27,0x5e,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x27,0x58,0xbe,0xb0,0x3, +0x40,0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x25,0x59,0xbe,0xb0,0x3, 0x50,0x9, +0x7e,0xb3,0x25,0x58,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x25,0xca,0xbe,0xb0,0x8, +0x50,0x9, 0x7e,0xb3,0x25,0xcb,0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3,0x33, +0x73,0xda,0xf8,0x22,0x12,0x98,0x68,0x2, 0x98,0x3a,0x7e,0xb3,0x28,0xfb,0x70,0x27, +0x7e,0xb3,0x32,0x73,0xb4,0x2, 0xd, 0x7e,0x73,0x28,0xf4,0xbe,0x70,0x1, 0x28,0x4, +0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x32,0x7e,0x7e,0x73,0x32,0x7f,0xbe,0x73,0x32, +0x7e,0x28,0x4, 0x7a,0x73,0x32,0x7e,0x22,0xca,0x3b,0x7e,0xb3,0x28,0xf4,0x7c,0xab, +0x7e,0x8, 0x28,0x90,0x7e,0x90,0xc, 0x7e,0x80,0x6, 0xb4,0x1, 0x22,0x7e,0xb3,0x27, +0x89,0x60,0xb, 0x7e,0xb3,0x29,0x5c,0x14,0xbe,0xb3,0x27,0x89,0x78,0x3, 0x7e,0x90, +0x18,0x7e,0xb3,0x29,0x5d,0x14,0xbe,0xb3,0x27,0x8a,0x78,0x3, 0x7e,0x90,0x24,0x4c, +0xaa,0x78,0x5, 0x12,0x1d,0x8e,0x61,0x9, 0x6c,0xff,0x7e,0x70,0x9, 0xac,0x7f,0x9, +0xe3,0x27,0xe0,0xbe,0xe0,0xff,0x78,0x2, 0x61,0x0, 0x12,0x9b,0x30,0x70,0x28,0x12, +0x9b,0x20,0x19,0xb3,0x32,0x49,0xa, 0x3f,0x19,0xb3,0x32,0x69,0xa, 0x3e,0x7c,0xb7, +0x7e,0x34,0x0, 0x1, 0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x6e,0x34,0xff,0xff,0x5e, +0x37,0x32,0x80,0x7a,0x37,0x32,0x80,0x12,0x9b,0x1d,0x50,0x60,0x7e,0x70,0x9, 0xac, +0x7e,0x9, 0xb3,0x27,0x89,0xbe,0xb3,0x39,0x0, 0x78,0xa, 0x9, 0x53,0x27,0x8a,0xbe, +0x53,0x39,0x2, 0x68,0x10,0xbe,0xb3,0x39,0x1, 0x78,0x41,0x9, 0xb3,0x27,0x8a,0xbe, +0xb3,0x39,0x3, 0x78,0x37,0x7e,0x34,0x0, 0x1, 0x7c,0xbe,0x60,0x5, 0x3e,0x34,0x14, +0x78,0xfb,0x7d,0x23,0x5e,0x27,0x32,0x80,0x78,0x22,0xa, 0x2e,0x9, 0xb2,0x32,0x3f, +0xbe,0xb0,0x1, 0x28,0x17,0x74,0x30,0xa, 0x2e,0x19,0xb2,0x32,0x3f,0x4e,0x37,0x32, +0x80,0x7a,0x37,0x32,0x80,0xe4,0xa, 0x3f,0x19,0xb3,0x32,0x69,0xbe,0xe0,0xff,0x78, +0x2, 0x61,0x0, 0xa, 0x3e,0x9, 0xb3,0x32,0x3f,0x7a,0xb3,0x32,0x3d,0x9, 0xb3,0x32, +0x49,0x7a,0xb3,0x32,0x3e,0x7f,0x50,0x2d,0xb3,0x7e,0x5b,0xb0,0xb4,0x2, 0x2, 0x80, +0x2, 0x41,0xce,0x12,0x9b,0x44,0x12,0x9b,0x13,0x12,0x9b,0x55,0x7e,0x70,0x4, 0xac, +0x7e,0x49,0x23,0x33,0x78,0x12,0x9b,0x3a,0x9d,0x32,0x12,0x1a,0x62,0x7d,0xe3,0x7e, +0x73,0x32,0x3d,0xa, 0x27,0xbd,0x2f,0x28,0x59,0xbd,0x2e,0x28,0x55,0x7e,0x50,0x4, +0xac,0x5e,0x49,0x22,0x33,0x76,0x7e,0xd0,0x9, 0xac,0xdf,0x59,0x26,0x27,0xdc,0x7e, +0x50,0x4, 0xac,0x5e,0x49,0x22,0x33,0x78,0x7e,0xd0,0x9, 0xac,0xdf,0x59,0x26,0x27, +0xde,0xe4,0xa, 0x2f,0x19,0xb2,0x32,0x69,0x7e,0xb3,0x32,0x3e,0x4, 0x7a,0xb3,0x32, +0x3e,0x7e,0x63,0x32,0x3e,0xbe,0x60,0x32,0x50,0x2, 0x41,0xbe,0xe4,0x7a,0xb3,0x32, +0x3e,0x7e,0xb3,0x32,0x3d,0xbc,0xb8,0x40,0x2, 0x41,0xbe,0x4, 0x7a,0xb3,0x32,0x3d, +0x41,0xbe,0xbe,0x70,0x1, 0x40,0x6a,0x12,0x9b,0x44,0x7e,0xd0,0x9, 0xac,0xdf,0x49, +0xd6,0x27,0xdc,0x9d,0xd2,0x49,0x33,0x33,0x78,0x49,0xc6,0x27,0xde,0x9d,0xc3,0x12, +0x9b,0xc, 0xbe,0xb0,0x10,0x50,0xa, 0xa, 0x3f,0x2e,0x34,0x32,0x69,0x4, 0x7a,0x39, +0xb0,0x7d,0x3c,0x2d,0x3d,0xbe,0x34,0x0, 0x64,0x58,0x36,0x12,0x9b,0xc, 0xa, 0x9b, +0xad,0x9d,0x7d,0x39,0x12,0x9b,0x4e,0xe, 0x34,0x12,0x9b,0x28,0x59,0x32,0x27,0xdc, +0x12,0x9b,0xc, 0xa, 0x3b,0xad,0x3c,0x7d,0x23,0xe, 0x24,0xe, 0x24,0xe, 0x24,0xe, +0x24,0x7e,0x70,0x4, 0xac,0x7e,0x49,0x33,0x33,0x78,0x12,0x9b,0x28,0x59,0x32,0x27, +0xde,0x7e,0x70,0x9, 0xac,0x7f,0x49,0x93,0x27,0xdc,0x7e,0x50,0x4, 0xac,0x5e,0x59, +0x92,0x33,0x76,0x49,0x33,0x27,0xde,0x59,0x32,0x33,0x78,0x12,0x9b,0x1d,0x50,0x21, +0xbe,0xa0,0x1, 0x78,0x1c,0x12,0x9b,0x13,0xbe,0x34,0x0, 0x96,0x40,0x6, 0xbe,0x34, +0x3, 0xa2,0x28,0xd, 0x7e,0xb3,0x32,0x3d,0xbe,0xb0,0x2, 0x40,0x1c,0x1e,0xb0,0x80, +0x14,0x7e,0xb3,0x32,0x3d,0xbc,0xb9,0x40,0x6, 0x7a,0x83,0x32,0x3d,0x80,0xa, 0xbe, +0xb0,0x1, 0x28,0x5, 0x14,0x7a,0xb3,0x32,0x3d,0xe4,0x7a,0xb3,0x32,0x3e,0x7e,0xb3, +0x32,0x3d,0xa, 0x3e,0x19,0xb3,0x32,0x3f,0x7e,0xb3,0x32,0x3e,0x80,0x2c,0x7e,0x5b, +0xb0,0x70,0x15,0x12,0x9b,0x13,0x7e,0x50,0x4, 0xac,0x5e,0x59,0x32,0x33,0x76,0x12, +0x9b,0x3a,0x59,0x32,0x33,0x78,0x80,0x18,0x12,0x9b,0x30,0xb4,0x1, 0x12,0x7e,0xb3, +0x28,0xf4,0xbe,0xb0,0x0, 0x28,0x9, 0x12,0x9b,0x20,0xa, 0x3e,0x19,0xb3,0x32,0x49, +0xb, 0xf0,0xbe,0xf0,0xa, 0x68,0x2, 0x1, 0xaa,0xda,0x3b,0x22,0xa, 0x3f,0x9, 0xb3, +0x32,0x69,0x22,0x7e,0x70,0x9, 0xac,0x7f,0x49,0x33,0x27,0xdc,0x22,0xa2,0x14,0x22, +0xa, 0x3e,0x19,0x93,0x32,0x3f,0xe4,0x22,0x2d,0x32,0x7e,0x50,0x9, 0xac,0x5f,0x22, +0xa, 0x3e,0x2d,0x31,0x7d,0x20,0x7e,0x1b,0xb0,0x22,0x7e,0x70,0x9, 0xac,0x7f,0x49, +0x33,0x27,0xde,0x22,0x7e,0x70,0x4, 0xac,0x7e,0x49,0x23,0x33,0x76,0x22,0xe, 0x34, +0xe, 0x34,0xe, 0x34,0x22,0x9d,0x32,0x12,0x1a,0x62,0x7d,0xf3,0x22,0xca,0x3b,0x12, +0x9d,0x50,0x38,0x2, 0x81,0x20,0x7e,0xc3,0x34,0x8b,0x4c,0xcc,0x78,0x3d,0x7a,0xb3, +0x34,0x8b,0xe4,0x7a,0xb3,0x34,0x8d,0x6c,0xaa,0x80,0x26,0x12,0x9c,0x2b,0x7e,0x70, +0x2, 0xac,0x7a,0x9, 0xd3,0x25,0xce,0x9, 0xe3,0x25,0xcf,0x7a,0x49,0xd0,0x19,0xe4, +0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12,0x9c,0x35,0x59,0x34,0x0, 0x2, 0xb, +0xa0,0x7e,0xb3,0x27,0x58,0xbc,0xba,0x38,0xd2,0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80, +0x31,0x12,0x9c,0x2b,0x7e,0x49,0xd0,0x9, 0xe4,0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70, +0x4, 0x1b,0xf0,0x80,0x1b,0x12,0x9c,0x35,0x7d,0x23,0x49,0x34,0x0, 0x2, 0x12,0x9b, +0x55,0xbe,0xf4,0x0, 0x23,0x8, 0x9, 0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x68,0x1, +0xb, 0xa0,0xbc,0xfa,0x38,0xcb,0x4c,0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x34,0x8d, +0xbe,0x70,0x4, 0x40,0x22,0x6c,0xaa,0x80,0xe, 0x12,0x9c,0x2b,0x9, 0xb4,0x0, 0x8, +0xbe,0xb0,0x5, 0x68,0x6, 0xb, 0xa0,0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75, +0x68,0x0, 0x12,0x9c,0x3c,0x80,0xf, 0x7c,0xb7,0x4, 0x7a,0xb3,0x34,0x8d,0x80,0x6, +0x12,0x9c,0x3c,0x75,0x68,0x0, 0xe5,0x68,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a, +0x2e,0x44,0x34,0x8e,0x22,0x7c,0xbd,0x7c,0x7e,0x2, 0x21,0x5e,0xe4,0x7a,0xb3,0x34, +0x8c,0x7a,0xb3,0x34,0x8b,0x7a,0xb3,0x34,0x8d,0x22,0xca,0x3b,0x7c,0xe7,0x7c,0xdb, +0xbe,0xd0,0x0, 0x28,0x8, 0x12,0x9d,0x58,0x58,0x3, 0xc3,0xa1,0x3e,0x6c,0xaa,0x6c, +0xff,0x12,0x9c,0x35,0xbe,0x34,0x2, 0x58,0x58,0x6, 0x7e,0x44,0x0, 0x96,0x80,0x4, +0x7e,0x44,0x0, 0xc8,0x7c,0xcd,0x80,0xb, 0x7c,0xbc,0x12,0x9d,0x41,0x8, 0xc, 0xb, +0xa0,0xb, 0xc0,0x7e,0xb3,0x29,0x5c,0xbc,0xbc,0x38,0xed,0x7c,0xcd,0x80,0xf, 0xa, +0x3c,0x1b,0x34,0x7c,0xb7,0x12,0x9d,0x41,0x8, 0x9, 0xb, 0xa0,0x1b,0xc0,0xbe,0xc0, +0x0, 0x38,0xec,0x7c,0xce,0x80,0xb, 0x12,0x9d,0x49,0xbd,0x34,0x8, 0xc, 0xb, 0xf0, +0xb, 0xc0,0x7e,0xb3,0x29,0x5d,0xbc,0xbc,0x38,0xed,0x7c,0xce,0x80,0x11,0x7c,0xbd, +0xa, 0x3c,0x1b,0x34,0x12,0x21,0x5e,0xbd,0x34,0x8, 0x9, 0xb, 0xf0,0x1b,0xc0,0xbe, +0xc0,0x0, 0x38,0xea,0xbe,0xf0,0x5, 0x40,0x5, 0xbe,0xa0,0x3, 0x28,0x8, 0xe4,0x7a, +0xb3,0x39,0x4, 0xc3,0x80,0x58,0xbe,0xa0,0x1, 0x68,0x10,0x7e,0x50,0x3, 0xac,0x5a, +0xa, 0x3f,0xbd,0x32,0x8, 0x15,0xbe,0xa0,0x2, 0x40,0x10,0x74,0x32,0x7a,0xb3,0x39, +0x4, 0x7a,0xd3,0x39,0x5, 0x7a,0xe3,0x39,0x6, 0x80,0xe, 0x7e,0xb3,0x39,0x4, 0xbe, +0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x39,0x4, 0x7e,0xb3,0x39,0x4, 0x60,0x1f,0x7e, +0xb3,0x39,0x5, 0xbc,0xbd,0x78,0x17,0x7e,0xb3,0x39,0x6, 0xa, 0x2b,0x7d,0x12,0xb, +0x14,0xa, 0x3e,0xbd,0x31,0x18,0x7, 0xb, 0x34,0xbd,0x32,0x48,0x1, 0xd3,0xda,0x3b, +0x22,0x7c,0x7e,0x12,0x21,0x5e,0xbd,0x34,0x22,0x7c,0xbd,0x7c,0x7c,0x2, 0x21,0x5e, +0x7e,0xb3,0x27,0x58,0xbe,0xb0,0x0, 0x22,0x7e,0xb3,0x29,0x5c,0xa, 0x2b,0x1b,0x24, +0xa, 0x3d,0xbd,0x32,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x7e,0xf0,0xa, 0x6c,0x11, +0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1e,0x48,0x7e,0x34,0x7f, +0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1e,0x44,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1e, +0x46,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d,0x12,0x9e,0xd6,0x7c, +0x7d,0x7c,0x6f,0x12,0x9e,0xd6,0x6c,0x0, 0x80,0x3d,0x6c,0xee,0x80,0x16,0x74,0x9, +0xac,0xbe,0x9, 0x65,0x1e,0x48,0x74,0x9, 0xac,0xb0,0x9, 0x75,0x27,0x86,0xbc,0x76, +0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x19,0x7e,0x70,0x9, 0xac, +0x70,0x2e,0x34,0x27,0x82,0x7e,0x30,0x9, 0xac,0x31,0x2e,0x14,0x1e,0x44,0x74,0x9, +0x12,0x17,0xb9,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xbf,0x74,0x9, 0xac,0xbf,0xca, +0x59,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0x28,0x36,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x79, +0xda,0xd8,0x22,0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0x7c,0x57,0xc1,0xb8,0x7e, +0xf0,0x9, 0xac,0xf6,0x9, 0x87,0x28,0x3a,0x7c,0x98,0x7e,0xd0,0x9, 0xac,0xd5,0x9, +0xb6,0x27,0x86,0xbc,0xb9,0x68,0x2, 0xc1,0xb6,0xbe,0x90,0xff,0x78,0x2, 0xc1,0xb6, +0x12,0x9e,0xcc,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x28,0x90,0x7e,0xf0,0x9, +0x70,0xc, 0xac,0xf5,0x7d,0x97,0x2e,0x94,0x27,0x82,0x6d,0x88,0x80,0xa, 0xac,0xf6, +0x7d,0x97,0x2e,0x94,0x28,0x36,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x9e,0xcc,0x1b,0x7a, +0xd0,0x69,0xf4,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6, +0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x87,0x12,0x9e,0xcc,0x39,0x87, +0x0, 0x5, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x88,0x12,0x9e,0xcc,0x39,0x87, +0x0, 0x6, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x89,0x12,0x9e,0xcc,0x39,0x87, +0x0, 0x7, 0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x8a,0x12,0x9e,0xcc,0x39,0x87, +0x0, 0x8, 0xb, 0xa0,0x80,0x8, 0xb, 0x50,0xbc,0x45,0x28,0x2, 0xc1,0xf, 0xb, 0x60, +0xbe,0x60,0xa, 0x50,0x2, 0xc1,0xb, 0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac, +0xfa,0x7f,0x70,0x2d,0xf7,0x22,0x7e,0x8, 0x1e,0x44,0x12,0x9e,0x3, 0x7c,0x1b,0x22, +0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31,0xa, 0x4a,0x9, 0x74,0x32,0x74, +0xbe,0x73,0x32,0x7e,0x50,0xe, 0x7d,0x24,0x2e,0x24,0x32,0x74,0x7c,0xb7,0x4, 0x7a, +0x29,0xb0,0xd3,0x22,0xbe,0x73,0x32,0x7e,0x40,0x9, 0xbe,0x70,0xff,0x68,0x4, 0xe4, +0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4,0x32,0x74,0x80,0x17,0xa, 0x3a,0x9, 0xb3,0x32, +0x74,0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x32,0x74,0xd3,0x22,0xe4,0x19,0xb3, +0x32,0x74,0xc3,0x22,0x6c,0xaa,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x28,0x36,0x12, +0x59,0x99,0x59,0x32,0x27,0x82,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x28,0x38,0x12, +0x59,0x99,0x59,0x32,0x27,0x84,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3a,0x19, +0xb4,0x27,0x86,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3b,0x19,0xb4,0x27,0x87, +0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3c,0x19,0xb4,0x27,0x88,0x7e,0x90,0x9, +0xac,0x9a,0x9, 0xb4,0x28,0x3d,0x19,0xb4,0x27,0x89,0x7e,0x90,0x9, 0xac,0x9a,0x9, +0xb4,0x28,0x3e,0x19,0xb4,0x27,0x8a,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0x98,0x22,0x7e, +0x8, 0x32,0x73,0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x1a,0x30,0x7e,0x8, 0x32,0x82,0x7e, +0x34,0x0, 0x14,0xe4,0x12,0x1a,0x30,0x7e,0x8, 0x32,0x53,0x7e,0x34,0x0, 0x14,0x2, +0x1a,0x30,0xca,0x79,0x7e,0x73,0x27,0x58,0xbe,0x70,0x2, 0x50,0x3, 0x2, 0xa0,0x50, +0x6c,0xaa,0x80,0x74,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0x93,0x25,0xcf,0xbe,0x90,0x0, +0x28,0x64,0x6c,0x88,0x80,0x58,0x7e,0x70,0x2, 0xac,0x78,0x12,0xa1,0x5f,0x12,0xa1, +0x58,0xbc,0xbf,0x78,0x47,0x4c,0xee,0x78,0x43,0xa, 0x2e,0xa, 0x39,0x12,0x57,0x2c, +0x48,0x3a,0x12,0xa0,0x53,0x7d,0x3, 0x7e,0x17,0x27,0x5e,0x7e,0x24,0x0, 0x2, 0x7d, +0x31,0x12,0x16,0xe6,0xbd,0x3, 0x58,0x24,0xbe,0x14,0x3, 0x20,0x8, 0x1e,0x7e,0x70, +0x2, 0xac,0x7e,0x49,0x23,0x4, 0xc0,0x7e,0x37,0x7, 0x12,0xe, 0x34,0xe, 0x34,0xbd, +0x23,0x58,0x9, 0x7c,0xb8,0x6c,0x77,0x12,0x5f,0x5a,0x80,0x14,0xb, 0x80,0x7e,0xb3, +0x27,0x58,0xbc,0xb8,0x38,0xa0,0xb, 0xa0,0x7e,0xb3,0x27,0x58,0xbc,0xba,0x38,0x84, +0xda,0x79,0x22,0x7c,0xbf,0x7c,0x7e,0x2, 0x21,0x5e,0xca,0x79,0x7e,0x23,0x27,0x58, +0x6c,0xaa,0x80,0x2f,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0x13,0x25,0xcf,0x6c,0x33,0x6c, +0x0, 0x80,0x1a,0xbc,0xa, 0x68,0x14,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xf3,0x25,0xcf, +0xa, 0x2f,0xa, 0x31,0x12,0xa1,0x50,0x78,0x2, 0xb, 0x30,0xb, 0x0, 0xbc,0x20,0x38, +0xe2,0xb, 0xa0,0xbc,0x2a,0x38,0xcd,0xbe,0x30,0x0, 0x38,0x2, 0x21,0x45,0x75,0x24, +0x0, 0x75,0x25,0x0, 0x75,0x26,0x0, 0x6c,0xaa,0x80,0x68,0x7e,0x70,0x2, 0xac,0x7a, +0x12,0xa1,0x5f,0x12,0xa0,0x53,0x7d,0xe3,0x4c,0xff,0x78,0x5, 0x7c,0xbf,0x4, 0x80, +0xa, 0x12,0xa1,0x58,0xbc,0xbf,0x7c,0xbf,0x78,0x8, 0x14,0x12,0xa1,0x48,0x7d,0x43, +0x80,0xe, 0x14,0x7c,0x7e,0x12,0x21,0x5e,0x7d,0x43,0x7c,0xbf,0x4, 0x12,0xa1,0x48, +0x7d,0xdf,0x2d,0xd4,0xbe,0x44,0x0, 0xa, 0x58,0xa, 0xbe,0xf4,0x0, 0xa, 0x58,0x4, +0x5, 0x24,0x80,0x1d,0xbe,0xd4,0x0, 0x14,0x58,0x4, 0x5, 0x25,0x80,0x13,0x7e,0x34, +0x0, 0x28,0xad,0x3e,0x7e,0x24,0x0, 0x64,0x12,0x16,0xe6,0xbd,0x3d,0x8, 0x2, 0x5, +0x26,0xb, 0xa0,0x7e,0x73,0x27,0x58,0xbc,0x7a,0x38,0x90,0xe5,0x25,0xa, 0xeb,0xe5, +0x24,0xa, 0x2b,0x2d,0x2e,0xe5,0x26,0xa, 0xeb,0x2d,0xe2,0x7d,0x2e,0x7c,0xb5,0xbe, +0xb0,0x1, 0x28,0x11,0x1e,0x70,0xa, 0x37,0xa, 0xeb,0xbd,0xe3,0x8, 0x7, 0x7c,0xba, +0x6c,0x77,0x12,0x5f,0x5a,0xda,0x79,0x22,0x7c,0x7e,0x12,0x21,0x5e,0x7d,0xf3,0x22, +0x9d,0x32,0x12,0x1a,0x62,0x4d,0x33,0x22,0x90,0x60,0x50,0xe4,0x93,0x14,0x22,0x9, +0xf3,0x25,0xce,0x9, 0xe3,0x25,0xcf,0x22,0xca,0x3b,0x6c,0xff,0x41,0x22,0x9f,0x77, +0x6d,0x33,0x74,0x2, 0xac,0xbf,0x59,0x35,0x1e,0x44,0x6c,0xee,0x6c,0xdd,0x80,0x63, +0x6c,0xaa,0x6c,0x99,0x80,0x46,0x12,0xa2,0x6f,0x9, 0x33,0x25,0xcf,0x1a,0x2d,0x1a, +0x33,0x9d,0x32,0x12,0x1a,0x62,0x7d,0x3, 0x1a,0x2f,0x1a,0x38,0x9d,0x32,0x12,0x1a, +0x62,0x2d,0x30,0xbe,0x34,0x0, 0x2, 0x18,0x21,0x7e,0xb3,0x27,0x58,0xb4,0x1, 0x2, +0x80,0x13,0x12,0x5f,0xfd,0x40,0x13,0x1a,0x33,0x3e,0x34,0x49,0x33,0x4, 0xc0,0xbe, +0x37,0x29,0x40,0x48,0x5, 0x7e,0xa0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0x23,0x27,0x58, +0xbc,0x29,0x38,0xb2,0x4c,0xaa,0x78,0x9, 0x7c,0xbf,0x7c,0x7d,0x12,0xa2,0x65,0xb, +0xe0,0xb, 0xd0,0x7e,0xc3,0x29,0x5d,0xbc,0xcd,0x38,0x95,0xa, 0x1e,0x6d,0x0, 0x7f, +0x17,0x12,0x17,0x85,0x7f,0x71,0xbe,0x78,0x0, 0x0, 0x8, 0x24,0x7c,0x7c,0x1e,0x70, +0xa, 0x27,0xa, 0x3e,0xbd,0x32,0x48,0x18,0x7d,0x4f,0x74,0x2, 0xac,0xbf,0x59,0x45, +0x1e,0x44,0xbe,0x44,0x0, 0xc8,0x8, 0x8, 0x7e,0x34,0x0, 0xc8,0x59,0x35,0x1e,0x44, +0xb, 0xf0,0x7e,0x73,0x29,0x5c,0xbc,0x7f,0x28,0x2, 0x21,0x6e,0x6c,0xff,0x80,0x23, +0x7c,0xbf,0x12,0x83,0x21,0x7d,0x43,0x74,0x2, 0xac,0xbf,0x9, 0xa5,0x25,0xce,0x74, +0x2, 0xa4,0x49,0x55,0x1e,0x44,0x2e,0x57,0x29,0x47,0xbd,0x54,0x8, 0x3, 0x12,0xa2, +0x5e,0xb, 0xf0,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x38,0xd5,0xda,0x3b,0x22,0x7c,0xbf, +0x6c,0x77,0x2, 0x5f,0x5a,0x12,0x21,0x5e,0x1a,0x26,0x1a,0x24,0x2f,0x71,0x22,0x7e, +0x70,0x2, 0xac,0x79,0x9, 0x83,0x25,0xce,0x22,0xca,0x79,0x7c,0xa7,0x7c,0x8b,0x7e, +0xb3,0x29,0x5c,0x7a,0xb3,0x1e,0x44,0x7e,0xb3,0x29,0x5d,0x7a,0xb3,0x1e,0x45,0x7e, +0x70,0x2, 0xac,0x78,0x9, 0x93,0x25,0xce,0x9, 0x83,0x25,0xcf,0x9f,0x77,0x1a,0x3a, +0x1a,0x79,0x9d,0x73,0x61,0x2b,0x7a,0xf1,0x2b,0xbe,0xf0,0x0, 0x58,0xe, 0x1a,0x3f, +0x1a,0x29,0x9d,0x23,0x1a,0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x2b,0x7e,0xb3,0x1e,0x44, +0xbc,0xbf,0x18,0xe, 0x1a,0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32,0x7c,0xb7, +0xf5,0x2b,0x1a,0x2a,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x2a,0x80,0x3d,0x85,0x2a, +0x2c,0xe5,0x2a,0xbe,0xb0,0x0, 0x58,0x10,0xe5,0x2a,0x1a,0x3b,0x1a,0x28,0x9d,0x23, +0x1a,0x38,0x2d,0x32,0x7c,0xb7,0xf5,0x2c,0x7e,0xb3,0x1e,0x45,0xbe,0xb1,0x2a,0x18, +0x10,0x1a,0x38,0xe5,0x2a,0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5, +0x2c,0xe5,0x2b,0x7e,0x71,0x2c,0x12,0xa2,0x65,0x5, 0x2a,0x1a,0x3a,0x1a,0x28,0x2d, +0x23,0xe5,0x2a,0x1a,0x3b,0xbd,0x32,0x8, 0xb5,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d, +0x23,0x1a,0x3f,0xbd,0x32,0x18,0x2, 0x41,0xa6,0x7f,0x17,0xda,0x79,0x22,0x7e,0x33, +0x27,0x58,0x7e,0xb3,0x3a,0xd0,0x60,0x29,0x6c,0x22,0x80,0x21,0x12,0xa3,0x72,0xbe, +0x10,0x2, 0x40,0x10,0x7e,0x3, 0x29,0x5c,0xa, 0x20,0x9e,0x24,0x0, 0x3, 0xa, 0x31, +0xbd,0x32,0x8, 0x7, 0x7c,0xb2,0x6c,0x77,0x12,0x5f,0x5a,0xb, 0x20,0xbc,0x32,0x38, +0xdb,0x22,0x74,0x2, 0xac,0xb2,0x9, 0x15,0x25,0xce,0x22,0xe4,0x7a,0xb3,0x39,0x84, +0x7e,0xb3,0x27,0x58,0x60,0x6, 0x7e,0xb3,0x39,0xfd,0x60,0x5, 0xe4,0x7a,0xb3,0x39, +0xff,0x22,0x6c,0x99,0x6c,0x88,0x80,0xf, 0x7c,0xb8,0x12,0x83,0x21,0xbe,0x34,0x1, +0xf4,0x8, 0x2, 0xb, 0x90,0xb, 0x80,0x7e,0x73,0x27,0x58,0xbc,0x78,0x38,0xe9,0xbe, +0x90,0x2, 0x38,0x2, 0xc3,0x22,0xd3,0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x70, +0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x1c,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x14, +0x1e,0x44,0x74,0xc, 0x12,0x17,0xda,0x6d,0x11,0x7e,0x4, 0x7f,0xff,0x6c,0xee,0x80, +0x13,0x12,0x77,0xa1,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd,0xc, 0x28,0x2, +0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58,0xa, 0x7e,0xb3, +0x27,0x68,0x70,0x4, 0x6d,0x33,0x81,0xb3,0xbe,0xd4,0x4, 0xb0,0x8, 0x2, 0xd2,0x0, +0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1e,0x44,0xbd,0x4d,0x58,0x6, 0x49,0xd5, +0x1e,0x46,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0,0x3, 0x78,0x4, +0x6d,0x33,0x80,0x7f,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xd0,0x9f,0x55,0x6c, +0xee,0x80,0xb, 0x12,0x77,0xa1,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xe0,0xbc,0xfe, +0x38,0xf1,0xa, 0x1f,0x12,0xa4,0xc1,0x9f,0x55,0x6c,0xee,0x80,0x1d,0x12,0xa4,0xb8, +0xb, 0x1a,0x90,0x7d,0x39,0x12,0x1a,0x62,0x7d,0xc3,0xbd,0x1c,0x28,0xa, 0x7d,0x39, +0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xdf,0x6d,0x11, +0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0xa4,0xc1,0xbd,0x1d,0x8, 0x4, 0x7d,0x1d, +0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c,0xee,0x80,0xd, +0x12,0xa4,0xb8,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0,0xbc,0xfe,0x38, +0xef,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35, +0x22,0x6d,0x0, 0x7f,0x15,0x12,0x17,0x85,0x7d,0x13,0x22,0x7e,0xb3,0x2a,0xa, 0xb4, +0x1, 0x31,0x12,0xa5,0x4, 0x7e,0x1f,0x3c,0x13,0x7a,0x37,0x24,0xa, 0x7e,0x34,0xc, +0xd8,0x7a,0x37,0x24,0x6, 0x12,0xa5,0xb, 0x12,0xa5,0x14,0xe4,0x7a,0xb3,0x24,0x5, +0x7e,0x34,0x0, 0x20,0x7a,0x37,0x24,0xc, 0x7a,0xb3,0x24,0x4, 0x7e,0x8, 0x24,0x2, +0x2, 0xd, 0x7, 0x22,0xa9,0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0x73,0x29,0x5a,0x7a, +0x73,0x24,0x2, 0x22,0x7e,0x73,0x29,0x5b,0x7a,0x73,0x24,0x3, 0x22,0x7e,0x43,0x29, +0x5b,0x7e,0x53,0x29,0x5a,0xac,0x54,0x7e,0x17,0x27,0x75,0x12,0xa5,0x4, 0x6d,0x0, +0x80,0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x3c,0x13,0x2d,0xf4,0xb, 0x7a,0x30,0xbd, +0x13,0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x7, 0x1a,0xb, 0xf8,0x50,0x9d,0x51,0x1b,0xf8, +0x50,0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44,0x7, 0x1a,0xb, +0x48,0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5,0x22,0x7e,0xa0, +0x1, 0x7e,0x47,0x7, 0x8, 0x7e,0x4, 0x0, 0xc8,0xbe,0x44,0xfd,0xa8,0x58,0x12,0x7e, +0xb3,0x27,0x80,0x60,0x7, 0xe4,0x7a,0xb3,0x27,0x81,0x80,0x38,0x7e,0xa0,0x5, 0x80, +0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x7e,0x14,0x0, 0x2, 0x12,0xa5,0xc9,0x8, 0x5, +0x7e,0xa0,0x4, 0x80,0x1f,0x7e,0x34,0xff,0xfc,0x12,0xa5,0xc7,0x8, 0x5, 0x7e,0xa0, +0x3, 0x80,0x11,0x7e,0x34,0xff,0xfd,0x12,0xa5,0xc7,0x8, 0x5, 0x7e,0xa0,0x2, 0x80, +0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0xad,0x30,0x7d,0x21,0x12,0x16,0xe6,0xbd,0x34, +0x22,0xe4,0x7a,0xb3,0x34,0x88,0x7a,0xb3,0x27,0x80,0x74,0x2, 0x2, 0xa5,0xe0,0xe4, +0x7a,0xb3,0x29,0xef,0x7a,0xb3,0x2a,0xb, 0x22,0x74,0x2, 0x7a,0xb3,0x34,0x88,0x74, +0x1, 0x7a,0xb3,0x27,0x80,0x2, 0xa5,0xdf,0x7e,0x60,0x4, 0x7e,0x27,0x3c,0x33,0xbe, +0x24,0x3, 0xe8,0x28,0x3, 0x7e,0x60,0x8, 0x7e,0xb3,0x27,0x80,0xb4,0x1, 0x1a,0x7e, +0x73,0x34,0x89,0xbc,0x76,0x50,0xf, 0xe4,0x7a,0xb3,0x27,0x81,0x12,0xa5,0xd1,0x7e, +0xb3,0x34,0x89,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x34,0x89,0x7e,0xb3, +0x27,0x81,0xb4,0x1, 0x17,0x7e,0xa3,0x34,0x8a,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a, +0xb3,0x27,0x81,0x7c,0xba,0x4, 0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x34, +0x8a,0x22,0x6c,0xaa,0x80,0x26,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0x80,0x49, +0x32,0x4, 0x0, 0x2d,0x31,0x59,0x32,0x5, 0x80,0x30,0x6, 0xe, 0x49,0x12,0x4, 0x60, +0x49,0x32,0x5, 0xe0,0x2d,0x31,0x59,0x32,0x5, 0xe0,0xb, 0xa0,0x7e,0xb3,0x29,0x61, +0xa, 0x3b,0x7e,0xb3,0x29,0x60,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6, +0x22,0xd2,0x0, 0x6c,0xaa,0x6c,0x77,0x80,0x1f,0x7e,0x63,0x29,0x5b,0xa, 0x16,0xa, +0x27,0x2d,0x21,0x7c,0x65,0x7e,0x50,0x2, 0xac,0x56,0x49,0x22,0x5, 0x20,0xbe,0x24, +0xfe,0xc, 0x58,0x2, 0xb, 0xa0,0xb, 0x70,0x7e,0xb3,0x29,0x5a,0xbc,0xb7,0x38,0xd9, +0xa, 0x2b,0x1e,0x24,0xa, 0x3a,0xbd,0x32,0x8, 0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0x7e, +0x63,0x29,0x5c,0x7e,0xa3,0x29,0x5d,0x7e,0x70,0x1, 0x80,0xf, 0xa, 0x17,0x12,0xa7, +0x19,0xbe,0x24,0xff,0x38,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b,0x14,0xa, +0x27,0xbd,0x21,0x48,0xe7,0x7e,0x70,0x2, 0x80,0x13,0x7e,0x50,0x2, 0xac,0x57,0x49, +0x22,0x4, 0xc0,0xbe,0x24,0xff,0x38,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b, +0x15,0xa, 0x27,0xbd,0x21,0x48,0xe3,0xc3,0x22,0x7e,0xb3,0x29,0x5b,0xa, 0x2b,0x2d, +0x21,0x3e,0x24,0x49,0x22,0x4, 0xc0,0x22,0x7e,0xb3,0x3a,0x13,0xb4,0x1, 0x3, 0x2, +0xa7,0x7f,0x7e,0xb3,0x3a,0x79,0x4, 0x7a,0xb3,0x3a,0x79,0x7e,0xb3,0x3a,0x7, 0xb4, +0x2, 0x18,0x7e,0xb3,0x3a,0x78,0x4, 0x7a,0xb3,0x3a,0x78,0xb4,0x1, 0x6, 0x74,0x1, +0x7a,0xb3,0x3a,0x79,0x74,0x1, 0x7a,0xb3,0x3a,0x7, 0x7e,0x73,0x3a,0x78,0xbe,0x70, +0x3, 0x40,0xf, 0x74,0x1, 0x7a,0xb3,0x3a,0x13,0x12,0xa7,0x7f,0x12,0xa7,0x99,0x12, +0xa7,0x86,0x7e,0x73,0x3a,0x79,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0xa7,0x86,0x22,0x74, +0x2, 0x7a,0xb3,0x3a,0x7, 0x22,0xe4,0x7a,0xb3,0x3a,0x79,0x7a,0xb3,0x3a,0x78,0x22, +0x12,0xa7,0x86,0xe4,0x7a,0xb3,0x3a,0x13,0x22,0xe4,0x7a,0xb3,0x3a,0x5, 0x6d,0x33, +0x6c,0xaa,0x7e,0x50,0xc, 0xac,0x5a,0x59,0x32,0x3a,0x1c,0xb, 0xa0,0xbe,0xa0,0x4, +0x40,0xf0,0xe4,0x7a,0xb3,0x3a,0x6, 0x6d,0x33,0x7a,0x37,0x3a,0xd, 0x7a,0x37,0x3a, +0x2, 0x22,0x7e,0x37,0x3c,0xc, 0x12,0x59,0x99,0x7a,0x37,0x3a,0x7b,0x6c,0xaa,0x80, +0x24,0xbe,0xa0,0x4, 0x50,0x27,0xa, 0x3a,0x9, 0x63,0x3a,0x14,0xbe,0x60,0x4, 0x50, +0x12,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42,0x3c,0x6, 0x7e,0x70,0xc, 0xac,0x67,0x59, +0x43,0x3a,0x1e,0xb, 0xa0,0x7e,0xb3,0x3a,0x11,0xbc,0xba,0x38,0xd4,0x22,0xbe,0x34, +0x2, 0x58,0x28,0xd, 0x7e,0x53,0x3a,0x7a,0xbe,0x50,0x8, 0x50,0x3f,0x74,0x8, 0x80, +0x37,0xbe,0x34,0x1, 0xe0,0x28,0xd, 0x7e,0x53,0x3a,0x7a,0xbe,0x50,0x6, 0x50,0x2c, +0x74,0x6, 0x80,0x24,0xbe,0x34,0x1, 0x68,0x28,0xd, 0x7e,0x53,0x3a,0x7a,0xbe,0x50, +0x4, 0x50,0x19,0x74,0x4, 0x80,0x11,0xbe,0x34,0x0, 0xf0,0x28,0xf, 0x7e,0x73,0x3a, +0x7a,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a,0xb3,0x3a,0x7a,0x7e,0xb3,0x3a,0x7a, +0xbe,0xb0,0x0, 0x28,0x19,0x14,0x7a,0xb3,0x3a,0x7a,0x74,0x1, 0x7a,0xb3,0x15,0xa2, +0x7e,0x73,0x3a,0x7a,0xbe,0x70,0x4, 0x28,0x5, 0xe4,0x7a,0xb3,0x15,0xa1,0x22,0x7c, +0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a,0x12,0xa8,0xe8,0x68,0x23,0x7e,0x70, +0xc, 0xac,0x72,0x12,0xac,0x83,0x7d,0x23,0x7e,0x70,0xc, 0xac,0x72,0x59,0x23,0x3a, +0x20,0x49,0x3, 0x3a,0x20,0x49,0x23,0x3a,0x1c,0xbd,0x20,0x50,0x4, 0x59,0x3, 0x3a, +0x1c,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa,0x6c,0x22,0x80,0x18,0x12,0xa8,0xe8, +0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, 0x3a,0x1c,0xbd,0x4, 0x50,0x4, 0x7d, +0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4,0x7e,0x37,0x3a,0x2, 0xbe,0x37,0x3a, +0x7b,0x50,0x8, 0x7e,0x37,0x3a,0x7b,0x7a,0x37,0x3a,0x2, 0x12,0xa9,0xfa,0x4d,0x33, +0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e,0x10,0x5, 0xac,0x12,0x9, 0xb0,0x25, +0x7, 0xbe,0xb3,0x29,0xfc,0x22,0xca,0x79,0x7e,0xf0,0xff,0x12,0xaa,0x95,0x7e,0xb3, +0x3a,0x9, 0xb4,0x1, 0x8, 0x12,0x6b,0xd6,0xe4,0x7a,0xb3,0x3a,0x9, 0x7e,0xb3,0x3a, +0x8, 0x60,0x4, 0x74,0xff,0x21,0xf7,0x7e,0xb3,0x3a,0x7, 0xb4,0x2, 0x2, 0x80,0x2, +0x21,0xeb,0x12,0xac,0x5f,0x38,0x12,0x12,0xac,0x57,0x38,0xd, 0x12,0xab,0xd1,0x38, +0x8, 0x7e,0xb3,0x15,0xa1,0x60,0x2, 0x21,0xeb,0x74,0x3, 0x12,0xa8,0x6f,0x7c,0xeb, +0x7e,0xb3,0x3a,0x6, 0x4, 0x7a,0xb3,0x3a,0x6, 0x74,0x3, 0x12,0xa8,0x6f,0x7c,0xab, +0xbe,0xa0,0xff,0x68,0x23,0xbe,0xe0,0xff,0x68,0x1c,0x7e,0x30,0xc, 0xac,0x3e,0x49, +0x21,0x3a,0x1c,0xbe,0x24,0x2, 0x58,0x28,0xf, 0x12,0xa9,0xfa,0x3e,0x34,0xbd,0x23, +0x28,0x6, 0x7c,0xea,0x80,0x2, 0x7c,0xea,0xbe,0xe0,0xff,0x78,0x11,0xe4,0x7a,0xb3, +0x3a,0x6, 0x7a,0xb3,0x3a,0x7, 0x7a,0xb3,0x3a,0x13,0x74,0xff,0x80,0x69,0x7e,0x73, +0x3a,0x6, 0xbe,0x70,0x4, 0x28,0x54,0x74,0xc, 0xac,0xbe,0x49,0x35,0x3a,0x1c,0xbe, +0x34,0x2, 0x58,0x40,0x6, 0x7e,0xb3,0x15,0xa1,0x70,0x37,0x7e,0x37,0x3a,0x2, 0xbe, +0x34,0x1, 0x2c,0x38,0xa, 0x7e,0x37,0x3a,0xd, 0xbe,0x34,0x1, 0x2c,0x28,0x23,0x74, +0x5, 0xac,0xbe,0x9, 0x75,0x25,0x7, 0xbe,0x73,0x29,0xfc,0x68,0x15,0x7c,0xfe,0xbe, +0xf0,0x4, 0x50,0x8, 0x12,0xaa,0x4, 0xbe,0xb0,0x4, 0x40,0x6, 0x74,0x1, 0x7a,0xb3, +0x3a,0x9, 0xe4,0x7a,0xb3,0x3a,0x13,0x7a,0xb3,0x3a,0x7, 0xbe,0xf0,0xff,0x68,0x5, +0xe4,0x7a,0xb3,0x3a,0x6, 0x7c,0xbf,0xda,0x79,0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49, +0x33,0x3a,0x1c,0x22,0x7e,0xb3,0x29,0xfc,0x7c,0xab,0x6c,0x77,0x7e,0x50,0x5, 0xac, +0x57,0x9, 0x62,0x25,0x7, 0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70, +0x4, 0x40,0xe9,0x74,0xff,0x22,0x7c,0x2b,0x7e,0xb3,0x1e,0x43,0xbc,0x2b,0x68,0x55, +0x12,0xaa,0x8, 0x7c,0x3b,0x7c,0xb2,0x12,0xaa,0x8, 0x7c,0xab,0xbe,0x30,0xff,0x68, +0x44,0xbe,0xa0,0xff,0x68,0x3f,0x7e,0x70,0x4, 0xac,0x73,0xa, 0x2a,0x2d,0x32,0x2e, +0x34,0x1a,0x52,0x12,0x5e,0x88,0xbe,0xb0,0x2, 0x38,0x2a,0xa, 0x2b,0x7e,0x34,0x2, +0xe0,0xad,0x32,0x2e,0x34,0x15,0xa3,0x6d,0x22,0x30,0x19,0x3, 0x2, 0xaa,0xdf,0x7e, +0xb3,0x2a,0xa, 0xb4,0x1, 0xf, 0x12,0x77,0xc7,0x7a,0x55,0x29,0x7e,0x8, 0xc, 0xd8, +0x74,0x1, 0x2, 0xab,0x10,0x22,0x7c,0xab,0x12,0xab,0x65,0xd2,0x19,0x7c,0xba,0x12, +0xaa,0x26,0xc2,0x19,0x22,0x7e,0xb3,0x3a,0x8, 0xb4,0x1, 0x27,0x7e,0xb3,0x3a,0x7e, +0x4, 0x7a,0xb3,0x3a,0x7e,0x7e,0x73,0x3a,0x7e,0xbe,0x70,0x3, 0x40,0x15,0x12,0xaa, +0xc4,0x7e,0x73,0x3a,0x7e,0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3,0x3a,0x7e,0x7a, +0xb3,0x3a,0x8, 0x22,0x12,0xa7,0xc2,0x6d,0x33,0x7a,0x37,0x3a,0x7b,0x6c,0xaa,0x12, +0xac,0xdc,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xf6,0xe4,0x7a,0xb3,0x3a,0x10,0x22,0x7c, +0x7b,0x90,0x60,0x93,0xe4,0x93,0xa, 0x1b,0x7e,0x63,0x29,0x5e,0xa, 0x6, 0x2d,0x1, +0x7e,0x63,0x29,0x5b,0xa, 0x16,0xad,0x10,0x7d,0x21,0x12,0xac,0x70,0xa, 0x26,0x7a, +0x25,0x29,0x74,0x1d,0xac,0x7b,0x2e,0x34,0x33,0xa2,0x6d,0x22,0xe4,0x2, 0xab,0x10, +0x7c,0xab,0x6d,0x44,0x80,0x29,0x4c,0xaa,0x68,0x11,0x12,0xab,0x53,0x60,0x5, 0x3e, +0xe4,0x14,0x78,0xfb,0x12,0xab,0x47,0x2d,0xfe,0x80,0xf, 0x12,0xab,0x53,0x60,0x5, +0x3e,0xe4,0x14,0x78,0xfb,0x12,0xab,0x47,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e, +0xf5,0x29,0xbd,0xf4,0x38,0xd0,0x22,0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, +0x6a,0xf0,0x22,0x7f,0x71,0x2d,0xf4,0x7e,0x7b,0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5, +0x29,0x7e,0x6b,0xb0,0x22,0xa9,0xd1,0xcb,0x74,0x1, 0x2, 0x0, 0xe, 0x12,0xab,0x65, +0x7e,0x34,0xc, 0xd8,0x7e,0xb3,0x29,0x5a,0x12,0xab,0xa6,0x12,0xab,0x89,0x7a,0x37, +0x3c,0x10,0x74,0x1, 0x7a,0xb3,0x15,0xa1,0x22,0x6d,0x33,0x90,0x60,0x91,0xe4,0x93, +0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xae,0x4f,0x90,0x60,0x92,0xe4,0x93,0xbe,0xb0,0x0, +0x28,0x3, 0x2, 0xad,0xb6,0x22,0x7a,0xb3,0x24,0x2, 0x7e,0x53,0x29,0x5b,0x7a,0x53, +0x24,0x3, 0x7a,0x37,0x24,0xa, 0xe4,0x7a,0xb3,0x24,0x4, 0x7a,0xb3,0x24,0x5, 0x7e, +0x34,0x40,0x0, 0x7a,0x37,0x24,0x6, 0x7e,0x34,0x0, 0x20,0x12,0xac,0x67,0x2, 0xd, +0x7, 0x7e,0x73,0x25,0xc9,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x3a,0x7, 0x7a,0x73,0x3a, +0x7d,0x7e,0x47,0x3c,0x10,0xbe,0x44,0x0, 0x78,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x3a, +0x7, 0xbe,0x44,0x0, 0xf0,0x28,0x8, 0xe4,0x7a,0xb3,0x3a,0x5, 0x12,0xa7,0x7f,0x7e, +0x57,0x3a,0xd, 0xbd,0x54,0x50,0x4, 0x7a,0x47,0x3a,0xd, 0x12,0xac,0x5f,0x38,0x10, +0x12,0xac,0x57,0x38,0xb, 0x12,0xab,0xd1,0x38,0x6, 0x7e,0xb3,0x15,0xa1,0x70,0x34, +0x12,0xa7,0x28,0xbe,0x44,0x0, 0x3c,0x50,0x21,0x7e,0xb3,0x3a,0x5, 0x4, 0x7a,0xb3, +0x3a,0x5, 0x7e,0x73,0x3a,0x5, 0xbe,0x70,0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x3a, +0x5, 0x12,0xac,0x79,0x7a,0xb3,0x3a,0x7a,0x80,0x5, 0xe4,0x7a,0xb3,0x3a,0x5, 0x7d, +0x34,0x2, 0xa7,0xfe,0x2, 0xa7,0x90,0x7e,0x73,0x25,0xc8,0xbe,0x70,0x0, 0x22,0x7e, +0x73,0x27,0x66,0xbe,0x70,0x0, 0x22,0x7a,0x37,0x24,0xc, 0x7e,0x8, 0x24,0x2, 0x22, +0x3e,0x24,0x7e,0xf, 0x3c,0x13,0x2d,0x12,0x22,0xe4,0x7a,0xb3,0x3a,0x7, 0x7a,0xb3, +0x3a,0xf, 0x22,0x49,0x23,0x3a,0x22,0x49,0x33,0x3a,0x1e,0x9d,0x32,0x2, 0x1a,0x62, +0x6c,0xaa,0x7e,0x70,0xc, 0xac,0x7a,0x12,0xac,0x83,0xbe,0x34,0x3, 0xe8,0x8, 0x5, +0x12,0xac,0xdc,0x80,0x2f,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x3a,0x22,0x49,0x12, +0x3a,0x1e,0xbd,0x13,0x28,0xf, 0x7d,0x2, 0x2e,0x4, 0x3a,0x22,0x7d,0x13,0xb, 0x15, +0x1b,0x8, 0x10,0x80,0xf, 0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24,0x3a,0x22,0x1b, +0x35,0x1b,0x28,0x30,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xb7,0x22,0x7e,0x50,0xc, 0xac, +0x5a,0x49,0x32,0x3a,0x1e,0x59,0x32,0x3a,0x22,0x22,0x12,0x77,0xaf,0x3e,0x34,0x7e, +0x8, 0x12,0x9e,0xe4,0x12,0x1a,0x30,0x90,0x60,0x93,0x93,0xa, 0x3b,0x7e,0xb3,0x29, +0x5e,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xad,0x32,0x7d,0x43,0x6c,0x77,0x80,0x1d,0xa, +0x27,0x2d,0x24,0x12,0xac,0x70,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37,0x2e,0x14, +0x12,0x9e,0xb, 0x18,0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xdf, +0x22,0xca,0x3b,0x7e,0xb3,0x29,0xfc,0x7a,0xb3,0x1e,0x43,0x7e,0xf3,0x2a,0x4f,0x12, +0xaa,0x8, 0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x6a,0x6c,0xcc,0x12,0x77,0xbe,0xf5,0x29, +0x7e,0x73,0x29,0xfc,0xbe,0x71,0x29,0x68,0x3c,0x7e,0x70,0x4, 0xac,0x7d,0xa, 0x2c, +0x2d,0x32,0x2e,0x34,0x1a,0x52,0x12,0x5e,0x88,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43, +0xa, 0xe, 0x7e,0x14,0x2, 0xe0,0xad,0x10,0x2e,0x14,0x15,0xa3,0x6d,0x0, 0x7a,0xd, +0x2a,0x7e,0x70,0x1d,0xac,0x7e,0x2e,0x34,0x33,0xa2,0x6d,0x22,0x7a,0x1f,0x33,0x9e, +0x7c,0xbc,0x12,0x75,0xdb,0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xaf,0x7e,0x73,0x2a,0x4f, +0xbc,0x7f,0x68,0x6, 0x7a,0xf3,0x2a,0x4f,0xd2,0xf, 0xd2,0x0, 0x7e,0xb3,0x1e,0x43, +0x12,0x44,0x39,0xda,0x3b,0x22,0xca,0xf8,0x6d,0xee,0x7d,0xfe,0x7e,0x83,0x29,0x5b, +0xa, 0xd8,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x2f,0x7e,0x8, 0x12,0x9e,0x6c,0xaa, +0x80,0x18,0x7e,0x70,0x2, 0xac,0x7a,0x49,0x23,0x13,0xe, 0x7f,0x50,0x2d,0xb3,0xb, +0x5a,0xc0,0x9d,0xc2,0x59,0xc3,0x12,0xd6,0xb, 0xa0,0xbc,0x8a,0x38,0xe4,0x90,0x60, +0x92,0xe4,0x93,0x7c,0x9b,0x6d,0xdd,0x80,0x11,0x7e,0x8, 0x13,0xe, 0x90,0x60,0x92, +0xe4,0x93,0xa, 0xcb,0x1b,0xc4,0x7d,0x3c,0x7c,0x97,0x6c,0xff,0x80,0x38,0x6c,0xaa, +0x80,0x28,0xa, 0x3a,0x7d,0x23,0x2d,0x2e,0x3e,0x24,0x49,0xc2,0x13,0xe, 0x2d,0x3d, +0x3e,0x34,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xb0,0x7d,0x3c,0x9d,0x3b,0x12,0x1a,0x62, +0x7d,0xa3,0xbd,0xfa,0x58,0x2, 0x7d,0xfa,0xb, 0xa0,0xbc,0x8a,0x38,0xd4,0xa, 0xc8, +0x2d,0xec,0x2d,0xdc,0xb, 0xf0,0xbc,0x9f,0x38,0xc4,0x7d,0x3f,0xda,0xf8,0x22,0xca, +0xf8,0x6d,0x44,0x7e,0xf3,0x29,0x5b,0x90,0x60,0x93,0xe4,0x93,0xa, 0xfb,0x7e,0xb3, +0x29,0x5a,0xa, 0xeb,0x2d,0xef,0xa, 0xff,0xad,0xfe,0xa, 0xef,0x2d,0xef,0x90,0x60, +0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e,0x8, 0x12,0x9e,0x6c,0xaa,0x80,0x23,0xa, 0xda, +0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x3c,0x13,0x2d,0x3d,0xb, 0x1a,0xd0,0x7e,0x50,0x2, +0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, 0x5a,0x30,0x9d,0x3d,0x59,0x32,0x12,0xd6,0xb, +0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, 0x7d,0x5e,0x3e,0x54,0x7e,0xf, 0x3c,0x13,0x2d, +0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea,0x2d,0xef,0x3e,0xe4,0x7e,0x1f,0x3c,0x13,0x2d, +0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, 0xac,0x7a,0x2d,0x31,0x7d,0x20,0xb, 0x1a,0xd0, +0x7d,0x3e,0x9d,0x3d,0x12,0x1a,0x62,0x7d,0xc3,0xbd,0x4c,0x58,0x2, 0x7d,0x4c,0xb, +0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34,0xda,0xf8,0x22,0x7e,0x8, 0x3a,0x18,0x7e,0x34, +0x0, 0x60,0xe4,0x12,0x1a,0x30,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac, +0x7a,0x59,0x43,0x3a,0x1a,0x59,0x43,0x3a,0x22,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8, +0x7e,0x8, 0x3a,0x6, 0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x1a,0x30,0x7e,0xa3,0x2a,0x4f, +0xbc,0xab,0x68,0x6, 0x7a,0xb3,0x2a,0x4f,0xd2,0xf, 0x30,0xf, 0x9, 0xc2,0xf, 0x12, +0xaf,0x37,0xe4,0x2, 0xa, 0x66,0x22,0x7e,0x8, 0x29,0x5a,0x12,0x3, 0x8b,0x7e,0x8, +0x29,0x5a,0x74,0x3, 0x2, 0x11,0x7a,0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80, +0x45,0x6c,0x22,0x80,0x37,0x7e,0xb3,0x29,0x5b,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d, +0x45,0x3e,0x44,0x7e,0x7f,0x12,0x9a,0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32, +0x8, 0x8, 0xbe,0x44,0x2, 0x58,0x58,0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, +0xbe,0x44,0xfd,0xa8,0x8, 0x2, 0xb, 0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x29,0x5b, +0xbc,0x92,0x38,0xc1,0xb, 0x31,0x7e,0xb3,0x29,0x5a,0xbc,0xb3,0x38,0xb3,0x7e,0x54, +0x0, 0x6, 0xad,0x53,0x7d,0x15,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x12,0x59,0x9b,0xbd, +0x12,0x50,0x22,0xbd,0x30,0x28,0x1e,0xe4,0x7a,0xb3,0x3c,0x37,0x7e,0xb3,0x3c,0x38, +0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3c,0x38,0x80,0x3c,0xe4,0x7a,0xb3,0x3c, +0x38,0x74,0x1, 0x80,0x2f,0xbd,0x10,0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3, +0x3c,0x38,0x7e,0xb3,0x3c,0x37,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3c,0x37, +0x80,0x16,0xe4,0x7a,0xb3,0x3c,0x37,0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x3c,0x37, +0x7a,0xb3,0x3c,0x38,0x7a,0xb3,0x3c,0x39,0x7e,0xb3,0x3c,0x39,0x22,0xe4,0x7a,0xb3, +0x27,0x7c,0x7a,0xb3,0x3c,0x3a,0x22,0x7e,0xb3,0x3a,0xa7,0xb4,0x3, 0x8, 0x7e,0xb3, +0x3b,0x7, 0x70,0x2, 0xc3,0x22,0xd3,0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e, +0xb3,0x29,0x5b,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51, +0x7e,0x13,0x29,0x5b,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x29,0x5a,0xa, 0x10,0xa, 0x21, +0x2d,0x12,0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23, +0x2, 0x8c,0x80,0x2d,0x7e,0x3, 0x29,0x5a,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42, +0xa, 0x3a,0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58, +0xe, 0x9d,0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x2, 0x8e,0x80,0x2, 0xe4, +0x22,0x7e,0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e, +0x60,0x80,0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0xb0, +0x28,0xa, 0x1b,0x7e,0x63,0x29,0x5b,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac, +0x1f,0x2d,0x3, 0x7e,0x1f,0x12,0x9a,0x2d,0x30,0x12,0xb0,0xe7,0x9d,0x35,0x1b,0x1a, +0x10,0xb, 0xf0,0x12,0xb0,0xe7,0x7e,0x73,0x29,0x5b,0xa, 0x27,0x2d,0x25,0xa, 0x3f, +0xbd,0x32,0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x29,0x5a,0x74,0x2, 0xa4,0x22,0xca, +0xf8,0x7c,0xfb,0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34,0x0, 0x6c,0x6d, +0x22,0x7e,0x8, 0x34,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39, +0xac,0x7f,0x2e,0x34,0x1, 0x4c,0x6d,0x22,0x7e,0x8, 0x2, 0x8c,0x12,0x1a,0xb, 0x1b, +0xfd,0xda,0xf8,0x22,0xca,0x3b,0x7c,0xdb,0x75,0x44,0x0, 0x75,0x45,0x0, 0x7e,0xb3, +0x29,0x5c,0xf5,0x4a,0x7e,0xb3,0x29,0x5d,0xf5,0x4b,0x75,0x4c,0x28,0x7e,0xb3,0x27, +0x58,0xf5,0x2c,0xe4,0x7a,0xb3,0x2, 0xe1,0x7a,0xb3,0x2, 0xdd,0x7a,0xb3,0x2, 0xde, +0x7e,0x8, 0x2, 0xe2,0x12,0x28,0xc6,0xe4,0x12,0x1a,0x30,0x12,0x28,0xc6,0x3e,0x34, +0x7e,0x8, 0x3, 0x2, 0xe4,0x12,0x1a,0x30,0x75,0x43,0x0, 0x30,0x14,0xd, 0x7e,0x34, +0x0, 0xfa,0x7a,0x35,0x3f,0x7e,0x34,0x1, 0x5e,0x80,0x7, 0x7e,0x34,0x1, 0x5e,0x7a, +0x35,0x3f,0x7a,0x35,0x41,0x7e,0x37,0x7, 0x12,0xbe,0x35,0x41,0x48,0x9, 0x7e,0x37, +0x7, 0x10,0xbe,0x35,0x3f,0x58,0x3, 0x75,0x43,0x1, 0x30,0xe, 0x3, 0x75,0x43,0x1, +0xe5,0x2c,0xbe,0xb0,0x2, 0x50,0x3, 0x2, 0xba,0x5a,0x6c,0xcc,0x2, 0xba,0x51,0x7e, +0x70,0x2, 0xac,0x7c,0x12,0x93,0xa, 0x9, 0xb3,0x25,0xcf,0xf5,0x25,0x4c,0xcc,0x68, +0x8, 0xa, 0x3c,0x9, 0xb3,0x2, 0xe2,0x70,0xa, 0xa, 0x3c,0xb, 0x34,0xa, 0x2c,0x19, +0x72,0x2, 0xe2,0xe5,0x2c,0x14,0xbc,0xbc,0x78,0x3, 0x2, 0xba,0x5a,0xa, 0x5c,0xb, +0x54,0xf5,0x2d,0x2, 0xba,0x45,0x75,0x59,0x0, 0x7e,0x71,0x2d,0x12,0xcf,0x1b,0x7a, +0xa1,0x26,0x9, 0xb3,0x25,0xcf,0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0xbc,0xd9,0x7c, +0xb7,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5,0x25,0x12,0xbc,0xd9,0x7c,0xb7,0xf5,0x29, +0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xba,0x43,0xe5,0x29,0xbe,0xb0,0x5, 0x40, +0x3, 0x2, 0xba,0x43,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26,0x7e,0x51,0x27,0x12, +0x8f,0x34,0x7a,0xb3,0x2, 0xe0,0x85,0x25,0x65,0x85,0x26,0x66,0x85,0x27,0x67,0x7e, +0x8, 0x0, 0x33,0x7e,0x18,0x0, 0x35,0xe5,0x24,0x12,0xbe,0xd3,0x75,0x44,0x0, 0x75, +0x45,0x0, 0x75,0x32,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x21,0x5e,0x7a,0x35,0x37, +0xe5,0x26,0x7e,0x71,0x27,0x12,0x21,0x5e,0x7a,0x35,0x39,0x7e,0x35,0x37,0xbe,0x35, +0x39,0x8, 0x5, 0x7e,0x35,0x39,0x80,0x3, 0x7e,0x35,0x37,0x7a,0x35,0x3d,0xe, 0x34, +0x7a,0x35,0x3b,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x11,0xe5,0x29,0xbe,0xb0,0x1, 0x38, +0xa, 0x7c,0xbd,0x30,0xe1,0x5, 0x75,0x32,0x1, 0xe1,0xdf,0xe5,0x28,0xbe,0xb0,0x1, +0x38,0x9, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x2, 0xe1,0xdf,0xe5,0x28,0xbe,0xb0,0x5, +0x40,0x2, 0xe1,0xdf,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x2, 0xe1,0xdf,0x7c,0xbd,0x20, +0xe0,0x2, 0xe1,0xdf,0x6d,0x88,0x7d,0x98,0x75,0x5a,0x0, 0x75,0x5b,0x0, 0xc2,0x1, +0xc2,0x2, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x6, 0xe5,0x24,0x7c,0xeb,0x80,0x3, 0x7e, +0xe1,0x26,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, 0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5, +0x2a,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x6, 0xe5,0x25,0x7c,0xfb,0x80,0x3, 0x7e,0xf1, +0x27,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x4, 0xe5,0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2b, +0xe5,0x4a,0xa, 0xdb,0x1b,0xd4,0xe5,0x2a,0xa, 0xab,0xbd,0xad,0xe5,0x2a,0x58,0x6, +0xa, 0x5b,0xb, 0x54,0x80,0x0, 0xf5,0x55,0xbe,0xe0,0x0, 0x28,0x6, 0xa, 0x5e,0x1b, +0x54,0x80,0x2, 0x7c,0xbe,0xf5,0x56,0x12,0xcf,0x12,0xa, 0xcb,0xbd,0xcb,0xe5,0x2b, +0x58,0x6, 0xa, 0x5b,0xb, 0x54,0x80,0x0, 0xf5,0x57,0xbe,0xf0,0x0, 0x28,0x6, 0xa, +0x5f,0x1b,0x54,0x80,0x2, 0x7c,0xbf,0xf5,0x58,0x75,0x2e,0x0, 0x80,0x71,0xbe,0xc1, +0x2e,0x68,0x6a,0xe5,0x2d,0xbe,0xb1,0x2e,0x68,0x63,0x7e,0x91,0x2e,0x74,0x2, 0xac, +0x9b,0x9, 0xa4,0x25,0xce,0xbe,0xa1,0x55,0x78,0x11,0x7d,0x3a,0xb, 0x34,0xe5,0x55, +0xa, 0xbb,0xbd,0xb3,0x78,0x5, 0x85,0x2a,0x55,0x80,0x14,0xbe,0xa1,0x56,0x78,0xf, +0xe5,0x56,0xa, 0xbb,0xb, 0xb4,0xa, 0x5e,0xbd,0xb5,0x78,0x3, 0x7a,0xe1,0x56,0x9, +0xa4,0x25,0xcf,0xbe,0xa1,0x57,0x78,0x11,0x7d,0x3c,0xb, 0x34,0xe5,0x57,0xa, 0xbb, +0xbd,0xb3,0x78,0x5, 0x85,0x2b,0x57,0x80,0x14,0xbe,0xa1,0x58,0x78,0xf, 0xe5,0x58, +0xa, 0x3b,0xb, 0x34,0xa, 0xbf,0xbd,0x3b,0x78,0x3, 0x7a,0xf1,0x58,0x5, 0x2e,0xe5, +0x2c,0xbe,0xb1,0x2e,0x38,0x88,0xe5,0x2a,0xbc,0xbe,0x78,0x1c,0xd2,0x1, 0x4c,0xee, +0x68,0x7, 0xe5,0x4a,0x14,0xbc,0xbe,0x78,0x2, 0xd2,0x2, 0xbe,0xe0,0x0, 0x28,0x2, +0x1b,0xe0,0xbd,0xad,0x58,0x2, 0x5, 0x2a,0xe5,0x2b,0xbc,0xbf,0x78,0x21,0xd2,0x1, +0x4c,0xff,0x68,0x7, 0xe5,0x4b,0x14,0xbc,0xbf,0x78,0x2, 0xd2,0x2, 0xbe,0xf0,0x0, +0x28,0x2, 0x1b,0xf0,0x12,0xcf,0x12,0xa, 0xdb,0xbd,0xdb,0x58,0x2, 0x5, 0x2b,0x75, +0x30,0x0, 0x75,0x31,0x0, 0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f,0xa, 0xdb,0x9, 0x7d, +0x25,0x2f,0xbe,0x71,0x55,0x38,0x7, 0xbe,0x71,0x56,0x40,0x2, 0x5, 0x30,0x5, 0x2f, +0x7e,0x73,0x25,0x58,0xbe,0x71,0x2f,0x38,0xe1,0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f, +0xa, 0xdb,0x9, 0x7d,0x25,0x43,0xbe,0x71,0x57,0x38,0x7, 0xbe,0x71,0x58,0x40,0x2, +0x5, 0x31,0x5, 0x2f,0x7e,0x73,0x25,0x59,0xbe,0x71,0x2f,0x38,0xe1,0x7a,0xe1,0x46, +0x80,0x4f,0x7a,0xf1,0x47,0x80,0x41,0xe5,0x46,0x7e,0x71,0x47,0x12,0x21,0x5e,0x7a, +0x35,0x48,0xbe,0xe1,0x46,0x68,0x13,0xe5,0x2a,0xbe,0xb1,0x46,0x68,0xc, 0xbe,0xf1, +0x47,0x68,0x7, 0xe5,0x2b,0xbe,0xb1,0x47,0x78,0x9, 0x7e,0xd5,0x48,0x2d,0x9d,0x5, +0x5a,0x80,0x13,0x5, 0x5b,0x7e,0xd5,0x48,0x2d,0x8d,0x7e,0xd5,0x35,0xbe,0xd5,0x48, +0x58,0x2, 0x5, 0x44,0x5, 0x45,0x5, 0x47,0xe5,0x2b,0xbe,0xb1,0x47,0x50,0xb8,0x5, +0x46,0xe5,0x2a,0xbe,0xb1,0x46,0x50,0xaa,0xe5,0x2a,0x12,0xcf,0x71,0x7c,0xbe,0x12, +0xcf,0x9, 0x12,0xcf,0x71,0xe5,0x2a,0x12,0xcf,0x9, 0x7e,0xd5,0x39,0x2e,0xd5,0x37, +0x7a,0xd5,0x3b,0x30,0x1, 0xa, 0x20,0x2, 0x7, 0x9e,0x95,0x3b,0x15,0x5a,0x15,0x5a, +0xe5,0x5a,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x5a,0x24,0xfc,0xf5,0x5a,0xbe,0x94,0x0, +0x0, 0x58,0x2, 0x6d,0x99,0x75,0x4c,0x22,0xe5,0x4a,0x14,0xbe,0xb1,0x24,0x68,0xd, +0xbe,0xb1,0x26,0x68,0x8, 0xe5,0x24,0x60,0x4, 0xe5,0x26,0x70,0xa, 0x12,0xbf,0x59, +0x28,0x58,0x75,0x4c,0x2c,0x80,0x53,0x30,0x14,0x42,0x7e,0x73,0x39,0x0, 0xbe,0x71, +0x2a,0x38,0x11,0xbc,0x7e,0x40,0xd, 0x7e,0x73,0x39,0x2, 0xbe,0x71,0x2b,0x38,0x4, +0xbc,0x7f,0x50,0x1a,0x7e,0x73,0x39,0x1, 0xbe,0x71,0x2a,0x38,0x2d,0xbc,0x7e,0x40, +0x29,0x7e,0x73,0x39,0x3, 0xbe,0x71,0x2b,0x38,0x20,0xbc,0x7f,0x40,0x1c,0x12,0xce, +0x80,0x7c,0xb7,0x25,0x4c,0xf5,0x4c,0x75,0x59,0x1, 0x80,0xe, 0x30,0xe, 0xb, 0x12, +0xce,0x80,0x7c,0xa7,0xe5,0x4c,0x9c,0xba,0xf5,0x4c,0x7d,0x18,0x1a,0x2, 0x1a,0x0, +0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5,0x4c,0xa, 0x1b,0x6d,0x0, 0x12,0x17, +0x18,0x7a,0x1d,0x4d,0x7e,0x15,0x3b,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x33,0x1a,0x26, +0x1a,0x24,0x12,0x17,0x18,0xe5,0x5b,0xa, 0xfb,0x6d,0xee,0xe5,0x5a,0xa, 0x1b,0x6d, +0x0, 0x2f,0x7, 0x12,0x17,0x18,0x7f,0x1, 0x7a,0xd, 0x51,0x7e,0x1d,0x4d,0xbf,0x10, +0x8, 0x3, 0x75,0x32,0x2, 0x12,0x5f,0xfd,0x50,0x2, 0xe1,0xdf,0xe5,0x43,0x60,0x2, +0xe1,0xdf,0x12,0xce,0x97,0x68,0x2, 0xc1,0xe5,0x12,0xbf,0x59,0x38,0x2, 0xc1,0xe5, +0xa, 0xe, 0xe5,0x2a,0xa, 0x1b,0x7d,0xd1,0x9d,0xd0,0xbe,0xd4,0x0, 0x5, 0x48,0x2, +0xc1,0xe5,0xa, 0x3f,0xe5,0x2b,0xa, 0xbb,0x7d,0x2b,0x9d,0x23,0xbe,0x24,0x0, 0x5, +0x48,0x2, 0xc1,0xe5,0x2d,0x3b,0x7e,0xd4,0x0, 0x2, 0x12,0xce,0x78,0x3e,0x54,0x12, +0xba,0x6d,0xb, 0x1a,0x30,0x7a,0x35,0x5f,0x7d,0x30,0x2d,0x31,0x7d,0x2d,0x12,0x16, +0xe6,0x7d,0xd3,0x3e,0xd4,0x12,0xba,0x5d,0x7d,0x54,0x2d,0x5d,0x12,0xba,0x6d,0xb, +0x1a,0x50,0x7a,0x55,0x61,0xe5,0x59,0xb4,0x1, 0x1c,0x7e,0x35,0x61,0x7e,0xd4,0x0, +0x3, 0x12,0xce,0x78,0x2e,0x55,0x61,0x7a,0x55,0x61,0x7e,0x35,0x5f,0x12,0xce,0x78, +0x2e,0x55,0x5f,0x7a,0x55,0x5f,0x74,0x2, 0xac,0xbe,0x12,0xba,0x83,0xb, 0x1a,0xd0, +0xbe,0xd5,0x61,0x18,0x39,0x7e,0x3, 0x29,0x5b,0x7e,0x10,0x2, 0xac,0x1, 0x7e,0x31, +0x2a,0x74,0x2, 0xac,0x3b,0x2d,0x10,0x12,0x5f,0x35,0xb, 0x1a,0x30,0xbe,0x35,0x61, +0x18,0x1c,0x74,0x2, 0xac,0xbf,0x12,0xba,0x6d,0xb, 0x1a,0x30,0xbe,0x35,0x5f,0x18, +0xd, 0x12,0xba,0x67,0xb, 0x1a,0x30,0xbe,0x35,0x5f,0x18,0x2, 0x80,0x44,0xa, 0x3f, +0x9d,0xb3,0xbe,0xb4,0x0, 0x2, 0x58,0x12,0xbe,0xd5,0x61,0x18,0xd, 0x12,0xba,0x74, +0xb, 0x1a,0xd0,0xbe,0xd5,0x61,0x18,0x2, 0x80,0x28,0xa, 0xbe,0xe5,0x2a,0xa, 0xdb, +0x9d,0xdb,0xbe,0xd4,0x0, 0x2, 0x58,0x1d,0x74,0x2, 0xac,0xbf,0x12,0xba,0x6d,0xb, +0x1a,0xd0,0xbe,0xd5,0x5f,0x18,0xe, 0x12,0xba,0x67,0xb, 0x1a,0xd0,0xbe,0xd5,0x5f, +0x18,0x3, 0x75,0x32,0x2, 0x12,0xce,0x97,0x8, 0xd, 0xe5,0x32,0xb4,0x2, 0x8, 0x12, +0xba,0x8e,0x28,0x3, 0x75,0x32,0x0, 0x12,0xba,0x8e,0x38,0x2, 0xe1,0xb3,0xa, 0x2e, +0xe5,0x2a,0xa, 0x3b,0x7d,0xd3,0x9d,0xd2,0xbe,0xd4,0x0, 0x2, 0x48,0x58,0x2d,0x32, +0x12,0xcd,0xe1,0x7d,0x13,0x3e,0x14,0x7e,0xa3,0x29,0x5b,0x7e,0x10,0x2, 0xac,0x1a, +0x2d,0x10,0x7e,0x1f,0x6, 0x44,0x7f,0x71,0x2d,0xf1,0xb, 0x7a,0x40,0x7e,0x30,0x2, +0xac,0x3e,0x7d,0xd1,0x2d,0xd0,0x2d,0x3d,0xb, 0x1a,0xd0,0xbd,0x4d,0x58,0x27,0xe5, +0x2a,0xa, 0x2b,0xa, 0x3e,0x2d,0x32,0x12,0xcd,0xe1,0x7d,0xd3,0x3e,0xd4,0x74,0x2, +0xa4,0x2d,0xd5,0x12,0xba,0x87,0xb, 0x1a,0xb0,0x12,0xba,0x74,0xb, 0x1a,0xd0,0xbd, +0xbd,0x58,0x3, 0x75,0x32,0x0, 0xa, 0xdf,0xe5,0x2b,0xa, 0x3b,0x7d,0x23,0x9d,0x2d, +0xbe,0x24,0x0, 0x2, 0x48,0x3d,0x12,0xcd,0xdf,0x7d,0xb3,0x3e,0xb4,0x7e,0xf, 0x6, +0x44,0x7f,0x10,0x2d,0x3b,0xb, 0x1a,0x30,0x74,0x2, 0xac,0xbf,0x2d,0x15,0xb, 0xa, +0xb0,0xbd,0x3b,0x58,0x1e,0xe5,0x2b,0xa, 0x3b,0x12,0xcd,0xdf,0x7d,0xd3,0x3e,0xd4, +0x12,0xba,0x87,0xb, 0x1a,0xb0,0x12,0xba,0x67,0xb, 0x1a,0xd0,0xbd,0xbd,0x58,0x3, +0x75,0x32,0x0, 0x7e,0x73,0x2, 0xe0,0xbe,0x70,0x2, 0x50,0x23,0xe5,0x24,0x7e,0x71, +0x27,0x12,0x24,0x2f,0x58,0x19,0xe5,0x26,0x7e,0x71,0x25,0x12,0x24,0x2f,0x58,0xf, +0x12,0xba,0x8e,0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x4c, +0xdd,0x78,0x3, 0x2, 0xb9,0xd8,0x12,0x5f,0xfd,0x50,0x3, 0x2, 0xb9,0xd8,0xe5,0x43, +0x60,0x3, 0x2, 0xb9,0xd8,0x7e,0xb3,0x25,0x58,0xb4,0x2, 0x2, 0x80,0x2, 0x1, 0xb9, +0x7e,0xb3,0x25,0x59,0xb4,0x1, 0x2, 0x80,0x2, 0x1, 0xb9,0x7e,0x73,0x29,0x5d,0xa, +0xb7,0x1b,0xb4,0x7e,0x73,0x25,0x43,0xa, 0xd7,0xbd,0xdb,0x48,0x2, 0x1, 0xb9,0x7e, +0x73,0x25,0x30,0xa, 0x27,0x7e,0x73,0x25,0x2f,0x12,0xba,0x9e,0xf5,0x5c,0x12,0xba, +0xa7,0x58,0x5b,0x85,0x5c,0x63,0x12,0xba,0x5d,0x7e,0xa1,0x63,0x74,0x2, 0xa4,0x2d, +0x54,0x7e,0x1f,0x6, 0x44,0x7f,0x1, 0x2d,0x15,0x1b,0x15,0xb, 0xa, 0xb0,0x7e,0xa1, +0x5c,0x74,0x2, 0xa4,0x7d,0xd5,0x2d,0xd4,0x2d,0x3d,0xb, 0x1a,0xd0,0xbd,0xdb,0x8, +0x8, 0xe5,0x63,0xa, 0x5b,0x1b,0x54,0xf5,0x5c,0x12,0xba,0x5d,0x7e,0xa1,0x63,0x12, +0xba,0x80,0x69,0xb1,0x0, 0x2, 0x12,0xba,0x5d,0x7e,0xa1,0x5c,0x12,0xba,0x80,0xb, +0x1a,0xd0,0xbd,0xdb,0x8, 0x8, 0xe5,0x63,0xa, 0x5b,0xb, 0x54,0xf5,0x5c,0xe5,0x2a, +0xbe,0xb1,0x5c,0x28,0x5, 0xbe,0xe1,0x5c,0x28,0x9, 0xe5,0x32,0x70,0x1b,0x75,0x32, +0x2, 0x80,0x16,0xbe,0xe1,0x5c,0x38,0x11,0xe5,0x2a,0xbe,0xb1,0x5c,0x28,0xa, 0xe5, +0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e,0xb3,0x25,0x58,0xb4,0x1, 0x2, +0x80,0x2, 0x21,0x58,0x7e,0xb3,0x25,0x59,0xb4,0x2, 0x2, 0x80,0x2, 0x21,0x58,0x7e, +0x73,0x25,0x44,0xa, 0x27,0x7e,0x73,0x25,0x43,0x12,0xba,0x9e,0xf5,0x5d,0x12,0xba, +0xa7,0x58,0x4a,0x85,0x5d,0x64,0x7e,0x31,0x64,0x74,0x2, 0xac,0x3b,0x7e,0x1f,0x6, +0x44,0x7f,0x21,0x2d,0x51,0x1b,0x55,0xb, 0x2a,0xd0,0x7e,0xa1,0x5d,0x74,0x2, 0xa4, +0x2d,0x35,0xb, 0x1a,0x0, 0xbd,0xd, 0x8, 0x8, 0xe5,0x64,0xa, 0x5b,0x1b,0x54,0xf5, +0x5d,0x12,0x5f,0x35,0x69,0xb1,0x0, 0x2, 0x7e,0xa1,0x5d,0x12,0xba,0x6a,0xb, 0x1a, +0xd0,0xbd,0xdb,0x8, 0x8, 0xe5,0x64,0xa, 0x5b,0xb, 0x54,0xf5,0x5d,0xe5,0x2b,0xbe, +0xb1,0x5d,0x28,0x5, 0xbe,0xf1,0x5d,0x28,0x9, 0xe5,0x32,0x70,0x1b,0x75,0x32,0x2, +0x80,0x16,0xbe,0xf1,0x5d,0x38,0x11,0xe5,0x2b,0xbe,0xb1,0x5d,0x28,0xa, 0xe5,0x32, +0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e,0x73,0x27,0x58,0xa5,0xbf,0x2, 0x21, +0x7e,0x63,0x2, 0xe0,0xbe,0x60,0x2, 0x50,0x18,0x7e,0x63,0x28,0xf5,0xbe,0x60,0x1, +0x28,0xf, 0xbe,0x73,0x25,0x58,0x28,0x6, 0xbe,0x73,0x25,0x59,0x38,0x3, 0x75,0x32, +0x0, 0x7e,0xb3,0x25,0x57,0xb4,0x1, 0x50,0x7e,0xb3,0x2, 0xe0,0x70,0x40,0x12,0xba, +0x8e,0x28,0x3b,0xe5,0x24,0x7e,0x71,0x27,0x12,0xba,0x96,0x58,0xc, 0xe5,0x26,0x7e, +0x71,0x25,0x12,0xba,0x96,0x58,0x2, 0x80,0x20,0x7e,0xb3,0x28,0xf5,0xb4,0x2, 0x28, +0x7e,0x73,0x27,0x58,0xbe,0x70,0x5, 0x50,0x1f,0x7e,0x73,0x27,0x59,0xbe,0x70,0x1, +0x50,0x16,0xe5,0x32,0xbe,0xb0,0x1, 0x28,0xf, 0x75,0x32,0x0, 0x80,0xa, 0x7e,0xb3, +0x28,0xf5,0xb4,0x1, 0x3, 0x75,0x32,0x2, 0xe5,0x32,0xbe,0xb0,0x0, 0x28,0x64,0xe5, +0x32,0xa, 0xdb,0x2e,0xd4,0x2, 0xdc,0x7e,0xd9,0xb0,0x4, 0x7a,0xd9,0xb0,0xe5,0x2d, +0xa, 0xdb,0x9, 0xad,0x2, 0xe2,0x4c,0xaa,0x78,0xc, 0xa, 0xbc,0x9, 0xbb,0x2, 0xe2, +0x19,0xbd,0x2, 0xe2,0x80,0x3d,0xa, 0xbc,0x9, 0xbb,0x2, 0xe2,0xf5,0x5e,0xbc,0xba, +0x28,0x3, 0x7a,0xa1,0x5e,0x75,0x2e,0x0, 0x80,0x22,0x9, 0x7d,0x2, 0xe2,0xe5,0x2e, +0xa, 0xbb,0x9, 0x6b,0x2, 0xe2,0xbc,0x67,0x68,0xa, 0xa, 0x2c,0x9, 0x72,0x2, 0xe2, +0xbc,0x67,0x78,0x6, 0xe5,0x5e,0x19,0xbb,0x2, 0xe2,0x5, 0x2e,0xe5,0x2c,0xbe,0xb1, +0x2e,0x38,0xd7,0x5, 0x2d,0xe5,0x2c,0xbe,0xb1,0x2d,0x28,0x3, 0x2, 0xb1,0xe6,0xb, +0xc0,0xe5,0x2c,0xbc,0xbc,0x28,0x3, 0x2, 0xb1,0xaf,0xda,0x3b,0x22,0x7e,0x83,0x29, +0x5b,0x7e,0x90,0x2, 0xac,0x89,0x22,0x7e,0xa1,0x2b,0x74,0x2, 0xa4,0x7e,0x1f,0x6, +0x44,0x2d,0x35,0x22,0x7e,0x83,0x29,0x5b,0x7e,0x90,0x2, 0xac,0x89,0x7e,0xa1,0x2a, +0x74,0x2, 0xa4,0x7d,0xd5,0x2d,0xd4,0x7e,0x1f,0x6, 0x44,0x2d,0x3d,0x22,0x7e,0x73, +0x28,0xf5,0xbe,0x70,0x1, 0x22,0x12,0x21,0x5e,0xbe,0x34,0xff,0x38,0x22,0xa, 0x37, +0x7d,0x53,0x2d,0x52,0xe, 0x54,0x22,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x6, +0x22,0xca,0x79,0xc2,0x0, 0x7e,0xf0,0x3, 0x7e,0xe3,0x28,0xf5,0x7e,0x34,0x1e,0x44, +0x7a,0x37,0x3, 0x0, 0x6c,0x11,0x80,0x49,0x6c,0x0, 0x80,0x17,0x74,0x2, 0xac,0xb0, +0x9, 0x75,0x25,0xce,0xa, 0x37,0xa, 0x21,0x9, 0x52,0x25,0x2f,0x12,0xbc,0x45,0x48, +0x7, 0xb, 0x0, 0x12,0xbc,0x3e,0x38,0xe4,0x12,0xbc,0x3e,0x78,0x22,0xa, 0x11,0x9, +0x71,0x25,0x2f,0xa, 0x37,0x7e,0x53,0x29,0x5b,0xa, 0x15,0x2d,0x13,0x12,0xbc,0x59, +0xbe,0x17,0x7, 0x10,0x68,0x9, 0x7c,0xb1,0x6c,0x77,0x6c,0x66,0x12,0x5f,0x88,0xb, +0x10,0x7e,0x73,0x25,0x58,0xbc,0x71,0x38,0xaf,0x6c,0x11,0x80,0x44,0x6c,0x0, 0x80, +0x17,0x74,0x2, 0xac,0xb0,0x9, 0x75,0x25,0xcf,0xa, 0x37,0xa, 0x21,0x9, 0x52,0x25, +0x43,0x12,0xbc,0x45,0x48,0x7, 0xb, 0x0, 0x12,0xbc,0x3e,0x38,0xe4,0x12,0xbc,0x3e, +0x78,0x1d,0xa, 0x11,0x9, 0xa1,0x25,0x43,0x74,0x2, 0xa4,0x49,0x15,0x4, 0xc0,0xbe, +0x17,0x7, 0x12,0x68,0xa, 0x7c,0xb1,0x6c,0x77,0x7e,0x60,0x1, 0x12,0x5f,0x88,0xb, +0x10,0x7e,0x73,0x25,0x59,0xbc,0x71,0x38,0xb4,0x12,0x5e,0x91,0x12,0xbc,0xe8,0x38, +0x2, 0x81,0x35,0x12,0x8f,0xce,0x92,0xb, 0x12,0x8f,0x8, 0x7c,0xbf,0x12,0xb1,0x24, +0x4c,0xee,0x68,0xe, 0x7e,0xa3,0x2, 0xdd,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x2, 0xde, +0x70,0x4, 0xd2,0x0, 0x80,0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x69,0xbe,0xb0,0x8, +0x28,0x4, 0xd2,0x0, 0x80,0x15,0xd2,0x0, 0x7e,0xb3,0x27,0x58,0xbc,0xbe,0x78,0xb, +0x20,0xb, 0x8, 0x4c,0xaa,0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c,0xbf, +0x12,0xb1,0x24,0x7e,0x8, 0x2, 0xe2,0x12,0x8c,0xcc,0x7a,0xb3,0x2, 0xe1,0xbe,0xb3, +0x27,0x58,0x50,0x40,0x7e,0x33,0x2, 0xe1,0x80,0x2c,0x7e,0x70,0x2, 0xac,0x73,0x9, +0x23,0x3, 0x2, 0x9, 0x13,0x3, 0x3, 0x2e,0x37,0x3, 0x0, 0xb, 0x38,0x50,0x7e,0x93, +0x29,0x5b,0xac,0x92,0xa, 0x31,0x2d,0x43,0x3e,0x44,0x7e,0x1f,0x12,0x9a,0x2d,0x34, +0x1b,0x1a,0x50,0x12,0x5f,0x55,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xcc,0x74,0x1, +0x7a,0xb3,0x2, 0xdf,0x7e,0xa3,0x2, 0xe1,0x7a,0xa3,0x27,0x58,0x74,0x2, 0xa4,0xca, +0x59,0x7e,0x18,0x3, 0x2, 0x7e,0x8, 0x25,0xce,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0xbc, +0x60,0xf5,0x69,0x80,0x6, 0x75,0x69,0x64,0x12,0xbc,0xf0,0xda,0x79,0x22,0x7e,0x73, +0x27,0x58,0xbc,0x70,0x22,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x3, 0x22,0xa, +0x9, 0x7e,0xb3,0x29,0x5b,0xa, 0x1b,0x2d,0x10,0x3e,0x14,0x49,0x11,0x4, 0xc0,0x22, +0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4a,0xa, 0x31,0xb, 0x34,0x7c,0x7, +0x80,0x38,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x25,0xce,0x12,0xbc,0xe0,0x9, 0xb3, +0x25,0xce,0x12,0xbc,0xd9,0x7c,0x97,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x25,0xcf, +0x12,0xbc,0xe0,0x9, 0xb3,0x25,0xcf,0x12,0xbc,0xd9,0x7c,0x87,0xbc,0x39,0x28,0x2, +0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28,0xb, 0x0, 0x7e,0xb3,0x27,0x58,0xbc,0xb0, +0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x27,0x58,0xbc,0xb1,0x38,0xae,0xa5,0xbb,0x64,0x2, +0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22,0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, +0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x23,0xe5,0x28,0xa, 0x3b,0x9d,0x32,0x2, 0x1a,0x62, +0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x71,0x22,0x7e,0x73,0x27,0x58,0xbe,0x70,0x1, 0x22, +0x7e,0x8, 0x3, 0x3e,0x7e,0x34,0x0, 0xb4,0xe4,0x2, 0x1a,0x30,0xca,0x79,0x7f,0x70, +0x7e,0xb4,0xff,0xff,0x6c,0xee,0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, 0x7e,0x7b, +0x70,0xbc,0x76,0x78,0xe, 0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76,0x78, +0x2, 0xd2,0x2, 0x6c,0xff,0x12,0xbe,0xc6,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20,0xe1, +0x2, 0xa1,0xb6,0x7f,0x6, 0x7e,0x7b,0xb0,0x12,0x8f,0xbb,0x50,0x2d,0x7f,0x6, 0x29, +0xb7,0x0, 0x2, 0x12,0x8f,0xbb,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c,0x77, +0x12,0x8f,0x86,0x50,0x15,0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0x8f,0x86, +0x50,0x8, 0x7c,0xef,0xd2,0x1, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27,0x7e, +0x7b,0x70,0x12,0x27,0xf7,0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77,0x0, +0x2, 0x12,0x27,0xf7,0x2d,0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, 0x1, +0x12,0x27,0xf7,0x2d,0xa3,0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, 0x12, +0x27,0xf7,0x2d,0xa3,0xbd,0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, 0x4, +0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0xa1,0x25,0x20, +0x1, 0xb, 0x20,0x2, 0x8, 0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, 0x2, +0xc1,0x77,0x74,0x6, 0xac,0xbe,0x12,0xbe,0xca,0x29,0x76,0x0, 0x5, 0x7c,0xb7,0xc4, +0x23,0x54,0x1f,0xbe,0xb0,0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c,0x67, +0x2e,0x60,0x8, 0x5e,0x60,0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20,0x2, +0x11,0x29,0xb6,0x0, 0x4, 0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, 0x7a, +0x1b,0xb0,0x29,0x67,0x0, 0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29,0x76, +0x0, 0x3, 0x80,0x4, 0x29,0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, 0x2, +0x29,0x76,0x0, 0x2, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29,0x77, +0x0, 0x2, 0x39,0x76,0x0, 0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc,0x76, +0x50,0x6, 0x29,0x76,0x0, 0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, 0x1, +0x7e,0x7b,0x60,0x7e,0x6b,0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, 0x7e, +0x7b,0x70,0x7a,0x6b,0x70,0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5,0x3, +0x43,0x30,0xe1,0x7, 0xb, 0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50,0x33, +0x74,0x1, 0x39,0xb7,0x0, 0x4, 0x12,0xbe,0xc6,0x7e,0x34,0x0, 0x6, 0xca,0x39,0x7f, +0x17,0x7f,0x6, 0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x8e,0xa5,0x44,0x1, 0x7a,0x1b,0xb0, +0x12,0x8e,0xa5,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x2, 0x8, 0x12,0x8e,0xa5,0x44,0x4, +0x7a,0x1b,0xb0,0xda,0x79,0x22,0x74,0x6, 0xac,0xbf,0x7d,0xd5,0x2e,0xd4,0x3, 0x3e, +0x6d,0xcc,0x22,0x7c,0x9b,0x7f,0x71,0x7f,0x60,0x7e,0x34,0x1b,0xff,0x7e,0x24,0x0, +0xff,0x7e,0x14,0x1e,0x80,0x74,0x2a,0x12,0x17,0xda,0x7e,0x58,0x1e,0x80,0x7c,0xb9, +0x7e,0x71,0x65,0x12,0x21,0x5e,0x7d,0x43,0xe5,0x66,0x7e,0x71,0x67,0x12,0x21,0x5e, +0x2d,0x34,0xe, 0x34,0x7f,0x5, 0x7e,0x50,0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10, +0x69,0x30,0x0, 0x2, 0x1b,0x6a,0x30,0x69,0x30,0x0, 0x4, 0x1b,0x7a,0x30,0x80,0x8, +0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78,0xe1,0x12,0xbf,0x59,0x28,0x2b,0xb, 0x6a,0x20, +0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e,0x24,0x0, 0x10,0x12,0x16,0xe6,0x1b,0x6a,0x30, +0xb, 0x7a,0x30,0x1a,0x26,0x1a,0x24,0x7e,0x14,0x0, 0xd, 0x12,0x17,0x29,0x7e,0x8, +0x0, 0x10,0x12,0x17,0x85,0x1b,0x7a,0x30,0x22,0x7e,0x73,0x2, 0xe0,0xbe,0x70,0x5, +0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4,0x9, 0x55,0x25,0xce,0x9, 0x65,0x25,0xcf,0x7e, +0x73,0x27,0x60,0xbc,0x75,0x78,0xa, 0x7e,0x73,0x27,0x61,0xbc,0x76,0x78,0x2, 0xd3, +0x22,0xc3,0x22,0x6c,0xaa,0x6c,0x99,0x80,0xc, 0xa, 0xf9,0x9, 0xbf,0x29,0x67,0xbc, +0xba,0x68,0x7, 0xb, 0x90,0x12,0xbf,0xaf,0x38,0xef,0x12,0xbf,0xaf,0x68,0x7, 0xb, +0xa0,0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, 0xa0,0x74,0x6e,0x7a,0x1b,0xb0,0x22,0x90, +0x60,0x50,0xe4,0x93,0xbc,0xb9,0x22,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a, +0x49,0x12,0x12,0xd6,0x49,0x32,0x12,0x9e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x12,0x9e, +0x9d,0x31,0x1b,0x28,0x30,0xb, 0xa0,0x7e,0xb3,0x29,0x5b,0xbc,0xba,0x38,0xdc,0x22, +0xca,0xf8,0x7e,0xd4,0x28,0x90,0x6c,0xff,0x12,0xc5,0x36,0xb4,0x1, 0x16,0x9, 0x7c, +0x0, 0x50,0xbe,0x70,0x37,0x50,0xd, 0xbe,0x70,0x0, 0x28,0x8, 0x74,0x3, 0xa, 0xcf, +0x19,0xbc,0x29,0x0, 0xa, 0xcf,0x9, 0x7c,0x29,0x0, 0xbe,0x70,0x0, 0x28,0x44,0x12, +0xc0,0x5d,0x7a,0xb3,0x32,0x74,0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x70,0x63,0xac, +0x7f,0x2e,0x34,0x2e,0x87,0x6d,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e,0x14,0x27,0xdc, +0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0xa, 0xcf,0x9, 0xac,0x29,0x0, 0xbe,0xa0,0x3, +0x78,0x3, 0xe4,0x80,0xb, 0xbe,0xa0,0x1, 0x78,0x4, 0x74,0x1, 0x80,0x2, 0x74,0x2, +0x12,0xc5,0x2e,0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0x8e,0xda,0xf8,0x22,0xe4,0x7a,0xb3, +0x32,0x7e,0x74,0xff,0x22,0xca,0xd8,0xca,0x79,0x7c,0xeb,0x7e,0xd4,0x28,0x90,0x7e, +0xb4,0x27,0xdc,0x7e,0x70,0x9, 0xac,0x7e,0x7d,0x23,0x2d,0x2b,0x9, 0xf2,0x0, 0x4, +0xbe,0xf0,0xa, 0x40,0x2, 0x81,0x78,0x7c,0xbf,0x54,0xf, 0xa, 0xcb,0x2d,0xcd,0x7e, +0xc9,0x90,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x32,0xf, 0x70,0x2, 0x21,0xc0,0xb, 0x28, +0x50,0x4d,0x55,0x78,0xa, 0x49,0x22,0x0, 0x2, 0x4d,0x22,0x78,0x2, 0x21,0xc0,0x12, +0xc0,0x5d,0xa, 0x2f,0x19,0xb2,0x32,0x74,0x49,0xc3,0x27,0xdc,0xbe,0xc4,0x0, 0x1e, +0x38,0x10,0x49,0x53,0x27,0xde,0xbe,0x54,0x0, 0x1e,0x40,0x6, 0xbe,0x54,0x8, 0xca, +0x28,0x52,0xbe,0xc4,0x4, 0x1a,0x40,0xb, 0x12,0xc4,0xe3,0x40,0x6, 0xbe,0x54,0x8, +0xca,0x28,0x41,0x12,0xc4,0xe3,0x38,0xc, 0xbe,0xc4,0x0, 0x1e,0x40,0x6, 0xbe,0xc4, +0x4, 0x1a,0x28,0x30,0xbe,0x54,0x8, 0xe8,0x40,0xc, 0xbe,0xc4,0x0, 0x1e,0x40,0x6, +0xbe,0xc4,0x4, 0x1a,0x28,0x1e,0x74,0x5, 0xac,0xbf,0x9, 0x75,0x32,0xf, 0xbe,0x70, +0x4, 0x28,0x11,0x74,0x5, 0xac,0xbf,0x7d,0xc5,0x2e,0xc4,0x32,0xf, 0x7e,0xc9,0xb0, +0x14,0x7a,0xc9,0xb0,0x74,0x5, 0xac,0xbf,0x9, 0xa5,0x32,0xf, 0xbe,0xa0,0x4, 0x28, +0x5, 0x7e,0x80,0x38,0x80,0x21,0xbe,0xa0,0x4, 0x78,0x5, 0x7e,0x80,0x30,0x80,0x17, +0xbe,0xa0,0x3, 0x78,0x5, 0x7e,0x80,0x20,0x80,0xd, 0xbe,0xa0,0x2, 0x78,0x5, 0x7e, +0x80,0x18,0x80,0x3, 0x7e,0x80,0x10,0x6c,0xdd,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x37, +0x98,0x54,0xf, 0xbc,0xbf,0x78,0x52,0x12,0xc4,0xba,0xb, 0xa8,0x30,0x6d,0x22,0xa, +0x58,0x7e,0xc4,0x0, 0x40,0x9d,0xc5,0x12,0xc5,0x1e,0x49,0x35,0x37,0x94,0x12,0xc4, +0xf0,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x53,0x1b, +0xa8,0x50,0x12,0xc4,0xba,0x49,0x3a,0x0, 0x2, 0x6d,0x22,0x12,0xc5,0x1e,0x49,0x35, +0x37,0x96,0x12,0xc4,0xf0,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78, +0xf4,0x7d,0xc3,0x59,0xca,0x0, 0x2, 0x80,0x7, 0xb, 0xd0,0xbe,0xd0,0xa, 0x40,0x99, +0x12,0xc5,0x36,0xb4,0x1, 0x10,0xa, 0xaf,0x9, 0xba,0x29,0x0, 0x70,0x8, 0xe4,0x19, +0xbc,0x0, 0x50,0x12,0xc4,0xd7,0x4c,0x99,0x68,0x2, 0x81,0x78,0xa, 0xcf,0x9, 0xbc, +0x29,0x0, 0x60,0x2, 0x81,0x78,0x7e,0x70,0x9, 0xac,0x7e,0x7d,0xc3,0x2d,0xcb,0xb, +0xc8,0xa0,0xbe,0xa4,0x0, 0x0, 0x40,0x6, 0xbe,0xa4,0x4, 0x38,0x28,0x2b,0x7e,0xa0, +0x1, 0x7e,0x50,0x5, 0xac,0x5f,0x19,0xa2,0x32,0xc, 0x7e,0x90,0x3, 0x74,0x3, 0xa, +0x2f,0x2d,0x2d,0x7a,0x29,0xb0,0xa, 0x2f,0x2d,0x2d,0x19,0xb2,0x0, 0xa, 0xe4,0xa, +0x2f,0x2d,0x2d,0x19,0xb2,0x0, 0x50,0x61,0xd3,0x49,0x23,0x27,0xdc,0xbe,0x24,0x0, +0x1e,0x38,0x10,0x49,0x13,0x27,0xde,0xbe,0x14,0x0, 0x1e,0x40,0x6, 0xbe,0x14,0x8, +0xca,0x28,0x1c,0xbe,0x24,0x4, 0x1a,0x50,0x2, 0x61,0x34,0x49,0x33,0x27,0xde,0xbe, +0x34,0x0, 0x1e,0x50,0x2, 0x61,0x34,0xbe,0x34,0x8, 0xca,0x28,0x2, 0x61,0x34,0x12, +0xc4,0x97,0x12,0x27,0xdd,0x58,0x2, 0x41,0xef,0x12,0xc4,0x86,0x70,0x2d,0x7e,0x34, +0x0, 0x9, 0xca,0x39,0x7e,0x30,0x63,0xac,0x3f,0x2e,0x14,0x2e,0x87,0x6d,0x0, 0xac, +0x7e,0x2d,0x3b,0x6d,0x22,0x12,0x1a,0xb, 0x1b,0xfd,0xa, 0x3f,0x2d,0x3d,0x2e,0x34, +0x0, 0x50,0x7e,0x39,0xb0,0x4, 0x7a,0x39,0xb0,0x80,0x54,0x74,0x63,0xac,0xbf,0x49, +0x25,0x2e,0x89,0x12,0xc4,0xa0,0x49,0x33,0x0, 0x2, 0x12,0x7e,0x2a,0x74,0x63,0xac, +0xbf,0x49,0x25,0x2e,0x87,0x12,0xc4,0xa0,0xb, 0x38,0x30,0x9d,0x32,0x12,0x1a,0x62, +0x2d,0x31,0xbe,0x34,0x0, 0x50,0x58,0x44,0x12,0xc5,0xe, 0x7c,0x6f,0x12,0x22,0x78, +0x40,0x8, 0x12,0xc5,0xe, 0x12,0x9c,0x4a,0x50,0x5, 0x74,0x38,0x12,0xc4,0xb1,0x12, +0xc4,0x86,0xbe,0xb0,0x37,0x50,0x8, 0x2e,0x34,0x0, 0x50,0x4, 0x7a,0x39,0xb0,0x7e, +0xa0,0x1, 0x7e,0x70,0x5, 0xac,0x7f,0x19,0xa3,0x32,0xc, 0x7e,0x90,0x3, 0x74,0x3, +0xa, 0x3f,0x2d,0x3d,0x7a,0x39,0xb0,0x12,0xc4,0xa8,0x61,0xd3,0x12,0xc0,0x5d,0xa, +0x3f,0x19,0xb3,0x32,0x74,0x7e,0x70,0x63,0xac,0x7f,0x49,0x23,0x2e,0x87,0x4d,0x22, +0x78,0x8, 0x49,0x23,0x2e,0x89,0x4d,0x22,0x68,0x3, 0x12,0xc4,0xfe,0x74,0x37,0x12, +0xc4,0xb1,0x61,0xd3,0x12,0xc4,0x86,0xbe,0xb0,0x0, 0x38,0x2, 0x61,0xd3,0xbe,0xb0, +0x38,0x78,0x2, 0x61,0xd3,0x12,0xc0,0x5d,0xa, 0x3f,0x19,0xb3,0x32,0x74,0x74,0x63, +0xac,0xbf,0x49,0x35,0x2e,0x87,0x4d,0x33,0x78,0x8, 0x49,0x35,0x2e,0x89,0x4d,0x33, +0x68,0x67,0x49,0xc, 0x0, 0x2, 0x74,0x9, 0xac,0xbe,0x49,0x25,0x37,0x94,0x7d,0x3a, +0x9d,0x32,0x12,0x1a,0x62,0x7d,0xc3,0x7e,0x70,0x63,0xac,0x7f,0x12,0xc4,0xfe,0xbe, +0xc4,0x0, 0x10,0x50,0x15,0x12,0xc4,0xcd,0xb, 0xc8,0x30,0xbe,0x34,0x0, 0x5, 0x28, +0x9, 0xbe,0x34,0x4, 0x33,0x50,0x3, 0x12,0xc4,0xc3,0x12,0x9b,0x1d,0x50,0x2a,0x12, +0xc4,0xcd,0x9, 0x8c,0x0, 0x7, 0xbe,0x83,0x39,0x0, 0x78,0xa, 0x9, 0x7c,0x0, 0x8, +0xbe,0x73,0x39,0x2, 0x68,0x10,0xbe,0x83,0x39,0x1, 0x78,0xd, 0x9, 0x8c,0x0, 0x8, +0xbe,0x83,0x39,0x3, 0x78,0x3, 0x12,0xc4,0xc3,0x74,0x37,0xa, 0xcf,0x2d,0xcd,0x19, +0xbc,0x0, 0x50,0x4c,0x99,0x68,0x2, 0x81,0x78,0x12,0xc4,0x8f,0x7c,0x6f,0x12,0x22, +0x78,0x40,0x8, 0x12,0xc4,0x8f,0x12,0x9c,0x4a,0x50,0x30,0x12,0xc4,0xd7,0xa, 0xcf, +0x2d,0xcd,0x9, 0xbc,0x0, 0x3c,0x70,0x6, 0x74,0x1, 0x19,0xbc,0x0, 0x3c,0xa, 0xcf, +0x2d,0xcd,0x9, 0x7c,0x0, 0x3c,0xbe,0x70,0x1, 0x38,0x6d,0x74,0x38,0x19,0xbc,0x0, +0x50,0x74,0x3, 0x12,0xc5,0x2e,0x12,0xc4,0xa8,0x80,0x5d,0x74,0x9, 0xac,0xbe,0x49, +0xc5,0x27,0xdc,0xbe,0xc4,0x0, 0x1e,0x38,0xb, 0x12,0xc4,0x7d,0x40,0x6, 0xbe,0x44, +0x8, 0xca,0x28,0x44,0xbe,0xc4,0x4, 0x1a,0x40,0xb, 0x12,0xc4,0x7d,0x40,0x6, 0xbe, +0x44,0x8, 0xca,0x28,0x33,0x12,0xc4,0x7d,0x38,0xc, 0xbe,0xc4,0x0, 0x1e,0x40,0x6, +0xbe,0xc4,0x4, 0x1a,0x28,0x22,0xbe,0x44,0x8, 0xe8,0x40,0xc, 0xbe,0xc4,0x0, 0x1e, +0x40,0x6, 0xbe,0xc4,0x4, 0x1a,0x28,0x10,0xa, 0x3f,0x2d,0x3d,0x9, 0xb3,0x0, 0x3c, +0x70,0x6, 0x74,0x2, 0x19,0xb3,0x0, 0x3c,0xda,0x79,0xda,0xd8,0x22,0x49,0x45,0x27, +0xde,0xbe,0x44,0x0, 0x1e,0x22,0xa, 0x3f,0x2d,0x3d,0x9, 0xb3,0x0, 0x50,0x22,0x74, +0x9, 0xac,0xbe,0x7d,0xc5,0x2d,0xcb,0x9, 0xbc,0x0, 0x7, 0x9, 0x7c,0x0, 0x8, 0x22, +0x7e,0x70,0x9, 0xac,0x7e,0x2d,0x3b,0x22,0xa, 0x3f,0x2d,0x3d,0x19,0xb3,0x0, 0xa, +0x22,0xa, 0x3f,0x2d,0x3d,0x19,0xb3,0x0, 0x50,0x22,0x74,0x9, 0xac,0xbe,0x7d,0xa5, +0x2d,0xab,0x22,0x1b,0xc8,0xa0,0x2d,0x1b,0x59,0x1, 0x0, 0x2, 0x22,0x7e,0x30,0x9, +0xac,0x3e,0x7d,0xc1,0x2d,0xcb,0x22,0x6c,0xaa,0x7e,0x70,0x5, 0xac,0x7f,0x19,0xa3, +0x32,0xf, 0x22,0x74,0x9, 0xac,0xbe,0x49,0x55,0x27,0xde,0xbe,0x54,0x0, 0x1e,0x22, +0x6d,0x22,0xa, 0x18,0x6d,0x0, 0x12,0x17,0x18,0x2f,0x17,0x74,0x6, 0x22,0x2e,0x34, +0x2e,0x87,0x7e,0x30,0x9, 0xac,0x3e,0x2d,0x1b,0x74,0x9, 0x2, 0x17,0xb9,0x7e,0x70, +0x9, 0xac,0x7e,0x2d,0x3b,0x9, 0xb3,0x0, 0x7, 0x9, 0x73,0x0, 0x8, 0x22,0x7d,0x1c, +0x1a,0x2, 0x1a,0x0, 0x12,0x17,0x18,0x7f,0x71,0x74,0x9, 0xac,0xbd,0x22,0xa, 0xcf, +0x2d,0xcd,0x7a,0xc9,0xb0,0x22,0xa, 0xcf,0x2d,0xcd,0x7e,0xc9,0xb0,0x22,0x7e,0x34, +0x28,0x90,0x6c,0xaa,0xa, 0x2a,0x2d,0x23,0x7e,0x29,0xb0,0xb4,0x3, 0x2c,0x7e,0x30, +0xff,0x7e,0x50,0x5, 0xac,0x5a,0x19,0x32,0x32,0xb, 0xe4,0x19,0xb2,0x32,0xc, 0x19, +0xb2,0x32,0xd, 0x74,0x3, 0x19,0xb2,0x32,0xe, 0xe4,0x19,0xb2,0x32,0xf, 0x12,0xc5, +0x82,0x28,0x4, 0x19,0xb2,0x32,0xe, 0x12,0xc5,0x8a,0xb, 0xa0,0xbe,0xa0,0xa, 0x40, +0xc3,0x22,0x7e,0xb3,0x3a,0xb5,0xbe,0xb0,0x0, 0x22,0x9, 0xb2,0x32,0xe, 0x7a,0xb3, +0x3a,0xb6,0x22,0xca,0x78,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9,0xc5,0xea,0xa9, +0x30,0xe5,0x19,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0x5, 0x6a,0x7e,0x73,0x3c,0x35,0xbe, +0x71,0x6a,0x38,0x2, 0xd2,0x1a,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9,0x34,0xe5,0x5, +0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9,0x33,0xe5,0x3, +0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5,0x3, 0xa9,0xc6, +0xcd,0xda,0x78,0x32,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22,0xa9,0xc4, +0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0xc6,0x1f,0xa9,0xd0,0xce,0xa9, +0xc0,0xc9,0xd2,0x2, 0x12,0x3b,0x5e,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75,0xc2,0xc, +0xd2,0x0, 0x12,0xc6,0x28,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1,0x22,0xa, +0x5b,0x2e,0x54,0x0, 0x8, 0xf5,0xcc,0x22,0xa2,0x0, 0xa9,0x97,0xc1,0xa2,0x0, 0xa9, +0x97,0xc2,0x22,0xa9,0xd0,0xce,0xa2,0x0, 0xa9,0x95,0xc9,0x22,0xca,0xf8,0xa2,0xaf, +0xe4,0x33,0x7c,0xfb,0xd2,0x0, 0x12,0xc6,0x33,0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0, +0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e, +0xa9,0xd0,0xcd,0x74,0x41,0x12,0x3f,0x4b,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0, +0xff,0x92,0xaf,0xda,0xf8,0x22,0xa9,0xd5,0xcb,0x74,0x10,0x12,0x0, 0x6e,0x7c,0x7b, +0x12,0x3e,0xcf,0x30,0xe7,0x3, 0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24,0x0, 0xef,0x7e, +0xf, 0x3b,0xfa,0x79,0x20,0x0, 0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, 0x3b,0xfa,0x79, +0x20,0x0, 0x82,0x7e,0x24,0x41,0x0, 0x7e,0xf, 0x3b,0xfa,0x79,0x20,0x0, 0x90,0x7c, +0x67,0x6c,0x77,0x2e,0x34,0x0, 0xc1,0x7e,0xf, 0x3b,0xfa,0x79,0x30,0x0, 0x86,0x7e, +0x34,0x29,0x90,0x7e,0xf, 0x3b,0xfa,0x79,0x30,0x0, 0x8a,0x7e,0x34,0x6a,0xd1,0x7e, +0xf, 0x3b,0xfa,0x79,0x30,0x0, 0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, 0x3b,0xfa,0x79, +0x30,0x0, 0x8e,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86,0xa9, +0xc2,0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9,0xd1, +0x99,0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, 0x75, +0x8b,0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7,0x0, +0x75,0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0,0xf7, +0xd2,0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7,0xc2, +0xbe,0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3c,0x33,0xb, 0x34,0x7a, +0x37,0x3c,0x33,0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3c, +0x33,0x22,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, +0x6c,0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6,0x12,0x77,0xd1,0xb, 0xa0, +0xbe,0xa0,0xd, 0x40,0xed,0xc2,0xc9,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4,0x6c, +0x11,0x80,0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x25,0xcf,0xa, +0x20,0xa, 0x33,0x9d,0x32,0x12,0x1a,0x62,0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, 0x74, +0x25,0xce,0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x1a,0x62,0x7c,0x97,0xbe,0x90,0x1, +0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, 0xbe, +0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x27,0x58,0xbc,0x81,0x18, +0xb2,0x22,0x7f,0x71,0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0xcf,0x69,0xb, 0x7a,0x20, +0x2d,0x25,0x1b,0xa, 0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c,0xab, +0xe4,0x1e,0x34,0x1e,0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, 0x7d, +0x53,0x7c,0xab,0xe4,0x3e,0x54,0x3e,0x54,0x12,0xc8,0x39,0x1e,0x24,0x2d,0x25,0x79, +0x20,0x0, 0x4, 0x69,0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12,0x59,0x99,0x1e,0x34, +0x1e,0x34,0x2d,0x32,0x79,0x30,0x0, 0x6, 0x22,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x22, +0x7c,0xab,0x9f,0x11,0x30,0x0, 0x22,0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d, +0xe0,0x7e,0x7b,0xb0,0x7e,0x78,0x0, 0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d, +0x3f,0x4d,0x2e,0xb, 0x90,0xbc,0xa9,0x38,0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4, +0x93,0x7c,0xfb,0x7e,0x8, 0x1e,0x44,0x12,0xc8,0xf6,0x7e,0x8, 0x1e,0x4c,0x12,0xc8, +0xfe,0xd2,0x0, 0x7e,0x8, 0x29,0xc9,0x7c,0xbf,0x12,0xc8,0x40,0x7e,0x8, 0x1e,0x44, +0x7a,0xf, 0x1e,0x68,0x7f,0x1, 0x7a,0x17,0x1e,0x6c,0x7d,0x32,0x7a,0x37,0x1e,0x6e, +0x7e,0x18,0x1e,0x4c,0x7a,0x1f,0x1e,0x74,0x6c,0x77,0x80,0xe, 0x12,0xc9,0x46,0x50, +0x7, 0x12,0xc9,0x3d,0x19,0x51,0x1e,0x4c,0xb, 0x70,0xbc,0xf7,0x38,0xee,0x12,0xc8, +0xe3,0xe4,0x12,0xc8,0xeb,0xe4,0x12,0xc, 0x9b,0x6d,0x33,0x7a,0x37,0x1e,0x6c,0x7a, +0x37,0x1e,0x6e,0x12,0xc8,0xe3,0x74,0x1, 0x12,0xc8,0xeb,0x74,0x1, 0x12,0xc, 0x9b, +0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e,0x8, 0x1e,0x68,0x22,0x12,0xc, 0x9b,0xa9,0xd6, +0xea,0x7e,0x8, 0x1e,0x68,0x22,0x7e,0x34,0x0, 0x8, 0xe4,0x2, 0x1a,0x30,0x7e,0x34, +0x0, 0x1c,0x74,0x3f,0x2, 0x1a,0x30,0x7e,0x8, 0x1e,0x44,0x12,0xc8,0xfe,0x6c,0x77, +0x80,0xe, 0x12,0xc9,0x46,0x50,0x7, 0x12,0xc9,0x3d,0x19,0x51,0x1e,0x44,0xb, 0x70, +0x7e,0x53,0x29,0x5b,0xbc,0x57,0x38,0xea,0xa9,0xc6,0xea,0x7e,0x8, 0x1e,0x44,0xe4, +0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e,0x8, 0x1e,0x44,0x2, 0x11,0x38,0xa, 0x27,0x9, +0x52,0x2a,0x31,0xa, 0x16,0x22,0xa, 0x27,0x9, 0x62,0x29,0xc9,0xbe,0x60,0x1c,0x22, +0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80,0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e, +0x7b,0x60,0xa, 0x46,0x2e,0x44,0x19,0xc5,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93, +0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12,0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e, +0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, +0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a, +0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80,0x58, +0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e,0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12,0xca, +0xd, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe, +0x60,0x1b,0x38,0x16,0x9e,0x60,0xe, 0x12,0xca,0xd, 0x60,0x5, 0x3e,0x44,0x14,0x78, +0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0xca,0xd, +0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a, +0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, 0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, +0x1, 0x7c,0xb6,0x22,0x7e,0x27,0x27,0x77,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64, +0x30,0x5, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0x80,0x49,0x4, 0x4, 0x0, +0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x24,0xca,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59, +0xf4,0x5, 0x80,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, +0x80,0x30,0x7, 0x2e,0x7e,0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xe0,0x49,0x4, 0x4, +0x60,0xbd,0x2, 0x8, 0x11,0x7e,0xb3,0x24,0xca,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3, +0x59,0xf4,0x5, 0xe0,0x80,0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, +0x5, 0xe0,0xb, 0xa0,0x7e,0xb3,0x29,0x61,0xa, 0xb, 0x7e,0xb3,0x29,0x60,0xa, 0x4b, +0x2d,0x40,0xa, 0xa, 0xbd,0x4, 0x48,0x88,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33, +0x19,0xb3,0x26,0x46,0xb, 0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0x5d,0x5a,0xb, 0x24, +0xa, 0x33,0xbd,0x32,0x48,0xe7,0xe4,0x7a,0xb3,0x27,0x58,0x7a,0xb3,0x27,0x59,0x6d, +0x33,0x7a,0x37,0x27,0x5a,0x7a,0x37,0x27,0x5c,0x7a,0x37,0x27,0x5e,0x7a,0x37,0x27, +0x62,0x7e,0xd4,0x1e,0x46,0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x12,0x9a,0x7a, +0x37,0x1e,0x86,0x7d,0x3d,0x7a,0x37,0x1e,0x8a,0x7e,0x34,0x14,0xae,0x7a,0x37,0x1e, +0x88,0x7e,0x73,0x29,0x5a,0x7a,0x73,0x1e,0x83,0x7e,0x73,0x29,0x5b,0x7a,0x73,0x1e, +0x82,0x7e,0x37,0x29,0x49,0x7a,0x37,0x1e,0x8c,0x7e,0x37,0x29,0x4b,0x7a,0x37,0x1e, +0x8e,0x7e,0x37,0x29,0x4d,0x7a,0x37,0x1e,0x90,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1e, +0x84,0x7e,0x73,0x3, 0xfe,0x7a,0x73,0x1e,0x85,0x7e,0x8, 0x1e,0x82,0x7e,0x18,0x1e, +0x92,0x12,0x8, 0x0, 0x7e,0x73,0x1e,0x92,0x7a,0x73,0x27,0x58,0x7e,0x73,0x1e,0x93, +0x7a,0x73,0x27,0x59,0x7e,0x37,0x1e,0x94,0x7a,0x37,0x27,0x5a,0x7e,0x37,0x1e,0x96, +0x7a,0x37,0x27,0x5c,0x7e,0x37,0x1e,0x9c,0x7a,0x37,0x27,0x5e,0x7e,0x37,0x1e,0x9e, +0x7d,0x23,0x7a,0x53,0x27,0x60,0xa, 0x36,0x7a,0x73,0x27,0x61,0x7e,0x37,0x1e,0x98, +0x7a,0x37,0x27,0x62,0x7e,0x37,0x1e,0x9a,0x7d,0x23,0x7a,0x53,0x27,0x64,0xa, 0x36, +0x7a,0x73,0x27,0x65,0x6c,0x33,0x80,0x1b,0x12,0x5f,0x55,0x74,0x2, 0xac,0xb3,0x49, +0x45,0x14,0xae,0xa, 0x38,0x7c,0x27,0x19,0x25,0x25,0xce,0x7c,0x29,0x19,0x25,0x25, +0xcf,0xb, 0x30,0x7e,0x23,0x27,0x58,0xbc,0x23,0x38,0xdd,0x6c,0x33,0x80,0x1b,0x74, +0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25, +0x26,0xa, 0x7c,0x29,0x19,0x25,0x26,0xb, 0xb, 0x30,0x7e,0x23,0x27,0x59,0xbc,0x23, +0x38,0xdd,0x22,0xe4,0x7a,0xb3,0x3, 0xf2,0x22,0x7e,0xb3,0x3a,0xd0,0x70,0x6, 0x12, +0xcc,0x12,0x2, 0xcb,0xd3,0x12,0x4e,0x9f,0x12,0xcd,0x22,0x50,0xa, 0x12,0xcc,0x18, +0x7c,0x3b,0x12,0xcc,0x12,0x80,0x5, 0x12,0x4b,0xf0,0x7c,0x3b,0x4c,0x33,0x68,0x11, +0x7c,0xb3,0x12,0xcc,0xa6,0x60,0xa, 0x7a,0x33,0x3a,0xd3,0x74,0x1, 0x7a,0xb3,0x28, +0xfa,0x22,0xe4,0x7a,0xb3,0x2e,0x5e,0x22,0x12,0xcc,0x9d,0x7a,0x37,0x2e,0x7a,0x12, +0xcc,0x28,0x7a,0x37,0x2e,0x7c,0xe4,0x22,0x7e,0x37,0x2e,0x74,0x9e,0x37,0x2e,0x6c, +0x22,0x7e,0x17,0x2e,0x6e,0xbd,0x13,0x28,0xa, 0x7a,0x37,0x2e,0x6e,0x7a,0x27,0x2e, +0x70,0x80,0x10,0x7e,0x17,0x2e,0x66,0xbd,0x13,0x50,0x8, 0x7a,0x37,0x2e,0x66,0x7a, +0x27,0x2e,0x68,0x7e,0x17,0x2e,0x6c,0xbd,0x12,0x28,0xa, 0x7a,0x27,0x2e,0x6c,0x7a, +0x37,0x2e,0x6a,0x80,0x10,0x7e,0x17,0x2e,0x74,0xbd,0x12,0x50,0x8, 0x7a,0x27,0x2e, +0x74,0x7a,0x37,0x2e,0x72,0x7e,0xb3,0x2e,0x86,0xb4,0xa, 0xf, 0x12,0xcc,0x9d,0x7a, +0x37,0x2e,0x7e,0x12,0xcc,0x28,0x7a,0x37,0x2e,0x80,0x22,0xb4,0x14,0xe, 0x12,0xcc, +0x9d,0x7a,0x37,0x2e,0x82,0x12,0xcc,0x28,0x7a,0x37,0x2e,0x84,0x22,0x7e,0x37,0x2e, +0x66,0x9e,0x37,0x2e,0x6e,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54,0x0, 0x20,0xe, 0x54, +0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60,0xf0,0xa5,0xbe,0x20, +0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb, +0x7e,0x73,0x33,0xf9,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x3a,0xd1,0x80,0x36,0xa5,0xbe, +0x30,0x18,0x12,0xcd,0x19,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53,0x33,0xfa, +0xa, 0x45,0x5d,0x43,0x7e,0x73,0x3a,0xd2,0x80,0x1a,0x12,0xcd,0x19,0x60,0x5, 0x3e, +0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x33,0xf9,0xa, 0x4b,0x5d,0x43,0xa, 0x5a, +0x9, 0x75,0x3a,0xd3,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54,0xf, 0x7e,0x34,0x0, +0x1, 0x22,0x7e,0xb3,0x2e,0x5e,0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x7e,0xa3,0x2e, +0x86,0xbe,0xa0,0xf0,0x50,0x1b,0x74,0x4, 0xa4,0x59,0x35,0x2a,0x9d,0x7e,0xa3,0x2e, +0x86,0x74,0x4, 0xa4,0x59,0x25,0x2a,0x9f,0x7e,0xb3,0x2e,0x86,0x4, 0x7a,0xb3,0x2e, +0x86,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x1a,0x62,0x7c,0xa7,0x7d,0x31,0x9d, +0x30,0x12,0x1a,0x62,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c,0xba,0x22,0x22,0x7d,0xf2, +0x7d,0xe3,0x7e,0x8, 0x2e,0x5e,0x7e,0x34,0x0, 0x28,0xe4,0x12,0x1a,0x30,0x7e,0x8, +0x2a,0x9d,0x7e,0x34,0x3, 0xc0,0x12,0x1a,0x30,0x7a,0xb3,0x3a,0xd3,0x7e,0x34,0x62, +0xa5,0x12,0x4b,0xe8,0x7a,0x37,0x2a,0x95,0x7a,0xe7,0x2e,0x62,0x7a,0xf7,0x2e,0x64, +0x7a,0xe7,0x2e,0x66,0x7a,0xe7,0x2e,0x6a,0x7a,0xe7,0x2e,0x6e,0x7a,0xe7,0x2e,0x72, +0x7a,0xf7,0x2e,0x68,0x7a,0xf7,0x2e,0x6c,0x7a,0xf7,0x2e,0x70,0x7a,0xf7,0x2e,0x74, +0x7a,0xe7,0x2a,0x99,0x7a,0xf7,0x2a,0x9b,0x7a,0xb3,0x2e,0x86,0x74,0x2, 0x7a,0xb3, +0x2e,0x5d,0x22,0x74,0xfe,0x7a,0xb3,0x3a,0xd3,0xe4,0x7a,0xb3,0x2e,0x5e,0x22,0x2d, +0x3d,0x7e,0x24,0x0, 0x2, 0x2, 0x16,0xe6,0xe5,0x2a,0xa, 0x3b,0x9, 0xb3,0x36,0xaa, +0xf5,0x27,0xe5,0x2a,0xa, 0x3b,0x9, 0xb3,0x36,0xb4,0xf5,0x28,0x22,0x7e,0xd, 0x27, +0x2d,0x15,0xb, 0xa, 0x30,0x9d,0x32,0x59,0x35,0x1e,0x44,0x5, 0x2d,0x22,0x7c,0xb8, +0x4, 0x7c,0x8b,0x1a,0x3b,0x7e,0xb3,0x29,0x5c,0x1a,0xeb,0xbd,0x3e,0x22,0x7c,0xb9, +0x4, 0x7c,0x9b,0x1a,0x3b,0x7e,0xb3,0x29,0x5d,0x1a,0xeb,0xbd,0x3e,0x22,0x7e,0x18, +0x5, 0x80,0x7a,0x1f,0x6, 0x40,0x22,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x49,0x35,0x1e, +0x44,0x2, 0x1a,0x62,0x7e,0xa1,0x2d,0x74,0x2, 0xa4,0x7f,0x13,0x2d,0x35,0xb, 0x1a, +0x20,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xe5,0x25,0xce,0x9, 0xd5,0x25,0xcf,0x22,0x74, +0xff,0xa, 0x3e,0x19,0xb3,0x39,0x0, 0x19,0xb3,0x39,0x2, 0x22,0x7a,0x5, 0x2c,0x7e, +0x24,0x0, 0x3, 0x7d,0x31,0x2, 0x16,0xe6,0x7d,0x2d,0x12,0x16,0xe6,0x7d,0x53,0x22, +0xe5,0x4c,0xa, 0x3b,0x7e,0x24,0x0, 0x3, 0x2, 0x16,0xe6,0x54,0xf, 0xa, 0x3b,0x2d, +0x37,0x7d,0x26,0x7e,0x1b,0xb0,0x22,0x7e,0xa1,0x31,0xe5,0x30,0xa4,0xbe,0x54,0x0, +0x1, 0x22,0x6d,0xff,0x9e,0xf7,0x29,0x47,0xbe,0xf7,0x27,0x62,0x22,0x7e,0xa1,0x2a, +0x74,0x5, 0xa4,0x9, 0xb5,0x32,0xc, 0x22,0x6d,0x33,0x7a,0x37,0x3b,0x93,0x22,0xa, +0x47,0x7f,0x70,0x2d,0xf4,0x7e,0x7b,0x60,0x22,0x7e,0x30,0x2, 0xac,0x39,0x49,0xf1, +0x4, 0xc0,0x22,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, +0xb3,0x1e,0x44,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e,0x14,0x27,0x82,0x22,0x74,0x2, +0x12,0x0, 0x1e,0x7e,0x8, 0x6, 0x48,0x22,0x7e,0x34,0x0, 0xa, 0xe4,0x2, 0x1a,0x30, +0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0x22,0x7e,0x71,0x2b,0x12,0x21,0x5e,0x9d, +0x93,0x22,0xe5,0x4b,0xa, 0xbb,0x1b,0xb4,0xe5,0x2b,0x22,0x74,0x2, 0xac,0x7b,0x9, +0xa3,0x25,0xce,0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18,0x0, 0x24,0x22,0x7a,0x37,0x27, +0x75,0x7a,0x37,0x27,0x77,0x22,0xa, 0x2b,0x1b,0x24,0xa, 0x3e,0xbd,0x32,0x22,0x6d, +0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, 0xe5,0x24,0xa, 0x3b,0x9, 0xb3,0x29,0x0, 0x22, +0x7e,0x73,0x3b,0x12,0x7a,0x73,0x2a,0xd, 0x22,0x12,0x0, 0x1e,0x7e,0xb3,0x29,0xe9, +0x22,0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0x22,0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4, +0x22,0x7c,0x7f,0x12,0x21,0x5e,0x9d,0x93,0x22,0x7e,0x73,0x27,0x59,0xbe,0x70,0x0, +0x22,0x7d,0x2e,0x12,0x16,0xe6,0x7d,0xf3,0x22,0x7e,0x24,0x0, 0x4, 0x2, 0x16,0xe6, +0xe4,0x12,0x13,0xde,0x2, 0x13,0x96,0x7e,0x37,0x29,0xf4,0xbe,0x35,0x2b,0x22,0x7e, +0x34,0x0, 0xc8,0x2, 0x1c,0xf4,0x7e,0x71,0x32,0x74,0x6, 0xac,0x7b,0x22,0x5, 0x29, +0xe5,0x29,0xbe,0xb0,0xa, 0x22,0xcf,0xb6,0x30,0x49,0xfa,0x5, 0xc, 0x51, \ No newline at end of file diff --git a/drivers/input/touchscreen/ft5446/include/firmware/D1S_1_FT5446_Ofilm_TM_V07_D01_20180613_app.i b/drivers/input/touchscreen/ft5446/include/firmware/D1S_1_FT5446_Ofilm_TM_V07_D01_20180613_app.i new file mode 100644 index 0000000000000..f47a2eac3750d --- /dev/null +++ b/drivers/input/touchscreen/ft5446/include/firmware/D1S_1_FT5446_Ofilm_TM_V07_D01_20180613_app.i @@ -0,0 +1,3347 @@ +0x2, 0x19,0x22,0x2, 0xc8,0x5d,0xeb,0xaa,0x8, 0x22,0x22,0x2, 0x0, 0x5a,0xb4,0x2, +0x4, 0xa9,0xb7,0xea,0x22,0x24,0xff,0xa9,0x97,0xea,0x22,0x2, 0x51,0x28,0xb4,0x2, +0x4, 0xa9,0xb6,0xea,0x22,0x24,0xff,0xa9,0x96,0xea,0x22,0x2, 0x68,0x2, 0x7f,0x60, +0xa9,0xc2,0xea,0x74,0x1, 0x12,0x13,0x96,0x7f,0x6, 0x12,0x5, 0xb4,0x7f,0x6, 0x2, +0x9, 0xa1,0x22,0x2, 0x68,0x1e,0xf5,0xfd,0xe5,0xfe,0x22,0x2, 0x0, 0x69,0x12,0x10, +0xa2,0x2, 0x13,0x79,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32,0x2, 0x0, 0x76,0x1, 0x2, +0x4, 0x8, 0x10,0x20,0x40,0x80,0xb2,0x86,0x22,0x32,0x32,0x2, 0x0, 0x6a,0xb2,0x82, +0x22,0xff,0xff,0x2, 0x10,0x52,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b, +0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0xd, 0x7e,0xf, 0x3c,0x5b, +0x69,0x30,0x0, 0x4, 0x7a,0x73,0x3c,0x6b,0x7e,0x73,0x3c,0x6b,0xa, 0x37,0x5e,0x34, +0x0, 0x4, 0x68,0x4, 0xd2,0xc, 0x80,0x2, 0xc2,0xc, 0x7e,0x34,0x0, 0x1f,0x79,0x30, +0x0, 0x4, 0xc2,0xc3,0x12,0x12,0x9e,0x12,0x69,0x31,0x7e,0x1f,0x3c,0x5b,0x69,0x31, +0x0, 0x2, 0x5e,0x34,0x0, 0x40,0x68,0x2e,0x6c,0xaa,0x7e,0x10,0x2, 0xac,0x1a,0x7e, +0x1f,0x3c,0x5b,0x7f,0x71,0x2d,0xf0,0x69,0x17,0x0, 0x9c,0x59,0x10,0x3c,0x5f,0xb, +0xa0,0xbe,0xa0,0x3, 0x78,0xe4,0x69,0x11,0x0, 0xa4,0x7a,0x17,0x3c,0x67,0x69,0x31, +0x0, 0xa2,0x7a,0x37,0x3c,0x65,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda, +0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0x7d,0x13, +0x7e,0x1f,0x3c,0x86,0x1b,0x1a,0x10,0xc2,0xc6,0xd2,0xee,0x22,0xff,0xff,0x54,0x2c, +0xca,0x79,0x7f,0x50,0x7c,0xeb,0x7e,0x34,0x0, 0x24,0x7e,0x8, 0x0, 0x2c,0x7e,0x24, +0x0, 0x2, 0x12,0x52,0xa0,0xe5,0x2c,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x4a,0xe5,0x2c, +0xbe,0xb0,0x76,0x28,0x2, 0x21,0x4a,0x7e,0xe1,0x2c,0xbe,0xe0,0x76,0x38,0x2, 0x21, +0x78,0x7e,0x34,0x18,0xae,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18,0x92,0x79,0x35,0x0, +0x4, 0xbe,0xe0,0x81,0x68,0x2, 0x21,0x71,0x74,0x23,0x7a,0x5b,0xb0,0x74,0x1c,0x61, +0x84,0x74,0x1, 0x7a,0x5b,0xb0,0x61,0x84,0x7c,0xbe,0x14,0xbe,0xb0,0x75,0x40,0x2, +0x61,0x33,0x7e,0xa0,0x3, 0xa4,0x2e,0x54,0x1, 0x8c,0x89,0x54,0x2, 0x2, 0xfb,0x2, +0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xed,0x2, 0x2, +0xfb,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x2, 0xfb, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x25,0x2, 0x3, 0x33,0x2, 0x3, 0x9, 0x2, +0x2, 0xfb,0x2, 0x3, 0x17,0x2, 0x3, 0x17,0x2, 0x2, 0xfb,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, +0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33, +0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, +0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x3, 0x33,0x2, 0x2, 0xfb,0x41,0xfb,0x7e,0x34,0x18, +0xae,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18,0x4b,0x61,0x3f,0x7e,0x34,0x18,0x82,0x79, +0x35,0x0, 0x2, 0x7e,0x34,0x18,0x92,0x61,0x3f,0x7e,0x34,0x18,0x82,0x79,0x35,0x0, +0x2, 0x7e,0x34,0x18,0x1b,0x61,0x3f,0x7e,0x34,0x17,0xff,0x79,0x35,0x0, 0x2, 0x7e, +0x34,0x18,0x2f,0x61,0x3f,0x7e,0x34,0x18,0x73,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18, +0x5a,0x61,0x3f,0x7e,0x34,0x18,0xae,0x79,0x35,0x0, 0x2, 0x7e,0x34,0x18,0x92,0x79, +0x35,0x0, 0x4, 0xbe,0xe0,0x16,0x28,0x2, 0x61,0x4e,0x7c,0xfe,0x61,0x62,0x7e,0xf0, +0x16,0xbe,0xe0,0x72,0x50,0x2, 0x61,0x62,0xa, 0x3e,0x9e,0x34,0x0, 0x72,0xb, 0x34, +0x2c,0xf7,0x7e,0x70,0x3, 0xac,0x7f,0x7d,0x23,0x2e,0x24,0x18,0xd2,0x7a,0x51,0x82, +0x7a,0x41,0x83,0xe4,0x93,0x7a,0x5b,0xb0,0x2e,0x34,0x18,0xd3,0x7a,0x71,0x82,0x7a, +0x61,0x83,0xe4,0x93,0x39,0xb5,0x0, 0x1, 0xda,0x79,0x22,0xca,0x3b,0x7f,0x30,0x74, +0x1, 0x12,0x13,0xde,0x29,0x73,0x0, 0xf3,0x2e,0x70,0xff,0x92,0x1, 0x29,0xb3,0x0, +0xf4,0x12,0x13,0xaf,0x7f,0x3, 0x12,0xd, 0x72,0x7f,0x3, 0x12,0x6, 0xba,0x29,0x73, +0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xa3, +0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24, +0x69,0x33,0x0, 0xff,0x4d,0x32,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x2, 0x29,0x73, +0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x5, 0xa, 0x57,0x9d,0x54,0xf5,0x34,0x29,0xb3, +0x0, 0xa5,0x70,0xb, 0x29,0xb3,0x0, 0xf8,0x29,0x73,0x0, 0xf7,0x12,0xb, 0xad,0x29, +0x73,0x0, 0xa5,0x2e,0x70,0xff,0x92,0x1, 0xe5,0x34,0x12,0xb, 0x1e,0x69,0x33,0x0, +0xfd,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x28,0x69,0x23,0x0, 0xfb,0x3e,0x24,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x0, 0xfa,0xa, 0x37,0x2d, +0x32,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x2a,0x29,0x73,0x0, 0xf9,0xa, 0x37,0x7e, +0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3c,0x5b,0x79, +0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x2e,0x29, +0x73,0x0, 0x5, 0xa, 0x37,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x10,0x69,0x33,0x0, +0xa8,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xaa,0x7e,0xf, 0x3c, +0x5b,0x79,0x30,0x0, 0x1e,0x6c,0xaa,0x7e,0x50,0x2, 0xac,0x5a,0x69,0x13,0x1, 0x1, +0x2d,0x12,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x7e,0xf, 0x3c,0x5b,0x2d,0x12,0x79, +0x30,0x0, 0x44,0xb, 0xa0,0xbe,0xa0,0xc, 0x40,0xdd,0xda,0x3b,0x22,0xca,0xf8,0x7f, +0x70,0x7e,0x7b,0xf0,0x29,0x77,0x0, 0x1, 0xbc,0x7f,0x28,0x2, 0x7c,0xf7,0x69,0x17, +0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2,0x74,0xff,0x12,0x1a,0x30,0x7f,0x7, 0x12, +0xe, 0xed,0xa9,0xd6,0xcb,0x6c,0xaa,0x80,0x2d,0x6c,0x77,0x80,0x1f,0x7e,0x10,0xb, +0xac,0x1a,0xa, 0x17,0x2d,0x1, 0x3e,0x4, 0x69,0x17,0x0, 0x6, 0x2d,0x10,0x6d,0x0, +0xb, 0xa, 0x20,0x6e,0x24,0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x67,0x0, 0x1, +0xbc,0x67,0x38,0xd9,0xb, 0xa0,0x7e,0x7b,0x60,0xbc,0x6a,0x38,0xcc,0x69,0x37,0x0, +0x6, 0x7e,0xf, 0x3c,0x95,0x79,0x30,0x0, 0x4, 0x7c,0x4f,0x6c,0x55,0xa, 0x3f,0x2d, +0x32,0x7e,0xf, 0x3c,0x95,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3c,0x95,0x1b, +0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0xf, 0x45,0x6c,0xaa,0xbe,0xa0,0x4, 0x50,0x18, +0x7e,0x70,0x4, 0xac,0x7a,0x7c,0xb7,0x7e,0x1f,0x3c,0x95,0x69,0x41,0x0, 0x26,0x60, +0x42,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3b,0xbe,0xa0,0x8, 0x50,0x1b,0xa, 0x3a,0x1b, +0x36,0x3e,0x34,0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3c,0x95,0x69,0x41,0x0, 0x28,0x60, +0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xa, 0x3a,0x9e,0x34,0x0, 0x8, 0x3e,0x34, +0x3e,0x34,0x7c,0xb7,0x7e,0x1f,0x3c,0x95,0x69,0x41,0x0, 0x2a,0x60,0x5, 0x1e,0x44, +0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x50,0x2, 0xac,0x5a,0x69,0x37,0x0, 0x6, +0x2d,0x32,0x6d,0x22,0x1b,0x1a,0x40,0xb, 0xa0,0xbe,0xa0,0xb, 0x40,0x8d,0xa9,0xc6, +0xcb,0xda,0xf8,0x22,0x29,0x70,0x0, 0x96,0x29,0x90,0x0, 0x98,0x29,0x60,0x0, 0x97, +0x29,0x80,0x0, 0x8d,0xbe,0x80,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe,0x80,0x8, +0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x80,0x10,0x38,0x5, 0x7e,0xa0,0x2, 0x80, +0xd, 0xbe,0x80,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, 0xbe,0x90, +0x3, 0x28,0x3, 0x7e,0x90,0x3, 0xbe,0x80,0x3f,0x28,0x3, 0x7e,0x80,0x3f,0xbe,0x60, +0x1, 0x28,0x3, 0x7e,0x60,0x1, 0xbe,0x70,0x2, 0x28,0x2, 0x6c,0x77,0xa, 0x28,0x3e, +0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x89,0x6c,0x99,0x3e,0x44,0x3e, +0x44,0x3e,0x44,0x2d,0x42,0xa, 0x26,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, +0x24,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0x7f,0x3c,0x86,0x79,0x37,0x0, +0x2, 0x29,0xb0,0x0, 0x8c,0x7c,0x4b,0x6c,0x55,0x29,0xb0,0x0, 0x8b,0xa, 0x3b,0x2d, +0x32,0x7e,0x7f,0x3c,0x53,0x79,0x37,0x0, 0x80,0x69,0x30,0x0, 0xa0,0x7e,0x7f,0x3c, +0x86,0x79,0x37,0x0, 0xc, 0x69,0x30,0x0, 0x9e,0x5e,0x34,0xe0,0xf, 0x29,0xb0,0x0, +0x8c,0xa, 0x2b,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e, +0x7f,0x3c,0x53,0x79,0x37,0x0, 0x82,0xa, 0x2a,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, +0x24,0x29,0xb0,0x0, 0x99,0xa, 0x3b,0x2d,0x32,0x7e,0x7f,0x3c,0x86,0x79,0x37,0x0, +0x6, 0x69,0x30,0x0, 0x9c,0x7e,0x7f,0x3c,0x86,0x79,0x37,0x0, 0x8, 0x69,0x30,0x0, +0x9a,0x7e,0xf, 0x3c,0x86,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x60,0x74,0x1, 0x12,0x13, +0xde,0x29,0x36,0x0, 0xf5,0x29,0x26,0x0, 0xa3,0x29,0x16,0x0, 0xa4,0xbe,0x20,0x2, +0x28,0x3, 0x7e,0x20,0x2, 0xbe,0x10,0x40,0x28,0x3, 0x7e,0x10,0x40,0x7e,0x34,0x0, +0x4, 0x7c,0xb2,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0x7, 0xa, 0x31,0x7e,0x2f, +0x3c,0x5b,0x79,0x32,0x0, 0x12,0x7c,0x73,0xac,0x70,0xa, 0x21,0x12,0x16,0xe6,0x7c, +0x27,0xa, 0x32,0x7e,0x2f,0x3c,0x5b,0x79,0x32,0x0, 0x14,0x7c,0x73,0xac,0x70,0x29, +0x26,0x0, 0xf6,0xa, 0x22,0xad,0x32,0xa, 0x21,0x8d,0x32,0x7d,0x43,0x7c,0x73,0xac, +0x70,0xa, 0x21,0x12,0x16,0xe6,0x7c,0xa7,0x7c,0x2a,0x7c,0xb9,0x2c,0xab,0xbe,0xa0, +0xc, 0x50,0x3, 0x7e,0xa0,0xc, 0xbe,0x20,0xc, 0x50,0x3, 0x7e,0x20,0xc, 0xa, 0x20, +0xa, 0x31,0x12,0x16,0xe6,0x7d,0xe3,0xa, 0x3a,0xb, 0x34,0xad,0x3e,0xb, 0x34,0xbe, +0x34,0x2, 0x0, 0x40,0x4, 0x7e,0x34,0x1, 0xff,0x29,0x46,0x0, 0xf7,0x7e,0x50,0x2, +0xac,0x45,0xa, 0xf2,0xad,0xfe,0x2d,0x2f,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, +0x7e,0x24,0x1, 0xff,0xa, 0x13,0x7e,0x7f,0x3c,0x5b,0x79,0x17,0x0, 0xa, 0x1e,0x24, +0x7c,0x45,0x6c,0x55,0x1e,0x34,0x2d,0x32,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0xc, +0xa, 0x3a,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30, +0x0, 0x4, 0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f, +0x3c,0x95,0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0x95,0x79,0x32, +0x0, 0x8, 0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d, +0x32,0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e, +0xf, 0x3c,0x95,0x79,0x30,0x0, 0xe, 0x6d,0x11,0x7e,0x1f,0x3c,0x95,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xe0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xd2,0x1, 0x2, 0x3b,0x8c, +0x7f,0x21,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x4, 0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, +0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, 0x6, 0x69,0x30,0x0, +0x6, 0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, 0x8, 0x29,0x70,0x0, 0x1, 0x7c,0x47,0x6c, +0x55,0x7e,0xb, 0x70,0xa, 0x37,0x2d,0x32,0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, 0xc, +0x29,0x70,0x0, 0x2, 0xa, 0x37,0x1b,0x34,0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, 0xa, +0x69,0x30,0x0, 0xa, 0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, 0xe, 0x69,0x30,0x0, 0xc, +0x7e,0x7f,0x3c,0x95,0x79,0x37,0x0, 0x10,0x69,0x30,0x0, 0xe, 0x7e,0x7f,0x3c,0x95, +0x79,0x37,0x0, 0x12,0x29,0x70,0x0, 0x3, 0x7c,0x27,0x6c,0x33,0x7e,0x1f,0x3c,0x95, +0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0xf, 0x45,0x7e,0x1f,0x3c,0x95,0x69,0x11, +0x0, 0x1a,0x7a,0x2b,0x30,0x69,0x11,0x0, 0x1c,0x39,0x32,0x0, 0x1, 0x69,0x11,0x0, +0x16,0x79,0x12,0x0, 0x2, 0x69,0x11,0x0, 0x18,0x79,0x12,0x0, 0x4, 0x69,0x11,0x0, +0x22,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x24,0x79,0x12,0x0, 0x8, 0x69,0x11,0x0, +0x1e,0x79,0x12,0x0, 0xa, 0x69,0x31,0x0, 0x20,0x79,0x32,0x0, 0xc, 0xa9,0xc6,0xcb, +0x22,0xca,0x3b,0x7c,0x57,0x7c,0x4b,0x5e,0x40,0x3, 0x69,0x30,0x0, 0x4, 0x5e,0x60, +0x3f,0x6c,0xaa,0xa, 0x4a,0x69,0xf0,0x0, 0xa, 0x69,0xe0,0x0, 0x8, 0x2d,0xf4,0x7e, +0x7b,0xb0,0xa, 0xfb,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0xa, 0xea,0x69,0xd0, +0x0, 0xe, 0x69,0xc0,0x0, 0xc, 0x2d,0xde,0x7e,0x6b,0xb0,0xa, 0x4b,0x2d,0x4f,0x7e, +0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, 0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0, +0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3c,0x82,0x2d,0xfd,0x79,0x47,0x1, 0x8c,0xb, 0xa0, +0xbe,0xa0,0xe, 0x78,0xae,0x6c,0xaa,0x7e,0x90,0x2, 0xac,0x9a,0x69,0xf0,0x0, 0x2, +0xb, 0xa, 0xe0,0x2d,0xf4,0xb, 0x7a,0x40,0x7e,0xd0,0x28,0xac,0xd5,0x7e,0xf0,0x2, +0xac,0xfa,0x7d,0xd7,0x2d,0xd6,0x7e,0xf0,0xf0,0xac,0xf4,0x2d,0xd7,0x7e,0x7f,0x3c, +0x82,0x2d,0xfd,0x79,0x47,0x1, 0x80,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xc9,0x7e,0x90, +0xf0,0xac,0x94,0x74,0x28,0xac,0xb5,0x7d,0xf5,0x2d,0xf4,0x7e,0x2f,0x3c,0x82,0x2d, +0x5f,0x79,0x32,0x1, 0x88,0x69,0x30,0x0, 0x6, 0x7e,0x30,0xf0,0xac,0x34,0x74,0x28, +0xac,0x5b,0x2d,0x21,0x7e,0xf, 0x3c,0x82,0x2d,0x12,0x79,0x30,0x1, 0x8a,0xda,0x3b, +0x22,0x29,0x60,0x0, 0xb, 0xa, 0x46,0x29,0x60,0x0, 0x4, 0xa, 0x26,0x2d,0x24,0x7c, +0x65,0x29,0xb0,0x0, 0x6, 0xbc,0xb6,0x28,0x2, 0x7c,0x6b,0x29,0x70,0x0, 0x5, 0x29, +0xb0,0x0, 0x7, 0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0x6c,0xaa,0x6d,0x22,0x7e,0x90,0x2, +0xac,0x9a,0x7e,0x7f,0x3c,0x53,0x2d,0xf4,0x79,0x27,0x0, 0x2, 0xb, 0xa0,0xbe,0xa0, +0x23,0x78,0xea,0x6c,0xaa,0x80,0x55,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x57,0x0, +0x4c,0xbe,0x50,0x23,0x50,0x23,0x29,0x47,0x0, 0xb4,0xa, 0xd4,0x7d,0x4d,0x7c,0x89, +0x6c,0x99,0x7d,0xd4,0x7e,0x90,0x2, 0xac,0x95,0x7e,0x7f,0x3c,0x53,0x2d,0xf4,0xb, +0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xa, 0x4a,0x7f,0x70,0x2d,0xf4,0x29, +0x47,0x0, 0x4c,0xa, 0xd4,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x3c,0x53,0x2d,0xf4, +0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, 0xa0,0xbc,0x6a,0x38,0xa7, +0x6c,0xaa,0x80,0x1d,0xa, 0x2a,0x7f,0x70,0x2d,0xf2,0x29,0x67,0x0, 0x6f,0xa, 0x46, +0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x3c,0x53,0x2d,0xf2,0x79,0x47,0x0, 0x48,0xb, +0xa0,0xbc,0x7a,0x38,0xdf,0x22,0x7c,0x7b,0x7e,0x7f,0x3c,0x5b,0x69,0x47,0x0, 0xc, +0x6c,0x88,0x3e,0x44,0x69,0x7, 0x0, 0xa, 0x69,0x57,0x0, 0x2, 0x1e,0x54,0x1e,0x54, +0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x1e,0x54,0x5e,0x54,0x0, 0x3, 0x7e,0x14, +0x0, 0x4, 0x70,0x2, 0x41,0x9b,0x3e,0x14,0x14,0x78,0xfb,0x7c,0xa3,0xa, 0xda,0xad, +0xd0,0x7d,0xcd,0x6d,0x11,0x79,0x17,0x0, 0x8c,0x7c,0xb7,0x70,0x2, 0x41,0xb4,0x1e, +0xd4,0x14,0x78,0xfb,0xbe,0xd4,0x1, 0x0, 0x38,0x2, 0x41,0xc2,0x7e,0xd4,0x1, 0x0, +0x41,0xce,0xbe,0xd4,0x0, 0x10,0x40,0x2, 0x41,0xce,0x7e,0xd4,0x0, 0x10,0x7d,0x3d, +0x12,0x12,0x6a,0xa, 0x1b,0x7e,0x1f,0x3c,0x5b,0x79,0x11,0x0, 0x90,0x7e,0x1f,0x3c, +0x5b,0x79,0xd1,0x0, 0x8e,0x7e,0x7f,0x3c,0x5b,0x69,0x37,0x0, 0x8, 0xad,0x3c,0x8d, +0x3d,0x79,0x37,0x0, 0x92,0x7e,0x14,0x0, 0x6, 0x7e,0x1f,0x3c,0x5b,0x79,0x11,0x0, +0x94,0x7d,0x24,0x9d,0x20,0xa, 0x3a,0xad,0x32,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, +0x96,0x7e,0x34,0x0, 0x10,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x98,0x22,0x7c,0x5b, +0x7e,0xf, 0x3c,0x5b,0x69,0x40,0x0, 0x22,0x30,0x1, 0x6b,0x6d,0xff,0x7d,0x3f,0xbe, +0x50,0x10,0x28,0x2e,0x7e,0x54,0xff,0xff,0x79,0x50,0x0, 0x42,0x9e,0x50,0x10,0x6c, +0xaa,0x80,0x11,0x7e,0xe4,0x0, 0x1, 0x7c,0xba,0x60,0x5, 0x3e,0xe4,0x14,0x78,0xfb, +0x2d,0x3e,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e,0x6f,0x3c,0x5b,0x79,0x36,0x0, 0x40, +0x80,0x25,0x79,0xf0,0x0, 0x40,0x6c,0xaa,0x80,0x11,0x7e,0xf4,0x0, 0x1, 0x7c,0xba, +0x60,0x5, 0x3e,0xf4,0x14,0x78,0xfb,0x2d,0x3f,0xb, 0xa0,0xbc,0x5a,0x38,0xeb,0x7e, +0x7f,0x3c,0x5b,0x79,0x37,0x0, 0x42,0x7d,0x34,0x2e,0x34,0x0, 0xc, 0x7e,0x7f,0x3c, +0x5b,0x79,0x37,0x0, 0x16,0x22,0x6d,0x33,0x79,0x30,0x0, 0x40,0x7e,0xf, 0x3c,0x5b, +0x79,0x30,0x0, 0x42,0x7e,0x1f,0x3c,0x5b,0x79,0x41,0x0, 0x16,0x22,0x7c,0x17,0x7c, +0x3b,0x6d,0x33,0x7e,0x2f,0x3c,0x5b,0x79,0x32,0x0, 0x40,0x7e,0x2f,0x3c,0x5b,0x79, +0x32,0x0, 0x42,0x7e,0x7f,0x3c,0x5b,0x69,0x57,0x0, 0x12,0x7c,0xab,0x69,0x37,0x0, +0x2, 0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, +0x34,0x0, 0x3, 0x7c,0xb7,0x7e,0x44,0x0, 0x4, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7c,0x29,0xa, 0x22,0xa, 0x3a,0x12,0x16,0xe6,0xa, 0x23,0x2d,0x32,0x7c,0xb7,0x7c, +0x61,0x6c,0x77,0xa, 0xb, 0x1e,0x4, 0x2d,0x3, 0x79,0x7, 0x0, 0xc, 0x7c,0x73,0xac, +0x72,0xa, 0x2a,0x12,0x16,0xe6,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x16,0x6d,0x33, +0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x22,0x22,0xa9,0xd6,0xcb,0x69,0x30,0x0, 0x6, +0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0x95, +0x79,0x32,0x0, 0x8, 0x29,0x70,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x3, +0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0xc, 0x7e,0xb, 0x70,0x7c, +0x47,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, +0xa, 0x29,0x70,0x0, 0x4, 0xa, 0x37,0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0xe, 0x29, +0xb0,0x0, 0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x3c,0x95,0x1b,0x1a,0x10, +0x7e,0x34,0x0, 0xc0,0x12,0xf, 0x45,0xa9,0xc6,0xcb,0x22,0xca,0x79,0x7c,0xab,0x5e, +0xa0,0x3, 0x6c,0x77,0x7e,0x50,0x2, 0xac,0x57,0x69,0xd0,0x0, 0xe, 0x69,0xc0,0x0, +0xc, 0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6,0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d, +0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e,0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e, +0x7f,0x3c,0x82,0x2d,0xf2,0x79,0x47,0x2, 0x54,0xb, 0x70,0xbe,0x70,0xe, 0x40,0xc4, +0x69,0x40,0x0, 0x4, 0x7e,0xf0,0xf0,0xac,0xfa,0x7e,0x1f,0x3c,0x82,0x2d,0x37,0x79, +0x41,0x2, 0x50,0x69,0x30,0x0, 0x6, 0x74,0xf0,0xa4,0x7e,0xf, 0x3c,0x82,0x2d,0x15, +0x79,0x30,0x2, 0x52,0xda,0x79,0x22,0xa9,0xd6,0xcb,0xc2,0x1c,0x69,0x30,0x0, 0x4, +0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0x4, 0x69,0x30,0x0, 0x6, 0x7e,0x2f,0x3c,0x95, +0x79,0x32,0x0, 0x6, 0x69,0x30,0x0, 0x8, 0x7e,0x2f,0x3c,0x95,0x79,0x32,0x0, 0x8, +0x7e,0xb, 0x70,0x7c,0x47,0x6c,0x55,0x29,0x70,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e, +0x2f,0x3c,0x95,0x79,0x32,0x0, 0xc, 0x29,0x70,0x0, 0x2, 0xa, 0x37,0x7e,0x2f,0x3c, +0x95,0x79,0x32,0x0, 0xe, 0x29,0xb0,0x0, 0x3, 0x54,0x1, 0xa, 0x5b,0x7c,0xab,0xe4, +0x7e,0x1f,0x3c,0x95,0x1b,0x1a,0x50,0x69,0x30,0x0, 0xa, 0x12,0xf, 0x45,0xa9,0xc6, +0xcb,0x22,0x69,0x30,0x0, 0xae,0x7e,0x2f,0x3c,0x5b,0x79,0x32,0x0, 0x6, 0x29,0x50, +0x0, 0xa6,0xa, 0x55,0x7d,0x23,0x1e,0x24,0x9d,0x25,0x7e,0x2f,0x3c,0x5b,0x79,0x22, +0x0, 0x18,0x7d,0x23,0x1e,0x24,0x1b,0x25,0x7e,0x2f,0x3c,0x5b,0x79,0x22,0x0, 0x38, +0x69,0x20,0x0, 0xfd,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0x2f,0x3c,0x5b, +0x79,0x32,0x0, 0x26,0x29,0x70,0x0, 0xa7,0xa, 0x37,0x7e,0x2f,0x3c,0x5b,0x79,0x32, +0x0, 0x1a,0x29,0x70,0x0, 0xb, 0xa, 0x27,0x29,0x70,0x0, 0x4, 0x2d,0x32,0x7e,0x2f, +0x3c,0x5b,0x79,0x32,0x0, 0x8, 0x2, 0x9, 0xa1,0xca,0x3b,0xf5,0x24,0x7f,0x41,0x7f, +0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0xe5,0x24,0xbe,0xb0,0x23,0x28, +0x3, 0x75,0x24,0x23,0x6c,0xaa,0x80,0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b, +0xb0,0xbe,0xb1,0x26,0x40,0xd, 0x74,0x23,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, +0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, 0x3b,0x2e,0x35,0x28,0x7a,0x71,0x82,0x7a,0x61, +0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13,0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24, +0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22,0xa9,0xd6,0xcb,0x69,0x20,0x0, 0x4, 0x7e,0x2f, +0x3c,0x95,0x79,0x22,0x0, 0x4, 0x69,0x20,0x0, 0x8, 0x7e,0x2f,0x3c,0x95,0x79,0x22, +0x0, 0x8, 0x7e,0xb, 0x50,0xa, 0x55,0x7c,0xab,0xe4,0x29,0x50,0x0, 0x1, 0xa, 0x25, +0x2d,0x25,0x7e,0x2f,0x3c,0x95,0x79,0x22,0x0, 0xc, 0x29,0x50,0x0, 0x2, 0xa, 0x25, +0x7e,0xf, 0x3c,0x95,0x79,0x20,0x0, 0xe, 0x7e,0xf, 0x3c,0x95,0x79,0x30,0x0, 0xa, +0x6d,0x11,0x7e,0x1f,0x3c,0x95,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0xf, 0x45, +0xa9,0xc6,0xcb,0x22,0x7c,0xab,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3c,0x86,0x79,0x30, +0x0, 0xe, 0xc2,0x1b,0xe4,0x7a,0xb3,0x3c,0x81,0x5e,0xa0,0x3, 0xa, 0x1a,0x3e,0x14, +0x7e,0x1f,0x3c,0x53,0x1b,0x1a,0x10,0x7e,0xf, 0x3c,0x53,0x2e,0x14,0x0, 0x84,0xb, +0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x13,0x56,0x7e,0xf, 0x3c, +0x86,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x3c, +0x86,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7f,0x10,0xa9, +0xd6,0xcb,0x69,0x11,0x0, 0x2, 0x7e,0x2f,0x3c,0x95,0x79,0x12,0x0, 0x4, 0x69,0x11, +0x0, 0x4, 0x7e,0x2f,0x3c,0x95,0x79,0x12,0x0, 0x6, 0x69,0x11,0x0, 0x6, 0x7e,0x2f, +0x3c,0x95,0x79,0x12,0x0, 0x8, 0x7e,0x1b,0x30,0xa, 0x3, 0x7e,0x14,0x1, 0x0, 0xad, +0x10,0x29,0x71,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e,0xf, 0x3c,0x95,0x79,0x30,0x0, +0xc, 0x6d,0x11,0x7e,0x1f,0x3c,0x95,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x60,0x12,0xf, +0x45,0xa9,0xc6,0xcb,0x22,0xa9,0xd7,0xcb,0x7d,0x23,0x4e,0x50,0x1, 0x7e,0xf, 0x3c, +0x95,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e,0x7e,0xf, 0x3c,0x95,0xb, +0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0xb, 0xa9,0xd7, +0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x1c,0x7e,0xf, 0x3c,0x95,0xb, 0xa, 0x30, +0x7d,0x23,0x5e,0x24,0x80,0x0, 0xbe,0x24,0x80,0x0, 0x78,0xcf,0x4e,0x60,0x40,0x1b, +0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x3c,0x95,0x1b,0x1a,0x10,0x22,0xca,0x3b,0xf5,0x24, +0x7f,0x41,0x7f,0x30,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0x1, 0x20,0x6c,0xaa,0x80, +0x36,0xa, 0x3a,0x2d,0x39,0x7d,0x28,0x7e,0x1b,0xb0,0xbe,0xb1,0x27,0x40,0xd, 0x74, +0x1c,0xa, 0x4a,0x7f,0x3, 0x2d,0x14,0x7a,0xb, 0xb0,0x80,0x19,0x7e,0x1b,0xb0,0xa, +0x3b,0x2e,0x35,0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x4a,0x7f,0x13, +0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xe5,0x24,0xbc,0xba,0x38,0xc4,0xda,0x3b,0x22, +0x5, 0x63,0x31,0x20,0x18,0x13,0xf, 0xd, 0xc, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, +0xca,0xf8,0x7d,0xe2,0x7d,0xd3,0x7c,0xfb,0xbe,0x30,0x1, 0x28,0x6, 0x7e,0xf4,0x0, +0x10,0x80,0xf, 0xbe,0x30,0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x8, 0x80,0x4, 0x7e,0xf4, +0x0, 0x4, 0x7d,0x1f,0x6d,0x0, 0x6d,0x33,0x7e,0x24,0x0, 0x10,0x12,0x17,0x85,0x7f, +0x1, 0x7d,0x3d,0x6d,0x22,0x12,0x17,0x18,0x7d,0x1e,0x12,0x17,0x32,0x74,0x4, 0xac, +0xbf,0x7e,0xf, 0x3c,0x5b,0x2d,0x15,0x79,0x30,0x0, 0x82,0x79,0x20,0x0, 0x80,0xda, +0xf8,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, +0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x1b,0x7e,0xf, 0x3c,0x86,0xb, 0xa, 0x30,0x7c, +0x57,0x7a,0x53,0x3c,0x81,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, +0xf, 0x3c,0x86,0x79,0x30,0x0, 0xe, 0x12,0x12,0x9e,0x12,0x69,0x31,0xd0,0x82,0xd0, +0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, +0x7b,0x32,0x74,0x3, 0x12,0x13,0x56,0xa9,0xd1,0xc4,0x7e,0xf, 0x3c,0x53,0x2e,0x14, +0x0, 0x84,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x7e,0x14,0x0, 0x1, 0x7e, +0x1f,0x3c,0x53,0x1b,0x1a,0x10,0x7e,0xf, 0x3c,0x5b,0xb, 0x16,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0xc2,0xd, 0xe4,0x7a,0xb3,0x3c,0x6b,0x7e,0x1f,0x3c,0x53, +0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74,0x2, 0x2, 0x13,0x56,0x7c,0x6b, +0x6c,0xaa,0x80,0x17,0x7e,0x90,0x2, 0xac,0x9a,0x7e,0x7f,0x3c,0x82,0x2d,0xf4,0xb, +0x7a,0x20,0x7f,0x70,0x2d,0xf4,0x1b,0x7a,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xe5,0x6c, +0xaa,0x80,0x20,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0x7f,0x3c,0x82,0x2d,0xf2,0x69,0x27, +0x0, 0x38,0xa, 0xf7,0xa, 0x4a,0x2d,0x4f,0x3e,0x44,0x7f,0x70,0x2d,0xf4,0x1b,0x7a, +0x20,0xb, 0xa0,0xbc,0x6a,0x38,0xdc,0x22,0xca,0x79,0x7c,0xab,0x5e,0xa0,0x3, 0x6c, +0x77,0x7e,0x50,0x2, 0xac,0x57,0x7f,0x60,0x2d,0xd2,0x29,0x66,0x0, 0x1, 0xa, 0xf6, +0x7d,0x4f,0x7c,0x89,0x6c,0x99,0x7d,0xf4,0x7e,0x6b,0x60,0xa, 0x46,0x2d,0x4f,0x7e, +0xf0,0xf0,0xac,0xfa,0x2d,0x27,0x7e,0x7f,0x3c,0x82,0x2d,0xf2,0x79,0x47,0x2, 0x54, +0xb, 0x70,0xbe,0x70,0xe, 0x40,0xca,0xda,0x79,0x22,0x29,0x50,0x0, 0xf5,0xac,0x5b, +0x7e,0xf, 0x3c,0x5b,0x69,0x30,0x0, 0xc, 0xa, 0x56,0x3e,0x54,0xbe,0x24,0x2, 0x0, +0x40,0x4, 0x7e,0x24,0x1, 0xff,0xbd,0x25,0x28,0x1f,0x2e,0x14,0x0, 0xc, 0x6c,0x66, +0x1b,0xa, 0x30,0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3c,0x5b,0x2e,0x14,0x0, +0xc, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50, +0x28,0xac,0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d, +0x24,0x7e,0x7f,0x3c,0x82,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x44,0xa, 0x4a,0x7f, +0x60,0x2d,0xd4,0x7e,0x6b,0xb0,0x7c,0x8b,0x6c,0x99,0x4d,0x24,0x79,0x27,0x1, 0x8c, +0xb, 0xa0,0xbe,0xa0,0xe, 0x40,0xc7,0x22,0x7c,0x6b,0x6c,0xaa,0x7e,0x50,0x28,0xac, +0x57,0x7e,0x90,0x2, 0xac,0x9a,0x2d,0x42,0x7e,0x50,0xf0,0xac,0x56,0x2d,0x24,0x7e, +0x7f,0x3c,0x82,0x2d,0xf2,0x69,0x27,0x1, 0x8c,0x6c,0x55,0xa, 0x4a,0x7f,0x60,0x2d, +0xd4,0x7e,0x6b,0xb0,0xa, 0x4b,0x4d,0x24,0x79,0x27,0x1, 0x8c,0xb, 0xa0,0xbe,0xa0, +0xe, 0x40,0xc9,0x22,0xa9,0xd6,0xcb,0x54,0x3f,0x5e,0x70,0x1f,0x7c,0x2b,0x6c,0x33, +0x3e,0x14,0x3e,0x14,0x2e,0x14,0x0, 0x5, 0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34, +0x3e,0x34,0x3e,0x34,0x2d,0x31,0x7e,0xf, 0x3c,0x95,0x79,0x30,0x0, 0x2, 0x7e,0xf, +0x3c,0x95,0x79,0x20,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x7d,0x23,0x6c,0x66,0x7e,0x30, +0x2, 0xac,0x36,0x2e,0x14,0x19,0xe1,0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0xa, +0x1b,0xbd,0x12,0x28,0x7, 0xb, 0x60,0xbe,0x60,0x14,0x40,0xe2,0x7e,0x70,0x2, 0xac, +0x67,0x2e,0x34,0x19,0xe2,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7e,0xf, +0x3c,0x53,0x2e,0x14,0x0, 0x84,0xb, 0xa, 0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74, +0x3, 0x12,0x13,0x56,0x7e,0x14,0x0, 0x3, 0x7e,0x1f,0x3c,0x53,0x1b,0x1a,0x10,0x7e, +0x1f,0x3c,0x53,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0xe4,0x2, 0x13,0x56, +0x2e,0x34,0x4, 0x0, 0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x60,0x7e,0x34,0x4, 0x0, +0x9d,0x32,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x62,0x7e,0x34,0x0, 0x1, 0x7e,0xf, +0x3c,0x5b,0x79,0x30,0x0, 0x64,0xa, 0x3b,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x66, +0x22,0x7c,0xa5,0xbe,0x34,0x0, 0x0, 0x28,0x10,0xa, 0x1b,0x3e,0x14,0x7d,0x23,0x7c, +0x45,0x6c,0x55,0x2d,0x21,0xa, 0x3a,0x80,0x8, 0xa, 0x2b,0x3e,0x24,0x7c,0x67,0x6c, +0x77,0x2d,0x32,0x7e,0xf, 0x3c,0x86,0x79,0x30,0x0, 0x4, 0x22,0x7c,0xa7,0x7e,0x1f, +0x3c,0x53,0x69,0x41,0x0, 0x8a,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14, +0x3e,0x14,0x3e,0x14,0xa, 0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d, +0x45,0x79,0x41,0x0, 0x8a,0x22,0x7e,0xf, 0x3c,0x53,0x69,0x30,0x0, 0x84,0x5e,0x70, +0xe7,0x1b,0xb1,0x68,0xc, 0x14,0x68,0xc, 0xb, 0xb1,0x78,0x5, 0x4e,0x70,0x10,0x80, +0x3, 0x4e,0x70,0x8, 0x79,0x30,0x0, 0x84,0x22,0x7e,0x34,0x0, 0x1f,0x7e,0xf, 0x3c, +0x5b,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xf, 0x3c,0x5b,0xb, 0xa, 0x30,0x4e, +0x70,0x1, 0x1b,0xa, 0x30,0x22,0xbe,0xb0,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3, +0xcb,0xa9,0xd2,0xcb,0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x30, +0x1, 0xa, 0x54,0x3, 0xa, 0x3b,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, +0x3c,0x5b,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x3c,0x53,0x69,0x30,0x0, 0x8a,0x60, +0x5, 0x4e,0x60,0x10,0x80,0x3, 0x5e,0x60,0xef,0x79,0x30,0x0, 0x8a,0x22,0xbe,0xb0, +0x0, 0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2, +0xcd,0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, +0x4, 0xc2,0xc3,0xd2,0xeb,0x22,0x2, 0x16,0x51,0x6e,0x0, 0x80,0x7c,0xb1,0x33,0x7c, +0xb0,0x33,0x68,0xd, 0x4, 0x68,0xef,0x7c,0xb5,0x33,0x7c,0xb4,0x33,0x78,0x3, 0x7f, +0x10,0x22,0x4, 0x68,0xe1,0x7d,0x50,0x92,0xf7,0x7d,0x45,0x7d,0x51,0xbf,0x21,0x40, +0x6, 0x7c,0x80,0x7f,0x1, 0x7f,0x12,0x12,0x16,0x14,0x7e,0xa1,0xd0,0x5c,0xb0,0x4, +0x78,0x3, 0x20,0xd5,0xc1,0x7c,0xb0,0x4, 0x78,0x7, 0x50,0x2, 0xb2,0xd5,0x2, 0x16, +0x59,0x92,0xd5,0xbe,0x80,0xff,0x68,0xf6,0x7c,0xb8,0x9c,0xb0,0x6c,0x0, 0x60,0x2a, +0xb4,0x18,0x5, 0x7c,0x41,0x2, 0x16,0x2d,0x50,0xfb,0x80,0x3, 0x2f,0x0, 0x4, 0x7c, +0x9b,0x5e,0x90,0x7, 0x78,0xf6,0x30,0xe4,0x6, 0x7c,0x43,0x7d,0x10,0x6d,0x0, 0x30, +0xe3,0x8, 0x7c,0x43,0x7c,0x32,0x7c,0x21,0xa, 0x0, 0x30,0xf5,0x19,0x9f,0x10,0x78, +0xe, 0x22,0x2, 0x16,0x56,0x1b,0x80,0x68,0xf9,0x2f,0x11,0x50,0x2, 0xb, 0x70,0x7c, +0xb5,0x30,0xe7,0xf1,0x80,0x1b,0x2d,0x31,0x7c,0xb5,0xa5,0x39,0x7c,0x5b,0x50,0x11, +0xb, 0x80,0x78,0x3, 0x2, 0x16,0x59,0x1e,0x34,0x13,0x50,0x3, 0x4e,0x60,0x80,0x1a, +0x2b,0x2, 0x16,0x2d,0x74,0xf8,0x6c,0xaa,0x6e,0x40,0x80,0x6e,0x0, 0x80,0xbe,0xb0, +0xff,0x68,0x27,0x7c,0x83,0x7c,0x97,0x5c,0x3b,0x5c,0x7b,0xbf,0x10,0x68,0x2a,0xf4, +0x40,0xd, 0x7c,0x38,0x2d,0x15,0xf4,0x5c,0x3b,0x50,0xf, 0xb, 0x4, 0x80,0xb, 0x7c, +0x79,0x2d,0x35,0xf4,0x5c,0x7b,0x50,0x2, 0xb, 0x24,0xbf,0x10,0x68,0xb, 0x7c,0xb0, +0x20,0xe7,0x6, 0x7c,0xb4,0x20,0xe7,0x1, 0xb3,0x22,0x7e,0xa0,0x20,0x80,0xc, 0x7e, +0xa0,0x10,0x80,0x5, 0x7e,0xa0,0x8, 0x6c,0x55,0x6d,0x33,0x33,0x92,0xd5,0x50,0xa, +0x6e,0x34,0xff,0xff,0x6e,0x24,0xff,0xff,0xb, 0x1c,0xa5,0xec,0x33,0x40,0x6, 0x2f, +0x11,0xd5,0xf0,0xf6,0x22,0x7c,0xba,0x24,0x7e,0xa2,0xd5,0x13,0x7c,0x76,0x7c,0x65, +0xa5,0xcc,0x92,0xe7,0x7c,0x5b,0x22,0x7c,0xb5,0x33,0x7c,0xb4,0x33,0x92,0xd5,0x4e, +0x50,0x80,0x24,0x81,0x40,0x3, 0x9f,0x11,0x22,0x7c,0x45,0x7c,0x56,0x7c,0x67,0x6c, +0x77,0x24,0xe0,0x50,0xe, 0x7e,0x1c,0xff,0xff,0x22,0x1e,0x34,0x1e,0x24,0x50,0x3, +0x4e,0x60,0x80,0x4, 0x78,0xf4,0x30,0xd5,0xa, 0x6e,0x34,0xff,0xff,0x6e,0x24,0xff, +0xff,0xb, 0x1c,0x22,0x7c,0xb5,0xa2,0xe7,0xd2,0xe7,0x7c,0x1b,0x7c,0xb4,0x33,0x40, +0x9, 0x68,0xd, 0xb4,0xff,0xb, 0xa5,0xbd,0xff,0x3, 0x2, 0x16,0x51,0x2, 0x16,0x59, +0x22,0x7c,0xb, 0x24,0x81,0xc2,0xe0,0xf5,0x82,0xf4,0x4, 0x2c,0xb0,0x7c,0x2b,0xc3, +0x13,0x7c,0x4b,0x7c,0xb5,0x92,0xe7,0x7c,0x5b,0x7f,0x41,0x7c,0xb6,0xa2,0xe7,0x7c, +0xb1,0xa5,0xba,0x7f,0x2, 0xc3,0x13,0x34,0x0, 0x94,0x0, 0x7c,0x2b,0x7e,0xa0,0x91, +0xa4,0x7c,0xba,0x13,0xf4,0x94,0xfe,0xac,0xb2,0x33,0x7c,0xba,0x33,0x24,0x8c,0xd3, +0x13,0x7c,0x5b,0xe4,0x92,0xe7,0x7c,0x6b,0x6c,0x77,0x7e,0x40,0x3f,0x75,0x83,0x2, +0x7f,0x51,0x7f,0x1, 0x7f,0x14,0x12,0x16,0x65,0x7f,0x5, 0x12,0x14,0xc, 0x9e,0x24, +0x0, 0x80,0xd5,0x83,0xeb,0x7e,0x1, 0x82,0x6c,0x11,0xe, 0x4, 0x1e,0x4, 0x2d,0x20, +0x5e,0x40,0x7f,0x22,0x2d,0x0, 0x92,0xd5,0xe, 0x10,0x4e,0x10,0x80,0x7d,0x42,0x2d, +0x44,0x50,0x2, 0xb2,0xd5,0x4e,0x50,0x80,0x6c,0x44,0x7c,0xb8,0x22,0x2c,0x44,0x50, +0x12,0xb, 0x1c,0x7e,0x40,0x0, 0x5e,0x50,0x7f,0xbe,0x18,0x0, 0x0, 0x78,0x4, 0xb, +0x80,0x68,0x16,0xa2,0xd5,0x7c,0xb8,0x13,0x7c,0x4b,0x7c,0xb5,0x92,0xe7,0x7c,0x5b, +0x22,0x7e,0x1c,0xff,0xff,0x22,0x9f,0x11,0x22,0x7e,0x24,0xff,0x80,0x20,0xd5,0x2, +0x6c,0x45,0x6d,0x33,0x22,0xbe,0x24,0xff,0xff,0x68,0x6, 0xbe,0x4, 0xff,0xff,0x78, +0x3, 0x2, 0x16,0x51,0x12,0x16,0x14,0x5c,0xb0,0x4, 0x68,0xf5,0x7c,0xb8,0xa5,0x48, +0x68,0xef,0x7c,0xb8,0x70,0x3, 0x9f,0x11,0x22,0xa5,0xb8,0x0, 0x3, 0x2, 0x16,0x59, +0x2e,0x0, 0x81,0x50,0x7, 0x9c,0x80,0x38,0x7, 0x2, 0x16,0x56,0x9c,0x80,0x50,0xed, +0xa, 0x51,0xc2,0xe7,0x4d,0x51,0x78,0x3, 0x2, 0x16,0x43,0x7e,0x54,0x0, 0x80,0x7e, +0x90,0x1a,0x6c,0x0, 0x80,0x6, 0x1b,0x90,0x68,0x14,0x2f,0x11,0xbf,0x10,0x40,0x4, +0x9f,0x10,0x4c,0xab,0x3, 0x30,0xe7,0xee,0xca,0xa8,0x6c,0xaa,0x80,0xe8,0xda,0x39, +0xda,0x58,0x7c,0x4a,0xbe,0x50,0x80,0x50,0xa, 0x1b,0x80,0x68,0xbc,0x2f,0x11,0x50, +0x2, 0xb, 0x70,0x2, 0x16,0x2d,0xc2,0xd5,0x7c,0xb4,0x30,0xe7,0x8, 0xb2,0xd5,0x6e, +0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7,0x12,0xb2,0xd5,0x6e,0x34,0xff,0xff, +0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, 0x24,0x80,0x2, 0x8d,0x32,0x30,0xd5, +0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d,0x51,0xad,0x3, 0x7d,0x2, 0x7d,0x21, +0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22,0x7d,0x2, 0xad,0x31,0xad,0x10,0x2d, +0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78,0xb, 0x4d,0x22,0x78,0x27,0x8d,0x31, +0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32,0x6d,0x22,0x2f,0x11,0x2d,0x44,0x50, +0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10,0xb, 0x90,0x14,0x78,0xed,0x7f,0x1, +0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13,0x8d,0x24,0x7d,0x2, 0x2f,0x0, 0x40, +0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14,0x14,0x78,0xf1,0x7d,0x23,0x7d,0x31, +0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0,0x30,0xe7,0x8, 0xb2,0xd5,0x9f,0x22, +0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13,0xb2,0xd5,0x9f,0x22,0x9f,0x21,0x7f, +0x12,0x12,0x17,0x34,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x80,0x3, 0x12,0x17,0x34,0x30, +0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1a,0x1e, +0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20,0xb, 0x35,0xb, 0x15,0x1b,0x54,0x78, +0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40,0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1e, +0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19,0x0, 0x68,0x12,0xb, 0x1c,0xb, 0x14, +0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x22,0x0, +0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, +0x11,0x12,0x13,0x14,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x4, 0x5, 0x6, 0x7, 0x8, +0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x0, +0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15, +0x16,0x0, 0x1, 0x2, 0x3, 0x4, 0x1c,0x1d,0x1e,0x1f,0x20,0x0, 0x1, 0x2, 0x3, 0xe, +0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x3, 0x4, 0x5, 0x6, 0x7, 0x8, +0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, +0x19,0x1a,0x1b,0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x1c,0x1d,0x1e,0x1f,0x20,0x21, +0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1c,0x1d,0x1e,0x1f,0x20, +0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, +0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x0, 0x1, +0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11, +0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21, +0x22,0x0, 0x1, 0x1, 0x1, 0x10,0x1c,0x2, 0x10,0x1c,0x0, 0x1, 0x1, 0x4, 0xf, 0x1c, +0x0, 0x1, 0x1, 0x6, 0x1b,0xf, 0x7, 0xe, 0x1c,0x8, 0x23,0x15,0x0, 0x1, 0x1, 0xa, +0x10,0x19,0xb, 0x14,0x1c,0xc, 0xf, 0x18,0x0, 0x1, 0x1, 0xe, 0x23,0x15,0xf, 0xd, +0x19,0x0, 0x1, 0x1, 0x11,0xd, 0x14,0x12,0x10,0x19,0x13,0x1c,0x10,0x14,0x1a,0x10, +0x15,0x10,0x19,0x16,0x23,0x1c,0x72,0x23,0x15,0x73,0x23,0x1c,0x74,0x23,0x1c,0x75, +0xe, 0x1c,0x75,0x84,0x1, 0x7e,0x44,0x3f,0xff,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78, +0xf9,0x7e,0xf8,0x3c,0x98,0x75,0xc, 0x0, 0x75,0xd, 0x0, 0x75,0xe, 0x2, 0x75,0xf, +0x0, 0xc2,0x8, 0xc2,0x9, 0xc2,0xe, 0x75,0x1b,0x0, 0x75,0x1c,0x0, 0xc2,0xf, 0xc2, +0x10,0xc2,0x12,0x75,0x1d,0x0, 0x75,0x1e,0x0, 0xc2,0x14,0xc2,0x15,0x75,0x1f,0x0, +0xc2,0x16,0x75,0x68,0x0, 0xc2,0x17,0xc2,0x18,0xc2,0xa, 0x75,0x69,0x64,0xc2,0x19, +0xc2,0x1a,0x75,0x6a,0x0, 0xd2,0x5, 0xd2,0x6, 0xd2,0x7, 0xd2,0x1b,0xc2,0xc, 0xd2, +0xd, 0x7e,0x4, 0x0, 0xff,0x7e,0x14,0x1a,0x72,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a, +0x69,0x20,0x0, 0x2, 0xb, 0xe, 0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0, +0xb, 0x24,0xb, 0xc, 0x1b,0x44,0x78,0xf2,0x80,0xdf,0x2, 0x2f,0xba,0x0, 0x0, 0x0, +0x47,0x0, 0xcb,0x1, 0x0, 0x0, 0x10,0xfd,0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, +0x9e,0x19,0x0, 0x21,0x45,0x0, 0xe, 0x1, 0xf, 0x2, 0x10,0x3, 0x11,0x4, 0x12,0x5, +0x13,0x6, 0x14,0x7, 0x15,0x8, 0x16,0x9, 0x17,0xa, 0x18,0xb, 0x19,0xc, 0x1a,0xd, +0x1b,0xdf,0x22,0xc3,0x21,0xa9,0x20,0x94,0x1f,0x81,0x1e,0x70,0x1d,0x62,0x1c,0x55, +0x1b,0x4a,0x1a,0x41,0x19,0x38,0x18,0x31,0x17,0x2b,0x16,0x25,0x15,0x21,0x14,0x1c, +0x13,0x19,0x12,0x16,0x11,0x13,0x10,0x11,0xf, 0x10,0xe, 0xca,0xf8,0x7f,0x20,0x80, +0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, 0x34,0xb, 0x54,0x69,0xff,0xff,0xfc,0x7d, +0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d,0xff,0x78,0xe6,0x7f,0x10,0xda,0xf8,0x22, +0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44,0x7a,0xb, 0xb0,0xb, 0x14,0x4d,0x44,0x78, +0xf5,0x22,0x3c,0x1, 0x32,0x1, 0x1e,0x2, 0xf6,0x4, 0xe7,0x5, 0xce,0x6, 0xc2,0x7, +0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff,0x1, 0x2, 0x0, 0x1, 0xff,0x2, 0x0, 0x1, +0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, 0x48,0x3, 0x7d,0x32,0x22,0x6d,0x33,0x9d, +0x32,0x22,0x0, 0x4, 0x37,0xf2,0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3, 0xff,0x1, 0x0, +0x1, 0x24,0xca,0x1, 0x0, 0x1, 0x3b,0x49,0x0, 0x0, 0x2, 0x3b,0x9b,0x0, 0x0, 0x0, +0x2, 0x3b,0x9d,0x0, 0x0, 0x0, 0x1, 0x3b,0x9f,0x0, 0x0, 0x1, 0x3a,0x7d,0xff,0x0, +0x1, 0x3c,0x29,0x0, 0x0, 0x1, 0x3c,0x2a,0x0, 0x0, 0x1, 0x33,0xfe,0x0, 0x0, 0x2, +0x32,0xc1,0x0, 0x0, 0x0, 0x1, 0x32,0xf0,0x0, 0x0, 0x1, 0x33,0xcd,0x0, 0x0, 0x1, +0x33,0xce,0x0, 0x0, 0x1, 0x33,0xcf,0x0, 0x0, 0x1, 0x38,0xfa,0x0, 0x0, 0x3c,0x39, +0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x39, +0x7f,0xff,0x0, 0x2, 0x39,0x80,0x0, 0x0, 0x0, 0x1, 0x39,0xfb,0x1, 0x0, 0x2, 0x39, +0xfe,0x0, 0x0, 0x0, 0x1, 0x34,0x88,0x0, 0x0, 0x1, 0x34,0x89,0x0, 0x0, 0x1, 0x34, +0x8a,0x0, 0x0, 0x1, 0x3a,0x2, 0x1, 0x0, 0x1, 0x3a,0x7c,0x0, 0x0, 0x1, 0x33,0xff, +0x0, 0x0, 0x6, 0x33,0xf8,0x30,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x3c,0x90,0x0, +0x0, 0x1, 0x3c,0x91,0x0, 0x0, 0x1, 0x3c,0x92,0x0, 0x0, 0x1, 0x3c,0x93,0x0, 0x0, +0x1, 0x3c,0x94,0x0, 0x0, 0x1, 0x0, 0x6b,0x0, 0x0, 0x1, 0x2, 0xdc,0x0, 0x0, 0x1, +0x2, 0xdf,0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x4, 0x3a,0xee,0x0, 0x0, 0x0, +0x0, 0x0, 0x1, 0x3c,0x8a,0x0, 0x0, 0x1, 0x3c,0x8b,0x0, 0x0, 0x2, 0x3c,0x8c,0x0, +0x0, 0x0, 0x1, 0x3c,0x8e,0x64,0x0, 0x1, 0x3c,0x8f,0x0, 0x0, 0x1, 0x34,0x4f,0x0, +0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, 0x1, 0x3, 0xf2,0x0, 0x0, +0x2, 0x2a,0x97,0x2a,0x9d,0x0, 0x1, 0x2e,0x5d,0x2, 0x0, 0x1, 0x2e,0x86,0x0, 0x0, +0x4, 0x3c,0x82,0x0, 0x0, 0x50,0x0, 0x0, 0x4, 0x3c,0x86,0x0, 0x0, 0x64,0x0, 0x0, +0x4, 0x3c,0x53,0x0, 0x0, 0x6c,0x0, 0x0, 0x4, 0x3c,0x57,0x0, 0x0, 0x68,0xc0,0x0, +0x4, 0x3c,0x5b,0x0, 0x0, 0x68,0x0, 0x0, 0x4, 0x3c,0x6c,0x0, 0x0, 0x40,0x0, 0x0, +0x4, 0x3c,0x95,0x0, 0x0, 0x60,0x0, 0x0, 0x0, 0x4, 0xe2,0x0, 0xc, 0x3, 0x52,0x3, +0xe8,0x0, 0xc, 0x2, 0x94,0x3, 0x6b,0x0, 0xc, 0x1, 0xf4,0x2, 0x71,0x0, 0xa, 0x1, +0x77,0x1, 0x77,0x0, 0x8, 0x0, 0xdc,0x0, 0xb4,0x0, 0x6, 0x0, 0x4b,0x0, 0x64,0x0, +0x6, 0x0, 0x0, 0x0, 0xe, 0x1c,0x23,0x3, 0xe8,0x0, 0x78,0x2, 0x58,0x0, 0x50,0x0, +0x0, 0x0, 0x1e,0x12,0x2d,0x65,0x12,0x1c,0xb3,0x12,0x1c,0x7e,0x12,0x1d,0x58,0x2, +0x1c,0x42,0x12,0x1c,0x53,0x7e,0xb3,0x29,0xfc,0x12,0x57,0xfb,0x74,0x1, 0x7a,0xb3, +0x3a,0x6, 0x22,0x12,0xb2,0xe6,0x74,0x1, 0x7a,0xb3,0x3a,0x2, 0x22,0x12,0x1c,0xea, +0x12,0x51,0x54,0x12,0x58,0xda,0x12,0x2d,0x65,0x12,0x1c,0xea,0x12,0x1c,0xb3,0x12, +0xd0,0x4, 0x12,0x1c,0x7e,0x12,0x1d,0x58,0x12,0x1d,0x88,0x2, 0x1c,0x42,0x12,0x59, +0x23,0x12,0x1c,0xd0,0x2, 0x1c,0x87,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0x2, 0x1c,0x90, +0x7d,0x43,0x7e,0xa3,0x34,0x38,0xbe,0xa0,0x5, 0x50,0x16,0x7e,0x70,0x4, 0xac,0x7a, +0x59,0x43,0x34,0x3b,0x59,0x23,0x34,0x3d,0x7c,0xba,0x4, 0x7a,0xb3,0x34,0x38,0xc3, +0x22,0xd3,0x22,0x12,0x64,0x46,0x12,0x6b,0x45,0x2, 0x1c,0xbc,0x30,0x12,0x10,0x12, +0x6b,0x7f,0x50,0x3, 0x12,0x55,0xb7,0x12,0x6a,0xc1,0x12,0x87,0xa, 0xc2,0x12,0x22, +0x6d,0x33,0x7e,0x24,0x6, 0x48,0x12,0x1c,0x90,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x6, +0xa8,0x2, 0x1c,0x90,0x74,0x1, 0x7a,0xb3,0x3b,0x4e,0x7e,0x34,0xd, 0xac,0x6d,0x22, +0x7a,0x27,0x3c,0x70,0x7a,0x37,0x3c,0x72,0x22,0xca,0xf8,0x7e,0xf3,0x3b,0x4e,0xbe, +0xf0,0x5, 0x78,0xb, 0x74,0x1, 0x7a,0xb3,0x3b,0x4e,0x12,0x0, 0x9, 0x80,0x40,0xbe, +0xf0,0x4, 0x78,0xd, 0x12,0x1c,0xe4,0xe4,0x7a,0xb3,0x29,0xef,0x12,0x64,0x46,0x80, +0x2e,0xbe,0xf0,0x6, 0x78,0x13,0x12,0x1c,0xe4,0x12,0x33,0xea,0xe4,0x7a,0xb3,0x2a, +0xb, 0x12,0x6b,0x45,0x12,0xd0,0xef,0x80,0x16,0xbe,0xf0,0x7, 0x78,0x17,0x12,0x1c, +0xe4,0x12,0x67,0xe1,0x50,0xfb,0x12,0x6b,0x6b,0x12,0x1c,0xbc,0x12,0x1d,0x58,0x74, +0x2, 0x7a,0xb3,0x3b,0x4e,0xda,0xf8,0x22,0xe4,0x7a,0xb3,0x34,0x3a,0x7a,0xb3,0x34, +0x39,0x12,0x37,0x61,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x34, +0x3a,0x22,0x12,0xd0,0x4, 0x12,0x9e,0xea,0x7a,0x37,0x3c,0x8c,0x12,0x1c,0xea,0x12, +0x1c,0xb3,0x12,0x1d,0x58,0x2, 0x1d,0x88,0x74,0xc, 0x7a,0xb3,0x32,0x3d,0xe4,0x7a, +0xb3,0x32,0x98,0x7e,0x8, 0x32,0x99,0x74,0xc, 0x12,0x1e,0xb0,0x7e,0x8, 0x32,0xa3, +0x12,0xd0,0x96,0x7e,0x8, 0x32,0xc3,0x12,0x1e,0xb0,0x6d,0x33,0x7a,0x37,0x32,0xda, +0x22,0xca,0x3b,0x12,0x67,0xe1,0x50,0xfb,0x7e,0xf3,0x29,0xfc,0x7c,0xbf,0x12,0xc6, +0x6e,0x12,0xc6,0x85,0x7e,0xb3,0x2a,0xc, 0xf5,0x28,0x7e,0xc3,0x2a,0xd, 0x7e,0xb3, +0x3a,0xa5,0xb4,0x1, 0xf, 0x12,0x55,0x7d,0x7e,0xb3,0x15,0xa1,0x70,0x6, 0x12,0x1d, +0x58,0xc3,0xc1,0xad,0x12,0x1e,0xb7,0x3e,0x34,0xca,0x39,0x7e,0x18,0x6, 0x48,0x7e, +0x8, 0x4, 0x60,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x1e,0xb7,0x3e,0x34,0xca,0x39,0x7e, +0x18,0x6, 0xa8,0x7e,0x8, 0x4, 0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0xb3,0x3a,0xa5, +0xb4,0x3, 0x7, 0x12,0xad,0xfa,0x7a,0x37,0x3b,0x91,0x74,0x1, 0x7a,0xb3,0x15,0xa0, +0x12,0x1c,0xb3,0x12,0xad,0xeb,0x12,0x54,0x92,0xe4,0x12,0x13,0xde,0x12,0x1d,0x58, +0x7e,0x8, 0x4, 0x60,0x7a,0xd, 0x29,0x7e,0x18,0x5, 0xe0,0x7e,0xb3,0x2a,0x5f,0x12, +0x67,0x1a,0x7e,0x8, 0x4, 0x0, 0x7a,0xd, 0x29,0x7e,0x18,0x5, 0x80,0x7e,0xb3,0x24, +0xc4,0x12,0x67,0x1a,0x7e,0xd3,0x2a,0xc, 0x7e,0xe3,0x2a,0xd, 0xe5,0x28,0x7a,0xb3, +0x2a,0xc, 0x7a,0xc3,0x2a,0xd, 0x7e,0x34,0x7, 0x1a,0x7e,0x4, 0xc, 0xd8,0x7d,0x20, +0x7d,0x10,0x12,0x69,0x9c,0x7a,0xd3,0x2a,0xc, 0x7a,0xe3,0x2a,0xd, 0x7c,0xbf,0x12, +0x86,0x88,0x12,0xad,0x99,0x7e,0xb3,0x3c,0x8f,0x4, 0x7a,0xb3,0x3c,0x8f,0x7e,0x73, +0x3c,0x8f,0xbe,0x70,0xfa,0x28,0x6, 0x74,0x64,0x7a,0xb3,0x3c,0x8f,0x7e,0xb3,0x15, +0xa0,0x60,0x9, 0x7e,0xb3,0x15,0xa1,0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22, +0x7e,0x34,0x0, 0xa, 0x2, 0x1a,0x30,0x7e,0x73,0x29,0x61,0xa, 0x27,0x7e,0x73,0x29, +0x60,0xa, 0x37,0x2d,0x32,0x22,0x12,0x32,0xed,0x7e,0xb3,0x3a,0xa5,0xb4,0x3, 0x66, +0x12,0xc9,0xf4,0x12,0x57,0xe7,0x12,0x2e,0x53,0x7e,0xb3,0x3b,0x4a,0x30,0xe7,0xe9, +0x12,0x1d,0xb1,0x12,0x1e,0xb7,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, +0x4, 0xc0,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x1e,0xb7,0x3e,0x34,0xca,0x39,0x7e,0x18, +0x4, 0x60,0x7e,0x8, 0x5, 0x20,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0xb3,0x2a,0xa, 0xb4, +0x1, 0x12,0x12,0x5e,0xbd,0x12,0x85,0x66,0x12,0x6b,0xcc,0x12,0x92,0xa7,0x12,0x1f, +0x47,0x12,0x3f,0xa1,0x12,0x33,0x1f,0x12,0x32,0xa6,0x7e,0xb3,0x3b,0x4a,0x54,0x7f, +0x7a,0xb3,0x3b,0x4a,0x80,0x93,0x12,0x67,0xec,0x2, 0x1f,0x3c,0x7e,0xb3,0x3a,0xec, +0x70,0x4, 0xe4,0x12,0x4c,0xc, 0x22,0x12,0x8e,0x36,0x12,0x27,0xa0,0x12,0x21,0x57, +0x12,0x4f,0x48,0x12,0x27,0xa0,0x12,0x4d,0x8c,0x12,0x27,0xa0,0x12,0x88,0x5d,0x12, +0x27,0xa0,0x12,0x8a,0xf, 0x12,0x93,0xe6,0x12,0xa1,0xc2,0x12,0xa1,0x2d,0x12,0x27, +0xa0,0x12,0x8f,0x5f,0x12,0x27,0xa0,0x2, 0x1f,0x7a,0xca,0x3b,0x75,0x24,0x0, 0x6c, +0xcc,0x6c,0xdd,0x7e,0xc4,0x0, 0x3c,0xca,0xc9,0x7e,0x18,0x39,0x43,0x7e,0x8, 0x39, +0x7, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0xf3,0x27,0x58,0xa, 0xcf,0x3e,0xc4,0xca,0xc9, +0x7e,0x18,0x25,0xce,0x7e,0x8, 0x1e,0x44,0x12,0x1a,0xb, 0x1b,0xfd,0x6c,0x88,0x6c, +0xee,0x2, 0x20,0x4f,0x7e,0xc4,0x3, 0xff,0x7e,0xc0,0xff,0x6c,0x99,0x80,0x4c,0x74, +0x2, 0xac,0xb9,0x9, 0xb5,0x1e,0x44,0xbe,0xb0,0xff,0x68,0x3d,0x7c,0xb9,0x12,0x80, +0xf8,0x60,0x36,0x74,0x2, 0xac,0xb9,0x9, 0x75,0x1e,0x45,0xa, 0x27,0x74,0x2, 0xac, +0xbe,0x9, 0x75,0x39,0x44,0x12,0xc4,0x67,0x7d,0x13,0x74,0x2, 0xac,0xb9,0x9, 0x75, +0x1e,0x44,0xa, 0x27,0x74,0x2, 0xac,0xbe,0x9, 0x75,0x39,0x43,0x12,0xc4,0x67,0x2d, +0x13,0xbd,0xc1,0x28,0x4, 0x7d,0xc1,0x7c,0xc9,0xb, 0x90,0xbc,0xf9,0x38,0xb0,0xbe, +0xc0,0xff,0x68,0x39,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x1e,0x44,0x9, 0x73,0x1e, +0x45,0x12,0x21,0x50,0xbe,0x37,0x29,0x47,0x48,0x23,0x7e,0x70,0x2, 0xac,0x7c,0x9, +0x53,0x1e,0x44,0x74,0x2, 0xac,0xbd,0x19,0x55,0x1e,0x80,0x9, 0x53,0x1e,0x45,0x19, +0x55,0x1e,0x81,0x74,0xff,0x19,0xb3,0x1e,0x44,0xb, 0x80,0xb, 0xd0,0xb, 0xe0,0x7e, +0x73,0x38,0xf9,0xbc,0x7e,0x28,0x3, 0x2, 0x1f,0xb4,0x7c,0xe8,0x80,0x6d,0x6d,0xdd, +0x7e,0x80,0xff,0x6c,0x99,0x80,0x3c,0x7c,0xb9,0x12,0x80,0xf8,0x60,0x33,0x12,0x27, +0xf4,0xbe,0xb0,0xff,0x68,0x2b,0x9, 0x73,0x1e,0x45,0x12,0x27,0x49,0x7f,0x71,0xb, +0x7a,0x50,0xbe,0x54,0x0, 0x0, 0x58,0x5, 0x6d,0x55,0x1b,0x7a,0x50,0xb, 0x7a,0xc0, +0xbd,0xcd,0x8, 0xd, 0x12,0x27,0xf4,0xf5,0x24,0x9, 0xc3,0x1e,0x45,0x7d,0xdc,0x7c, +0x89,0xb, 0x90,0xbc,0xf9,0x38,0xc0,0xbe,0x80,0xff,0x68,0x1d,0x7e,0x71,0x24,0x74, +0x2, 0xac,0xbd,0x19,0x75,0x1e,0x80,0x19,0xc5,0x1e,0x81,0x7e,0xa0,0xff,0x7e,0x70, +0x2, 0xac,0x78,0x19,0xa3,0x1e,0x44,0xb, 0xd0,0xb, 0xe0,0xbe,0xe0,0xa, 0x40,0x8e, +0x90,0x60,0x9a,0xe4,0x93,0x7c,0xab,0x74,0x2, 0xa4,0xca,0x59,0x7e,0x18,0x1e,0x80, +0x7e,0x8, 0x1e,0x44,0x12,0x1a,0xb, 0x1b,0xfd,0x7c,0xfd,0x7e,0x8, 0x39,0x43,0x7e, +0x34,0x0, 0x14,0x74,0xff,0x12,0x1a,0x30,0xbe,0xf0,0x0, 0x28,0x35,0xa, 0x3f,0x3e, +0x34,0xca,0x39,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0x25,0xce,0x12,0x1a,0xb, 0x1b,0xfd, +0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0x39,0x43,0x12,0x1a, +0xb, 0x1b,0xfd,0x6c,0xee,0x80,0x7, 0x7c,0xbe,0x12,0x27,0x6d,0xb, 0xe0,0xbc,0xfe, +0x38,0xf5,0x7a,0xf3,0x38,0xf9,0x7a,0xf3,0x27,0x58,0x7e,0x73,0x27,0x58,0xbe,0x70, +0xa, 0x28,0x6, 0x74,0xa, 0x7a,0xb3,0x27,0x58,0xda,0x3b,0x22,0x7c,0xb9,0x7c,0x78, +0x12,0x27,0x49,0xb, 0x1a,0x30,0x22,0xca,0x79,0x75,0x25,0x0, 0x7e,0xb3,0x27,0x58, +0x70,0x7, 0xe4,0x7a,0xb3,0x38,0xfa,0x41,0x65,0x75,0x24,0xff,0x7e,0xe0,0xff,0x6c, +0xff,0x6c,0x88,0x6c,0x99,0x80,0x39,0x6c,0xaa,0x80,0x2b,0x7c,0xb9,0x7c,0x7a,0x12, +0x21,0x50,0xbe,0x34,0x0, 0xc8,0x8, 0x1c,0x5, 0x25,0xbc,0x9e,0x50,0x2, 0x7c,0xe9, +0xbe,0xa1,0x24,0x50,0x3, 0x7a,0xa1,0x24,0xbc,0x98,0x28,0x2, 0x7c,0x89,0xbc,0xaf, +0x28,0x2, 0x7c,0xfa,0xb, 0xa0,0x7e,0xb3,0x29,0x5d,0xbc,0xba,0x38,0xcd,0xb, 0x90, +0x7e,0xb3,0x29,0x5c,0xbc,0xb9,0x38,0xbf,0xa, 0x2e,0xa, 0x38,0x9d,0x32,0x7c,0x67, +0xe5,0x24,0xa, 0x2b,0xa, 0x5f,0x9d,0x52,0x7c,0x7b,0x7e,0x27,0x27,0x5e,0xbe,0x24, +0x2, 0xbc,0x58,0x6c,0xbe,0x24,0x1, 0x2c,0x8, 0x66,0xbe,0x60,0x6, 0x40,0x61,0xbe, +0x60,0x7, 0x38,0x5c,0xbe,0x70,0x6, 0x40,0x57,0xbe,0x70,0x7, 0x38,0x52,0x7c,0xbe, +0x12,0x24,0x1d,0x58,0x4b,0x7c,0xb8,0x12,0x24,0x1d,0x58,0x44,0x7c,0xbe,0x7c,0x7f, +0x12,0x24,0x20,0x58,0x3b,0x7c,0xb8,0x7c,0x7f,0x12,0x24,0x20,0x58,0x32,0xa, 0x28, +0xa, 0x3e,0x2d,0x32,0x7e,0x14,0x0, 0x2, 0x7d,0x21,0x12,0x16,0xe6,0x7c,0xb7,0xca, +0xb8,0xa, 0x2f,0xe5,0x24,0xa, 0x3b,0x2d,0x32,0x7d,0x21,0x12,0x16,0xe6,0xda,0xb8, +0x12,0x24,0x20,0x58,0xb, 0xe5,0x25,0xbe,0xb0,0xe, 0x40,0x4, 0x74,0x64,0x80,0xa, +0x7e,0xb3,0x38,0xfa,0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x38,0xfa,0x7e,0xb3, +0x38,0xfa,0x60,0x11,0x6c,0x99,0x80,0x5, 0x12,0x27,0x66,0xb, 0x90,0x7e,0x73,0x27, +0x58,0xbc,0x79,0x38,0xf3,0xda,0x79,0x22,0xca,0x79,0x7c,0xa6,0x7c,0x67,0x7c,0x7b, +0x7e,0xe0,0xff,0x75,0x3f,0xff,0xc2,0x0, 0xc2,0x1, 0xc2,0x2, 0xc2,0x3, 0xc2,0x4, +0x7e,0xe4,0x1, 0x2c,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x6, 0x12,0xc8,0x8, 0xc3,0x81, +0x1a,0xbe,0xa0,0x0, 0x40,0x5, 0xbe,0xa0,0xa, 0x28,0x3, 0xc3,0x81,0x1a,0x7e,0x30, +0x3, 0x7e,0x50,0x5, 0xac,0x5a,0x19,0x32,0x32,0xe, 0x7d,0xfe,0x12,0xc8,0x4c,0x28, +0x4, 0x19,0xb2,0x32,0xe, 0x12,0xc8,0x54,0x7a,0x71,0x39,0x7c,0xf6,0xc2,0x2, 0xc2, +0x3, 0x7c,0x87,0x85,0x39,0x3a,0x80,0xa, 0x12,0x27,0x2a,0xbd,0x3f,0x8, 0x8, 0x7a, +0x81,0x3a,0x12,0x27,0xe2,0x58,0xf1,0x7e,0x81,0x39,0x85,0x39,0x3b,0x80,0xa, 0x12, +0x27,0x2a,0xbd,0x3f,0x8, 0x8, 0x7a,0x81,0x3b,0x12,0xcf,0xda,0x48,0xf1,0x75,0x3e, +0x0, 0x7e,0x73,0x29,0x5c,0x7c,0xb7,0x14,0xbe,0xb1,0x3b,0x78,0xc, 0xd2,0x3, 0xa, +0xe7,0x1b,0xe4,0x7d,0x3e,0x7c,0xe7,0x80,0x8, 0xe5,0x3a,0x70,0x4, 0xd2,0x2, 0x6c, +0xee,0x7c,0x9f,0x7a,0xf1,0x3c,0x20,0x3, 0xf, 0x30,0x2, 0x37,0x80,0xa, 0x7c,0xbe, +0x12,0x27,0x3, 0x8, 0x8, 0x7a,0x91,0x3c,0x12,0x27,0xeb,0x58,0xf1,0x7c,0x9f,0x7a, +0xf1,0x3d,0x80,0xa, 0x7c,0xbe,0x12,0x27,0x3, 0x8, 0x8, 0x7a,0x91,0x3d,0x12,0xcf, +0xea,0x48,0xf1,0xe5,0x3c,0xa, 0x3b,0xe5,0x3d,0xa, 0xeb,0x9d,0xe3,0x7d,0x3e,0x7c, +0xb7,0xf5,0x3e,0xc2,0x0, 0xc2,0x1, 0x7c,0x9f,0x7a,0xf1,0x3c,0x80,0x8, 0x12,0x27, +0x1, 0x8, 0x8, 0x7a,0x91,0x3c,0x12,0x27,0xeb,0x58,0xf3,0x7c,0x9f,0x7a,0xf1,0x3d, +0x80,0x8, 0x12,0x27,0x1, 0x8, 0x8, 0x7a,0x91,0x3d,0x12,0xcf,0xea,0x48,0xf3,0x75, +0x40,0x0, 0xe5,0x3c,0x70,0x6, 0xd2,0x0, 0xf5,0x3f,0x80,0x18,0x7e,0x73,0x29,0x5d, +0x7c,0xb7,0x14,0xbe,0xb1,0x3d,0x78,0xc, 0xd2,0x1, 0xa, 0xe7,0x1b,0xe4,0x7d,0x3e, +0x7c,0xb7,0xf5,0x3f,0x7e,0x81,0x39,0x85,0x39,0x3a,0x20,0x0, 0xd, 0x30,0x1, 0x32, +0x80,0x8, 0x12,0x27,0x3a,0x8, 0x8, 0x7a,0x81,0x3a,0x12,0x27,0xe2,0x58,0xf3,0x7e, +0x81,0x39,0x85,0x39,0x3b,0x80,0x8, 0x12,0x27,0x3a,0x8, 0x8, 0x7a,0x81,0x3b,0x12, +0xcf,0xda,0x48,0xf3,0xe5,0x3a,0xa, 0x2b,0xe5,0x3b,0xa, 0x3b,0x9d,0x32,0x7c,0xb7, +0xf5,0x40,0x7e,0x70,0x5, 0xac,0x7a,0x9, 0xb3,0x32,0xe, 0xbe,0xb1,0x3e,0x40,0x19, +0xbe,0xb1,0x40,0x50,0x2, 0x80,0x12,0x9, 0xb3,0x32,0xd, 0x60,0x16,0x20,0x3, 0x9, +0x20,0x2, 0x6, 0x20,0x0, 0x3, 0x30,0x1, 0xa, 0x74,0x1, 0x19,0xb3,0x32,0xd, 0xd2, +0x4, 0x80,0x5, 0xe4,0x19,0xb3,0x32,0xd, 0xa2,0x4, 0xda,0x79,0x22,0x7e,0x71,0x24, +0x12,0x21,0x50,0xbe,0x34,0x0, 0x0, 0x22,0xca,0x3b,0x6d,0xee,0x7e,0xc3,0x29,0x5b, +0x7e,0xd3,0x29,0x5a,0x7e,0xb3,0x3a,0xce,0xb4,0x1, 0x3, 0xe4,0xa1,0x51,0x7e,0xb3, +0x27,0x58,0x70,0x2, 0x81,0xc5,0x7e,0xb3,0x28,0xf5,0x60,0x2, 0x80,0x77,0x7e,0xa3, +0x25,0xce,0x7e,0x73,0x25,0xcf,0x7a,0x71,0x24,0x6c,0xee,0x6d,0xff,0x6c,0xff,0xa, +0x47,0x80,0x1c,0x12,0x27,0x1e,0x8, 0x1d,0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c, +0xba,0x14,0x12,0x27,0xe, 0x12,0x27,0x31,0x58,0x3, 0x12,0x27,0xb, 0x1b,0x44,0xbe, +0x44,0x0, 0x0, 0x58,0xde,0xe5,0x24,0xa, 0x4b,0x80,0x1a,0x12,0x27,0x1e,0x8, 0x21, +0xb, 0xe0,0xbe,0xa0,0x0, 0x28,0x6, 0x7c,0xba,0x14,0x12,0x27,0xe, 0x12,0x27,0x31, +0x58,0x3, 0x12,0x27,0xb, 0x7d,0x24,0xb, 0x24,0x7d,0x42,0xa, 0x3c,0xbd,0x23,0x48, +0xda,0xbe,0xe0,0x2, 0x50,0x2, 0x80,0xd, 0xa, 0x2f,0x7d,0x3f,0x12,0x16,0xe6,0xbe, +0x34,0x0, 0x3c,0x8, 0x7, 0xe4,0x7a,0xb3,0x33,0xce,0xa1,0x51,0x6d,0xdd,0xbe,0xa0, +0x0, 0x28,0x8, 0x7c,0xba,0x14,0x12,0x27,0x18,0x2d,0xd3,0xa, 0x3d,0x1b,0x34,0xa, +0xca,0xbd,0xc3,0x58,0x8, 0x7c,0xba,0x4, 0x12,0x27,0x18,0x2d,0xd3,0x7e,0x70,0x8, +0x80,0x25,0x7e,0x50,0x2, 0xac,0x57,0x7d,0xc2,0x2e,0xc4,0x1a,0x42,0x7d,0x1c,0x12, +0xd0,0xb0,0x1a,0xcb,0xbd,0xcd,0x8, 0xf, 0x7d,0xc2,0x2e,0xc4,0x1a,0x43,0x7d,0x2c, +0x12,0x28,0x2, 0x1a,0xcb,0x2d,0xec,0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xd3,0x7c, +0xba,0x12,0x27,0x18,0x12,0x1a,0x62,0xbe,0x34,0x7, 0xd0,0x8, 0x4, 0x2e,0xe4,0x0, +0x28,0xbe,0xe4,0x0, 0xfa,0x28,0x4, 0x7e,0xe4,0x0, 0xfa,0x7e,0xb3,0x33,0xce,0xa, +0x3b,0xbd,0x3e,0x50,0x8, 0x7d,0x3e,0x7c,0xb7,0x7a,0xb3,0x33,0xce,0x7e,0xb3,0x33, +0xce,0xda,0x3b,0x22,0x7c,0xbd,0x7c,0x7e,0x7f,0x4, 0xca,0x3b,0x7f,0x70,0x7c,0xe7, +0x7c,0xdb,0x7e,0xc0,0x4, 0x7e,0xb3,0x29,0x5a,0xf5,0x27,0x7e,0xb3,0x29,0x5b,0xf5, +0x26,0x7e,0xd4,0x0, 0x78,0x6c,0xff,0x12,0x27,0x45,0x7f,0x1, 0x7e,0xc7,0x27,0x5e, +0xbe,0xc4,0x5, 0xdc,0x8, 0x6, 0x2e,0xd4,0x0, 0xc8,0x80,0x22,0xbe,0xc4,0x4, 0xb0, +0x8, 0x6, 0x2e,0xd4,0x0, 0x96,0x80,0x16,0xbe,0xc4,0x3, 0x84,0x8, 0x6, 0x2e,0xd4, +0x0, 0x64,0x80,0xa, 0xbe,0xc4,0x2, 0x58,0x8, 0x4, 0x2e,0xd4,0x0, 0x32,0xe5,0x27, +0x12,0xcf,0xc0,0x58,0xf, 0xe5,0x26,0x12,0xd0,0xd4,0x58,0x8, 0x4c,0xee,0x68,0x4, +0x4c,0xdd,0x78,0x3, 0x4e,0xf0,0x10,0xb, 0xa, 0x20,0xbd,0x2d,0x8, 0x8, 0xbe,0xc4, +0x3, 0x20,0x8, 0x2, 0xc1,0xc0,0x7d,0x3d,0xe, 0x34,0xbd,0x23,0x8, 0x8, 0xbe,0xc4, +0x3, 0x20,0x58,0x2, 0xc1,0xc0,0x6c,0xaa,0x7c,0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80, +0x0, 0x48,0x11,0x7e,0xb3,0x29,0x5a,0xbc,0xb8,0x8, 0x9, 0x12,0x26,0xf7,0x58,0x14, +0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0x1b,0x80,0x1a,0x2c,0x1a,0x3d,0x9d,0x32,0x1a,0xc8, +0xbd,0xc3,0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x1, 0xc1,0xc0,0x6c,0xaa,0x7c, +0x8d,0x80,0x1c,0x7c,0x9e,0xbe,0x80,0x0, 0x48,0x11,0x7e,0xb3,0x29,0x5a,0xbc,0xb8, +0x8, 0x9, 0x12,0x26,0xf7,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x80,0x1a, +0x2c,0x1a,0x3d,0x2d,0x32,0x1a,0xc8,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x5, 0x4e, +0xf0,0x2, 0x80,0x6c,0x6c,0xaa,0x7c,0x9e,0x80,0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48, +0x11,0x7e,0xb3,0x29,0x5b,0xbc,0xb9,0x8, 0x9, 0x12,0x26,0xf7,0x58,0x14,0xb, 0xa0, +0x80,0x2, 0xb, 0xa0,0x1b,0x90,0x1a,0x2c,0x1a,0x3e,0x9d,0x32,0x1a,0xc9,0xbd,0xc3, +0x18,0xd8,0xbc,0xca,0x18,0x5, 0x4e,0xf0,0x4, 0x80,0x35,0x6c,0xaa,0x7c,0x9e,0x80, +0x1c,0x7c,0x8d,0xbe,0x90,0x0, 0x48,0x11,0x7e,0xb3,0x29,0x5b,0xbc,0xb9,0x8, 0x9, +0x12,0x26,0xf7,0x58,0x14,0xb, 0xa0,0x80,0x2, 0xb, 0xa0,0xb, 0x90,0x1a,0x2c,0x1a, +0x3e,0x2d,0x32,0x1a,0xc9,0xbd,0xc3,0x48,0xd8,0xbc,0xca,0x18,0x3, 0x4e,0xf0,0x8, +0x4c,0xff,0x68,0x2e,0x7e,0x7b,0xb0,0xbc,0xbd,0x40,0x3, 0x7a,0x7b,0xd0,0x29,0xb7, +0x0, 0x2, 0xbc,0xbd,0x38,0x4, 0x39,0xd7,0x0, 0x2, 0x29,0xb7,0x0, 0x1, 0xbc,0xbe, +0x40,0x4, 0x39,0xe7,0x0, 0x1, 0x29,0xb7,0x0, 0x3, 0xbc,0xbe,0x38,0x4, 0x39,0xe7, +0x0, 0x3, 0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xb8,0x7c,0x79,0x12,0x21,0x50,0xbd,0x3d, +0x22,0xe5,0x39,0x7c,0x79,0x12,0x21,0x50,0xbd,0x3f,0x22,0x7c,0xba,0x4, 0x7c,0x79, +0x12,0x21,0x50,0x2d,0xf3,0xb, 0xf0,0x22,0x7e,0x71,0x24,0x2, 0x21,0x50,0x7c,0xba, +0x7c,0x79,0x12,0x21,0x50,0xbe,0x34,0x0, 0x64,0x22,0x7c,0xb8,0x7c,0x7f,0x2, 0x21, +0x50,0xa, 0x2d,0x1b,0x24,0xa, 0x3a,0xbd,0x32,0x22,0x7c,0xb8,0x7e,0x71,0x3f,0x12, +0x21,0x50,0xbd,0x3f,0x22,0x7c,0xbd,0x7c,0x7e,0x7e,0x13,0x29,0x5b,0xac,0x1b,0x3e, +0x4, 0x7e,0x30,0x2, 0xac,0x37,0x2d,0x10,0x7e,0x1f,0x12,0x9a,0x2d,0x31,0x22,0x7c, +0xbd,0x7c,0x7e,0x2, 0x21,0x50,0x7c,0xb9,0x6c,0x77,0x2, 0x27,0x70,0x7e,0x70,0x1, +0x12,0xd0,0x2a,0x54,0x7, 0xa, 0x2b,0x2e,0x24,0x0, 0x5e,0x12,0x28,0x2, 0x7c,0x7b, +0x4c,0x66,0x68,0x9, 0xa, 0x2a,0x2e,0x24,0x26,0x46,0x2, 0xd0,0xa7,0x12,0x86,0x72, +0x2e,0x24,0x26,0x46,0x2, 0x27,0x97,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22, +0xca,0x79,0x6c,0xff,0x6c,0xee,0x80,0x2e,0x7c,0xbe,0x12,0x80,0xf8,0x60,0x25,0x7e, +0x34,0x0, 0x2, 0xca,0x39,0xac,0x7e,0x2e,0x34,0x25,0xce,0x6d,0x22,0x7e,0x30,0x2, +0xac,0x3f,0x2e,0x14,0x25,0xce,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7c,0xbf,0x12, +0x27,0x6d,0xb, 0xf0,0xb, 0xe0,0x12,0x48,0x2f,0x38,0xcd,0x7a,0xf3,0x27,0x58,0xda, +0x79,0x22,0x7c,0xb8,0x14,0x7c,0x8b,0xbe,0xb0,0x0, 0x22,0x7c,0xb9,0x14,0x7c,0x9b, +0xbe,0xb0,0x0, 0x22,0x7e,0x70,0x2, 0xac,0x79,0x9, 0xb3,0x1e,0x44,0x22,0x2e,0x24, +0x19,0xc5,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22,0xb4,0xeb,0x5, 0xe4,0x7a, +0xb3,0x3b,0xa0,0x7e,0x73,0x3b,0xa0,0xa, 0x27,0x2e,0x24,0x0, 0x6, 0x12,0x28,0x2, +0x7c,0xab,0x7c,0xb7,0x4, 0x7a,0xb3,0x3b,0xa0,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3,0x3b, +0xa0,0x6d,0x33,0x7a,0x37,0x3b,0x9d,0x75,0x1a,0xeb,0x7c,0xba,0x22,0x70,0x5, 0x7e, +0xb3,0x3b,0x4a,0x22,0xbe,0xb0,0x3, 0x38,0x15,0x75,0x1b,0x0, 0x30,0x11,0x6, 0x7e, +0x18,0x36,0xbe,0x80,0x4, 0x7e,0x18,0x36,0xfc,0x7a,0x1d,0x14,0x80,0x8, 0xbe,0xb0, +0x5e,0x38,0x10,0x75,0x1b,0x0, 0xa, 0x1b,0x7e,0x1d,0x14,0x2d,0x31,0x1b,0x34,0x7e, +0x1b,0xb0,0x22,0xbe,0xb0,0xd3,0x68,0x3, 0xb4,0xd4,0x10,0xb4,0xd3,0x8, 0x6d,0x33, +0x7a,0x37,0x3b,0x9b,0x80,0x2, 0x15,0x1a,0x2, 0x67,0x72,0xbe,0xb0,0xeb,0x68,0x3, +0xb4,0xec,0x3, 0x2, 0x28,0xb, 0xbe,0xb0,0x80,0x40,0xc, 0xbe,0xb0,0xdf,0x38,0x7, +0xa, 0x3b,0x9, 0xb3,0x39,0xfe,0x22,0xb4,0xfc,0x5, 0x7e,0xb3,0x3a,0xa5,0x22,0xb4, +0xfd,0x1d,0x6c,0xaa,0x7e,0xb3,0x27,0x7c,0x60,0x3, 0x4e,0xa0,0x1, 0x7e,0xb3,0x3a, +0xd, 0x60,0x3, 0x4e,0xa0,0x2, 0x30,0x13,0x3, 0x4e,0xa0,0x8, 0x7c,0xba,0x22,0xb4, +0xfe,0x5, 0x7e,0xb3,0x29,0xfc,0x22,0x74,0xff,0x22,0x7c,0x7b,0x6c,0xaa,0x12,0x2b, +0xc7,0x78,0x9, 0x7c,0xb7,0x12,0x28,0x3d,0x7c,0xab,0x80,0xa, 0xb4,0x4, 0x7, 0x7c, +0xb7,0x12,0x2f,0xfc,0x7c,0xab,0x7c,0xba,0x22,0x30,0x90,0x19,0xc2,0x90,0xe5,0x18, +0x70,0x9, 0x75,0x18,0x1, 0xe5,0x91,0xf5,0x1a,0x80,0x11,0x7e,0x71,0x91,0xe5,0x1a, +0x12,0x29,0x24,0x5, 0x1a,0x30,0x91,0xb, 0xc2,0x91,0x5, 0x1a,0xe5,0x1a,0x12,0x28, +0xda,0xf5,0x91,0x22,0x7c,0x6b,0x12,0x2b,0xc7,0x78,0x5, 0x7c,0xb6,0x2, 0x68,0x50, +0xb4,0x4, 0x5, 0x7c,0xb6,0x2, 0x29,0x39,0x22,0xca,0xf8,0x7c,0x6b,0xa5,0xbe,0x0, +0x9, 0x7c,0xb7,0x12,0x68,0x25,0xd2,0x8, 0x61,0xbb,0xa5,0xbe,0x1, 0x3d,0x7a,0x73, +0x3b,0x4b,0xa5,0xbf,0xad,0x2, 0x80,0x2f,0xa5,0xbf,0xae,0x4, 0xd2,0x9, 0x61,0xbb, +0xa5,0xbf,0xaa,0x5, 0x12,0xd0,0xe6,0x80,0x1e,0xa5,0xbf,0xab,0xa, 0x7e,0x34,0x5, +0x20,0x7a,0x37,0x37,0xf0,0x80,0x10,0xa5,0xbf,0xac,0x2, 0x80,0x2, 0x61,0xbb,0x7e, +0x34,0x4, 0xc0,0x7a,0x37,0x37,0xf0,0x6d,0x33,0x41,0x37,0xbe,0x60,0x4, 0x40,0x20, +0xbe,0x60,0x8, 0x38,0x1b,0x12,0x2b,0xbe,0xa5,0xbe,0x7, 0x7, 0x6d,0x33,0x7a,0x35, +0xa, 0x61,0xbb,0xa5,0xbe,0x8, 0x2, 0x80,0x2, 0x61,0xbb,0x12,0x0, 0x66,0x61,0xbb, +0xa5,0xbe,0xa, 0x9, 0x43,0xc, 0x20,0x7a,0x73,0x3b,0x54,0x61,0xbb,0xa5,0xbe,0xb, +0x8, 0x12,0x2b,0xbe,0x12,0x0, 0x6e,0x61,0xbb,0xbe,0x60,0x1b,0x40,0x7, 0xbe,0x60, +0x1c,0x38,0x2, 0x61,0x53,0xbe,0x60,0x1e,0x40,0xd, 0xbe,0x60,0x23,0x38,0x8, 0x12, +0x2b,0xc0,0x43,0xc, 0x40,0x61,0xbb,0xbe,0x60,0x15,0x40,0x1a,0xbe,0x60,0x18,0x38, +0x15,0x12,0x2b,0xc0,0xd2,0x8, 0xa5,0xbe,0x15,0x2, 0x80,0x2, 0x61,0xbb,0x74,0x7, +0x7a,0xb3,0x3b,0x4e,0x61,0xbb,0xa5,0xbe,0x19,0x7, 0xe4,0x7a,0xb3,0x3b,0x63,0x61, +0xbb,0xbe,0x60,0x24,0x40,0x7, 0xbe,0x60,0x2c,0x38,0x2, 0x61,0x53,0xa5,0xbe,0x2d, +0x1b,0x12,0x2b,0xc0,0x20,0x9, 0x2, 0x61,0xbb,0x7e,0x63,0x3b,0x76,0x7c,0x46,0x6c, +0x55,0xa, 0x37,0x2d,0x32,0x3e,0x34,0x7a,0x35,0x8, 0x61,0xbb,0xbe,0x60,0x2f,0x40, +0xa, 0xbe,0x60,0x33,0x38,0x5, 0x43,0xc, 0x8, 0x61,0x53,0xa5,0xbe,0x34,0xf, 0x43, +0xc, 0x10,0xbe,0x70,0x64,0x38,0x2, 0x61,0x53,0x7e,0x70,0x64,0x61,0x53,0xbe,0x60, +0x38,0x68,0x4, 0xa5,0xbe,0x39,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x3b,0x6f,0x7c,0xbf, +0x4, 0x7a,0xb3,0x3b,0x6f,0xa, 0x2f,0x19,0x72,0x2a,0xe, 0xa5,0xbe,0x39,0x2, 0x80, +0x2, 0x61,0xbb,0x75,0x1a,0x38,0x61,0xbb,0xbe,0x60,0x3a,0x68,0x4, 0xa5,0xbe,0x3b, +0x21,0x43,0xc, 0x2, 0x7e,0xf3,0x3b,0x71,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x71,0xa, +0x2f,0x19,0x72,0x2a,0x31,0xa5,0xbe,0x3b,0x2, 0x80,0x2, 0x61,0xbb,0x75,0x1a,0x3a, +0x61,0xbb,0xa5,0xbe,0xfb,0x9, 0x43,0xc, 0x4, 0x7a,0x73,0x29,0xff,0x61,0xbb,0xa5, +0xbe,0x50,0x6, 0x7a,0x73,0x3b,0x9a,0x61,0xbb,0xbe,0x60,0x3c,0x68,0x4, 0xa5,0xbe, +0x3d,0x21,0x43,0xc, 0x1, 0x7e,0xf3,0x3b,0x73,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x73, +0xa, 0x2f,0x19,0x72,0x29,0x67,0xa5,0xbe,0x3d,0x2, 0x80,0x2, 0x61,0xbb,0x75,0x1a, +0x3c,0x61,0xbb,0xbe,0x60,0x3e,0x68,0x4, 0xa5,0xbe,0x3f,0x21,0x43,0xc, 0x1, 0x7e, +0xf3,0x3b,0x75,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x75,0xa, 0x2f,0x19,0x72,0x29,0x8a, +0xa5,0xbe,0x3f,0x2, 0x80,0x2, 0x61,0xbb,0x75,0x1a,0x3e,0x61,0xbb,0xbe,0x60,0x40, +0x40,0xd, 0xbe,0x60,0x42,0x38,0x8, 0x12,0x2b,0xc0,0x75,0xd, 0x1, 0x80,0xa, 0xa5, +0xbe,0x43,0xb, 0x12,0x2b,0xc0,0x75,0xd, 0x2, 0x12,0x2b,0xcf,0x80,0x7d,0xa5,0xbe, +0x44,0x8, 0x12,0x2b,0xc0,0x12,0x2d,0x9b,0x80,0x71,0xbe,0x60,0x45,0x68,0x4, 0xa5, +0xbe,0x46,0x5, 0x12,0x2b,0xc0,0x80,0x63,0xbe,0x60,0x4e,0x68,0x4, 0xa5,0xbe,0x4f, +0x20,0x43,0xd, 0x4, 0x7e,0xf3,0x3b,0x90,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x90,0xa, +0x2f,0x2e,0x27,0x37,0xee,0x7a,0x29,0x70,0xa5,0xbe,0x4f,0x3f,0x75,0x1a,0x4e,0x80, +0x3a,0xa5,0xbe,0x6d,0x5, 0x7a,0x71,0xe, 0x80,0x31,0xbe,0x60,0xf0,0x40,0x25,0xbe, +0x60,0xf3,0x38,0x20,0x7c,0x16,0x2e,0x10,0x20,0x7c,0xb7,0xa5,0xf7,0xa5,0xbe,0xf3, +0x1a,0x7e,0x15,0x12,0x7e,0x5, 0x10,0x3e,0x4, 0x7e,0x1f,0x37,0xf2,0x2d,0x30,0x1b, +0x1a,0x10,0x80,0x7, 0xa5,0xbe,0xf6,0x3, 0x7a,0x71,0xf, 0xda,0xf8,0x22,0xd2,0x8, +0xa, 0x26,0x19,0x72,0x3b,0x4a,0x22,0x7e,0xb3,0x3b,0x4a,0xc4,0x54,0x7, 0x22,0x12, +0x2f,0xe3,0xb4,0x1, 0x14,0xca,0x39,0x7e,0x18,0x3b,0x8a,0x7e,0x8, 0x24,0xc2,0x12, +0x1a,0xb, 0x1b,0xfd,0x12,0x2d,0xd5,0x80,0x12,0xca,0x39,0x7e,0x18,0x3b,0x8a,0x7e, +0x8, 0x2a,0x5d,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x2d,0xde,0x2, 0x2b,0xfe,0x7a,0x1f, +0x29,0xe9,0x7a,0xf, 0x29,0xe5,0x22,0x7a,0xb3,0x29,0xed,0x70,0x14,0x12,0x2d,0xde, +0x12,0x2b,0xfe,0x7e,0x18,0x5, 0xe0,0x7a,0x1f,0x6, 0x40,0x7e,0x18,0x4, 0x60,0x80, +0x10,0xb4,0x1, 0x11,0x12,0x2d,0xd5,0x12,0x2b,0xfe,0x12,0x5f,0x7f,0x7e,0x18,0x4, +0x0, 0x7a,0x1f,0x6, 0x44,0x22,0x74,0x1, 0x12,0x0, 0x1e,0xe4,0x12,0x2c,0x7, 0x12, +0x2c,0x4e,0xe4,0x12,0x0, 0x1e,0x74,0x1, 0x12,0x2c,0x7, 0x2, 0x2c,0x4e,0xca,0x3b, +0x7e,0xd3,0x29,0x60,0x7e,0xc3,0x29,0x61,0x7e,0x8, 0x1e,0x54,0x12,0x67,0xcf,0x7e, +0x8, 0x1e,0x9a,0x7e,0x34,0x0, 0x46,0x12,0x1a,0x30,0x7e,0x8, 0x1e,0xe0,0x12,0xd0, +0x96,0x7e,0x8, 0x1e,0xea,0x12,0x1e,0xb0,0x7e,0xf3,0x29,0xe9,0x7e,0x18,0x29,0xc9, +0x7a,0x1d,0x24,0x7e,0x18,0x1e,0xe0,0x7a,0x1d,0x28,0x7c,0xbd,0x7c,0x7c,0x7e,0x8, +0x29,0xa6,0x12,0xcc,0x9, 0x6c,0xee,0x80,0x2b,0xa, 0x3e,0x9, 0xa3,0x29,0xc9,0xa, +0x3a,0x2e,0x34,0x19,0xc5,0x12,0x80,0xef,0x7c,0xab,0xbe,0xa0,0x1c,0x50,0x13,0xa, +0x3e,0x12,0x2d,0x5d,0xa, 0x4a,0x19,0xb4,0x1e,0x54,0x7e,0xb3,0x29,0xe8,0x19,0xb4, +0x1e,0x9a,0xb, 0xe0,0xbc,0xce,0x38,0xd1,0x6c,0xee,0x80,0x24,0xa, 0x3e,0x9, 0xa3, +0x29,0xa6,0xbe,0xa0,0x23,0x50,0x17,0xa, 0x2e,0xa, 0x3c,0x2d,0x32,0x12,0x2d,0x5d, +0xa, 0x4a,0x19,0xb4,0x1e,0x70,0x7e,0xb3,0x29,0xe8,0x19,0xb4,0x1e,0xb6,0xb, 0xe0, +0xbc,0xde,0x38,0xd8,0x7e,0xb3,0x29,0xea,0x7e,0x8, 0x1e,0xf4,0x60,0x9, 0x7e,0x18, +0x1e,0xe0,0x12,0x6d,0x7e,0x80,0x3, 0x12,0xcb,0xaf,0x6c,0xee,0x7e,0x18,0x1e,0xf4, +0x7a,0x1f,0x1e,0x44,0x74,0x2, 0xac,0xbe,0x49,0x35,0x1e,0xe0,0x7a,0x37,0x1e,0x48, +0x74,0x2, 0xac,0xbe,0x49,0x35,0x1e,0xea,0x7a,0x37,0x1e,0x4a,0x7e,0x70,0xe, 0xac, +0x7e,0x2e,0x34,0x1e,0x54,0x6d,0x22,0x7a,0x1f,0x1e,0x4c,0x7e,0x70,0xe, 0xac,0x7e, +0x2e,0x34,0x1e,0x9a,0x7a,0x1f,0x1e,0x50,0x7e,0x8, 0x1e,0x44,0x7c,0xbf,0x7c,0x7e, +0x12,0x8, 0xd1,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xb2,0xda,0x3b,0x22,0x2e,0x37,0x29, +0xeb,0x7e,0x39,0xb0,0x22,0x74,0x1, 0x7a,0xb3,0x3a,0xa5,0x12,0x2f,0xec,0x12,0x13, +0xf5,0x12,0xcb,0x23,0xe4,0x12,0xa, 0x66,0x7e,0x24,0x3, 0xd4,0x12,0x2f,0xdc,0x74, +0x1, 0x12,0x2c,0x7, 0x12,0x5f,0xf9,0x7e,0x34,0xd0,0xc, 0x12,0x1, 0xe, 0x12,0x2c, +0x36,0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x12,0x2f,0xe3,0xb4,0x1, +0x17,0xca,0x39,0x7e,0x18,0x24,0xc2,0x7e,0x8, 0x3b,0x8a,0x12,0x1a,0xb, 0x1b,0xfd, +0x12,0xd0,0xdd,0x12,0x2d,0xd5,0x80,0x1a,0xca,0x39,0x7e,0x18,0x2a,0x5d,0x7e,0x8, +0x3b,0x8a,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x37,0x2a,0x63,0x7a,0x37,0x37,0xee,0x12, +0x2d,0xde,0x2, 0x2b,0xfe,0x7e,0x1f,0x24,0xc6,0x7e,0xf, 0x24,0xc2,0x22,0x7e,0x1f, +0x2a,0x61,0x7e,0xf, 0x2a,0x5d,0x22,0xe5,0xd, 0x60,0x52,0xe5,0xd, 0x30,0xe0,0x6, +0x53,0xd, 0xfe,0x12,0x37,0xcd,0xe5,0xd, 0x30,0xe1,0x14,0x53,0xd, 0xfd,0x7e,0xb3, +0x3b,0x8e,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x12,0x67,0xc7,0x12,0xca,0x83,0xe5, +0xd, 0x30,0xe2,0x29,0x53,0xd, 0xfb,0xe4,0x7a,0xb3,0x3b,0x8f,0x7e,0xb3,0x3b,0x8e, +0x70,0xa, 0x74,0x1, 0x12,0x0, 0x1e,0x12,0x2d,0xde,0x80,0x7, 0xe4,0x12,0x0, 0x1e, +0x12,0x2d,0xd5,0x12,0x2b,0xfe,0x7e,0xb3,0x29,0xe9,0x2, 0x65,0x65,0x22,0x7a,0xb3, +0x29,0xed,0x70,0x5, 0x12,0x2d,0xde,0x80,0x6, 0xb4,0x1, 0x6, 0x12,0x2d,0xd5,0x12, +0x2b,0xfe,0x22,0x30,0x8, 0x3b,0xc2,0x8, 0x12,0x1c,0xf9,0x7e,0x73,0x3b,0x4f,0x7a, +0x73,0x29,0x3a,0x7e,0x73,0x3b,0x50,0x7a,0x73,0x2a,0xa, 0x7e,0x73,0x3b,0x50,0x7a, +0x73,0x29,0xee,0x7e,0xb3,0x3b,0x51,0x60,0x18,0x7e,0x34,0x0, 0x2, 0x12,0x38,0x41, +0x7e,0x34,0x0, 0x1, 0x12,0x38,0x41,0x6d,0x33,0x12,0x38,0x41,0xe4,0x7a,0xb3,0x3b, +0x51,0x12,0x2d,0xe7,0x2, 0x2e,0x97,0xe5,0xc, 0x70,0x2, 0xe1,0xb9,0xe5,0xc, 0x30, +0xe0,0x10,0x53,0xc, 0xfe,0x12,0x5c,0x29,0x12,0x63,0x6d,0x7e,0x8, 0x29,0x5a,0x12, +0x9, 0xa1,0xe5,0xc, 0x30,0xe1,0x6, 0x53,0xc, 0xfd,0x12,0xcb,0xc0,0xe5,0xc, 0x30, +0xe2,0x32,0x53,0xc, 0xfb,0x7e,0xb3,0x29,0xff,0x60,0x9, 0x7e,0x8, 0x29,0x5a,0x12, +0x6, 0xba,0x80,0xb, 0x7e,0xb3,0x2a,0x52,0x7e,0x73,0x2a,0x51,0x12,0xb, 0xad,0x7e, +0x73,0x29,0xff,0x2e,0x70,0xff,0x92,0x1, 0x90,0x60,0x51,0xe4,0x93,0x9e,0xb3,0x29, +0x64,0x12,0xb, 0x1e,0xe5,0xc, 0x30,0xe3,0x4a,0x53,0xc, 0xf7,0x7e,0x73,0x3b,0x7c, +0x7a,0x73,0x29,0xfc,0x12,0x86,0xe8,0x7a,0xb3,0x0, 0x6b,0xbe,0xb0,0xff,0x68,0xb, +0x43,0xc, 0x20,0x7e,0x73,0x0, 0x6b,0x7a,0x73,0x3b,0x54,0x12,0x54,0xf0,0x12,0x37, +0xd4,0x7e,0x73,0x3b,0x7d,0xbe,0x73,0x2a,0x4f,0x68,0x6, 0x7a,0x73,0x2a,0x4f,0xd2, +0xf, 0x30,0xf, 0x9, 0xc2,0xf, 0x12,0x2f,0xec,0xe4,0x12,0xa, 0x66,0x12,0x1c,0x53, +0x12,0x57,0xf7,0xe5,0xc, 0x30,0xe4,0xf, 0x53,0xc, 0xef,0x7e,0x43,0x3b,0x7e,0x7e, +0x50,0xa, 0xac,0x45,0x12,0x2f,0xdc,0xe5,0xc, 0x30,0xe6,0x4e,0x53,0xc, 0xbf,0x7e, +0x73,0x3b,0x6a,0xbe,0x70,0x7, 0x28,0x6, 0x74,0x7, 0x7a,0xb3,0x3b,0x6a,0xa9,0xd5, +0xcb,0x74,0xe, 0x12,0x0, 0x46,0x7c,0x7b,0x5e,0x70,0xf, 0x7e,0x63,0x3b,0x6a,0xa, +0x26,0x2e,0x24,0x0, 0x3, 0x12,0x46,0x24,0x7c,0x65,0x4c,0x76,0x74,0xe, 0x12,0x3a, +0x27,0x12,0x0, 0x46,0x12,0x3a,0x72,0x7e,0x73,0x3b,0x6d,0x7a,0x73,0x2a,0x1, 0x7e, +0x73,0x3b,0x6c,0x7a,0x73,0x2a,0xc, 0x12,0xd0,0xef,0xe5,0xc, 0x30,0xe5,0xa, 0x53, +0xc, 0xdf,0x7e,0xb3,0x3b,0x54,0x2, 0x33,0x5d,0x22,0x12,0x51,0x54,0x12,0x62,0xbc, +0x12,0x58,0xda,0x12,0x1c,0x33,0x7e,0xb3,0x3a,0xa5,0x24,0xfd,0x68,0x9, 0xb, 0xb1, +0x78,0xf4,0x12,0x44,0x7f,0x80,0xef,0x12,0x1e,0xc6,0x80,0xea,0x7d,0x32,0x74,0xfa, +0x2, 0x12,0xd0,0x7e,0xb3,0x3b,0x8e,0x7e,0x34,0x0, 0x4, 0x22,0x7e,0x8, 0x29,0x5a, +0x12,0x3, 0x8b,0x7e,0x8, 0x29,0x5a,0x74,0x3, 0x2, 0x11,0x7a,0xca,0xf8,0x7c,0xab, +0xbe,0xa0,0x34,0x38,0x2, 0x21,0xd, 0xbe,0xa0,0x35,0x78,0x6, 0x7e,0xb3,0x29,0xfd, +0x41,0x23,0xbe,0xa0,0x36,0x68,0x5, 0xbe,0xa0,0x37,0x78,0x1d,0x7e,0x35,0x8, 0x7d, +0x23,0xb, 0x24,0x7a,0x25,0x8, 0x2e,0x37,0x37,0xf0,0x7e,0x39,0xb0,0xbe,0xa0,0x37, +0x68,0x2, 0x41,0x23,0x75,0x1a,0x36,0x41,0x23,0xbe,0xa0,0x38,0x68,0x5, 0xbe,0xa0, +0x39,0x78,0x1b,0x7e,0xf3,0x3b,0x6e,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x6e,0xbe,0xa0, +0x39,0x78,0x3, 0x75,0x1a,0x38,0xa, 0x3f,0x9, 0xb3,0x2a,0xe, 0x41,0x23,0xbe,0xa0, +0x3a,0x68,0x5, 0xbe,0xa0,0x3b,0x78,0x1b,0x7e,0xf3,0x3b,0x70,0x7c,0xbf,0x4, 0x7a, +0xb3,0x3b,0x70,0xbe,0xa0,0x3b,0x78,0x3, 0x75,0x1a,0x3a,0xa, 0x3f,0x9, 0xb3,0x2a, +0x31,0x41,0x23,0xbe,0xa0,0xfb,0x78,0x6, 0x7e,0xb3,0x29,0xff,0x41,0x23,0xbe,0xa0, +0x5e,0x78,0x26,0x7e,0xf, 0x3c,0x53,0x69,0x30,0x0, 0x8e,0xa, 0x56,0x1e,0x54,0x1e, +0x54,0x1e,0x54,0x5e,0x54,0x0, 0x1, 0x3, 0x3, 0x54,0xc0,0xa, 0x36,0x5e,0x34,0x0, +0x3, 0x7c,0xa7,0x4c,0xba,0x44,0x80,0x41,0x23,0xbe,0xa0,0x3c,0x68,0x5, 0xbe,0xa0, +0x3d,0x78,0x1b,0x7e,0xf3,0x3b,0x72,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x72,0xbe,0xa0, +0x3d,0x78,0x3, 0x75,0x1a,0x3c,0xa, 0x3f,0x9, 0xb3,0x29,0x67,0x41,0x23,0xbe,0xa0, +0x3e,0x68,0x5, 0xbe,0xa0,0x3f,0x78,0x1b,0x7e,0xf3,0x3b,0x74,0x7c,0xbf,0x4, 0x7a, +0xb3,0x3b,0x74,0xbe,0xa0,0x3f,0x78,0x3, 0x75,0x1a,0x3e,0xa, 0x3f,0x9, 0xb3,0x29, +0x8a,0x41,0x23,0xbe,0xa0,0x40,0x40,0xd, 0xbe,0xa0,0x4d,0x38,0x8, 0xa, 0x3a,0x9, +0xb3,0x3b,0x4a,0x41,0x23,0xbe,0xa0,0x4e,0x68,0x5, 0xbe,0xa0,0x4f,0x78,0x1e,0x7e, +0xf3,0x3b,0x8f,0x7c,0xbf,0x4, 0x7a,0xb3,0x3b,0x8f,0xbe,0xa0,0x4f,0x78,0x3, 0x75, +0x1a,0x4e,0xa, 0x3f,0x2e,0x37,0x37,0xee,0x7e,0x39,0xb0,0x41,0x23,0xbe,0xa0,0x51, +0x68,0x5, 0xbe,0xa0,0x52,0x78,0x28,0x7e,0x14,0x60,0x0, 0x6d,0x0, 0x2e,0x4, 0x0, +0xff,0x7e,0xb3,0x3b,0x9a,0xa, 0x3b,0x6d,0x22,0x2f,0x10,0x7e,0x1b,0x70,0x4, 0x7a, +0xb3,0x3b,0x9a,0xbe,0xa0,0x52,0x78,0x3, 0x75,0x1a,0x51,0x7c,0xb7,0x41,0x23,0xbe, +0xa0,0x5c,0x68,0x5, 0xbe,0xa0,0x5d,0x78,0x1a,0x7e,0xf3,0x3b,0x63,0x7c,0xbf,0x4, +0x7a,0xb3,0x3b,0x63,0xbe,0xa0,0x5d,0x78,0x3, 0x75,0x1a,0x5c,0x7c,0xbf,0x12,0x32, +0x26,0x41,0x23,0xbe,0xa0,0x60,0x40,0xd, 0xbe,0xa0,0x6c,0x38,0x8, 0xa, 0x3a,0x9, +0xb3,0x3c,0x14,0x80,0x7e,0xbe,0xa0,0x6d,0x78,0x4, 0xe5,0xe, 0x80,0x75,0xbe,0xa0, +0xf4,0x68,0x5, 0xbe,0xa0,0xf5,0x78,0x18,0x7e,0x35,0xa, 0x7d,0x23,0xb, 0x24,0x7a, +0x25,0xa, 0x9, 0xb3,0x37,0xf6,0xbe,0xa0,0xf5,0x78,0x58,0x75,0x1a,0xf4,0x80,0x53, +0xbe,0xa0,0xf0,0x68,0x5, 0xbe,0xa0,0xf1,0x78,0x9, 0x7c,0x1a,0x2e,0x10,0x20,0xa5, +0xe7,0x80,0x40,0xbe,0xa0,0xf2,0x68,0x5, 0xbe,0xa0,0xf3,0x78,0x1b,0x7e,0x15,0x10, +0x3e,0x14,0x7e,0x1f,0x37,0xf2,0x2d,0x31,0xb, 0x1a,0x30,0xbe,0xa0,0xf2,0x78,0x4, +0xa, 0x56,0x80,0x1f,0x7d,0x53,0x80,0x1b,0xbe,0xa0,0xf6,0x78,0x4, 0xe5,0xf, 0x80, +0x12,0xbe,0xa0,0xf7,0x78,0x4, 0x74,0x50,0x80,0x9, 0xbe,0xa0,0xfd,0x78,0x3, 0xe4, +0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7c,0xab,0xbe,0xa0,0x0, 0x40,0x11,0x7e,0xb3,0x29, +0x5b,0xbc,0xba,0x28,0x9, 0x74,0x2, 0xa4,0x49,0x25,0x34,0x0, 0x80,0x51,0x7e,0x13, +0x29,0x5b,0xbc,0x1a,0x38,0x1c,0x7e,0x3, 0x29,0x5a,0xa, 0x10,0xa, 0x21,0x2d,0x12, +0xa, 0x3a,0xbd,0x31,0x58,0xc, 0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x2, 0x8c, +0x80,0x2d,0x7e,0x3, 0x29,0x5a,0xa, 0x20,0xa, 0x11,0x7d,0x41,0x2d,0x42,0xa, 0x3a, +0xbd,0x34,0x48,0x19,0x7e,0x10,0x2, 0xac,0x1, 0x2d,0x1, 0xbd,0x30,0x58,0xe, 0x9d, +0x31,0x9d,0x32,0x3e,0x34,0x3e,0x34,0x49,0x23,0x2, 0x8e,0x80,0x2, 0xe4,0x22,0x7e, +0x34,0x0, 0x64,0xad,0x23,0x74,0xc, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80, +0x14,0x78,0xf4,0x7c,0xb7,0x22,0xca,0xf8,0x80,0x38,0x7c,0xbf,0x12,0x32,0x26,0xa, +0x1b,0x7e,0x63,0x29,0x5b,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x10,0x2, 0xac,0x1f,0x2d, +0x3, 0x7e,0x1f,0x12,0x9a,0x2d,0x30,0x12,0x32,0xe5,0x9d,0x35,0x1b,0x1a,0x10,0xb, +0xf0,0x12,0x32,0xe5,0x7e,0x73,0x29,0x5b,0xa, 0x27,0x2d,0x25,0xa, 0x3f,0xbd,0x32, +0x48,0xc8,0xda,0xf8,0x22,0x7e,0xa3,0x29,0x5a,0x74,0x2, 0xa4,0x22,0x12,0xd0,0xe6, +0x12,0xd0,0xdd,0x6d,0x33,0x7a,0x35,0xa, 0x12,0x33,0x3c,0x12,0x33,0x16,0x74,0x50, +0x7a,0xb3,0x3b,0x7e,0x7e,0x24,0x3, 0x20,0x12,0x2f,0xdc,0xe4,0x12,0xd0,0x6, 0x6d, +0x33,0x7a,0x37,0x3c,0x8c,0x22,0x7e,0x73,0x2a,0x4f,0x7a,0x73,0x3b,0x7d,0x22,0xa2, +0xc, 0xe4,0x33,0x7a,0xb3,0x3b,0x78,0x7e,0x73,0x3b,0x7c,0xbe,0x73,0x29,0xfc,0x68, +0xa, 0xe5,0xc, 0x70,0x6, 0x12,0x33,0x3c,0x12,0x33,0x16,0x22,0x7e,0x73,0x29,0xfc, +0x7a,0x73,0x3b,0x7c,0x7e,0x73,0x2a,0xc, 0x7a,0x73,0x3b,0x6c,0x7e,0x73,0x2a,0xd, +0x7a,0x73,0x3b,0x6b,0x7e,0x73,0x2a,0x1, 0x7a,0x73,0x3b,0x6d,0x22,0xca,0xd8,0xca, +0x79,0x7c,0xdb,0x7e,0xa0,0x4, 0xbe,0xd0,0x80,0x78,0x18,0x7e,0xe0,0xff,0x6c,0xff, +0x80,0xb, 0x12,0x33,0xc5,0x38,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38, +0xf1,0x80,0x1a,0xbe,0xd0,0x81,0x78,0x15,0x6c,0xee,0x6c,0xff,0x80,0xb, 0x12,0x33, +0xc5,0x40,0x4, 0x7c,0xeb,0x7c,0xdf,0xb, 0xf0,0xbc,0xaf,0x38,0xf1,0xbc,0xad,0x38, +0x2, 0x6c,0xdd,0x7c,0xbd,0x12,0x55,0x43,0x12,0x33,0x54,0x12,0x37,0x24,0x12,0x33, +0xe1,0x7e,0x73,0x29,0xfc,0x7a,0x73,0x3b,0x7c,0x12,0x33,0x16,0x7a,0xd3,0x3b,0x54, +0xda,0x79,0xda,0xd8,0x22,0x7e,0x90,0x5, 0xac,0x9f,0x9, 0xb4,0x25,0x7, 0xbc,0xbe, +0x22,0x30,0x0, 0x3, 0x12,0x33,0x54,0xa2,0x1, 0x92,0x2, 0x12,0x34,0x95,0x2, 0x33, +0xe1,0x7e,0x73,0x2a,0xd, 0x7a,0x73,0x3b,0x6b,0x22,0x12,0x37,0xdb,0x12,0x6b,0x7f, +0x50,0x9, 0xd2,0x0, 0xd2,0x1, 0x12,0x33,0xd1,0x80,0x15,0x74,0x1, 0x12,0x34,0x19, +0x7e,0x43,0x3b,0x69,0x7e,0x50,0x64,0xac,0x45,0x12,0x7c,0x81,0x7a,0xb3,0x2a,0xc, +0x12,0x33,0xe1,0x12,0x37,0x24,0x2, 0x33,0x54,0xca,0x3b,0x7c,0xdb,0xe4,0x7a,0xb3, +0x2a,0x1, 0x12,0x37,0xd4,0x7e,0xc0,0xa, 0x12,0x37,0x34,0x30,0xd, 0xfd,0x74,0x1, +0x12,0x0, 0xe, 0x7e,0x1f,0x3c,0x6c,0x12,0x7f,0xb5,0x7d,0x73,0xbe,0x74,0xff,0xff, +0x78,0x9, 0x12,0x34,0x89,0x2e,0x34,0x0, 0x3, 0x80,0x18,0xbe,0x74,0x80,0x0, 0x28, +0x7, 0x12,0x34,0x89,0xb, 0x35,0x80,0xb, 0xbe,0x74,0x40,0x0, 0x28,0xc, 0x12,0x34, +0x89,0xb, 0x34,0x1b,0xa, 0x30,0x1b,0xc0,0x78,0xbe,0xbe,0xd0,0x1, 0x78,0x9, 0x7e, +0x1f,0x3c,0x6c,0x12,0x7c,0xa0,0x7d,0x73,0x7e,0x1f,0x3c,0x5b,0x69,0x31,0x0, 0x1a, +0x7a,0x73,0x2a,0x1, 0x7d,0x37,0xda,0x3b,0x22,0x7e,0xf, 0x3c,0x5b,0x2e,0x14,0x0, +0x1a,0xb, 0xa, 0x30,0x22,0xca,0x3b,0x7e,0x34,0xff,0xff,0x7a,0x35,0x34,0x7e,0xb3, +0x3b,0x5f,0xf5,0x29,0x7e,0xb3,0x29,0x5a,0xf5,0x2a,0x7e,0xb3,0x29,0x5b,0xf5,0x2b, +0x7e,0xb3,0x29,0x5d,0xf5,0x2c,0x7e,0xb3,0x29,0x5c,0xf5,0x2d,0x7e,0x34,0x27,0x10, +0x7a,0x35,0x2e,0x7e,0x18,0x40,0x0, 0x7a,0x1d,0x30,0x12,0x37,0x2d,0x30,0xd, 0xfd, +0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x8, 0x34,0x0, 0x12,0x37,0xe2,0x6c,0xff,0x80,0x34, +0x9f,0x77,0x6c,0xee,0x80,0x19,0x7e,0x11,0x2b,0xac,0x1e,0x3e,0x4, 0x7e,0x30,0x2, +0xac,0x3f,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x30,0x12,0x36,0xf3,0xe5, +0x2d,0xbc,0xbe,0x38,0xe1,0xe5,0x2d,0x12,0x36,0xfa,0x74,0x2, 0xac,0xbf,0x59,0x35, +0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xc6,0x6c,0xff,0x80,0x72,0x9f,0x77, +0x6c,0xee,0x80,0x12,0x12,0x37,0x7a,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80, +0x14,0x78,0xf4,0x12,0x36,0xf3,0xe5,0x29,0xbc,0xbe,0x38,0xe8,0xe5,0x29,0x12,0x36, +0xfa,0x74,0x4, 0xac,0xbf,0x59,0x35,0x2, 0x8c,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x32, +0x9f,0x77,0x7e,0xe1,0x29,0x80,0x12,0x12,0x37,0x7a,0x1e,0x34,0x1e,0x24,0x50,0x3, +0x4e,0x60,0x80,0x14,0x78,0xf4,0x12,0x36,0xf3,0xe5,0x2c,0xbc,0xbe,0x38,0xe8,0xe5, +0x29,0xa, 0x3b,0x6d,0x22,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x9f,0x1, 0x12,0x36,0xfe, +0x80,0x4, 0x7e,0x34,0x10,0x0, 0x74,0x4, 0xac,0xbf,0x59,0x35,0x2, 0x8e,0xb, 0xf0, +0xe5,0x2d,0xbc,0xbf,0x38,0x88,0xe5,0x2c,0xa, 0x1b,0x6d,0x0, 0x7e,0x78,0x0, 0x28, +0x12,0x37,0x1c,0x80,0x2e,0x74,0x2, 0xac,0xbf,0x49,0x25,0x34,0x0, 0xa, 0x5f,0xad, +0x53,0x7e,0x14,0x10,0x0, 0x9d,0x15,0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50, +0x3, 0x4e,0x20,0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x2, 0xac,0xbf,0x59,0x25,0x34, +0x0, 0xb, 0xf0,0xe5,0x2c,0xbc,0xbf,0x38,0xcc,0xe5,0x2a,0xa, 0x1b,0x6d,0x0, 0x12, +0x37,0x1c,0x80,0x5c,0x74,0x4, 0xac,0xbf,0x49,0x25,0x2, 0x8c,0xa, 0x1f,0xad,0x13, +0x7e,0xf4,0x10,0x0, 0x9d,0xf1,0xad,0xf2,0x74,0xc, 0x1e,0xf4,0x1e,0xe4,0x50,0x4, +0x4e,0xf4,0x80,0x0, 0x14,0x78,0xf3,0x7d,0x2f,0x74,0x4, 0xac,0xbf,0x59,0x25,0x2, +0x8c,0xe5,0x29,0xbe,0xb1,0x2c,0x50,0x26,0x74,0x4, 0xac,0xbf,0x49,0x25,0x2, 0x8e, +0x2e,0x14,0x10,0x0, 0xad,0x12,0x74,0xc, 0x1e,0x14,0x1e,0x4, 0x50,0x3, 0x4e,0x20, +0x80,0x14,0x78,0xf4,0x7d,0x21,0x74,0x4, 0xac,0xbf,0x59,0x25,0x2, 0x8e,0xb, 0xf0, +0xe5,0x2a,0xbc,0xbf,0x38,0x9e,0x7e,0x73,0x3b,0x61,0xa, 0x37,0x6d,0x22,0x74,0xc, +0x2f,0x11,0x14,0x78,0xfb,0x7e,0xf4,0x0, 0x64,0x7d,0x1f,0x12,0x17,0x32,0x7d,0xe3, +0x7a,0xe5,0x34,0x7e,0x73,0x3b,0x62,0xa, 0x37,0x6d,0x22,0x74,0xc, 0x2f,0x11,0x14, +0x78,0xfb,0x7d,0x1f,0x12,0x17,0x32,0x7d,0x63,0x6c,0xff,0x80,0x20,0x74,0x2, 0xac, +0xbf,0x49,0x45,0x34,0x0, 0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x34, +0x0, 0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x34,0x0, 0xb, 0xf0,0xe5,0x2c,0xbc, +0xbf,0x38,0xda,0x6c,0xff,0x80,0x3a,0x74,0x4, 0xac,0xbf,0x49,0x45,0x2, 0x8c,0xbe, +0x45,0x34,0x28,0x9, 0x7e,0x35,0x34,0x59,0x35,0x2, 0x8c,0x80,0x8, 0xbd,0x46,0x50, +0x4, 0x59,0x65,0x2, 0x8c,0x49,0x45,0x2, 0x8e,0xbe,0x45,0x34,0x28,0x9, 0x7e,0x35, +0x34,0x59,0x35,0x2, 0x8e,0x80,0x8, 0xbd,0x46,0x50,0x4, 0x59,0x65,0x2, 0x8e,0xb, +0xf0,0xe5,0x2a,0xbc,0xbf,0x38,0xc0,0x30,0x2, 0x6, 0x74,0x1, 0x7a,0xb3,0x2a,0xd, +0xda,0x3b,0x22,0x6d,0x22,0x2f,0x71,0xb, 0xe0,0x22,0xa, 0x1b,0x6d,0x0, 0x7f,0x17, +0x12,0x17,0x34,0x7f,0x71,0x7e,0x25,0x2e,0x74,0xc, 0x7d,0x13,0x7d,0x32,0x6d,0x22, +0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14,0x2, 0x17,0x32,0x7f,0x17,0x12,0x17, +0x34,0x6c,0xff,0x22,0x7e,0x73,0x2a,0xc, 0x7a,0x73,0x3b,0x6c,0x22,0x7e,0x8, 0x29, +0x5a,0x12,0xd, 0x72,0xe4,0x12,0x0, 0xe, 0x74,0x1, 0x7e,0x70,0x99,0x12,0x13,0x2c, +0x2, 0x0, 0x4e,0xb4,0x3, 0x5, 0x12,0x37,0x53,0x80,0x2, 0xe4,0x22,0x12,0x37,0x38, +0x74,0x1, 0x22,0x12,0x37,0xf2,0xe4,0x12,0x0, 0xe, 0x7e,0x8, 0x29,0x5a,0x2, 0xd, +0x72,0x12,0x69,0x93,0x38,0x2, 0xe4,0x22,0x12,0x37,0xea,0x49,0x55,0x34,0x3b,0xbe, +0xb0,0x2, 0x38,0x3, 0x2, 0x37,0xa1,0x2, 0x37,0x43,0x7e,0x11,0x2b,0xac,0x1f,0x3e, +0x4, 0x7e,0x30,0x2, 0xac,0x3e,0x2d,0x10,0x7e,0x1d,0x30,0x2d,0x31,0xb, 0x1a,0x20, +0x7a,0x27,0x24,0x2, 0x74,0x2, 0xac,0xbe,0x49,0x35,0x34,0x0, 0xad,0x23,0x74,0xc, +0x22,0x7e,0xd7,0x29,0xfa,0xbe,0xb0,0x1, 0x28,0x2, 0xe4,0x22,0x12,0x69,0x24,0x12, +0x37,0xcd,0x7a,0xd7,0x29,0xfa,0x7e,0x73,0x29,0xe7,0xa, 0x37,0x3e,0x34,0x3e,0x34, +0xe4,0x7e,0x50,0x1, 0x12,0x13,0x1, 0x12,0x65,0xee,0x74,0x1, 0x22,0x7e,0x8, 0x29, +0x5a,0x2, 0x5, 0xb4,0x7e,0x8, 0x29,0x5a,0x2, 0xd, 0x72,0x74,0x40,0x7a,0xb3,0x2a, +0xd, 0x22,0x7e,0x34,0x0, 0x38,0xe4,0x2, 0x1a,0x30,0x7e,0xa3,0x34,0x39,0x74,0x4, +0xa4,0x22,0x74,0x1, 0x12,0x13,0xde,0xe4,0x2, 0x0, 0x1e,0x7e,0xf, 0x3c,0x57,0x69, +0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33,0x69,0x10,0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74, +0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x7e,0x34, +0x0, 0x1, 0x7e,0xf, 0x3c,0x57,0x79,0x30,0x0, 0x4, 0x7e,0xf, 0x3c,0x57,0x69,0x30, +0x0, 0x12,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, 0x79,0x30,0x0, 0x12, +0x22,0xca,0xd8,0xca,0x79,0x7d,0xd3,0x90,0x60,0x50,0xe4,0x93,0x7c,0xfb,0x90,0x60, +0x51,0xe4,0x93,0x7c,0x8b,0xa, 0x38,0xa, 0xcf,0x2d,0xc3,0xb, 0xc4,0x7d,0x3c,0x7c, +0xe7,0x12,0x57,0xe7,0xa9,0xd0,0xc4,0xa9,0xd5,0xcb,0x74,0x7, 0x12,0x0, 0x46,0x7c, +0x8b,0x74,0x7, 0x7e,0x70,0xf, 0x12,0x3a,0x6f,0x7e,0x54,0x0, 0x78,0x7e,0x1f,0x3c, +0x57,0x79,0x51,0x0, 0x6, 0x7e,0x54,0x0, 0x80,0x7e,0x1f,0x3c,0x57,0x79,0x51,0x0, +0x8, 0x7e,0x54,0x0, 0xc, 0x7e,0x1f,0x3c,0x57,0x79,0x51,0x0, 0x10,0xbe,0xd4,0x0, +0x2, 0x78,0x7, 0x12,0x3a,0xc, 0x44,0x1, 0x80,0x1c,0x12,0x3a,0xc, 0x44,0x8, 0x1b, +0x1a,0x50,0x4d,0xdd,0x7e,0x1f,0x3c,0x57,0x78,0x7, 0x12,0x3a,0x10,0x54,0xfb,0x80, +0x5, 0x12,0x3a,0x10,0x44,0x4, 0x1b,0x1a,0x50,0x7e,0x1f,0x3c,0x53,0x69,0xe1,0x0, +0x84,0x69,0x51,0x0, 0x90,0x7d,0xf5,0x2e,0x34,0x0, 0x90,0x5e,0xa0,0xf6,0x1b,0x1a, +0x50,0x7e,0xb3,0x3a,0xaf,0xbe,0xb0,0x6, 0x40,0x3, 0xb4,0xff,0xe, 0x12,0x3a,0x1b, +0x54,0xe6,0x12,0x3a,0x18,0x4e,0x54,0x1, 0xa4,0x80,0xc, 0x12,0x3a,0x1b,0x5e,0x54, +0xfe,0xe6,0x12,0x3a,0x18,0x44,0xa4,0x1b,0x1a,0x50,0xbe,0xd4,0x0, 0x2, 0x78,0x21, +0x12,0x3a,0xc, 0x12,0x3b,0x10,0x12,0x3a,0xc, 0x44,0x50,0x1b,0x1a,0x50,0x7e,0x34, +0x0, 0x2, 0x12,0x3a,0xab,0x12,0x38,0x1e,0x12,0x37,0xfb,0x7a,0x37,0x37,0xf6,0x21, +0xc8,0x6c,0xdd,0x21,0xc2,0x4c,0xdd,0x78,0x4, 0x6c,0x99,0x80,0x2b,0xbc,0xfd,0x40, +0x12,0xa, 0xcd,0x9, 0x9c,0x29,0xa5,0xbe,0x90,0x23,0x40,0x3, 0x7e,0x90,0x22,0xb, +0x90,0x80,0x15,0xa, 0x3f,0xa, 0xcd,0x9d,0xc3,0x9, 0x9c,0x29,0xc8,0xbe,0x90,0x1c, +0x40,0x3, 0x7e,0x90,0x1b,0x2e,0x90,0x24,0x12,0x3a,0xc, 0x12,0x3b,0x10,0xa, 0xc9, +0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x3e,0xc4,0x12,0x3a,0xc, 0x4d,0x5c,0x1b,0x1a,0x50, +0xe5,0xe, 0x60,0x7, 0xe5,0xe, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, 0x80, +0x4, 0xe5,0xe, 0xa, 0x3b,0x12,0x3a,0xab,0x12,0x38,0x1e,0xbe,0xd4,0x0, 0x1, 0x78, +0x10,0x12,0x38,0x1e,0x12,0x37,0xfb,0x74,0x2, 0xac,0xbd,0x59,0x35,0x37,0xf8,0x80, +0xf, 0x12,0x37,0xfb,0xa, 0x5e,0xa, 0x2d,0x2d,0x25,0x3e,0x24,0x59,0x32,0x37,0xf8, +0xb, 0xd0,0xbc,0xed,0x28,0x2, 0x21,0x35,0xa9,0xd5,0xcb,0x74,0x7, 0x7c,0x78,0x12, +0x3a,0x6f,0xa9,0xc0,0xc4,0x7e,0x1f,0x3c,0x53,0x79,0xe1,0x0, 0x84,0x7e,0x1f,0x3c, +0x53,0x79,0xf1,0x0, 0x90,0x6d,0x33,0x7e,0xf, 0x3c,0x57,0x79,0x30,0x0, 0x6, 0x7e, +0xf, 0x3c,0x57,0x79,0x30,0x0, 0x8, 0x7e,0xf, 0x3c,0x57,0x79,0x30,0x0, 0x10,0x7e, +0xf, 0x3c,0x57,0x79,0x30,0x0, 0xe, 0xda,0x79,0xda,0xd8,0x22,0x7e,0x1f,0x3c,0x57, +0x2e,0x34,0x0, 0xe, 0xb, 0x1a,0x50,0x22,0x1b,0x1a,0x50,0x7e,0x1f,0x3c,0x53,0x2e, +0x34,0x0, 0x84,0xb, 0x1a,0x50,0x22,0xf5,0xfd,0x7a,0x71,0xfe,0x22,0xa9,0xd5,0xcb, +0x74,0x2, 0x7e,0x70,0x3f,0x12,0x3a,0x27,0x74,0xf, 0x12,0x0, 0x46,0x7c,0x7b,0x74, +0xf, 0x5e,0x70,0xfe,0x12,0x3a,0x27,0x74,0xc, 0x12,0x0, 0x46,0x54,0x7f,0x68,0x8, +0x74,0xc, 0x7e,0x70,0xf8,0x12,0x3a,0x27,0x7e,0x70,0x72,0x74,0xe, 0x12,0x3a,0x27, +0x74,0x7, 0x12,0x0, 0x46,0x7c,0x7b,0x5e,0x70,0xfb,0x74,0x7, 0x2, 0x3a,0x6f,0x12, +0x3a,0x27,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0x6d,0x33,0x7e,0x8, 0x0, 0x24,0x7e, +0x24,0x0, 0x12,0x12,0x52,0xa0,0xe5,0x34,0x20,0xe7,0x1b,0xa9,0xd5,0xcb,0x74,0x3, +0x7e,0x71,0x27,0x12,0x3a,0x27,0x74,0xb, 0x7e,0x71,0x2f,0x12,0x3a,0x27,0x74,0xc, +0x7e,0x71,0x30,0x12,0x3a,0x6f,0x22,0x7e,0x34,0x0, 0x1, 0x7d,0x23,0x80,0x12,0x7e, +0x30,0x4, 0x80,0x5, 0x74,0xfa,0x12,0x3b,0x18,0x7c,0x23,0x1b,0x30,0xa5,0xba,0x0, +0xf3,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe6,0x22,0x24,0xab,0x68,0x10,0x24,0xef, +0x68,0x1c,0x24,0xde,0x68,0x26,0x24,0xde,0x78,0x2f,0x74,0x5, 0x80,0x2d,0x7e,0xb3, +0x3, 0xff,0xb4,0x5, 0x2a,0x12,0x3a,0xa7,0x12,0xc8,0xb8,0x2, 0xc9,0xd2,0x7e,0xb3, +0x3, 0xff,0xb4,0x5, 0x1a,0x12,0x3a,0xa7,0x75,0xe9,0xff,0x22,0x7e,0xb3,0x3, 0xff, +0xb4,0x5, 0xc, 0x12,0x3a,0xa7,0x2, 0xc9,0xcc,0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22, +0x5e,0x54,0x0, 0xf, 0x1b,0x1a,0x50,0x22,0x7c,0xab,0x80,0xe, 0x7e,0x70,0x3, 0x80, +0x1, 0x0, 0x7c,0x67,0x1b,0x70,0xa5,0xbe,0x0, 0xf7,0x7c,0x6a,0x1b,0xa0,0xa5,0xbe, +0x0, 0xea,0x22,0x7c,0x6b,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x3a,0x27,0x7a,0x61,0xfc, +0x12,0x3a,0x72,0x12,0x53,0xe3,0xd2,0x0, 0x12,0xc9,0xe9,0x12,0x3f,0x6f,0x12,0x13, +0xde,0x2, 0x13,0x96,0x12,0xd1,0x10,0xc2,0x0, 0x12,0x57,0xee,0xc2,0x2, 0x12,0x3b, +0x83,0xc2,0x0, 0x12,0xc9,0xe9,0xa9,0xd5,0xcb,0x74,0xf, 0x12,0x0, 0x46,0x7a,0x1b, +0xb0,0x74,0xf, 0x6c,0x77,0x12,0x3a,0x27,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10, +0x2, 0x3a,0x72,0xa9,0xd0,0xce,0xa2,0x2, 0xa9,0x91,0xc9,0x22,0x30,0x1, 0x6, 0x12, +0x3f,0x6f,0x2, 0x13,0x96,0x12,0xd1,0x10,0xc2,0x2, 0x2, 0x3b,0x83,0xca,0x3b,0x7e, +0xb3,0x3a,0xa3,0xb4,0x1, 0x2, 0x80,0x2, 0x81,0xed,0x6c,0xcc,0x6c,0xdd,0x7e,0xb3, +0x3a,0xce,0xb4,0x1, 0x8, 0x7e,0xe0,0x10,0x7e,0xf0,0x32,0x80,0x6, 0x7e,0xe0,0x6, +0x7e,0xf0,0x1e,0x12,0x80,0x91,0x7d,0xf3,0x12,0x67,0xe1,0x50,0xfb,0x74,0x1, 0x7a, +0xb3,0x3b,0xef,0x12,0x2c,0x7, 0x12,0x13,0xc7,0x12,0x0, 0x1e,0x74,0xa, 0x12,0x3b, +0x18,0x12,0x67,0xbf,0x7e,0xe7,0x29,0xfa,0x7a,0xe5,0x25,0x7e,0xb3,0x29,0xe7,0xf5, +0x24,0x74,0x4, 0x7a,0xb3,0x29,0xe7,0x7e,0xe7,0x29,0xfa,0x5e,0xe4,0x0, 0x3f,0x7a, +0xe7,0x29,0xfa,0x7e,0xb3,0x29,0xe7,0x12,0xcc,0xcd,0x7c,0x7b,0x74,0x6, 0xac,0x7b, +0x12,0xa9,0x49,0x7d,0x23,0x7d,0x3f,0x12,0x6c,0x83,0xad,0x32,0x7a,0x37,0x29,0xf4, +0x12,0x37,0xcd,0x81,0xce,0x12,0x57,0xe7,0x30,0x10,0x2, 0x81,0xd4,0x7c,0xbe,0x12, +0x80,0xdb,0x12,0x65,0xee,0xc2,0x0, 0x80,0x2f,0x80,0x7, 0x12,0x3e,0x1d,0xe4,0x12, +0x3e,0x75,0x20,0x93,0xf6,0x30,0x1b,0x1d,0x20,0x0, 0x1a,0xd2,0x1, 0x12,0x3b,0x8c, +0x12,0x3d,0x2b,0xd2,0x0, 0x12,0x3c,0xf0,0x68,0x6, 0x7e,0xb3,0x3b,0xee,0x60,0xe, +0xc2,0x1, 0x12,0x3b,0x8c,0x12,0x3c,0xfb,0x30,0x1b,0xd7,0x30,0x1a,0xd4,0xd2,0x1, +0x12,0x3b,0x8c,0xe4,0x12,0x13,0xde,0xb, 0xc0,0x12,0x3d,0x2b,0x12,0x87,0xfe,0x7e, +0xa3,0x3b,0xee,0x4c,0xaa,0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x3b,0xef,0x4c,0xaa,0x68, +0xb, 0x7e,0xb3,0x3a,0xce,0x70,0x5, 0xe4,0x7a,0xb3,0x3b,0xee,0x12,0x3c,0xf0,0x78, +0x18,0x7e,0xb3,0x3b,0xee,0x60,0x12,0xe4,0x7a,0xb3,0x3b,0xee,0x7a,0xb3,0x28,0xf4, +0x7a,0xb3,0x28,0xf5,0x7e,0xd0,0x1, 0x80,0x1b,0x12,0x3c,0xf0,0x68,0x10,0x7e,0xb3, +0x3b,0xee,0x70,0xa, 0x7e,0xd0,0x1, 0xe4,0x7a,0xb3,0x3a,0xa3,0x80,0x6, 0xbc,0xfc, +0x28,0x2, 0x81,0x25,0xe4,0x7a,0xb3,0x29,0xf1,0x7e,0x35,0x25,0x7a,0x37,0x29,0xfa, +0xe5,0x24,0x7a,0xb3,0x29,0xe7,0x4c,0xdd,0x68,0x3, 0x12,0x1d,0x58,0xda,0x3b,0x22, +0x7e,0x73,0x3c,0x81,0xa, 0x37,0x5e,0x34,0x0, 0x2, 0x22,0x30,0x1b,0x5, 0xc2,0x1, +0x12,0x3b,0x8c,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x30,0x1a,0x3, 0x20,0x1b,0x14,0x12, +0x3e,0x1d,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x2, 0x12,0x3e,0x75,0xa9,0xd0,0xce, +0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xd2,0x1, 0x2, 0x3b,0x8c,0xca,0x3b,0x7e,0x8, 0x1e, +0x44,0x12,0x37,0xe2,0x7e,0x1f,0x3c,0x82,0x7a,0x1d,0x27,0x7e,0xb3,0x29,0x61,0xf5, +0x2e,0x7e,0xb3,0x3b,0xef,0xb4,0x1, 0x6, 0x7e,0x38,0x3b,0xf1,0x80,0x4, 0x7e,0x38, +0x5, 0x80,0x6d,0x33,0x7a,0x35,0x2b,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x3b,0xf0, +0x70,0xe, 0x7e,0xb3,0x3b,0xee,0x70,0x8, 0x74,0x1, 0x7a,0xb3,0x3b,0xf0,0xa1,0xf0, +0x7e,0xb3,0x3b,0xf0,0x70,0x6, 0x74,0x1, 0x7a,0xb3,0x3b,0xf0,0x7e,0xb3,0x3b,0xef, +0xb4,0x1, 0x14,0x75,0x2d,0x0, 0x80,0x6, 0x12,0xd0,0x1c,0x12,0xcf,0xc9,0xe5,0x2e, +0xbe,0xb1,0x2d,0x38,0xf3,0x80,0x18,0x75,0x2d,0x0, 0x80,0xc, 0x12,0xd0,0x1c,0x3e, +0x24,0x3e,0x24,0x1e,0x24,0x12,0xcf,0xc9,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xed,0x7e, +0x34,0x0, 0xc8,0x7a,0x35,0x2f,0x7e,0x18,0x1e,0x44,0x7f,0x1, 0x12,0xa9,0xb9,0x75, +0x2d,0x0, 0x80,0x10,0x12,0xd0,0xf, 0xbe,0x35,0x2b,0x8, 0x6, 0x12,0xd0,0xf, 0x7a, +0x35,0x2b,0x5, 0x2d,0xe5,0x2e,0xbe,0xb1,0x2d,0x38,0xe9,0x12,0x3f,0x77,0x40,0x25, +0x7e,0xb3,0x3b,0xef,0xb4,0x1, 0x1e,0x5, 0x1d,0xe5,0x1d,0xbe,0xb0,0xa, 0x40,0x15, +0x75,0x1d,0x0, 0xe5,0x2e,0xa, 0x3b,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x27,0x7f,0x3, +0x12,0x1a,0xb, 0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x12,0x3f,0x77,0x50,0xb, 0x74, +0x2, 0x7a,0xb3,0x3c,0x81,0xe4,0x7a,0xb3,0x3b,0xf0,0xda,0x3b,0x22,0x74,0x81,0x7a, +0xb3,0x3c,0x8a,0x22,0x12,0x3e,0x1d,0x12,0x80,0x5f,0x75,0xcd,0x0, 0xc2,0xce,0x12, +0x5f,0x88,0x12,0x3b,0x54,0x74,0x1, 0x12,0x3e,0x75,0xd2,0xce,0xe5,0x25,0x7e,0x71, +0x24,0x2, 0x3b,0x33,0x80,0x1d,0x12,0x3e,0x1d,0x12,0x80,0x57,0x68,0x5, 0xc2,0x1, +0x12,0x3b,0x8c,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x2, 0x68,0x18,0x20,0x1a,0x15,0xe4, +0x12,0x3e,0x75,0x20,0x93,0xe0,0x12,0x3e,0x1d,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x74, +0x2, 0x2, 0x3e,0x75,0x22,0x7c,0xab,0x7e,0xb3,0x3c,0x8a,0xb4,0x81,0x38,0x4c,0xaa, +0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, 0xc2,0xaf,0xa9,0xd0, +0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe,0xa0,0x2, 0x78,0x16, +0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3c,0x8a,0x22,0x7e,0xb3,0x3a,0xa3, +0x14,0x68,0x5a,0x14,0x78,0x2, 0xe1,0x5c,0x14,0x68,0x6d,0x24,0x3, 0x68,0x2, 0xe1, +0x54,0x12,0x3f,0x7f,0x38,0x8, 0x30,0x13,0xf, 0x12,0x8f,0xeb,0x68,0xa, 0x12,0x9e, +0xea,0xe4,0x7a,0xb3,0x3b,0xee,0x80,0x74,0x7e,0xb3,0x3a,0x84,0x30,0xe0,0x6d,0x7e, +0x73,0x3a,0x85,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x3a,0xce,0xb4, +0x1, 0xb, 0x7e,0x34,0x62,0x7b,0x12,0x9b,0x7, 0x2e,0x34,0x4, 0x0, 0xbe,0x37,0x3b, +0xec,0x50,0x49,0x12,0x3f,0x62,0xe4,0x7a,0xb3,0x3b,0xf0,0x80,0x3f,0x12,0x3f,0x7f, +0x38,0x3, 0x30,0x13,0x32,0xe4,0x7a,0xb3,0x3a,0xa3,0x7e,0xb3,0x3b,0xee,0xb4,0x1, +0x3, 0x12,0x3f,0x68,0xd2,0x1a,0x80,0x1f,0x74,0xff,0x7a,0xb3,0x3a,0x7d,0x12,0xd1, +0x17,0x12,0x3e,0x24,0x12,0x1c,0x5d,0xe4,0x7a,0xb3,0x3a,0xa3,0x7a,0xb3,0x3c,0x8f, +0xd2,0x1a,0x80,0x8, 0x12,0x3f,0x68,0xe4,0x7a,0xb3,0x3c,0x8f,0x12,0x80,0x2f,0x2, +0x3b,0x9d,0x6d,0x33,0x7a,0x37,0x3b,0xec,0x74,0x1, 0x7a,0xb3,0x3a,0xa3,0x22,0xd2, +0x2, 0x12,0x3b,0x83,0x74,0x1, 0x22,0x7e,0x37,0x29,0xf4,0xbe,0x35,0x2b,0x22,0x7e, +0x73,0x28,0xf4,0xbe,0x70,0x0, 0x22,0xd2,0x0, 0x80,0x12,0x30,0x0, 0xc, 0x12,0x80, +0x57,0x68,0x7, 0xc2,0x0, 0xc2,0x1, 0x12,0x3b,0x8c,0x12,0x3e,0x44,0x30,0x1a,0xeb, +0x22,0xca,0xd8,0xca,0x79,0x7e,0x73,0x29,0x5b,0x7e,0xf3,0x29,0x5a,0xac,0xf7,0x7d, +0x37,0x3e,0x34,0x7e,0x8, 0x1e,0x44,0xe4,0x12,0x1a,0x30,0x7e,0xb3,0x3b,0x65,0xb4, +0x1, 0x64,0x7e,0x73,0x3b,0x66,0xbe,0x70,0x0, 0x28,0x5b,0x6c,0xdd,0x80,0x3c,0x12, +0x57,0xe7,0x12,0x1d,0xb1,0x6d,0x33,0x80,0x28,0x7e,0x35,0x24,0x3e,0x34,0x49,0x33, +0xc, 0xd8,0x12,0x1a,0x62,0x7a,0x35,0x26,0x7e,0x35,0x24,0x7d,0x13,0x3e,0x14,0x49, +0x21,0x1e,0x44,0xbe,0x25,0x26,0x58,0x7, 0x7e,0x25,0x26,0x59,0x21,0x1e,0x44,0xb, +0x34,0x7a,0x35,0x24,0xbe,0x75,0x24,0x38,0xd0,0xb, 0xd0,0x7e,0x73,0x3b,0x66,0xbc, +0x7d,0x38,0xbc,0x7d,0x37,0x3e,0x34,0xca,0x39,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0xc, +0xd8,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3,0x3a,0xa2,0xb4, +0x1, 0x4, 0xe4,0x2, 0x40,0x37,0x22,0x70,0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0xca, +0x3b,0x75,0x25,0x0, 0x75,0x26,0x0, 0x75,0x27,0x0, 0x75,0x28,0x0, 0x75,0x2b,0x3, +0x75,0x32,0x0, 0x75,0x33,0x0, 0x7e,0x38,0x28,0x90,0x12,0xc8,0x8, 0x12,0xc7,0x8b, +0x75,0x24,0x0, 0x12,0x44,0xfd,0x60,0x3, 0x75,0x33,0x1, 0x5, 0x24,0xe5,0x24,0xb4, +0xa, 0xf1,0x7e,0xb3,0x28,0xfd,0x70,0x12,0x7e,0xb3,0x28,0xf9,0x70,0xc, 0x7e,0xb3, +0x28,0xfa,0x70,0x6, 0xe5,0x33,0x70,0x2, 0x81,0x23,0x75,0x24,0x0, 0x12,0x44,0xfd, +0x60,0x8, 0x2e,0x34,0x29,0x0, 0x14,0x7a,0x39,0xb0,0x5, 0x24,0xe5,0x24,0xb4,0xa, +0xec,0x30,0x11,0x6, 0x7e,0x48,0x36,0xfc,0x80,0x4, 0x7e,0x48,0x36,0xbe,0x7f,0x4, +0x12,0xd0,0x8d,0x7e,0x73,0x28,0xf6,0x7a,0x4b,0x70,0x75,0x24,0x0, 0x61,0xcd,0xe5, +0x24,0x12,0xa3,0xcf,0x12,0x44,0x71,0x9, 0xb5,0x27,0xe0,0xf5,0x2a,0x12,0x45,0x1d, +0xf5,0x2b,0xe5,0x2a,0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, 0x61,0xcb,0xe5,0x2b,0xb4, +0x3, 0x7, 0x12,0x45,0x6, 0x70,0x2, 0x61,0xcb,0x7e,0x8, 0x0, 0x2b,0xe5,0x2a,0x12, +0x98,0xb6,0x50,0x7, 0x12,0x45,0x6, 0x70,0x2, 0x61,0xcb,0x12,0x44,0x71,0x9, 0xb5, +0x27,0xe1,0xf5,0x27,0x12,0x44,0x71,0x9, 0xb5,0x27,0xe2,0xc4,0x54,0xf0,0xf5,0x28, +0x7e,0x73,0x29,0x3a,0xbe,0x71,0x2a,0x28,0x5a,0x7e,0xb3,0x28,0xfb,0x70,0x2e,0x75, +0x39,0xf, 0x7e,0x8, 0x0, 0x27,0xe5,0x2a,0xa, 0x3b,0x2e,0x34,0x36,0xaa,0x6d,0x22, +0x74,0x1, 0x12,0x45,0x91,0x75,0x39,0x20,0x7e,0x8, 0x0, 0x28,0xe5,0x2a,0xa, 0x3b, +0x2e,0x34,0x36,0xb4,0x6d,0x22,0x74,0x10,0x12,0x45,0x91,0x80,0x3, 0x12,0x45,0x29, +0xe5,0x2a,0xa, 0x3b,0x7f,0x3, 0x2d,0x13,0x7e,0xb, 0xb0,0xb4,0x1, 0x15,0xe4,0x19, +0xb3,0x36,0xaa,0x6c,0xaa,0xe5,0x2a,0xa, 0x3b,0x19,0xa3,0x36,0xb4,0x75,0x27,0x0, +0x75,0x28,0x0, 0x7e,0xb3,0x29,0x51,0xb4,0xff,0x12,0x75,0x27,0x0, 0x12,0x44,0x71, +0x9, 0xb5,0x27,0xe0,0xbe,0xb0,0xff,0x68,0x3, 0x75,0x27,0x1, 0x12,0x44,0x71,0x49, +0x45,0x27,0xdc,0x7a,0x45,0x2c,0x49,0x35,0x27,0xde,0x7a,0x35,0x2e,0xe5,0x2b,0xb4, +0x1, 0x2, 0x80,0x2, 0x61,0x45,0x75,0x34,0x0, 0xe5,0x24,0xbe,0xb0,0x1, 0x38,0x14, +0xe5,0x24,0xa, 0x3b,0x6d,0x22,0x9d,0x23,0x7e,0x34,0x0, 0x9, 0xad,0x32,0x9, 0xb3, +0x27,0xe9,0xf5,0x34,0x6c,0xaa,0x7e,0x71,0x2a,0x74,0x5, 0xac,0x7b,0x19,0xa3,0x32, +0xd, 0xe5,0x2a,0xa, 0x3b,0x2d,0x37,0x7d,0x26,0x39,0xa1,0x0, 0x3c,0x75,0x29,0x0, +0x7e,0x71,0x29,0x74,0x9, 0xac,0x7b,0x9, 0xb3,0x37,0x98,0x54,0xf, 0xbe,0xb1,0x2a, +0x78,0x1c,0x49,0x23,0x37,0x94,0x7a,0x25,0x2c,0x49,0x23,0x37,0x96,0x7a,0x25,0x2e, +0x9, 0xb3,0x27,0xe3,0xf5,0x30,0x9, 0xb3,0x27,0xe4,0xf5,0x31,0x80,0x5, 0x12,0x44, +0xf5,0x40,0xcd,0x75,0x29,0x0, 0x12,0x44,0x78,0x9, 0xb5,0x37,0x3e,0x54,0xf, 0xbe, +0xb1,0x2a,0x68,0x5, 0x12,0x44,0xf5,0x40,0xed,0x7e,0x35,0x2c,0xbe,0x34,0x1, 0x2c, +0x50,0x6, 0xbe,0x34,0x0, 0xa, 0x38,0x25,0xbe,0x34,0x3, 0xc, 0x28,0x6, 0xbe,0x34, +0x4, 0x2e,0x40,0x19,0xe5,0x30,0xbe,0xb0,0x1, 0x28,0x12,0x7e,0x73,0x29,0x5c,0xa, +0x27,0x1b,0x25,0xe5,0x30,0xa, 0x3b,0xbd,0x32,0x8, 0x2, 0x61,0x45,0x12,0x44,0x78, +0x49,0x25,0x37,0x3a,0x7e,0x35,0x2c,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x14, +0x18,0x2, 0x61,0x45,0xe5,0x29,0xbe,0xb0,0xa, 0x40,0x2, 0x61,0x45,0x7e,0x73,0x28, +0xf4,0xbe,0x70,0x2, 0x40,0x2, 0x61,0x45,0xe5,0x34,0x12,0x45,0x1d,0xbe,0xb0,0x1, +0x78,0x2, 0x61,0x45,0x7e,0xa1,0x34,0x74,0x9, 0xa4,0x49,0x35,0x27,0xdc,0xbe,0x34, +0x0, 0x1e,0x38,0x2, 0x61,0x45,0xbe,0x34,0x4, 0x1a,0x40,0x2, 0x61,0x45,0x7e,0xa1, +0x34,0x74,0x5, 0xa4,0x9, 0xb5,0x32,0xd, 0x60,0x2, 0x61,0x45,0x75,0x2b,0x2, 0x7e, +0xb3,0x28,0xf4,0x4, 0x7a,0xb3,0x28,0xf4,0x12,0x44,0x78,0x49,0x15,0x37,0x3a,0x7e, +0x5, 0x2c,0x9d,0x1, 0x3e,0x4, 0x2e,0x5, 0x2c,0x7a,0x5, 0x35,0x49,0x45,0x37,0x3c, +0x7e,0x15,0x2e,0x9d,0x14,0x7d,0x41,0x2e,0x45,0x2e,0x7a,0x45,0x37,0xbe,0x4, 0x0, +0x0, 0x58,0xf, 0x6d,0x0, 0x12,0x45,0x11,0x7d,0x3, 0x2e,0x5, 0x2e,0x7a,0x5, 0x37, +0x80,0x1e,0x7e,0x5, 0x35,0xbe,0x4, 0x4, 0x37,0x8, 0xf, 0x7e,0x4, 0x4, 0x37,0x12, +0x45,0x11,0x2e,0x35,0x2e,0x7a,0x35,0x37,0x80,0x6, 0x7e,0x35,0x35,0x7a,0x35,0x2c, +0x7e,0x35,0x37,0xbe,0x34,0x0, 0x0, 0x58,0x7, 0x6d,0x22,0x7a,0x25,0x2e,0x80,0x12, +0xbe,0x34,0x8, 0xe7,0x8, 0x6, 0x7e,0x34,0x8, 0xe7,0x80,0x3, 0x7e,0x35,0x37,0x7a, +0x35,0x2e,0x12,0x45,0x29,0x7e,0x35,0x2c,0x5e,0x60,0xf, 0x7a,0x35,0x2c,0x7e,0x35, +0x2e,0x5e,0x60,0xf, 0x7a,0x35,0x2e,0x7e,0x91,0x24,0x74,0x9, 0xac,0x9b,0x9, 0x74, +0x27,0xe0,0xa, 0x57,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x7d,0x25,0x2e,0x25,0x2e,0x7a, +0x25,0x2e,0xbe,0x70,0xff,0x68,0x19,0xe5,0x2b,0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x25, +0x5, 0x26,0xe5,0x2b,0xa, 0x5b,0x12,0xd0,0xf8,0x7d,0x35,0x2e,0x35,0x2c,0x80,0x7, +0x7e,0x35,0x2c,0x2e,0x34,0xc0,0x0, 0x7a,0x35,0x2c,0x7e,0x25,0x2c,0x12,0x44,0xed, +0x7f,0x4, 0x2d,0x13,0x79,0x20,0x0, 0x2, 0x7e,0x25,0x2e,0x7f,0x4, 0x2d,0x13,0x79, +0x20,0x0, 0x4, 0xe5,0x27,0x2d,0x39,0x7d,0x28,0x39,0xb1,0x0, 0x6, 0x7e,0xa1,0x28, +0x12,0x44,0xed,0x2d,0x39,0x39,0xa1,0x0, 0x7, 0x5, 0x32,0x5, 0x24,0x7e,0x73,0x29, +0x3a,0xbe,0x71,0x24,0x28,0x2, 0x1, 0xbf,0xe5,0x25,0x39,0xb4,0x0, 0x1, 0x7e,0xb3, +0x3a,0xce,0xb4,0x1, 0x9, 0x7e,0xb3,0x28,0xfa,0xb4,0x1, 0x19,0x80,0xf, 0xe5,0x26, +0xbe,0xb0,0x0, 0x38,0x6, 0x7e,0xb3,0x28,0xfa,0x60,0xa, 0xb2,0x11,0x12,0x69,0x5, +0x74,0x1, 0x12,0x40,0x37,0x7e,0xb3,0x28,0xf9,0x60,0x9, 0xe5,0x33,0x70,0x5, 0x7f, +0x3, 0x12,0x45,0x56,0xe4,0x7a,0xb3,0x28,0xfd,0x7a,0xb3,0x28,0xf9,0x7a,0xb3,0x28, +0xfa,0x80,0x9, 0x7f,0x3, 0x12,0x45,0x56,0xe4,0x12,0x40,0x37,0x7e,0x34,0x0, 0x5a, +0xca,0x39,0x7e,0x18,0x37,0x94,0x7e,0x8, 0x37,0x3a,0x12,0x1a,0xb, 0x1b,0xfd,0x7e, +0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x27,0xdc,0x7e,0x8, 0x37,0x94,0x12,0x1a,0xb, +0x1b,0xfd,0xe5,0x26,0x70,0x18,0x7e,0x8, 0x37,0x3a,0x7e,0x34,0x0, 0x5a,0x74,0xff, +0x12,0x1a,0x30,0x7e,0x8, 0x37,0x94,0x7e,0x34,0x0, 0x5a,0x12,0x1a,0x30,0xda,0x3b, +0x22,0x7e,0xa1,0x24,0x74,0x9, 0xa4,0x22,0x7e,0xa1,0x29,0x74,0x9, 0xa4,0x22,0x12, +0x1d,0x72,0x12,0x67,0xf2,0x7e,0xb3,0x3a,0xa5,0xb4,0x1, 0x5b,0x12,0xc9,0xf4,0x12, +0xd1,0x17,0x12,0x80,0x96,0x12,0x45,0xd3,0x12,0x1d,0xb1,0x50,0xe5,0x12,0x5e,0xbd, +0x7e,0xb3,0x3a,0xa2,0xb4,0x1, 0x4, 0xe4,0x12,0x40,0x37,0x12,0x85,0x66,0x12,0x45, +0x3e,0x40,0xcf,0x12,0x6b,0xcc,0x12,0x45,0x3e,0x40,0xc7,0x12,0x92,0xa7,0x12,0x1f, +0x47,0x12,0x46,0xa1,0x12,0x47,0xe1,0x12,0x92,0x44,0x12,0x77,0xb4,0x12,0x6e,0xd4, +0x12,0x71,0x61,0x12,0x94,0x1a,0x12,0x9d,0x1a,0x12,0x40,0x3f,0x12,0x50,0x73,0x12, +0x80,0x71,0x12,0x50,0x1c,0x80,0x9b,0x12,0x67,0xec,0x2, 0x40,0x2b,0x7e,0x71,0x32, +0x74,0x6, 0xac,0x7b,0x22,0x5, 0x29,0xe5,0x29,0xbe,0xb0,0xa, 0x22,0xe5,0x24,0xa, +0x3b,0x9, 0xb3,0x29,0x0, 0x22,0x7e,0xa1,0x2a,0x74,0x5, 0xa4,0x9, 0xb5,0x32,0xc, +0x22,0x7a,0x5, 0x2c,0x7e,0x24,0x0, 0x3, 0x7d,0x31,0x2, 0x16,0xe6,0x54,0xf, 0xa, +0x3b,0x2d,0x37,0x7d,0x26,0x7e,0x1b,0xb0,0x22,0xe5,0x2a,0xa, 0x3b,0x9, 0xb3,0x36, +0xaa,0xf5,0x27,0xe5,0x2a,0xa, 0x3b,0x9, 0xb3,0x36,0xb4,0xf5,0x28,0x22,0xc2,0x0, +0x7e,0xb3,0x15,0xa1,0x60,0x6, 0x7e,0xb3,0x15,0xa0,0x70,0x7, 0x12,0xd0,0x44,0x28, +0x2, 0xd2,0x0, 0xa2,0x0, 0x22,0x6c,0xaa,0x74,0x3, 0x12,0xad,0x43,0x7f,0x10,0x2d, +0x34,0x39,0xb1,0x0, 0xa, 0x12,0x7b,0x15,0x7f,0x70,0x2d,0xf3,0x79,0x47,0x0, 0x14, +0x2d,0x31,0x79,0x41,0x0, 0x28,0xe4,0xa, 0x4a,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, +0x46,0x7f,0x10,0x2d,0x34,0x39,0xb1,0x0, 0x50,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xc8, +0x22,0x7c,0x9b,0x7f,0x71,0x7e,0x7b,0x80,0x4c,0x88,0x78,0x7, 0x7e,0xb, 0x90,0x7a, +0x7b,0x90,0x22,0xa, 0x28,0x7e,0xb, 0x80,0xa, 0x38,0x9d,0x32,0x12,0x1a,0x62,0xe5, +0x39,0xa, 0x2b,0xbd,0x32,0x8, 0x15,0x7e,0x7b,0xa0,0x7e,0xb, 0xb0,0xbc,0xba,0x7c, +0xba,0x28,0x4, 0x2c,0xb9,0x80,0x2, 0x9c,0xb9,0x7a,0x7b,0xb0,0x7e,0x7b,0x70,0x7a, +0xb, 0x70,0x22,0x7e,0x34,0x3a,0x7e,0x30,0x10,0x47,0xc2,0x10,0x9, 0x53,0x0, 0x2, +0x12,0x46,0x22,0x7a,0x27,0x29,0x3c,0x9, 0x53,0x0, 0x3, 0x12,0x46,0x22,0x7a,0x27, +0x29,0x3e,0x9, 0x53,0x0, 0x4, 0x12,0x46,0x22,0x7a,0x27,0x29,0x40,0x7e,0x39,0x50, +0x12,0x46,0x2d,0x7a,0x27,0x29,0x47,0x9, 0x53,0x0, 0x1, 0x12,0x46,0x2d,0x7a,0x27, +0x29,0x49,0x9, 0x73,0x0, 0x5, 0xa, 0x37,0x12,0x7c,0x71,0x3e,0x34,0x7a,0x37,0x29, +0x4f,0x22,0xa, 0x25,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x22,0xa, 0x25,0x3e, +0x24,0x3e,0x24,0x22,0x7c,0x67,0x7c,0x7b,0xa5,0xbf,0x0, 0x17,0xbe,0x60,0x0, 0x28, +0xf, 0x74,0x1, 0x7a,0xb3,0x28,0xf9,0xe4,0x7a,0xb3,0x28,0xfb,0x7a,0xb3,0x28,0xfc, +0x2, 0xa0,0x6, 0xa5,0xbe,0x0, 0x1b,0x6c,0xaa,0x7e,0x60,0xff,0x7e,0x50,0x9, 0xac, +0x5a,0x19,0x62,0x28,0x3a,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xf0,0x74,0x1, 0x7a,0xb3, +0x28,0xf8,0x6c,0xaa,0x80,0x26,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x27,0x82,0xb, +0x18,0x20,0x12,0x46,0x24,0x1b,0x18,0x20,0x7e,0x30,0x9, 0xac,0x3a,0x2e,0x14,0x27, +0x84,0xb, 0x18,0x20,0x12,0x46,0x24,0x1b,0x18,0x20,0xb, 0xa0,0xbc,0x7a,0x38,0xd6, +0x22,0x2, 0x46,0xa4,0xca,0x3b,0x6c,0xff,0x7e,0xb3,0x29,0x5c,0xf5,0x29,0x7e,0xe3, +0x29,0x5d,0x6c,0xdd,0x7e,0xb3,0x15,0xa1,0xbe,0xb0,0x1, 0x68,0xf, 0x60,0x2, 0xe1, +0xd3,0x7e,0xb3,0x27,0x58,0xb4,0x1, 0x2, 0x80,0x2, 0xe1,0xd3,0x6c,0xcc,0xe1,0xc5, +0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xa3,0x25,0xce,0x7a,0xa1,0x27,0x9, 0xb3,0x25,0xcf, +0xf5,0x28,0x75,0x25,0x2, 0x75,0x26,0x2, 0x4c,0xaa,0x68,0xe, 0xe5,0x29,0xa, 0x2b, +0x1b,0x24,0xe5,0x27,0xa, 0x3b,0xbd,0x32,0x48,0x3, 0x75,0x25,0x1, 0xe5,0x28,0x60, +0xc, 0xa, 0x2e,0x1b,0x24,0xe5,0x28,0xa, 0x3b,0xbd,0x32,0x48,0x3, 0x75,0x26,0x1, +0x75,0x24,0x0, 0x80,0x5c,0xe5,0x24,0xbc,0xbc,0x68,0x54,0x7e,0x71,0x24,0x12,0xd0, +0xc2,0x9, 0x33,0x25,0xcf,0xa, 0x2a,0xe5,0x27,0x12,0x47,0xda,0xbe,0x34,0x0, 0x3, +0x18,0x11,0x12,0x47,0xd6,0xbe,0x34,0x0, 0x3, 0x18,0x8, 0x75,0x25,0x1, 0x75,0x26, +0x1, 0x80,0x37,0xa, 0x2a,0xe5,0x27,0x12,0x47,0xda,0xbe,0x34,0x0, 0x4, 0x18,0x1f, +0x12,0x47,0xd6,0xbe,0x34,0x0, 0x4, 0x18,0x16,0xe5,0x25,0xbe,0xb0,0x2, 0x28,0x3, +0x75,0x25,0x2, 0xe5,0x26,0xbe,0xb0,0x2, 0x28,0x10,0x75,0x26,0x2, 0x80,0xb, 0x5, +0x24,0x7e,0x23,0x27,0x58,0xbe,0x21,0x24,0x38,0x9b,0x12,0x97,0x26,0x50,0x2a,0x7e, +0x73,0x39,0x0, 0xbe,0x71,0x27,0x78,0x9, 0x7e,0x73,0x39,0x2, 0xbe,0x71,0x28,0x68, +0x12,0x7e,0x73,0x39,0x1, 0xbe,0x71,0x27,0x78,0xf, 0x7e,0x73,0x39,0x3, 0xbe,0x71, +0x28,0x78,0x6, 0x75,0x25,0x3, 0x75,0x26,0x3, 0xe5,0x28,0xbe,0xb0,0x1, 0x68,0x3, +0x75,0x28,0x0, 0xe5,0x25,0x7e,0x71,0x26,0x7c,0x6c,0x7c,0x5f,0x7c,0x4d,0x12,0x7c, +0xfd,0xb, 0xf0,0xb, 0xc0,0x7e,0x73,0x27,0x58,0xbc,0x7c,0x28,0x2, 0xc1,0xd0,0x7a, +0xf3,0x27,0x58,0xda,0x3b,0x22,0xa, 0x23,0xe5,0x28,0xa, 0x3b,0x9d,0x32,0x2, 0x1a, +0x62,0x2, 0x47,0xe4,0xca,0x79,0x6c,0xff,0x7e,0xd7,0x29,0x47,0x6c,0xee,0x80,0x2f, +0x7c,0xbe,0x12,0x8c,0x77,0xbd,0x3d,0x48,0x24,0x7c,0xbe,0x12,0x80,0xf8,0x60,0x1d, +0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x70,0x9, 0xac,0x7e,0x2e,0x34,0x26,0x4a,0x6d, +0x22,0x12,0x77,0xaa,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0xb, 0xf0,0xb, 0xe0,0x12, +0x48,0x2f,0x38,0xcc,0x7a,0x73,0x27,0x67,0x7a,0xf3,0x28,0xf4,0xda,0x79,0x22,0x7e, +0x73,0x27,0x58,0xbc,0x7e,0x22,0xca,0x3b,0x7e,0xf3,0x29,0x61,0x12,0x48,0xb3,0x40, +0x6f,0x6d,0x33,0x9e,0x37,0x29,0x3c,0x3e,0x34,0xbe,0x37,0x7, 0x8, 0x18,0x61,0x7e, +0xb3,0x15,0xa2,0x70,0x5b,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x54,0x7e,0x37,0x29,0x3e, +0x7a,0x35,0x26,0x7e,0x67,0x29,0x40,0x6c,0xee,0x80,0x40,0x7c,0xbe,0x12,0x80,0xf8, +0x60,0x37,0x7e,0x70,0x2, 0xac,0x7e,0x12,0x8c,0x63,0x9, 0xa3,0x25,0xcf,0x7a,0xa1, +0x25,0x74,0x2, 0xa4,0x49,0x35,0x4, 0xc0,0xbd,0x36,0x48,0x13,0xe5,0x24,0xa, 0x2b, +0xa, 0x3f,0x2d,0x32,0x3e,0x34,0x49,0x33,0x4, 0xc0,0xbe,0x35,0x26,0x58,0xa, 0x7c, +0xbe,0x12,0x4f,0x3f,0xac,0x7e,0x12,0x4f,0xf9,0xb, 0xe0,0x12,0x48,0x2f,0x38,0xbb, +0xda,0x3b,0x22,0xa2,0x16,0x22,0xca,0xd8,0xca,0x79,0x75,0x24,0x1, 0x7e,0xe4,0x7f, +0xff,0x7d,0xfe,0x7e,0x34,0x80,0x0, 0x7d,0x23,0x7e,0xa3,0x29,0x5c,0x7e,0x83,0x29, +0x5d,0x7e,0x90,0x1, 0x80,0x17,0x12,0x4c,0x32,0xbd,0x1f,0x58,0x2, 0x7d,0xf1,0x12, +0x4c,0x32,0xbd,0x12,0x8, 0x5, 0xa, 0x19,0x12,0x4c,0x23,0xb, 0x90,0xa, 0xa, 0x1b, +0x4, 0xa, 0x19,0xbd,0x10,0x48,0xdf,0x7e,0x90,0x1, 0x80,0x1b,0x12,0x4b,0xeb,0xbd, +0xfe,0x58,0x2, 0x7d,0xef,0x12,0x4b,0xeb,0xbd,0xf3,0x8, 0x9, 0x7e,0x70,0x2, 0xac, +0x79,0x49,0x33,0x4, 0xc0,0xb, 0x90,0xa, 0x18,0x1b,0x14,0xa, 0xf9,0xbd,0xf1,0x48, +0xdb,0xbd,0x32,0x58,0x6, 0x7d,0xf2,0x7d,0x8f,0x80,0x2, 0x7d,0x83,0x7e,0xf4,0x0, +0x4, 0x7a,0xf7,0x27,0x75,0x7a,0xf7,0x27,0x77,0x7e,0xd4,0x0, 0xc8,0x7e,0xb4,0x0, +0x96,0xe4,0x7a,0xb3,0x27,0x80,0x12,0x4b,0xdd,0x7e,0x34,0xfd,0xa8,0x7e,0x94,0xfe, +0xd4,0x7e,0xb3,0x29,0x55,0xb4,0x1, 0x4, 0x7d,0xad,0x80,0x4, 0x7d,0xad,0x3e,0xa4, +0x6c,0xdd,0x6c,0x99,0x80,0x2f,0x7e,0x50,0x2, 0xac,0x59,0x9, 0xe2,0x25,0xce,0x9, +0xf2,0x25,0xcf,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x22,0x4, 0xc0,0xbd,0x2d,0x48,0x13, +0xa, 0xfe,0x7e,0xb3,0x29,0x5b,0xa, 0x2b,0x2d,0x2f,0x12,0x4c,0x2b,0xbd,0x2d,0x48, +0x2, 0xb, 0xd0,0xb, 0x90,0x12,0x4b,0xe4,0x38,0xcc,0x7e,0xf7,0x7, 0xe, 0xbd,0xf3, +0x58,0x14,0x7e,0xf7,0x7, 0xc, 0xbd,0xf9,0x58,0xc, 0x12,0x4b,0xf5,0x8, 0x39,0x12, +0x4b,0xda,0x60,0x34,0x80,0x2f,0x7e,0xf7,0x29,0x47,0x3e,0xf4,0x6e,0xf4,0xff,0xff, +0xb, 0xf4,0xbe,0xf7,0x27,0x62,0x8, 0x20,0x6d,0xff,0x9d,0xfd,0xbe,0xf7,0x7, 0xe, +0x8, 0x16,0x6d,0xff,0x9d,0xfa,0xbe,0xf7,0x7, 0xc, 0x8, 0xc, 0x4c,0xdd,0x78,0x8, +0x12,0x4b,0xda,0x60,0x3, 0x12,0x4c,0x0, 0x12,0x4b,0xda,0xa, 0xfb,0x4d,0xff,0x68, +0x47,0x6d,0x33,0x9d,0x3d,0x12,0xb6,0x4f,0xbe,0x37,0x7, 0xe, 0x18,0x6, 0xbe,0x37, +0x7, 0xc, 0x8, 0x34,0x12,0x4b,0xf5,0x8, 0x2f,0x7e,0x37,0x27,0x62,0x12,0x1a,0x62, +0xbe,0x37,0x27,0x5e,0x8, 0x22,0x12,0x4f,0x2f,0x28,0x1d,0x7e,0xb3,0x27,0x59,0xbe, +0xb0,0x1, 0x28,0x14,0x7e,0xf7,0x7, 0xa, 0xbd,0xfd,0x58,0xc, 0x12,0x4c,0x0, 0xe4, +0x7a,0xb3,0x27,0x58,0x7a,0xb3,0x28,0xf4,0x6c,0x99,0x80,0x3c,0x74,0x2, 0xac,0xb9, +0x9, 0xe5,0x25,0xce,0x9, 0xf5,0x25,0xcf,0x7e,0xa3,0x29,0x5c,0x6c,0x88,0x80,0x7, +0x12,0x27,0x2a,0x2d,0xc3,0xb, 0x80,0xbc,0xe8,0x38,0xf5,0xa, 0xfe,0xb, 0xf4,0x7d, +0x3f,0x7c,0x87,0x80,0x7, 0x12,0x27,0x2a,0x2d,0xc3,0xb, 0x80,0xa, 0x3a,0x1b,0x34, +0xa, 0xf8,0xbd,0xf3,0x48,0xef,0xb, 0x90,0x12,0x4b,0xe4,0x38,0xbf,0x12,0xaf,0xb, +0x40,0x5, 0xe4,0x7a,0xb3,0x27,0x7c,0x12,0x91,0x58,0x68,0x6, 0x7e,0xb3,0x3c,0x93, +0x60,0x7, 0xe4,0x7a,0xb3,0x27,0x81,0x80,0x63,0x12,0x4b,0xd2,0x28,0x5, 0xe4,0x7a, +0xb3,0x27,0x81,0x30,0x13,0x5, 0xe4,0x7a,0xb3,0x27,0x81,0x12,0xaf,0x49,0x50,0xa, +0x12,0x4b,0xdd,0x12,0x4c,0x43,0xf5,0x24,0x80,0x17,0x7e,0xb3,0x25,0x58,0x70,0x11, +0x7e,0xb3,0x25,0x59,0x70,0xb, 0x12,0x4b,0xd2,0x28,0x6, 0x75,0x24,0x3, 0x12,0x4b, +0xdd,0xbe,0x84,0x5, 0xdc,0x8, 0x17,0x12,0x4b,0xd2,0x28,0x12,0x6d,0xff,0x9d,0xfb, +0xbe,0xf7,0x27,0x62,0x58,0x8, 0x12,0x4c,0x15,0xe4,0x7a,0xb3,0x27,0x81,0x7e,0xa1, +0x24,0x74,0x4, 0xa4,0x7a,0x57,0x27,0x75,0x7a,0x57,0x27,0x77,0x12,0x48,0xb3,0x50, +0xd, 0xe4,0x7a,0xb3,0x27,0x81,0x12,0x4b,0xd2,0x28,0x3, 0x12,0x4c,0x15,0x7e,0xf7, +0x27,0x5e,0xbd,0xfb,0x8, 0x1d,0x7e,0x24,0x0, 0x2, 0x7d,0x3b,0x12,0x16,0xe6,0x6d, +0xff,0x9d,0xf3,0xbe,0xf7,0x27,0x62,0x58,0xa, 0x12,0x48,0xb3,0x50,0x5, 0xe4,0x7a, +0xb3,0x27,0x81,0x12,0x4c,0xa6,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x27,0x81,0x7e,0xb3, +0x25,0x58,0x60,0x8, 0x6d,0x33,0x9d,0x3d,0xbd,0x3e,0x8, 0x32,0x7e,0xb3,0x25,0x59, +0x70,0x2c,0x12,0x4b,0xd2,0x28,0x27,0x12,0x8f,0xe3,0x28,0x22,0x4c,0xdd,0x78,0x1e, +0x7e,0x37,0x29,0x47,0x7d,0x23,0x3e,0x24,0x6e,0x24,0xff,0xff,0xb, 0x24,0xbe,0x27, +0x27,0x62,0x8, 0xa, 0x3e,0x34,0x3e,0x34,0xbe,0x37,0x27,0x5e,0x38,0x9, 0x7e,0x73, +0x34,0x88,0xbe,0x70,0x0, 0x28,0x1b,0x6c,0x33,0x80,0xc, 0x7c,0xb3,0x12,0x4f,0x3f, +0xac,0x73,0x12,0x4f,0xf9,0xb, 0x30,0x7e,0x23,0x27,0x58,0xbc,0x23,0x38,0xec,0x12, +0x27,0xa0,0x12,0xae,0x72,0x7e,0xb3,0x34,0x88,0xbe,0xb0,0x0, 0x28,0x1f,0x14,0x7a, +0xb3,0x34,0x88,0x70,0x18,0xe4,0x7a,0xb3,0x27,0x81,0x12,0x4f,0x37,0x7a,0xb3,0x15, +0xa1,0x7a,0xb3,0x15,0xa0,0x7a,0xb3,0x27,0x58,0x7a,0xb3,0x25,0x57,0xda,0x79,0xda, +0xd8,0x22,0x7e,0x73,0x27,0x58,0xbe,0x70,0x0, 0x22,0x74,0x1, 0x22,0x74,0x1, 0x7a, +0xb3,0x27,0x81,0x22,0x7e,0xb3,0x27,0x58,0xbc,0xb9,0x22,0x7e,0x30,0x2, 0xac,0x39, +0x49,0xf1,0x4, 0xc0,0x22,0x6d,0xff,0x9e,0xf7,0x29,0x47,0xbe,0xf7,0x27,0x62,0x22, +0x74,0x2, 0x7a,0xb3,0x34,0x88,0x12,0x4f,0x37,0x2, 0x4c,0xc, 0x7a,0xb3,0x29,0xef, +0x7a,0xb3,0x2a,0xb, 0x22,0xe4,0x7a,0xb3,0x34,0x88,0x7a,0xb3,0x27,0x80,0x74,0x2, +0x2, 0x4c,0xc, 0x7e,0xb3,0x29,0x5b,0xa, 0x2b,0x2d,0x21,0x3e,0x24,0x49,0x22,0x4, +0xc0,0x22,0xa, 0x9, 0x7e,0xb3,0x29,0x5b,0xa, 0x1b,0x2d,0x10,0x3e,0x14,0x49,0x11, +0x4, 0xc0,0x22,0x7e,0xa0,0x1, 0x7e,0x47,0x7, 0x8, 0x7e,0x4, 0x0, 0xc8,0xbe,0x44, +0xfd,0xa8,0x58,0x12,0x7e,0xb3,0x27,0x80,0x60,0x7, 0xe4,0x7a,0xb3,0x27,0x81,0x80, +0x38,0x7e,0xa0,0x5, 0x80,0x33,0x7e,0x34,0xff,0xfb,0xad,0x30,0x7e,0x14,0x0, 0x2, +0x12,0x4c,0x9e,0x8, 0x5, 0x7e,0xa0,0x4, 0x80,0x1f,0x7e,0x34,0xff,0xfc,0x12,0x4c, +0x9c,0x8, 0x5, 0x7e,0xa0,0x3, 0x80,0x11,0x7e,0x34,0xff,0xfd,0x12,0x4c,0x9c,0x8, +0x5, 0x7e,0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0xad,0x30,0x7d,0x21, +0x12,0x16,0xe6,0xbd,0x34,0x22,0xca,0x3b,0x12,0x4f,0x2f,0x38,0x2, 0xa1,0x69,0x7e, +0xc3,0x34,0x8b,0x4c,0xcc,0x78,0x3d,0x7a,0xb3,0x34,0x8b,0xe4,0x7a,0xb3,0x34,0x8d, +0x6c,0xaa,0x80,0x26,0x12,0x4d,0x74,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xd3,0x25,0xce, +0x9, 0xe3,0x25,0xcf,0x7a,0x49,0xd0,0x19,0xe4,0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, +0x8, 0x12,0x27,0x5f,0x59,0x34,0x0, 0x2, 0xb, 0xa0,0x7e,0xb3,0x27,0x58,0xbc,0xba, +0x38,0xd2,0x80,0x7b,0x7c,0xfc,0x6c,0xaa,0x80,0x31,0x12,0x4d,0x74,0x7e,0x49,0xd0, +0x9, 0xe4,0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xf0,0x80,0x1b,0x12,0x27, +0x5f,0x7d,0x23,0x49,0x34,0x0, 0x2, 0x12,0x97,0x30,0xbe,0xf4,0x0, 0x23,0x8, 0x9, +0x74,0x5, 0x19,0xb4,0x0, 0x8, 0x75,0x68,0x1, 0xb, 0xa0,0xbc,0xfa,0x38,0xcb,0x4c, +0xff,0x78,0x2, 0x80,0x26,0x7e,0x73,0x34,0x8d,0xbe,0x70,0x4, 0x40,0x22,0x6c,0xaa, +0x80,0xe, 0x12,0x4d,0x74,0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, 0x68,0x6, 0xb, 0xa0, +0xbc,0xfa,0x38,0xee,0xbc,0xfa,0x78,0x3, 0x75,0x68,0x0, 0x12,0x4d,0x7e,0x80,0xf, +0x7c,0xb7,0x4, 0x7a,0xb3,0x34,0x8d,0x80,0x6, 0x12,0x4d,0x7e,0x75,0x68,0x0, 0xe5, +0x68,0xda,0x3b,0x22,0x7e,0x90,0x9, 0xac,0x9a,0x2e,0x44,0x34,0x8e,0x22,0xe4,0x7a, +0xb3,0x34,0x8c,0x7a,0xb3,0x34,0x8b,0x7a,0xb3,0x34,0x8d,0x22,0xca,0x79,0xc2,0x0, +0x7e,0xf0,0x3, 0x7e,0xe3,0x28,0xf5,0x7e,0x34,0x1e,0x44,0x7a,0x37,0x3, 0x0, 0x6c, +0x11,0x80,0x49,0x6c,0x0, 0x80,0x17,0x74,0x2, 0xac,0xb0,0x9, 0x75,0x25,0xce,0xa, +0x37,0xa, 0x21,0x9, 0x52,0x25,0x2f,0x12,0x4f,0x25,0x48,0x7, 0xb, 0x0, 0x12,0x4f, +0x1e,0x38,0xe4,0x12,0x4f,0x1e,0x78,0x22,0xa, 0x11,0x9, 0x71,0x25,0x2f,0xa, 0x37, +0x7e,0x53,0x29,0x5b,0xa, 0x15,0x2d,0x13,0x12,0x4c,0x3c,0xbe,0x17,0x7, 0x10,0x68, +0x9, 0x7c,0xb1,0x6c,0x77,0x6c,0x66,0x12,0x86,0x2b,0xb, 0x10,0x7e,0x73,0x25,0x58, +0xbc,0x71,0x38,0xaf,0x6c,0x11,0x80,0x44,0x6c,0x0, 0x80,0x17,0x74,0x2, 0xac,0xb0, +0x9, 0x75,0x25,0xcf,0xa, 0x37,0xa, 0x21,0x9, 0x52,0x25,0x43,0x12,0x4f,0x25,0x48, +0x7, 0xb, 0x0, 0x12,0x4f,0x1e,0x38,0xe4,0x12,0x4f,0x1e,0x78,0x1d,0xa, 0x11,0x9, +0xa1,0x25,0x43,0x74,0x2, 0xa4,0x49,0x15,0x4, 0xc0,0xbe,0x17,0x7, 0x12,0x68,0xa, +0x7c,0xb1,0x6c,0x77,0x7e,0x60,0x1, 0x12,0x86,0x2b,0xb, 0x10,0x7e,0x73,0x25,0x59, +0xbc,0x71,0x38,0xb4,0x12,0x85,0x8f,0x12,0xd0,0x44,0x38,0x2, 0xe1,0x15,0x12,0xc5, +0x12,0x92,0xb, 0x12,0xc6,0x1, 0x7c,0xbf,0x12,0xb6,0x56,0x4c,0xee,0x68,0xe, 0x7e, +0xa3,0x2, 0xdd,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x2, 0xde,0x70,0x4, 0xd2,0x0, 0x80, +0x25,0xbe,0xe0,0x1, 0x28,0xb, 0xe5,0x69,0xbe,0xb0,0x8, 0x28,0x4, 0xd2,0x0, 0x80, +0x15,0xd2,0x0, 0x7e,0xb3,0x27,0x58,0xbc,0xbe,0x78,0xb, 0x20,0xb, 0x8, 0x4c,0xaa, +0x78,0x4, 0x6c,0xff,0xc2,0x0, 0x20,0x0, 0x5, 0x7c,0xbf,0x12,0xb6,0x56,0x7e,0x8, +0x2, 0xe2,0x12,0xc0,0xbd,0x7a,0xb3,0x2, 0xe1,0xbe,0xb3,0x27,0x58,0x50,0x45,0x7e, +0x33,0x2, 0xe1,0x80,0x31,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x3, 0x2, 0x9, 0x13, +0x3, 0x3, 0x2e,0x37,0x3, 0x0, 0xb, 0x38,0x50,0x7e,0x93,0x29,0x5b,0xac,0x92,0xa, +0x31,0x2d,0x43,0x3e,0x44,0x7e,0x1f,0x12,0x9a,0x2d,0x34,0x1b,0x1a,0x50,0x7c,0xb3, +0x7e,0x70,0x1, 0x12,0x27,0x70,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xc7,0x74,0x1, +0x7a,0xb3,0x2, 0xdf,0x7e,0xa3,0x2, 0xe1,0x7a,0xa3,0x27,0x58,0x74,0x2, 0xa4,0xca, +0x59,0x7e,0x18,0x3, 0x2, 0x7e,0x8, 0x25,0xce,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0xc0, +0x40,0xf5,0x69,0x80,0x6, 0x75,0x69,0x64,0x12,0xc6,0x39,0xda,0x79,0x22,0x7e,0x73, +0x27,0x58,0xbc,0x70,0x22,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x3, 0x22,0x7e, +0xb3,0x27,0x58,0xbe,0xb0,0x0, 0x22,0x74,0x1, 0x7a,0xb3,0x27,0x80,0xe4,0x22,0x6c, +0x77,0x12,0x27,0x70,0x7e,0x70,0x2, 0x22,0x12,0xa9,0xa2,0x12,0x48,0x36,0x12,0xa7, +0xf9,0x2, 0x4f,0x54,0xca,0x3b,0x12,0x27,0xa0,0x7e,0xb3,0x27,0x58,0x60,0x6, 0x7e, +0xb3,0x39,0xfb,0x60,0x9, 0xe4,0x7a,0xb3,0x39,0xfd,0x7a,0xb3,0x39,0x82,0x7e,0xb3, +0x39,0xfb,0x70,0x62,0x6c,0x99,0x80,0x56,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x25,0xce, +0x9, 0xf5,0x25,0xcf,0x7c,0xb9,0x12,0xa9,0x5a,0x40,0x41,0x6c,0xee,0x80,0x35,0x74, +0x2, 0xac,0xbe,0x9, 0xd5,0x39,0x83,0x9, 0xc5,0x39,0x84,0xa, 0x28,0xa, 0x3d,0x12, +0xa2,0xb6,0x78,0x1e,0xa, 0x2f,0xa, 0x3c,0x12,0xa2,0xb6,0x78,0x15,0x7c,0xb9,0x12, +0x8c,0x77,0xbe,0x34,0x3, 0x20,0x58,0xa, 0x12,0x27,0x66,0x7c,0xb8,0x7c,0x7f,0x12, +0x50,0x1, 0xb, 0xe0,0x7e,0x73,0x39,0xfd,0xbc,0x7e,0x38,0xc3,0xb, 0x90,0x7e,0x73, +0x27,0x58,0xbc,0x79,0x38,0xa2,0x7e,0x73,0x39,0x82,0x7a,0x73,0x39,0xfd,0xa, 0x37, +0x3e,0x34,0xca,0x39,0x7e,0x18,0x39,0xbf,0x7e,0x8, 0x39,0x83,0x12,0x1a,0xb, 0x1b, +0xfd,0xe4,0x7a,0xb3,0x39,0xfb,0xda,0x3b,0x22,0x9, 0xb3,0x25,0xce,0x9, 0x73,0x25, +0xcf,0x7c,0x6b,0x7e,0xa3,0x39,0x82,0x7e,0x50,0x2, 0xac,0x5a,0x19,0x62,0x39,0xbf, +0x19,0x72,0x39,0xc0,0x7c,0xba,0x4, 0x7a,0xb3,0x39,0x82,0x22,0x7e,0x8, 0x3b,0xa1, +0x12,0x50,0x50,0x7e,0x8, 0x3b,0xa9,0x12,0x50,0x50,0x12,0x50,0x6c,0x12,0x50,0x65, +0x2, 0x50,0x33,0x7e,0x37,0x3b,0xa1,0xbe,0x34,0x0, 0x0, 0x28,0x12,0x7e,0x73,0x3c, +0x8f,0xbe,0x70,0x5, 0x50,0x9, 0x7e,0xb3,0x3a,0xce,0x70,0x3, 0x12,0x3f,0x62,0x22, +0xb, 0xa, 0x30,0xe5,0x6a,0xa, 0x2b,0xbd,0x32,0x28,0x4, 0x9d,0x32,0x80,0x2, 0x6d, +0x33,0x1b,0xa, 0x30,0x22,0x7e,0x8, 0x3, 0xfb,0x2, 0x50,0x50,0x7e,0x8, 0x2a,0x95, +0x2, 0x50,0x50,0x6c,0x55,0x7e,0x63,0x27,0x67,0xbe,0x60,0x3, 0x40,0x61,0x6c,0x44, +0x6c,0x77,0x7e,0xa0,0xff,0x7e,0x30,0xff,0x6c,0x22,0x80,0x27,0x7e,0x10,0x2, 0xac, +0x12,0x9, 0xb0,0x25,0xce,0xbc,0xb7,0x28,0x2, 0x7c,0x7b,0xbc,0xba,0x50,0x2, 0x7c, +0xab,0x9, 0xb0,0x25,0xcf,0xbc,0xb4,0x28,0x2, 0x7c,0x4b,0xbc,0xb3,0x50,0x2, 0x7c, +0x3b,0xb, 0x20,0x7e,0xb3,0x27,0x58,0xbc,0xb2,0x38,0xd1,0xa, 0x3, 0xb, 0x5, 0xa, +0x14,0xbd,0x10,0x18,0x11,0xa, 0xa, 0x2e,0x4, 0x0, 0x6, 0xa, 0x17,0xbd,0x10,0x48, +0x5, 0x7e,0x50,0x64,0x80,0x10,0xbe,0x50,0x0, 0x28,0xb, 0x1b,0x50,0x80,0x7, 0xbe, +0x50,0x0, 0x28,0x2, 0x1b,0x50,0xbe,0x50,0x0, 0x28,0x4, 0xd2,0xe, 0x80,0x2, 0xc2, +0xe, 0x7a,0x63,0x27,0x68,0x7e,0x63,0x28,0xf4,0x7a,0x63,0x28,0xf5,0xe4,0x7a,0xb3, +0x28,0xf8,0x22,0x7e,0x37,0x3c,0x70,0xb, 0x34,0x7a,0x37,0x3c,0x70,0x7e,0x37,0x3c, +0x72,0xbe,0x37,0x3c,0x70,0x28,0x3, 0x2, 0x51,0x1e,0x22,0x2, 0x51,0x3, 0xe5,0x9a, +0x60,0x5, 0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b, +0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x12,0x51,0x1b,0xd0, +0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda, +0x6b,0xda,0x7b,0x32,0xe4,0x12,0x53,0xb2,0x12,0xc9,0x6e,0x12,0x57,0xe7,0x12,0x57, +0xe0,0x12,0x3a,0x2d,0x12,0xc8,0xae,0x12,0xc9,0x85,0x12,0x0, 0xa, 0x12,0xc9,0x91, +0x12,0x53,0x3d,0x12,0xc9,0xa1,0xd2,0xaf,0x12,0xc9,0x0, 0x12,0x51,0xa2,0x12,0x3a, +0x79,0x12,0x53,0xe3,0x7e,0x8, 0x3c,0x74,0x12,0x53,0x8c,0x90,0x60,0x50,0xe4,0x93, +0xca,0xb8,0x90,0x60,0x51,0xe4,0x93,0x7c,0x7b,0x7e,0x24,0xff,0xff,0xda,0xb8,0x2, +0x12,0x34,0xd2,0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13,0xa9,0xd1,0xb4,0xa9, +0xc0,0xb4,0x12,0x53,0x2d,0xe4,0x12,0x51,0xc5,0x2, 0x51,0xbc,0xa9,0xc5,0xca,0xe4, +0x7a,0xb3,0x34,0x4f,0x22,0xca,0xf8,0x7c,0xfb,0x74,0x2, 0x12,0x52,0x44,0x4c,0xff, +0x78,0x5, 0x5e,0x70,0xdf,0x80,0x3, 0x4e,0x70,0x20,0x74,0x2, 0x12,0x51,0xe6,0xda, +0xf8,0x22,0x74,0x6, 0x7d,0x30,0x7d,0x23,0x7c,0x6b,0xa, 0x14,0x7c,0x73,0x7d,0x52, +0x7c,0xab,0x7e,0xb3,0x34,0x4f,0xb4,0xa5,0x3c,0x12,0x52,0xd8,0x75,0xb5,0x1, 0xa9, +0x36,0xb3,0xfc,0x12,0x52,0x3d,0xa9,0x36,0xb3,0xfc,0x12,0x52,0x3d,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x71, +0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0xa1,0xb5,0xa9,0x36,0xb3,0xfc,0xa9, +0xc6,0xb3,0xa9,0xd2,0xb4,0x22,0x74,0x4, 0x7d,0x30,0x2, 0x51,0xe6,0xa9,0xc6,0xb3, +0x75,0xb5,0x0, 0x22,0x7c,0x6b,0x6c,0x77,0x6c,0xaa,0x7e,0xb3,0x34,0x4f,0xb4,0xa5, +0x46,0x12,0x52,0xd8,0x75,0xb5,0x5, 0xa9,0x36,0xb3,0xfc,0x12,0x52,0x3d,0xa9,0x36, +0xb3,0xfc,0x12,0x52,0x3d,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0x7a,0x61,0xb5,0xa9, +0x36,0xb3,0xfc,0x12,0x52,0x3d,0xa9,0x36,0xb3,0xfc,0x12,0x52,0x3d,0xa9,0x36,0xb3, +0xfc,0xa9,0xc6,0xb3,0x7e,0x71,0xb5,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6, +0xb3,0x7e,0xa1,0xb5,0xa9,0xd2,0xb4,0x7c,0x47,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x22, +0x7d,0x42,0x7f,0x60,0x7d,0x3, 0x12,0x53,0x2d,0x74,0x2, 0x12,0x52,0x44,0x7d,0xf3, +0x4e,0xf4,0x0, 0x1, 0x4e,0xf4,0x0, 0xa, 0x12,0x52,0xd1,0x7a,0x45,0x36,0x7d,0x30, +0x6d,0x22,0x7f,0x6, 0x12,0x52,0xe9,0x5e,0xf4,0xff,0xfd,0x12,0x52,0xd1,0x2, 0x51, +0xbc,0x74,0x2, 0x7d,0x3f,0x2, 0x51,0xe6,0xa9,0xc2,0xb4,0xa9,0xc6,0xb3,0x22,0x74, +0x6, 0x12,0x52,0x44,0x7d,0x3, 0x6c,0x11,0x22,0x12,0x52,0xf7,0x7e,0x35,0x36,0x12, +0xca,0xd, 0xa9,0xd2,0xb4,0xd3,0x22,0x7d,0x52,0xf5,0x3a,0x7c,0xb6,0x7c,0xa5,0xa, +0x44,0xf5,0x39,0x7f,0x21,0xf5,0x38,0xa9,0xc2,0xb4,0x74,0xb, 0x12,0x53,0x22,0xe5, +0x3a,0x12,0x53,0x22,0xe5,0x39,0x12,0x53,0x22,0xe5,0x38,0x12,0x53,0x22,0xe4,0x2, +0x53,0x22,0xf5,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0xa9,0xd5,0xca, +0xa9,0xd1,0xea,0xa9,0xc1,0xea,0x74,0xa5,0x7a,0xb3,0x34,0x4f,0x22,0xe4,0x7a,0xb3, +0x3b,0x4a,0x7e,0x8, 0x36,0xbe,0x12,0xd0,0x8d,0x7e,0x8, 0x36,0xfc,0x7e,0x34,0x0, +0x3e,0x12,0x1a,0x30,0x7e,0x18,0x36,0xbe,0x7a,0x1d,0x14,0x12,0x53,0x6e,0x2, 0x53, +0x61,0x75,0x18,0x0, 0x75,0x1a,0x0, 0x7e,0xb3,0x3b,0x4a,0xf5,0x91,0x22,0x2, 0x53, +0x71,0x90,0x60,0x0, 0xe4,0x93,0x54,0xfe,0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2, +0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2,0xc0,0xd2,0xad,0x22,0xd2,0xc9,0x75,0xf2, +0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5,0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80, +0xb4,0x80,0xf9,0xe5,0xf6,0x12,0xad,0x43,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xed,0xc2, +0xc9,0x22,0xa9,0xc4,0xca,0xa9,0xc5,0xca,0xbe,0xb0,0x8, 0x50,0x3, 0x12,0x80,0x68, +0xa9,0xd0,0xce,0xa9,0xc0,0xc9,0xd2,0x2, 0x12,0x3b,0x83,0xa9,0xc2,0xea,0x75,0xc1, +0x6, 0x75,0xc2,0xc, 0xd2,0x0, 0x12,0xc9,0xe9,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9, +0xc2,0xe1,0x22,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x0, 0x12,0x57,0xee, +0xa9,0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c, +0x20,0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x3b,0x18,0xa9, +0xd0,0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0x7e,0x23,0x29, +0xfc,0x7e,0x33,0x3b,0x7b,0xac,0x23,0x2e,0x14,0x1, 0xf4,0xbe,0x14,0x0, 0xa, 0x50, +0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0x63,0x29,0xfd,0xbe,0x14,0xf, 0x3c,0x40,0x4, 0x7e, +0x14,0xf, 0x3c,0xbe,0x14,0x7, 0x8, 0x40,0x3, 0xe4,0x80,0x2, 0x74,0x1, 0x7a,0xb3, +0x29,0xfd,0x7e,0x73,0x29,0xfd,0xbc,0x76,0x68,0x2, 0xd2,0xf, 0x7e,0x24,0x1, 0xf4, +0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe,0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e,0x1f, +0x3c,0x53,0x69,0x51,0x0, 0x86,0x54,0x1f,0xa, 0x1, 0x12,0x7c,0x78,0x3e,0x4, 0x2d, +0x5, 0x79,0x1, 0x0, 0x86,0x6d,0x0, 0x7e,0x34,0xb8,0x0, 0x7e,0x24,0x0, 0xb, 0x2, +0x17,0x85,0x7e,0xa3,0x0, 0x6b,0xbe,0xa0,0xff,0x68,0x48,0xbe,0xa3,0x2, 0xdc,0x68, +0x42,0x74,0x5, 0xa4,0x12,0x57,0xd7,0x12,0x54,0xe4,0x12,0x57,0x99,0x12,0x54,0xe4, +0x12,0x57,0x90,0x12,0x6b,0x7f,0x50,0x9, 0x7e,0xb3,0x0, 0x6b,0x12,0x57,0xa2,0x80, +0x6, 0x12,0x54,0xe4,0x12,0x56,0x94,0x12,0x54,0xf0,0x12,0x56,0x8d,0x7e,0x73,0x2a, +0x1, 0xa, 0x37,0x7e,0xf, 0x3c,0x5b,0x79,0x30,0x0, 0x1a,0x7e,0x73,0x0, 0x6b,0x7a, +0x73,0x2, 0xdc,0x22,0x7e,0xa3,0x0, 0x6b,0x74,0x5, 0xa4,0x22,0x7a,0xb3,0x29,0xfc, +0x12,0x54,0x1d,0x7a,0x37,0x2a,0x8, 0x22,0x12,0x54,0xec,0x30,0xf, 0xc, 0xc2,0xf, +0x12,0x2f,0xec,0x30,0x0, 0x4, 0xe4,0x12,0xa, 0x66,0x30,0x0, 0x9, 0x12,0xb2,0xe6, +0x12,0x57,0xf7,0x2, 0x6c,0xf, 0x22,0x7e,0xb, 0x70,0x7a,0x73,0x29,0xfc,0x29,0x70, +0x0, 0x4, 0x7a,0x73,0x2a,0x4f,0x29,0x70,0x0, 0x1, 0x7a,0x73,0x2a,0x1, 0x29,0x70, +0x0, 0x3, 0x7a,0x73,0x2a,0xd, 0x12,0x54,0xf0,0x12,0x56,0x8d,0xd2,0x0, 0xc2,0x1, +0x2, 0x33,0xd1,0xca,0xf8,0x7c,0xfb,0x74,0x5, 0xac,0xbf,0x12,0x57,0xd7,0x12,0x57, +0x99,0x12,0x56,0x94,0x12,0x57,0x90,0x7a,0xf3,0x0, 0x6b,0x7c,0xbf,0x12,0x57,0xa2, +0x12,0x54,0xf0,0x74,0x5, 0xac,0xbf,0x9, 0xb5,0x25,0xb, 0x12,0xb3,0x18,0x12,0x1c, +0x45,0xe4,0x7a,0xb3,0x15,0xa1,0x7a,0xb3,0x3a,0x78,0xda,0xf8,0x22,0x7e,0xb3,0x3a, +0x2, 0x60,0x6, 0x14,0x7a,0xb3,0x3a,0x2, 0x22,0x12,0x6c,0x47,0x7e,0xb3,0x3a,0x89, +0x70,0xe, 0x7e,0xb3,0x33,0xff,0xb4,0x1, 0x7, 0xe4,0x12,0x55,0x43,0x12,0xb2,0xa0, +0x12,0x56,0x51,0x12,0xb0,0xfb,0x7e,0xa3,0x3a,0x89,0x7a,0xa3,0x33,0xff,0xbe,0xb0, +0xff,0x68,0x3, 0x2, 0x55,0x43,0x22,0xca,0xf8,0x6c,0xff,0x7e,0x73,0x0, 0x6b,0xbc, +0x7f,0x68,0x2a,0x7e,0x30,0x5, 0xac,0x3f,0x12,0x56,0x2d,0xca,0x39,0x7e,0x30,0x38, +0xac,0x3f,0x12,0x56,0x46,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39, +0x7e,0x30,0x50,0xac,0x3f,0x12,0x56,0x3b,0x12,0x1a,0xb, 0x1b,0xfd,0xb, 0xf0,0xbe, +0xf0,0x4, 0x40,0xc7,0x7e,0x23,0x0, 0x6b,0x7e,0x30,0x5, 0xac,0x23,0x12,0x56,0x2d, +0xca,0x39,0x7e,0x23,0x0, 0x6b,0x7e,0x30,0x38,0xac,0x23,0x12,0x56,0x46,0x12,0x1a, +0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39,0x7e,0x23,0x0, 0x6b,0x7e,0x30,0x50, +0xac,0x23,0x12,0x56,0x3b,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0xf8,0x22,0x2e,0x14,0x25, +0x7, 0x6d,0x0, 0x12,0x55,0x17,0x7e,0x34,0x0, 0x38,0x22,0x2e,0x14,0x1, 0x4c,0x6d, +0x0, 0x7e,0x18,0x2, 0x8c,0x22,0x2e,0x14,0x0, 0x6c,0x6d,0x0, 0x7e,0x18,0x34,0x0, +0x22,0x12,0xb0,0x75,0x2, 0x56,0x57,0x7e,0xb3,0x3a,0x5, 0x60,0xf, 0x74,0x1, 0x7a, +0xb3,0x3a,0xd, 0x7e,0xb3,0x3a,0x7b,0x70,0x3, 0x12,0xb3,0x33,0x7e,0xb3,0x3a,0xd, +0xb4,0x1, 0xc, 0x74,0x3, 0x7a,0xb3,0x32,0xd9,0x7e,0x34,0x14,0x0, 0x80,0x9, 0xe4, +0x7a,0xb3,0x32,0xd9,0x7e,0x34,0xa, 0x0, 0x7a,0x37,0x29,0x4f,0x22,0x7e,0x8, 0x29, +0x5a,0x2, 0x3, 0x8b,0x9, 0x75,0x25,0x9, 0x7a,0x73,0x2a,0xc, 0x22,0xca,0x3b,0x7a, +0xd, 0x2e,0x7c,0xcb,0x7e,0xb3,0x2a,0xa, 0xf5,0x32,0x7e,0xb3,0x29,0xfc,0xf5,0x33, +0x7e,0xd3,0x2a,0x1, 0x7e,0xe3,0x2a,0xc, 0x7e,0xf3,0x2a,0xd, 0x7e,0x34,0x0, 0x38, +0xca,0x39,0x7e,0x18,0x34,0x0, 0x7e,0x8, 0x24,0x2, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e, +0x34,0x0, 0x50,0xca,0x39,0x7e,0x18,0x2, 0x8c,0x7e,0x8, 0x24,0x3a,0x12,0x1a,0xb, +0x1b,0xfd,0x7c,0xbc,0x12,0x57,0xa2,0x74,0x1, 0x7a,0xb3,0x2a,0xa, 0x74,0x5, 0xac, +0xbc,0x12,0x57,0x99,0x74,0x5, 0xac,0xbc,0x12,0x56,0x94,0x74,0x5, 0xac,0xbc,0x12, +0x57,0x90,0x74,0x5, 0xac,0xbc,0x9, 0x75,0x25,0xb, 0xbe,0x73,0x2a,0x4f,0x68,0x6, +0x7a,0x73,0x2a,0x4f,0xd2,0xf, 0xc2,0x0, 0x12,0xd0,0xcb,0x12,0x54,0xf8,0x12,0x37, +0x2d,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x0, 0xe, 0x7e,0x14,0x40,0x0, 0x7d,0x31,0x7e, +0x2f,0x12,0x96,0x7d,0x25,0x7e,0x4, 0xc, 0xd8,0x12,0x69,0x9c,0x12,0xcf,0xfa,0x7a, +0x55,0x34,0x7e,0xd, 0x2e,0x7e,0x18,0xc, 0xd8,0x12,0xac,0xbc,0x12,0xad,0x4d,0xe5, +0x32,0x7a,0xb3,0x2a,0xa, 0xe5,0x33,0x7a,0xb3,0x29,0xfc,0x7a,0xd3,0x2a,0x1, 0x7a, +0xe3,0x2a,0xc, 0x7a,0xf3,0x2a,0xd, 0x7e,0x34,0x0, 0x38,0xca,0x39,0x7e,0x18,0x24, +0x2, 0x7e,0x8, 0x34,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x50,0xca,0x39, +0x7e,0x18,0x24,0x3a,0x7e,0x8, 0x2, 0x8c,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x3b,0x22, +0x9, 0x75,0x25,0xa, 0x7a,0x73,0x2a,0xd, 0x22,0x9, 0x75,0x25,0x8, 0x7a,0x73,0x2a, +0x1, 0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x34,0x0, 0x38,0xca,0x39,0xac,0x7f,0x2e,0x34, +0x0, 0x6c,0x6d,0x22,0x7e,0x8, 0x34,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, +0x50,0xca,0x39,0xac,0x7f,0x2e,0x34,0x1, 0x4c,0x6d,0x22,0x7e,0x8, 0x2, 0x8c,0x12, +0x1a,0xb, 0x1b,0xfd,0xda,0xf8,0x22,0x9, 0x75,0x25,0x7, 0x7a,0x73,0x29,0xfc,0x22, +0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x34,0x3, 0xe8,0x2, 0x1c,0xee,0xa9,0xd0, +0xce,0xa2,0x0, 0xa9,0x95,0xc9,0x22,0x7e,0xb3,0x29,0xfc,0xca,0x3b,0x7c,0xeb,0x6c, +0xff,0x7e,0xc4,0x1, 0xf4,0x7e,0x73,0x3b,0x7b,0xa, 0xb7,0x7e,0xb3,0x29,0xfd,0xf5, +0x34,0x75,0x35,0x4, 0xe4,0x7a,0xb3,0x3a,0xe, 0xa, 0x3e,0xad,0x3b,0x7d,0xa3,0x2d, +0xac,0x6c,0xdd,0x7e,0xa3,0x3a,0xe, 0xbe,0xa1,0x35,0x40,0x2, 0x80,0x19,0xbe,0xa0, +0x0, 0x28,0x19,0x74,0x5, 0xa4,0x9, 0x75,0x25,0x7, 0xbc,0x7e,0x78,0xe, 0xe5,0x35, +0x14,0xbe,0xb3,0x3a,0xe, 0x78,0x5, 0xe4,0x7a,0xb3,0x3a,0xe, 0x7e,0xc3,0x3a,0xe, +0x80,0x3a,0x7e,0xb3,0x3a,0xe, 0x4, 0x7a,0xb3,0x3a,0xe, 0x74,0x5, 0xac,0xbc,0x9, +0x75,0x25,0x7, 0xbc,0x7e,0x68,0x23,0xa, 0xdd,0x19,0xcd,0x3a,0x12,0xa, 0x97,0xad, +0x9b,0x2d,0x9c,0x7c,0xad,0xb, 0xd0,0x7c,0xba,0x7d,0x39,0x7d,0x2a,0x7e,0x31,0x34, +0x12,0x10,0x0, 0xb, 0xf0,0xbe,0xf0,0x3, 0x50,0x8, 0xb, 0xc0,0xe5,0x35,0xbc,0xbc, +0x38,0xc0,0x7a,0xf3,0x3a,0xf, 0xda,0x3b,0x22,0x74,0xa, 0x7a,0xb3,0x29,0x3a,0x74, +0x10,0x7a,0xb3,0x29,0x3b,0x12,0x5f,0xa6,0x7a,0x37,0x29,0x42,0x74,0x28,0x7a,0xb3, +0x29,0x46,0x12,0x5f,0xbd,0x7e,0x34,0x0, 0x64,0x7a,0x37,0x29,0x4d,0xe4,0x7a,0xb3, +0x29,0x51,0x74,0x4, 0x7a,0xb3,0x29,0x52,0x7a,0x37,0x29,0x53,0x7e,0x34,0xa, 0x0, +0x7a,0x37,0x29,0x4f,0xe4,0x7a,0xb3,0x15,0xa2,0x22,0x12,0x59,0xad,0x12,0x5a,0x9b, +0x12,0x0, 0x42,0x12,0x5f,0x7f,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0x44,0x7e,0xf, +0x6, 0x44,0x7e,0x1f,0x6, 0x40,0x12,0x63,0xb6,0x7e,0x18,0x7, 0x1a,0x7a,0x1f,0x12, +0x96,0x7e,0x18,0xc, 0xd8,0x7a,0x1f,0x12,0x9a,0x7e,0xf, 0x12,0x9a,0x7e,0x1f,0x12, +0x96,0x12,0x5f,0xd6,0x12,0x59,0x31,0x12,0x58,0x99,0x12,0x63,0x35,0x12,0x59,0x8a, +0x2, 0x59,0x23,0xe4,0x7a,0xb3,0x34,0x38,0x7a,0xb3,0x34,0x39,0x7a,0xb3,0x34,0x3a, +0x22,0x2, 0x59,0x34,0x7e,0x34,0x0, 0xc8,0x7a,0x37,0x27,0x69,0x7e,0x34,0x2, 0x8a, +0x7a,0x37,0x27,0x6d,0x7e,0x34,0x0, 0x96,0x7a,0x37,0x27,0x6b,0x7e,0x34,0x0, 0x64, +0x7a,0x37,0x27,0x6f,0x7e,0x34,0x0, 0x50,0x7a,0x37,0x27,0x71,0x7e,0x34,0x0, 0x2b, +0x7a,0x37,0x27,0x73,0x7e,0x34,0x0, 0x4, 0x12,0x5f,0x91,0x74,0x1, 0x7a,0xb3,0x27, +0x79,0xe4,0x7a,0xb3,0x27,0x7c,0x12,0x59,0x83,0x3e,0x34,0x7e,0x8, 0x24,0xcb,0xe4, +0x2, 0x1a,0x30,0x90,0x60,0x9a,0x93,0xa, 0x3b,0x22,0x7e,0x8, 0x27,0x82,0x7e,0x34, +0x1, 0xe, 0x74,0xff,0x12,0x1a,0x30,0x12,0x5f,0x9a,0x7e,0x8, 0x28,0x90,0x12,0x45, +0x56,0x7e,0x8, 0x28,0xf4,0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x1a,0x30,0xe4,0x7a,0xb3, +0x3b,0x4a,0x7a,0xb3,0x3b,0x4b,0x90,0x60,0x50,0x93,0x7a,0xb3,0x3b,0x4c,0x90,0x60, +0x51,0xe4,0x93,0x7a,0xb3,0x3b,0x4d,0xe4,0x7a,0xb3,0x3b,0x4e,0x74,0xa, 0x7a,0xb3, +0x3b,0x4f,0xe4,0x7a,0xb3,0x3b,0x50,0x7a,0xb3,0x3b,0x51,0x74,0x1, 0x7a,0xb3,0x3b, +0x53,0x74,0x25,0x7a,0xb3,0x3b,0x57,0x74,0x32,0x7a,0xb3,0x3b,0x58,0x74,0x64,0x7a, +0xb3,0x3b,0x69,0x74,0x4, 0x7a,0xb3,0x3b,0x6a,0xe4,0x7a,0xb3,0x3b,0x56,0x74,0x30, +0x7a,0xb3,0x3b,0x6c,0x74,0x40,0x7a,0xb3,0x3b,0x6b,0x74,0x2, 0x7a,0xb3,0x3b,0x6d, +0x74,0x40,0x7a,0xb3,0x3b,0x68,0xe4,0x7a,0xb3,0x3b,0x63,0x74,0xfa,0x7a,0xb3,0x3b, +0x61,0x74,0x1e,0x7a,0xb3,0x3b,0x62,0x74,0x1, 0x7a,0xb3,0x3b,0x60,0x74,0xe, 0x7a, +0xb3,0x3b,0x5f,0x74,0x1, 0x7a,0xb3,0x3b,0x64,0xe4,0x7a,0xb3,0x3b,0x65,0x7a,0xb3, +0x3b,0x66,0x7e,0x8, 0x3b,0x6e,0x7e,0x34,0x0, 0x2c,0x12,0x1a,0x30,0x74,0x1, 0x7a, +0xb3,0x3b,0x79,0x74,0xf4,0x7a,0xb3,0x3b,0x7a,0x74,0x19,0x7a,0xb3,0x3b,0x7b,0x74, +0x1e,0x7a,0xb3,0x3b,0x7c,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5f,0x76,0x7e,0x8, +0x3b,0x8a,0x12,0x1a,0xb, 0x1b,0xfd,0x74,0x5, 0x7a,0xb3,0x3b,0x97,0x74,0x1, 0x7a, +0xb3,0x3b,0x8e,0x7e,0x34,0x0, 0x28,0xca,0x39,0x7e,0x34,0x61,0xec,0x7e,0x24,0x0, +0xff,0x7e,0x8, 0x25,0x7, 0x12,0x1a,0xb, 0x1b,0xfd,0x22,0xca,0x79,0x90,0x60,0x50, +0xe4,0x93,0x7c,0xab,0x90,0x60,0x51,0xe4,0x93,0x7c,0xeb,0x7e,0xb3,0x29,0x61,0xbc, +0xbe,0x28,0x4, 0x7c,0xfb,0x80,0x2, 0x7c,0xfe,0x7a,0xa3,0x29,0x5a,0x7a,0xe3,0x29, +0x5b,0x7a,0xa3,0x29,0x5e,0x7a,0xe3,0x29,0x5f,0x7a,0xa3,0x29,0x60,0x7a,0xe3,0x29, +0x61,0xe4,0x7a,0xb3,0x29,0x64,0x7a,0xa3,0x29,0x5c,0x7a,0xe3,0x29,0x5d,0x90,0x60, +0x91,0x93,0x7a,0xb3,0x29,0x65,0x90,0x60,0x94,0xe4,0x93,0x7a,0xb3,0x29,0x66,0xa, +0x3a,0xca,0x39,0x7e,0x34,0x60,0x52,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x29,0x67,0x12, +0x1a,0xb, 0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x34,0x60,0x75,0x7e,0x24,0x0, 0xff, +0x7e,0x8, 0x29,0x8a,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e, +0x34,0x60,0xd8,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0xe, 0x12,0x1a,0xb, 0x1b,0xfd, +0x12,0x5c,0x29,0x12,0x63,0x6d,0x12,0x5f,0x28,0x74,0x1, 0x12,0x2c,0x7, 0xe4,0x7a, +0xb3,0x29,0xee,0x7a,0xb3,0x29,0xef,0x12,0x5c,0xbf,0x7a,0x37,0x29,0xfa,0x74,0x3, +0x7a,0xb3,0x29,0xf0,0xe4,0x7a,0xb3,0x29,0xf1,0x74,0x2, 0x7a,0xb3,0x29,0xf2,0x7e, +0x34,0x0, 0xc8,0x7a,0x37,0x29,0xf4,0x74,0x4, 0x7a,0xb3,0x29,0xf3,0x7e,0x34,0x0, +0xf, 0x7a,0x37,0x29,0xf6,0x7e,0x34,0x20,0x5f,0x7a,0x37,0x29,0xf8,0x74,0x20,0x7a, +0xb3,0x2a,0x4f,0x74,0x1, 0x7a,0xb3,0x29,0xfd,0x74,0x20,0x7a,0xb3,0x29,0xfe,0x74, +0x4, 0x7a,0xb3,0x2a,0x0, 0x74,0x1e,0x12,0x54,0xec,0xe4,0x7a,0xb3,0x2a,0xa, 0x7a, +0xb3,0x2a,0xb, 0x7e,0x34,0x1, 0x90,0x7a,0x37,0x2a,0x6, 0x74,0x1, 0x7a,0xb3,0x29, +0xff,0x12,0x37,0xdb,0x74,0x30,0x7a,0xb3,0x2a,0xc, 0x6d,0x33,0x7a,0x37,0x2a,0x2, +0x7a,0x37,0x2a,0x4, 0x74,0x2, 0x7a,0xb3,0x2a,0x1, 0x7e,0x34,0x0, 0x30,0x7a,0x37, +0x2a,0x57,0x74,0x4, 0x7a,0xb3,0x2a,0x54,0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x2a,0x55, +0xe4,0x7a,0xb3,0x2a,0x53,0x7e,0x34,0x4, 0x6d,0x7a,0x37,0x2a,0x59,0x74,0x1, 0x7a, +0xb3,0x2a,0x50,0x74,0x5, 0x7a,0xb3,0x2a,0x51,0xe4,0x7a,0xb3,0x2a,0x52,0x74,0x1, +0x7a,0xb3,0x2a,0x4d,0xe4,0x7a,0xb3,0x2a,0x4e,0x7e,0x34,0x19,0xad,0x7a,0x37,0x2a, +0x5b,0xa, 0x3e,0xca,0x39,0x7e,0x34,0x60,0xfb,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a, +0x31,0x12,0x1a,0xb, 0x1b,0xfd,0xda,0x79,0x22,0x12,0x5f,0x88,0x12,0x5c,0x8b,0x90, +0x60,0x50,0xe4,0x93,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x29,0x67,0x6d,0x0, 0x9, 0xb3, +0x29,0x66,0x12,0x5c,0x72,0xa, 0x3b,0x7d,0x13,0x2e,0x14,0x2a,0xe, 0x6d,0x0, 0x9, +0xb3,0x2a,0xd, 0x12,0x5c,0x72,0xa, 0x1b,0x2e,0x14,0x29,0x69,0x12,0x5c,0x7f,0xe5, +0x25,0x12,0x5c,0x76,0xa, 0x1b,0x2e,0x14,0x2a,0x10,0x12,0x5c,0x7f,0xe5,0x24,0x2, +0x1a,0x30,0x7e,0x34,0x0, 0x2, 0x12,0x1a,0x30,0x90,0x60,0x50,0xe4,0x93,0x22,0x6d, +0x0, 0x90,0x60,0x91,0xe4,0x93,0xa, 0x3b,0x1b,0x35,0x22,0x6c,0xaa,0x6c,0x99,0x80, +0xc, 0xa, 0xf9,0x9, 0xbf,0x29,0x67,0xbc,0xba,0x68,0x7, 0xb, 0x90,0x12,0x5c,0xb7, +0x38,0xef,0x12,0x5c,0xb7,0x68,0x7, 0xb, 0xa0,0xbe,0xa0,0x23,0x40,0xdf,0x7a,0xb, +0xa0,0x74,0x6e,0x7a,0x1b,0xb0,0x22,0x90,0x60,0x50,0xe4,0x93,0xbc,0xb9,0x22,0x6d, +0x33,0x6c,0xaa,0x80,0x14,0xa, 0x2a,0x9, 0xb2,0x29,0xc9,0x54,0x1, 0x78,0x5, 0x4e, +0x70,0x1, 0x80,0x3, 0x4e,0x70,0x10,0xb, 0xa0,0x7e,0x53,0x29,0x61,0xbc,0x5a,0x38, +0xe4,0x6c,0xaa,0x80,0x1f,0xa, 0x2a,0x9, 0xb2,0x29,0xa6,0xbe,0xb0,0xd, 0x38,0x5, +0x4e,0x70,0xc0,0x80,0xd, 0xbe,0xb0,0x1b,0x38,0x5, 0x4e,0x60,0x8, 0x80,0x3, 0x4e, +0x60,0x50,0xb, 0xa0,0x12,0x5d,0xa, 0x38,0xdc,0x22,0x7e,0xb3,0x29,0x60,0xbc,0xba, +0x22,0xca,0x3b,0x7e,0xb4,0x7f,0xff,0x7d,0xab,0x7d,0x8b,0x6d,0x22,0x7d,0x32,0x7d, +0x9b,0x75,0x24,0x0, 0x6c,0x99,0x7e,0x78,0x4, 0xc0,0x7e,0x8, 0x5, 0x20,0xe4,0x7a, +0xb3,0x7, 0x18,0x7a,0xb3,0x7, 0x19,0x7a,0xb3,0x25,0xca,0x7a,0xb3,0x25,0xcc,0x7a, +0xb3,0x25,0xcb,0x7a,0xb3,0x25,0xcd,0x6c,0xaa,0x80,0x5f,0x12,0x5e,0x86,0xb, 0x6a, +0xc0,0xbd,0xca,0x58,0x2, 0x7d,0xac,0xbd,0xc3,0x8, 0x2, 0x7d,0x3c,0x2d,0x71,0x7d, +0x60,0xb, 0x3a,0xd0,0xbd,0xd9,0x58,0x2, 0x7d,0x9d,0x7e,0x67,0x29,0x40,0x7e,0x74, +0x0, 0x3, 0xad,0x76,0xbd,0xc7,0x8, 0x2, 0x5, 0x24,0x12,0x5e,0x73,0xb, 0x3a,0xd0, +0xbd,0xcd,0x8, 0xb, 0x7e,0xb3,0x25,0xcb,0x4, 0x7a,0xb3,0x25,0xcb,0x80,0x19,0x12, +0x5e,0x7c,0xb, 0x3a,0xc0,0x6e,0xd4,0xff,0xff,0xb, 0xd4,0xbd,0xcd,0x58,0x9, 0x7e, +0xb3,0x25,0xcd,0x4, 0x7a,0xb3,0x25,0xcd,0xb, 0xa0,0x7e,0xb3,0x29,0x61,0xbc,0xba, +0x38,0x99,0x7a,0xa7,0x7, 0xe, 0x7a,0x37,0x7, 0x12,0xe5,0x24,0x7a,0xb3,0x7, 0x19, +0x7a,0x97,0x7, 0x16,0x12,0x5e,0x6b,0x2d,0xf5,0x6c,0xaa,0x80,0x50,0x12,0x5e,0x86, +0xb, 0x6a,0xd0,0xbd,0xd8,0x58,0x2, 0x7d,0x8d,0xbd,0xd2,0x8, 0x2, 0x7d,0x2d,0x7e, +0x67,0x29,0x3e,0x7e,0x74,0x0, 0x3, 0xad,0x76,0xbd,0xd7,0x8, 0x2, 0xb, 0x90,0x12, +0x5e,0x73,0xb, 0x3a,0xc0,0xbd,0xdc,0x8, 0xb, 0x7e,0xb3,0x25,0xca,0x4, 0x7a,0xb3, +0x25,0xca,0x80,0x17,0x12,0x5e,0x7c,0xb, 0x3a,0xd0,0x6d,0x99,0x9d,0x9c,0xbd,0xd9, +0x58,0x9, 0x7e,0xb3,0x25,0xcc,0x4, 0x7a,0xb3,0x25,0xcc,0xb, 0xa0,0x12,0x5d,0xa, +0x38,0xab,0x7a,0x87,0x7, 0xc, 0x7a,0x27,0x7, 0x10,0x7a,0x93,0x7, 0x18,0x12,0x5e, +0x6b,0x2d,0x15,0x6c,0xaa,0x80,0x14,0x7e,0x90,0x2, 0xac,0x9a,0x7f,0x70,0x2d,0xf4, +0xb, 0x7a,0x90,0xbd,0x9b,0x58,0x2, 0x7d,0xb9,0xb, 0xa0,0x12,0x5d,0xa, 0x38,0xe7, +0x7a,0xb7,0x7, 0x14,0xbd,0x8a,0x58,0x2, 0x7d,0xa8,0x7a,0xa7,0x7, 0x8, 0xbd,0x32, +0x58,0x2, 0x7d,0x32,0x7a,0x37,0x7, 0xa, 0xda,0x3b,0x22,0x7e,0xa3,0x29,0x61,0x74, +0x2, 0xa4,0x22,0x7e,0x74,0x62,0x27,0x7e,0x64,0x0, 0xff,0x22,0x7e,0xf0,0x2, 0xac, +0xfa,0x2d,0x7f,0x7d,0x6e,0x22,0x7e,0xf0,0x2, 0xac,0xfa,0x7f,0x67,0x2d,0xd7,0x22, +0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x24,0x7e,0x35,0x28,0x7a,0x35,0x2f,0x7e,0xd, 0x24, +0x7f,0x13,0x12,0xa9,0xb9,0x7e,0x35,0x28,0x7a,0x35,0x2a,0x12,0x5e,0x6b,0x7e,0xd, +0x24,0x2d,0x15,0x7f,0x13,0x2d,0x35,0x12,0xaa,0x76,0xda,0x3b,0x22,0x7e,0x37,0x29, +0x3c,0x1e,0x34,0x7a,0x35,0x28,0x7e,0x8, 0x4, 0xc0,0x7e,0x18,0x4, 0x0, 0x12,0x5e, +0x90,0x7e,0x37,0x27,0x6d,0xe, 0x34,0x7a,0x35,0x28,0x7e,0x8, 0x5, 0x20,0x7e,0x18, +0x4, 0x60,0x12,0x5e,0x90,0x12,0x5e,0xfc,0x2, 0x5e,0xeb,0xe4,0x7a,0xb3,0x3, 0xfe, +0x7e,0xb3,0x27,0x7c,0x60,0x5, 0xe4,0x7a,0xb3,0x3, 0xfe,0x22,0xca,0x3b,0x7e,0xf3, +0x29,0x5b,0x7e,0xe3,0x29,0x5c,0x7e,0xd3,0x29,0x5d,0x6c,0xcc,0x80,0x13,0x7c,0x7c, +0xac,0x7f,0x3e,0x34,0x7e,0xf, 0x12,0x9a,0x2d,0x13,0x7c,0xbd,0x12,0xab,0x9b,0xb, +0xc0,0xbc,0xec,0x38,0xe9,0xda,0x3b,0x22,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x34, +0x61,0x2d,0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x2a,0x5d,0x12,0x1a,0xb, 0x1b,0xfd,0x7e, +0x34,0x29,0xa, 0x7a,0x37,0x2a,0x63,0xe4,0x7a,0xb3,0x2a,0x61,0x7a,0xb3,0x2a,0x62, +0x7e,0x34,0x0, 0x4, 0xca,0x39,0x12,0x5f,0x76,0x7e,0x8, 0x24,0xc2,0x12,0x1a,0xb, +0x1b,0xfd,0x7e,0x34,0x2a,0x65,0x7a,0x37,0x24,0xc8,0xe4,0x7a,0xb3,0x24,0xc6,0x74, +0x1, 0x7a,0xb3,0x24,0xc7,0x22,0x7e,0x34,0x61,0x29,0x7e,0x24,0x0, 0xff,0x22,0x7e, +0x18,0x5, 0x80,0x7a,0x1f,0x6, 0x40,0x22,0x7e,0x8, 0x0, 0x25,0x7e,0x18,0x0, 0x24, +0x22,0x7a,0x37,0x27,0x75,0x7a,0x37,0x27,0x77,0x22,0x7e,0x8, 0x32,0xcd,0x7e,0x34, +0x0, 0xd, 0xe4,0x2, 0x1a,0x30,0x7e,0x34,0x0, 0xc8,0x7a,0x37,0x29,0x3c,0x7a,0x37, +0x29,0x3e,0x7a,0x37,0x29,0x40,0x22,0x12,0x5f,0xbd,0x2, 0x5f,0xa6,0x7e,0x34,0x0, +0x96,0x7a,0x37,0x29,0x47,0x7e,0x34,0x0, 0x82,0x7a,0x37,0x29,0x49,0x7e,0x34,0xff, +0x6a,0x7a,0x37,0x29,0x4b,0x22,0x7f,0x60,0x7e,0xa3,0x29,0x5a,0x7e,0xb3,0x29,0x5b, +0xa4,0x7d,0xf5,0x3e,0xf4,0x7f,0x1, 0x7d,0x3f,0xe4,0x12,0x1a,0x30,0x7f,0x6, 0x7d, +0x3f,0x12,0x1a,0x30,0x7a,0xb3,0x15,0xa1,0x22,0x7e,0x8, 0x29,0x5a,0x2, 0x0, 0x2e, +0x70,0x8f,0x0, 0xff,0x51,0xae,0x37,0xc8,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x34,0x36,0x31,0x1, 0xd1,0x53,0x34,0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x7, 0xf8,0x44,0x31,0x53,0x5f,0x74,0x69,0x61,0x6e,0x6d,0x61,0x0, 0x0, 0x0, 0x0, +0xd, 0x1b,0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11, +0x10,0xf, 0xe, 0x9, 0x1, 0xa, 0x2, 0xb, 0x3, 0xc, 0x4, 0xd, 0x5, 0x6, 0x7, 0x8, +0x0, 0x5, 0x0, 0x4, 0xff,0x14,0x1c,0x2, 0xdf,0xa, 0x1e,0xa, 0x64,0x28,0x10,0x0, +0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x1, 0x19,0x1e,0x1, 0xf4,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e, +0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x6e,0x0, 0x4, 0x30,0x20,0x1, 0x20,0x2, 0x0, 0x0, +0x0, 0x0, 0x1, 0x90,0x40,0x40,0xd, 0x1b,0x28,0x11,0x10,0x6, 0x80,0x11,0x10,0x6, +0x78,0x8, 0x10,0x4, 0x20,0x1, 0x0, 0x4, 0x38,0x49,0x47,0x2, 0xcc,0x2, 0xe0,0x1, +0x52,0x1, 0x54,0x8, 0xe8,0x47,0x47,0x2, 0x4a,0x2, 0x36,0x1, 0x56,0x1, 0x57,0x0, +0x96,0x0, 0x82,0x0, 0x96,0x0, 0xc8,0x0, 0x64,0x0, 0xc8,0x0, 0xc8,0xa, 0x0, 0x0, +0xbe,0x6, 0x10,0x1e,0x32,0x1, 0xf, 0xb, 0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x7, 0xf7,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x1, +0x0, 0x1, 0x54,0x1, 0x0, 0x7, 0x1, 0x51,0x1, 0x14,0x0, 0x37,0x1, 0x1, 0x12,0x0, +0x5, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +0x96,0x2, 0x8a,0x0, 0x50,0x0, 0x2b,0x0, 0x4, 0x0, 0x4, 0x1, 0x4, 0x1, 0x90,0x0, +0xf0,0x0, 0x64,0x2, 0x58,0x0, 0xc8,0x1, 0x2c,0x1, 0x2c,0x4, 0x1e,0x2, 0x30,0x40, +0x20,0x13,0x2, 0x2d,0x40,0x20,0x2c,0x2, 0x34,0x40,0x20,0x32,0x2, 0x37,0x40,0x20, +0x1e,0x2, 0x30,0x40,0x20,0x1e,0x2, 0x30,0x40,0x20,0x1e,0x2, 0x30,0x40,0x20,0x1e, +0x2, 0x30,0x40,0x20,0x4, 0x5, 0x10,0x11,0x12,0x13,0x14,0x4, 0x0, 0x96,0x1, 0x90, +0x28,0x0, 0x78,0x1, 0x5e,0x0, 0x64,0x0, 0x64,0x0, 0x64,0x0, 0x64,0xb, 0xb8,0x8, +0x5, 0x6, 0x80,0x1, 0x90,0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20, +0x4, 0xb0,0x3, 0x20,0x1, 0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x1, 0x2c,0x1, 0x18,0x1, +0x90,0x1, 0x90,0x1, 0x90,0x1, 0x90,0x1, 0x2c,0x1, 0x90,0x1, 0x7c,0x1, 0x7c,0x0, +0x50,0x0, 0x46,0x0, 0x78,0x0, 0x78,0x0, 0x78,0x1, 0x18,0x1, 0x18,0xf, 0x5, 0x0, +0x64,0x3, 0xd4,0x0, 0x50,0x8, 0x98,0x0, 0x23,0x1, 0xf4,0x1, 0xf4,0x3, 0x20,0x0, +0x14,0x0, 0x53,0x0, 0x1e,0x0, 0x80,0x1, 0xe, 0x1, 0x1d,0x0, 0x3c,0x3, 0xe8,0x2, +0x3a,0x0, 0x87,0x0, 0x3c,0x3, 0xe8,0x0, 0x20,0x4, 0x18,0x0, 0x0, 0x8, 0xe8,0x0, +0x64,0x0, 0xa0,0x0, 0xa0,0x13,0x88,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, +0x0, 0xc, 0xb, 0x5, 0x5, 0x8, 0x8, 0x6, 0x6, 0xc, 0x64,0xc8,0x7e,0x54,0x0, 0x54, +0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69,0x22,0x0, 0x2, 0xb, 0x2a,0x10,0x7a, +0x1d,0x26,0x7a,0x15,0x24,0x7e,0x34,0x0, 0x20,0x7e,0x8, 0x0, 0x24,0x7e,0x24,0x0, +0x6, 0x12,0x52,0xa0,0x74,0x25,0x7a,0xb3,0x3a,0x7e,0x74,0x20,0x7a,0xb3,0x3a,0x7f, +0x74,0xc, 0x7a,0xb3,0x3a,0x80,0x7a,0xb3,0x3a,0x81,0x7a,0xb3,0x3a,0x82,0x74,0xa0, +0x7a,0xb3,0x3a,0x83,0x7e,0x34,0x0, 0x6a,0xca,0x39,0x7e,0x34,0x61,0x65,0x7e,0x24, +0x0, 0xff,0x7e,0x8, 0x3a,0x84,0x12,0x1a,0xb, 0x1b,0xfd,0xe5,0x25,0x7a,0xb3,0x3a, +0xaf,0xe5,0x28,0x7a,0xb3,0x3a,0x9e,0xe4,0x7a,0xb3,0x3a,0xb2,0x7a,0xb3,0x3a,0xb3, +0x7a,0xb3,0x3a,0xb4,0x22,0x7e,0x8, 0x25,0x2f,0x7e,0x34,0x2, 0x3a,0xe4,0x12,0x1a, +0x30,0x7e,0x8, 0x25,0x60,0x7e,0x34,0x0, 0xc8,0x74,0xff,0x12,0x1a,0x30,0x7e,0x8, +0x25,0x88,0x7e,0x34,0x0, 0xc8,0x12,0x1a,0x30,0x90,0x60,0x9a,0xe4,0x93,0x7c,0x7b, +0x74,0x9, 0xac,0x7b,0x7e,0x8, 0x26,0x4a,0x74,0xff,0x2, 0x1a,0x30,0xca,0xf8,0x7e, +0x73,0x29,0x65,0xa, 0x47,0x7e,0x73,0x29,0x5e,0xa, 0x57,0x2d,0x54,0x7e,0xa3,0x29, +0x60,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x29,0x5f,0x7e,0xa3,0x29,0x61,0xbc, +0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0x1, 0x7e,0x8, 0x29,0xa6,0x7e,0x18,0x29,0x67, +0x12,0xd, 0xd9,0x75,0x25,0x1, 0x7e,0x8, 0x29,0xc9,0x7e,0x18,0x29,0x8a,0x7c,0xbf, +0x12,0xf, 0x9c,0xda,0xf8,0x22,0x7f,0x70,0x7e,0x33,0x29,0x61,0xa, 0x43,0x7e,0x33, +0x29,0x60,0xa, 0x53,0x2d,0x54,0x3e,0x54,0x7c,0xab,0xe4,0x7a,0xb3,0x15,0xa0,0x7f, +0x1, 0xa, 0x3a,0x12,0x1a,0x30,0x7f,0x7, 0xa, 0x3a,0x2, 0x1a,0x30,0xca,0xd8,0xca, +0x79,0x7c,0xfb,0x7f,0x51,0x7f,0x40,0x7f,0x15,0x12,0x63,0xb6,0x12,0x5f,0xf9,0x7e, +0xe0,0x1, 0x12,0x65,0xee,0x30,0x1b,0xfd,0x74,0x2, 0x12,0x0, 0x1e,0x7f,0x4, 0x12, +0x66,0xc6,0x6c,0xdd,0x80,0x18,0x74,0x2, 0xac,0xbd,0x7f,0x14,0x2d,0x35,0xb, 0x1a, +0x20,0x74,0x2, 0xac,0xbd,0x7f,0x5, 0x2d,0x15,0x12,0x67,0xd8,0xb, 0xd0,0x7e,0x73, +0x29,0x61,0xa, 0x7, 0x7e,0x63,0x29,0x60,0xa, 0x16,0x2d,0x10,0xa, 0x2d,0xbd,0x21, +0x48,0xd4,0x1b,0xe0,0x78,0xbc,0x7f,0x5, 0x7c,0xbf,0x2e,0x73,0x29,0x60,0x12,0x66, +0xe0,0xda,0x79,0xda,0xd8,0x22,0x7e,0xb3,0x29,0xef,0x70,0x41,0x12,0x67,0xe1,0x50, +0xfb,0xe4,0x6c,0x77,0x6c,0x66,0x12,0x64,0x8e,0x7e,0x8, 0x6, 0x48,0x7e,0x1f,0x6, +0x40,0x7e,0xb3,0x2a,0x5f,0x12,0x63,0xdd,0x74,0x1, 0x7e,0x70,0x1, 0x7e,0x60,0x1, +0x12,0x64,0x8e,0x7e,0x8, 0x6, 0xa8,0x7e,0x1f,0x6, 0x40,0x7e,0xb3,0x24,0xc4,0x12, +0x63,0xdd,0x74,0x2, 0x7a,0xb3,0x29,0xef,0xe4,0x7a,0xb3,0x15,0xa0,0x22,0x7c,0x96, +0x7c,0xa7,0x12,0x2c,0x7, 0x7c,0xba,0x12,0x13,0xc7,0x74,0xa, 0x12,0x3b,0x18,0x7c, +0xb9,0x12,0x0, 0x1e,0x2, 0x64,0xa7,0xca,0x3b,0x7e,0xe3,0x29,0x61,0x7e,0xf3,0x29, +0xe7,0x74,0x1, 0x7a,0xb3,0x29,0xe7,0x12,0x37,0xcd,0x12,0x67,0xbf,0x12,0x1e,0xb7, +0x7e,0x17,0x29,0xeb,0x6d,0x0, 0x12,0x1a,0x30,0x7e,0xd0,0x7, 0x12,0x57,0xe7,0x6c, +0xcc,0x80,0x1f,0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb, +0x7c,0x67,0xa, 0x2c,0x2e,0x27,0x29,0xeb,0x7e,0x29,0x70,0x4c,0x76,0x7a,0x29,0x70, +0xb, 0xc0,0x12,0x66,0xad,0xa, 0x3c,0xbd,0x32,0x48,0xd8,0x12,0x65,0xdd,0x30,0x1b, +0xfd,0x12,0x66,0xd6,0x7e,0xb3,0x29,0x60,0x7c,0x7e,0x12,0x66,0xce,0x6c,0xcc,0x80, +0x2a,0x74,0x2, 0xac,0xbc,0x49,0x35,0x6, 0x48,0xbe,0x34,0x15,0x40,0x50,0x1a,0x7e, +0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7c,0xb7,0x64,0xff, +0xa, 0x2c,0x2e,0x27,0x29,0xeb,0x12,0x27,0x97,0xb, 0xc0,0x12,0x66,0xad,0xa, 0x3c, +0xbd,0x32,0x48,0xcd,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0x81,0x12,0x66,0x2f,0x74,0x2, +0x12,0x67,0xc7,0x12,0x65,0x65,0x74,0x2, 0x12,0x0, 0x1e,0x7a,0xf3,0x29,0xe7,0x12, +0x37,0xcd,0xda,0x3b,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x24,0x2, 0x12,0x67,0xcf, +0x7e,0xa3,0x29,0x60,0x7e,0x73,0x29,0x61,0x6c,0xee,0x80,0x1d,0xa, 0x2e,0x9, 0x62, +0x29,0xc9,0xa, 0x26,0x12,0x27,0xfe,0x7c,0x6b,0xbe,0x60,0x1c,0x50,0x9, 0xa, 0x2e, +0x12,0x66,0xbc,0x19,0xb2,0x24,0x2, 0xb, 0xe0,0xbc,0x7e,0x38,0xdf,0x6c,0xee,0x80, +0x1a,0xa, 0x2e,0x9, 0x62,0x29,0xa6,0xbe,0x60,0x23,0x50,0xd, 0xa, 0x1e,0xa, 0x27, +0x2d,0x21,0x12,0x66,0xbc,0x19,0xb2,0x24,0x1e,0xb, 0xe0,0xbc,0xae,0x38,0xe2,0x6c, +0xee,0x7e,0x30,0xe, 0xac,0x3e,0x2e,0x14,0x24,0x2, 0x6d,0x0, 0x7c,0xbf,0x7c,0x7e, +0x12,0x11,0xba,0xb, 0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x74,0x2, 0x12, +0x0, 0x1e,0x7e,0xb3,0x29,0xe9,0x12,0x65,0x65,0x74,0x2, 0x12,0x0, 0x1e,0x74,0x5, +0x7e,0x70,0x9b,0x12,0x13,0x2c,0x12,0x66,0x0, 0x7e,0xb3,0x29,0xe9,0x2, 0xe, 0x94, +0x6c,0xaa,0x80,0x22,0xa, 0x3a,0x9, 0x73,0x29,0xc9,0x2e,0x34,0x19,0xc5,0x12,0x80, +0xef,0x7c,0x7b,0xa, 0x47,0x7e,0x50,0x2, 0xac,0x5a,0x7e,0xf, 0x3c,0x53,0x2d,0x12, +0x79,0x40,0x0, 0x48,0xb, 0xa0,0x7e,0x63,0x29,0x61,0xbc,0x6a,0x38,0xd6,0x22,0xca, +0xd8,0xca,0x79,0x7e,0xf0,0xa, 0x74,0x1, 0x7a,0xb3,0x29,0xe7,0x12,0x1e,0xb7,0x7c, +0xe7,0x80,0x5d,0x12,0x57,0xe7,0x12,0x65,0xdd,0x30,0x1b,0xfd,0x12,0x66,0xd6,0x12, +0x66,0xc6,0x6c,0xdd,0x80,0x3d,0x7e,0x50,0x2, 0xac,0x5d,0x49,0x32,0x6, 0x48,0xbe, +0x34,0x14,0x78,0x50,0x14,0xa, 0x1d,0x2e,0x17,0x29,0xeb,0x7e,0x19,0xb0,0xbe,0xb0, +0x0, 0x28,0x1e,0x14,0x7a,0x19,0xb0,0x80,0x18,0xbe,0x34,0x19,0x28,0x28,0x10,0xa, +0x3d,0x12,0x2d,0x5d,0xbe,0xb0,0xff,0x68,0x8, 0x4, 0x7a,0x39,0xb0,0x80,0x2, 0x1b, +0xe0,0xb, 0xd0,0x12,0x66,0xad,0xa, 0x3d,0xbd,0x32,0x48,0xba,0x4c,0xee,0x68,0x8, +0x7c,0xaf,0x1b,0xf0,0x4c,0xaa,0x78,0x9b,0xda,0x79,0xda,0xd8,0x22,0x7e,0x73,0x29, +0x61,0xa, 0x37,0x7e,0x53,0x29,0x60,0xa, 0x25,0x2d,0x23,0x22,0x2e,0x27,0x29,0xeb, +0x7e,0x29,0xb0,0xa, 0x26,0x22,0x7e,0xb3,0x29,0x60,0x7e,0x73,0x29,0x61,0x12,0x10, +0xee,0x74,0x2, 0x2, 0x0, 0x1e,0x74,0x2, 0x12,0x0, 0x1e,0x7e,0x8, 0x6, 0x48,0x22, +0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7f,0x70,0x12,0xcc,0xcd,0x7c,0xeb,0x6c,0xdd,0x80, +0x20,0x74,0x2, 0xac,0xbd,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x30,0x6d,0x22,0x74,0x4, +0x2f,0x11,0x14,0x78,0xfb,0xa, 0x1e,0x6d,0x0, 0x12,0x17,0x34,0x1b,0x6a,0x30,0xb, +0xd0,0xbc,0xfd,0x38,0xdc,0xda,0x79,0xda,0xd8,0x22,0xca,0x79,0x7f,0x51,0x7f,0x40, +0x7e,0xa3,0x29,0x61,0xa, 0x3a,0x7e,0xa3,0x29,0x60,0xa, 0x7a,0x2d,0x73,0x7e,0xd, +0x29,0x7c,0x7f,0x12,0x66,0xe0,0xa, 0x3f,0x3e,0x34,0xca,0x39,0x7e,0x1d,0x29,0x7f, +0x4, 0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0xb3,0x29,0xee,0xb4,0x1, 0x22,0x6c,0xaa,0x80, +0x1a,0x7e,0x70,0x2, 0xac,0x7a,0x7f,0x5, 0x2d,0x13,0xb, 0xa, 0x20,0x7f,0x4, 0x2d, +0x13,0xb, 0xa, 0x30,0x9d,0x32,0x1b,0xa, 0x30,0xb, 0xa0,0xbc,0xfa,0x38,0xe2,0xda, +0x79,0x22,0x7e,0xa3,0x2e,0x86,0x7e,0x70,0x4, 0xac,0x7a,0xb, 0x34,0xbe,0x37,0x3b, +0x9b,0x40,0x39,0x7e,0x37,0x3b,0x9b,0xb, 0x34,0x7a,0x37,0x3b,0x9b,0xbe,0x34,0x0, +0x1, 0x78,0x5, 0x7e,0xb3,0x3a,0xd1,0x22,0xbe,0x34,0x0, 0x2, 0x78,0x3, 0x7c,0xba, +0x22,0xbe,0x34,0x0, 0x2, 0x50,0x9, 0x7d,0x23,0x1b,0x25,0x9, 0xb2,0x33,0xf8,0x22, +0x9e,0x34,0x0, 0x3, 0x2e,0x37,0x2a,0x97,0x7e,0x39,0xb0,0x22,0x74,0xff,0x22,0x6d, +0x33,0xe4,0x6c,0x55,0x2, 0x13,0x1, 0x12,0x0, 0x1e,0x7e,0xb3,0x29,0xe9,0x22,0x7e, +0x34,0x0, 0x46,0x74,0x3f,0x2, 0x1a,0x30,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30, +0x22,0x7e,0xb3,0x34,0x3a,0xb4,0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x12,0x67,0xe1,0x50, +0xfb,0x22,0x7e,0xa3,0x3b,0x49,0x7c,0xba,0x4, 0x7a,0xb3,0x3b,0x49,0x7a,0xa3,0x3a, +0x8f,0x22,0xca,0x7b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82,0x12,0x28, +0xf9,0xd0,0x82,0xd0,0x83,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32,0xa9,0xc0, +0x93,0x75,0x18,0x0, 0x32,0x7a,0xb3,0x3b,0x4a,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68, +0x3, 0xb4,0x2, 0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a, +0xb3,0x3a,0xa5,0x22,0x74,0x1, 0x7a,0xb3,0x3a,0xa5,0xe4,0x7a,0xb3,0x3b,0x4a,0x22, +0x7c,0xa7,0x7c,0x3b,0xa5,0xbb,0x0, 0x7, 0x7c,0xba,0x12,0x68,0x25,0x80,0x2c,0xbe, +0x30,0xeb,0x68,0x4, 0xa5,0xbb,0xec,0x9, 0x7c,0xb3,0x7c,0x7a,0x12,0x68,0xc9,0x80, +0x1a,0xbe,0x30,0x80,0x40,0x15,0xbe,0x30,0xdf,0x38,0x10,0x7c,0xb3,0x24,0x80,0x7c, +0x7a,0x12,0x68,0x9b,0xa5,0xbb,0x8f,0x3, 0x75,0x19,0x1, 0xa5,0xbb,0xfc,0x5, 0x7c, +0xba,0x2, 0x3a,0xca,0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7c,0x6b,0x2e,0x60,0xdd, +0x68,0x26,0x2e,0x60,0xfd,0x68,0x21,0x1b,0x61,0x68,0x1d,0x1b,0x62,0x68,0x19,0x1b, +0x61,0x68,0x15,0x1b,0x60,0x68,0x11,0x2e,0x60,0xa, 0x78,0x4, 0x7a,0x73,0x3a,0x7d, +0xa, 0x2b,0x19,0x72,0x3a,0x7e,0xd2,0x10,0x22,0xbe,0xb0,0xeb,0x68,0x3, 0xb4,0xec, +0x33,0x7e,0x27,0x3b,0x9d,0x4d,0x22,0x78,0xe, 0xa5,0xbf,0xaa,0xa, 0x7e,0x24,0x0, +0x1, 0x7a,0x27,0x3b,0x9d,0x15,0x1a,0x7e,0x27,0x3b,0x9d,0xbe,0x24,0x0, 0x1, 0x78, +0x10,0xa5,0xbf,0x9, 0x6, 0x7e,0x34,0x0, 0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x3b, +0x9d,0x75,0x1a,0xea,0x22,0x7e,0xb3,0x3b,0x9f,0x4, 0x7a,0xb3,0x3b,0x9f,0xe5,0x19, +0xb4,0x1, 0x8, 0xe4,0x7a,0xb3,0x3b,0x9f,0x75,0x19,0x0, 0x7e,0x73,0x3b,0x9f,0x7a, +0x73,0x3a,0x8d,0x22,0x7c,0xab,0x12,0x2e,0x3e,0x7c,0xba,0x12,0x13,0xc7,0x2, 0x0, +0x1e,0x30,0x1b,0x8, 0x74,0x5, 0x7e,0x70,0x99,0x12,0x13,0x2c,0x7e,0xb3,0x34,0x3a, +0xb4,0x1, 0x4f,0x12,0x37,0xea,0x49,0x35,0x34,0x3b,0x49,0x15,0x34,0x3d,0x6d,0x0, +0xbe,0x8, 0x0, 0x0, 0x68,0x1a,0xbe,0x70,0x0, 0x40,0x15,0xbe,0x70,0x2, 0x38,0x10, +0x74,0x2, 0x12,0x0, 0x1e,0x7e,0xb3,0x29,0x60,0x7e,0x73,0x29,0x61,0x12,0x10,0xee, +0x7e,0xb3,0x34,0x39,0x4, 0x7a,0xb3,0x34,0x39,0x12,0x69,0x93,0x28,0xe, 0x12,0x37, +0x61,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, 0x74,0x3, 0x80,0x2, 0x74,0x2, 0x7a,0xb3, +0x34,0x3a,0x22,0x7e,0x73,0x34,0x38,0xbe,0x73,0x34,0x39,0x22,0x7e,0xb3,0x29,0x5a, +0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7d,0xc0,0x7d,0xd1,0x7d,0xf2,0x7d,0xe3,0x12,0x6b, +0x7f,0x50,0x5e,0x6c,0xee,0x80,0xd, 0x12,0x6a,0x9c,0x12,0x6a,0x82,0x7e,0x34,0x34, +0x0, 0x12,0x6a,0xa9,0x7e,0x73,0x29,0x5c,0xbc,0x7e,0x38,0xeb,0x6c,0xee,0x80,0x3b, +0x12,0x6a,0x9c,0x6c,0xdd,0x80,0x22,0x7e,0x73,0x3b,0x5f,0xbc,0x7d,0x74,0x4, 0x28, +0x8, 0xac,0xbe,0x49,0x35,0x2, 0x8c,0x80,0x6, 0xac,0xbe,0x49,0x35,0x2, 0x8e,0x74, +0x2, 0xac,0xbd,0x59,0x35,0x34,0x50,0xb, 0xd0,0x7e,0x73,0x29,0x5d,0xbc,0x7d,0x38, +0xd6,0x12,0x6a,0x82,0x7e,0x34,0x34,0x50,0x12,0x6a,0xa9,0xbc,0xfe,0x38,0xc1,0x80, +0x2c,0x7a,0xf3,0x24,0x8a,0x7e,0x73,0x29,0x5d,0x7a,0x73,0x24,0x8b,0xe4,0x7a,0xb3, +0x24,0x8d,0x74,0x6, 0x7a,0xb3,0x24,0x8c,0x7a,0xd7,0x24,0x8e,0x7a,0xd7,0x24,0x92, +0x7e,0x8, 0x24,0x8a,0x7e,0x73,0x2a,0xc, 0xa, 0x37,0x12,0xe, 0x37,0x7a,0xc7,0x24, +0x92,0xe4,0x7a,0xb3,0x24,0x8c,0x12,0x6a,0x93,0x7a,0xf3,0x24,0x8a,0x7e,0xb3,0x2a, +0xa, 0x70,0xf, 0xe4,0x7a,0xb3,0x24,0x8d,0x7a,0xd7,0x24,0x8e,0x7e,0x34,0x0, 0x20, +0x80,0x10,0x74,0x1, 0x7a,0xb3,0x24,0x8d,0x7a,0xe7,0x24,0x8e,0x7a,0xf7,0x24,0x90, +0x6d,0x33,0x7a,0x37,0x24,0x94,0x7e,0x8, 0x24,0x8a,0x12,0xd, 0x7, 0xda,0x79,0xda, +0xd8,0x22,0x74,0xc, 0x7a,0xb3,0x24,0x8c,0x74,0x1, 0x7a,0xb3,0x24,0x8a,0xe4,0x7a, +0xb3,0x24,0x8d,0x7e,0x73,0x29,0x5b,0x7a,0x73,0x24,0x8b,0x22,0x7e,0x73,0x29,0x5b, +0xac,0x7e,0x3e,0x34,0x7d,0xbd,0x2d,0xb3,0x22,0x7a,0x37,0x24,0x8e,0x7d,0x3b,0x7a, +0x37,0x24,0x90,0x7a,0x37,0x24,0x92,0x7e,0x8, 0x24,0x8a,0x12,0x7, 0x9b,0xb, 0xe0, +0x22,0x7e,0xf, 0x12,0x9a,0x7e,0x18,0x7, 0x1a,0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30, +0x12,0xcf,0xfa,0x7a,0x55,0x31,0x7e,0xb3,0x2a,0xa, 0xf5,0x2e,0xe4,0x7a,0xb3,0x2a, +0xa, 0x7f,0x3, 0x7e,0x1d,0x29,0x12,0x5f,0xd6,0x12,0x37,0xf2,0x12,0x37,0xd4,0x75, +0x2d,0x0, 0x12,0x37,0x34,0x30,0xd, 0xfd,0x74,0x1, 0x12,0x6b,0xc4,0x7e,0x14,0x40, +0x0, 0x7d,0x21,0x7d,0x7, 0x12,0x69,0x9c,0x12,0x6c,0x8c,0x6d,0x33,0x80,0x19,0x7e, +0x35,0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13, +0x12,0x67,0xd8,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e,0x35,0x31,0xbe,0x35, +0x2f,0x38,0xdc,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb6,0xe5,0x2e,0x7a,0xb3, +0x2a,0xa, 0xda,0x3b,0x22,0x7e,0xb3,0x2a,0xb, 0x70,0x1f,0x12,0x57,0xe7,0x12,0x67, +0xe1,0x50,0xfb,0x12,0x6a,0xc1,0x12,0x6b,0x6b,0x20,0x12,0x3, 0x12,0x87,0xa, 0x74, +0x2, 0x7a,0xb3,0x2a,0xb, 0xe4,0x7a,0xb3,0x15,0xa1,0x22,0x12,0x6b,0x7f,0x50,0x3, +0xd2,0x12,0x22,0xc2,0x12,0x22,0x12,0xae,0xcc,0x12,0x6b,0x90,0x2, 0x6b,0x6b,0x7e, +0xb3,0x3a,0xa5,0xb4,0x3, 0x8, 0x7e,0xb3,0x3b,0x60,0x70,0x2, 0xc3,0x22,0xd3,0x22, +0x7e,0x8, 0x24,0x2, 0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x1a,0x30,0x12,0xad,0xe2,0x12, +0xad,0xd9,0xa9,0xd1,0xcb,0x12,0x6b,0xc4,0x7a,0x37,0x24,0x6, 0x7e,0x1f,0x3c,0x6c, +0x7a,0x37,0x24,0x8, 0x7e,0x1f,0x12,0x96,0x7a,0x37,0x24,0xa, 0x6d,0x33,0x12,0xc6, +0xe9,0x2, 0xd, 0x7, 0x12,0x0, 0xe, 0x7e,0x1f,0x12,0x96,0x22,0x12,0x8c,0x89,0x12, +0x48,0xb6,0x12,0x6c,0x2a,0x7e,0xb3,0x3a,0xa3,0xb4,0x1, 0x7, 0x7e,0x34,0x0, 0x14, +0x12,0x5f,0x91,0x7e,0xb3,0x33,0xfe,0x60,0x7, 0x14,0x7a,0xb3,0x33,0xfe,0x80,0x6, +0x7e,0xb3,0x27,0x80,0x60,0x9, 0x12,0x6b,0x76,0x12,0x6c,0xf, 0x12,0xc6,0x45,0x7e, +0xb3,0x27,0x81,0x60,0x9, 0x12,0xcd,0xaf,0x12,0x6d,0x2d,0x2, 0x6c,0xd3,0x22,0x12, +0x6c,0x47,0x6d,0x33,0x7a,0x37,0x3a,0x79,0x6c,0xaa,0x12,0x6d,0x1f,0xb, 0xa0,0xbe, +0xa0,0x4, 0x40,0xf6,0xe4,0x7a,0xb3,0x3a,0xe, 0x22,0x12,0xb3,0xc0,0x60,0x17,0x12, +0x4b,0xdd,0x7e,0x37,0x27,0x75,0x3e,0x34,0x7a,0x37,0x27,0x75,0x7e,0x37,0x27,0x77, +0x3e,0x34,0x7a,0x37,0x27,0x77,0x22,0x7e,0x37,0x3c,0x65,0x12,0x6c,0x83,0x7a,0x37, +0x3a,0x79,0x6c,0xaa,0x80,0x24,0xbe,0xa0,0x4, 0x50,0x27,0xa, 0x3a,0x9, 0x63,0x3a, +0x12,0xbe,0x60,0x4, 0x50,0x12,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x42,0x3c,0x5f,0x7e, +0x70,0xc, 0xac,0x67,0x59,0x43,0x3a,0x1c,0xb, 0xa0,0x7e,0xb3,0x3a,0xf, 0xbc,0xba, +0x38,0xd4,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x22,0x12,0x87,0xf7,0x3e, +0x34,0x7e,0x8, 0x12,0x9e,0xe4,0x12,0x1a,0x30,0x90,0x60,0x93,0x93,0xa, 0x3b,0x7e, +0xb3,0x29,0x5e,0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xad,0x32,0x7d,0x43,0x6c,0x77,0x80, +0x1d,0xa, 0x27,0x2d,0x24,0x12,0xd0,0x9e,0xb, 0xa, 0x0, 0x7e,0x30,0x2, 0xac,0x37, +0x2e,0x14,0x12,0x9e,0xb, 0x18,0x20,0x2d,0x20,0x1b,0x18,0x20,0xb, 0x70,0xbc,0xa7, +0x38,0xdf,0x22,0x6c,0xaa,0x7e,0x70,0xc, 0xac,0x7a,0x12,0xb2,0xaa,0xbe,0x34,0x3, +0xe8,0x8, 0x5, 0x12,0x6d,0x1f,0x80,0x2f,0x7e,0x50,0xc, 0xac,0x5a,0x49,0x32,0x3a, +0x20,0x49,0x12,0x3a,0x1c,0xbd,0x13,0x28,0xf, 0x7d,0x2, 0x2e,0x4, 0x3a,0x20,0x7d, +0x13,0xb, 0x15,0x1b,0x8, 0x10,0x80,0xf, 0xbe,0x34,0x0, 0x2, 0x28,0x9, 0x2e,0x24, +0x3a,0x20,0x1b,0x35,0x1b,0x28,0x30,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xb7,0x22,0x7e, +0x50,0xc, 0xac,0x5a,0x49,0x32,0x3a,0x1c,0x59,0x32,0x3a,0x20,0x22,0x7e,0x43,0x29, +0x5b,0x7e,0x53,0x29,0x5a,0xac,0x54,0x7e,0x17,0x27,0x75,0x12,0xad,0xd2,0x6d,0x0, +0x80,0x37,0x7d,0x40,0x3e,0x44,0x7e,0x7f,0x3c,0x6c,0x2d,0xf4,0xb, 0x7a,0x30,0xbd, +0x13,0x58,0x10,0x7d,0xf4,0x2e,0xf4,0x7, 0x1a,0xb, 0xf8,0x50,0x9d,0x51,0x1b,0xf8, +0x50,0x80,0x14,0x6d,0x55,0x9d,0x51,0xbd,0x53,0x8, 0xc, 0x2e,0x44,0x7, 0x1a,0xb, +0x48,0x50,0x2d,0x51,0x1b,0x48,0x50,0xb, 0x4, 0xbd,0x20,0x38,0xc5,0x22,0x7f,0x71, +0x69,0x37,0x0, 0x2, 0x7d,0x53,0x12,0xd0,0xf8,0xb, 0x7a,0x20,0x2d,0x25,0x1b,0xa, +0x20,0x69,0x27,0x0, 0x4, 0x7d,0x52,0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x1e,0x34,0x1e, +0x34,0x2d,0x35,0x79,0x30,0x0, 0x2, 0x69,0x37,0x0, 0x6, 0x7d,0x53,0x7c,0xab,0xe4, +0x3e,0x54,0x3e,0x54,0x12,0x8f,0xdc,0x1e,0x24,0x2d,0x25,0x79,0x20,0x0, 0x4, 0x69, +0x27,0x0, 0x8, 0x7c,0x45,0x6c,0x55,0x12,0x6c,0x83,0x1e,0x34,0x1e,0x34,0x2d,0x32, +0x79,0x30,0x0, 0x6, 0x22,0x6c,0xaa,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x28,0x36, +0x12,0x6c,0x83,0x59,0x32,0x27,0x82,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x32,0x28,0x38, +0x12,0x6c,0x83,0x59,0x32,0x27,0x84,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3a, +0x19,0xb4,0x27,0x86,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3b,0x19,0xb4,0x27, +0x87,0x7e,0x90,0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3c,0x19,0xb4,0x27,0x88,0x7e,0x90, +0x9, 0xac,0x9a,0x9, 0xb4,0x28,0x3d,0x19,0xb4,0x27,0x89,0x7e,0x90,0x9, 0xac,0x9a, +0x9, 0xb4,0x28,0x3e,0x19,0xb4,0x27,0x8a,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0x98,0x22, +0xca,0x79,0x7e,0xf3,0x28,0xf4,0x7e,0xe3,0x28,0xf5,0x7c,0xbf,0x7c,0x7e,0x12,0x46, +0x34,0x7c,0xbf,0x12,0x97,0x38,0x4c,0xee,0x78,0x18,0x7e,0x34,0x0, 0x5a,0xca,0x39, +0x7e,0x18,0x27,0x82,0x7e,0x8, 0x28,0x36,0x12,0x1a,0xb, 0x1b,0xfd,0x12,0x6e,0x93, +0x80,0xe, 0x7e,0xb3,0x28,0xfb,0x70,0x8, 0x12,0x6e,0x93,0x7c,0xbf,0x12,0x6e,0xe0, +0x7c,0xbf,0x12,0x6d,0xd5,0xbe,0xf0,0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xfd, +0xda,0x79,0x22,0x7e,0xa3,0x28,0xf4,0x6c,0x77,0x80,0x34,0x7e,0x90,0x9, 0xac,0x97, +0x9, 0x64,0x28,0x3a,0xa, 0x26,0x9, 0xb2,0x28,0x90,0x70,0x21,0x7e,0x30,0x1, 0x7e, +0x50,0x9, 0xac,0x56,0x19,0x32,0x32,0x41,0x49,0x14,0x27,0x82,0x59,0x12,0x32,0x42, +0x49,0x14,0x27,0x84,0x59,0x12,0x32,0x44,0xe4,0x19,0xb2,0x32,0x46,0xb, 0x70,0xbc, +0xa7,0x38,0xc8,0x22,0x7e,0xb3,0x3a,0xce,0x70,0x3, 0x12,0x73,0xb8,0x2, 0x6e,0x40, +0xca,0x3b,0x7c,0xfb,0x6c,0xee,0x80,0x74,0x6c,0xdd,0x74,0x9, 0xac,0xbd,0x9, 0x45, +0x28,0x3a,0x7e,0x70,0x9, 0xac,0x7e,0x9, 0x53,0x27,0x86,0xbc,0x45,0x68,0x7, 0xb, +0xd0,0xbe,0xd0,0xa, 0x40,0xe4,0xbe,0xd0,0xa, 0x50,0x55,0x74,0x9, 0xac,0xbd,0x9, +0xc5,0x28,0x3a,0x49,0x25,0x28,0x38,0x49,0x33,0x27,0x84,0x12,0xae,0x6a,0x74,0x9, +0xac,0xbd,0x12,0xd0,0x37,0x9d,0x32,0x12,0x1a,0x62,0x2d,0x31,0x7a,0x35,0x24,0xa, +0x3c,0x9, 0xb3,0x28,0x90,0xb4,0x1, 0xe, 0x6d,0x33,0x74,0x2, 0xac,0xbc,0x59,0x35, +0x32,0xad,0x59,0x35,0x32,0xdc,0x7e,0x35,0x24,0x7c,0xbd,0x7c,0x5e,0x7c,0x4c,0x12, +0xa0,0x1d,0x7a,0x35,0x24,0x7c,0xbd,0x12,0x6f,0x63,0xb, 0xe0,0xbc,0xfe,0x38,0x88, +0xda,0x3b,0x22,0x2, 0x6f,0x66,0xca,0xd8,0xca,0x79,0x7c,0xd4,0x7c,0xe5,0x7c,0xfb, +0x7c,0xbd,0x12,0x99,0xa, 0x7d,0xf3,0x30,0x14,0x2a,0x74,0x9, 0xac,0xbe,0x9, 0x75, +0x27,0x89,0xbe,0x73,0x39,0x0, 0x78,0xa, 0x9, 0x65,0x27,0x8a,0xbe,0x63,0x39,0x2, +0x68,0x10,0xbe,0x73,0x39,0x1, 0x78,0xc, 0x9, 0x75,0x27,0x8a,0xbe,0x73,0x39,0x3, +0x78,0x2, 0x1e,0xf4,0x7e,0x50,0x9, 0xac,0x5e,0x49,0x32,0x27,0x84,0xbe,0x34,0x2, +0x60,0x50,0x5, 0x12,0xcf,0x9f,0x40,0xb, 0xbe,0x34,0x69,0xb0,0x28,0x1f,0x12,0xcf, +0x9f,0x28,0x1a,0x3e,0xf4,0xbe,0x34,0x2, 0x30,0x50,0x5, 0x12,0xcf,0x9f,0x40,0xb, +0xbe,0x34,0x69,0xe0,0x28,0x7, 0x12,0xcf,0x9f,0x28,0x2, 0x3e,0xf4,0xbe,0xf4,0x1, +0x0, 0x28,0x4, 0x7e,0xf4,0x1, 0x0, 0x7c,0xbe,0x7c,0x7d,0x12,0x7b,0x46,0x7d,0x3, +0x74,0x9, 0xac,0xbf,0x12,0xd0,0x37,0x12,0x70,0x7f,0x7d,0x13,0x5d,0x10,0x7e,0x70, +0x9, 0xac,0x7f,0x49,0xe3,0x28,0x36,0x74,0x9, 0xac,0xbe,0x49,0x25,0x27,0x82,0xbd, +0x2e,0x28,0xf, 0x7d,0x53,0x2e,0x54,0x28,0x36,0x7d,0x2e,0x2d,0x21,0x1b,0x58,0x20, +0x80,0xd, 0xbd,0xe1,0x40,0x9, 0x2e,0x34,0x28,0x36,0x9d,0xe1,0x1b,0x38,0xe0,0x74, +0x9, 0xac,0xbf,0x49,0x25,0x28,0x38,0x74,0x9, 0xac,0xbe,0x49,0x35,0x27,0x84,0x12, +0x70,0x7f,0x7d,0x13,0x5d,0x10,0x7e,0x50,0x9, 0xac,0x5f,0x49,0x32,0x28,0x38,0x74, +0x9, 0xac,0xbe,0x49,0x5, 0x27,0x84,0xbd,0x3, 0x28,0xd, 0x7d,0x2, 0x2e,0x4, 0x28, +0x38,0x2d,0x13,0x1b,0x8, 0x10,0x80,0x12,0xbd,0x31,0x40,0xe, 0x7e,0x50,0x9, 0xac, +0x5f,0x2e,0x24,0x28,0x38,0x9d,0x31,0x1b,0x28,0x30,0xda,0x79,0xda,0xd8,0x22,0x9d, +0x32,0x12,0x1a,0x62,0x7d,0x13,0x7d,0x3f,0xad,0x31,0x7c,0x76,0x7c,0x65,0xa, 0x24, +0x22,0x7d,0xd3,0x7e,0x44,0x4, 0x38,0x7e,0xa3,0x29,0x5c,0x74,0x40,0xa4,0x7d,0xb5, +0x1b,0xb4,0xbe,0xd4,0x0, 0x3f,0x38,0x29,0x7e,0xe4,0x0, 0x3f,0x9d,0xed,0x7e,0xf4, +0x2, 0xcc,0xad,0xef,0x7d,0x3f,0x7d,0x2e,0x12,0x70,0x8a,0x7f,0x71,0xbe,0x78,0x0, +0x49,0x40,0x4, 0x7e,0x78,0x0, 0x49,0x7e,0x18,0x0, 0x49,0x9f,0x17,0x7f,0x71,0x21, +0x55,0x7d,0xcb,0x9e,0xc4,0x0, 0x3f,0xbd,0xcd,0x38,0x24,0x7d,0x5d,0x9d,0x5c,0x7e, +0xf4,0x2, 0xe0,0xad,0xf5,0x7d,0x3f,0x7d,0x2e,0x12,0x70,0x8a,0x7f,0x71,0xbe,0x78, +0x0, 0x47,0x40,0x4, 0x7e,0x78,0x0, 0x46,0x12,0x71,0x58,0x2f,0x71,0x80,0x56,0x7d, +0xcb,0xb, 0xc4,0x1e,0xc4,0x7d,0x5c,0x1b,0x54,0xbd,0x5d,0x40,0xc, 0x7d,0xf5,0x9d, +0xfd,0x6d,0xee,0x7e,0x14,0x1, 0x52,0x80,0xa, 0x7d,0xfd,0x9d,0xfc,0x6d,0xee,0x7e, +0x14,0x1, 0x54,0x12,0x73,0x9c,0x12,0x70,0x8a,0x7f,0x71,0xbd,0x5d,0x7d,0x34,0x40, +0x5, 0x12,0x73,0xa4,0x80,0x6, 0x1e,0x34,0x6d,0x22,0x2f,0x71,0xbe,0x78,0x0, 0x49, +0x50,0x6, 0x7e,0x78,0x0, 0x49,0x80,0xd, 0x12,0x71,0x58,0x7d,0x13,0x6d,0x0, 0xbf, +0x70,0x28,0x2, 0x7f,0x71,0x7d,0x3f,0x22,0x7d,0x34,0x6d,0x22,0x9e,0x18,0x0, 0x47, +0x22,0xca,0x69,0xca,0xf8,0x7e,0xa3,0x28,0xf4,0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x28, +0xf5,0xbe,0xb0,0x0, 0x28,0x13,0x74,0x1, 0x7a,0xb3,0x28,0xf9,0x80,0xb, 0xbe,0xa0, +0x0, 0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x28,0xfd,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e, +0x18,0x27,0x82,0x7e,0x8, 0x27,0xdc,0x12,0x1a,0xb, 0x1b,0xfd,0x6c,0xff,0x12,0x73, +0xaf,0x12,0x70,0x91,0x74,0x9, 0xac,0xbf,0x59,0x35,0x27,0xdc,0x49,0x35,0x27,0x84, +0x12,0x72,0x8b,0x7e,0xd0,0x9, 0xac,0xdf,0x59,0x36,0x27,0xde,0x49,0x16,0x27,0xde, +0xbe,0x14,0x0, 0x5a,0x38,0x2, 0x41,0x7d,0xbe,0x14,0x0, 0x96,0x40,0x2, 0x41,0x7d, +0x49,0xf6,0x27,0xdc,0xbe,0xf4,0x1, 0x68,0x38,0x2, 0x41,0x7d,0xbe,0xf4,0x2, 0xd0, +0x40,0x2, 0x41,0x7d,0x7e,0x18,0x9, 0x3b,0x7a,0x1d,0x24,0x6d,0x0, 0x7e,0x18,0x0, +0x96,0x9f,0x10,0x7a,0x1d,0x2c,0xbe,0xf4,0x1, 0x68,0x28,0x10,0xbe,0xf4,0x1, 0xcc, +0x50,0xa, 0x7d,0x1f,0x6d,0x0, 0x9e,0x8, 0x1, 0x68,0x80,0x16,0xbe,0xf4,0x2, 0x6c, +0x28,0x31,0xbe,0xf4,0x2, 0xd0,0x50,0x2b,0x7d,0x3f,0x6d,0x22,0x7e,0x8, 0x2, 0xd0, +0x9f,0x1, 0x7a,0xd, 0x28,0x7e,0x1d,0x24,0x9e,0x18,0x4, 0x0, 0x7a,0x1d,0x24,0x12, +0x17,0x18,0x7e,0x14,0x0, 0x64,0x12,0x17,0x32,0x7a,0x1d,0x24,0x2e,0x18,0x4, 0x0, +0x7a,0x1d,0x24,0x7e,0xd, 0x24,0x7e,0x1d,0x2c,0x12,0x17,0x18,0x74,0xa, 0x1e,0x34, +0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7a,0x1d,0x2c,0xbe,0x18,0x0, +0x3c,0x28,0x7, 0x7e,0x18,0x0, 0x3c,0x7a,0x1d,0x2c,0x7e,0x1d,0x2c,0x7d,0x23,0x7e, +0x34,0x0, 0x96,0x9d,0x32,0x74,0x9, 0xac,0xbf,0x59,0x35,0x27,0xde,0xb, 0xf0,0xbe, +0xf0,0xa, 0x50,0x2, 0x21,0x9e,0xda,0xf8,0xda,0x69,0x22,0xca,0x3b,0x7d,0xb3,0x9f, +0x77,0x7e,0xd4,0x8, 0xe8,0x7e,0xa3,0x29,0x5d,0x74,0x40,0xa4,0x7d,0x95,0x1b,0x94, +0xbe,0xb4,0x0, 0x3f,0x38,0x1f,0x7e,0xe4,0x0, 0x3f,0x9d,0xeb,0x7e,0xf4,0x2, 0x4a, +0x12,0x73,0x86,0xbe,0x78,0x0, 0x47,0x40,0x4, 0x7e,0x78,0x0, 0x47,0x7e,0x18,0x0, +0x47,0x9f,0x17,0x7f,0x71,0x7d,0xc9,0x9e,0xc4,0x0, 0x3f,0xbd,0xcb,0x38,0x3f,0x7d, +0xf9,0x9e,0xf4,0x0, 0x40,0x7d,0xeb,0x9d,0xef,0x7e,0xf4,0x2, 0x36,0x12,0x73,0x86, +0x7c,0xb4,0x12,0x15,0xa, 0x6d,0x77,0x7e,0x64,0x42,0x8f,0x7f,0x3, 0x12,0x14,0xc4, +0x40,0x4, 0x7e,0x78,0x0, 0x46,0x7d,0x2d,0xe4,0x12,0x15,0xf, 0x7f,0x3, 0x12,0x14, +0x9, 0x7f,0x1, 0x12,0x73,0x95,0x12,0x14,0xc, 0x12,0x15,0x47,0x7f,0x71,0xbe,0xb4, +0x0, 0x3f,0x28,0x6d,0xbd,0xcb,0x28,0x69,0x7d,0xa9,0xb, 0xa4,0x1e,0xa4,0x7d,0xca, +0x1b,0xc4,0xbd,0xcb,0x40,0xc, 0x7d,0xfc,0x9d,0xfb,0x6d,0xee,0x7e,0x14,0x1, 0x56, +0x80,0xa, 0x7d,0xfb,0x9d,0xfa,0x6d,0xee,0x7e,0x14,0x1, 0x57,0x12,0x73,0x9c,0x12, +0x73,0x8c,0xbd,0xcb,0x7d,0x3d,0x40,0x5, 0x12,0x73,0xa4,0x80,0x6, 0x1e,0x34,0x6d, +0x22,0x2f,0x71,0xbe,0x78,0x0, 0x47,0x50,0x6, 0x7e,0x78,0x0, 0x47,0x80,0x22,0x7d, +0x2d,0xe4,0x12,0x15,0xf, 0x6d,0x11,0x7e,0x4, 0x42,0x8f,0x12,0x14,0x9, 0x7f,0x61, +0x12,0x73,0x95,0x7f,0x6, 0x12,0x14,0xc4,0x28,0x7, 0x7f,0x16,0x12,0x15,0x47,0x7f, +0x71,0x7d,0x3f,0xda,0x3b,0x22,0xad,0xef,0x7d,0x3f,0x7d,0x2e,0x7c,0x76,0x7c,0x65, +0x1a,0x24,0x7f,0x71,0x22,0x7f,0x17,0x7c,0xb4,0x2, 0x15,0xa, 0x7f,0x17,0x12,0x17, +0x29,0x7f,0x71,0x22,0x1e,0x34,0x1b,0x34,0x6d,0x22,0x9f,0x17,0x7f,0x71,0x22,0x74, +0x9, 0xac,0xbf,0x49,0x35,0x27,0x82,0x22,0xca,0x3b,0x7e,0x90,0x1, 0x7e,0xb3,0x28, +0xf4,0xf5,0x2a,0x75,0x2b,0x0, 0x75,0x2c,0x0, 0x70,0x30,0x7e,0xf1,0x2a,0x80,0x26, +0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x27,0x86,0x6d,0x22,0x74,0x2, 0xac,0xbf,0x59, +0x25,0x33,0x4b,0x74,0xff,0x19,0xb3,0x32,0xf5,0x19,0xb3,0x33,0x6d,0xe4,0xa, 0x3f, +0x19,0xb3,0x33,0xc3,0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xd5,0xe5,0x1c,0x60,0xb, 0x7e, +0xa1,0x1c,0x74,0x14,0xa4,0xf5,0x2b,0x75,0x2c,0x14,0x7e,0xa3,0x3a,0xd, 0x4c,0xaa, +0x68,0x9, 0x75,0x2c,0x14,0xe5,0x2b,0x24,0x28,0xf5,0x2b,0xe5,0x1c,0x70,0x1e,0x4c, +0xaa,0x78,0x1a,0xe5,0x2b,0xbe,0xb0,0x0, 0x28,0x6, 0xe5,0x2b,0x1e,0xb0,0xf5,0x2b, +0xe5,0x2c,0xbe,0xb0,0x0, 0x28,0x6, 0xe5,0x2c,0x1e,0xb0,0xf5,0x2c,0x75,0x1c,0x0, +0x6c,0xff,0x74,0x9, 0xac,0xbf,0x9, 0xe5,0x27,0x86,0x5e,0xe0,0xf, 0xbe,0xe0,0xa, +0x40,0x2, 0xe1,0x44,0xa, 0x3e,0x9, 0xa3,0x28,0x90,0x4c,0xaa,0x78,0x17,0x74,0x1, +0x19,0xb3,0x33,0xc3,0x19,0xb3,0x33,0x5f,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3e,0x59, +0x21,0x33,0x4b,0xe1,0x44,0xbe,0xa0,0x1, 0x78,0x2, 0xe1,0x1e,0x9, 0xb3,0x33,0xc3, +0xbe,0xb0,0x14,0x50,0x8, 0x2e,0x34,0x33,0xc3,0x4, 0x7a,0x39,0xb0,0x75,0x24,0x0, +0x12,0x77,0x89,0x9, 0x83,0x32,0xf5,0x7a,0x81,0x29,0xbc,0x8e,0x68,0x2, 0xe1,0x11, +0x49,0x23,0x32,0xf1,0x12,0x73,0xaf,0x9d,0x32,0x12,0x1a,0x62,0x7a,0x35,0x25,0x12, +0x44,0x71,0x49,0x25,0x32,0xf3,0x12,0x77,0x91,0x9d,0x32,0x12,0x1a,0x62,0x7a,0x35, +0x27,0x7d,0x63,0x2e,0x65,0x25,0x7e,0x35,0x25,0xbe,0x34,0x0, 0x50,0x50,0x38,0xe5, +0x2a,0xb4,0x1, 0x33,0x7e,0xb3,0x15,0xa2,0x70,0x2d,0x7e,0x35,0x27,0xbe,0x34,0x0, +0xc8,0x28,0x24,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xb3,0x27,0x89,0x9, 0x73,0x27,0x8a, +0x12,0x77,0x81,0x8, 0x12,0x12,0x77,0x89,0x9, 0xb3,0x32,0xf8,0x9, 0x73,0x32,0xf9, +0x12,0x77,0x81,0x8, 0x2, 0xc1,0x84,0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xa3,0x27,0x89, +0x4c,0xaa,0x78,0x16,0x7e,0x51,0x24,0x74,0x9, 0xac,0x5b,0x9, 0x82,0x32,0xf8,0x7e, +0xb3,0x29,0x5c,0x14,0xbc,0x8b,0x78,0x2, 0xc1,0x84,0x12,0x77,0x9a,0x78,0xb, 0x12, +0x44,0x71,0x9, 0xb5,0x32,0xf8,0x70,0x2, 0xc1,0x84,0x7e,0x31,0x29,0x74,0x2, 0xac, +0x3b,0x49,0x21,0x33,0x4b,0xbe,0x24,0x0, 0x14,0x28,0x13,0xe5,0x29,0xa, 0x2b,0x9, +0x82,0x33,0xc3,0xbe,0x80,0xa, 0x50,0x6, 0x74,0xa, 0x19,0xb2,0x33,0xc3,0xbe,0x64, +0x0, 0xa, 0x50,0x10,0xe5,0x29,0xa, 0x2b,0x2e,0x24,0x33,0xc3,0x7e,0x29,0x80,0x1e, +0x80,0x7a,0x29,0x80,0xe5,0x29,0xa, 0x2b,0x9, 0xb2,0x33,0x5f,0xb4,0x1, 0x14,0xbe, +0x64,0x2, 0xbc,0x50,0xe, 0x59,0x61,0x33,0x4b,0x2e,0x24,0x33,0x5f,0x14,0x7a,0x29, +0xb0,0xe1,0x44,0xbe,0x64,0x0, 0x64,0x28,0x52,0x75,0x2d,0x0, 0x7e,0xa1,0x2d,0x74, +0x9, 0xa4,0x9, 0x85,0x33,0x6d,0xbe,0x81,0x29,0x68,0x9, 0x5, 0x2d,0xe5,0x2d,0xbe, +0xb0,0xa, 0x40,0xe8,0x7e,0x51,0x2d,0x74,0x9, 0xac,0x5b,0x9, 0xb2,0x33,0x6d,0xbe, +0xb0,0xff,0x68,0x2a,0x49,0x33,0x27,0x82,0x7a,0x35,0x2e,0x12,0x77,0x91,0x7a,0x35, +0x30,0x49,0x32,0x33,0x69,0x49,0x22,0x33,0x6b,0x12,0x44,0x71,0x49,0x15,0x32,0xf1, +0x49,0x5, 0x32,0xf3,0x12,0x9f,0x2d,0x7c,0x9b,0x80,0x3, 0x7e,0x90,0x1, 0x4c,0x99, +0x78,0x2, 0xc1,0x84,0x7e,0xb3,0x28,0xfb,0xbe,0xb0,0x1, 0x78,0x2, 0xe1,0x44,0x7e, +0x51,0x29,0x74,0x2, 0xac,0x5b,0x49,0x32,0x33,0x4b,0x7d,0x13,0x2e,0x14,0x1, 0x5e, +0xbd,0x16,0x38,0xa, 0x7d,0x13,0x3e,0x14,0x3e,0x14,0xbd,0x16,0x28,0x32,0xbe,0x34, +0x0, 0x32,0x28,0xc, 0xbe,0x64,0x0, 0x32,0x28,0x6, 0x59,0x62,0x33,0x4b,0xe1,0x44, +0x7d,0x3, 0x2e,0x4, 0x0, 0x50,0xe5,0x2b,0xa, 0x1b,0x2d,0x10,0xbd,0x16,0x50,0x10, +0xe5,0x2c,0xa, 0x1b,0x7e,0x24,0x0, 0x50,0x9d,0x21,0xbd,0x32,0x28,0x2, 0xe1,0x5, +0x7e,0x83,0x15,0xa2,0xbe,0x80,0x0, 0x28,0x2, 0xe1,0x44,0xbe,0x64,0x0, 0xe6,0x38, +0x23,0xbe,0x34,0x0, 0xa, 0x50,0x6, 0xbe,0x64,0x0, 0x96,0x38,0x17,0xe5,0x29,0xa, +0x3b,0x9, 0x83,0x33,0xc3,0xbe,0x80,0x5, 0x40,0x2, 0xe1,0x5, 0xbe,0x64,0x0, 0x6e, +0x38,0x2, 0xe1,0x5, 0x74,0x1, 0xa, 0x3e,0x19,0xb3,0x28,0x90,0x7e,0xa0,0x3, 0xe5, +0x29,0xa, 0x3b,0x19,0xa3,0x28,0x9a,0x6c,0xaa,0xe5,0x29,0xa, 0x3b,0x19,0xa3,0x33, +0xc3,0xe5,0x2a,0xbe,0xb0,0x0, 0x28,0x4f,0x15,0x2a,0x7e,0x70,0x9, 0xac,0x7f,0x2e, +0x34,0x27,0x82,0x7e,0x14,0x1e,0x44,0x74,0x9, 0x12,0x17,0xb9,0x7e,0x71,0x2a,0x74, +0x9, 0xac,0x7b,0x2e,0x34,0x27,0x82,0x12,0x77,0xaa,0x12,0x77,0xa2,0x7e,0x31,0x2a, +0x74,0x9, 0xac,0x3b,0x2e,0x14,0x27,0x82,0x12,0x17,0xb9,0xe5,0x2a,0x7a,0xb3,0x3c, +0x2a,0x7e,0x34,0x7f,0xff,0x74,0x2, 0xac,0xbe,0x59,0x35,0x28,0xa4,0x74,0x2, 0xac, +0xbe,0x59,0x35,0x28,0xb8,0x1b,0xf0,0x6d,0x33,0x7e,0xa1,0x29,0x74,0x2, 0xa4,0x59, +0x35,0x33,0x4b,0x80,0x3f,0x7e,0xa1,0x29,0x74,0x2, 0xa4,0x59,0x65,0x33,0x4b,0x80, +0x33,0x5, 0x24,0xe5,0x24,0xbe,0xb0,0xa, 0x50,0x2, 0x81,0x90,0x80,0x26,0xe4,0xa, +0x3e,0x19,0xb3,0x33,0xc3,0x6d,0x33,0x74,0x2, 0xac,0xbe,0x59,0x35,0x33,0x4b,0x7e, +0xa0,0xff,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x32,0xf5,0x7e,0x70,0x9, 0xac,0x7f, +0x19,0xa3,0x33,0x6d,0xb, 0xf0,0xbe,0xf0,0xa, 0x50,0x2, 0x81,0x42,0xe4,0x7a,0xb3, +0x15,0xa2,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x32,0xf1,0x7e,0x8, 0x33,0x69, +0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x34,0x0, 0x5a,0xca,0x39,0x7e,0x18,0x27,0x82,0x7e, +0x8, 0x32,0xf1,0x12,0x1a,0xb, 0x1b,0xfd,0xe5,0x2a,0x7a,0xb3,0x28,0xf4,0xda,0x3b, +0x22,0x12,0x21,0x50,0xbe,0x34,0x0, 0x96,0x22,0x7e,0x71,0x24,0x74,0x9, 0xac,0x7b, +0x22,0x74,0x9, 0xac,0xbf,0x49,0x35,0x27,0x84,0x22,0x7e,0xb3,0x29,0x5c,0x14,0xbc, +0xab,0x22,0x12,0x17,0xb9,0x7e,0x34,0x1e,0x44,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e, +0x14,0x27,0x82,0x22,0xca,0xf8,0x7e,0x68,0x28,0x90,0x6c,0xaa,0x7e,0x70,0xff,0x12, +0x7b,0x32,0xe4,0xa, 0x4a,0x19,0xb4,0x1e,0x44,0x74,0xff,0x19,0xb4,0x1e,0x56,0x19, +0xb4,0x1e,0x60,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xe2,0x7e,0x73,0x28,0xf4,0xa5,0xbf, +0x0, 0x22,0x7e,0xb3,0x3c,0x2a,0x70,0x3, 0x2, 0x7a,0x7a,0x6c,0xaa,0x7e,0x44,0x7f, +0xff,0x12,0x7b,0x1f,0x79,0x40,0x0, 0x14,0x12,0x7b,0x29,0xb, 0xa0,0xbe,0xa0,0xa, +0x78,0xeb,0x41,0x7a,0x7e,0xb3,0x3c,0x2a,0x70,0x3d,0xbe,0x70,0x0, 0x28,0x38,0x6c, +0xaa,0x80,0x2a,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x34,0x27,0x82,0x12,0x7b,0x1f,0x79, +0x30,0x0, 0x14,0x49,0x34,0x27,0x84,0x7f,0x6, 0x2d,0x12,0x79,0x30,0x0, 0x28,0x74, +0x1, 0xa, 0x3a,0x19,0xb3,0x1e,0x44,0x19,0xa4,0x27,0x86,0xb, 0xa0,0x7e,0xb3,0x28, +0xf4,0xbc,0xba,0x38,0xce,0x41,0x7a,0x6c,0xaa,0x12,0x7b,0x15,0x3e,0x34,0x59,0x43, +0x14,0x5e,0x59,0x43,0x14,0x60,0x59,0x43,0x14,0x86,0x59,0x43,0x14,0x88,0xb, 0xa0, +0xbe,0xa0,0xa, 0x78,0xe4,0x7e,0xb3,0x3c,0x2a,0xbe,0xb3,0x28,0xf4,0x28,0xd, 0xbe, +0xb0,0x2, 0x40,0x8, 0x74,0x1, 0x7a,0xb3,0x3c,0x29,0x80,0x5, 0xe4,0x7a,0xb3,0x3c, +0x29,0x6c,0xaa,0x21,0x3f,0x6c,0xff,0x7e,0x70,0x2, 0xac,0x7f,0x7f,0x76,0x2d,0xf3, +0x69,0x17,0x0, 0x14,0xbe,0x14,0x7f,0xff,0x78,0x2, 0x21,0x34,0xa, 0x2f,0x9, 0xb2, +0x1e,0x60,0xb4,0xff,0x2, 0x80,0x2, 0x21,0x34,0x7e,0xb3,0x3c,0x29,0xb4,0x1, 0x67, +0x49,0x3, 0x3c,0x2b,0xbe,0x4, 0x7f,0xff,0x68,0x5d,0x49,0xb3,0x3c,0x2b,0x69,0x7, +0x0, 0x14,0x7d,0x40,0x9d,0x4b,0x2d,0x40,0x49,0xb3,0x3c,0x3f,0x69,0x7, 0x0, 0x28, +0x7d,0x30,0x9d,0x3b,0x2d,0x30,0xbe,0x44,0x0, 0x20,0x58,0x4, 0x7e,0x44,0x0, 0x20, +0xbe,0x34,0x0, 0x20,0x58,0x4, 0x7e,0x34,0x0, 0x20,0x7e,0x3, 0x29,0x5c,0x7e,0x10, +0x40,0xac,0x1, 0x9e,0x4, 0x0, 0x20,0xbd,0x4, 0x58,0x2, 0x7d,0x40,0x12,0x7b,0x3c, +0x9e,0x4, 0x0, 0x20,0xbd,0x3, 0x58,0x2, 0x7d,0x30,0x12,0x7b,0xd, 0x59,0x40,0x14, +0x5e,0x59,0x30,0x14,0x60,0x80,0xf, 0x12,0x7b,0xd, 0x59,0x10,0x14,0x5e,0x69,0x17, +0x0, 0x28,0x59,0x10,0x14,0x60,0xa, 0x1a,0x19,0xf1,0x1e,0x56,0x74,0x1, 0x19,0xb2, +0x1e,0x60,0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0xa, 0x50,0x2, 0x1, 0x87,0xb, 0xa0,0x7e, +0xb3,0x3c,0x2a,0xbc,0xba,0x28,0x2, 0x1, 0x85,0x6c,0xaa,0x12,0x7b,0x1f,0x69,0x30, +0x0, 0x14,0x59,0x32,0x3c,0x2b,0x69,0x30,0x0, 0x28,0x59,0x32,0x3c,0x3f,0xb, 0xa0, +0xbe,0xa0,0xa, 0x78,0xe6,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3,0x1e,0x56,0xb4,0xff,0x20, +0x6c,0xff,0xa, 0x4f,0x9, 0xb4,0x1e,0x60,0xb4,0xff,0xe, 0xa, 0x3a,0x19,0xf3,0x1e, +0x56,0x74,0x1, 0x19,0xb4,0x1e,0x60,0x80,0x7, 0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe2, +0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xd0,0x6c,0xaa,0x80,0x1e,0x7e,0x70,0x9, 0xac,0x7a, +0x49,0x43,0x27,0x82,0x7e,0x50,0x2, 0xac,0x5a,0x3e,0x24,0x59,0x42,0x14,0x86,0x49, +0x33,0x27,0x84,0x59,0x32,0x14,0x88,0xb, 0xa0,0x7e,0xb3,0x28,0xf4,0xbc,0xba,0x38, +0xda,0x7e,0x34,0x14,0x5e,0x7a,0x37,0x1e,0x50,0x7e,0x34,0x14,0x86,0x7a,0x37,0x1e, +0x52,0x7e,0x34,0x14,0xae,0x7a,0x37,0x1e,0x54,0x7e,0x73,0x3c,0x2a,0x7a,0x73,0x1e, +0x4e,0x7e,0x73,0x28,0xf4,0x7a,0x73,0x1e,0x4f,0x7e,0x8, 0x1e,0x4e,0x12,0x4, 0xad, +0x6c,0xaa,0x80,0x57,0x7e,0x70,0xff,0x6c,0xff,0x7e,0x50,0x2, 0xac,0x5f,0x49,0x12, +0x14,0xae,0xa, 0x2a,0xbd,0x21,0x78,0x8, 0xa, 0x3f,0x9, 0x73,0x1e,0x56,0x80,0x7, +0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xe2,0xbe,0x70,0xff,0x68,0x2d,0x12,0x7b,0x32,0x74, +0x1, 0xa, 0x47,0x19,0xb4,0x1e,0x44,0x7e,0x90,0x9, 0xac,0x9a,0x49,0x24,0x27,0x82, +0x7e,0x30,0x2, 0xac,0x37,0x2d,0x1d,0x7d,0xc, 0x79,0x20,0x0, 0x14,0x49,0x44,0x27, +0x84,0x7e,0x50,0x2, 0xac,0x57,0x12,0x7b,0x29,0xb, 0xa0,0x7e,0x63,0x28,0xf4,0xbc, +0x6a,0x38,0xa1,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3,0x1e,0x44,0xbe,0xb0,0x1, 0x68,0x13, +0x12,0x7b,0x15,0x7f,0x6, 0x2d,0x13,0x79,0x40,0x0, 0x14,0x2d,0x3d,0x7d,0x2c,0x79, +0x41,0x0, 0x28,0xb, 0xa0,0xbe,0xa0,0xa, 0x78,0xdb,0x7e,0xf3,0x28,0xf4,0x7a,0xf3, +0x3c,0x2a,0x6c,0xaa,0xa, 0x3a,0x9, 0xb3,0x1e,0x44,0xb4,0x1, 0x2c,0x12,0x7b,0x6, +0x29,0xb1,0x0, 0xa, 0xb4,0x1, 0x6, 0x74,0x3, 0x39,0xb1,0x0, 0xa, 0x12,0x7b,0x6, +0x29,0x31,0x0, 0xa, 0xa5,0xbb,0x3, 0x6, 0xe4,0x7a,0x1b,0xb0,0x80,0x38,0xa5,0xbb, +0x0, 0x34,0x74,0x2, 0x7a,0x1b,0xb0,0x80,0x2d,0x12,0x7b,0x6, 0x29,0xb1,0x0, 0xa, +0xbe,0xb0,0x2, 0x68,0x8, 0x60,0x6, 0x29,0xb1,0x0, 0x5a,0x70,0x14,0x74,0x1, 0x7a, +0x1b,0xb0,0x7c,0x2f,0xb, 0xf0,0x7e,0x30,0x9, 0xac,0x23,0x19,0xa1,0x27,0x86,0x80, +0x5, 0x74,0x3, 0x7a,0x1b,0xb0,0x12,0x7b,0x6, 0x7e,0x1b,0xb0,0x39,0xb1,0x0, 0xa, +0xa, 0x3a,0x2d,0x3d,0x29,0xb1,0x0, 0xa, 0x39,0xb1,0x0, 0x5a,0xb, 0xa0,0xbe,0xa0, +0xa, 0x40,0x81,0xda,0xf8,0x22,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c,0x22,0x7e,0x10,0x2, +0xac,0x1a,0x3e,0x4, 0x22,0x7e,0x44,0x7f,0xff,0x7e,0x70,0x2, 0xac,0x7a,0x22,0x7e, +0x50,0x2, 0xac,0x5a,0x7f,0x6, 0x2d,0x12,0x22,0x7f,0x6, 0x2d,0x12,0x79,0x40,0x0, +0x28,0x22,0x7e,0x50,0x9, 0xac,0x5a,0x19,0x72,0x27,0x86,0x22,0x7e,0x3, 0x29,0x5d, +0x7e,0x10,0x40,0xac,0x1, 0x22,0x7c,0x17,0x7c,0xab,0x7e,0x14,0xff,0xfc,0x7e,0x3, +0x28,0xf4,0x7e,0x90,0x9, 0xac,0x91,0x9, 0xb4,0x32,0x41,0xb4,0x1, 0x49,0xa5,0xb8, +0x1, 0xc, 0xbe,0x14,0xff,0x0, 0x28,0x10,0x7e,0x14,0xff,0x0, 0x80,0xa, 0xbe,0x14, +0xff,0xe0,0x28,0x4, 0x7e,0x14,0xff,0xe0,0x49,0x34,0x32,0x42,0x7e,0x50,0x9, 0xac, +0x5a,0x49,0x22,0x27,0x82,0x12,0x7c,0x5b,0x8, 0x3, 0x12,0x7c,0x65,0x7e,0x70,0x9, +0xac,0x71,0x49,0x33,0x32,0x44,0x7e,0x50,0x9, 0xac,0x5a,0x49,0x22,0x27,0x84,0x12, +0x7c,0x5b,0x8, 0x3, 0x12,0x7c,0x65,0x7e,0x70,0x9, 0xac,0x7a,0x9, 0x3, 0x27,0x88, +0xbe,0x0, 0xc, 0x28,0xc, 0xbe,0x14,0xff,0x80,0x28,0x26,0x7e,0x14,0xff,0x80,0x80, +0x20,0xbe,0x0, 0x8, 0x28,0xc, 0xbe,0x14,0xff,0xe0,0x28,0x15,0x7e,0x14,0xff,0xe0, +0x80,0xf, 0xbe,0x0, 0x6, 0x28,0xa, 0xbe,0x14,0xff,0xf0,0x28,0x4, 0x7e,0x14,0xff, +0xf0,0x7e,0x50,0x9, 0xac,0x51,0x49,0x22,0x32,0x42,0x49,0x33,0x27,0x82,0x12,0x7c, +0x51,0x18,0x16,0x74,0x9, 0xac,0x1b,0x49,0x20,0x32,0x44,0x7e,0x70,0x9, 0xac,0x7a, +0x49,0x33,0x27,0x84,0x12,0x7c,0x51,0x8, 0x4, 0x7e,0x14,0xff,0xfc,0x7e,0x50,0x9, +0xac,0x5a,0x49,0x2, 0x27,0x82,0xbe,0x4, 0x6, 0x50,0x40,0x2e,0x7e,0x63,0x29,0x5c, +0x7e,0x70,0x40,0xac,0x67,0x9e,0x34,0x0, 0x65,0x12,0x7c,0x71,0x3e,0x34,0xbd,0x3, +0x38,0x18,0x49,0x32,0x27,0x84,0xbe,0x34,0x6, 0x50,0x40,0xe, 0x12,0x7b,0x3c,0x9e, +0x4, 0x0, 0x65,0x12,0x7c,0x78,0xbd,0x30,0x28,0x4, 0x7e,0x14,0xff,0xff,0x7d,0x31, +0x22,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x4, 0x0, 0x22,0x9d,0x32,0x12,0x1a,0x62, +0xbe,0x34,0x1, 0x0, 0x22,0x6c,0x0, 0x7e,0x70,0x9, 0xac,0x71,0x19,0x3, 0x32,0x41, +0x22,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, +0x22,0x7d,0x13,0x7d,0x32,0x6d,0x22,0x74,0x6, 0x2f,0x11,0x14,0x78,0xfb,0xb, 0x14, +0x12,0x17,0x32,0x7d,0x53,0xbe,0x54,0x0, 0xff,0x28,0x4, 0x7e,0x54,0x0, 0x40,0x22, +0xca,0xf8,0x7e,0xf3,0x29,0x5d,0x7a,0x37,0x1e,0x4a,0x7e,0x34,0x14,0xae,0x7a,0x37, +0x1e,0x4c,0xe4,0x7a,0xb3,0x1e,0x44,0x7a,0xb3,0x1e,0x45,0x7e,0x73,0x29,0x5c,0x7a, +0x73,0x1e,0x46,0x7a,0xf3,0x1e,0x47,0x7a,0xb3,0x1e,0x48,0x7a,0xb3,0x1e,0x49,0x7e, +0x8, 0x1e,0x44,0x12,0x7c,0xf5,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x14,0xb0, +0x2f,0x10,0x7e,0x33,0x1e,0x46,0x6d,0x0, 0x12,0x17,0x34,0xa, 0x1f,0x6d,0x0, 0x12, +0x17,0x34,0xda,0xf8,0x22,0x12,0xc, 0x29,0x7e,0x37,0x14,0xae,0x22,0xca,0x3b,0x7a, +0x41,0x2a,0x12,0x7f,0xac,0x74,0x9, 0xac,0xbf,0x7d,0x95,0x2e,0x94,0x26,0x4a,0x6d, +0x88,0x7e,0xe7,0x29,0x53,0xe4,0x39,0xb4,0x0, 0x6, 0x7e,0x70,0x2, 0xac,0x7e,0x9, +0xb3,0x25,0xce,0xf5,0x35,0x9, 0xb3,0x25,0xcf,0xf5,0x36,0x7e,0x73,0x29,0x5b,0x7c, +0x6d,0x7e,0x8, 0x0, 0x39,0x12,0x7f,0x59,0xf5,0x37,0xe5,0x35,0x7e,0x73,0x29,0x5a, +0x7c,0x6c,0x7e,0x8, 0x0, 0x38,0x12,0x7f,0x59,0x7c,0xab,0xe5,0x38,0x7e,0x71,0x39, +0x12,0x27,0x49,0x7d,0xf3,0x7a,0xf5,0x41,0x7e,0xf4,0x14,0xae,0x7a,0xf5,0x43,0x85, +0x38,0x3b,0x85,0x39,0x3c,0x7a,0xa1,0x3d,0x85,0x37,0x3e,0x7e,0xb3,0x29,0x46,0xf5, +0x3f,0x75,0x40,0x0, 0xe5,0x2a,0xb4,0x1, 0x8, 0xe5,0x3f,0x1e,0xb0,0x1e,0xb0,0xf5, +0x3f,0x7e,0x8, 0x0, 0x3b,0x12,0x7c,0xf5,0x7d,0x23,0x6d,0x33,0x7e,0xb7,0x14,0xb0, +0x6d,0xaa,0x2f,0x51,0x7e,0x37,0x14,0xb2,0x6d,0x22,0x7d,0x3, 0x6d,0x11,0x7e,0x37, +0x14,0xb4,0x2f,0x10,0x7a,0x1d,0x2b,0x7e,0x37,0x14,0xb6,0x6d,0x22,0x7d,0x3, 0x7e, +0x37,0x14,0xb8,0x2f,0x10,0x7a,0x1d,0x2f,0x7f,0x65,0xa, 0x4c,0xe5,0x35,0xa, 0x5b, +0x9d,0x54,0xf5,0x33,0xc1,0x9d,0xa, 0x4d,0xe5,0x36,0xa, 0x5b,0x9d,0x54,0xf5,0x34, +0xc1,0x87,0xe5,0x33,0xbe,0xb0,0x0, 0x58,0x2, 0xc1,0x85,0x7e,0x73,0x29,0x5a,0xbe, +0x71,0x33,0x18,0x2, 0xc1,0x85,0xe5,0x34,0xbe,0xb0,0x0, 0x58,0x2, 0xc1,0x85,0x7e, +0x73,0x29,0x5b,0xbe,0x71,0x34,0x18,0x2, 0xc1,0x85,0xe5,0x33,0x7e,0x71,0x34,0x12, +0x21,0x50,0x7e,0x53,0x29,0x46,0xa, 0x25,0x7d,0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, +0x8, 0x73,0xbd,0xef,0x18,0xd, 0x7f,0x14,0x2e,0x34,0x0, 0x6, 0x7e,0x1b,0xb0,0x4, +0x7a,0x1b,0xb0,0xe5,0x35,0xa, 0x2b,0xe5,0x33,0x12,0x7f,0x3e,0x18,0xb, 0xe5,0x36, +0xa, 0x2b,0xe5,0x34,0x12,0x7f,0x3e,0x8, 0x4c,0xe5,0x33,0x7e,0x71,0x34,0x7c,0x6e, +0x12,0xca,0x29,0xf5,0x3a,0xb4,0x2, 0x6, 0x7d,0x3f,0xe, 0x34,0x9d,0xf3,0xe5,0x3a, +0xbe,0xb0,0x2, 0x68,0x5, 0xe5,0x3a,0xb4,0x1, 0x2b,0x12,0x7f,0x2d,0xe5,0x33,0x12, +0x7f,0x34,0x7e,0x1d,0x2b,0x9f,0x10,0x7a,0x1d,0x2b,0x12,0x7f,0x2d,0xe5,0x34,0x12, +0x7f,0x34,0x7e,0x1d,0x2f,0x9f,0x10,0x7a,0x1d,0x2f,0x12,0x7f,0x2d,0x9f,0x51,0x1a, +0x26,0x1a,0x24,0x9f,0x61,0x5, 0x34,0xa, 0x2d,0xe5,0x36,0xa, 0x3b,0x2d,0x32,0x1a, +0x27,0xe5,0x34,0x1a,0x3b,0xbd,0x32,0x18,0x2, 0xa1,0xd2,0x5, 0x33,0xa, 0x2c,0xe5, +0x35,0xa, 0x3b,0x2d,0x32,0x1a,0x37,0xe5,0x33,0x1a,0xfb,0xbd,0xf3,0x18,0x2, 0xa1, +0xc6,0xbe,0x58,0x0, 0x0, 0x78,0x2, 0xb, 0x5c,0xbe,0x68,0x0, 0x0, 0x78,0x2, 0xb, +0x6c,0x7e,0x1d,0x2b,0x7f,0x5, 0x12,0x7f,0x4a,0x1b,0x4a,0x30,0x7e,0x1d,0x2f,0x7f, +0x6, 0x12,0x7f,0x4a,0x79,0x34,0x0, 0x2, 0x7e,0xb3,0x29,0x52,0x60,0xd, 0x1e,0xd4, +0x1e,0xc4,0x50,0x4, 0x4e,0xd4,0x80,0x0, 0x14,0x78,0xf3,0xbe,0x68,0x0, 0x7f,0x28, +0x4, 0x7e,0x68,0x0, 0x7f,0x7d,0x3d,0x39,0x74,0x0, 0x5, 0x74,0x9, 0xac,0xbe,0x9, +0x75,0x26,0x50,0x39,0x74,0x0, 0x6, 0xbe,0x70,0xf, 0x28,0x6, 0x74,0xf, 0x39,0xb4, +0x0, 0x6, 0x7e,0xa1,0x35,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x26,0x51,0x7e,0xa1, +0x36,0x7e,0x70,0x9, 0xac,0x7f,0x19,0xa3,0x26,0x52,0xda,0x3b,0x22,0x7d,0x3f,0x1a, +0x26,0x1a,0x24,0x22,0x1a,0x1b,0x1a,0x2, 0x12,0x17,0x18,0x7f,0x1, 0x22,0x1a,0x3b, +0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x1, 0x22,0x74,0x6, 0x2f,0x11,0x14,0x78, +0xfb,0x12,0x17,0x34,0x2e,0x18,0x0, 0x20,0x22,0xca,0xf8,0x7c,0xf6,0x7c,0x87,0x7c, +0x9b,0xa, 0x2f,0x7d,0x32,0x3e,0x34,0xb, 0x34,0x7c,0xb7,0xbc,0xf9,0x38,0x14,0xa, +0xf8,0x1b,0xf4,0xa, 0x3f,0x9d,0xf3,0xa, 0x39,0xbd,0x3f,0x18,0x6, 0x7c,0xab,0xa, +0x39,0x80,0x1d,0xbc,0xf9,0x28,0xd, 0xa, 0x39,0xa, 0x5f,0x2d,0x53,0xb, 0x54,0x7c, +0xab,0xe4,0x80,0x10,0xa, 0x3f,0xa, 0x58,0x2d,0x53,0xa, 0x39,0x9d,0x53,0x7c,0xab, +0x9d,0x32,0x7c,0xb7,0x7a,0xb, 0xb0,0x7c,0xba,0xda,0xf8,0x22,0x7c,0xf5,0x7c,0xe6, +0x7c,0xd7,0x7c,0xcb,0x22,0x7a,0x37,0x1e,0x48,0x7e,0x34,0x14,0xb8,0x7a,0x37,0x1e, +0x4c,0x7e,0x34,0x14,0xae,0x7a,0x37,0x1e,0x4a,0x7e,0x73,0x29,0x5c,0x7a,0x73,0x1e, +0x45,0x7e,0x73,0x29,0x5d,0x7a,0x73,0x1e,0x44,0x7e,0x37,0x29,0x49,0x7a,0x37,0x1e, +0x4e,0x7e,0x37,0x29,0x4b,0x7a,0x37,0x1e,0x50,0x7e,0x37,0x29,0x4d,0x7a,0x37,0x1e, +0x52,0x74,0x1, 0x7a,0xb3,0x1e,0x46,0x7a,0xb3,0x1e,0x47,0x7e,0x8, 0x1e,0x44,0x7e, +0x18,0x1e,0x54,0x12,0x8, 0x0, 0x7e,0x37,0x1e,0x5e,0x7e,0x27,0x1e,0x5a,0xbd,0x23, +0x28,0x2, 0x7d,0x32,0x22,0x74,0xc8,0x7a,0xb3,0x3c,0x8e,0xc2,0x1a,0x80,0xa, 0x12, +0x3e,0x44,0x30,0x1a,0x4, 0x75,0xe9,0xff,0x22,0x12,0x80,0x57,0x68,0xf1,0x22,0x74, +0x1, 0x12,0x80,0x4e,0x20,0x1a,0x6, 0x12,0x3f,0x87,0x12,0x7, 0xfb,0x7e,0xb3,0x34, +0x3a,0xb4,0x1, 0x6, 0x12,0x80,0x15,0x12,0x7, 0xfb,0xe4,0x2, 0x80,0x4e,0xbe,0xb0, +0x8, 0x50,0x3, 0x12,0x80,0x68,0x22,0x7e,0xb3,0x34,0x3a,0xbe,0xb0,0x1, 0x22,0x12, +0x80,0x57,0x68,0xfb,0x20,0x93,0xfd,0x22,0xa, 0x5b,0x2e,0x54,0x0, 0x8, 0xf5,0xcc, +0x22,0x12,0x3e,0xbc,0x7e,0x73,0x3a,0x7d,0xbe,0x70,0xff,0x68,0x13,0xbe,0x73,0x3a, +0xa3,0x68,0xd, 0x7a,0x73,0x3a,0xa3,0x74,0xff,0x7a,0xb3,0x3a,0x7d,0x2, 0x3e,0xbc, +0x22,0x7e,0x34,0x0, 0x5a,0x22,0x7e,0xb3,0x3a,0xa3,0x70,0x2e,0x7e,0x73,0x3a,0x86, +0xbe,0x70,0x10,0x40,0x2, 0x6c,0x77,0x7e,0xb3,0x3a,0xce,0xb4,0x1, 0x3, 0x7e,0x70, +0x6, 0xa, 0x37,0x2e,0x34,0xf, 0xf0,0x12,0x80,0xef,0x7c,0xab,0xe5,0x6a,0xa, 0x3b, +0x2e,0x37,0x3b,0xec,0x7a,0x37,0x3b,0xec,0x80,0xc, 0x7e,0xa3,0x3a,0x87,0xbe,0xa0, +0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x2, 0x80,0xdb,0x75,0x6a,0x0, 0x7a,0xb3, +0x3c,0x8e,0xc2,0x1a,0x22,0x7c,0xb7,0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x5e,0x7a, +0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7c,0x7b,0x12,0x81,0xb, 0x9, 0xa2,0x26, +0x46,0x12,0x80,0xe5,0x5c,0xba,0x22,0x7c,0xa5,0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, +0x2b,0x22,0x7e,0x8, 0x25,0x5a,0x7e,0x34,0x0, 0x3, 0xe4,0x12,0x1a,0x30,0x7e,0x8, +0x25,0x5d,0x7e,0x34,0x0, 0x3, 0x12,0x1a,0x30,0x7a,0xb3,0x25,0x57,0x7a,0xb3,0x25, +0x58,0x7a,0xb3,0x25,0x59,0x7a,0xb3,0x25,0xc4,0x7a,0xb3,0x25,0xc5,0x7a,0xb3,0x25, +0xc6,0x7e,0x18,0x25,0x43,0x12,0x84,0xe9,0x6c,0x55,0x12,0x81,0xd8,0x7a,0xb3,0x25, +0x59,0x7e,0x18,0x25,0x2f,0x12,0x85,0x4d,0x6c,0x55,0x12,0x81,0xd8,0x7a,0xb3,0x25, +0x58,0x6c,0x77,0x80,0x14,0x12,0x84,0xb2,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12, +0x81,0x7, 0x2e,0x24,0x25,0x5a,0x12,0x84,0xc6,0x7e,0x63,0x25,0x58,0xbc,0x67,0x38, +0xe4,0x6c,0x77,0x80,0x14,0x12,0x84,0xb2,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0x12, +0x81,0x7, 0x2e,0x24,0x25,0x5d,0x12,0x84,0xc6,0x7e,0xa3,0x25,0x59,0xbc,0xa7,0x38, +0xe4,0x7e,0xb3,0x25,0x58,0xa4,0x7a,0xb3,0x25,0x57,0x7e,0x18,0x25,0xba,0x12,0x84, +0xe9,0x7e,0x50,0x1, 0x12,0x81,0xd8,0x7a,0xb3,0x25,0xc6,0x7e,0x18,0x25,0xb0,0x12, +0x85,0x4d,0x7e,0x50,0x1, 0x12,0x81,0xd8,0x7c,0xab,0x7a,0xa3,0x25,0xc5,0x7e,0xb3, +0x25,0xc6,0xa4,0x7a,0xb3,0x25,0xc4,0x22,0xca,0x69,0xca,0xf8,0x7c,0x4b,0x6c,0xaa, +0x6d,0xff,0x6c,0xff,0x80,0x70,0x7e,0xd0,0x2, 0xac,0xdf,0x7f,0x60,0x2d,0xd6,0xb, +0x6a,0xe0,0x4c,0x55,0x68,0x6, 0x6e,0xe4,0xff,0xff,0xb, 0xe4,0xbd,0x3e,0x58,0x54, +0x4c,0xff,0x78,0x8, 0x6d,0x44,0x69,0xf0,0x0, 0x2, 0x80,0x1b,0x7c,0xb4,0x14,0xbc, +0xbf,0x7f,0x56,0x78,0x9, 0x1b,0xb5,0xb, 0x5a,0x40,0x6d,0xff,0x80,0x9, 0x1b,0xb5, +0xb, 0x5a,0x40,0x69,0xf6,0x0, 0x2, 0x4c,0x55,0x68,0xc, 0x6e,0x44,0xff,0xff,0xb, +0x44,0x6e,0xf4,0xff,0xff,0xb, 0xf4,0xbd,0x4e,0x58,0x19,0xbd,0xfe,0x18,0x15,0xa, +0xba,0x7e,0x6d,0x24,0x2d,0xdb,0x7a,0x6b,0xf0,0xb, 0xa0,0x90,0x60,0x9b,0xe4,0x93, +0xbc,0xba,0x28,0x6, 0xb, 0xf0,0xbc,0x4f,0x38,0x8c,0x7c,0xba,0xda,0xf8,0xda,0x69, +0x22,0xca,0x3b,0xe4,0x7a,0xb3,0x27,0x67,0x12,0xce,0x34,0x7e,0xb3,0x15,0xa1,0xb4, +0x1, 0x8, 0x7e,0x73,0x27,0x58,0x7a,0x73,0x27,0x66,0x7e,0x18,0x4, 0xc0,0x7a,0x1f, +0x6, 0x44,0x12,0x5f,0x7f,0x12,0x81,0x12,0x7e,0x73,0x25,0x59,0xbe,0x70,0x2, 0x50, +0x2, 0x61,0x29,0x6c,0xff,0x61,0x19,0xa, 0x5f,0xb, 0x54,0x7c,0xab,0x6c,0xee,0x80, +0xc, 0xa, 0x3e,0x9, 0xb3,0x25,0x43,0xbc,0xbf,0x68,0xa, 0xb, 0xe0,0x7e,0xb3,0x25, +0x59,0xbc,0xbe,0x38,0xec,0x7e,0x33,0x25,0x59,0xbc,0x3e,0x68,0x5a,0x6c,0xee,0x80, +0x12,0xa, 0x3e,0x9, 0x23,0x25,0x43,0xa, 0x22,0xa, 0x3f,0xb, 0x35,0xbd,0x23,0x68, +0x6, 0xb, 0xe0,0xbc,0x3e,0x38,0xea,0xbc,0x3e,0x78,0x4, 0xb, 0xf1,0x80,0x38,0x12, +0x84,0xdd,0x7f,0x75,0x1b,0xf5,0xb, 0x7a,0x30,0x7e,0xc4,0x0, 0x3, 0x12,0x84,0xbb, +0xb, 0x5a,0x40,0xbd,0x43,0x8, 0x20,0x69,0x5, 0x0, 0x2, 0x7d,0x30,0x12,0x84,0xab, +0xbd,0x43,0x8, 0x13,0xb, 0x7a,0x40,0x2d,0x40,0x12,0x84,0x9f,0xb, 0x1a,0x30,0x9d, +0x43,0x12,0x84,0x9f,0x1b,0x1a,0x40,0xb, 0xf0,0x7e,0x23,0x29,0x5b,0xa, 0x22,0x1b, +0x25,0xa, 0x3f,0xbd,0x32,0x58,0x2, 0x41,0x97,0x7e,0x73,0x25,0x58,0xbe,0x70,0x2, +0x50,0x2, 0x61,0xcb,0x6c,0xff,0x61,0xc1,0xa, 0x1f,0x7e,0x73,0x29,0x5b,0xa, 0x57, +0x2d,0x51,0xb, 0x54,0x7c,0xab,0x6c,0xee,0x80,0xc, 0xa, 0xe, 0x9, 0xb0,0x25,0x2f, +0xbc,0xbf,0x68,0xa, 0xb, 0xe0,0x7e,0xb3,0x25,0x58,0xbc,0xbe,0x38,0xec,0x7e,0x13, +0x25,0x58,0xbc,0x1e,0x68,0x59,0x6c,0xee,0x80,0x12,0xa, 0x3e,0x9, 0x3, 0x25,0x2f, +0xa, 0x20,0x7d,0x31,0xb, 0x35,0xbd,0x23,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xea, +0xbc,0x1e,0x78,0x4, 0xb, 0xf1,0x80,0x37,0x12,0x84,0xdd,0x7f,0x15,0x1b,0x35,0xb, +0x1a,0xf0,0x7e,0xc4,0x0, 0x3, 0x7d,0x3f,0x12,0x84,0xbb,0xb, 0x5a,0xe0,0xbd,0xe3, +0x8, 0x1d,0x69,0x45,0x0, 0x2, 0x7d,0x34,0x12,0x84,0xab,0xbd,0xe3,0x8, 0x10,0x2d, +0x4f,0x12,0x84,0xd1,0xb, 0x1a,0x30,0x9d,0x43,0x12,0x84,0xd1,0x1b,0x1a,0x40,0xb, +0xf0,0x7e,0x3, 0x29,0x5a,0xbc,0xf, 0x28,0x2, 0x61,0x38,0x12,0x81,0x12,0x6c,0xff, +0x80,0x43,0xa, 0x4f,0x9, 0xb4,0x25,0x43,0x7c,0xab,0xbe,0xb0,0x2, 0x40,0x10,0x12, +0x85,0x35,0x8, 0xb, 0x12,0x85,0x20,0x8, 0x6, 0x12,0x86,0x79,0x1b,0x1a,0x40,0xa, +0x3f,0x9, 0xb3,0x25,0x43,0xa, 0x2b,0x7e,0xb3,0x29,0x5b,0xa, 0x3b,0x1b,0x35,0xbd, +0x23,0x58,0x10,0x12,0x85,0xb, 0x8, 0xb, 0x12,0x84,0xf9,0x8, 0x6, 0x12,0x84,0x9b, +0x1b,0x1a,0x10,0xb, 0xf0,0x7e,0xb3,0x25,0x59,0xbc,0xbf,0x38,0xb5,0x6c,0xff,0x80, +0x4a,0xa, 0x4f,0x9, 0xb4,0x25,0x2f,0xa, 0x2b,0x12,0x87,0xf7,0x2d,0x32,0x7c,0xa7, +0xbe,0xb0,0x2, 0x40,0x10,0x12,0x85,0x35,0x8, 0xb, 0x12,0x85,0x20,0x8, 0x6, 0x12, +0x86,0x79,0x1b,0x1a,0x40,0xa, 0x3f,0x9, 0xb3,0x25,0x2f,0xa, 0x2b,0x7e,0xb3,0x29, +0x5a,0xa, 0x3b,0x1b,0x35,0xbd,0x23,0x58,0x10,0x12,0x85,0xb, 0x8, 0xb, 0x12,0x84, +0xf9,0x8, 0x6, 0x12,0x84,0x9b,0x1b,0x1a,0x10,0xb, 0xf0,0x7e,0xb3,0x25,0x58,0xbc, +0xbf,0x38,0xae,0x12,0x81,0x12,0x12,0x5d,0x11,0x7e,0xb3,0x15,0xa0,0xb4,0x1, 0x18, +0x7e,0x73,0x25,0x57,0x7a,0x73,0x25,0xc7,0x7e,0x73,0x25,0x59,0x7a,0x73,0x25,0xc9, +0x7e,0x73,0x25,0x58,0x7a,0x73,0x25,0xc8,0xda,0x3b,0x22,0x79,0x7, 0x0, 0x2, 0x7e, +0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x6, 0x44,0x2d,0x30,0x22,0xad,0x3c,0x7d,0x2d,0x2, +0x16,0xe6,0x7c,0xb7,0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x22,0xad,0x3c,0x7e,0xd4,0x0, +0x4, 0x7d,0x2d,0x2, 0x16,0xe6,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70, +0x22,0x7e,0xd0,0x2, 0xac,0xda,0x7e,0x1f,0x6, 0x44,0x2d,0x36,0x22,0x7e,0x70,0x2, +0xac,0x7a,0x7e,0x5f,0x6, 0x44,0x2d,0xb3,0x22,0x7a,0x1d,0x24,0x7e,0xf, 0x6, 0x44, +0x7e,0xb3,0x29,0x5b,0x7e,0x37,0x29,0x40,0x22,0x69,0x17,0x0, 0x2, 0x7e,0x24,0x0, +0xa, 0x7d,0x31,0x12,0x16,0xe6,0x2d,0x31,0xbd,0x30,0x22,0x7e,0x70,0x2, 0xac,0x7a, +0x7e,0x7f,0x6, 0x44,0x2d,0xf3,0xb, 0x7a,0x0, 0x69,0x17,0x0, 0x4, 0xbd,0x10,0x22, +0x1b,0x15,0xb, 0xa, 0x40,0x7e,0x24,0x0, 0xa, 0x7d,0x34,0x12,0x16,0xe6,0x7d,0xe4, +0x2d,0xe3,0xbd,0xef,0x22,0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x6, 0x44,0x2d,0x13, +0x7f,0x10,0x1b,0x36,0xb, 0x1a,0xe0,0xb, 0xa, 0xf0,0xbd,0xef,0x22,0x7a,0x1d,0x24, +0x7e,0xa3,0x29,0x5b,0x74,0x2, 0xa4,0x7e,0xf, 0x6, 0x44,0x2d,0x15,0x7e,0xb3,0x29, +0x5a,0x7e,0x37,0x29,0x3e,0x22,0x12,0xb3,0x5c,0xe4,0x7a,0xb3,0x3, 0xfd,0x2, 0x82, +0x61,0x7c,0x7b,0x12,0x81,0xb, 0x9, 0xa2,0x25,0x5d,0x12,0x80,0xe5,0x5c,0xba,0x22, +0x7c,0x7b,0x12,0x81,0xb, 0x9, 0xa2,0x25,0x5a,0x12,0x80,0xe5,0x5c,0xba,0x22,0xca, +0xd8,0xca,0x79,0x6c,0xdd,0x6c,0xff,0x6c,0xee,0x80,0x30,0x7c,0xbe,0x12,0x85,0x80, +0x60,0x27,0x7e,0x34,0x0, 0x1, 0xca,0x39,0xa, 0x3e,0x2e,0x34,0x25,0x2f,0x6d,0x22, +0xa, 0x1d,0x2e,0x14,0x25,0x2f,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7c,0xbd,0x7e, +0x70,0x1, 0x6c,0x66,0x12,0x86,0x2b,0xb, 0xd0,0xb, 0xe0,0x7e,0x73,0x25,0x58,0xbc, +0x7e,0x38,0xc8,0x7a,0xd3,0x25,0x58,0x6c,0xee,0x80,0x31,0x7c,0xbe,0x12,0x85,0x71, +0x60,0x28,0x7e,0x34,0x0, 0x1, 0xca,0x39,0xa, 0x3e,0x2e,0x34,0x25,0x43,0x6d,0x22, +0xa, 0x1f,0x2e,0x14,0x25,0x43,0x6d,0x0, 0x12,0x1a,0xb, 0x1b,0xfd,0x7c,0xbf,0x7e, +0x70,0x1, 0x7e,0x60,0x1, 0x12,0x86,0x2b,0xb, 0xf0,0xb, 0xe0,0x7e,0x73,0x25,0x59, +0xbc,0x7e,0x38,0xc7,0x7a,0xf3,0x25,0x59,0x7e,0x63,0x25,0x59,0x7e,0x73,0x25,0x58, +0xac,0x76,0x7a,0x73,0x25,0x57,0xda,0x79,0xda,0xd8,0x22,0x7c,0x56,0x12,0xd0,0x2a, +0x54,0x7, 0xa, 0x1b,0x2e,0x14,0x0, 0x5e,0x12,0xd0,0xb0,0x7c,0x7b,0xa5,0xbd,0x0, +0x15,0x4c,0x66,0x68,0x8, 0xa, 0x2a,0x2e,0x24,0x25,0x5a,0x80,0x17,0x12,0x86,0x72, +0x2e,0x24,0x25,0x5a,0x80,0x18,0xa5,0xbd,0x1, 0x17,0x4c,0x66,0x68,0x9, 0xa, 0x2a, +0x2e,0x24,0x25,0x5d,0x2, 0xd0,0xa7,0x12,0x86,0x72,0x2e,0x24,0x25,0x5d,0x12,0x27, +0x97,0x22,0x7c,0xb7,0x64,0xff,0xa, 0x2a,0x22,0x1b,0xa, 0xf0,0x7e,0x30,0x2, 0xac, +0x3a,0x7e,0x1f,0x6, 0x44,0x2d,0x31,0x22,0x7c,0x2b,0x7e,0xb3,0x1e,0x43,0xbc,0x2b, +0x68,0x55,0x12,0x86,0xec,0x7c,0x3b,0x7c,0xb2,0x12,0x86,0xec,0x7c,0xab,0xbe,0x30, +0xff,0x68,0x44,0xbe,0xa0,0xff,0x68,0x3f,0x7e,0x70,0x4, 0xac,0x73,0xa, 0x2a,0x2d, +0x32,0x2e,0x34,0x1a,0x52,0x12,0x80,0xef,0xbe,0xb0,0x2, 0x38,0x2a,0xa, 0x2b,0x7e, +0x34,0x2, 0xe0,0xad,0x32,0x2e,0x34,0x15,0xa3,0x6d,0x22,0x30,0x19,0x3, 0x2, 0x87, +0x8f,0x7e,0xb3,0x2a,0xa, 0xb4,0x1, 0xf, 0x12,0xcf,0xfa,0x7a,0x55,0x29,0x7e,0x8, +0xc, 0xd8,0x74,0x1, 0x2, 0x87,0xc0,0x22,0x7e,0xb3,0x29,0xfc,0x7c,0xab,0x6c,0x77, +0x7e,0x50,0x5, 0xac,0x57,0x9, 0x62,0x25,0x7, 0xbc,0x6a,0x78,0x3, 0x7c,0xb7,0x22, +0xb, 0x70,0xbe,0x70,0x4, 0x40,0xe9,0x74,0xff,0x22,0xca,0x3b,0x7e,0xb3,0x29,0xfc, +0x7a,0xb3,0x1e,0x43,0x7e,0xf3,0x2a,0x4f,0x12,0x86,0xec,0x7c,0xdb,0xbe,0xd0,0xff, +0x68,0x6a,0x6c,0xcc,0x12,0xd0,0xcb,0xf5,0x29,0x7e,0x73,0x29,0xfc,0xbe,0x71,0x29, +0x68,0x3c,0x7e,0x70,0x4, 0xac,0x7d,0xa, 0x2c,0x2d,0x32,0x2e,0x34,0x1a,0x52,0x12, +0x80,0xef,0x7c,0xeb,0xbe,0xe0,0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, 0xe0,0xad, +0x10,0x2e,0x14,0x15,0xa3,0x6d,0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x1d,0xac,0x7e,0x2e, +0x34,0x3a,0xf2,0x6d,0x22,0x7a,0x1f,0x3a,0xee,0x7c,0xbc,0x12,0x56,0x9d,0xb, 0xc0, +0xbe,0xc0,0x4, 0x40,0xaf,0x7e,0x73,0x2a,0x4f,0xbc,0x7f,0x68,0x6, 0x7a,0xf3,0x2a, +0x4f,0xd2,0xf, 0xd2,0x0, 0x7e,0xb3,0x1e,0x43,0x12,0x54,0xf8,0xda,0x3b,0x22,0x7c, +0x7b,0x90,0x60,0x93,0xe4,0x93,0xa, 0x1b,0x7e,0x63,0x29,0x5e,0xa, 0x6, 0x2d,0x1, +0x7e,0x63,0x29,0x5b,0xa, 0x16,0xad,0x10,0x7d,0x21,0x12,0xd0,0x9e,0xa, 0x26,0x7a, +0x25,0x29,0x74,0x1d,0xac,0x7b,0x2e,0x34,0x3a,0xf2,0x6d,0x22,0xe4,0x2, 0x87,0xc0, +0x7c,0xab,0x6d,0x44,0x80,0x29,0x4c,0xaa,0x68,0x11,0x12,0xcf,0xaa,0x60,0x5, 0x3e, +0xe4,0x14,0x78,0xfb,0x12,0xd0,0x57,0x2d,0xfe,0x80,0xf, 0x12,0xcf,0xaa,0x60,0x5, +0x3e,0xe4,0x14,0x78,0xfb,0x12,0xd0,0x57,0x9d,0xfe,0x1b,0x6a,0xf0,0xb, 0x44,0x7e, +0xf5,0x29,0xbd,0xf4,0x38,0xd0,0x22,0x7e,0xa3,0x29,0x5b,0xa, 0x3a,0x22,0x7e,0xb3, +0x3b,0xef,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x3b,0xef,0x22,0x7f,0x20, +0xc2,0x1, 0x7e,0x2b,0x60,0x29,0x72,0x0, 0x2, 0x9c,0x76,0x1a,0x37,0x12,0x1a,0x62, +0x7c,0x27,0x29,0x72,0x0, 0x1, 0x29,0x32,0x0, 0x3, 0x9c,0x37,0x1a,0x33,0x12,0x1a, +0x62,0x7c,0x37,0x1a,0x23,0x1a,0x32,0x9d,0x32,0x12,0x1a,0x62,0x7c,0x67,0x7c,0x72, +0xbc,0x32,0x58,0x2, 0x7c,0x73,0xbe,0x60,0x5, 0x18,0x5, 0xbe,0x70,0x6, 0x58,0x8, +0x7e,0x37,0x3b,0xa1,0x4d,0x33,0x68,0x2, 0xd2,0x1, 0xa2,0x1, 0x22,0xca,0x3b,0xc2, +0x0, 0x6d,0x88,0x7e,0x64,0x0, 0x28,0x7e,0x37,0x27,0x5e,0xbe,0x34,0x5, 0xdc,0x8, +0x6, 0x2e,0x64,0x0, 0xa, 0x80,0x20,0xbe,0x34,0x4, 0xb0,0x8, 0x6, 0x2e,0x64,0x0, +0x5, 0x80,0x14,0xbe,0x34,0x3, 0x84,0x8, 0x6, 0x2e,0x64,0x0, 0x3, 0x80,0x8, 0xbe, +0x34,0x2, 0x58,0x8, 0x2, 0xb, 0x65,0x7a,0x87,0x3b,0xea,0xe4,0x7a,0xb3,0x1e,0x68, +0xe5,0x1e,0xbe,0xb0,0xff,0x50,0x2, 0x5, 0x1e,0x7e,0xb3,0x27,0x58,0x60,0xa, 0x7e, +0x87,0x7, 0xa, 0xbe,0x84,0x0, 0xc8,0x58,0xa, 0xc2,0x13,0x6d,0x88,0x7a,0x87,0x3b, +0xab,0x21,0xaa,0x12,0x91,0x60,0x60,0xc, 0x7e,0x84,0x0, 0x64,0x7a,0x87,0x3b,0xa1, +0x7a,0x67,0x3b,0xab,0x6c,0xff,0x80,0x7a,0xe4,0xa, 0x3f,0x19,0xb3,0x1e,0x44,0x12, +0x8c,0x5e,0x9, 0xe3,0x25,0xcf,0x7e,0x8, 0x1e,0x62,0x7c,0x7e,0x12,0x8f,0xfc,0x7d, +0x93,0x7e,0x87,0x3b,0xab,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x3b,0xab,0x7e,0x87,0x3b, +0xea,0xbd,0x89,0x50,0x4, 0x7a,0x97,0x3b,0xea,0xe5,0x1e,0xbe,0xb0,0x5, 0x38,0x23, +0x7e,0x8, 0x3b,0xad,0xe5,0x24,0x7c,0x7e,0x12,0x8d,0xf4,0x50,0x7, 0x12,0x8c,0x55, +0xd2,0x0, 0x80,0x2c,0x7e,0x8, 0x3b,0xad,0x7e,0x18,0x1e,0x62,0x12,0x8f,0x2d,0x50, +0x1f,0x80,0xd, 0xbd,0x69,0x38,0x19,0x7e,0x8, 0x1e,0x62,0x12,0x88,0xe, 0x50,0x10, +0x12,0x8c,0x55,0x7e,0x8, 0x1e,0x68,0x7e,0x18,0x1e,0x62,0x12,0x91,0x1b,0xd2,0x0, +0xb, 0xf0,0x12,0x8a,0x8, 0x38,0x81,0x30,0x0, 0x36,0x6c,0xff,0x80,0x22,0x12,0x8c, +0x5e,0x9, 0xe3,0x25,0xcf,0x7e,0x8, 0x1e,0x68,0x7c,0x7e,0x12,0x8d,0xf4,0x40,0x9, +0xa, 0x3f,0x9, 0xb3,0x1e,0x44,0xb4,0x1, 0x5, 0x7c,0xbf,0x12,0x8d,0xd6,0xb, 0xf0, +0x12,0x8a,0x8, 0x38,0xd9,0x75,0x1e,0x0, 0x7e,0x34,0x0, 0x64,0x7a,0x37,0x3b,0xa1, +0x7e,0x63,0x1e,0x68,0x7e,0x70,0x6, 0xac,0x67,0xb, 0x34,0xca,0x39,0x7e,0x18,0x1e, +0x68,0x7e,0x8, 0x3b,0xad,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x37,0x3b,0xa1,0x4d,0x33, +0x78,0x32,0x7e,0x37,0x3b,0xab,0xbd,0x36,0x40,0x3e,0x7d,0x36,0x1e,0x34,0xbe,0x37, +0x3b,0xea,0x38,0x34,0x90,0x60,0x51,0x12,0x8c,0x4c,0x7e,0x73,0x25,0xcb,0xa, 0x37, +0xbd,0x32,0x8, 0x24,0x90,0x60,0x50,0x12,0x8c,0x4c,0x7e,0x73,0x25,0xca,0xa, 0x37, +0xbd,0x32,0x8, 0x14,0x6c,0xff,0x80,0x7, 0x7c,0xbf,0x12,0x8d,0xd6,0xb, 0xf0,0x12, +0x8a,0x8, 0x38,0xf4,0xd2,0x0, 0x80,0x6, 0x6d,0x33,0x7a,0x37,0x3b,0xab,0xa2,0x0, +0x92,0x13,0x12,0x91,0x41,0xda,0x3b,0x22,0x7e,0x73,0x27,0x58,0xbc,0x7f,0x22,0xca, +0x79,0x7e,0xc4,0x0, 0x7, 0x7e,0xb3,0x27,0x58,0x70,0x20,0x6d,0xcc,0x7a,0xc7,0x38, +0xfe,0x7a,0xc7,0x38,0xfc,0xc2,0x14,0x7e,0x8, 0x39,0x0, 0x7e,0x34,0x0, 0x4, 0x74, +0xff,0x12,0x1a,0x30,0xe4,0x7a,0xb3,0x38,0xfb,0x61,0xf7,0x12,0x8c,0x2a,0x38,0x2, +0x61,0x48,0x6c,0xee,0x41,0xf3,0x6c,0xff,0x41,0xea,0x12,0x8b,0xfa,0xa, 0x27,0xa, +0x3e,0x9, 0x73,0x39,0x0, 0x12,0x7f,0x40,0x18,0x7d,0x12,0x8c,0x7, 0xa, 0x27,0xa, +0x3e,0x9, 0x73,0x39,0x2, 0x12,0x7f,0x40,0x18,0x6d,0x12,0x8d,0x9c,0x58,0x4, 0x7e, +0xc4,0x0, 0x6, 0x12,0x8c,0x14,0x68,0x5, 0x12,0x77,0x9a,0x78,0x4, 0x7e,0xc4,0x0, +0x6, 0xbd,0xc4,0x58,0x18,0x7e,0x34,0x1, 0x90,0x74,0x2, 0xac,0xbe,0x12,0x8c,0x10, +0x68,0x5, 0x12,0x77,0x9a,0x78,0x13,0x7e,0x34,0x3, 0x20,0x80,0xa, 0x7d,0x5c,0x1b, +0x55,0xbd,0x54,0x48,0x5, 0x6d,0x33,0x12,0x8c,0x3a,0x7e,0x70,0x2, 0xac,0x7e,0x49, +0x53,0x38,0xfc,0xbe,0x54,0x0, 0x0, 0x28,0x19,0x2e,0x34,0x38,0xfc,0x1b,0x54,0x1b, +0x38,0x50,0x12,0x8b,0xfa,0xa, 0x5e,0x12,0x8c,0x3, 0xa, 0x5e,0x19,0x75,0x39,0x2, +0x80,0x1f,0x12,0x8c,0x6a,0x80,0x1a,0x7e,0xb3,0x27,0x58,0x14,0xbc,0xbf,0x78,0x8, +0x6d,0x33,0x12,0x8c,0x3a,0x12,0x8c,0x6a,0xb, 0xf0,0x12,0x8a,0x8, 0x28,0x2, 0x41, +0x4a,0xb, 0xe0,0x7e,0x73,0x38,0xfb,0xbc,0x7e,0x28,0x2, 0x41,0x46,0x7e,0x57,0x38, +0xfc,0x4d,0x55,0x78,0x29,0x12,0x8c,0x43,0x28,0x24,0x7a,0x57,0x38,0xfc,0x7e,0x73, +0x39,0x1, 0x7a,0x73,0x39,0x0, 0x7e,0x73,0x39,0x3, 0x7a,0x73,0x39,0x2, 0x6d,0x55, +0x7a,0x57,0x38,0xfe,0x74,0xff,0x7a,0xb3,0x39,0x1, 0x7a,0xb3,0x39,0x3, 0xe4,0x7a, +0xb3,0x38,0xfb,0x7e,0x57,0x38,0xfc,0xbe,0x54,0x0, 0x0, 0x28,0x3, 0x12,0x8c,0x20, +0x12,0x8c,0x43,0x28,0x3, 0x12,0x8c,0x20,0x7e,0x73,0x38,0xfb,0xbe,0x70,0x2, 0x40, +0x2, 0x61,0xe3,0x7e,0x73,0x27,0x58,0xbe,0x73,0x38,0xfb,0x38,0x2, 0x61,0xe3,0x6c, +0xff,0x80,0x7b,0x12,0x8b,0xfa,0xa, 0x27,0x7e,0x73,0x39,0x0, 0xa, 0x37,0x12,0x7f, +0x40,0x18,0x10,0x12,0x8c,0x7, 0xa, 0x27,0x7e,0x73,0x39,0x2, 0xa, 0x37,0x12,0x7f, +0x40,0x8, 0x59,0x12,0x8d,0x9c,0x58,0x4, 0x7e,0xc4,0x0, 0x6, 0x12,0x8c,0x14,0x68, +0x5, 0x12,0x77,0x9a,0x78,0x4, 0x7e,0xc4,0x0, 0x5, 0xbd,0xc4,0x58,0x35,0x7e,0x34, +0x1, 0x90,0x12,0x8c,0x32,0x12,0x8c,0x10,0x68,0x5, 0x12,0x77,0x9a,0x78,0xb, 0x7e, +0x34,0x3, 0x20,0x12,0x8c,0x32,0x59,0x35,0x38,0xfc,0x12,0x8b,0xfa,0x7e,0x63,0x38, +0xfb,0xa, 0x56,0x12,0x8c,0x3, 0x7e,0x63,0x38,0xfb,0xa, 0x56,0x19,0x75,0x39,0x2, +0x12,0x8c,0x20,0x7e,0xb3,0x38,0xfb,0xbe,0xb0,0x2, 0x68,0x7, 0xb, 0xf0,0x12,0x8a, +0x8, 0x38,0x80,0x12,0x8c,0x2a,0x28,0xd, 0x20,0x14,0xc, 0xd2,0x14,0x74,0x14,0x7a, +0xb3,0x32,0x3d,0x80,0x2, 0xc2,0x14,0xda,0x79,0x22,0x74,0x2, 0xac,0xbf,0x9, 0x75, +0x25,0xce,0x22,0x19,0x75,0x39,0x0, 0x74,0x2, 0xac,0xbf,0x9, 0x75,0x25,0xcf,0x22, +0x59,0x35,0x38,0xfc,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xa3,0x25,0xce,0x4c,0xaa,0x22, +0x7e,0xb3,0x38,0xfb,0x4, 0x7a,0xb3,0x38,0xfb,0x22,0x7e,0x73,0x38,0xfb,0xbe,0x70, +0x0, 0x22,0x7e,0xa3,0x38,0xfb,0x74,0x2, 0xa4,0x22,0x74,0x2, 0xac,0xbe,0x59,0x35, +0x38,0xfc,0x22,0x7e,0x57,0x38,0xfe,0xbe,0x54,0x0, 0x0, 0x22,0xe4,0x93,0x7c,0x7b, +0x1e,0x70,0xa, 0x27,0x22,0x74,0x1, 0xa, 0x8f,0x19,0xb8,0x1e,0x44,0x22,0x7e,0x70, +0x2, 0xac,0x7f,0x9, 0xb3,0x25,0xce,0xf5,0x24,0x22,0x74,0xff,0xa, 0x3e,0x19,0xb3, +0x39,0x0, 0x19,0xb3,0x39,0x2, 0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7a,0x9, 0xb3, +0x25,0xce,0x9, 0x73,0x25,0xcf,0x2, 0x21,0x50,0xca,0xd8,0xca,0x79,0x7e,0xa3,0x29, +0x5b,0x7e,0x47,0x27,0x6d,0xe4,0x7a,0xb3,0x27,0x7a,0x7e,0xb3,0x25,0xc4,0xbe,0xb0, +0x0, 0x28,0x48,0x12,0x8f,0xe3,0x28,0x43,0x6c,0xff,0x80,0x3b,0x7e,0x50,0x2, 0xac, +0x5f,0x9, 0xd2,0x26,0xa, 0x9, 0xe2,0x26,0xb, 0x7e,0x50,0x2, 0xac,0x5e,0x49,0x12, +0x4, 0xc0,0x6d,0x22,0x9e,0x27,0x29,0x40,0xbd,0x12,0x58,0x19,0x12,0x8d,0xcd,0x49, +0x12,0x4, 0xc0,0x6d,0x22,0x9e,0x27,0x29,0x3e,0xbd,0x12,0x58,0x8, 0x74,0x1, 0x7a, +0xb3,0x27,0x7a,0x80,0x6, 0xb, 0xf0,0xbc,0x7f,0x38,0xc1,0xe4,0x7a,0xb3,0x27,0x7b, +0x7e,0xb3,0x25,0x57,0x70,0x40,0x12,0x4b,0xd2,0x28,0x3b,0x6c,0xff,0x80,0x33,0x7e, +0x50,0x2, 0xac,0x5f,0x9, 0xd2,0x25,0xce,0x9, 0xe2,0x25,0xcf,0x12,0x8d,0xcd,0x49, +0x2, 0x5, 0x20,0x6d,0x11,0x9d,0x14,0xbd,0x1, 0x48,0xd, 0x7e,0x10,0x2, 0xac,0x1e, +0x49,0x20,0x5, 0x20,0xbd,0x21,0x58,0x8, 0x74,0x1, 0x7a,0xb3,0x27,0x7b,0x80,0x6, +0xb, 0xf0,0xbc,0x7f,0x38,0xc9,0x12,0xb4,0x90,0xe4,0x7a,0xb3,0x27,0x7d,0x12,0x8f, +0xf3,0xbe,0x37,0x27,0x73,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x27,0x7d,0x74,0x1, 0x7a, +0xb3,0x27,0x7e,0x6c,0xff,0x80,0x1f,0x12,0x8d,0x92,0x49,0x25,0x24,0xcb,0x7d,0x43, +0x9d,0x42,0x7d,0x34,0x12,0x1a,0x62,0xbe,0x37,0x27,0x71,0x8, 0x7, 0xe4,0x7a,0xb3, +0x27,0x7e,0x80,0x7, 0xb, 0xf0,0x12,0x8a,0x8, 0x38,0xdc,0x6c,0xff,0x80,0x9, 0x12, +0x8d,0x92,0x59,0x35,0x24,0xcb,0xb, 0xf0,0x12,0x8a,0x8, 0x38,0xf2,0xda,0x79,0xda, +0xd8,0x22,0x7c,0xbf,0x12,0x8c,0x77,0x74,0x2, 0xac,0xbf,0x22,0x7c,0xbf,0x12,0x8d, +0xaf,0x1a,0x4b,0x7c,0xbf,0x12,0x8c,0x77,0x7d,0xd3,0xbe,0xd4,0x2, 0x58,0x22,0xca, +0xf8,0x7c,0xfb,0x7e,0x70,0x2, 0x12,0xa8,0x84,0x7f,0x71,0x7c,0xbf,0x12,0x8c,0x77, +0x12,0x8f,0xd5,0x7f,0x17,0x12,0x17,0x85,0x7c,0xb7,0xda,0xf8,0x22,0xa, 0x1d,0xa, +0x2a,0x2d,0x21,0x3e,0x24,0x22,0x7c,0xab,0x7e,0xb3,0x27,0x7c,0x70,0x15,0x12,0x8f, +0xeb,0x68,0x10,0x7e,0xb3,0x29,0x58,0xbe,0xb0,0x1, 0x68,0x7, 0x7c,0xba,0x6c,0x77, +0x2, 0x27,0x70,0x22,0x7c,0x6b,0xc2,0x1, 0x6c,0xaa,0x80,0x30,0x7e,0x50,0x6, 0xac, +0x5a,0x7f,0x70,0x2d,0xf2,0xb, 0xf4,0x29,0xb7,0x0, 0x2, 0xbc,0xb6,0x40,0x1b,0x7e, +0x7b,0xb0,0xbc,0xb6,0x38,0x14,0x29,0xb7,0x0, 0x3, 0xbc,0xb7,0x40,0xc, 0x29,0xb7, +0x0, 0x1, 0xbc,0xb7,0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xa0,0x7e,0xb, 0xb0,0xbc, +0xba,0x38,0xc9,0xa2,0x1, 0x22,0xca,0x3b,0x6c,0xff,0xc1,0xf0,0x9f,0x77,0x6d,0x33, +0x74,0x2, 0xac,0xbf,0x59,0x35,0x1e,0x44,0x6c,0xee,0x6c,0xdd,0x80,0x63,0x6c,0xaa, +0x6c,0x99,0x80,0x46,0x12,0x93,0xdc,0x9, 0x33,0x25,0xcf,0x1a,0x2d,0x1a,0x33,0x9d, +0x32,0x12,0x1a,0x62,0x7d,0x3, 0x1a,0x2f,0x1a,0x38,0x9d,0x32,0x12,0x1a,0x62,0x2d, +0x30,0xbe,0x34,0x0, 0x2, 0x18,0x21,0x7e,0xb3,0x27,0x58,0xb4,0x1, 0x2, 0x80,0x13, +0x12,0x48,0xb3,0x40,0x13,0x1a,0x33,0x3e,0x34,0x49,0x33,0x4, 0xc0,0xbe,0x37,0x29, +0x40,0x48,0x5, 0x7e,0xa0,0x1, 0x80,0xa, 0xb, 0x90,0x7e,0x23,0x27,0x58,0xbc,0x29, +0x38,0xb2,0x4c,0xaa,0x78,0x9, 0x7c,0xbf,0x7c,0x7d,0x12,0xa9,0x50,0xb, 0xe0,0xb, +0xd0,0x7e,0xc3,0x29,0x5d,0xbc,0xcd,0x38,0x95,0xa, 0x1e,0x6d,0x0, 0x7f,0x17,0x12, +0x17,0x85,0x7f,0x71,0xbe,0x78,0x0, 0x0, 0x8, 0x24,0x7c,0x7c,0x1e,0x70,0xa, 0x27, +0xa, 0x3e,0xbd,0x32,0x48,0x18,0x7d,0x4f,0x74,0x2, 0xac,0xbf,0x59,0x45,0x1e,0x44, +0xbe,0x44,0x0, 0xc8,0x8, 0x8, 0x7e,0x34,0x0, 0xc8,0x59,0x35,0x1e,0x44,0xb, 0xf0, +0x7e,0x73,0x29,0x5c,0xbc,0x7f,0x28,0x2, 0xc1,0x3c,0x6c,0xff,0x80,0x27,0x7c,0xbf, +0x12,0x8c,0x77,0x7d,0x43,0x74,0x2, 0xac,0xbf,0x9, 0xa5,0x25,0xce,0x74,0x2, 0xa4, +0x49,0x55,0x1e,0x44,0x2e,0x57,0x29,0x47,0xbd,0x54,0x8, 0x7, 0x7c,0xbf,0x6c,0x77, +0x12,0x27,0x70,0xb, 0xf0,0x12,0x8a,0x8, 0x38,0xd4,0xda,0x3b,0x22,0x7f,0x61,0x7f, +0x50,0x7e,0x6b,0x90,0x80,0x1f,0x29,0x86,0x0, 0x1, 0x80,0xf, 0x7f,0x5, 0x7c,0xb9, +0x7c,0x78,0x12,0x8d,0xf4,0x50,0x2, 0xd3,0x22,0xb, 0x80,0x29,0x76,0x0, 0x3, 0xbc, +0x78,0x50,0xe9,0xb, 0x90,0x29,0x76,0x0, 0x2, 0xbc,0x79,0x50,0xd9,0xc3,0x22,0x7e, +0xa3,0x27,0x58,0x4c,0xaa,0x78,0xc, 0x74,0xff,0x7a,0xb3,0x39,0x7f,0x6d,0x33,0x7a, +0x37,0x39,0x80,0x7e,0xb3,0x28,0xf5,0x70,0x5b,0xbe,0xa0,0x1, 0x78,0x56,0xe4,0x12, +0x8c,0x77,0x7e,0x27,0x29,0x47,0x12,0x8f,0xdc,0x2e,0x27,0x29,0x47,0xbd,0x32,0x18, +0x43,0x7e,0xa3,0x39,0x7f,0xbe,0xa0,0xff,0x78,0x15,0x7e,0x23,0x25,0xcf,0x7a,0x23, +0x39,0x7f,0x7e,0x30,0x2, 0xac,0x23,0x12,0x86,0x81,0xb, 0x1a,0x30,0x80,0x1c,0x7e, +0xb3,0x25,0xcf,0xbe,0xb3,0x39,0x7f,0x78,0x1b,0x12,0xbf,0x94,0xb, 0x1a,0x30,0x7e, +0x27,0x39,0x80,0x2e,0x24,0x0, 0x14,0xbd,0x32,0x8, 0x9, 0x7a,0x37,0x39,0x80,0xe4, +0x7a,0xb3,0x27,0x58,0x22,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0x22,0x1e,0x24,0x1e,0x24, +0x1e,0x24,0x22,0x7e,0x73,0x27,0x59,0xbe,0x70,0x0, 0x22,0x7e,0xb3,0x3a,0xce,0xbe, +0xb0,0x1, 0x22,0x7e,0x37,0x27,0x5c,0x2e,0x37,0x27,0x5a,0x22,0xca,0x3b,0x7c,0xc7, +0x7c,0xfb,0x7f,0x40,0x6d,0xbb,0x7e,0xa3,0x29,0x5a,0x7e,0x73,0x29,0x5b,0x4c,0xcc, +0x78,0x5, 0x7e,0xc0,0x1, 0x80,0xd, 0x7c,0xb7,0x14,0xbc,0xbc,0x78,0x6, 0xa, 0x6c, +0x1b,0x65,0x7c,0xcd,0x4c,0xff,0x78,0x5, 0x7e,0xf0,0x1, 0x80,0xb, 0x7c,0xba,0x14, +0xbc,0xbf,0x78,0x4, 0xa, 0x7f,0x1b,0x75,0x7f,0x4, 0x7e,0x34,0x0, 0x6, 0xe4,0x12, +0x1a,0x30,0x7e,0x73,0x29,0x5a,0xa, 0x37,0x1b,0x34,0x7a,0x4b,0x70,0x7e,0x73,0x29, +0x5b,0xa, 0x37,0x1b,0x34,0x39,0x74,0x0, 0x1, 0x7c,0xec,0x80,0x1d,0x75,0x25,0x0, +0x7c,0xdf,0x80,0xb, 0x12,0x25,0x54,0x70,0xb, 0x5, 0x25,0xb, 0xb4,0x1b,0xd0,0xbe, +0xd0,0x0, 0x58,0xf0,0xe5,0x25,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xde,0x7c, +0xec,0x80,0x26,0x75,0x25,0x0, 0x1a,0xaf,0xb, 0xa4,0x7d,0x3a,0x7c,0xd7,0x80,0xb, +0x12,0x25,0x54,0x70,0xe, 0x5, 0x25,0xb, 0xb4,0xb, 0xd0,0x7e,0x73,0x29,0x5a,0xbc, +0x7d,0x18,0xed,0xe5,0x25,0x60,0x7, 0x1b,0xe0,0xbe,0xe0,0x0, 0x58,0xd5,0x12,0x91, +0x12,0x80,0x1d,0x75,0x25,0x0, 0x7c,0xdf,0x80,0xb, 0x12,0x25,0x54,0x70,0xb, 0x5, +0x25,0xb, 0xb4,0x1b,0xd0,0xbe,0xd0,0x0, 0x58,0xf0,0xe5,0x25,0x60,0xa, 0xb, 0xe0, +0x7e,0x73,0x29,0x5b,0xbc,0x7e,0x18,0xdb,0x12,0x91,0x12,0x80,0x22,0x75,0x25,0x0, +0x1a,0x6f,0xb, 0x64,0x80,0xb, 0x12,0x25,0x54,0x70,0xe, 0x5, 0x25,0xb, 0xb4,0xb, +0xd0,0x7e,0x73,0x29,0x5a,0xbc,0x7d,0x18,0xed,0xe5,0x25,0x60,0xa, 0xb, 0xe0,0x7e, +0x73,0x29,0x5b,0xbc,0x7e,0x18,0xd6,0x7d,0x3b,0x39,0x74,0x0, 0x5, 0x7d,0x3b,0xda, +0x3b,0x22,0x1a,0xac,0xb, 0xa4,0x7d,0x3a,0x7c,0xe7,0x22,0x7f,0x60,0x7e,0x6b,0xa0, +0xbe,0xa0,0xa, 0x50,0x1b,0x7e,0x14,0x0, 0x6, 0xca,0x19,0x74,0x6, 0xa4,0x7f,0x6, +0x2d,0x15,0xb, 0x14,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x6b,0xb0,0x4, 0x7a,0x6b,0xb0, +0x22,0x30,0x13,0x13,0x12,0x91,0x58,0x68,0x6, 0x7e,0xb3,0x3c,0x93,0x60,0x8, 0x7e, +0x34,0xb, 0xb8,0x7a,0x37,0x3b,0xa9,0x22,0x7e,0xb3,0x27,0x7c,0xbe,0xb0,0x1, 0x22, +0x6c,0xaa,0x7e,0x23,0x29,0x5b,0x7e,0x33,0x29,0x5a,0xac,0x32,0x7e,0xe4,0x0, 0x3, +0x7d,0xf1,0x8d,0xfe,0x7d,0x3f,0x7e,0x4, 0x0, 0x6, 0x8d,0x10,0x7c,0x43,0x7e,0x7, +0x27,0x5e,0xbe,0x4, 0x5, 0x78,0x8, 0x12,0x7d,0xef,0x2e,0xe4,0x0, 0xf, 0x7d,0x4e, +0x7c,0x59,0x7d,0xe1,0x2e,0xe4,0x0, 0xc, 0x80,0x16,0xbe,0x4, 0x3, 0xe8,0x8, 0x16, +0x7d,0xef,0x2e,0xe4,0x0, 0xa, 0x7d,0x4e,0x7c,0x59,0x7d,0xe1,0x2e,0xe4,0x0, 0x8, +0x7d,0x4e,0x7c,0xb9,0x80,0x18,0xbe,0x4, 0x3, 0x20,0x8, 0xe, 0x7d,0xf, 0x2e,0x4, +0x0, 0x6, 0x7c,0x51,0xb, 0x16,0x7c,0xb3,0x80,0x4, 0x7c,0x57,0x7c,0xb4,0x12,0x8f, +0xf3,0xa, 0x45,0xbd,0x34,0x38,0x8, 0xa, 0x3b,0xbe,0x37,0x27,0x5a,0x50,0x29,0x90, +0x60,0x51,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x25,0xcb,0xa, 0x3b,0xbd,0x32, +0x8, 0x16,0x90,0x60,0x50,0xe4,0x93,0x1e,0xb0,0xa, 0x2b,0x7e,0xb3,0x25,0xca,0xa, +0x3b,0xbd,0x32,0x8, 0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0x7e,0xa3,0x28,0xf5,0xbe, +0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x28,0xf4,0x50,0x19,0x7e,0xb3,0x28,0xfe,0xbe,0xb3, +0x33,0xcf,0x28,0x14,0x7e,0xb3,0x33,0xcf,0x4, 0x7a,0xb3,0x33,0xcf,0x7a,0xa3,0x28, +0xf4,0x80,0x5, 0xe4,0x7a,0xb3,0x33,0xcf,0x7e,0xb3,0x28,0xf4,0x70,0x5, 0xe4,0x7a, +0xb3,0x28,0xfd,0x22,0x12,0x92,0x4a,0x2, 0x92,0xb, 0x7e,0xb3,0x28,0xf4,0x70,0x2d, +0x7e,0x73,0x28,0xf5,0xbe,0x70,0x0, 0x28,0x24,0x7e,0xb3,0x32,0xf0,0x70,0x18,0x12, +0x92,0x87,0x7e,0x73,0x28,0xf5,0x7a,0x73,0x28,0xf4,0x74,0x1, 0x7a,0xb3,0x28,0xfb, +0x7e,0xb3,0x32,0xf0,0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x32,0xf0,0x22,0xe4,0x7a,0xb3, +0x32,0xf0,0x7a,0xb3,0x28,0xfb,0x22,0x7e,0x34,0x0, 0x3c,0xca,0x39,0x7e,0x18,0x39, +0x7, 0x7e,0x8, 0x39,0x43,0x12,0x1a,0xb, 0x1b,0xfd,0x7e,0x73,0x27,0x68,0x7a,0x73, +0x38,0xf9,0x7a,0x73,0x27,0x67,0x22,0x12,0x92,0xb2,0x12,0x24,0x28,0x7a,0xb3,0x28, +0xfe,0x22,0x7e,0xa3,0x27,0x58,0xe4,0x7a,0xb3,0x32,0xcd,0x7e,0xb3,0x3a,0x89,0x60, +0x4d,0x6c,0x33,0x80,0x42,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x25,0xcf,0x7e,0x10, +0x1, 0xbe,0x20,0x2, 0x28,0x35,0x6c,0x0, 0x80,0x27,0xbc,0x3, 0x68,0x21,0x7e,0x70, +0x2, 0xac,0x70,0x9, 0x93,0x25,0xcf,0xa, 0x29,0xa, 0x32,0x12,0x7f,0x40,0x18,0x2, +0xb, 0x10,0xbe,0x10,0x2, 0x40,0x8, 0x74,0x2, 0x7a,0xb3,0x32,0xcd,0x80,0x6, 0xb, +0x0, 0xbc,0xa0,0x38,0xd5,0xb, 0x30,0xbc,0xa3,0x38,0xba,0x2, 0x93,0xf, 0x22,0xca, +0xf8,0x7e,0x33,0x27,0x58,0x6c,0x22,0x80,0x3a,0x12,0x93,0xd3,0x9, 0x5, 0x25,0xcf, +0x7e,0xa0,0x1, 0x6c,0x99,0x80,0x26,0xbc,0x92,0x68,0x20,0x12,0x93,0xdc,0x9, 0xf3, +0x25,0xcf,0xa, 0x28,0xa, 0x31,0x12,0x7f,0x40,0x18,0xb, 0xa, 0x2f,0xa, 0x30,0x12, +0x7f,0x40,0x8, 0x2, 0xb, 0xa0,0xbe,0xa0,0x3, 0x50,0x6, 0xb, 0x90,0xbc,0x39,0x38, +0xd6,0xb, 0x20,0xbc,0x32,0x38,0xc2,0x7e,0xb3,0x33,0xcd,0xbe,0xb0,0x0, 0x28,0x12, +0x14,0x7a,0xb3,0x33,0xcd,0xbe,0xb0,0x14,0x28,0x8, 0x7e,0x34,0x0, 0x8c,0x7a,0x37, +0x29,0x47,0x7e,0xb3,0x3a,0x89,0x70,0x58,0x7e,0xb3,0x3c,0x93,0x70,0x52,0x7e,0xb3, +0x3a,0xd, 0x70,0x4c,0x7e,0x37,0x3b,0xab,0xbe,0x34,0x0, 0x14,0x50,0x42,0x7e,0x37, +0x27,0x5e,0xbe,0x34,0x3, 0x20,0x58,0x38,0x7e,0xb3,0x27,0x58,0xbe,0xb0,0x3, 0x40, +0x2f,0xbe,0xa0,0x3, 0x40,0x2a,0x7e,0xb3,0x25,0x59,0xbe,0xb0,0x3, 0x50,0x9, 0x7e, +0xb3,0x25,0x58,0xbe,0xb0,0x3, 0x40,0x18,0x7e,0xb3,0x25,0xca,0xbe,0xb0,0x8, 0x50, +0x9, 0x7e,0xb3,0x25,0xcb,0xbe,0xb0,0x8, 0x40,0x6, 0x74,0x1e,0x7a,0xb3,0x33,0xcd, +0xda,0xf8,0x22,0x74,0x2, 0xac,0xb2,0x9, 0x15,0x25,0xce,0x22,0x7e,0x70,0x2, 0xac, +0x79,0x9, 0x83,0x25,0xce,0x22,0x7e,0x33,0x27,0x58,0x7e,0xb3,0x3a,0xce,0x60,0x29, +0x6c,0x22,0x80,0x21,0x12,0x93,0xd3,0xbe,0x10,0x2, 0x40,0x10,0x7e,0x3, 0x29,0x5c, +0xa, 0x20,0x9e,0x24,0x0, 0x3, 0xa, 0x31,0xbd,0x32,0x8, 0x7, 0x7c,0xb2,0x6c,0x77, +0x12,0x27,0x70,0xb, 0x20,0xbc,0x32,0x38,0xdb,0x22,0x12,0x94,0x4e,0x2, 0x94,0x20, +0x7e,0xb3,0x28,0xfb,0x70,0x27,0x7e,0xb3,0x32,0xcd,0xb4,0x2, 0xd, 0x7e,0x73,0x28, +0xf4,0xbe,0x70,0x1, 0x28,0x4, 0x74,0x3, 0x80,0x1, 0xe4,0x7a,0xb3,0x32,0xd8,0x7e, +0x73,0x32,0xd9,0xbe,0x73,0x32,0xd8,0x28,0x4, 0x7a,0x73,0x32,0xd8,0x22,0xca,0x3b, +0x7e,0xb3,0x28,0xf4,0x7c,0xab,0x7e,0x8, 0x28,0x90,0x7e,0x90,0xc, 0x7e,0x80,0x6, +0xb4,0x1, 0x22,0x7e,0xb3,0x27,0x89,0x60,0xb, 0x7e,0xb3,0x29,0x5c,0x14,0xbe,0xb3, +0x27,0x89,0x78,0x3, 0x7e,0x90,0x18,0x7e,0xb3,0x29,0x5d,0x14,0xbe,0xb3,0x27,0x8a, +0x78,0x3, 0x7e,0x90,0x24,0x4c,0xaa,0x78,0x5, 0x12,0x1d,0x88,0xc1,0xd0,0x6c,0xff, +0x7e,0x70,0x9, 0xac,0x7f,0x9, 0xe3,0x27,0xe0,0xbe,0xe0,0xff,0x78,0x2, 0xc1,0xc7, +0x12,0x96,0xea,0x70,0x28,0x12,0x96,0xda,0x19,0xb3,0x32,0xa3,0xa, 0x3f,0x19,0xb3, +0x32,0xc3,0xa, 0x3e,0x7c,0xb7,0x7e,0x34,0x0, 0x1, 0x60,0x5, 0x3e,0x34,0x14,0x78, +0xfb,0x6e,0x34,0xff,0xff,0x5e,0x37,0x32,0xda,0x7a,0x37,0x32,0xda,0x12,0x97,0x26, +0x50,0x60,0x12,0x97,0x1c,0xbe,0xb0,0x0, 0x28,0x58,0xa, 0xfb,0x7e,0xb3,0x29,0x5c, +0xa, 0x2b,0x1b,0x24,0xbd,0xf2,0x58,0x4a,0x9, 0xb3,0x27,0x89,0xbe,0xb3,0x39,0x0, +0x78,0x9, 0x12,0x97,0x12,0xbe,0xb3,0x39,0x2, 0x68,0x12,0x12,0x97,0x1c,0xbe,0xb3, +0x39,0x1, 0x78,0x2e,0x12,0x97,0x12,0xbe,0xb3,0x39,0x3, 0x78,0x25,0x7e,0x34,0x0, +0x1, 0x7c,0xbe,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7d,0x23,0x5e,0x27,0x32,0xda, +0x78,0x10,0x74,0x24,0xa, 0x2e,0x19,0xb2,0x32,0x99,0x4e,0x37,0x32,0xda,0x7a,0x37, +0x32,0xda,0xbe,0xe0,0xff,0x78,0x2, 0xc1,0xc7,0xa, 0x3e,0x9, 0xb3,0x32,0x99,0x7a, +0xb3,0x32,0x3d,0x9, 0xb3,0x32,0xa3,0x7a,0xb3,0x32,0x98,0x7f,0x50,0x2d,0xb3,0x7e, +0x5b,0xb0,0xb4,0x2, 0x2, 0x80,0x2, 0xc1,0x95,0x12,0x97,0x8, 0x12,0x96,0xfe,0x12, +0x97,0x30,0x7e,0x70,0x4, 0xac,0x7e,0x49,0x23,0x33,0xd2,0x12,0x96,0xf4,0x9d,0x32, +0x12,0x1a,0x62,0x7d,0xe3,0x7e,0x73,0x32,0x3d,0xa, 0x27,0xbd,0x2f,0x28,0x60,0xbd, +0x2e,0x28,0x5c,0x7e,0x50,0x4, 0xac,0x5e,0x49,0x22,0x33,0xd0,0x7e,0xd0,0x9, 0xac, +0xdf,0x59,0x26,0x27,0xdc,0x7e,0x50,0x4, 0xac,0x5e,0x49,0x22,0x33,0xd2,0x7e,0xd0, +0x9, 0xac,0xdf,0x59,0x26,0x27,0xde,0xe4,0xa, 0x2f,0x19,0xb2,0x32,0xc3,0xbe,0xa0, +0x0, 0x28,0x2, 0x1b,0xa0,0x7e,0xb3,0x32,0x98,0x4, 0x7a,0xb3,0x32,0x98,0x7e,0x63, +0x32,0x98,0xbe,0x60,0x32,0x50,0x2, 0xc1,0x85,0xe4,0x7a,0xb3,0x32,0x98,0x7e,0xb3, +0x32,0x3d,0xbc,0xb8,0x40,0x2, 0xc1,0x85,0x4, 0x7a,0xb3,0x32,0x3d,0xc1,0x85,0xbe, +0x70,0x1, 0x40,0x6a,0x12,0x97,0x8, 0x7e,0xd0,0x9, 0xac,0xdf,0x49,0xd6,0x27,0xdc, +0x9d,0xd2,0x49,0x33,0x33,0xd2,0x49,0xc6,0x27,0xde,0x9d,0xc3,0x12,0x96,0xd3,0xbe, +0xb0,0x10,0x50,0xa, 0xa, 0x3f,0x2e,0x34,0x32,0xc3,0x4, 0x7a,0x39,0xb0,0x7d,0x3d, +0x2d,0x3d,0xbe,0x34,0x0, 0x64,0x58,0x36,0x12,0x96,0xd3,0xa, 0x9b,0xad,0x9d,0x7d, +0x39,0x12,0x97,0x29,0xe, 0x34,0x12,0x96,0xe2,0x59,0x32,0x27,0xdc,0x12,0x96,0xd3, +0xa, 0x3b,0xad,0x3c,0x7d,0x23,0xe, 0x24,0xe, 0x24,0xe, 0x24,0xe, 0x24,0x7e,0x70, +0x4, 0xac,0x7e,0x49,0x33,0x33,0xd2,0x12,0x96,0xe2,0x59,0x32,0x27,0xde,0x7e,0x70, +0x9, 0xac,0x7f,0x49,0x93,0x27,0xdc,0x7e,0x50,0x4, 0xac,0x5e,0x59,0x92,0x33,0xd0, +0x49,0x33,0x27,0xde,0x59,0x32,0x33,0xd2,0x7e,0xb3,0x32,0x3d,0xbc,0xb9,0x40,0x6, +0x7a,0x83,0x32,0x3d,0x80,0xa, 0xbe,0xb0,0x1, 0x28,0x5, 0x14,0x7a,0xb3,0x32,0x3d, +0xe4,0x7a,0xb3,0x32,0x98,0x7e,0xb3,0x32,0x3d,0xa, 0x3e,0x19,0xb3,0x32,0x99,0x7e, +0xb3,0x32,0x98,0x80,0x2c,0x7e,0x5b,0xb0,0x70,0x15,0x12,0x96,0xfe,0x7e,0x50,0x4, +0xac,0x5e,0x59,0x32,0x33,0xd0,0x12,0x96,0xf4,0x59,0x32,0x33,0xd2,0x80,0x18,0x12, +0x96,0xea,0xb4,0x1, 0x12,0x7e,0xb3,0x28,0xf4,0xbe,0xb0,0x0, 0x28,0x9, 0x12,0x96, +0xda,0xa, 0x3e,0x19,0xb3,0x32,0xa3,0xb, 0xf0,0xbe,0xf0,0xa, 0x68,0x2, 0x81,0x90, +0xda,0x3b,0x22,0xa, 0x3f,0x9, 0xb3,0x32,0xc3,0x22,0xa, 0x3e,0x19,0x93,0x32,0x99, +0xe4,0x22,0x2d,0x32,0x7e,0x50,0x9, 0xac,0x5f,0x22,0xa, 0x3e,0x2d,0x31,0x7d,0x20, +0x7e,0x1b,0xb0,0x22,0x7e,0x70,0x9, 0xac,0x7f,0x49,0x33,0x27,0xde,0x22,0x7e,0x70, +0x9, 0xac,0x7f,0x49,0x33,0x27,0xdc,0x22,0x7e,0x70,0x4, 0xac,0x7e,0x49,0x23,0x33, +0xd0,0x22,0x7e,0x70,0x9, 0xac,0x7e,0x9, 0xb3,0x27,0x8a,0x22,0x7e,0x70,0x9, 0xac, +0x7e,0x9, 0xb3,0x27,0x89,0x22,0xa2,0x14,0x22,0xe, 0x34,0xe, 0x34,0xe, 0x34,0x22, +0x9d,0x32,0x12,0x1a,0x62,0x7d,0xf3,0x22,0xca,0xd8,0xca,0x79,0x7c,0xdb,0x7e,0xf0, +0xa, 0x6c,0x11,0x80,0x21,0x7e,0x0, 0xff,0x74,0x9, 0xac,0xb1,0x19,0x5, 0x1e,0x48, +0x7e,0x34,0x7f,0xff,0x74,0x9, 0xac,0xb1,0x59,0x35,0x1e,0x44,0x74,0x9, 0xac,0xb1, +0x59,0x35,0x1e,0x46,0xb, 0x10,0xbc,0xf1,0x38,0xdb,0xe4,0x6c,0x77,0x7c,0x6d,0x12, +0x97,0xd6,0x7c,0x7d,0x7c,0x6f,0x12,0x97,0xd6,0x6c,0x0, 0x80,0x3d,0x6c,0xee,0x80, +0x16,0x74,0x9, 0xac,0xbe,0x9, 0x65,0x1e,0x48,0x74,0x9, 0xac,0xb0,0x9, 0x75,0x27, +0x86,0xbc,0x76,0x68,0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x19,0x7e, +0x70,0x9, 0xac,0x70,0x2e,0x34,0x27,0x82,0x7e,0x30,0x9, 0xac,0x31,0x2e,0x14,0x1e, +0x44,0x74,0x9, 0x12,0x17,0xb9,0xb, 0x10,0xb, 0x0, 0xbc,0xf0,0x38,0xbf,0x74,0x9, +0xac,0xbf,0xca,0x59,0x7e,0x18,0x1e,0x44,0x7e,0x8, 0x28,0x36,0x12,0x1a,0xb, 0x1b, +0xfd,0xda,0x79,0xda,0xd8,0x22,0x7e,0x8, 0x1e,0x44,0x12,0x97,0xe0,0x7c,0x1b,0x22, +0xca,0x3b,0x7c,0x46,0x7c,0xab,0x6c,0x66,0x7c,0x57,0x2, 0x98,0x96,0x7e,0xf0,0x9, +0xac,0xf6,0x9, 0x87,0x28,0x3a,0x7c,0x98,0x7e,0xd0,0x9, 0xac,0xd5,0x9, 0xb6,0x27, +0x86,0xbc,0xb9,0x68,0x2, 0x1, 0x94,0xbe,0x90,0xff,0x78,0x2, 0x1, 0x94,0x12,0x98, +0xac,0x39,0x87,0x0, 0x4, 0xa, 0xf9,0x9, 0xbf,0x28,0x90,0x7e,0xf0,0x9, 0x70,0xc, +0xac,0xf5,0x7d,0x97,0x2e,0x94,0x27,0x82,0x6d,0x88,0x80,0xa, 0xac,0xf6,0x7d,0x97, +0x2e,0x94,0x28,0x36,0x6d,0x88,0xb, 0x4a,0xd0,0x12,0x98,0xac,0x1b,0x7a,0xd0,0x69, +0xf4,0x0, 0x2, 0x7e,0xf0,0x9, 0xac,0xfa,0x7f,0x60,0x2d,0xd7,0x79,0xf6,0x0, 0x2, +0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x87,0x12,0x98,0xac,0x39,0x87,0x0, 0x5, +0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x88,0x12,0x98,0xac,0x39,0x87,0x0, 0x6, +0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x89,0x12,0x98,0xac,0x39,0x87,0x0, 0x7, +0x7e,0xf0,0x9, 0xac,0xf5,0x9, 0x87,0x27,0x8a,0x12,0x98,0xac,0x39,0x87,0x0, 0x8, +0xb, 0xa0,0x80,0x9, 0xb, 0x50,0xbc,0x45,0x28,0x3, 0x2, 0x97,0xed,0xb, 0x60,0xbe, +0x60,0xa, 0x50,0x3, 0x2, 0x97,0xe8,0x7c,0xba,0xda,0x3b,0x22,0x7e,0xf0,0x9, 0xac, +0xfa,0x7f,0x70,0x2d,0xf7,0x22,0x7c,0xab,0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x31, +0xa, 0x4a,0x9, 0x74,0x32,0xce,0xbe,0x73,0x32,0xd8,0x50,0xe, 0x7d,0x24,0x2e,0x24, +0x32,0xce,0x7c,0xb7,0x4, 0x7a,0x29,0xb0,0xd3,0x22,0xbe,0x73,0x32,0xd8,0x40,0x9, +0xbe,0x70,0xff,0x68,0x4, 0xe4,0x7a,0xb, 0xb0,0x74,0xff,0x19,0xb4,0x32,0xce,0x80, +0x17,0xa, 0x3a,0x9, 0xb3,0x32,0xce,0xbe,0xb0,0xff,0x68,0x7, 0xe4,0x19,0xb3,0x32, +0xce,0xd3,0x22,0xe4,0x19,0xb3,0x32,0xce,0xc3,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0xf3, +0x7e,0x17,0x29,0x4f,0xbd,0x13,0x38,0x6, 0x7e,0x34,0x1, 0x0, 0x80,0x15,0x6d,0x22, +0x7c,0x56,0x7c,0x67,0x6c,0x77,0x12,0x17,0x32,0xbe,0x34,0x0, 0x8, 0x50,0x4, 0x7e, +0x34,0x0, 0x8, 0x74,0x2, 0xac,0xbf,0x49,0x25,0x32,0xdc,0xbd,0x2f,0x28,0x6, 0x49, +0x35,0x32,0xad,0x80,0x4, 0x59,0x35,0x32,0xad,0x59,0xf5,0x32,0xdc,0xbe,0x34,0x1, +0x0, 0x28,0x4, 0x7e,0x34,0x1, 0x0, 0x7e,0x50,0x9, 0xac,0x5f,0x49,0x2, 0x27,0x82, +0xbe,0x4, 0x4, 0x0, 0x40,0x20,0x7e,0x23,0x29,0x5c,0x12,0x99,0xb7,0xbd,0x1, 0x38, +0x15,0x49,0x2, 0x27,0x84,0xbe,0x4, 0x4, 0x0, 0x40,0xb, 0x7e,0x23,0x29,0x5d,0x12, +0x99,0xb7,0xbd,0x1, 0x28,0xc, 0x3e,0x34,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e,0x34, +0x1, 0x0, 0xbe,0x34,0x0, 0x20,0x50,0x10,0x9, 0xb2,0x32,0x46,0xb4,0x1, 0x9, 0x7e, +0x34,0x1, 0x0, 0xe4,0x19,0xb2,0x32,0x46,0xbe,0x34,0x0, 0x40,0x28,0x6, 0x74,0x1, +0x19,0xb2,0x32,0x46,0xda,0xf8,0x22,0x7e,0x30,0x40,0xac,0x23,0x9e,0x14,0x0, 0x40, +0x3e,0x14,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x22,0x7d,0x13,0x12,0x99,0xc2,0x7e,0x37, +0x3, 0xf7,0x9e,0x37,0x3, 0xf3,0x12,0x1a,0x62,0xbd,0x31,0x38,0x12,0x7e,0x37,0x3, +0xf9,0x9e,0x37,0x3, 0xf5,0x12,0x1a,0x62,0xbd,0x31,0x38,0x3, 0x74,0x1, 0x22,0xe4, +0x22,0xca,0xd8,0xca,0x79,0x6c,0xff,0x6d,0xdd,0x7d,0xed,0x7d,0xfd,0x7e,0xd3,0x28, +0xf4,0x7e,0xe3,0x28,0xf5,0x7e,0xb3,0x3, 0xf2,0x60,0x11,0x7e,0xc7,0x3, 0xfb,0x4d, +0xcc,0x78,0x2, 0x41,0xe5,0xbe,0xd0,0x1, 0x28,0x2, 0x41,0xe5,0xbe,0xd0,0x1, 0x78, +0x1d,0xbe,0xb0,0x4, 0x78,0x2, 0x41,0xe5,0x7e,0xe7,0x27,0xdc,0x7e,0xf7,0x27,0xde, +0x7d,0x3e,0x7d,0x2f,0x12,0x9b,0x21,0xbe,0xb0,0x1, 0x78,0x2, 0x41,0xe5,0x7e,0xa3, +0x3, 0xf2,0x7c,0xba,0x14,0x68,0x29,0x14,0x68,0x54,0x14,0x68,0x23,0x14,0x78,0x2, +0x41,0xe2,0xb, 0xb2,0x68,0x2, 0x41,0xe5,0xbe,0xd0,0x1, 0x68,0x2, 0x41,0xf4,0x4c, +0xee,0x68,0x2, 0x41,0xf4,0x74,0x1, 0x7a,0xb3,0x3, 0xf2,0x12,0x9b,0xf, 0x80,0x65, +0x4c,0xdd,0x78,0x1d,0xbe,0xa0,0x1, 0x78,0xc, 0x74,0x2, 0x7a,0xb3,0x3, 0xf2,0x7e, +0x34,0x62,0x7b,0x80,0x54,0x74,0x4, 0x7a,0xb3,0x3, 0xf2,0x7e,0x34,0x62,0x7f,0x80, +0x48,0x12,0x9b,0x18,0x90,0x62,0x6e,0x12,0x9a,0xfb,0x68,0x49,0x80,0x56,0xbe,0xd0, +0x1, 0x78,0x51,0x4c,0xee,0x78,0x4d,0x12,0x9b,0x18,0x7e,0x34,0x62,0x77,0x12,0x9b, +0x7, 0x7e,0x14,0x62,0x7b,0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0xc0,0x9d,0xc3,0xbe,0xc7, +0x3, 0xfb,0x40,0x21,0x90,0x62,0x6d,0x12,0x9a,0xfb,0x68,0x19,0x12,0x9b,0xf, 0x74, +0x3, 0x7a,0xb3,0x3, 0xf2,0x7e,0x34,0x62,0x7b,0x12,0x9b,0x7, 0x7a,0x37,0x3, 0xfb, +0x80,0x12,0x7e,0xf0,0x24,0xe4,0x7a,0xb3,0x3, 0xf2,0x6d,0x33,0x7a,0x37,0x3, 0xfb, +0x7c,0xbf,0x80,0x2, 0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xe4,0x93,0xa, 0x3b,0x12, +0x99,0xc9,0xa, 0xdb,0x4d,0xdd,0x22,0x7e,0x24,0x0, 0xff,0xb, 0x1a,0x30,0x22,0x7a, +0xe7,0x3, 0xf3,0x7a,0xf7,0x3, 0xf5,0x22,0x7a,0xe7,0x3, 0xf7,0x7a,0xf7,0x3, 0xf9, +0x22,0x7d,0x13,0x7e,0x54,0x62,0x6f,0x12,0x9d,0x10,0x50,0x21,0x7e,0x54,0x62,0x71, +0x12,0x9d,0x10,0x28,0x18,0x7e,0x14,0x62,0x73,0x12,0x9b,0x50,0xbd,0x32,0x50,0xd, +0x7e,0x14,0x62,0x75,0x12,0x9b,0x50,0xbd,0x32,0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22, +0x7e,0x4, 0x0, 0xff,0xb, 0xa, 0x30,0x22,0xca,0xf8,0x7e,0xa3,0x28,0xf4,0x7e,0xb3, +0x28,0xf5,0xbe,0xa0,0x1, 0x38,0x21,0xbe,0xb0,0x1, 0x38,0x1c,0x7e,0x47,0x27,0x5a, +0xbe,0x44,0x0, 0x1e,0x28,0x2, 0x80,0x10,0x7e,0xf3,0x2e,0x5e,0x4c,0xff,0x68,0x17, +0x7e,0x47,0x2a,0x95,0x4d,0x44,0x78,0xf, 0x12,0x9e,0xea,0x74,0x1, 0x7a,0xb3,0x3b, +0xee,0x7a,0xb3,0x3a,0xa3,0x80,0x35,0x4c,0xaa,0x78,0x36,0xb4,0x1, 0x33,0x7e,0x37, +0x2a,0x95,0x7a,0x37,0x2e,0x60,0x7e,0xb3,0x2e,0x5e,0xb4,0x3, 0x1f,0x7e,0x37,0x2a, +0x95,0xbe,0x34,0x0, 0x0, 0x28,0x15,0x74,0x4, 0x7a,0xb3,0x2e,0x5e,0x7e,0x37,0x2e, +0x76,0x7e,0x27,0x2e,0x78,0x12,0x9c,0x69,0x81,0x62,0x80,0x0, 0x12,0x9e,0xfc,0x81, +0x62,0x7e,0xc7,0x27,0xdc,0x7e,0xd7,0x27,0xde,0x4c,0xff,0x78,0x19,0x70,0x57,0xbe, +0xa0,0x1, 0x78,0x52,0x7d,0x3c,0x7d,0x2d,0x12,0x9e,0x3, 0x12,0x9c,0x65,0x74,0x1, +0x7a,0xb3,0x2e,0x5e,0x80,0x40,0xbe,0xf0,0x1, 0x78,0x2e,0x7e,0x27,0x2e,0x66,0x9e, +0x27,0x2e,0x6e,0x7e,0x14,0x62,0xa1,0x12,0x9b,0x50,0xbd,0x23,0x38,0x13,0x7e,0x27, +0x2e,0x74,0x9e,0x27,0x2e,0x6c,0x7e,0x14,0x62,0xa3,0x12,0x9b,0x50,0xbd,0x23,0x28, +0x15,0x74,0x3, 0x7a,0xb3,0x2e,0x5e,0x80,0x5, 0xbe,0xf0,0x3, 0x78,0x8, 0x7a,0xc7, +0x2e,0x76,0x7a,0xd7,0x2e,0x78,0x7e,0xb3,0x2e,0x5e,0x60,0x26,0x7d,0x3c,0x7d,0x2d, +0x7e,0x17,0x2a,0x99,0x7e,0x7, 0x2a,0x9b,0x12,0x9d,0xe7,0xa, 0x2b,0x7e,0x73,0x2e, +0x5d,0xa, 0x37,0xbd,0x32,0x58,0xb, 0x12,0x9c,0x65,0x7a,0xc7,0x2a,0x99,0x7a,0xd7, +0x2a,0x9b,0xda,0xf8,0x22,0x7d,0x3c,0x7d,0x2d,0x7d,0x42,0x7d,0x13,0x7d,0x24,0x12, +0x9f,0x8, 0x7d,0x31,0x12,0x9d,0x72,0x2, 0x9c,0x7a,0x7e,0x3, 0x2e,0x86,0xbe,0x0, +0xf0,0x50,0x2, 0xa1,0xf, 0x80,0x7d,0x6c,0x99,0x7e,0xb3,0x2e,0x5d,0xbe,0xb0,0x20, +0x50,0x5, 0x4, 0x7a,0xb3,0x2e,0x5d,0x7e,0x1f,0x2a,0x9d,0x7a,0x1f,0x1e,0x44,0x7e, +0x80,0x1, 0x80,0x45,0x74,0x4, 0xac,0xb8,0x49,0x35,0x2a,0x9d,0x49,0x25,0x2a,0x9f, +0x7e,0x17,0x1e,0x44,0x7e,0x7, 0x1e,0x46,0x12,0x9d,0xe7,0x7c,0x1b,0x7e,0x3, 0x2e, +0x5d,0xbc,0x1, 0x38,0x22,0xb, 0x90,0x7e,0x70,0x4, 0xac,0x78,0x2e,0x34,0x2a,0x9d, +0x7e,0x14,0x1e,0x44,0x74,0x4, 0x12,0x77,0xa2,0x7e,0x30,0x4, 0xac,0x39,0x2e,0x14, +0x2a,0x9d,0x74,0x4, 0x12,0x17,0xb9,0xb, 0x80,0x7e,0x3, 0x2e,0x86,0xbc,0x8, 0x38, +0xb3,0xa, 0x59,0xb, 0x54,0x7c,0xb, 0x7a,0x3, 0x2e,0x86,0x7e,0x3, 0x2e,0x5d,0xbe, +0x0, 0x20,0x50,0xb, 0x7e,0x3, 0x2e,0x86,0xbe,0x0, 0xec,0x40,0x2, 0x81,0x87,0x22, +0x7e,0x44,0x0, 0xff,0xb, 0x2a,0x30,0xbd,0x31,0x22,0x7e,0xb3,0x3a,0xce,0x70,0x6, +0x12,0x9d,0x53,0x2, 0x9e,0xe4,0x12,0x9b,0x58,0x12,0x9e,0xf1,0x50,0xa, 0x12,0x9d, +0x59,0x7c,0x3b,0x12,0x9d,0x53,0x80,0x5, 0x12,0x99,0xf1,0x7c,0x3b,0x4c,0x33,0x68, +0x11,0x7c,0xb3,0x12,0x9e,0x68,0x60,0xa, 0x7a,0x33,0x3a,0xd1,0x74,0x1, 0x7a,0xb3, +0x28,0xfa,0x22,0xe4,0x7a,0xb3,0x2e,0x5e,0x22,0x12,0x9d,0xde,0x7a,0x37,0x2e,0x7a, +0x12,0x9d,0x69,0x7a,0x37,0x2e,0x7c,0xe4,0x22,0x7e,0x37,0x2e,0x74,0x9e,0x37,0x2e, +0x6c,0x22,0x7e,0x17,0x2e,0x6e,0xbd,0x13,0x28,0xa, 0x7a,0x37,0x2e,0x6e,0x7a,0x27, +0x2e,0x70,0x80,0x10,0x7e,0x17,0x2e,0x66,0xbd,0x13,0x50,0x8, 0x7a,0x37,0x2e,0x66, +0x7a,0x27,0x2e,0x68,0x7e,0x17,0x2e,0x6c,0xbd,0x12,0x28,0xa, 0x7a,0x27,0x2e,0x6c, +0x7a,0x37,0x2e,0x6a,0x80,0x10,0x7e,0x17,0x2e,0x74,0xbd,0x12,0x50,0x8, 0x7a,0x27, +0x2e,0x74,0x7a,0x37,0x2e,0x72,0x7e,0xb3,0x2e,0x86,0xb4,0xa, 0xf, 0x12,0x9d,0xde, +0x7a,0x37,0x2e,0x7e,0x12,0x9d,0x69,0x7a,0x37,0x2e,0x80,0x22,0xb4,0x14,0xe, 0x12, +0x9d,0xde,0x7a,0x37,0x2e,0x82,0x12,0x9d,0x69,0x7a,0x37,0x2e,0x84,0x22,0x7e,0x37, +0x2e,0x66,0x9e,0x37,0x2e,0x6e,0x22,0x7d,0x51,0x7d,0x12,0x9d,0x35,0x12,0x1a,0x62, +0x7c,0xa7,0x7d,0x31,0x9d,0x30,0x12,0x1a,0x62,0x7c,0xb7,0xbc,0xba,0x50,0x3, 0x7c, +0xba,0x22,0x22,0x7d,0xf2,0x7d,0xe3,0x7e,0x8, 0x2e,0x5e,0x7e,0x34,0x0, 0x28,0xe4, +0x12,0x1a,0x30,0x7e,0x8, 0x2a,0x9d,0x7e,0x34,0x3, 0xc0,0x12,0x1a,0x30,0x7a,0xb3, +0x3a,0xd1,0x7e,0x34,0x62,0xa5,0x12,0x9b,0x7, 0x7a,0x37,0x2a,0x95,0x7a,0xe7,0x2e, +0x62,0x7a,0xf7,0x2e,0x64,0x7a,0xe7,0x2e,0x66,0x7a,0xe7,0x2e,0x6a,0x7a,0xe7,0x2e, +0x6e,0x7a,0xe7,0x2e,0x72,0x7a,0xf7,0x2e,0x68,0x7a,0xf7,0x2e,0x6c,0x7a,0xf7,0x2e, +0x70,0x7a,0xf7,0x2e,0x74,0x7a,0xe7,0x2a,0x99,0x7a,0xf7,0x2a,0x9b,0x7a,0xb3,0x2e, +0x86,0x74,0x2, 0x7a,0xb3,0x2e,0x5d,0x22,0x7c,0x7b,0xa, 0x57,0x9e,0x54,0x0, 0x20, +0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x7c,0xab,0x7c,0x67,0x5e,0x60,0xf0,0xa5, +0xbe,0x20,0x1d,0x7c,0xb7,0x54,0xf, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14, +0x78,0xfb,0x7e,0x73,0x33,0xf8,0xa, 0x47,0x5d,0x42,0x7e,0x73,0x3a,0xcf,0x80,0x36, +0xa5,0xbe,0x30,0x18,0x12,0x9e,0xdb,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7e,0x53, +0x33,0xf9,0xa, 0x45,0x5d,0x43,0x7e,0x73,0x3a,0xd0,0x80,0x1a,0x12,0x9e,0xdb,0x60, +0x5, 0x3e,0x34,0x14,0x78,0xfb,0xa, 0x2a,0x9, 0xb2,0x33,0xf8,0xa, 0x4b,0x5d,0x43, +0xa, 0x5a,0x9, 0x75,0x3a,0xd1,0xa, 0x57,0x5d,0x54,0x22,0x7c,0xb7,0x54,0xf, 0x7e, +0x34,0x0, 0x1, 0x22,0xe4,0x7a,0xb3,0x3, 0xf2,0x22,0x6d,0x33,0x7a,0x37,0x3b,0xec, +0x22,0x7e,0xb3,0x2e,0x5e,0xb4,0x4, 0x2, 0xd3,0x22,0xc3,0x22,0x74,0xfe,0x7a,0xb3, +0x3a,0xd1,0xe4,0x7a,0xb3,0x2e,0x5e,0x22,0x7e,0xa3,0x2e,0x86,0xbe,0xa0,0xf0,0x50, +0x1b,0x74,0x4, 0xa4,0x59,0x35,0x2a,0x9d,0x7e,0xa3,0x2e,0x86,0x74,0x4, 0xa4,0x59, +0x25,0x2a,0x9f,0x7e,0xb3,0x2e,0x86,0x4, 0x7a,0xb3,0x2e,0x86,0x22,0xca,0x3b,0x7d, +0xf0,0x7d,0x41,0x7d,0xe2,0x7d,0xd3,0x7e,0x75,0x2e,0x7e,0x65,0x30,0x75,0x3e,0x1, +0x7d,0x1e,0x1a,0x2, 0x1a,0x0, 0x7d,0x3f,0x12,0xcf,0x7b,0x7f,0x51,0x7d,0x1d,0x1a, +0x2, 0x1a,0x0, 0x7d,0x34,0x12,0xcf,0x7b,0x2f,0x15,0x7a,0x1d,0x32,0x12,0xc2,0x7a, +0x7d,0x36,0x12,0xcf,0x7b,0x7f,0x51,0x12,0xcf,0x73,0x2f,0x15,0x7a,0x1d,0x36,0x9d, +0x74,0x9d,0x6f,0x9d,0x4d,0x9d,0xfe,0x12,0xc2,0x7a,0x7d,0x36,0x12,0xcf,0x7b,0x7f, +0x71,0x12,0xcf,0x73,0x7f,0x21,0x2f,0x27,0x7e,0xd, 0x36,0x7e,0x1d,0x32,0x2f,0x1, +0x9f,0x2, 0x7a,0xd, 0x3a,0x12,0xd0,0x63,0x7a,0x1d,0x32,0x7e,0x1d,0x36,0x12,0xd0, +0x63,0x7a,0x1d,0x36,0x7e,0x7d,0x36,0xbe,0x78,0x0, 0x32,0x58,0x4, 0x74,0x1, 0x80, +0x52,0x7e,0x1d,0x32,0x7f,0x7, 0x12,0x17,0x18,0x7f,0x21,0x2f,0x22,0x7e,0x14,0x0, +0x64,0x7e,0x1d,0x3a,0x12,0x17,0x29,0x7f,0x2, 0x12,0x17,0x85,0x7a,0x1d,0x3a,0xbe, +0x18,0x0, 0x64,0x8, 0x9, 0x7e,0x8, 0x0, 0x64,0x7a,0xd, 0x3a,0x80,0xd, 0xbe,0x1c, +0xff,0x9c,0x58,0x7, 0x7e,0x1c,0xff,0x9c,0x7a,0x1d,0x3a,0x7e,0x1d,0x3a,0xbe,0x18, +0x0, 0x57,0x58,0xd, 0x2e,0x18,0x0, 0xa0,0x2f,0x11,0xbf,0x71,0x8, 0x3, 0x75,0x3e, +0x0, 0xe5,0x3e,0xda,0x3b,0x22,0x7e,0x8, 0x32,0xdc,0x7e,0x34,0x0, 0x14,0xe4,0x12, +0x1a,0x30,0x7e,0x8, 0x32,0xad,0x7e,0x34,0x0, 0x14,0x2, 0x1a,0x30,0xca,0x3b,0x7c, +0xab,0x7d,0x3, 0x7e,0x20,0x10,0x7d,0x30,0x7e,0x90,0x9, 0xac,0x95,0x9, 0x34,0x27, +0x88,0xbe,0x30,0x10,0x28,0x2, 0x7c,0x23,0xbe,0x20,0x18,0x28,0x3, 0x7e,0x20,0x18, +0x49,0xe4,0x27,0x82,0xbe,0xe4,0x6, 0x50,0x40,0x20,0x7e,0x33,0x29,0x5c,0x12,0xa1, +0x19,0xbd,0xef,0x38,0x15,0x49,0xe4,0x27,0x84,0xbe,0xe4,0x6, 0x50,0x40,0xb, 0x7e, +0x33,0x29,0x5d,0x12,0xa1,0x19,0xbd,0xef,0x28,0x3, 0x7e,0x20,0x8, 0x7e,0xf0,0x10, +0xac,0xf2,0xbd,0x70,0x40,0x5d,0x7e,0xf0,0x9, 0xac,0xf4,0x9, 0xb7,0x32,0x46,0x70, +0x52,0x7e,0xd0,0x8, 0xac,0xd2,0xbd,0x60,0x50,0x3c,0x9, 0xb7,0x32,0x3f,0x70,0x1f, +0x9, 0xb7,0x32,0x40,0xbe,0xb0,0x0, 0x28,0xc, 0x7d,0x37,0x2e,0x34,0x32,0x40,0x14, +0x7a,0x39,0xb0,0x80,0x6, 0x74,0x1, 0x19,0xb7,0x32,0x3f,0x6d,0x33,0x80,0x34,0x9, +0xb7,0x32,0x40,0xbe,0xb0,0x14,0x50,0x2b,0x7d,0x37,0x2e,0x34,0x32,0x40,0x4, 0x7a, +0x39,0xb0,0x6d,0x33,0x80,0x1d,0xe4,0x19,0xb7,0x32,0x40,0x19,0xb7,0x32,0x3f,0x6d, +0x33,0x80,0x10,0x6c,0x33,0x7e,0xf0,0x9, 0xac,0xf4,0x19,0x37,0x32,0x40,0xe4,0x19, +0xb7,0x32,0x3f,0x7e,0x30,0x8, 0xac,0x23,0xbd,0x10,0x40,0x2a,0x7e,0x70,0x9, 0xac, +0x7a,0x49,0x33,0x28,0x36,0x59,0x34,0x27,0x82,0x74,0x9, 0xa4,0x49,0x35,0x28,0x38, +0x74,0x9, 0xac,0xb5,0x59,0x35,0x27,0x84,0x7e,0xa0,0x1, 0x7e,0x70,0x9, 0xac,0x74, +0x19,0xa3,0x32,0x3e,0x6d,0x33,0xda,0x3b,0x22,0x7e,0xf0,0x40,0xac,0xf3,0x7d,0xf7, +0x9e,0xf4,0x0, 0x65,0x3e,0xf4,0x3e,0xf4,0x3e,0xf4,0x3e,0xf4,0x22,0xca,0x79,0x7e, +0x73,0x27,0x58,0xbe,0x70,0x2, 0x50,0x2, 0x21,0xb8,0x6c,0xaa,0x80,0x72,0x7e,0x70, +0x2, 0xac,0x7a,0x9, 0x93,0x25,0xcf,0xbe,0x90,0x0, 0x28,0x62,0x6c,0x88,0x80,0x56, +0x7e,0x70,0x2, 0xac,0x78,0x12,0xa2,0xc7,0x12,0xa2,0xbe,0x78,0x47,0x4c,0xee,0x78, +0x43,0xa, 0x2e,0xa, 0x39,0x12,0x7f,0x40,0x48,0x3a,0x12,0xa1,0xbb,0x7d,0x3, 0x7e, +0x17,0x27,0x5e,0x7e,0x24,0x0, 0x2, 0x7d,0x31,0x12,0x16,0xe6,0xbd,0x3, 0x58,0x24, +0xbe,0x14,0x3, 0x20,0x8, 0x1e,0x7e,0x70,0x2, 0xac,0x7e,0x49,0x23,0x4, 0xc0,0x7e, +0x37,0x7, 0x12,0xe, 0x34,0xe, 0x34,0xbd,0x23,0x58,0x9, 0x7c,0xb8,0x6c,0x77,0x12, +0x27,0x70,0x80,0x14,0xb, 0x80,0x7e,0xb3,0x27,0x58,0xbc,0xb8,0x38,0xa2,0xb, 0xa0, +0x7e,0xb3,0x27,0x58,0xbc,0xba,0x38,0x86,0xda,0x79,0x22,0x7c,0xbf,0x7c,0x7e,0x2, +0x21,0x50,0xca,0x79,0x7e,0x23,0x27,0x58,0x6c,0xaa,0x80,0x2f,0x7e,0x70,0x2, 0xac, +0x7a,0x9, 0x13,0x25,0xcf,0x6c,0x33,0x6c,0x0, 0x80,0x1a,0xbc,0xa, 0x68,0x14,0x7e, +0x70,0x2, 0xac,0x70,0x9, 0xf3,0x25,0xcf,0xa, 0x2f,0xa, 0x31,0x12,0xa2,0xb6,0x78, +0x2, 0xb, 0x30,0xb, 0x0, 0xbc,0x20,0x38,0xe2,0xb, 0xa0,0xbc,0x2a,0x38,0xcd,0xbe, +0x30,0x0, 0x38,0x2, 0x41,0xab,0x75,0x24,0x0, 0x75,0x25,0x0, 0x75,0x26,0x0, 0x6c, +0xaa,0x80,0x66,0x7e,0x70,0x2, 0xac,0x7a,0x12,0xa2,0xc7,0x12,0xa1,0xbb,0x7d,0xe3, +0x4c,0xff,0x78,0x5, 0x7c,0xbf,0x4, 0x80,0x8, 0x12,0xa2,0xbe,0x7c,0xbf,0x78,0x8, +0x14,0x12,0xa2,0xae,0x7d,0x43,0x80,0xe, 0x14,0x7c,0x7e,0x12,0x21,0x50,0x7d,0x43, +0x7c,0xbf,0x4, 0x12,0xa2,0xae,0x7d,0xdf,0x2d,0xd4,0xbe,0x44,0x0, 0xa, 0x58,0xa, +0xbe,0xf4,0x0, 0xa, 0x58,0x4, 0x5, 0x24,0x80,0x1d,0xbe,0xd4,0x0, 0x14,0x58,0x4, +0x5, 0x25,0x80,0x13,0x7e,0x34,0x0, 0x28,0xad,0x3e,0x7e,0x24,0x0, 0x64,0x12,0x16, +0xe6,0xbd,0x3d,0x8, 0x2, 0x5, 0x26,0xb, 0xa0,0x7e,0x73,0x27,0x58,0xbc,0x7a,0x38, +0x92,0xe5,0x25,0xa, 0xeb,0xe5,0x24,0xa, 0x2b,0x2d,0x2e,0xe5,0x26,0xa, 0xeb,0x2d, +0xe2,0x7d,0x2e,0x7c,0xb5,0xbe,0xb0,0x1, 0x28,0x11,0x1e,0x70,0xa, 0x37,0xa, 0xeb, +0xbd,0xe3,0x8, 0x7, 0x7c,0xba,0x6c,0x77,0x12,0x27,0x70,0xda,0x79,0x22,0x7c,0x7e, +0x12,0x21,0x50,0x7d,0xf3,0x22,0x9d,0x32,0x12,0x1a,0x62,0x4d,0x33,0x22,0x90,0x60, +0x50,0xe4,0x93,0x14,0xbc,0xbf,0x22,0x9, 0xf3,0x25,0xce,0x9, 0xe3,0x25,0xcf,0x22, +0xca,0x3b,0x7c,0xe7,0x7c,0xdb,0xbe,0xd0,0x0, 0x28,0x8, 0x12,0xcf,0xbc,0x58,0x3, +0xc3,0x61,0xc4,0x6c,0xaa,0x6c,0xff,0x12,0x27,0x5f,0xbe,0x34,0x2, 0x58,0x58,0x6, +0x7e,0x44,0x0, 0x96,0x80,0x4, 0x7e,0x44,0x0, 0xc8,0x7c,0xcd,0x80,0xb, 0x7c,0xbc, +0x12,0xa3,0xc7,0x8, 0xc, 0xb, 0xa0,0xb, 0xc0,0x7e,0xb3,0x29,0x5c,0xbc,0xbc,0x38, +0xed,0x7c,0xcd,0x80,0xf, 0xa, 0x3c,0x1b,0x34,0x7c,0xb7,0x12,0xa3,0xc7,0x8, 0x9, +0xb, 0xa0,0x1b,0xc0,0xbe,0xc0,0x0, 0x38,0xec,0x7c,0xce,0x80,0xb, 0x12,0xa7,0xea, +0xbd,0x34,0x8, 0xc, 0xb, 0xf0,0xb, 0xc0,0x7e,0xb3,0x29,0x5d,0xbc,0xbc,0x38,0xed, +0x7c,0xce,0x80,0x11,0x7c,0xbd,0xa, 0x3c,0x1b,0x34,0x12,0x21,0x50,0xbd,0x34,0x8, +0x9, 0xb, 0xf0,0x1b,0xc0,0xbe,0xc0,0x0, 0x38,0xea,0xbe,0xf0,0x5, 0x40,0x5, 0xbe, +0xa0,0x3, 0x28,0x8, 0xe4,0x7a,0xb3,0x39,0x4, 0xc3,0x80,0x58,0xbe,0xa0,0x1, 0x68, +0x10,0x7e,0x50,0x3, 0xac,0x5a,0xa, 0x3f,0xbd,0x32,0x8, 0x15,0xbe,0xa0,0x2, 0x40, +0x10,0x74,0x32,0x7a,0xb3,0x39,0x4, 0x7a,0xd3,0x39,0x5, 0x7a,0xe3,0x39,0x6, 0x80, +0xe, 0x7e,0xb3,0x39,0x4, 0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x39,0x4, 0x7e, +0xb3,0x39,0x4, 0x60,0x1f,0x7e,0xb3,0x39,0x5, 0xbc,0xbd,0x78,0x17,0x7e,0xb3,0x39, +0x6, 0xa, 0x2b,0x7d,0x12,0xb, 0x14,0xa, 0x3e,0xbd,0x31,0x18,0x7, 0xb, 0x34,0xbd, +0x32,0x48,0x1, 0xd3,0xda,0x3b,0x22,0x7c,0x7e,0x12,0x21,0x50,0xbd,0x34,0x22,0xca, +0xd8,0xca,0x79,0x7c,0xeb,0x7e,0xd4,0x28,0x90,0x7e,0xb4,0x27,0xdc,0x7e,0x70,0x9, +0xac,0x7e,0x7d,0x23,0x2d,0x2b,0x9, 0xf2,0x0, 0x4, 0xbe,0xf0,0xa, 0x40,0x2, 0xe1, +0x4e,0x7c,0xbf,0x54,0xf, 0xa, 0xcb,0x2d,0xcd,0x7e,0xc9,0x90,0x74,0x5, 0xac,0xbf, +0x9, 0xb5,0x32,0xf, 0x70,0x2, 0xa1,0x2a,0xb, 0x28,0x50,0x4d,0x55,0x78,0xa, 0x49, +0x22,0x0, 0x2, 0x4d,0x22,0x78,0x2, 0xa1,0x2a,0x12,0xa7,0xf1,0xa, 0x2f,0x19,0xb2, +0x32,0xce,0x49,0xc3,0x27,0xdc,0xbe,0xc4,0x0, 0x1e,0x38,0x10,0x49,0x53,0x27,0xde, +0xbe,0x54,0x0, 0x1e,0x40,0x6, 0xbe,0x54,0x8, 0xca,0x28,0x52,0xbe,0xc4,0x4, 0x1a, +0x40,0xb, 0x12,0xa7,0xaf,0x40,0x6, 0xbe,0x54,0x8, 0xca,0x28,0x41,0x12,0xa7,0xaf, +0x38,0xc, 0xbe,0xc4,0x0, 0x1e,0x40,0x6, 0xbe,0xc4,0x4, 0x1a,0x28,0x30,0xbe,0x54, +0x8, 0xe8,0x40,0xc, 0xbe,0xc4,0x0, 0x1e,0x40,0x6, 0xbe,0xc4,0x4, 0x1a,0x28,0x1e, +0x74,0x5, 0xac,0xbf,0x9, 0x75,0x32,0xf, 0xbe,0x70,0x4, 0x28,0x11,0x74,0x5, 0xac, +0xbf,0x7d,0xc5,0x2e,0xc4,0x32,0xf, 0x7e,0xc9,0xb0,0x14,0x7a,0xc9,0xb0,0x74,0x5, +0xac,0xbf,0x9, 0xa5,0x32,0xf, 0xbe,0xa0,0x4, 0x28,0x5, 0x7e,0x80,0x38,0x80,0x21, +0xbe,0xa0,0x4, 0x78,0x5, 0x7e,0x80,0x30,0x80,0x17,0xbe,0xa0,0x3, 0x78,0x5, 0x7e, +0x80,0x20,0x80,0xd, 0xbe,0xa0,0x2, 0x78,0x5, 0x7e,0x80,0x18,0x80,0x3, 0x7e,0x80, +0x10,0x6c,0xdd,0x74,0x9, 0xac,0xbd,0x9, 0xb5,0x37,0x98,0x54,0xf, 0xbc,0xbf,0x78, +0x52,0x12,0xa7,0x90,0xb, 0xa8,0x30,0x6d,0x22,0xa, 0x58,0x7e,0xc4,0x0, 0x40,0x9d, +0xc5,0x12,0xa7,0xda,0x49,0x35,0x37,0x94,0x12,0xa7,0xbc,0x1e,0x34,0x1e,0x24,0x50, +0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0x53,0x1b,0xa8,0x50,0x12,0xa7,0x90,0x49, +0x3a,0x0, 0x2, 0x6d,0x22,0x12,0xa7,0xda,0x49,0x35,0x37,0x96,0x12,0xa7,0xbc,0x1e, +0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x7d,0xc3,0x59,0xca,0x0, +0x2, 0x80,0x7, 0xb, 0xd0,0xbe,0xd0,0xa, 0x40,0x99,0x12,0xd1,0x0, 0xb4,0x1, 0x10, +0xa, 0xaf,0x9, 0xba,0x29,0x0, 0x70,0x8, 0xe4,0x19,0xbc,0x0, 0x50,0x12,0xa7,0xa3, +0x4c,0x99,0x68,0x2, 0xe1,0x4e,0xa, 0xcf,0x9, 0xbc,0x29,0x0, 0x60,0x2, 0xe1,0x4e, +0x7e,0x70,0x9, 0xac,0x7e,0x7d,0xc3,0x2d,0xcb,0xb, 0xc8,0x20,0xbe,0x24,0x0, 0x0, +0x40,0x6, 0xbe,0x24,0x4, 0x38,0x28,0x2b,0x7e,0xa0,0x1, 0x7e,0x50,0x5, 0xac,0x5f, +0x19,0xa2,0x32,0xc, 0x7e,0x90,0x3, 0x74,0x3, 0xa, 0x2f,0x2d,0x2d,0x7a,0x29,0xb0, +0xa, 0x2f,0x2d,0x2d,0x19,0xb2,0x0, 0xa, 0xe4,0xa, 0x2f,0x2d,0x2d,0x19,0xb2,0x0, +0x50,0xc1,0xa6,0x49,0x23,0x27,0xdc,0xbe,0x24,0x0, 0x1e,0x38,0xb, 0x12,0xa7,0x87, +0x40,0x6, 0xbe,0xa4,0x8, 0xca,0x28,0x17,0xbe,0x24,0x4, 0x1a,0x50,0x2, 0xc1,0x84, +0x12,0xa7,0x87,0x50,0x2, 0xc1,0x84,0xbe,0xa4,0x8, 0xca,0x28,0x2, 0xc1,0x84,0x12, +0xa7,0x5b,0x12,0x21,0x50,0xbe,0x34,0x1, 0x2c,0x58,0x2, 0xc1,0x56,0x12,0xa7,0x75, +0x70,0x2c,0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x30,0x63,0xac,0x3f,0x2e,0x14,0x2e, +0x87,0x6d,0x0, 0x12,0xa7,0x64,0x6d,0x22,0x12,0x1a,0xb, 0x1b,0xfd,0xa, 0xcf,0x2d, +0xcd,0x2e,0xc4,0x0, 0x50,0x7e,0xc9,0xb0,0x4, 0x7a,0xc9,0xb0,0x80,0x58,0x74,0x63, +0xac,0xbf,0x49,0x25,0x2e,0x89,0x12,0xa7,0x64,0x49,0x33,0x0, 0x2, 0x9d,0x32,0x12, +0x1a,0x62,0x7d,0xc3,0x74,0x63,0xac,0xbf,0x49,0x25,0x2e,0x87,0x12,0xa7,0x64,0xb, +0x38,0x30,0x9d,0x32,0x12,0x1a,0x62,0x2d,0xc3,0xbe,0xc4,0x0, 0x50,0x58,0x43,0x12, +0xa7,0x53,0x7c,0x6f,0x12,0x22,0x68,0x40,0x8, 0x12,0xa7,0x53,0x12,0xa2,0xd0,0x50, +0x5, 0x74,0x38,0x12,0xa7,0x7e,0x12,0xa7,0x75,0xbe,0xb0,0x37,0x50,0x8, 0x2e,0xc4, +0x0, 0x50,0x4, 0x7a,0xc9,0xb0,0x7e,0xa0,0x1, 0x7e,0x70,0x5, 0xac,0x7f,0x19,0xa3, +0x32,0xc, 0x7e,0x90,0x3, 0x12,0xa7,0x99,0xa, 0xcf,0x2d,0xcd,0x19,0xbc,0x0, 0xa, +0x80,0x34,0x12,0xcf,0x86,0x78,0x8, 0x49,0x23,0x2e,0x89,0x4d,0x22,0x68,0x22,0x12, +0xa7,0xca,0x80,0x1d,0x12,0xa7,0x75,0xbe,0xb0,0x0, 0x28,0x1a,0xbe,0xb0,0x38,0x68, +0x15,0x12,0xcf,0x86,0x78,0x8, 0x49,0x23,0x2e,0x89,0x4d,0x22,0x68,0x3, 0x12,0xa7, +0xca,0x74,0x37,0x12,0xa7,0x7e,0x4c,0x99,0x68,0x2, 0xe1,0x4e,0x12,0xa7,0x53,0x7c, +0x6f,0x12,0x22,0x68,0x40,0x8, 0x12,0xa7,0x53,0x12,0xa2,0xd0,0x50,0x33,0x12,0xa7, +0xa3,0xa, 0xcf,0x2d,0xcd,0x9, 0xbc,0x0, 0x3c,0x70,0x6, 0x74,0x1, 0x19,0xbc,0x0, +0x3c,0xa, 0xcf,0x2d,0xcd,0x9, 0x7c,0x0, 0x3c,0xbe,0x70,0x1, 0x38,0x70,0x74,0x38, +0x19,0xbc,0x0, 0x50,0x12,0xa7,0x99,0xa, 0x3f,0x2d,0x3d,0x19,0xb3,0x0, 0xa, 0x80, +0x5d,0x74,0x9, 0xac,0xbe,0x49,0xc5,0x27,0xdc,0xbe,0xc4,0x0, 0x1e,0x38,0xb, 0x12, +0xa7,0x6c,0x40,0x6, 0xbe,0x44,0x8, 0xca,0x28,0x44,0xbe,0xc4,0x4, 0x1a,0x40,0xb, +0x12,0xa7,0x6c,0x40,0x6, 0xbe,0x44,0x8, 0xca,0x28,0x33,0x12,0xa7,0x6c,0x38,0xc, +0xbe,0xc4,0x0, 0x1e,0x40,0x6, 0xbe,0xc4,0x4, 0x1a,0x28,0x22,0xbe,0x44,0x8, 0xe8, +0x40,0xc, 0xbe,0xc4,0x0, 0x1e,0x40,0x6, 0xbe,0xc4,0x4, 0x1a,0x28,0x10,0xa, 0x3f, +0x2d,0x3d,0x9, 0xb3,0x0, 0x3c,0x70,0x6, 0x74,0x2, 0x19,0xb3,0x0, 0x3c,0xda,0x79, +0xda,0xd8,0x22,0x74,0x9, 0xac,0xbe,0x7d,0xc5,0x2d,0xcb,0x9, 0xbc,0x0, 0x7, 0x9, +0x7c,0x0, 0x8, 0x22,0x7e,0x70,0x9, 0xac,0x7e,0x2d,0x3b,0x22,0x49,0x45,0x27,0xde, +0xbe,0x44,0x0, 0x1e,0x22,0xa, 0xcf,0x2d,0xcd,0x9, 0xbc,0x0, 0x50,0x22,0xa, 0xcf, +0x2d,0xcd,0x19,0xbc,0x0, 0x50,0x22,0x49,0xa3,0x27,0xde,0xbe,0xa4,0x0, 0x1e,0x22, +0x74,0x9, 0xac,0xbe,0x7d,0xa5,0x2d,0xab,0x22,0x74,0x3, 0xa, 0xcf,0x2d,0xcd,0x7a, +0xc9,0xb0,0x22,0x6c,0xaa,0x7e,0x70,0x5, 0xac,0x7f,0x19,0xa3,0x32,0xf, 0x22,0x74, +0x9, 0xac,0xbe,0x49,0x55,0x27,0xde,0xbe,0x54,0x0, 0x1e,0x22,0x6d,0x22,0xa, 0x18, +0x6d,0x0, 0x12,0x17,0x18,0x2f,0x17,0x74,0x6, 0x22,0x2e,0x34,0x2e,0x87,0x7e,0x30, +0x9, 0xac,0x3e,0x2d,0x1b,0x74,0x9, 0x2, 0x17,0xb9,0x7d,0x1c,0x1a,0x2, 0x1a,0x0, +0x12,0x17,0x18,0x7f,0x71,0x74,0x9, 0xac,0xbd,0x22,0x7c,0xbd,0x7c,0x7c,0x2, 0x21, +0x50,0xe4,0x7a,0xb3,0x32,0xd8,0x74,0xff,0x22,0xca,0xd8,0xca,0x79,0x7e,0x74,0x3, +0x20,0x12,0xa9,0x7c,0x40,0x79,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x4, 0x7e,0x74,0x4, +0xb0,0x7e,0x37,0x27,0x5e,0xbe,0x34,0x1, 0xc2,0x8, 0x64,0x6c,0xdd,0x80,0x58,0xc2, +0x0, 0x7c,0xbd,0x12,0x8c,0x77,0x7a,0x35,0x26,0x7c,0xbd,0x7e,0x70,0x1, 0x12,0xa8, +0x84,0x7a,0x35,0x24,0x9e,0x35,0x26,0x7a,0x35,0x24,0x7e,0x15,0x26,0x7d,0x31,0x3e, +0x34,0x12,0xa9,0x49,0x7a,0x35,0x28,0xbe,0x75,0x28,0x58,0x3, 0x7a,0x75,0x28,0x7e, +0x5, 0x28,0xbe,0x5, 0x24,0x8, 0x8, 0xbe,0x14,0x0, 0xfa,0x58,0x2, 0xd2,0x0, 0x7c, +0xbd,0x12,0xa9,0x5a,0x50,0x2, 0xc2,0x0, 0x30,0x0, 0xa, 0x7c,0xbd,0x12,0x4f,0x3f, +0xac,0x7d,0x12,0x4f,0xf9,0xb, 0xd0,0x7e,0x73,0x27,0x58,0xbc,0x7d,0x38,0xa0,0xda, +0x79,0xda,0xd8,0x22,0xca,0x79,0x7c,0xa7,0x7c,0x8b,0x7e,0xb3,0x29,0x5c,0x7a,0xb3, +0x1e,0x44,0x7e,0xb3,0x29,0x5d,0x7a,0xb3,0x1e,0x45,0x7e,0x70,0x2, 0xac,0x78,0x9, +0x93,0x25,0xce,0x9, 0x83,0x25,0xcf,0x9f,0x77,0x1a,0x3a,0x1a,0x79,0x9d,0x73,0x21, +0x36,0x7a,0xf1,0x2b,0xbe,0xf0,0x0, 0x58,0xe, 0x1a,0x3f,0x1a,0x29,0x9d,0x23,0x1a, +0x39,0x2d,0x32,0x7c,0xb7,0xf5,0x2b,0x7e,0xb3,0x1e,0x44,0xbc,0xbf,0x18,0xe, 0x1a, +0x39,0x1a,0x2f,0x9d,0x23,0x1a,0x39,0x9d,0x32,0x7c,0xb7,0xf5,0x2b,0x1a,0x2a,0x1a, +0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x2a,0x80,0x3d,0x85,0x2a,0x2c,0xe5,0x2a,0xbe,0xb0, +0x0, 0x58,0x10,0xe5,0x2a,0x1a,0x3b,0x1a,0x28,0x9d,0x23,0x1a,0x38,0x2d,0x32,0x7c, +0xb7,0xf5,0x2c,0x7e,0xb3,0x1e,0x45,0xbe,0xb1,0x2a,0x18,0x10,0x1a,0x38,0xe5,0x2a, +0x1a,0x2b,0x9d,0x23,0x1a,0x38,0x9d,0x32,0x7c,0xb7,0xf5,0x2c,0xe5,0x2b,0x7e,0x71, +0x2c,0x12,0xa9,0x50,0x5, 0x2a,0x1a,0x3a,0x1a,0x28,0x2d,0x23,0xe5,0x2a,0x1a,0x3b, +0xbd,0x32,0x8, 0xb5,0xb, 0xf0,0x1a,0x3a,0x1a,0x29,0x2d,0x23,0x1a,0x3f,0xbd,0x32, +0x18,0x2, 0x1, 0xb1,0x7f,0x17,0xda,0x79,0x22,0x7e,0x24,0x0, 0x4, 0x2, 0x16,0xe6, +0x12,0x21,0x50,0x1a,0x26,0x1a,0x24,0x2f,0x71,0x22,0x7c,0x4b,0x74,0x2, 0xac,0xb4, +0x9, 0x55,0x25,0xce,0x9, 0x65,0x25,0xcf,0x7e,0x73,0x27,0x60,0xbc,0x75,0x78,0xa, +0x7e,0x73,0x27,0x61,0xbc,0x76,0x78,0x2, 0xd3,0x22,0xc3,0x22,0x6c,0x99,0x6c,0x88, +0x80,0xf, 0x7c,0xb8,0x12,0x8c,0x77,0xbe,0x34,0x1, 0xf4,0x8, 0x2, 0xb, 0x90,0xb, +0x80,0x7e,0x73,0x27,0x58,0xbc,0x78,0x38,0xe9,0xbe,0x90,0x2, 0x38,0x2, 0xc3,0x22, +0xd3,0x22,0xe4,0x7a,0xb3,0x39,0x82,0x7e,0xb3,0x27,0x58,0x60,0x6, 0x7e,0xb3,0x39, +0xfb,0x60,0x5, 0xe4,0x7a,0xb3,0x39,0xfd,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e, +0x73,0x29,0x5b,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x1a,0xb, +0x1b,0xfd,0x6c,0xdd,0x12,0xaa,0x6e,0x7a,0xb3,0x1e,0x7c,0x6c,0xcc,0x80,0x45,0x12, +0xaa,0x5d,0x78,0x3e,0x12,0xab,0x65,0xb, 0x1a,0xe0,0x7d,0x3f,0x12,0x1a,0x62,0x7d, +0x13,0x7d,0x3e,0x12,0x1a,0x62,0xbd,0x31,0x58,0x2, 0x7d,0xfe,0xbe,0xe5,0x2f,0x8, +0x5, 0x7e,0xe5,0x2f,0x80,0xb, 0x6d,0x33,0x9e,0x35,0x2f,0xbd,0x3e,0x8, 0x2, 0x7d, +0xe3,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1e,0x7c,0x4, 0x7a,0xb3, +0x1e,0x7c,0xb, 0xc0,0x7e,0x73,0x29,0x5d,0xbc,0x7c,0x38,0xb3,0x7e,0x73,0x1e,0x7c, +0x4c,0x77,0x68,0x1d,0x12,0xab,0x83,0x8, 0x2, 0x7d,0x7f,0x6c,0xcc,0x80,0xa, 0x12, +0xaa,0x5d,0x78,0x3, 0x12,0xab,0x6e,0xb, 0xc0,0x7e,0x73,0x29,0x5d,0xbc,0x7c,0x38, +0xee,0xb, 0xd0,0xbe,0xd0,0x2, 0x50,0x2, 0x21,0xd4,0xda,0x3b,0x22,0xa, 0xec,0x9, +0x7e,0x29,0xc9,0xa, 0x37,0x5e,0x34,0x0, 0x1, 0xa, 0xed,0xbd,0x3e,0x22,0x7e,0xf4, +0x7f,0xff,0x9f,0x44,0xe4,0x22,0xca,0x3b,0x7f,0x61,0x7f,0x50,0x7e,0x14,0x1c,0x23, +0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, 0xa, 0x20,0x7a,0x1d,0x2c,0x7e,0x73, +0x29,0x5a,0xa, 0x37,0x3e,0x34,0xca,0x39,0x7f,0x16,0x7f,0x5, 0x12,0x1a,0xb, 0x1b, +0xfd,0x6c,0xdd,0x12,0xaa,0x6e,0x7a,0xb3,0x1e,0x44,0x6c,0xcc,0x80,0x4a,0x12,0xab, +0x55,0x40,0x43,0x12,0xab,0x4b,0x50,0x3e,0x12,0xab,0x65,0xb, 0x1a,0x10,0x7d,0x3f, +0x12,0x1a,0x62,0x7d,0x3, 0x7d,0x31,0x12,0x1a,0x62,0xbd,0x30,0x58,0x2, 0x7d,0xf1, +0xbe,0x15,0x2a,0x8, 0x5, 0x7e,0x15,0x2a,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2a,0xbd, +0x1, 0x8, 0x2, 0x7d,0x10,0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x1e, +0x44,0x4, 0x7a,0xb3,0x1e,0x44,0xb, 0xc0,0x7e,0x73,0x29,0x5c,0xbc,0x7c,0x38,0xae, +0x7e,0x73,0x1e,0x44,0x4c,0x77,0x68,0x37,0x12,0xab,0x83,0x8, 0x2, 0x7d,0x7f,0xbe, +0x75,0x2a,0x8, 0x5, 0x7e,0x75,0x2a,0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2a,0xbd,0xe7, +0x8, 0x2, 0x7d,0x7e,0x6c,0xcc,0x80,0xf, 0x12,0xab,0x55,0x40,0x8, 0x12,0xab,0x4b, +0x50,0x3, 0x12,0xab,0x6e,0xb, 0xc0,0x7e,0x73,0x29,0x5c,0xbc,0x7c,0x38,0xe9,0xb, +0xd0,0xbe,0xd0,0x3, 0x50,0x2, 0x41,0xa3,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x2d, +0xa5,0xe7,0xbc,0xab,0x22,0xa, 0xec,0x9, 0xae,0x29,0xa6,0x7c,0x1d,0x2e,0x10,0x2c, +0xa5,0xe7,0xbc,0xab,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0x22,0x74,0x2, +0xac,0xbc,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xe0,0x9d,0xe7,0x7f,0x15,0x2d,0x35,0x1b, +0x1a,0xe0,0x22,0xa, 0x17,0x6d,0x0, 0x7f,0x14,0x12,0x17,0x85,0x7d,0x73,0x12,0x1a, +0x62,0x7d,0xe3,0x7d,0x3f,0x12,0x1a,0x62,0xbd,0x3e,0x22,0xca,0xd8,0xca,0x79,0x7c, +0xfb,0x7f,0x70,0xc2,0x0, 0x6c,0xdd,0x6d,0xdd,0x7e,0x34,0x1c,0x27,0x7e,0x24,0x0, +0xff,0x7e,0x14,0x1e,0x44,0x74,0xc, 0x12,0x17,0xda,0x6d,0x11,0x7e,0x4, 0x7f,0xff, +0x6c,0xee,0x80,0x13,0x12,0xac,0xae,0x7d,0xc3,0xbd,0xdc,0x50,0x2, 0x7d,0xdc,0xbd, +0xc, 0x28,0x2, 0x7d,0xc, 0xb, 0xe0,0xbc,0xfe,0x38,0xe9,0xbe,0xd4,0x0, 0x1e,0x58, +0xa, 0x7e,0xb3,0x27,0x68,0x70,0x4, 0x6d,0x33,0x81,0x96,0xbe,0xd4,0x4, 0xb0,0x8, +0x2, 0xd2,0x0, 0x6c,0xee,0x74,0x4, 0xac,0xbe,0x49,0x45,0x1e,0x44,0xbd,0x4d,0x58, +0x6, 0x49,0xd5,0x1e,0x46,0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0x3, 0x40,0xe7,0xbe,0xe0, +0x3, 0x78,0x4, 0x6d,0x33,0x80,0x7f,0xbd,0xd, 0x8, 0x5, 0x30,0x0, 0x2, 0x7d,0xd0, +0x9f,0x55,0x6c,0xee,0x80,0xb, 0x12,0xac,0xae,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, +0xe0,0xbc,0xfe,0x38,0xf1,0xa, 0x1f,0x12,0xac,0xa4,0x9f,0x55,0x6c,0xee,0x80,0x1d, +0x12,0xac,0x9b,0xb, 0x1a,0x90,0x7d,0x39,0x12,0x1a,0x62,0x7d,0xc3,0xbd,0x1c,0x28, +0xa, 0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f,0x51,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38, +0xdf,0x6d,0x11,0xbe,0xd0,0x0, 0x28,0x5, 0xa, 0x1d,0x12,0xac,0xa4,0xbd,0x1d,0x8, +0x4, 0x7d,0x1d,0x80,0xa, 0x6d,0x0, 0x9d,0xd, 0xbd,0x1, 0x8, 0x2, 0x7d,0x10,0x6c, +0xee,0x80,0xd, 0x12,0xac,0x9b,0xb, 0x1a,0x0, 0x9d,0x1, 0x1b,0x1a,0x0, 0xb, 0xe0, +0xbc,0xfe,0x38,0xef,0x7d,0x31,0xda,0x79,0xda,0xd8,0x22,0x74,0x2, 0xac,0xbe,0x7f, +0x17,0x2d,0x35,0x22,0x6d,0x0, 0x7f,0x15,0x12,0x17,0x85,0x7d,0x13,0x22,0x74,0x2, +0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, 0x1a,0x62,0xca,0xf8,0x7f,0x71, +0x6d,0xdd,0x6c,0xaa,0x7e,0xf0,0x7f,0xc2,0x0, 0x6d,0x44,0x80,0x1e,0x7d,0xc4,0x3e, +0xc4,0x7f,0x17,0x2d,0x3c,0x12,0xac,0xb6,0xbd,0x3d,0x48,0xd, 0x7d,0x34,0x3e,0x34, +0x2d,0x3f,0x7d,0x2e,0x12,0xac,0xb6,0x7d,0xd3,0xb, 0x44,0x7e,0xc5,0x34,0xbd,0xc4, +0x38,0xdb,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x3d,0x60, +0x5, 0xe, 0x34,0x14,0x78,0xfb,0xa, 0xcf,0xbd,0x3c,0x18,0xe8,0x7f,0x10,0x2e,0x35, +0x34,0x7a,0x1b,0xa0,0x6d,0x44,0x80,0x21,0x7d,0x54,0x3e,0x54,0x7f,0x17,0x2d,0x35, +0xb, 0x1a,0x30,0x7f,0x60,0x2e,0xd5,0x34,0x7e,0x6b,0xb0,0x60,0x5, 0xe, 0x34,0x14, +0x78,0xfb,0x7c,0xb7,0x12,0xad,0x45,0xb, 0x44,0x7e,0x55,0x34,0xbd,0x54,0x38,0xd8, +0xda,0xf8,0x22,0xa, 0x4a,0x7f,0x10,0x2d,0x34,0x7a,0x1b,0xb0,0x22,0x90,0x60,0x93, +0xe4,0x93,0xa, 0xb, 0x7e,0x73,0x29,0x5e,0xa, 0x17,0x2d,0x10,0x12,0x87,0xf7,0xad, +0x13,0x7d,0x21,0x6c,0x33,0x80,0x20,0xa, 0x3, 0x2d,0x2, 0x3e,0x4, 0x7e,0x7f,0x3c, +0x6c,0x2d,0xf0,0xb, 0x7a,0x0, 0x7e,0x90,0x2, 0xac,0x93,0x49,0xf4,0x12,0x9e,0x9d, +0xf, 0x59,0x4, 0x24,0x8a,0xb, 0x30,0xbc,0xa3,0x38,0xdc,0x7a,0x35,0x34,0x7e,0xf, +0x3a,0xee,0x7e,0x18,0x24,0x8a,0x2, 0xac,0xbc,0x7e,0xb3,0x2a,0xa, 0xb4,0x1, 0x31, +0x12,0xad,0xd2,0x7e,0x1f,0x3c,0x6c,0x7a,0x37,0x24,0xa, 0x7e,0x34,0xc, 0xd8,0x7a, +0x37,0x24,0x6, 0x12,0xad,0xd9,0x12,0xad,0xe2,0xe4,0x7a,0xb3,0x24,0x5, 0x7e,0x34, +0x0, 0x20,0x7a,0x37,0x24,0xc, 0x7a,0xb3,0x24,0x4, 0x7e,0x8, 0x24,0x2, 0x2, 0xd, +0x7, 0x22,0xa9,0xd1,0xcb,0xe4,0x2, 0x0, 0xe, 0x7e,0x73,0x29,0x5a,0x7a,0x73,0x24, +0x2, 0x22,0x7e,0x73,0x29,0x5b,0x7a,0x73,0x24,0x3, 0x22,0x12,0xad,0xfa,0xbe,0x34, +0x1, 0x90,0x28,0x3, 0xd2,0x16,0x22,0xc2,0x16,0x22,0x6d,0x11,0xe4,0x12,0x0, 0x1e, +0x6c,0xaa,0x80,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x7f,0x3c,0x82,0x2d,0xf0,0x69, +0x27,0x1, 0x0, 0x69,0x37,0x0, 0x80,0x9d,0x32,0x12,0x1a,0x62,0xbd,0x31,0x28,0x16, +0x7e,0x70,0x2, 0xac,0x7a,0x7e,0xf, 0x3c,0x82,0x2d,0x13,0x69,0x20,0x1, 0x0, 0x69, +0x30,0x0, 0x80,0x12,0xae,0x6a,0x7e,0x10,0x2, 0xac,0x1a,0x7e,0x1f,0x3c,0x82,0x2d, +0x30,0x69,0x1, 0x0, 0x80,0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0x69, +0x1, 0x1, 0x0, 0xbe,0x4, 0x7f,0xff,0x78,0x4, 0x7e,0x14,0x7f,0xff,0xb, 0xa0,0x7e, +0xb3,0x29,0x61,0xbc,0xba,0x38,0x9d,0x7d,0x31,0x22,0x9d,0x32,0x12,0x1a,0x62,0x7d, +0x13,0x22,0x7e,0x60,0x4, 0x7e,0x27,0x3c,0x8c,0xbe,0x24,0x3, 0xe8,0x28,0x3, 0x7e, +0x60,0x8, 0x7e,0xb3,0x27,0x80,0xb4,0x1, 0x1a,0x7e,0x73,0x34,0x89,0xbc,0x76,0x50, +0xf, 0xe4,0x7a,0xb3,0x27,0x81,0x12,0x4c,0x15,0x7e,0xb3,0x34,0x89,0x4, 0x80,0x4, +0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x34,0x89,0x7e,0xb3,0x27,0x81,0xb4,0x1, 0x17,0x7e, +0xa3,0x34,0x8a,0xbe,0xa0,0x5, 0x50,0xa, 0xe4,0x7a,0xb3,0x27,0x81,0x7c,0xba,0x4, +0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x34,0x8a,0x22,0x6c,0xaa,0x80,0x26, +0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12,0x5, 0x80,0x49,0x32,0x4, 0x0, 0x2d,0x31,0x59, +0x32,0x5, 0x80,0x30,0x6, 0xe, 0x49,0x12,0x4, 0x60,0x49,0x32,0x5, 0xe0,0x2d,0x31, +0x59,0x32,0x5, 0xe0,0xb, 0xa0,0x7e,0xb3,0x29,0x61,0xa, 0x3b,0x7e,0xb3,0x29,0x60, +0xa, 0x2b,0x2d,0x23,0xa, 0x3a,0xbd,0x32,0x48,0xc6,0x22,0xd2,0x0, 0x6c,0xaa,0x6c, +0x77,0x80,0x1f,0x7e,0x63,0x29,0x5b,0xa, 0x16,0xa, 0x27,0x2d,0x21,0x7c,0x65,0x7e, +0x50,0x2, 0xac,0x56,0x49,0x22,0x5, 0x20,0xbe,0x24,0xfe,0xc, 0x58,0x2, 0xb, 0xa0, +0xb, 0x70,0x7e,0xb3,0x29,0x5a,0xbc,0xb7,0x38,0xd9,0xa, 0x2b,0x1e,0x24,0xa, 0x3a, +0xbd,0x32,0x8, 0x2, 0xc2,0x0, 0xa2,0x0, 0x22,0x7e,0x63,0x29,0x5c,0x7e,0xa3,0x29, +0x5d,0x7e,0x70,0x1, 0x80,0xf, 0xa, 0x17,0x12,0x4c,0x23,0xbe,0x24,0xff,0x38,0x58, +0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x16,0x1b,0x14,0xa, 0x27,0xbd,0x21,0x48,0xe7,0x7e, +0x70,0x2, 0x80,0x13,0x7e,0x50,0x2, 0xac,0x57,0x49,0x22,0x4, 0xc0,0xbe,0x24,0xff, +0x38,0x58,0x2, 0xd3,0x22,0xb, 0x70,0xa, 0x1a,0x1b,0x15,0xa, 0x27,0xbd,0x21,0x48, +0xe3,0xc3,0x22,0x7e,0xb3,0x3a,0x11,0xb4,0x1, 0x3, 0x2, 0xaf,0xea,0x7e,0xb3,0x3a, +0x77,0x4, 0x7a,0xb3,0x3a,0x77,0x7e,0xb3,0x3a,0x5, 0xb4,0x2, 0x18,0x7e,0xb3,0x3a, +0x76,0x4, 0x7a,0xb3,0x3a,0x76,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x3a,0x77,0x74, +0x1, 0x7a,0xb3,0x3a,0x5, 0x7e,0x73,0x3a,0x76,0xbe,0x70,0x3, 0x40,0xf, 0x74,0x1, +0x7a,0xb3,0x3a,0x11,0x12,0xaf,0xea,0x12,0xb3,0x33,0x12,0xaf,0xf1,0x7e,0x73,0x3a, +0x77,0xbe,0x70,0xa, 0x28,0x3, 0x2, 0xaf,0xf1,0x22,0x74,0x2, 0x7a,0xb3,0x3a,0x5, +0x22,0xe4,0x7a,0xb3,0x3a,0x77,0x7a,0xb3,0x3a,0x76,0x22,0x12,0xaf,0xf1,0xe4,0x7a, +0xb3,0x3a,0x11,0x22,0xbe,0x34,0x2, 0x58,0x28,0xd, 0x7e,0x53,0x3a,0x78,0xbe,0x50, +0x8, 0x50,0x3f,0x74,0x8, 0x80,0x37,0xbe,0x34,0x1, 0xe0,0x28,0xd, 0x7e,0x53,0x3a, +0x78,0xbe,0x50,0x6, 0x50,0x2c,0x74,0x6, 0x80,0x24,0xbe,0x34,0x1, 0x68,0x28,0xd, +0x7e,0x53,0x3a,0x78,0xbe,0x50,0x4, 0x50,0x19,0x74,0x4, 0x80,0x11,0xbe,0x34,0x0, +0xf0,0x28,0xf, 0x7e,0x73,0x3a,0x78,0xbe,0x70,0x2, 0x50,0x6, 0x74,0x2, 0x7a,0xb3, +0x3a,0x78,0x7e,0xb3,0x3a,0x78,0xbe,0xb0,0x0, 0x28,0x19,0x14,0x7a,0xb3,0x3a,0x78, +0x74,0x1, 0x7a,0xb3,0x15,0xa2,0x7e,0x73,0x3a,0x78,0xbe,0x70,0x4, 0x28,0x5, 0xe4, +0x7a,0xb3,0x15,0xa1,0x22,0x7e,0x73,0x3a,0x5, 0x7a,0x73,0x3a,0x7b,0x7e,0x47,0x3c, +0x69,0xbe,0x44,0x0, 0x78,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x3a,0x5, 0xbe,0x44,0x0, +0xf0,0x28,0x8, 0xe4,0x7a,0xb3,0x3a,0x3, 0x12,0xaf,0xea,0x7e,0x57,0x3a,0xb, 0xbd, +0x54,0x50,0x4, 0x7a,0x47,0x3a,0xb, 0x12,0xb2,0x8e,0x38,0x10,0x12,0xb2,0x86,0x38, +0xb, 0x12,0xb0,0xf3,0x38,0x6, 0x7e,0xb3,0x15,0xa1,0x70,0x34,0x12,0xaf,0x93,0xbe, +0x44,0x0, 0x3c,0x50,0x21,0x7e,0xb3,0x3a,0x3, 0x4, 0x7a,0xb3,0x3a,0x3, 0x7e,0x73, +0x3a,0x3, 0xbe,0x70,0x32,0x28,0x14,0x74,0x32,0x7a,0xb3,0x3a,0x3, 0x12,0xb2,0xa0, +0x7a,0xb3,0x3a,0x78,0x80,0x5, 0xe4,0x7a,0xb3,0x3a,0x3, 0x7d,0x34,0x2, 0xb0,0x4, +0x2, 0xaf,0xfb,0x7e,0x73,0x25,0xc9,0xbe,0x70,0x0, 0x22,0xca,0x79,0x7e,0xf0,0xff, +0x12,0xb2,0xb7,0x7e,0xb3,0x3a,0x7, 0xb4,0x1, 0x8, 0x12,0x6b,0x76,0xe4,0x7a,0xb3, +0x3a,0x7, 0x7e,0xb3,0x3a,0x6, 0x60,0x4, 0x74,0xff,0x21,0xfc,0x7e,0xb3,0x3a,0x5, +0xb4,0x2, 0x2, 0x80,0x2, 0x21,0xf0,0x12,0xb2,0x8e,0x38,0x12,0x12,0xb2,0x86,0x38, +0xd, 0x12,0xb0,0xf3,0x38,0x8, 0x7e,0xb3,0x15,0xa1,0x60,0x2, 0x21,0xf0,0x74,0x3, +0x12,0xb1,0xff,0x7c,0xeb,0x7e,0xb3,0x3a,0x4, 0x4, 0x7a,0xb3,0x3a,0x4, 0x74,0x3, +0x12,0xb1,0xff,0x7c,0xab,0xbe,0xa0,0xff,0x68,0x23,0xbe,0xe0,0xff,0x68,0x1c,0x7e, +0x30,0xc, 0xac,0x3e,0x49,0x21,0x3a,0x1a,0xbe,0x24,0x2, 0x58,0x28,0xf, 0x12,0xb2, +0x96,0x3e,0x34,0xbd,0x23,0x28,0x6, 0x7c,0xea,0x80,0x2, 0x7c,0xea,0xbe,0xe0,0xff, +0x78,0x11,0xe4,0x7a,0xb3,0x3a,0x4, 0x7a,0xb3,0x3a,0x5, 0x7a,0xb3,0x3a,0x11,0x74, +0xff,0x80,0x69,0x7e,0x73,0x3a,0x4, 0xbe,0x70,0x4, 0x28,0x54,0x74,0xc, 0xac,0xbe, +0x49,0x35,0x3a,0x1a,0xbe,0x34,0x2, 0x58,0x40,0x6, 0x7e,0xb3,0x15,0xa1,0x70,0x37, +0x7e,0x37,0x3a,0x0, 0xbe,0x34,0x1, 0x2c,0x38,0xa, 0x7e,0x37,0x3a,0xb, 0xbe,0x34, +0x1, 0x2c,0x28,0x23,0x74,0x5, 0xac,0xbe,0x9, 0x75,0x25,0x7, 0xbe,0x73,0x29,0xfc, +0x68,0x15,0x7c,0xfe,0xbe,0xf0,0x4, 0x50,0x8, 0x12,0x86,0xe8,0xbe,0xb0,0x4, 0x40, +0x6, 0x74,0x1, 0x7a,0xb3,0x3a,0x7, 0xe4,0x7a,0xb3,0x3a,0x11,0x7a,0xb3,0x3a,0x5, +0xbe,0xf0,0xff,0x68,0x5, 0xe4,0x7a,0xb3,0x3a,0x4, 0x7c,0xbf,0xda,0x79,0x22,0x7c, +0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22,0x80,0x2a,0x12,0xb2,0x78,0x68,0x23,0x7e,0x70, +0xc, 0xac,0x72,0x12,0xb2,0xaa,0x7d,0x23,0x7e,0x70,0xc, 0xac,0x72,0x59,0x23,0x3a, +0x1e,0x49,0x3, 0x3a,0x1e,0x49,0x23,0x3a,0x1a,0xbd,0x20,0x50,0x4, 0x59,0x3, 0x3a, +0x1a,0xb, 0x20,0xbc,0x32,0x50,0xd2,0x6c,0xaa,0x6c,0x22,0x80,0x18,0x12,0xb2,0x78, +0x68,0x11,0x7e,0x70,0xc, 0xac,0x72,0x49,0x3, 0x3a,0x1a,0xbd,0x4, 0x50,0x4, 0x7d, +0x40,0x7c,0xa2,0xb, 0x20,0xbc,0x32,0x50,0xe4,0x7e,0x37,0x3a,0x0, 0xbe,0x37,0x3a, +0x79,0x50,0x8, 0x7e,0x37,0x3a,0x79,0x7a,0x37,0x3a,0x0, 0x12,0xb2,0x96,0x4d,0x33, +0x78,0x3, 0x7e,0xa0,0xff,0x7c,0xba,0x22,0x7e,0x10,0x5, 0xac,0x12,0x9, 0xb0,0x25, +0x7, 0xbe,0xb3,0x29,0xfc,0x22,0x7e,0x73,0x25,0xc8,0xbe,0x70,0x0, 0x22,0x7e,0x73, +0x27,0x66,0xbe,0x70,0x0, 0x22,0x7e,0x70,0xc, 0xac,0x7a,0x49,0x33,0x3a,0x1a,0x22, +0xe4,0x7a,0xb3,0x3a,0x5, 0x7a,0xb3,0x3a,0xd, 0x22,0x49,0x23,0x3a,0x20,0x49,0x33, +0x3a,0x1c,0x9d,0x32,0x2, 0x1a,0x62,0x7e,0xb3,0x3a,0x6, 0xb4,0x1, 0x27,0x7e,0xb3, +0x3a,0x7c,0x4, 0x7a,0xb3,0x3a,0x7c,0x7e,0x73,0x3a,0x7c,0xbe,0x70,0x3, 0x40,0x15, +0x12,0x6c,0xf, 0x7e,0x73,0x3a,0x7c,0xbe,0x70,0x6, 0x40,0x9, 0xe4,0x7a,0xb3,0x3a, +0x7c,0x7a,0xb3,0x3a,0x6, 0x22,0x7e,0x8, 0x3a,0x16,0x7e,0x34,0x0, 0x60,0xe4,0x12, +0x1a,0x30,0x6c,0xaa,0x7e,0x44,0xff,0xff,0x7e,0x70,0xc, 0xac,0x7a,0x59,0x43,0x3a, +0x18,0x59,0x43,0x3a,0x20,0xb, 0xa0,0xbe,0xa0,0x8, 0x40,0xe8,0x7e,0x8, 0x3a,0x4, +0x7e,0x34,0x0, 0xd, 0xe4,0x2, 0x1a,0x30,0x7e,0xa3,0x2a,0x4f,0xbc,0xab,0x68,0x6, +0x7a,0xb3,0x2a,0x4f,0xd2,0xf, 0x30,0xf, 0x9, 0xc2,0xf, 0x12,0x2f,0xec,0xe4,0x2, +0xa, 0x66,0x22,0xe4,0x7a,0xb3,0x3a,0x3, 0x6d,0x33,0x6c,0xaa,0x7e,0x50,0xc, 0xac, +0x5a,0x59,0x32,0x3a,0x1a,0xb, 0xa0,0xbe,0xa0,0x4, 0x40,0xf0,0xe4,0x7a,0xb3,0x3a, +0x4, 0x6d,0x33,0x7a,0x37,0x3a,0xb, 0x7a,0x37,0x3a,0x0, 0x22,0x12,0x5f,0xb7,0x7e, +0xb3,0x3a,0x89,0xb4,0x1, 0x10,0x7e,0x34,0x1, 0x2c,0x7a,0x37,0x29,0x47,0x7e,0x34, +0x1, 0x18,0x7a,0x37,0x29,0x49,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x1b,0x7e,0x34,0x1, +0x90,0x7a,0x37,0x29,0x47,0x7e,0x24,0x1, 0x2c,0x7a,0x27,0x29,0x49,0x7a,0x37,0x29, +0x3c,0x7e,0x34,0x1, 0x7c,0x12,0x5f,0xae,0x7e,0xb3,0x28,0xf4,0x70,0x21,0x7e,0x27, +0x29,0x47,0x7d,0x32,0x7e,0x14,0x0, 0x4, 0xad,0x13,0x7d,0x31,0x12,0x6c,0x83,0xbe, +0x34,0x0, 0x28,0x28,0x4, 0x7e,0x34,0x0, 0x28,0x2d,0x32,0x7a,0x37,0x29,0x47,0x22, +0x6d,0x33,0x7d,0x23,0x7d,0x3, 0x6c,0x33,0x80,0x45,0x6c,0x22,0x80,0x37,0x7e,0xb3, +0x29,0x5b,0xac,0xb3,0xa, 0x42,0x2d,0x54,0x7d,0x45,0x3e,0x44,0x7e,0x7f,0x12,0x9a, +0x2d,0xf4,0xb, 0x7a,0x40,0xbe,0x44,0x0, 0x32,0x8, 0x8, 0xbe,0x44,0x2, 0x58,0x58, +0x2, 0xb, 0x24,0xbe,0x44,0xff,0xce,0x58,0x8, 0xbe,0x44,0xfd,0xa8,0x8, 0x2, 0xb, +0x4, 0xb, 0x34,0xb, 0x21,0x7e,0x93,0x29,0x5b,0xbc,0x92,0x38,0xc1,0xb, 0x31,0x7e, +0xb3,0x29,0x5a,0xbc,0xb3,0x38,0xb3,0x7e,0x54,0x0, 0x6, 0xad,0x53,0x7d,0x15,0x1e, +0x14,0x1e,0x14,0x1e,0x14,0x12,0x6c,0x85,0xbd,0x12,0x50,0x22,0xbd,0x30,0x28,0x1e, +0xe4,0x7a,0xb3,0x3c,0x90,0x7e,0xb3,0x3c,0x91,0xbe,0xb0,0x5, 0x50,0x7, 0x4, 0x7a, +0xb3,0x3c,0x91,0x80,0x3c,0xe4,0x7a,0xb3,0x3c,0x91,0x74,0x1, 0x80,0x2f,0xbd,0x10, +0x50,0x22,0xbd,0x32,0x28,0x1e,0xe4,0x7a,0xb3,0x3c,0x91,0x7e,0xb3,0x3c,0x90,0xbe, +0xb0,0x5, 0x50,0x7, 0x4, 0x7a,0xb3,0x3c,0x90,0x80,0x16,0xe4,0x7a,0xb3,0x3c,0x90, +0x74,0x2, 0x80,0x9, 0xe4,0x7a,0xb3,0x3c,0x90,0x7a,0xb3,0x3c,0x91,0x7a,0xb3,0x3c, +0x92,0x7e,0xb3,0x3c,0x92,0x22,0xe4,0x7a,0xb3,0x27,0x7c,0x7a,0xb3,0x3c,0x93,0x22, +0xca,0xd8,0xca,0x79,0xc2,0x0, 0x6c,0xdd,0x7e,0x57,0x27,0x6d,0x7d,0xf5,0x7e,0xe7, +0x27,0x6b,0x7e,0x37,0x3b,0xa9,0x4d,0x33,0x68,0x4, 0x7d,0xf5,0xe, 0xf4,0x6c,0xff, +0x7e,0xa3,0x29,0x5b,0x7c,0x8a,0x7e,0xb3,0x27,0x79,0x14,0x68,0x21,0x14,0x68,0x14, +0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0x16,0x24,0x45,0x78,0x10,0x7c,0xfa,0x7e,0x83, +0x29,0x5a,0x80,0xa, 0x7e,0x73,0x29,0x5a,0x2c,0x87,0x80,0x2, 0x6c,0x88,0x6c,0x99, +0x80,0xf, 0x7c,0xb9,0x12,0x8c,0x77,0xbe,0x34,0x2, 0x58,0x8, 0x2, 0xb, 0xd0,0xb, +0x90,0x7e,0x33,0x27,0x58,0xbc,0x39,0x38,0xe9,0xbe,0xd0,0x3, 0x40,0x2, 0xc1,0x48, +0x7e,0xa3,0x27,0x59,0xbe,0xa0,0x0, 0x38,0xb, 0xbe,0x30,0x0, 0x28,0x37,0x7e,0xb3, +0x25,0x57,0x70,0x31,0x6c,0x99,0x80,0x29,0xa, 0x29,0xa, 0x3f,0x2d,0x32,0x3e,0x34, +0x49,0x23,0x5, 0x20,0xbd,0x2f,0x8, 0x17,0x49,0x3, 0x4, 0xc0,0xbd,0xe, 0x58,0xf, +0x6d,0x33,0x9d,0x3e,0x12,0xb6,0x4f,0xbd,0x3, 0x8, 0x4, 0xd2,0x0, 0x80,0x6, 0xb, +0x90,0xbc,0x89,0x38,0xd3,0x6d,0xee,0x9e,0xe7,0x29,0x3c,0xbe,0xe7,0x7, 0x8, 0x8, +0x2, 0xc2,0x0, 0x30,0x0, 0x20,0x7e,0xb3,0x3c,0x93,0x4, 0x7a,0xb3,0x3c,0x93,0x7e, +0x23,0x3c,0x93,0xbe,0x20,0xa, 0x28,0x1d,0x74,0xa, 0x7a,0xb3,0x3c,0x93,0x74,0x1, +0x7a,0xb3,0x27,0x7c,0x80,0xf, 0x7e,0x23,0x3c,0x93,0xbe,0x20,0x0, 0x28,0x6, 0x1e, +0x20,0x7a,0x23,0x3c,0x93,0x6c,0xee,0xbe,0x30,0x0, 0x38,0x5, 0xbe,0xa0,0x0, 0x28, +0x60,0x7e,0xb3,0x27,0x7b,0xb4,0x1, 0x9, 0x7e,0xb3,0x27,0x7e,0xbe,0xb0,0x1, 0x68, +0x50,0x7e,0xb3,0x27,0x7c,0xb4,0x1, 0x49,0x6c,0x99,0x80,0x18,0x7e,0x70,0x2, 0xac, +0x79,0x9, 0xa3,0x25,0xce,0x9, 0xd3,0x25,0xcf,0x7c,0xba,0x7c,0x7d,0x12,0x77,0x81, +0x18,0x7, 0xb, 0x90,0x12,0x4b,0xe4,0x38,0xe3,0x6c,0x99,0x80,0x1c,0x7e,0x70,0x2, +0xac,0x79,0x9, 0xa3,0x26,0xa, 0x9, 0xd3,0x26,0xb, 0x7c,0xba,0x7c,0x7d,0x12,0x21, +0x50,0xbe,0x34,0xff,0x6a,0x48,0xa, 0xb, 0x90,0x7e,0xb3,0x27,0x59,0xbc,0xb9,0x38, +0xdc,0x6c,0x99,0x80,0x17,0xa, 0xe9,0xa, 0x5f,0x2d,0x5e,0x3e,0x54,0x49,0x55,0x5, +0x20,0xbd,0x5f,0x8, 0x5, 0x7e,0xe0,0x1, 0x80,0x6, 0xb, 0x90,0xbc,0x89,0x38,0xe5, +0x4c,0xee,0x78,0x25,0x7e,0xb3,0x3c,0x94,0x4, 0x7a,0xb3,0x3c,0x94,0x7e,0x73,0x3c, +0x94,0xbe,0x70,0x5, 0x28,0x22,0x74,0x5, 0x7a,0xb3,0x3c,0x94,0x7e,0xb3,0x27,0x7c, +0x60,0x2, 0xd2,0x18,0x12,0xb4,0x86,0x80,0xf, 0x7e,0x73,0x3c,0x94,0xbe,0x70,0x0, +0x28,0x6, 0x1e,0x70,0x7a,0x73,0x3c,0x94,0xda,0x79,0xda,0xd8,0x22,0x2d,0x3d,0x7e, +0x24,0x0, 0x2, 0x2, 0x16,0xe6,0xca,0x3b,0x7c,0xdb,0x75,0x44,0x0, 0x75,0x45,0x0, +0x7e,0xb3,0x29,0x5c,0xf5,0x4a,0x7e,0xb3,0x29,0x5d,0xf5,0x4b,0x75,0x4c,0x28,0x7e, +0xb3,0x27,0x58,0xf5,0x2c,0xe4,0x7a,0xb3,0x2, 0xe1,0x7a,0xb3,0x2, 0xdd,0x7a,0xb3, +0x2, 0xde,0x7e,0x8, 0x2, 0xe2,0x12,0x59,0x83,0xe4,0x12,0x1a,0x30,0x12,0x59,0x83, +0x3e,0x34,0x7e,0x8, 0x3, 0x2, 0xe4,0x12,0x1a,0x30,0x75,0x43,0x0, 0x30,0x14,0xd, +0x7e,0x34,0x0, 0xfa,0x7a,0x35,0x3f,0x7e,0x34,0x1, 0x5e,0x80,0x7, 0x7e,0x34,0x1, +0x5e,0x7a,0x35,0x3f,0x7a,0x35,0x41,0x7e,0x37,0x7, 0x12,0xbe,0x35,0x41,0x48,0x9, +0x7e,0x37,0x7, 0x10,0xbe,0x35,0x3f,0x58,0x3, 0x75,0x43,0x1, 0x30,0xe, 0x3, 0x75, +0x43,0x1, 0xe5,0x2c,0xbe,0xb0,0x2, 0x50,0x3, 0x2, 0xbf,0x8e,0x6c,0xcc,0x2, 0xbf, +0x85,0x7e,0x70,0x2, 0xac,0x7c,0x12,0x8c,0x63,0x9, 0xb3,0x25,0xcf,0xf5,0x25,0x4c, +0xcc,0x68,0x8, 0xa, 0x3c,0x9, 0xb3,0x2, 0xe2,0x70,0xa, 0xa, 0x3c,0xb, 0x34,0xa, +0x2c,0x19,0x72,0x2, 0xe2,0xe5,0x2c,0x14,0xbc,0xbc,0x78,0x3, 0x2, 0xbf,0x8e,0xa, +0x5c,0xb, 0x54,0xf5,0x2d,0x2, 0xbf,0x79,0x75,0x59,0x0, 0x7e,0x71,0x2d,0x12,0xd0, +0xc2,0x7a,0xa1,0x26,0x9, 0xb3,0x25,0xcf,0xf5,0x27,0xa, 0x2a,0xe5,0x24,0x12,0x47, +0xda,0x7c,0xb7,0xf5,0x28,0xe5,0x27,0xa, 0x2b,0xe5,0x25,0x12,0x47,0xda,0x7c,0xb7, +0xf5,0x29,0xe5,0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xbf,0x77,0xe5,0x29,0xbe,0xb0, +0x5, 0x40,0x3, 0x2, 0xbf,0x77,0xe5,0x24,0x7e,0x71,0x25,0x7e,0x61,0x26,0x7e,0x51, +0x27,0x12,0xc4,0xc3,0x7a,0xb3,0x2, 0xe0,0x85,0x25,0x65,0x85,0x26,0x66,0x85,0x27, +0x67,0x7e,0x8, 0x0, 0x33,0x7e,0x18,0x0, 0x35,0xe5,0x24,0x12,0xc5,0x7b,0x75,0x44, +0x0, 0x75,0x45,0x0, 0x75,0x32,0x0, 0xe5,0x24,0x7e,0x71,0x25,0x12,0x21,0x50,0x7a, +0x35,0x37,0xe5,0x26,0x7e,0x71,0x27,0x12,0x21,0x50,0x7a,0x35,0x39,0x7e,0x35,0x37, +0xbe,0x35,0x39,0x8, 0x5, 0x7e,0x35,0x39,0x80,0x3, 0x7e,0x35,0x37,0x7a,0x35,0x3d, +0xe, 0x34,0x7a,0x35,0x3b,0xe5,0x28,0xbe,0xb0,0x1, 0x38,0x12,0xe5,0x29,0xbe,0xb0, +0x1, 0x38,0xb, 0x7c,0xbd,0x30,0xe1,0x6, 0x75,0x32,0x1, 0x2, 0xbd,0x16,0xe5,0x28, +0xbe,0xb0,0x1, 0x38,0xa, 0xe5,0x29,0xbe,0xb0,0x1, 0x38,0x3, 0x2, 0xbd,0x16,0xe5, +0x28,0xbe,0xb0,0x5, 0x40,0x3, 0x2, 0xbd,0x16,0xe5,0x29,0xbe,0xb0,0x5, 0x40,0x3, +0x2, 0xbd,0x16,0x7c,0xbd,0x20,0xe0,0x3, 0x2, 0xbd,0x16,0x6d,0x88,0x7d,0x98,0x75, +0x5a,0x0, 0x75,0x5b,0x0, 0xc2,0x1, 0xc2,0x2, 0xe5,0x26,0xbe,0xb1,0x24,0x28,0x6, +0xe5,0x24,0x7c,0xeb,0x80,0x3, 0x7e,0xe1,0x26,0xe5,0x26,0xbe,0xb1,0x24,0x50,0x4, +0xe5,0x24,0x80,0x2, 0xe5,0x26,0xf5,0x2a,0xe5,0x27,0xbe,0xb1,0x25,0x28,0x6, 0xe5, +0x25,0x7c,0xfb,0x80,0x3, 0x7e,0xf1,0x27,0xe5,0x27,0xbe,0xb1,0x25,0x50,0x4, 0xe5, +0x25,0x80,0x2, 0xe5,0x27,0xf5,0x2b,0xe5,0x4a,0xa, 0xdb,0x1b,0xd4,0xe5,0x2a,0xa, +0xab,0xbd,0xad,0xe5,0x2a,0x58,0x6, 0xa, 0x5b,0xb, 0x54,0x80,0x0, 0xf5,0x55,0xbe, +0xe0,0x0, 0x28,0x6, 0xa, 0x5e,0x1b,0x54,0x80,0x2, 0x7c,0xbe,0xf5,0x56,0x12,0xd0, +0xb9,0xa, 0xcb,0xbd,0xcb,0xe5,0x2b,0x58,0x6, 0xa, 0x5b,0xb, 0x54,0x80,0x0, 0xf5, +0x57,0xbe,0xf0,0x0, 0x28,0x6, 0xa, 0x5f,0x1b,0x54,0x80,0x2, 0x7c,0xbf,0xf5,0x58, +0x75,0x2e,0x0, 0x80,0x71,0xbe,0xc1,0x2e,0x68,0x6a,0xe5,0x2d,0xbe,0xb1,0x2e,0x68, +0x63,0x7e,0x91,0x2e,0x74,0x2, 0xac,0x9b,0x9, 0xa4,0x25,0xce,0xbe,0xa1,0x55,0x78, +0x11,0x7d,0x3a,0xb, 0x34,0xe5,0x55,0xa, 0xbb,0xbd,0xb3,0x78,0x5, 0x85,0x2a,0x55, +0x80,0x14,0xbe,0xa1,0x56,0x78,0xf, 0xe5,0x56,0xa, 0xbb,0xb, 0xb4,0xa, 0x5e,0xbd, +0xb5,0x78,0x3, 0x7a,0xe1,0x56,0x9, 0xa4,0x25,0xcf,0xbe,0xa1,0x57,0x78,0x11,0x7d, +0x3c,0xb, 0x34,0xe5,0x57,0xa, 0xbb,0xbd,0xb3,0x78,0x5, 0x85,0x2b,0x57,0x80,0x14, +0xbe,0xa1,0x58,0x78,0xf, 0xe5,0x58,0xa, 0x3b,0xb, 0x34,0xa, 0xbf,0xbd,0x3b,0x78, +0x3, 0x7a,0xf1,0x58,0x5, 0x2e,0xe5,0x2c,0xbe,0xb1,0x2e,0x38,0x88,0xe5,0x2a,0xbc, +0xbe,0x78,0x1c,0xd2,0x1, 0x4c,0xee,0x68,0x7, 0xe5,0x4a,0x14,0xbc,0xbe,0x78,0x2, +0xd2,0x2, 0xbe,0xe0,0x0, 0x28,0x2, 0x1b,0xe0,0xbd,0xad,0x58,0x2, 0x5, 0x2a,0xe5, +0x2b,0xbc,0xbf,0x78,0x21,0xd2,0x1, 0x4c,0xff,0x68,0x7, 0xe5,0x4b,0x14,0xbc,0xbf, +0x78,0x2, 0xd2,0x2, 0xbe,0xf0,0x0, 0x28,0x2, 0x1b,0xf0,0x12,0xd0,0xb9,0xa, 0xdb, +0xbd,0xdb,0x58,0x2, 0x5, 0x2b,0x75,0x30,0x0, 0x75,0x31,0x0, 0x75,0x2f,0x0, 0x80, +0x16,0xe5,0x2f,0xa, 0xdb,0x9, 0x7d,0x25,0x2f,0xbe,0x71,0x55,0x38,0x7, 0xbe,0x71, +0x56,0x40,0x2, 0x5, 0x30,0x5, 0x2f,0x7e,0x73,0x25,0x58,0xbe,0x71,0x2f,0x38,0xe1, +0x75,0x2f,0x0, 0x80,0x16,0xe5,0x2f,0xa, 0xdb,0x9, 0x7d,0x25,0x43,0xbe,0x71,0x57, +0x38,0x7, 0xbe,0x71,0x58,0x40,0x2, 0x5, 0x31,0x5, 0x2f,0x7e,0x73,0x25,0x59,0xbe, +0x71,0x2f,0x38,0xe1,0x7a,0xe1,0x46,0x80,0x4f,0x7a,0xf1,0x47,0x80,0x41,0xe5,0x46, +0x7e,0x71,0x47,0x12,0x21,0x50,0x7a,0x35,0x48,0xbe,0xe1,0x46,0x68,0x13,0xe5,0x2a, +0xbe,0xb1,0x46,0x68,0xc, 0xbe,0xf1,0x47,0x68,0x7, 0xe5,0x2b,0xbe,0xb1,0x47,0x78, +0x9, 0x7e,0xd5,0x48,0x2d,0x9d,0x5, 0x5a,0x80,0x13,0x5, 0x5b,0x7e,0xd5,0x48,0x2d, +0x8d,0x7e,0xd5,0x35,0xbe,0xd5,0x48,0x58,0x2, 0x5, 0x44,0x5, 0x45,0x5, 0x47,0xe5, +0x2b,0xbe,0xb1,0x47,0x50,0xb8,0x5, 0x46,0xe5,0x2a,0xbe,0xb1,0x46,0x50,0xaa,0xe5, +0x2a,0x12,0xbf,0xe2,0x7c,0xbe,0x12,0xbf,0xf3,0x12,0xbf,0xe2,0xe5,0x2a,0x12,0xbf, +0xf3,0x7e,0xd5,0x39,0x2e,0xd5,0x37,0x7a,0xd5,0x3b,0x30,0x1, 0xa, 0x20,0x2, 0x7, +0x9e,0x95,0x3b,0x15,0x5a,0x15,0x5a,0xe5,0x5a,0xbe,0xb0,0x4, 0x28,0x6, 0xe5,0x5a, +0x24,0xfc,0xf5,0x5a,0xbe,0x94,0x0, 0x0, 0x58,0x2, 0x6d,0x99,0x75,0x4c,0x22,0xe5, +0x4a,0x14,0xbe,0xb1,0x24,0x68,0xd, 0xbe,0xb1,0x26,0x68,0x8, 0xe5,0x24,0x60,0x4, +0xe5,0x26,0x70,0xa, 0x12,0xbf,0xd2,0x28,0x58,0x75,0x4c,0x2c,0x80,0x53,0x30,0x14, +0x42,0x7e,0x73,0x39,0x0, 0xbe,0x71,0x2a,0x38,0x11,0xbc,0x7e,0x40,0xd, 0x7e,0x73, +0x39,0x2, 0xbe,0x71,0x2b,0x38,0x4, 0xbc,0x7f,0x50,0x1a,0x7e,0x73,0x39,0x1, 0xbe, +0x71,0x2a,0x38,0x2d,0xbc,0x7e,0x40,0x29,0x7e,0x73,0x39,0x3, 0xbe,0x71,0x2b,0x38, +0x20,0xbc,0x7f,0x40,0x1c,0x12,0xd0,0x4c,0x7c,0xb7,0x25,0x4c,0xf5,0x4c,0x75,0x59, +0x1, 0x80,0xe, 0x30,0xe, 0xb, 0x12,0xd0,0x4c,0x7c,0xa7,0xe5,0x4c,0x9c,0xba,0xf5, +0x4c,0x7d,0x18,0x1a,0x2, 0x1a,0x0, 0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f,0x10,0xe5, +0x4c,0xa, 0x1b,0x6d,0x0, 0x12,0x17,0x18,0x7a,0x1d,0x4d,0x7e,0x15,0x3b,0x1a,0x2, +0x1a,0x0, 0x7e,0x35,0x33,0x1a,0x26,0x1a,0x24,0x12,0x17,0x18,0xe5,0x5b,0xa, 0xfb, +0x6d,0xee,0xe5,0x5a,0xa, 0x1b,0x6d,0x0, 0x2f,0x7, 0x12,0x17,0x18,0x7f,0x1, 0x7a, +0xd, 0x51,0x7e,0x1d,0x4d,0xbf,0x10,0x8, 0x3, 0x75,0x32,0x2, 0x12,0x48,0xb3,0x50, +0x2, 0xa1,0x16,0xe5,0x43,0x60,0x2, 0xa1,0x16,0x12,0xd0,0x6e,0x68,0x2, 0x81,0x1c, +0x12,0xbf,0xd2,0x38,0x2, 0x81,0x1c,0xa, 0xe, 0xe5,0x2a,0xa, 0x1b,0x7d,0xd1,0x9d, +0xd0,0xbe,0xd4,0x0, 0x5, 0x48,0x2, 0x81,0x1c,0xa, 0x3f,0xe5,0x2b,0xa, 0xbb,0x7d, +0x2b,0x9d,0x23,0xbe,0x24,0x0, 0x5, 0x48,0x2, 0x81,0x1c,0x2d,0x3b,0x7e,0xd4,0x0, +0x2, 0x12,0xbf,0xca,0x3e,0x54,0x12,0xbf,0x97,0xb, 0x1a,0x30,0x7a,0x35,0x5f,0x7d, +0x30,0x2d,0x31,0x7d,0x2d,0x12,0x16,0xe6,0x7d,0xd3,0x3e,0xd4,0x12,0xbf,0xc0,0x7d, +0x54,0x2d,0x5d,0x12,0xbf,0x97,0xb, 0x1a,0x50,0x7a,0x55,0x61,0xe5,0x59,0xb4,0x1, +0x1c,0x7e,0x35,0x61,0x7e,0xd4,0x0, 0x3, 0x12,0xbf,0xca,0x2e,0x55,0x61,0x7a,0x55, +0x61,0x7e,0x35,0x5f,0x12,0xbf,0xca,0x2e,0x55,0x5f,0x7a,0x55,0x5f,0x74,0x2, 0xac, +0xbe,0x12,0xbf,0xad,0xb, 0x1a,0xd0,0xbe,0xd5,0x61,0x18,0x39,0x7e,0x3, 0x29,0x5b, +0x7e,0x10,0x2, 0xac,0x1, 0x7e,0x31,0x2a,0x74,0x2, 0xac,0x3b,0x2d,0x10,0x12,0x86, +0x81,0xb, 0x1a,0x30,0xbe,0x35,0x61,0x18,0x1c,0x74,0x2, 0xac,0xbf,0x12,0xbf,0x97, +0xb, 0x1a,0x30,0xbe,0x35,0x5f,0x18,0xd, 0x12,0xbf,0x91,0xb, 0x1a,0x30,0xbe,0x35, +0x5f,0x18,0x2, 0x80,0x44,0xa, 0x3f,0x9d,0xb3,0xbe,0xb4,0x0, 0x2, 0x58,0x12,0xbe, +0xd5,0x61,0x18,0xd, 0x12,0xbf,0x9e,0xb, 0x1a,0xd0,0xbe,0xd5,0x61,0x18,0x2, 0x80, +0x28,0xa, 0xbe,0xe5,0x2a,0xa, 0xdb,0x9d,0xdb,0xbe,0xd4,0x0, 0x2, 0x58,0x1d,0x74, +0x2, 0xac,0xbf,0x12,0xbf,0x97,0xb, 0x1a,0xd0,0xbe,0xd5,0x5f,0x18,0xe, 0x12,0xbf, +0x91,0xb, 0x1a,0xd0,0xbe,0xd5,0x5f,0x18,0x3, 0x75,0x32,0x2, 0x12,0xd0,0x6e,0x8, +0xd, 0xe5,0x32,0xb4,0x2, 0x8, 0x12,0xbf,0xb8,0x28,0x3, 0x75,0x32,0x0, 0x12,0xbf, +0xb8,0x38,0x2, 0x81,0xea,0xa, 0x2e,0xe5,0x2a,0xa, 0x3b,0x7d,0xd3,0x9d,0xd2,0xbe, +0xd4,0x0, 0x2, 0x48,0x58,0x2d,0x32,0x12,0xb6,0x4f,0x7d,0x13,0x3e,0x14,0x7e,0xa3, +0x29,0x5b,0x7e,0x10,0x2, 0xac,0x1a,0x2d,0x10,0x7e,0x1f,0x6, 0x44,0x7f,0x71,0x2d, +0xf1,0xb, 0x7a,0x40,0x7e,0x30,0x2, 0xac,0x3e,0x7d,0xd1,0x2d,0xd0,0x2d,0x3d,0xb, +0x1a,0xd0,0xbd,0x4d,0x58,0x27,0xe5,0x2a,0xa, 0x2b,0xa, 0x3e,0x2d,0x32,0x12,0xb6, +0x4f,0x7d,0xd3,0x3e,0xd4,0x74,0x2, 0xa4,0x2d,0xd5,0x12,0xbf,0xb1,0xb, 0x1a,0xb0, +0x12,0xbf,0x9e,0xb, 0x1a,0xd0,0xbd,0xbd,0x58,0x3, 0x75,0x32,0x0, 0xa, 0xdf,0xe5, +0x2b,0xa, 0x3b,0x7d,0x23,0x9d,0x2d,0xbe,0x24,0x0, 0x2, 0x48,0x3d,0x12,0xb6,0x4d, +0x7d,0xb3,0x3e,0xb4,0x7e,0xf, 0x6, 0x44,0x7f,0x10,0x2d,0x3b,0xb, 0x1a,0x30,0x74, +0x2, 0xac,0xbf,0x2d,0x15,0xb, 0xa, 0xb0,0xbd,0x3b,0x58,0x1e,0xe5,0x2b,0xa, 0x3b, +0x12,0xb6,0x4d,0x7d,0xd3,0x3e,0xd4,0x12,0xbf,0xb1,0xb, 0x1a,0xb0,0x12,0xbf,0x91, +0xb, 0x1a,0xd0,0xbd,0xbd,0x58,0x3, 0x75,0x32,0x0, 0x7e,0x73,0x2, 0xe0,0xbe,0x70, +0x2, 0x50,0x23,0xe5,0x24,0x7e,0x71,0x27,0x12,0x24,0x20,0x58,0x19,0xe5,0x26,0x7e, +0x71,0x25,0x12,0x24,0x20,0x58,0xf, 0x12,0xbf,0xb8,0x28,0xa, 0xe5,0x32,0xbe,0xb0, +0x1, 0x28,0x3, 0x75,0x32,0x0, 0x4c,0xdd,0x78,0x2, 0xe1,0xc, 0x12,0x48,0xb3,0x50, +0x2, 0xe1,0xc, 0xe5,0x43,0x60,0x2, 0xe1,0xc, 0x7e,0xb3,0x25,0x58,0xb4,0x2, 0x2, +0x80,0x2, 0xa1,0xed,0x7e,0xb3,0x25,0x59,0xb4,0x1, 0x2, 0x80,0x2, 0xa1,0xed,0x7e, +0x73,0x29,0x5d,0xa, 0xb7,0x1b,0xb4,0x7e,0x73,0x25,0x43,0xa, 0xd7,0xbd,0xdb,0x48, +0x2, 0xa1,0xed,0x7e,0x73,0x25,0x30,0xa, 0x27,0x7e,0x73,0x25,0x2f,0x12,0xbf,0xea, +0xf5,0x5c,0x12,0xd0,0x83,0x58,0x5b,0x85,0x5c,0x63,0x12,0xbf,0xc0,0x7e,0xa1,0x63, +0x74,0x2, 0xa4,0x2d,0x54,0x7e,0x1f,0x6, 0x44,0x7f,0x1, 0x2d,0x15,0x1b,0x15,0xb, +0xa, 0xb0,0x7e,0xa1,0x5c,0x74,0x2, 0xa4,0x7d,0xd5,0x2d,0xd4,0x2d,0x3d,0xb, 0x1a, +0xd0,0xbd,0xdb,0x8, 0x8, 0xe5,0x63,0xa, 0x5b,0x1b,0x54,0xf5,0x5c,0x12,0xbf,0xc0, +0x7e,0xa1,0x63,0x12,0xbf,0xaa,0x69,0xb1,0x0, 0x2, 0x12,0xbf,0xc0,0x7e,0xa1,0x5c, +0x12,0xbf,0xaa,0xb, 0x1a,0xd0,0xbd,0xdb,0x8, 0x8, 0xe5,0x63,0xa, 0x5b,0xb, 0x54, +0xf5,0x5c,0xe5,0x2a,0xbe,0xb1,0x5c,0x28,0x5, 0xbe,0xe1,0x5c,0x28,0x9, 0xe5,0x32, +0x70,0x1b,0x75,0x32,0x2, 0x80,0x16,0xbe,0xe1,0x5c,0x38,0x11,0xe5,0x2a,0xbe,0xb1, +0x5c,0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e,0xb3,0x25, +0x58,0xb4,0x1, 0x2, 0x80,0x2, 0xc1,0x8c,0x7e,0xb3,0x25,0x59,0xb4,0x2, 0x2, 0x80, +0x2, 0xc1,0x8c,0x7e,0x73,0x25,0x44,0xa, 0x27,0x7e,0x73,0x25,0x43,0x12,0xbf,0xea, +0xf5,0x5d,0x12,0xd0,0x83,0x58,0x4a,0x85,0x5d,0x64,0x7e,0x31,0x64,0x74,0x2, 0xac, +0x3b,0x7e,0x1f,0x6, 0x44,0x7f,0x21,0x2d,0x51,0x1b,0x55,0xb, 0x2a,0xd0,0x7e,0xa1, +0x5d,0x74,0x2, 0xa4,0x2d,0x35,0xb, 0x1a,0x0, 0xbd,0xd, 0x8, 0x8, 0xe5,0x64,0xa, +0x5b,0x1b,0x54,0xf5,0x5d,0x12,0x86,0x81,0x69,0xb1,0x0, 0x2, 0x7e,0xa1,0x5d,0x12, +0xbf,0x94,0xb, 0x1a,0xd0,0xbd,0xdb,0x8, 0x8, 0xe5,0x64,0xa, 0x5b,0xb, 0x54,0xf5, +0x5d,0xe5,0x2b,0xbe,0xb1,0x5d,0x28,0x5, 0xbe,0xf1,0x5d,0x28,0x9, 0xe5,0x32,0x70, +0x1b,0x75,0x32,0x2, 0x80,0x16,0xbe,0xf1,0x5d,0x38,0x11,0xe5,0x2b,0xbe,0xb1,0x5d, +0x28,0xa, 0xe5,0x32,0xbe,0xb0,0x1, 0x28,0x3, 0x75,0x32,0x0, 0x7e,0x73,0x27,0x58, +0xa5,0xbf,0x2, 0x21,0x7e,0x63,0x2, 0xe0,0xbe,0x60,0x2, 0x50,0x18,0x7e,0x63,0x28, +0xf5,0xbe,0x60,0x1, 0x28,0xf, 0xbe,0x73,0x25,0x58,0x28,0x6, 0xbe,0x73,0x25,0x59, +0x38,0x3, 0x75,0x32,0x0, 0x7e,0xb3,0x25,0x57,0xb4,0x1, 0x50,0x7e,0xb3,0x2, 0xe0, +0x70,0x40,0x12,0xbf,0xb8,0x28,0x3b,0xe5,0x24,0x7e,0x71,0x27,0x12,0xbf,0xda,0x58, +0xc, 0xe5,0x26,0x7e,0x71,0x25,0x12,0xbf,0xda,0x58,0x2, 0x80,0x20,0x7e,0xb3,0x28, +0xf5,0xb4,0x2, 0x28,0x7e,0x73,0x27,0x58,0xbe,0x70,0x5, 0x50,0x1f,0x7e,0x73,0x27, +0x59,0xbe,0x70,0x1, 0x50,0x16,0xe5,0x32,0xbe,0xb0,0x1, 0x28,0xf, 0x75,0x32,0x0, +0x80,0xa, 0x7e,0xb3,0x28,0xf5,0xb4,0x1, 0x3, 0x75,0x32,0x2, 0xe5,0x32,0xbe,0xb0, +0x0, 0x28,0x64,0xe5,0x32,0xa, 0xdb,0x2e,0xd4,0x2, 0xdc,0x7e,0xd9,0xb0,0x4, 0x7a, +0xd9,0xb0,0xe5,0x2d,0xa, 0xdb,0x9, 0xad,0x2, 0xe2,0x4c,0xaa,0x78,0xc, 0xa, 0xbc, +0x9, 0xbb,0x2, 0xe2,0x19,0xbd,0x2, 0xe2,0x80,0x3d,0xa, 0xbc,0x9, 0xbb,0x2, 0xe2, +0xf5,0x5e,0xbc,0xba,0x28,0x3, 0x7a,0xa1,0x5e,0x75,0x2e,0x0, 0x80,0x22,0x9, 0x7d, +0x2, 0xe2,0xe5,0x2e,0xa, 0xbb,0x9, 0x6b,0x2, 0xe2,0xbc,0x67,0x68,0xa, 0xa, 0x2c, +0x9, 0x72,0x2, 0xe2,0xbc,0x67,0x78,0x6, 0xe5,0x5e,0x19,0xbb,0x2, 0xe2,0x5, 0x2e, +0xe5,0x2c,0xbe,0xb1,0x2e,0x38,0xd7,0x5, 0x2d,0xe5,0x2c,0xbe,0xb1,0x2d,0x28,0x3, +0x2, 0xb7,0x18,0xb, 0xc0,0xe5,0x2c,0xbc,0xbc,0x28,0x3, 0x2, 0xb6,0xe1,0xda,0x3b, +0x22,0x7e,0xa1,0x2b,0x74,0x2, 0xa4,0x7e,0x1f,0x6, 0x44,0x2d,0x35,0x22,0x7e,0x83, +0x29,0x5b,0x7e,0x90,0x2, 0xac,0x89,0x7e,0xa1,0x2a,0x74,0x2, 0xa4,0x7d,0xd5,0x2d, +0xd4,0x7e,0x1f,0x6, 0x44,0x2d,0x3d,0x22,0x7e,0x73,0x28,0xf5,0xbe,0x70,0x1, 0x22, +0x7e,0x83,0x29,0x5b,0x7e,0x90,0x2, 0xac,0x89,0x22,0x7d,0x2d,0x12,0x16,0xe6,0x7d, +0x53,0x22,0x7e,0x73,0x2, 0xe0,0xbe,0x70,0x5, 0x22,0x12,0x21,0x50,0xbe,0x34,0xff, +0x38,0x22,0x7c,0x7f,0x12,0x21,0x50,0x9d,0x93,0x22,0xa, 0x37,0x7d,0x53,0x2d,0x52, +0xe, 0x54,0x22,0x7e,0x71,0x2b,0x12,0x21,0x50,0x9d,0x93,0x22,0x6c,0xaa,0x12,0xc6, +0x2d,0x29,0x81,0x0, 0x5, 0x7c,0x98,0x5e,0x90,0x1, 0x3e,0x90,0x7f,0x1, 0x2e,0x14, +0x0, 0x5, 0x7c,0xb8,0x54,0xfd,0x4c,0xb9,0x7a,0xb, 0xb0,0x29,0xb1,0x0, 0x5, 0x30, +0xe0,0x16,0x30,0xe2,0x13,0xc4,0x23,0x54,0x1f,0xb4,0x1, 0xc, 0x7f,0x1, 0xb, 0x16, +0x7e,0xb, 0xb0,0x1e,0xb0,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xbf,0x22, +0x7e,0x30,0x64,0x7e,0x20,0x64,0x6c,0x11,0x80,0x4a,0xa, 0x31,0xb, 0x34,0x7c,0x7, +0x80,0x38,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x25,0xce,0x12,0xc0,0xb5,0x9, 0xb3, +0x25,0xce,0x12,0x47,0xda,0x7c,0x97,0x7e,0x70,0x2, 0xac,0x70,0x9, 0xb3,0x25,0xcf, +0x12,0xc0,0xb5,0x9, 0xb3,0x25,0xcf,0x12,0x47,0xda,0x7c,0x87,0xbc,0x39,0x28,0x2, +0x7c,0x39,0xbc,0x28,0x28,0x2, 0x7c,0x28,0xb, 0x0, 0x7e,0xb3,0x27,0x58,0xbc,0xb0, +0x38,0xc0,0xb, 0x10,0x7e,0xb3,0x27,0x58,0xbc,0xb1,0x38,0xae,0xa5,0xbb,0x64,0x2, +0x6c,0x33,0xa5,0xba,0x64,0x2, 0x6c,0x22,0xbc,0x23,0x28,0x4, 0x7c,0xa2,0x80,0x2, +0x7c,0xa3,0x7c,0xba,0x22,0xa, 0x2b,0x7e,0x70,0x2, 0xac,0x71,0x22,0xca,0x3b,0x7f, +0x40,0x7e,0xe3,0x27,0x58,0x6c,0xdd,0x7e,0xc0,0x1, 0x80,0x1a,0xa, 0x3d,0x2d,0x39, +0x7d,0x28,0x7e,0x1b,0x60,0xa, 0x2c,0x7f,0x4, 0x2d,0x12,0x7e,0xb, 0x70,0xbc,0x76, +0x40,0x2, 0x7c,0xdc,0xb, 0xc0,0xbc,0xec,0x38,0xe2,0xa, 0x3d,0x2d,0x39,0x7d,0x28, +0x7e,0x1b,0xd0,0x6c,0xff,0x7e,0xc0,0x1, 0x41,0x6c,0x75,0x31,0x0, 0x6d,0x33,0x7a, +0x35,0x32,0x7a,0x35,0x34,0x9f,0x11,0x7a,0x1d,0x25,0x7a,0x1d,0x29,0x7e,0x18,0x1e, +0x80,0x7a,0x1d,0x2d,0x74,0xff,0x7e,0x34,0x1e,0x81,0x7e,0x24,0x0, 0x0, 0x7a,0x1b, +0xb0,0x7e,0x1d,0x2d,0x7a,0x1b,0xb0,0xe4,0x7e,0x1d,0x2d,0x39,0xb1,0x0, 0x3, 0x7e, +0x1d,0x2d,0x39,0xb1,0x0, 0x2, 0x7e,0x1d,0x2d,0x12,0xc4,0x70,0x44,0x1, 0x7a,0x1b, +0xb0,0x75,0x24,0x0, 0x21,0xdc,0x7e,0xa1,0x24,0x74,0x2, 0xa4,0x9, 0x95,0x25,0xce, +0x9, 0x85,0x25,0xcf,0xe5,0x24,0xa, 0x5b,0x7f,0x14,0x2d,0x35,0x7e,0x1b,0x70,0xbc, +0x7c,0x78,0x77,0x5, 0x31,0x12,0x21,0x4c,0x7d,0x53,0x2e,0x55,0x32,0x7a,0x55,0x32, +0x12,0x21,0x4c,0x12,0x8f,0xd5,0xa, 0x39,0x6d,0x22,0x12,0x17,0x18,0x12,0xc2,0x92, +0x12,0x21,0x4c,0x12,0x8f,0xd5,0xa, 0x38,0x6d,0x22,0x12,0x17,0x18,0x7f,0x1, 0x12, +0xc2,0x89,0x12,0x21,0x4c,0xbe,0x35,0x34,0x8, 0x6, 0x12,0x21,0x4c,0x7a,0x35,0x34, +0x7e,0x1d,0x2d,0x7e,0x1b,0x30,0xbc,0x39,0x28,0x3, 0x7a,0x1b,0x90,0x7e,0x1d,0x2d, +0x29,0x31,0x0, 0x2, 0xbc,0x39,0x50,0x4, 0x39,0x91,0x0, 0x2, 0x7e,0x1d,0x2d,0x29, +0x31,0x0, 0x1, 0xbc,0x38,0x28,0x4, 0x39,0x81,0x0, 0x1, 0x7e,0x1d,0x2d,0x29,0x31, +0x0, 0x3, 0xbc,0x38,0x50,0x4, 0x39,0x81,0x0, 0x3, 0x5, 0x24,0xbe,0xe1,0x24,0x28, +0x2, 0x21,0x46,0xe5,0x31,0xbe,0xb0,0x0, 0x38,0x2, 0x41,0x6a,0x7e,0xd, 0x2d,0x12, +0xc2,0x9d,0x7e,0xf5,0x32,0x12,0x7f,0x2d,0x7e,0x8, 0x0, 0x2, 0x12,0x17,0x85,0x12, +0xc2,0x92,0x12,0xc2,0x89,0x12,0xc2,0x7a,0x7e,0x1d,0x25,0x12,0x17,0x85,0x7a,0x1d, +0x25,0x12,0xc2,0x7a,0x7e,0x1d,0x29,0x12,0x17,0x85,0x7a,0x1d,0x29,0x7e,0x2d,0x25, +0x12,0xc2,0x81,0x19,0xa3,0x3, 0x2, 0x7e,0x2d,0x29,0x12,0xc2,0x81,0x19,0xa3,0x3, +0x3, 0x7e,0x37,0x27,0x5e,0xbe,0x35,0x34,0x78,0xe, 0x7e,0x1d,0x25,0x7a,0x73,0x27, +0x60,0x7e,0x1d,0x29,0x7a,0x73,0x27,0x61,0x7e,0x37,0x3, 0x0, 0x4d,0x33,0x68,0x18, +0x7e,0x2d,0x25,0x7e,0x1d,0x29,0x12,0x21,0x50,0x7e,0x25,0x34,0x7e,0x70,0x2, 0xac, +0x7f,0x2e,0x37,0x3, 0x0, 0x1b,0x38,0x20,0xb, 0xf0,0xb, 0xc0,0xbc,0xdc,0x40,0x2, +0x1, 0xfa,0x12,0xbf,0xfc,0x7c,0xbf,0xda,0x3b,0x22,0x7d,0x1f,0x1a,0x2, 0x1a,0x0, +0x22,0x7c,0xab,0x7e,0x70,0x2, 0xac,0x7f,0x22,0x7e,0x1d,0x29,0x2f,0x10,0x7a,0x1d, +0x29,0x22,0x7f,0x1, 0x7e,0x1d,0x25,0x2f,0x10,0x7a,0x1d,0x25,0x22,0xca,0x79,0x7f, +0x70,0x7e,0xb4,0xff,0xff,0x6c,0xee,0xc2,0x1, 0xc2,0x2, 0x29,0x67,0x0, 0x2, 0x7e, +0x7b,0x70,0xbc,0x76,0x78,0xe, 0x29,0x67,0x0, 0x3, 0x29,0x77,0x0, 0x1, 0xbc,0x76, +0x78,0x2, 0xd2,0x2, 0x6c,0xff,0x12,0xc4,0x78,0x6d,0xaa,0x29,0xb6,0x0, 0x5, 0x20, +0xe1,0x2, 0x61,0x57,0x7f,0x6, 0x7e,0x7b,0xb0,0x12,0xc4,0x85,0x50,0x2d,0x7f,0x6, +0x29,0xb7,0x0, 0x2, 0x12,0xc4,0x85,0x50,0x22,0x7f,0x6, 0x29,0xb7,0x0, 0x1, 0x6c, +0x77,0x12,0xc4,0x8e,0x50,0x15,0x7f,0x6, 0x29,0xb7,0x0, 0x3, 0x6c,0x77,0x12,0xc4, +0x8e,0x50,0x8, 0x7c,0xef,0xd2,0x1, 0x6d,0xbb,0x80,0x55,0x7e,0x6b,0x70,0xa, 0x27, +0x7e,0x7b,0x70,0x12,0xc4,0x67,0x2d,0xa3,0x29,0x76,0x0, 0x2, 0xa, 0x27,0x29,0x77, +0x0, 0x2, 0x12,0xc4,0x67,0x2d,0xa3,0x29,0x76,0x0, 0x1, 0xa, 0x27,0x29,0x77,0x0, +0x1, 0x12,0xc4,0x67,0x2d,0xa3,0x29,0x76,0x0, 0x3, 0xa, 0x27,0x29,0x77,0x0, 0x3, +0x12,0xc4,0x67,0x2d,0xa3,0xbd,0xab,0x50,0x4, 0x7d,0xba,0x7c,0xef,0xbe,0xa4,0x0, +0x4, 0x38,0x4, 0xd2,0x1, 0x80,0x9, 0xb, 0xf0,0xbe,0xf0,0x1e,0x50,0x2, 0x41,0xc6, +0x20,0x1, 0xb, 0x20,0x2, 0x8, 0xbe,0xb4,0x0, 0x8, 0x50,0x2, 0xd2,0x1, 0x20,0x1, +0x2, 0x81,0x18,0x74,0x6, 0xac,0xbe,0x12,0xc4,0x7c,0x29,0x76,0x0, 0x5, 0x7c,0xb7, +0xc4,0x23,0x54,0x1f,0xbe,0xb0,0x1f,0x50,0x16,0x7f,0x6, 0x2e,0x14,0x0, 0x5, 0x7c, +0x67,0x2e,0x60,0x8, 0x5e,0x60,0xf8,0x5e,0x70,0x7, 0x4c,0x76,0x7a,0xb, 0x70,0x20, +0x2, 0x11,0x29,0xb6,0x0, 0x4, 0xbe,0xb0,0xfa,0x50,0x8, 0x7f,0x16,0xb, 0x36,0x4, +0x7a,0x1b,0xb0,0x29,0x67,0x0, 0x3, 0x29,0x76,0x0, 0x3, 0xbc,0x76,0x28,0x6, 0x29, +0x76,0x0, 0x3, 0x80,0x4, 0x29,0x77,0x0, 0x3, 0x39,0x76,0x0, 0x3, 0x29,0x67,0x0, +0x2, 0x29,0x76,0x0, 0x2, 0xbc,0x76,0x28,0x6, 0x29,0x76,0x0, 0x2, 0x80,0x4, 0x29, +0x77,0x0, 0x2, 0x39,0x76,0x0, 0x2, 0x29,0x67,0x0, 0x1, 0x29,0x76,0x0, 0x1, 0xbc, +0x76,0x50,0x6, 0x29,0x76,0x0, 0x1, 0x80,0x4, 0x29,0x77,0x0, 0x1, 0x39,0x76,0x0, +0x1, 0x7e,0x7b,0x60,0x7e,0x6b,0x70,0xbc,0x76,0x50,0x5, 0x7e,0x6b,0x70,0x80,0x3, +0x7e,0x7b,0x70,0x7a,0x6b,0x70,0x80,0x31,0x6c,0xff,0x74,0x6, 0xac,0xbf,0x9, 0xb5, +0x3, 0x43,0x30,0xe1,0x7, 0xb, 0xf0,0xbe,0xf0,0x1e,0x40,0xee,0xbe,0xf0,0x1e,0x50, +0x33,0x74,0x1, 0x39,0xb7,0x0, 0x4, 0x12,0xc4,0x78,0x7e,0x34,0x0, 0x6, 0xca,0x39, +0x7f,0x17,0x7f,0x6, 0x12,0x1a,0xb, 0x1b,0xfd,0x12,0xc4,0x6e,0x44,0x1, 0x7a,0x1b, +0xb0,0x12,0xc4,0x6e,0x44,0x2, 0x7a,0x1b,0xb0,0x30,0x2, 0x8, 0x12,0xc4,0x6e,0x44, +0x4, 0x7a,0x1b,0xb0,0xda,0x79,0x22,0xa, 0x37,0x9d,0x32,0x2, 0x1a,0x62,0x7f,0x16, +0x2e,0x34,0x0, 0x5, 0x7e,0x1b,0xb0,0x22,0x74,0x6, 0xac,0xbf,0x7d,0xd5,0x2e,0xd4, +0x3, 0x3e,0x6d,0xcc,0x22,0x7e,0x70,0x1, 0x2, 0xc4,0x8e,0x7e,0x70,0x1, 0x7c,0x87, +0x7c,0x9b,0x29,0xa0,0x0, 0x3, 0x29,0x60,0x0, 0x1, 0x7e,0x70,0x1, 0xbe,0x80,0x1, +0x78,0x7, 0x29,0xa0,0x0, 0x2, 0x7e,0xb, 0x60,0xa, 0x7, 0xa, 0x29,0x2d,0x2, 0xa, +0x16,0xbd,0x1, 0x48,0xc, 0xa, 0x17,0xa, 0x3a,0x2d,0x31,0xbd,0x23,0x18,0x2, 0xd3, +0x22,0xc3,0x22,0xca,0x3b,0x12,0x7f,0xac,0x75,0x65,0x0, 0x7e,0xa1,0x65,0x74,0x6, +0xa4,0x12,0xc5,0x6e,0x30,0xe1,0x2e,0x7f,0x7, 0x7c,0xbc,0x12,0xc4,0x85,0x50,0x25, +0x7f,0x7, 0x7c,0xbe,0x12,0xc4,0x8b,0x50,0x1c,0x7f,0x7, 0x7c,0xbd,0x6c,0x77,0x12, +0xc4,0x8e,0x50,0x11,0x7f,0x7, 0x7c,0xbf,0x6c,0x77,0x12,0xc4,0x8e,0x50,0x6, 0x29, +0xb7,0x0, 0x4, 0x80,0xa, 0x5, 0x65,0xe5,0x65,0xbe,0xb0,0x1e,0x40,0xbd,0xe4,0xda, +0x3b,0x22,0xca,0x3b,0x7e,0xe3,0x27,0x58,0x6c,0xdd,0x6c,0xff,0x74,0x6, 0xac,0xbd, +0x12,0xc5,0x6e,0x30,0xe0,0x3d,0x6c,0xcc,0x80,0x2d,0x7e,0x70,0x2, 0xac,0x7c,0x9, +0xb3,0x25,0xce,0x7a,0xb3,0x1e,0x80,0x9, 0xa3,0x25,0xcf,0x7a,0xa3,0x1e,0x81,0x7f, +0x7, 0x12,0xc4,0x8b,0x50,0xf, 0x7f,0x7, 0x7e,0xb3,0x1e,0x81,0x6c,0x77,0x12,0xc4, +0x8e,0x50,0x2, 0xb, 0xf0,0xb, 0xc0,0xbc,0xec,0x38,0xcf,0xbe,0xf0,0x2, 0x40,0x3, +0xd3,0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0x1e,0x40,0xb0,0xc3,0xda,0x3b,0x22,0x7d,0xf5, +0x2e,0xf4,0x3, 0x3e,0x6d,0xee,0x29,0xb7,0x0, 0x5, 0x22,0x7c,0x9b,0x7f,0x71,0x7f, +0x60,0x7e,0x34,0x1b,0xf9,0x7e,0x24,0x0, 0xff,0x7e,0x14,0x1e,0x80,0x74,0x2a,0x12, +0x17,0xda,0x7e,0x58,0x1e,0x80,0x7c,0xb9,0x7e,0x71,0x65,0x12,0x21,0x50,0x7d,0x43, +0xe5,0x66,0x7e,0x71,0x67,0x12,0x21,0x50,0x2d,0x34,0xe, 0x34,0x7f,0x5, 0x7e,0x50, +0x7, 0xb, 0xa, 0x50,0xbd,0x53,0x58,0x10,0x69,0x30,0x0, 0x2, 0x1b,0x6a,0x30,0x69, +0x30,0x0, 0x4, 0x1b,0x7a,0x30,0x80,0x8, 0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78,0xe1, +0x12,0xbf,0xd2,0x28,0x2b,0xb, 0x6a,0x20,0x7e,0x34,0x0, 0xd, 0xad,0x32,0x7e,0x24, +0x0, 0x10,0x12,0x16,0xe6,0x1b,0x6a,0x30,0xb, 0x7a,0x30,0x1a,0x26,0x1a,0x24,0x7e, +0x14,0x0, 0xd, 0x12,0x17,0x29,0x7e,0x8, 0x0, 0x10,0x12,0x17,0x85,0x1b,0x7a,0x30, +0x22,0x6c,0xaa,0x12,0xc6,0x2d,0x12,0xc6,0x23,0x54,0xfe,0x12,0xc6,0x20,0x54,0x7, +0x12,0xc6,0x20,0x54,0xfb,0x7a,0xb, 0xb0,0xb, 0xa0,0xbe,0xa0,0x1e,0x40,0xe4,0x22, +0x7a,0xb, 0xb0,0x7f,0x1, 0x2e,0x14,0x0, 0x5, 0x7e,0xb, 0xb0,0x22,0x7e,0x70,0x6, +0xac,0x7a,0x2e,0x34,0x3, 0x3e,0x6d,0x22,0x22,0x7e,0x8, 0x3, 0x3e,0x7e,0x34,0x0, +0xb4,0xe4,0x2, 0x1a,0x30,0x6c,0xaa,0x80,0x1c,0x7e,0x50,0x2, 0xac,0x5a,0x49,0x12, +0x12,0xd6,0x49,0x32,0x12,0x9e,0xbd,0x31,0x28,0x9, 0x2e,0x24,0x12,0x9e,0x9d,0x31, +0x1b,0x28,0x30,0xb, 0xa0,0x7e,0xb3,0x29,0x5b,0xbc,0xba,0x38,0xdc,0x22,0x7c,0xab, +0x12,0xc6,0x7d,0xd2,0x19,0x7c,0xba,0x12,0x86,0x88,0xc2,0x19,0x22,0xa9,0xd1,0xcb, +0x74,0x1, 0x2, 0x0, 0xe, 0x12,0xc6,0x7d,0x7e,0x34,0xc, 0xd8,0x7e,0xb3,0x29,0x5a, +0x12,0xc6,0xbe,0x12,0xc6,0xa1,0x7a,0x37,0x3c,0x69,0x74,0x1, 0x7a,0xb3,0x15,0xa1, +0x22,0x6d,0x33,0x90,0x60,0x91,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xcd,0x14, +0x90,0x60,0x92,0xe4,0x93,0xbe,0xb0,0x0, 0x28,0x3, 0x2, 0xc6,0xf2,0x22,0x7a,0xb3, +0x24,0x2, 0x7e,0x53,0x29,0x5b,0x7a,0x53,0x24,0x3, 0x7a,0x37,0x24,0xa, 0xe4,0x7a, +0xb3,0x24,0x4, 0x7a,0xb3,0x24,0x5, 0x7e,0x34,0x40,0x0, 0x7a,0x37,0x24,0x6, 0x7e, +0x34,0x0, 0x20,0x12,0xc6,0xe9,0x2, 0xd, 0x7, 0x7a,0x37,0x24,0xc, 0x7e,0x8, 0x24, +0x2, 0x22,0xca,0xf8,0x6d,0xee,0x7d,0xfe,0x7e,0x83,0x29,0x5b,0xa, 0xd8,0x90,0x60, +0x94,0xe4,0x93,0xb4,0xff,0x2f,0x7e,0x8, 0x12,0x9e,0x6c,0xaa,0x80,0x18,0x7e,0x70, +0x2, 0xac,0x7a,0x49,0x23,0x13,0xe, 0x7f,0x50,0x2d,0xb3,0xb, 0x5a,0xc0,0x9d,0xc2, +0x59,0xc3,0x12,0xd6,0xb, 0xa0,0xbc,0x8a,0x38,0xe4,0x90,0x60,0x92,0xe4,0x93,0x7c, +0x9b,0x6d,0xdd,0x80,0x11,0x7e,0x8, 0x13,0xe, 0x90,0x60,0x92,0xe4,0x93,0xa, 0xcb, +0x1b,0xc4,0x7d,0x3c,0x7c,0x97,0x6c,0xff,0x80,0x38,0x6c,0xaa,0x80,0x28,0xa, 0x3a, +0x7d,0x23,0x2d,0x2e,0x3e,0x24,0x49,0xc2,0x13,0xe, 0x2d,0x3d,0x3e,0x34,0x2d,0x31, +0x7d,0x20,0xb, 0x1a,0xb0,0x7d,0x3c,0x9d,0x3b,0x12,0x1a,0x62,0x7d,0xa3,0xbd,0xfa, +0x58,0x2, 0x7d,0xfa,0xb, 0xa0,0xbc,0x8a,0x38,0xd4,0xa, 0xc8,0x2d,0xec,0x2d,0xdc, +0xb, 0xf0,0xbc,0x9f,0x38,0xc4,0x7d,0x3f,0xda,0xf8,0x22,0xca,0xf8,0x7e,0xd4,0x28, +0x90,0x6c,0xff,0x12,0xd1,0x0, 0xb4,0x1, 0x16,0x9, 0x7c,0x0, 0x50,0xbe,0x70,0x37, +0x50,0xd, 0xbe,0x70,0x0, 0x28,0x8, 0x74,0x3, 0xa, 0xcf,0x19,0xbc,0x29,0x0, 0xa, +0xcf,0x9, 0x7c,0x29,0x0, 0xbe,0x70,0x0, 0x28,0x44,0x12,0xa7,0xf1,0x7a,0xb3,0x32, +0xce,0x7e,0xc4,0x0, 0x9, 0xca,0xc9,0x7e,0x70,0x63,0xac,0x7f,0x2e,0x34,0x2e,0x87, +0x6d,0x22,0x7e,0x30,0x9, 0xac,0x3f,0x2e,0x14,0x27,0xdc,0x6d,0x0, 0x12,0x1a,0xb, +0x1b,0xfd,0xa, 0xcf,0x9, 0xac,0x29,0x0, 0xbe,0xa0,0x3, 0x78,0x3, 0xe4,0x80,0xb, +0xbe,0xa0,0x1, 0x78,0x4, 0x74,0x1, 0x80,0x2, 0x74,0x2, 0x12,0xa7,0x9b,0xb, 0xf0, +0xbe,0xf0,0xa, 0x40,0x8e,0xda,0xf8,0x22,0x7e,0x34,0x28,0x90,0x6c,0xaa,0xa, 0x2a, +0x2d,0x23,0x7e,0x29,0xb0,0xb4,0x3, 0x2c,0x7e,0x30,0xff,0x7e,0x50,0x5, 0xac,0x5a, +0x19,0x32,0x32,0xb, 0xe4,0x19,0xb2,0x32,0xc, 0x19,0xb2,0x32,0xd, 0x74,0x3, 0x19, +0xb2,0x32,0xe, 0xe4,0x19,0xb2,0x32,0xf, 0x12,0xc8,0x4c,0x28,0x4, 0x19,0xb2,0x32, +0xe, 0x12,0xc8,0x54,0xb, 0xa0,0xbe,0xa0,0xa, 0x40,0xc3,0x22,0x7e,0xb3,0x3a,0xb3, +0xbe,0xb0,0x0, 0x22,0x9, 0xb2,0x32,0xe, 0x7a,0xb3,0x3a,0xb4,0x22,0xca,0x78,0xa9, +0x31,0xe5,0x6, 0xa9,0xd5,0xea,0xa9,0xc5,0xea,0xa9,0x30,0xe5,0x19,0xa9,0xd0,0x9e, +0xa9,0xd4,0x9e,0x5, 0x6a,0x7e,0x73,0x3c,0x8e,0xbe,0x71,0x6a,0x38,0x2, 0xd2,0x1a, +0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9,0x34,0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9, +0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9,0x33,0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5, +0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5,0x3, 0xa9,0xc6,0xcd,0xda,0x78,0x32,0xc2,0x9a, +0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22,0x7e,0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff, +0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50,0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e, +0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79,0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e, +0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79,0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e, +0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79,0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22, +0xa9,0xd5,0xcb,0x74,0x10,0x12,0x0, 0x46,0x7c,0x7b,0x12,0x3a,0x72,0x30,0xe7,0x3, +0x7e,0x70,0x2, 0xd2,0xcd,0x7e,0x24,0x0, 0xef,0x7e,0xf, 0x3c,0x53,0x79,0x20,0x0, +0x84,0x7e,0x24,0x20,0x5f,0x7e,0xf, 0x3c,0x53,0x79,0x20,0x0, 0x82,0x7e,0x24,0x41, +0x0, 0x7e,0xf, 0x3c,0x53,0x79,0x20,0x0, 0x90,0x7c,0x67,0x6c,0x77,0x2e,0x34,0x0, +0xc1,0x7e,0xf, 0x3c,0x53,0x79,0x30,0x0, 0x86,0x7e,0x34,0x29,0x90,0x7e,0xf, 0x3c, +0x53,0x79,0x30,0x0, 0x8a,0x7e,0x34,0x6a,0xd1,0x7e,0xf, 0x3c,0x53,0x79,0x30,0x0, +0x8c,0x7e,0x34,0x3, 0x61,0x7e,0xf, 0x3c,0x53,0x79,0x30,0x0, 0x8e,0x22,0xa9,0xc6, +0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2,0xeb,0xa9,0xd2,0xac,0xa9, +0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99,0xd2,0x9c,0xa9,0xd6,0xdf, +0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b,0x0, 0xd2,0x8e,0xd2,0xab, +0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75,0xf8,0x0, 0xa9,0xd0,0xb7, +0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2,0xf8,0xa9,0xc1,0xb7,0xc2, +0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe,0x22,0x75,0xe7,0x6b,0x2, +0xc9,0xd2,0xe4,0x7e,0x34,0xd7,0xfc,0x7e,0x24,0x0, 0xff,0x7a,0x1b,0xb0,0x7e,0x34, +0xd7,0xfd,0x7a,0x1b,0xb0,0x75,0xe9,0xff,0x22,0xa2,0x0, 0xa9,0x97,0xc1,0xa2,0x0, +0xa9,0x97,0xc2,0x22,0x7e,0x37,0x3c,0x8c,0xb, 0x34,0x7a,0x37,0x3c,0x8c,0xbe,0x34, +0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3c,0x8c,0x22,0x6d,0x22,0x80, +0x13,0x75,0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0, +0xb, 0x14,0xb, 0x24,0xbd,0x32,0x38,0xe9,0x22,0x7c,0xa6,0x7c,0x37,0x7c,0x2b,0xe4, +0x6c,0x11,0x80,0x46,0xbc,0xa1,0x68,0x40,0x1a,0x41,0x3e,0x44,0x9, 0x4, 0x25,0xcf, +0xa, 0x20,0xa, 0x33,0x9d,0x32,0x12,0x1a,0x62,0x7c,0x7, 0x1a,0x41,0x3e,0x44,0x9, +0x74,0x25,0xce,0xa, 0x27,0xa, 0x32,0x9d,0x32,0x12,0x1a,0x62,0x7c,0x97,0xbe,0x90, +0x1, 0x18,0x8, 0xbe,0x0, 0x1, 0x18,0x3, 0x74,0x1, 0x22,0xbe,0x90,0x2, 0x18,0x8, +0xbe,0x0, 0x2, 0x18,0x3, 0x74,0x2, 0x22,0xb, 0x10,0x7e,0x83,0x27,0x58,0xbc,0x81, +0x18,0xb2,0x22,0xca,0x79,0x7c,0xfb,0x7e,0x8, 0x1e,0x44,0x12,0x67,0xcf,0x7e,0xa3, +0x29,0x60,0x7e,0x63,0x29,0x61,0x6c,0xee,0x80,0x1e,0xa, 0x2e,0x9, 0x72,0x29,0xc9, +0xbe,0x70,0x1c,0x50,0x11,0xa, 0x27,0x12,0x27,0xfe,0x7c,0x7b,0x7e,0xb3,0x29,0xe8, +0xa, 0x27,0x19,0xb2,0x1e,0x44,0xb, 0xe0,0xbc,0x6e,0x38,0xde,0x6c,0xee,0x80,0x17, +0xa, 0x3e,0x9, 0x73,0x29,0xa6,0xbe,0x70,0x23,0x50,0xa, 0x7e,0x63,0x29,0xe8,0xa, +0x27,0x19,0x62,0x1e,0x60,0xb, 0xe0,0xbc,0xae,0x38,0xe5,0x6c,0xee,0x7e,0x30,0xe, +0xac,0x3e,0x2e,0x14,0x1e,0x44,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x11,0xf8,0xb, +0xe0,0xbe,0xe0,0x5, 0x40,0xe7,0xda,0x79,0x22,0x7c,0xab,0x9f,0x11,0x30,0x0, 0x22, +0x6c,0x99,0x80,0x1a,0xa, 0xf9,0x2d,0xf1,0x7d,0xe0,0x7e,0x7b,0xb0,0x7e,0x78,0x0, +0x1, 0x60,0x5, 0x2f,0x77,0x14,0x78,0xfb,0x4d,0x3f,0x4d,0x2e,0xb, 0x90,0xbc,0xa9, +0x38,0xe2,0x22,0xca,0xf8,0x90,0x60,0x51,0xe4,0x93,0x7c,0xfb,0x7e,0x8, 0x1e,0x44, +0x12,0xcb,0xaf,0x7e,0x8, 0x1e,0x4c,0x12,0xcb,0xb7,0xd2,0x0, 0x7e,0x8, 0x29,0xc9, +0x7c,0xbf,0x12,0xca,0xf9,0x7e,0x8, 0x1e,0x44,0x7a,0xf, 0x1e,0x68,0x7f,0x1, 0x7a, +0x17,0x1e,0x6c,0x7d,0x32,0x7a,0x37,0x1e,0x6e,0x7e,0x18,0x1e,0x4c,0x7a,0x1f,0x1e, +0x74,0x6c,0x77,0x80,0xe, 0x12,0xcb,0xff,0x50,0x7, 0x12,0xcb,0xf6,0x19,0x51,0x1e, +0x4c,0xb, 0x70,0xbc,0xf7,0x38,0xee,0x12,0xcb,0x9c,0xe4,0x12,0xcb,0xa4,0xe4,0x12, +0xc, 0x9b,0x6d,0x33,0x7a,0x37,0x1e,0x6c,0x7a,0x37,0x1e,0x6e,0x12,0xcb,0x9c,0x74, +0x1, 0x12,0xcb,0xa4,0x74,0x1, 0x12,0xc, 0x9b,0xda,0xf8,0x22,0xa9,0xc6,0xea,0x7e, +0x8, 0x1e,0x68,0x22,0x12,0xc, 0x9b,0xa9,0xd6,0xea,0x7e,0x8, 0x1e,0x68,0x22,0x7e, +0x34,0x0, 0x8, 0xe4,0x2, 0x1a,0x30,0x7e,0x34,0x0, 0x1c,0x74,0x3f,0x2, 0x1a,0x30, +0x7e,0x8, 0x1e,0x44,0x12,0xcb,0xb7,0x6c,0x77,0x80,0xe, 0x12,0xcb,0xff,0x50,0x7, +0x12,0xcb,0xf6,0x19,0x51,0x1e,0x44,0xb, 0x70,0x7e,0x53,0x29,0x5b,0xbc,0x57,0x38, +0xea,0xa9,0xc6,0xea,0x7e,0x8, 0x1e,0x44,0xe4,0x12,0x11,0x38,0xa9,0xd6,0xea,0x7e, +0x8, 0x1e,0x44,0x2, 0x11,0x38,0xa, 0x27,0x9, 0x52,0x2a,0x31,0xa, 0x16,0x22,0xa, +0x27,0x9, 0x62,0x29,0xc9,0xbe,0x60,0x1c,0x22,0x7c,0x57,0x7c,0xab,0x6c,0x77,0x80, +0x50,0xa, 0x47,0x7e,0x7d,0x24,0x2d,0xf4,0x7e,0x7b,0x60,0xa, 0x46,0x2e,0x44,0x19, +0xc5,0x7a,0x91,0x82,0x7a,0x81,0x83,0xe4,0x93,0x7c,0x6b,0xbe,0x60,0xd, 0x38,0x12, +0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14,0x78,0xfb,0x7e,0x7d,0x28, +0x80,0x15,0x9e,0x60,0xe, 0x7e,0xd4,0x0, 0x1, 0x7c,0xb6,0x60,0x5, 0x3e,0xd4,0x14, +0x78,0xfb,0x7e,0x7d,0x28,0xb, 0xf5,0xb, 0x7a,0x40,0x4d,0x4d,0x1b,0x7a,0x40,0xb, +0x70,0xbc,0x57,0x38,0xac,0x6c,0x77,0x80,0x58,0xa, 0x27,0x7f,0x70,0x2d,0xf2,0x7e, +0x7b,0x60,0xbe,0x60,0xd, 0x38,0x11,0x12,0xcc,0xc6,0x60,0x5, 0x3e,0x44,0x14,0x78, +0xfb,0x7e,0x7d,0x28,0xb, 0xf6,0x80,0x2f,0xbe,0x60,0x1b,0x38,0x16,0x9e,0x60,0xe, +0x12,0xcc,0xc6,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x7d,0x28,0x2e,0xf4,0x0, +0x6, 0x80,0x14,0x9e,0x60,0x1c,0x12,0xcc,0xc6,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb, +0x7e,0x7d,0x28,0x2e,0xf4,0x0, 0x8, 0xb, 0x7a,0x20,0x4d,0x24,0x1b,0x7a,0x20,0xb, +0x70,0xbc,0xa7,0x38,0xa4,0x22,0x7e,0x44,0x0, 0x1, 0x7c,0xb6,0x22,0x7c,0x7b,0xa5, +0xbf,0x0, 0x3, 0x74,0x10,0x22,0xbe,0x70,0x4, 0x38,0x4, 0x6c,0xaa,0x80,0x21,0xbe, +0x70,0x8, 0x38,0x5, 0x7e,0xa0,0x1, 0x80,0x17,0xbe,0x70,0x10,0x38,0x5, 0x7e,0xa0, +0x2, 0x80,0xd, 0xbe,0x70,0x20,0x38,0x5, 0x7e,0xa0,0x3, 0x80,0x3, 0x7e,0xa0,0x4, +0xa, 0x47,0x3e,0x44,0x3e,0x44,0x3e,0x44,0x7c,0xba,0x60,0x5, 0x1e,0x44,0x14,0x78, +0xfb,0x7c,0xb9,0x22,0xca,0xf8,0x6d,0x44,0x7e,0xf3,0x29,0x5b,0x90,0x60,0x93,0xe4, +0x93,0xa, 0xfb,0x7e,0xb3,0x29,0x5a,0xa, 0xeb,0x2d,0xef,0xa, 0xff,0xad,0xfe,0xa, +0xef,0x2d,0xef,0x90,0x60,0x94,0xe4,0x93,0xb4,0xff,0x31,0x7e,0x8, 0x12,0x9e,0x6c, +0xaa,0x80,0x23,0xa, 0xda,0x2d,0xdf,0x3e,0xd4,0x7e,0x1f,0x3c,0x6c,0x2d,0x3d,0xb, +0x1a,0xd0,0x7e,0x50,0x2, 0xac,0x5a,0x7f,0x50,0x2d,0xb2,0xb, 0x5a,0x30,0x9d,0x3d, +0x59,0x32,0x12,0xd6,0xb, 0xa0,0xbc,0xfa,0x38,0xd9,0x80,0xa, 0x7d,0x5e,0x3e,0x54, +0x7e,0xf, 0x3c,0x6c,0x2d,0x15,0x6c,0xaa,0x80,0x2c,0xa, 0xea,0x2d,0xef,0x3e,0xe4, +0x7e,0x1f,0x3c,0x6c,0x2d,0x3e,0xb, 0x1a,0xe0,0x7e,0x70,0x2, 0xac,0x7a,0x2d,0x31, +0x7d,0x20,0xb, 0x1a,0xd0,0x7d,0x3e,0x9d,0x3d,0x12,0x1a,0x62,0x7d,0xc3,0xbd,0x4c, +0x58,0x2, 0x7d,0x4c,0xb, 0xa0,0xbc,0xfa,0x38,0xd0,0x7d,0x34,0xda,0xf8,0x22,0x7e, +0x27,0x27,0x77,0x6d,0x11,0x9d,0x12,0x6c,0xaa,0x80,0x64,0x30,0x5, 0x2e,0x7e,0x90, +0x2, 0xac,0x9a,0x49,0x34,0x5, 0x80,0x49,0x4, 0x4, 0x0, 0xbd,0x2, 0x8, 0x11,0x7e, +0xb3,0x24,0xca,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x5, 0x80,0x80,0xc, +0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, 0x80,0x30,0x7, 0x2e,0x7e, +0x90,0x2, 0xac,0x9a,0x49,0x34,0x5, 0xe0,0x49,0x4, 0x4, 0x60,0xbd,0x2, 0x8, 0x11, +0x7e,0xb3,0x24,0xca,0xb4,0x1, 0x16,0x7d,0xf2,0x2d,0xf3,0x59,0xf4,0x5, 0xe0,0x80, +0xc, 0xbd,0x1, 0x58,0x8, 0x7d,0x3, 0x9d,0x2, 0x59,0x4, 0x5, 0xe0,0xb, 0xa0,0x7e, +0xb3,0x29,0x61,0xa, 0xb, 0x7e,0xb3,0x29,0x60,0xa, 0x4b,0x2d,0x40,0xa, 0xa, 0xbd, +0x4, 0x48,0x88,0x22,0x6c,0x33,0x80,0x9, 0xe4,0xa, 0x33,0x19,0xb3,0x26,0x46,0xb, +0x30,0x90,0x60,0x9a,0xe4,0x93,0x12,0x81,0xb, 0xb, 0x24,0xa, 0x33,0xbd,0x32,0x48, +0xe7,0xe4,0x7a,0xb3,0x27,0x58,0x7a,0xb3,0x27,0x59,0x6d,0x33,0x7a,0x37,0x27,0x5a, +0x7a,0x37,0x27,0x5c,0x7a,0x37,0x27,0x5e,0x7a,0x37,0x27,0x62,0x7e,0xd4,0x1e,0x46, +0x5e,0xd4,0xff,0xfe,0x6d,0xcc,0x7e,0x1f,0x12,0x9a,0x7a,0x37,0x1e,0x86,0x7d,0x3d, +0x7a,0x37,0x1e,0x8a,0x7e,0x34,0x14,0xae,0x7a,0x37,0x1e,0x88,0x7e,0x73,0x29,0x5a, +0x7a,0x73,0x1e,0x83,0x7e,0x73,0x29,0x5b,0x7a,0x73,0x1e,0x82,0x7e,0x37,0x29,0x49, +0x7a,0x37,0x1e,0x8c,0x7e,0x37,0x29,0x4b,0x7a,0x37,0x1e,0x8e,0x7e,0x37,0x29,0x4d, +0x7a,0x37,0x1e,0x90,0x90,0x60,0x9a,0x93,0x7a,0xb3,0x1e,0x84,0x7e,0x73,0x3, 0xfe, +0x7a,0x73,0x1e,0x85,0x7e,0x8, 0x1e,0x82,0x7e,0x18,0x1e,0x92,0x12,0x8, 0x0, 0x7e, +0x73,0x1e,0x92,0x7a,0x73,0x27,0x58,0x7e,0x73,0x1e,0x93,0x7a,0x73,0x27,0x59,0x7e, +0x37,0x1e,0x94,0x7a,0x37,0x27,0x5a,0x7e,0x37,0x1e,0x96,0x7a,0x37,0x27,0x5c,0x7e, +0x37,0x1e,0x9c,0x7a,0x37,0x27,0x5e,0x7e,0x37,0x1e,0x9e,0x7d,0x23,0x7a,0x53,0x27, +0x60,0xa, 0x36,0x7a,0x73,0x27,0x61,0x7e,0x37,0x1e,0x98,0x7a,0x37,0x27,0x62,0x7e, +0x37,0x1e,0x9a,0x7d,0x23,0x7a,0x53,0x27,0x64,0xa, 0x36,0x7a,0x73,0x27,0x65,0x6c, +0x33,0x80,0x20,0x7c,0xb3,0x7e,0x70,0x1, 0x12,0x27,0x70,0x74,0x2, 0xac,0xb3,0x49, +0x45,0x14,0xae,0xa, 0x38,0x7c,0x27,0x19,0x25,0x25,0xce,0x7c,0x29,0x19,0x25,0x25, +0xcf,0xb, 0x30,0x7e,0x23,0x27,0x58,0xbc,0x23,0x38,0xd8,0x6c,0x33,0x80,0x1b,0x74, +0x2, 0xac,0xb3,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x40,0xa, 0x38,0x7c,0x27,0x19,0x25, +0x26,0xa, 0x7c,0x29,0x19,0x25,0x26,0xb, 0xb, 0x30,0x7e,0x23,0x27,0x59,0xbc,0x23, +0x38,0xdd,0x22,0x7d,0x14,0x1a,0x2, 0x1a,0x0, 0x7d,0x37,0x1a,0x26,0x1a,0x24,0x9f, +0x10,0x7f,0x1, 0x2, 0x17,0x18,0xe4,0x7a,0xb3,0x32,0xd8,0x74,0xff,0xa, 0xcf,0x19, +0xbc,0x32,0xce,0x7e,0x70,0x63,0xac,0x7f,0x49,0x23,0x2e,0x87,0x4d,0x22,0x22,0x74, +0x9, 0xac,0xbf,0x49,0xe5,0x28,0x38,0xbd,0x3e,0x22,0x7f,0x71,0x2d,0xf4,0x7e,0x7b, +0xb0,0x1a,0xeb,0x7f,0x61,0x2e,0xd5,0x29,0x7e,0x6b,0xb0,0x22,0x7e,0xb3,0x29,0x5c, +0xa, 0x2b,0x1b,0x24,0xa, 0x3d,0xbd,0x32,0x22,0x7e,0xd, 0x27,0x2d,0x15,0xb, 0xa, +0x30,0x9d,0x32,0x59,0x35,0x1e,0x44,0x5, 0x2d,0x22,0x7c,0xb8,0x4, 0x7c,0x8b,0x1a, +0x3b,0x7e,0xb3,0x29,0x5c,0x1a,0xeb,0xbd,0x3e,0x22,0x7c,0xb9,0x4, 0x7c,0x9b,0x1a, +0x3b,0x7e,0xb3,0x29,0x5d,0x1a,0xeb,0xbd,0x3e,0x22,0x7e,0xa3,0x29,0x5b,0x7e,0xb3, +0x29,0x5a,0xa4,0x22,0x74,0x1, 0x7a,0xb3,0x29,0xee,0x7a,0xb3,0x2a,0xa, 0x22,0x7e, +0xa1,0x2d,0x74,0x2, 0xa4,0x49,0x35,0x1e,0x44,0x2, 0x1a,0x62,0x7e,0xa1,0x2d,0x74, +0x2, 0xa4,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0x22,0x7c,0x67,0x7c,0x7b,0xc4,0x23, +0x54,0x1f,0x7c,0xab,0x7c,0xb7,0x22,0x49,0x25,0x28,0x36,0x74,0x9, 0xac,0xbe,0x49, +0x35,0x27,0x82,0x22,0x7e,0x73,0x27,0x58,0xbe,0x70,0x1, 0x22,0xe5,0x4c,0xa, 0x3b, +0x7e,0x24,0x0, 0x3, 0x2, 0x16,0xe6,0x7d,0xf4,0x3e,0xf4,0x7f,0x60,0x2d,0xdf,0xb, +0x6a,0xf0,0x22,0x7c,0xb4,0x12,0x15,0xa, 0x12,0x15,0x84,0x2, 0x15,0x47,0x7e,0xa1, +0x31,0xe5,0x30,0xa4,0xbe,0x54,0x0, 0x1, 0x22,0xa, 0x47,0x7f,0x70,0x2d,0xf4,0x7e, +0x7b,0x60,0x22,0x9d,0x32,0x12,0x1a,0x62,0xbe,0x34,0x0, 0x6, 0x22,0x7e,0x34,0x0, +0x3e,0x74,0xff,0x2, 0x1a,0x30,0x7e,0x34,0x0, 0xa, 0xe4,0x2, 0x1a,0x30,0x3e,0x24, +0x7e,0xf, 0x3c,0x6c,0x2d,0x12,0x22,0x7e,0x29,0xb0,0x4c,0xb7,0x7a,0x29,0xb0,0x22, +0x7a,0x31,0x82,0x7a,0x21,0x83,0xe4,0x93,0x22,0xe5,0x4b,0xa, 0xbb,0x1b,0xb4,0xe5, +0x2b,0x22,0x74,0x2, 0xac,0x7b,0x9, 0xa3,0x25,0xce,0x22,0x74,0x5, 0xac,0xbc,0x9, +0xb5,0x25,0x7, 0x22,0xa, 0x2b,0x1b,0x24,0xa, 0x3e,0xbd,0x32,0x22,0x7e,0x37,0x24, +0xc8,0x7a,0x37,0x37,0xee,0x22,0x7e,0x34,0xc, 0xd8,0x7a,0x37,0x37,0xf0,0x22,0x7e, +0x73,0x3b,0x6b,0x7a,0x73,0x2a,0xd, 0x22,0x3, 0x3, 0x54,0xc0,0x7c,0xab,0xe4,0x22, +0xa, 0xcf,0x2d,0xcd,0x7e,0xc9,0xb0,0x22,0x7d,0x2e,0x12,0x16,0xe6,0x7d,0xf3,0x22, +0xe4,0x12,0x13,0xde,0x2, 0x13,0x96,0x7e,0x34,0x0, 0xc8,0x2, 0x1c,0xee,0xd1,0x1e, +0x2e,0xe1,0x69,0x96,0x7, 0x51, \ No newline at end of file diff --git a/drivers/input/touchscreen/gt917d/Kconfig b/drivers/input/touchscreen/gt917d/Kconfig new file mode 100644 index 0000000000000..ca5c60fb679fc --- /dev/null +++ b/drivers/input/touchscreen/gt917d/Kconfig @@ -0,0 +1,35 @@ +# +# Goodix GT9xx Touchscreen driver +# +config TOUCHSCREEN_GT917d + bool "Goodix touchpanel GT9xx series" + depends on I2C + help + Say Y here if you have a Goodix GT9xx touchscreen + controller. + + If unsure, say N. + +config TOUCHSCREEN_GT917d_UPDATE + tristate "Goodix GT9xx touch controller auto update support" + depends on TOUCHSCREEN_GT9XX + default y + help + Enable this for support firmware update. + + Say Y here if you want update touch controller firmware. + + If unsure, say N. + +config TOUCHSCREEN_GT917d_TOOL + tristate "Goodix GT9xx Tools for debuging" + depends on TOUCHSCREEN_GT9XX + default y + help + This implement interface support for Goodix GT9xx + touchscreen debug. + + Say Y here if you want to have a Android app debug interface + to your system. + + If unsure, say N. diff --git a/drivers/input/touchscreen/gt917d/Makefile b/drivers/input/touchscreen/gt917d/Makefile new file mode 100644 index 0000000000000..96d7219c08011 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Goodix gt9xx touchscreen driver. +# +#subdir-ccflags-y += -DDEBUG +obj-$(CONFIG_TOUCHSCREEN_GT917d) += gt9xx.o +obj-$(CONFIG_TOUCHSCREEN_GT917d) += gt9xx_update.o +obj-$(CONFIG_TOUCHSCREEN_GT917d) += goodix_tool.o +obj-$(CONFIG_TOUCHSCREEN_GT917d) += gt9xx_selftest.o diff --git a/drivers/input/touchscreen/gt917d/goodix_tool.c b/drivers/input/touchscreen/gt917d/goodix_tool.c new file mode 100644 index 0000000000000..e92f6af66a0a0 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/goodix_tool.c @@ -0,0 +1,539 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2016 - 2017 Goodix. Ltd. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.8.0.1 + * Release Date: 2017/11/24 + */ + +#include "gt9xx.h" + +#define DATA_LENGTH_UINT 512 +#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *)) +static char procname[20] = {0}; +#define DEBUG + +#pragma pack(1) +struct st_cmd_head { + u8 wr; /*write read flag 0:R 1:W 2:PID 3:*/ + u8 flag; /*0:no need flag/int 1: need flag 2:need int*/ + u8 flag_addr[2]; /*flag address*/ + u8 flag_val; /*flag val*/ + u8 flag_relation; /*flag_val:flag 0:not equal 1:equal 2:> 3:<*/ + u16 circle; /*polling cycle*/ + u8 times; /*plling times*/ + u8 retry; /*I2C retry times*/ + u16 delay; /*delay before read or after write*/ + u16 data_len; /*data length*/ + u8 addr_len; /*address length*/ + u8 addr[2]; /*address*/ + u8 res[3]; /*reserved*/ + u8 *data; }; /*data pointer*/ +#pragma pack() +struct st_cmd_head cmd_head; + +static struct i2c_client *gt_client; +static struct proc_dir_entry *goodix_proc_entry; + +static ssize_t goodix_tool_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t goodix_tool_write(struct file *, const char __user *, size_t, loff_t *); +static const struct file_operations gtp_proc_ops = { + .owner = THIS_MODULE, + .read = goodix_tool_read, + .write = goodix_tool_write, +}; + +/* static s32 goodix_tool_write(struct file *filp, + * const char __user *buff, unsigned long len, void *data); + */ +/*static s32 goodix_tool_read( char *page, char + **start, off_t off, int count, int *eof, void *data ); + */ +static s32 (*tool_i2c_read)(u8 *, u16); +static s32 (*tool_i2c_write)(u8 *, u16); + +static s32 DATA_LENGTH = (s32)0; +static s8 IC_TYPE[16] = "GT9XX"; + +static void tool_set_proc_name(char *procname) +{ + snprintf(procname, 20, "gmnode"); /* modify for moto */ +} + +static s32 tool_i2c_read_no_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + s32 i = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + for (i = 0; i < cmd_head.retry; i++) { + ret = gtp_i2c_read(ts->client, buf, len + GTP_ADDR_LENGTH); + if (ret > 0) + break; + } + return ret; +} + +static s32 tool_i2c_write_no_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + s32 i = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + for (i = 0; i < cmd_head.retry; i++) { + ret = gtp_i2c_write(ts->client, buf, len); + if (ret > 0) + break; + } + + return ret; +} + +static s32 tool_i2c_read_with_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + u8 pre[2] = {0x0f, 0xff}; + u8 end[2] = {0x80, 0x00}; + + tool_i2c_write_no_extra(pre, 2); + ret = tool_i2c_read_no_extra(buf, len); + tool_i2c_write_no_extra(end, 2); + + return ret; +} + +static s32 tool_i2c_write_with_extra(u8 *buf, u16 len) +{ + s32 ret = -1; + u8 pre[2] = {0x0f, 0xff}; + u8 end[2] = {0x80, 0x00}; + + tool_i2c_write_no_extra(pre, 2); + ret = tool_i2c_write_no_extra(buf, len); + tool_i2c_write_no_extra(end, 2); + + return ret; +} + +static void register_i2c_func(void) +{ + /* if (!strncmp(IC_TYPE, "GT818", 5) + * || !strncmp(IC_TYPE, "GT816", 5) + * || !strncmp(IC_TYPE, "GT811", 5) + * || !strncmp(IC_TYPE, "GT818F", 6) + * || !strncmp(IC_TYPE, "GT827", 5) + * || !strncmp(IC_TYPE,"GT828", 5) + * || !strncmp(IC_TYPE, "GT813", 5)) + */ + if (strncmp(IC_TYPE, "GT8110", 6) && + strncmp(IC_TYPE, "GT8105", 6) && + strncmp(IC_TYPE, "GT801", 5) && + strncmp(IC_TYPE, "GT800", 5) && + strncmp(IC_TYPE, "GT801PLUS", 9) && + strncmp(IC_TYPE, "GT811", 5) && + strncmp(IC_TYPE, "GTxxx", 5) && + strncmp(IC_TYPE, "GT9XX", 5)) { + tool_i2c_read = tool_i2c_read_with_extra; + tool_i2c_write = tool_i2c_write_with_extra; + dev_dbg(>_client->dev, "I2C function: with pre and end cmd!"); + } else { + tool_i2c_read = tool_i2c_read_no_extra; + tool_i2c_write = tool_i2c_write_no_extra; + dev_info(>_client->dev, "I2C function: without pre and end cmd!"); + } +} + +static void unregister_i2c_func(void) +{ + tool_i2c_read = NULL; + tool_i2c_write = NULL; + dev_info(>_client->dev, "I2C function: unregister i2c transfer function!"); +} + +s32 init_wr_node(struct i2c_client *client) +{ + s32 i; + + gt_client = client; + memset(&cmd_head, 0, sizeof(cmd_head)); + cmd_head.data = NULL; + + i = 3; + while ((!cmd_head.data) && i) { + cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL); + if (cmd_head.data) + break; + i--; + } + if (i) { + DATA_LENGTH = i * DATA_LENGTH_UINT - GTP_ADDR_LENGTH; + dev_info(>_client->dev, + "Alloc memory size:%d.", DATA_LENGTH); + } else { + dev_err(>_client->dev, "Apply for memory failed."); + return FAIL; + } + + cmd_head.addr_len = 2; + cmd_head.retry = 5; + + register_i2c_func(); + + tool_set_proc_name(procname); + goodix_proc_entry = proc_create(procname, 0666, NULL, >p_proc_ops); + if (!goodix_proc_entry) { + dev_err(>_client->dev, "Couldn't create proc entry!"); + return FAIL; + } + + dev_info(>_client->dev, "Create proc entry success!"); + return SUCCESS; +} + +void uninit_wr_node(void) +{ + kfree(cmd_head.data); + cmd_head.data = NULL; + unregister_i2c_func(); + remove_proc_entry(procname, NULL); +} + +static u8 relation(u8 src, u8 dst, u8 rlt) +{ + u8 ret = 0; + + switch (rlt) { + case 0: + ret = (src != dst) ? true : false; + break; + + case 1: + ret = (src == dst) ? true : false; + dev_dbg(>_client->dev, + "equal:src:0x%02x dst:0x%02x ret:%d.", + src, dst, (s32)ret); + break; + + case 2: + ret = (src > dst) ? true : false; + break; + + case 3: + ret = (src < dst) ? true : false; + break; + + case 4: + ret = (src & dst) ? true : false; + break; + + case 5: + ret = (!(src | dst)) ? true : false; + break; + + default: + ret = false; + break; + } + + return ret; +} + +/******************************************************* + * Function: + * Comfirm function. + * Input: + * None. + * Output: + * Return write length. + ********************************************************/ +static u8 comfirm(void) +{ + s32 i = 0; + u8 buf[32]; + + memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len); + + for (i = 0; i < cmd_head.times; i++) { + if (tool_i2c_read(buf, 1) <= 0) { + dev_err(>_client->dev, "Read flag data failed!"); + return FAIL; + } + if (true == relation(buf[GTP_ADDR_LENGTH], + cmd_head.flag_val, cmd_head.flag_relation)) { + dev_dbg(>_client->dev, "value at flag addr:0x%02x.", + buf[GTP_ADDR_LENGTH]); + dev_dbg(>_client->dev, "flag value:0x%02x.", + cmd_head.flag_val); + break; + } + + msleep(cmd_head.circle); + } + + if (i >= cmd_head.times) { + dev_err(>_client->dev, "Can't get the continue flag!"); + return FAIL; + } + + return SUCCESS; +} + +ssize_t goodix_tool_write(struct file *filp, const char __user *buff, + size_t len, loff_t *off) +{ + s32 ret = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); + + ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH); + if (ret) { + dev_err(>_client->dev, "copy_from_user failed."); + return -EPERM; + } + + dev_dbg(>_client->dev, "[Operation]wr: %02X", cmd_head.wr); + dev_dbg(>_client->dev, + "[Flag]flag: %02X,addr: %02X%02X,value: %02X,relation: %02X", + cmd_head.flag, cmd_head.flag_addr[0], + cmd_head.flag_addr[1], cmd_head.flag_val, + cmd_head.flag_relation); + dev_dbg(>_client->dev, + "[Retry]circle: %d,times: %d,retry: %d, delay: %d", + (s32)cmd_head.circle, + (s32)cmd_head.times, (s32)cmd_head.retry, + (s32)cmd_head.delay); + dev_dbg(>_client->dev, + "[Data]data len: %d,addr len: %d, addr: %02X%02X,buffer len:%d, data[0]: %02X", + (s32)cmd_head.data_len, + (s32)cmd_head.addr_len, cmd_head.addr[0], + cmd_head.addr[1], (s32)len, buff[CMD_HEAD_LENGTH]); + + if (1 == cmd_head.wr) { + if (cmd_head.data_len > DATA_LENGTH) { + dev_err(>_client->dev, + "Tool write failed data too long"); + return -EPERM; + } + ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], + &buff[CMD_HEAD_LENGTH], + cmd_head.data_len); + if (ret) { + dev_err(>_client->dev, "copy_from_user failed."); + return -EPERM; + } + memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len], + cmd_head.addr, cmd_head.addr_len); + + GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len + + cmd_head.addr_len); + GTP_DEBUG_ARRAY((u8 *)&buff[CMD_HEAD_LENGTH], + cmd_head.data_len); + + if (1 == cmd_head.flag) { + if (FAIL == comfirm()) { + dev_err(>_client->dev, + "[WRITE]Comfirm fail!"); + return -EPERM; + } + } else if (2 == cmd_head.flag) { + /*Need interrupt!*/ + } + if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH - + cmd_head.addr_len], cmd_head.data_len + + cmd_head.addr_len) <= 0) { + dev_err(>_client->dev, "[WRITE]Write data failed!"); + return -EPERM; + } + + GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH - + cmd_head.addr_len], + cmd_head.data_len + cmd_head.addr_len); + if (cmd_head.delay) + msleep(cmd_head.delay); + } else if (3 == cmd_head.wr) { + if (cmd_head.data_len > DATA_LENGTH) { + dev_err(>_client->dev, + "Tool write failed data too long"); + return -EPERM; + } + ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH], + cmd_head.data_len); + if (ret) { + dev_err(>_client->dev, "copy_from_user failed."); + return -EPERM; + } + memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); + + register_i2c_func(); + } else if (5 == cmd_head.wr) { + /*memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);*/ + } else if (7 == cmd_head.wr) {/*disable irq!*/ + gtp_work_control_enable(i2c_get_clientdata(gt_client), false); + + if (ts->pdata->esd_protect) + gtp_esd_off(ts); + } else if (9 == cmd_head.wr) {/*enable irq!*/ + gtp_work_control_enable(i2c_get_clientdata(gt_client), true); + + if (ts->pdata->esd_protect) + gtp_esd_on(ts); + } else if (17 == cmd_head.wr) { + if (cmd_head.data_len > DATA_LENGTH) { + dev_err(>_client->dev, + "Tool write failed data too long"); + return -EPERM; + } + ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH], + &buff[CMD_HEAD_LENGTH], + cmd_head.data_len); + if (ret) { + dev_dbg(>_client->dev, "copy_from_user failed."); + return -EPERM; + } + if (cmd_head.data[GTP_ADDR_LENGTH]) { + dev_info(>_client->dev, "gtp enter rawdiff."); + set_bit(RAW_DATA_MODE, &ts->flags); + } else { + clear_bit(RAW_DATA_MODE, &ts->flags); + dev_info(>_client->dev, "gtp leave rawdiff."); + } + } else if (19 == cmd_head.wr) { + /* add new command: reset guitar */ + gtp_reset_guitar(gt_client, 20); + } +#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE + else if (11 == cmd_head.wr) {/*Enter update mode!*/ + if (FAIL == gup_enter_update_mode(gt_client)) + return -EPERM; + } else if (13 == cmd_head.wr) {/*Leave update mode!*/ + gup_leave_update_mode(gt_client); + } else if (15 == cmd_head.wr) {/*Update firmware!*/ + show_len = 0; + total_len = 0; + if (cmd_head.data_len > DATA_LENGTH) { + dev_err(>_client->dev, + "Tool write failed data too long"); + return -EPERM; + } + memset(cmd_head.data, 0, DATA_LENGTH); + ret = copy_from_user(cmd_head.data, + &buff[CMD_HEAD_LENGTH], + cmd_head.data_len); + if (ret) { + dev_dbg(>_client->dev, "copy_from_user failed."); + return -EPERM; + } + + if (FAIL == gup_update_proc((void *)cmd_head.data)) + return -EPERM; + } +#endif + + return len; +} + +/******************************************************* + * Function: + * Goodix tool read function. + * Input: + * standard proc read function param. + * Output: + * Return read length. + ********************************************************/ +ssize_t goodix_tool_read(struct file *file, char __user *page, + size_t size, loff_t *ppos) +{ + s32 ret = 0; + + if (*ppos) { + /* ADB call again + * dev_dbg(>_client->dev, "[HEAD]wr: %d", cmd_head.wr); + * dev_dbg(>_client->dev, + * "[PARAM]size: %d, *ppos: %d", size, (int)*ppos); + * dev_dbg(>_client->dev, + * "[TOOL_READ]ADB call again, return it."); + */ + *ppos = 0; + return 0; + } + + if (cmd_head.wr % 2) { + return -EPERM; + } else if (!cmd_head.wr) { + u16 len, data_len, loc, addr; + + if (1 == cmd_head.flag) { + if (FAIL == comfirm()) { + dev_err(>_client->dev, "[READ]Comfirm fail!"); + return -EPERM; + } + } else if (2 == cmd_head.flag) { + /*Need interrupt!*/ + } + + if (cmd_head.delay) + msleep(cmd_head.delay); + + data_len = cmd_head.data_len; + addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1]; + loc = 0; + + while (data_len > 0) { + len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len; + cmd_head.data[0] = (addr >> 8) & 0xFF; + cmd_head.data[1] = (addr & 0xFF); + if (tool_i2c_read(cmd_head.data, len) <= 0) { + dev_err(>_client->dev, "[READ]Read data failed!"); + return -EPERM; + } + ret = simple_read_from_buffer(&page[loc], size, ppos, + &cmd_head.data[GTP_ADDR_LENGTH], len); + if (ret < 0) + return ret; + loc += len; + addr += len; + data_len -= len; + } + return cmd_head.data_len; + } else if (2 == cmd_head.wr) { + ret = simple_read_from_buffer(page, size, ppos, + IC_TYPE, sizeof(IC_TYPE)); + return ret; + } +#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE + else if (4 == cmd_head.wr) { + u8 progress_buf[4]; + + progress_buf[0] = show_len >> 8; + progress_buf[1] = show_len & 0xff; + progress_buf[2] = total_len >> 8; + progress_buf[3] = total_len & 0xff; + + ret = simple_read_from_buffer(page, size, ppos, + progress_buf, 4); + return ret; + } +#endif + else if (6 == cmd_head.wr) { + /*Read error code!*/ + } else if (8 == cmd_head.wr) { /*Read driver version*/ + ret = simple_read_from_buffer(page, size, ppos, + GTP_DRIVER_VERSION, + strlen(GTP_DRIVER_VERSION)); + return ret; + } + + return -EPERM; +} diff --git a/drivers/input/touchscreen/gt917d/gt9xx.c b/drivers/input/touchscreen/gt917d/gt9xx.c new file mode 100644 index 0000000000000..ec082b4c4763a --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx.c @@ -0,0 +1,3055 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2016 - 2017 Goodix. Ltd. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.8.0.1 + * Release Date: 2017/11/24 + */ + +#include +#include +#include +#include +#include "gt9xx.h" +#include + +#define GOODIX_COORDS_ARR_SIZE 4 +#define PROP_NAME_SIZE 24 +#define I2C_MAX_TRANSFER_SIZE 255 +#define GTP_PEN_BUTTON1 BTN_STYLUS +#define GTP_PEN_BUTTON2 BTN_STYLUS2 + +#if GTP_CHARGER_SWITCH +bool gtp_get_charger_status(void); +static void gtp_charger_updateconfig(struct goodix_ts_data *ts , s32 dir_update); +static void gtp_charger_check_func(struct work_struct *work); +static int gtp_charger_init(struct goodix_ts_data *ts); +void gtp_charger_on(struct goodix_ts_data *ts); +void gtp_charger_off(struct goodix_ts_data *ts); +#endif +static const char *goodix_ts_name = "goodix-ts"; +static const char *goodix_input_phys = "input/ts"; +struct i2c_client *i2c_connect_client; +static struct proc_dir_entry *gtp_config_proc; +/*Add by HQ-zmc [Date: 2018-01-19 09:53:53]*/ +static struct proc_dir_entry *gtp_locdown_proc; +static struct proc_dir_entry *gtp_wakeup_gesture_proc; +static char tp_info_summary[80]=""; +static char tp_lockdown_info[128]; +extern void gtp_test_sysfs_init(void); +extern void gtp_test_sysfs_deinit(void); + +#if ((defined CONFIG_PM)&&(defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +extern bool lcm_ffbm_mode; +#endif + +enum doze { + DOZE_DISABLED = 0, + DOZE_ENABLED = 1, + DOZE_WAKEUP = 2, +}; + +static enum doze doze_status = DOZE_DISABLED; + +int gtp_i2c_test(struct i2c_client *client); +static int gtp_enter_doze(struct goodix_ts_data *ts); + +static int gtp_unregister_powermanager(struct goodix_ts_data *ts); +static int gtp_register_powermanager(struct goodix_ts_data *ts); + +static int gtp_esd_init(struct goodix_ts_data *ts); +static void gtp_esd_check_func(struct work_struct *); +static int gtp_init_ext_watchdog(struct i2c_client *client); +static int gtp_i2c_write_no_rst(struct i2c_client *client,u8 *buf,s32 len); +static int gtp_power_on(struct goodix_ts_data *ts); +static int gtp_power_off(struct goodix_ts_data *ts); + +extern int create_gtp_data_dump_proc(void); + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-02-01 16:35:11 + * @input: + * @output: + * ============================ + */ +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 +bool GTP_gesture_func_on = false; + +int gtp_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + unsigned int input ; + if (type == EV_SYN && code == SYN_CONFIG) + { + if(value == WAKEUP_OFF){ + GTP_gesture_func_on = false; + input = 0; + }else if(value == WAKEUP_ON){ + GTP_gesture_func_on = true; + input = 1; + } + } + return 0; +} + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-01-18 21:23:28 + * @input: + * @output: + * ============================ + */ +static int gtp_i2c_write_no_rst(struct i2c_client *client,u8 *buf,s32 len) +{ + struct i2c_msg msg; + s32 ret = -1; + s32 retries = 0; + + GTP_DEBUG_FUNC(); + + msg.flags = !I2C_M_RD; + msg.addr = client->addr; + msg.len = len; + msg.buf = buf; + + while(retries < 5) + { + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret == 1)break; + retries++; + } + if((retries >= 5)) + { + dev_info(&client->dev,"I2C Write: 0x%04X, %d bytes failed, errcode: %d!", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret); + } + return ret; +} + +/* + * return: 2 - ok, < 0 - i2c transfer error + */ +int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len) +{ + unsigned int transfer_length = 0; + unsigned int pos = 0, address = (buf[0] << 8) + buf[1]; + unsigned char get_buf[64], addr_buf[2]; + int retry, r = 2; + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = !I2C_M_RD, + .buf = &addr_buf[0], + .len = GTP_ADDR_LENGTH, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + } + }; + + len -= GTP_ADDR_LENGTH; + if (likely(len < sizeof(get_buf))) { + /* code optimize, use stack memory */ + msgs[1].buf = &get_buf[0]; + } else { + msgs[1].buf = kzalloc(len > I2C_MAX_TRANSFER_SIZE + ? I2C_MAX_TRANSFER_SIZE : len, GFP_KERNEL); + if (!msgs[1].buf) + return -ENOMEM; + } + + while (pos != len) { + if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE)) + transfer_length = I2C_MAX_TRANSFER_SIZE; + else + transfer_length = len - pos; + msgs[0].buf[0] = (address >> 8) & 0xFF; + msgs[0].buf[1] = address & 0xFF; + msgs[1].len = transfer_length; + for (retry = 0; retry < RETRY_MAX_TIMES; retry++) { + if (likely(i2c_transfer(client->adapter, msgs, 2) == 2)) { + memcpy(&buf[2 + pos], msgs[1].buf, transfer_length); + pos += transfer_length; + address += transfer_length; + break; + } + dev_dbg(&client->dev, "I2c read retry[%d]:0x%x\n", + retry + 1, address); + usleep_range(2000, 2100); + } + if (unlikely(retry == RETRY_MAX_TIMES)) { + dev_err(&client->dev, + "I2c read failed,dev:%02x,reg:%04x,size:%u\n", + client->addr, address, len); + r = -EAGAIN; + goto read_exit; + } + } +read_exit: + if (len >= sizeof(get_buf)) + kfree(msgs[1].buf); + return r; +} + +/******************************************************* + * Function: + * Write data to the i2c slave device. + * Input: + * client: i2c device. + * buf[0~1]: write start address. + * buf[2~len-1]: data buffer + * len: GTP_ADDR_LENGTH + write bytes count + * Output: + * numbers of i2c_msgs to transfer: + * 1: succeed, otherwise: failed + *********************************************************/ +int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len) + +{ + unsigned int pos = 0, transfer_length = 0; + unsigned int address = (buf[0] << 8) + buf[1]; + unsigned char put_buf[64]; + int retry, r = 1; + struct i2c_msg msg = { + .addr = client->addr, + .flags = !I2C_M_RD, + }; + + if (likely(len < sizeof(put_buf))) { + /* code optimize,use stack memory*/ + msg.buf = &put_buf[0]; + } else { + msg.buf = kmalloc(len > I2C_MAX_TRANSFER_SIZE + ? I2C_MAX_TRANSFER_SIZE : len, GFP_KERNEL); + if (!msg.buf) + return -ENOMEM; + } + + len -= GTP_ADDR_LENGTH; + while (pos != len) { + if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE - GTP_ADDR_LENGTH)) + transfer_length = I2C_MAX_TRANSFER_SIZE - GTP_ADDR_LENGTH; + else + transfer_length = len - pos; + msg.buf[0] = (unsigned char)((address >> 8) & 0xFF); + msg.buf[1] = (unsigned char)(address & 0xFF); + msg.len = transfer_length + 2; + memcpy(&msg.buf[2], &buf[2 + pos], transfer_length); + for (retry = 0; retry < RETRY_MAX_TIMES; retry++) { + if (likely(i2c_transfer(client->adapter, &msg, 1) == 1)) { + pos += transfer_length; + address += transfer_length; + break; + } + dev_dbg(&client->dev, "I2C write retry[%d]\n", retry + 1); + usleep_range(2000, 2100); + } + if (unlikely(retry == RETRY_MAX_TIMES)) { + dev_err(&client->dev, + "I2c write failed,dev:%02x,reg:%04x,size:%u\n", + client->addr, address, len); + r = -EAGAIN; + goto write_exit; + } + } +write_exit: + if (len + GTP_ADDR_LENGTH >= sizeof(put_buf)) + kfree(msg.buf); + return r; +} + +/******************************************************* + * Function: + * i2c read twice, compare the results + * Input: + * client: i2c device + * addr: operate address + * rxbuf: read data to store, if compare successful + * len: bytes to read + * Output: + * FAIL: read failed + * SUCCESS: read successful + *********************************************************/ +s32 gtp_i2c_read_dbl_check(struct i2c_client *client, + u16 addr, u8 *rxbuf, int len) +{ + u8 buf[16] = {0}; + u8 confirm_buf[16] = {0}; + u8 retry = 0; + + if (len + 2 > sizeof(buf)) { + dev_warn(&client->dev, + "%s, only support length less then %zu\n", + __func__, sizeof(buf) - 2); + return FAIL; + } + while (retry++ < 3) { + memset(buf, 0xAA, 16); + buf[0] = (u8)(addr >> 8); + buf[1] = (u8)(addr & 0xFF); + gtp_i2c_read(client, buf, len + 2); + + memset(confirm_buf, 0xAB, 16); + confirm_buf[0] = (u8)(addr >> 8); + confirm_buf[1] = (u8)(addr & 0xFF); + gtp_i2c_read(client, confirm_buf, len + 2); + + if (!memcmp(buf, confirm_buf, len + 2)) { + memcpy(rxbuf, confirm_buf + 2, len); + return SUCCESS; + } + } + dev_err(&client->dev, + "I2C read 0x%04X, %d bytes, double check failed!\n", + addr, len); + + return FAIL; +} + +/******************************************************* + * Function: + * Send config. + * Input: + * client: i2c device. + * Output: + * result of i2c write operation. + * 1: succeed, otherwise + * 0: Not executed + * < 0: failed + *********************************************************/ +s32 gtp_send_cfg(struct i2c_client *client) +{ + s32 ret, i; + u8 check_sum; + s32 retry = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(client); + struct goodix_config_data *cfg = &ts->pdata->config; + + if (!cfg->length || !ts->pdata->driver_send_cfg) { + dev_info(&ts->client->dev, + "No config data or error occurred in panel_init\n"); + return 0; + } + + check_sum = 0; + for (i = GTP_ADDR_LENGTH; i < cfg->length; i++) + check_sum += cfg->data[i]; + cfg->data[cfg->length] = (~check_sum) + 1; + + dev_info(&ts->client->dev, "Driver send config\n"); + for (retry = 0; retry < RETRY_MAX_TIMES; retry++) { + ret = gtp_i2c_write(client, cfg->data, + GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + if (ret > 0) + break; + } + + return ret; +} + +/******************************************************* + * Function: + * Control enable or disable of work thread. + * Input: + * ts: goodix i2c_client private data + * enable: enable var. + *********************************************************/ +void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable) +{ + if (enable) { + set_bit(WORK_THREAD_ENABLED, &ts->flags); + dev_dbg(&ts->client->dev, "Input report thread enabled!\n"); + } else { + clear_bit(WORK_THREAD_ENABLED, &ts->flags); + dev_dbg(&ts->client->dev, "Input report thread disabled!\n"); + } +} + +static int gtp_gesture_handler(struct goodix_ts_data *ts) +{ + u8 doze_buf[3] = {GTP_REG_DOZE_BUF >> 8, GTP_REG_DOZE_BUF & 0xFF}; + int ret; + + ret = gtp_i2c_read(ts->client, doze_buf, 3); + if (ret < 0) { + dev_err(&ts->client->dev, "Failed read doze buf"); + return -EINVAL; + } + + dev_dbg(&ts->client->dev, "0x814B = 0x%02X", doze_buf[2]); + if (doze_buf[2] == 0xCC) { + doze_status = DOZE_WAKEUP; + input_report_key(ts->input_dev, KEY_WAKEUP, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, KEY_WAKEUP, 0); + input_sync(ts->input_dev); + /* clear 0x814B */ + doze_buf[2] = 0x00; + gtp_i2c_write(ts->client, doze_buf, 3); + } else { + /* clear 0x814B */ + doze_buf[2] = 0x00; + gtp_i2c_write(ts->client, doze_buf, 3); + gtp_enter_doze(ts); + } + return 0; +} + +/* + * return touch state register value + * pen event id fixed with 9 and set tool type TOOL_PEN + * + */ +static u8 gtp_get_points(struct goodix_ts_data *ts, + struct goodix_point_t *points, + u8 *key_value) +{ + int ret; + int i; + u8 *coor_data = NULL; + u8 finger_state = 0; + u8 touch_num = 0; + u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8, + GTP_READ_COOR_ADDR & 0xFF, 0 }; + u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH_ID + 1] = { + GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF }; + + ret = gtp_i2c_read(ts->client, point_data, 12); + if (ret < 0) { + dev_err(&ts->client->dev, + "I2C transfer error. errno:%d\n ", ret); + return 0; + } + finger_state = point_data[GTP_ADDR_LENGTH]; + if (finger_state == 0x00) + return 0; + + touch_num = finger_state & 0x0f; + if ((finger_state & MASK_BIT_8) == 0 || + touch_num > ts->pdata->max_touch_id) { + dev_err(&ts->client->dev, + "Invalid touch state: 0x%x", finger_state); + finger_state = 0; + goto exit_get_point; + } + + if (touch_num > 1) { + u8 buf[8 * GTP_MAX_TOUCH_ID] = { + (GTP_READ_COOR_ADDR + 10) >> 8, + (GTP_READ_COOR_ADDR + 10) & 0xff }; + + ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1)); + if (ret < 0) { + dev_err(&ts->client->dev, "I2C error. %d\n", ret); + finger_state = 0; + goto exit_get_point; + } + memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1)); + } + + /* panel have touch key */ + /* 0x20_UPKEY 0X10_DOWNKEY 0X40_ALLKEYDOWN */ + *key_value = point_data[3 + 8 * touch_num]; + + memset(points, 0, sizeof(*points) * GTP_MAX_TOUCH_ID); + for (i = 0; i < touch_num; i++) { + coor_data = &point_data[i * 8 + 3]; + points[i].id = coor_data[0]; + points[i].x = coor_data[1] | (coor_data[2] << 8); + points[i].y = coor_data[3] | (coor_data[4] << 8); + points[i].w = coor_data[5] | (coor_data[6] << 8); + /* if pen hover points[].p must set to zero */ + points[i].p = coor_data[5] | (coor_data[6] << 8); + + if (ts->pdata->swap_x2y) + GTP_SWAP(points[i].x, points[i].y); + + dev_dbg(&ts->client->dev, "[%d][%d %d %d]\n", + points[i].id, points[i].x, points[i].y, points[i].p); + + /* pen device coordinate */ + if (points[i].id & 0x80) { + points[i].tool_type = GTP_TOOL_PEN; + points[i].id = 10; + if (ts->pdata->pen_suppress_finger) { + points[0] = points[i]; + memset(++points, 0, sizeof(*points) * (GTP_MAX_TOUCH_ID - 1)); + finger_state &= 0xf0; + finger_state |= 0x01; + break; + } + } else { + points[i].tool_type = GTP_TOOL_FINGER; + } + } + +exit_get_point: + if (!test_bit(RAW_DATA_MODE, &ts->flags)) { + ret = gtp_i2c_write(ts->client, end_cmd, 3); + if (ret < 0) + dev_info(&ts->client->dev, "I2C write end_cmd error!"); + } + return finger_state; +} + +static void gtp_type_a_report(struct goodix_ts_data *ts, u8 touch_num, + struct goodix_point_t *points) +{ + int i; + u16 cur_touch = 0; + static u8 pre_pen_id; + + if (touch_num) + input_report_key(ts->input_dev, BTN_TOUCH, 1); + + for (i = 0; i < ts->pdata->max_touch_id; i++) { + if (touch_num && i == points->id) { + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, points->id); + + if (points->tool_type == GTP_TOOL_PEN) { + input_report_key(ts->input_dev, BTN_TOOL_PEN, true); + pre_pen_id = points->id; + } else { + input_report_key(ts->input_dev, BTN_TOOL_FINGER, true); + } + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + points->x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + points->y); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + points->w); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + points->p); + input_mt_sync(ts->input_dev); + + cur_touch |= 0x01 << points->id; + points++; + } else if (ts->pre_touch & 0x01 << i) { + if (pre_pen_id == i) { + input_report_key(ts->input_dev, BTN_TOOL_PEN, false); + /* valid id will < 10, so id to 0xff to indicate a invalid state */ + pre_pen_id = 0xff; + } else { + input_report_key(ts->input_dev, BTN_TOOL_FINGER, false); + } + } + } + + ts->pre_touch = cur_touch; + if (!ts->pre_touch) { + input_mt_sync(ts->input_dev); + input_report_key(ts->input_dev, BTN_TOUCH, 0); + } + input_sync(ts->input_dev); +} + +/*Add by HQ-zmc [Date: 2018-03-02 14:33:55] + report log is printed only when finger is DWN and UP + flag DWN is needed to judge finger status +*/ +static bool p_down[10] = {0}; +static void gtp_mt_slot_report(struct goodix_ts_data *ts, u8 touch_num, + struct goodix_point_t *points) +{ + int i; + u16 cur_touch = 0; + static u8 pre_pen_id; + + for (i = 0; i < ts->pdata->max_touch_id; i++) { + if (touch_num && i == points->id) { + input_mt_slot(ts->input_dev, points->id); + + if (points->tool_type == GTP_TOOL_PEN) { + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_PEN, true); + pre_pen_id = points->id; + } else { + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_FINGER, true); /*finger DWN send true*/ + if(!p_down[points->id]){ + printk("[GTP]:F%d x%d y%d DWN\n",\ + cur_touch,points->x,points->y); + p_down[points->id] = 1; + } + } + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, + points->x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, + points->y); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, + points->w); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, + points->p); + + cur_touch |= 0x01 << points->id; + points++; + } else if (ts->pre_touch & 0x01 << i) { + input_mt_slot(ts->input_dev, i); + + if (pre_pen_id == i) { + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_PEN, false); + /* valid id will < 10, so set id to 0xff to + * indicate a invalid state + */ + pre_pen_id = 0xff; + } else { + if(p_down[points->id]){ + printk("[GTP]:F UP\n"); + p_down[points->id] = 0; + } + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_FINGER, false); /*finger UP send false*/ + } + } + } + + ts->pre_touch = cur_touch; + /* report BTN_TOUCH event */ + input_mt_sync_frame(ts->input_dev); + input_sync(ts->input_dev); +} + +/******************************************************* + * Function: + * Goodix touchscreen sensor report function + * Input: + * ts: goodix tp private data + * Output: + * None. + *********************************************************/ +static void gtp_work_func(struct goodix_ts_data *ts) +{ + u8 point_state = 0; + u8 key_value = 0; + s32 i = 0; + s32 ret = -1; + static u8 pre_key; + struct goodix_point_t points[GTP_MAX_TOUCH_ID]; + + if (test_bit(PANEL_RESETTING, &ts->flags)) + return; + if (!test_bit(WORK_THREAD_ENABLED, &ts->flags)) + return; + + /* gesture event */ + if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) { + ret = gtp_gesture_handler(ts); + if (ret) + dev_err(&ts->client->dev, + "Failed handler gesture event %d\n", ret); + return; + } + + point_state = gtp_get_points(ts, points, &key_value); + if (!point_state) { + dev_err(&ts->client->dev, "Invalid finger points\n"); + return; + } + + /* touch key event */ + if (key_value & 0xf0 || pre_key & 0xf0) { + /* pen button */ + switch (key_value) { + case 0x40: + input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1); + input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1); + break; + case 0x10: + input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1); + input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0); + dev_dbg(&ts->client->dev, "pen button1 down\n"); + break; + case 0x20: + input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0); + input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1); + break; + default: + input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0); + input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0); + dev_dbg(&ts->client->dev, "button1 up\n"); + break; + } + input_sync(ts->input_dev); + pre_key = key_value; + } else if (key_value & 0x0f || pre_key & 0x0f) { + /* panel key */ + for (i = 0; i < ts->pdata->key_nums; i++) { + if ((pre_key | key_value) & (0x01 << i)) + input_report_key(ts->input_dev, + ts->pdata->key_map[i], + key_value & (0x01 << i)); + } + input_sync(ts->input_dev); + pre_key = key_value; + } + + mutex_lock(&ts->lock); + if (!ts->pdata->type_a_report) + gtp_mt_slot_report(ts, point_state & 0x0f, points); + else + gtp_type_a_report(ts, point_state & 0x0f, points); + mutex_unlock(&ts->lock); +} + +/******************************************************* + * Function: + * Timer interrupt service routine for polling mode. + * Input: + * timer: timer struct pointer + * Output: + * Timer work mode. + * HRTIMER_NORESTART: + * no restart mode + *********************************************************/ +static enum hrtimer_restart gtp_timer_handler(struct hrtimer *timer) +{ + struct goodix_ts_data *ts = + container_of(timer, struct goodix_ts_data, timer); + + gtp_work_func(ts); + hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000), + HRTIMER_MODE_REL); + + return HRTIMER_NORESTART; +} + +static irqreturn_t gtp_irq_handler(int irq, void *dev_id) +{ + struct goodix_ts_data *ts = dev_id; + + gtp_work_func(ts); + return IRQ_HANDLED; +} + +void gtp_int_output(struct goodix_ts_data *ts, int level) +{ + if (!ts->pdata->int_sync) + return; + + if (level == 0) { + if (ts->pinctrl.pinctrl) + pinctrl_select_state(ts->pinctrl.pinctrl, + ts->pinctrl.int_out_low); + else if (gpio_is_valid(ts->pdata->irq_gpio)) + gpio_direction_output(ts->pdata->irq_gpio, 0); + else + dev_err(&ts->client->dev, + "Failed set int pin output low\n"); + } else { + if (ts->pinctrl.pinctrl) + pinctrl_select_state(ts->pinctrl.pinctrl, + ts->pinctrl.int_out_high); + else if (gpio_is_valid(ts->pdata->irq_gpio)) + gpio_direction_output(ts->pdata->irq_gpio, 1); + else + dev_err(&ts->client->dev, + "Failed set int pin output high\n"); + } +} + +void gtp_int_sync(struct goodix_ts_data *ts, s32 ms) +{ + if (!ts->pdata->int_sync) + return; + + if (ts->pinctrl.pinctrl) { + gtp_int_output(ts, 0); + msleep(ms); + pinctrl_select_state(ts->pinctrl.pinctrl, + ts->pinctrl.int_input); + } else if (gpio_is_valid(ts->pdata->irq_gpio)) { + gpio_direction_output(ts->pdata->irq_gpio, 0); + msleep(ms); + gpio_direction_input(ts->pdata->irq_gpio); + } else { + dev_err(&ts->client->dev, "Failed sync int pin\n"); + } +} + +/******************************************************* + * Function: + * Reset chip. Control the reset pin and int-pin(if + * defined), + * Input: + * client: i2c device. + * ms: reset time in millisecond + * Output: + * None. + *******************************************************/ +void gtp_reset_guitar(struct i2c_client *client, s32 ms) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + dev_info(&client->dev,"%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + dev_info(&client->dev, "Guitar reset"); + set_bit(PANEL_RESETTING, &ts->flags); + if (!gpio_is_valid(ts->pdata->rst_gpio)) { + dev_warn(&client->dev, "reset failed no valid reset gpio"); + return; + } + + gpio_direction_output(ts->pdata->rst_gpio, 0); + usleep_range(ms * 1000, ms * 1000 + 100); /* T2: > 10ms */ + + gtp_int_output(ts, client->addr == 0x14); + + usleep_range(2000, 3000); /* T3: > 100us (2ms)*/ + gpio_direction_output(ts->pdata->rst_gpio, 1); + + usleep_range(6000, 7000); /* T4: > 5ms */ + + gtp_int_sync(ts, 50); + if (ts->pdata->esd_protect) + gtp_init_ext_watchdog(client); + + clear_bit(PANEL_RESETTING, &ts->flags); + + dev_info(&client->dev,"%s:Exit FUNC ---- %d\n",__func__,__LINE__); +} + +/******************************************************* + * Function: + * Enter doze mode for sliding wakeup. + * Input: + * ts: goodix tp private data + * Output: + * 1: succeed, otherwise failed + *******************************************************/ +static int gtp_enter_doze(struct goodix_ts_data *ts) +{ + int ret = -1; + int retry = 0; + u8 i2c_control_buf[3] = { (u8)(GTP_REG_COMMAND >> 8), + (u8)GTP_REG_COMMAND, 8 }; + + /* resend doze command + * if (test_and_set_bit(DOZE_MODE, &ts->flags)) { + * dev_info(&ts->client->dev, "Already in doze mode\n"); + * return SUCCESS; + * } + */ + set_bit(DOZE_MODE, &ts->flags); + dev_dbg(&ts->client->dev, "Entering gesture mode."); + while (retry++ < 5) { + i2c_control_buf[0] = (u8)(GTP_REG_COMMAND_CHECK >> 8); + i2c_control_buf[1] = (u8)GTP_REG_COMMAND_CHECK; + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret < 0) { + dev_dbg(&ts->client->dev, + "failed to set doze flag into 0x8046, %d\n", + retry); + continue; + } + i2c_control_buf[0] = (u8)(GTP_REG_COMMAND >> 8); + i2c_control_buf[1] = (u8)GTP_REG_COMMAND; + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret > 0) { + dev_dbg(&ts->client->dev, "Gesture mode enabled\n"); + return ret; + } + usleep_range(10000, 11000); + } + + dev_err(&ts->client->dev, "Failed enter doze mode\n"); + clear_bit(DOZE_MODE, &ts->flags); + return ret; +} + +static s8 gtp_enter_sleep(struct goodix_ts_data *ts) +{ + s8 ret = -1; + s8 retry = 0; + u8 i2c_control_buf[3] = { (u8)(GTP_REG_COMMAND >> 8), + (u8)GTP_REG_COMMAND, 5 }; + + gtp_int_output(ts, 0); + usleep_range(5000, 6000); + + while (retry++ < 5) { + ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); + if (ret > 0) { + dev_info(&ts->client->dev, "Enter sleep mode\n"); + + return ret; + } + usleep_range(10000, 11000); + } + dev_err(&ts->client->dev, "Failed send sleep cmd\n"); + + return ret; +} + +static int gtp_wakeup_sleep(struct goodix_ts_data *ts) +{ + u8 retry = 0; + int ret = -1; + + while (retry++ < 10) { + gtp_reset_guitar(ts->client, 20); + + ret = gtp_i2c_test(ts->client); + if (!ret) { + dev_dbg(&ts->client->dev, "Success wakeup sleep\n"); + return ret; + } + } + + dev_err(&ts->client->dev, "Failed wakeup from sleep mode\n"); + return -EINVAL; +} + +static int gtp_find_valid_cfg_data(struct goodix_ts_data *ts) +{ + int ret = -1; + u8 sensor_id = 0; + struct goodix_config_data *cfg = &ts->pdata->config; + + /* if defined CONFIG_OF, parse config data from dtsi + * else parse config data form header file. + */ + cfg->length = 0; + +#ifndef CONFIG_OF + u8 cfg_info_group0[] = CTP_CFG_GROUP0; + u8 cfg_info_group1[] = CTP_CFG_GROUP1; + u8 cfg_info_group2[] = CTP_CFG_GROUP2; + u8 cfg_info_group3[] = CTP_CFG_GROUP3; + u8 cfg_info_group4[] = CTP_CFG_GROUP4; + u8 cfg_info_group5[] = CTP_CFG_GROUP5; + + u8 *send_cfg_buf[] = { cfg_info_group0, cfg_info_group1, + cfg_info_group2, cfg_info_group3, + cfg_info_group4, cfg_info_group5 }; + u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group0), + CFG_GROUP_LEN(cfg_info_group1), + CFG_GROUP_LEN(cfg_info_group2), + CFG_GROUP_LEN(cfg_info_group3), + CFG_GROUP_LEN(cfg_info_group4), + CFG_GROUP_LEN(cfg_info_group5)}; + + dev_dbg(&ts->client->dev, + "Config Groups\' Lengths: %d, %d, %d, %d, %d, %d", + cfg_info_len[0], cfg_info_len[1], cfg_info_len[2], + cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]); +#endif + + /* read sensor id */ + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, + &sensor_id, 1); + if (SUCCESS != ret || sensor_id >= 0x06) { + dev_err(&ts->client->dev, + "Failed get valid sensor_id(0x%02X), No Config Sent\n", + sensor_id); + return -EINVAL; + } + + dev_dbg(&ts->client->dev, "Sensor_ID: %d", sensor_id); + dev_err(&ts->client->dev, "Sensor_ID: %d", sensor_id); + /* parse config data */ +#ifdef CONFIG_OF + dev_dbg(&ts->client->dev, "Get config data from device tree\n"); + ret = gtp_parse_dt_cfg(&ts->client->dev, + &cfg->data[GTP_ADDR_LENGTH], + &cfg->length, sensor_id); + if (ret < 0) { + dev_err(&ts->client->dev, + "Failed to parse config data form device tree\n"); + cfg->length = 0; + return -EPERM; + } +#else + dev_dbg(&ts->client->dev, "Get config data from header file\n"); + if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && + (!cfg_info_len[3]) && (!cfg_info_len[4]) && + (!cfg_info_len[5])) { + sensor_id = 0; + } + cfg->length = cfg_info_len[sensor_id]; + memset(&cfg->data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); + memcpy(&cfg->data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], + cfg->length); +#endif + + if (cfg->length < GTP_CONFIG_MIN_LENGTH) { + dev_err(&ts->client->dev, + "Failed get valid config data with sensor id %d\n", + sensor_id); + cfg->length = 0; + return -EPERM; + } + + dev_info(&ts->client->dev, "Config group%d used,length: %d\n", + sensor_id, cfg->length); + + return 0; +} + +/******************************************************* + * Function: + * Get valid config data from dts or .h file. + * Read firmware version info and judge firmware + * working state + * Input: + * ts: goodix private data + * Output: + * Executive outcomes. + * 0: succeed, otherwise: failed + *******************************************************/ +static s32 gtp_init_panel(struct goodix_ts_data *ts) +{ + s32 ret = -1; + u8 opr_buf[16] = {0}; + u8 drv_cfg_version = 0; + u8 flash_cfg_version = 0; + struct goodix_config_data *cfg = &ts->pdata->config; + + if (!ts->pdata->driver_send_cfg) { + dev_info(&ts->client->dev, "Driver set not send config\n"); + cfg->length = GTP_CONFIG_MAX_LENGTH; + ret = gtp_i2c_read(ts->client, + cfg->data, cfg->length + + GTP_ADDR_LENGTH); + if (ret < 0) + dev_err(&ts->client->dev, "Read origin Config Failed\n"); + + return 0; + } + + gtp_find_valid_cfg_data(ts); + + /* check firmware */ + ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1); + if (SUCCESS == ret) { + if (opr_buf[0] != 0xBE) { + set_bit(FW_ERROR, &ts->flags); + dev_err(&ts->client->dev, + "Firmware error, no config sent!\n"); + return -EINVAL; + } + } + + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, + &opr_buf[0], 1); + if (ret == SUCCESS) { + dev_dbg(&ts->client->dev, + "Config Version: %d; IC Config Version: %d\n", + cfg->data[GTP_ADDR_LENGTH], opr_buf[0]); + flash_cfg_version = opr_buf[0]; + drv_cfg_version = cfg->data[GTP_ADDR_LENGTH]; + + if (flash_cfg_version < 90 && + flash_cfg_version > drv_cfg_version) + cfg->data[GTP_ADDR_LENGTH] = 0x00; + } else { + dev_err(&ts->client->dev, + "Failed to get ic config version!No config sent\n"); + return -EPERM; + } + + ret = gtp_send_cfg(ts->client); + if (ret < 0) + dev_err(&ts->client->dev, "Send config error\n"); + else + usleep_range(10000, 11000); /* 10 ms */ + + /* restore config version */ + cfg->data[GTP_ADDR_LENGTH] = drv_cfg_version; + + return 0; +} + +static ssize_t gtp_config_read_proc(struct file *file, char __user *page, + size_t size, loff_t *ppos) +{ + int i, ret; + char *ptr; + size_t data_len = 0; + char temp_data[GTP_CONFIG_MAX_LENGTH + 2] = { + (u8)(GTP_REG_CONFIG_DATA >> 8), + (u8)GTP_REG_CONFIG_DATA }; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + struct goodix_config_data *cfg = &ts->pdata->config; + + ptr = kzalloc(4096, GFP_KERNEL); + if (!ptr) { + dev_err(&ts->client->dev, "Failed alloc memory for config\n"); + return -ENOMEM; + } + + data_len += snprintf(ptr + data_len, 4096 - data_len, + "====init value====\n"); + for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++) { + data_len += snprintf(ptr + data_len, 4096 - data_len, + "0x%02X ", cfg->data[i + 2]); + + if (i % 8 == 7) + data_len += snprintf(ptr + data_len, + 4096 - data_len, "\n"); + } + data_len += snprintf(ptr + data_len, 4096 - data_len, "\n"); + + data_len += snprintf(ptr + data_len, 4096 - data_len, + "====real value====\n"); + ret = gtp_i2c_read(i2c_connect_client, temp_data, + GTP_CONFIG_MAX_LENGTH + 2); + if (ret < 0) { + data_len += snprintf(ptr + data_len, 4096 - data_len, + "Failed read real config data\n"); + } else { + for (i = 0; i < GTP_CONFIG_MAX_LENGTH; i++) { + data_len += snprintf(ptr + data_len, 4096 - data_len, + "0x%02X ", temp_data[i + 2]); + + if (i % 8 == 7) + data_len += snprintf(ptr + data_len, + 4096 - data_len, "\n"); + } + } + + data_len = simple_read_from_buffer(page, size, ppos, ptr, data_len); + kfree(ptr); + ptr = NULL; + return data_len; +} + +static u8 ascii2hex(u8 a) +{ + s8 value = 0; + + if (a >= '0' && a <= '9') + value = a - '0'; + else if (a >= 'A' && a <= 'F') + value = a - 'A' + 0x0A; + else if (a >= 'a' && a <= 'f') + value = a - 'a' + 0x0A; + else + value = 0xff; + + return value; +} + +int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf) +{ + int i, ret; + int cfg_len = 0; + u8 high, low; + + for (i = 0; i < src_len;) { + if (src_buf[i] == ' ' || src_buf[i] == '\r' || + src_buf[i] == '\n') { + i++; + continue; + } + + if ((src_buf[i] == '0') && ((src_buf[i + 1] == 'x') || + (src_buf[i + 1] == 'X'))) { + high = ascii2hex(src_buf[i + 2]); + low = ascii2hex(src_buf[i + 3]); + + if ((high == 0xFF) || (low == 0xFF)) { + ret = -1; + goto convert_failed; + } + + if (cfg_len < GTP_CONFIG_MAX_LENGTH) { + dst_buf[cfg_len++] = (high << 4) + low; + i += 5; + } else { + ret = -2; + goto convert_failed; + } + } else { + ret = -3; + goto convert_failed; + } + } + return cfg_len; + +convert_failed: + return ret; +} + +static ssize_t gtp_config_write_proc(struct file *filp, + const char __user *buffer, + size_t count, loff_t *off) +{ + u8 *temp_buf; + u8 *file_config; + int file_cfg_len; + s32 ret = 0, i; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + dev_info(&ts->client->dev, "write count %zu\n", count); + + if (count > PAGE_SIZE) { + dev_err(&ts->client->dev, "config to long %zu\n", count); + return -EFAULT; + } + + temp_buf = kzalloc(count, GFP_KERNEL); + if (!temp_buf) { + dev_err(&ts->client->dev, "failed alloc temp memory"); + return -ENOMEM; + } + + file_config = kzalloc(GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, + GFP_KERNEL); + if (!file_config) { + dev_err(&ts->client->dev, "failed alloc config memory"); + kfree(temp_buf); + return -ENOMEM; + } + file_config[0] = GTP_REG_CONFIG_DATA >> 8; + file_config[1] = GTP_REG_CONFIG_DATA & 0xff; + + if (copy_from_user(temp_buf, buffer, count)) { + dev_err(&ts->client->dev, "Failed copy from user\n"); + ret = -EFAULT; + goto send_cfg_err; + } + + file_cfg_len = gtp_ascii_to_array(temp_buf, (int)count, + &file_config[GTP_ADDR_LENGTH]); + if (file_cfg_len < 0) { + dev_err(&ts->client->dev, "failed covert ascii to hex"); + ret = -EFAULT; + goto send_cfg_err; + } + + GTP_DEBUG_ARRAY(file_config + GTP_ADDR_LENGTH, file_cfg_len); + + i = 0; + while (i++ < 5) { + ret = gtp_i2c_write(ts->client, file_config, file_cfg_len + 2); + if (ret > 0) { + dev_info(&ts->client->dev, "Send config SUCCESS."); + break; + } + dev_err(&ts->client->dev, "Send config i2c error."); + ret = -EFAULT; + goto send_cfg_err; + } + + ret = count; +send_cfg_err: + kfree(temp_buf); + kfree(file_config); + return ret; +} + +static const struct file_operations config_proc_ops = { + .owner = THIS_MODULE, + .read = gtp_config_read_proc, + .write = gtp_config_write_proc, +}; + +static ssize_t gtp_workmode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t data_len = 0; + struct goodix_ts_data *data = dev_get_drvdata(dev); + + if (test_bit(DOZE_MODE, &data->flags)) + data_len = scnprintf(buf, PAGE_SIZE, "%s\n", + "doze_mode"); + else if (test_bit(SLEEP_MODE, &data->flags)) + data_len = scnprintf(buf, PAGE_SIZE, "%s\n", + "sleep_mode"); + else + data_len = scnprintf(buf, PAGE_SIZE, "%s\n", + "normal_mode"); + + return data_len; +} +static DEVICE_ATTR(workmode, 0444, gtp_workmode_show, NULL); + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE +#define FW_NAME_MAX_LEN 80 +static ssize_t gtp_dofwupdate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct goodix_ts_data *ts = dev_get_drvdata(dev); + char update_file_name[FW_NAME_MAX_LEN]; + int retval; + + if (count > FW_NAME_MAX_LEN) { + dev_info(&ts->client->dev, "FW filename is too long\n"); + retval = -EINVAL; + goto exit; + } + + strlcpy(update_file_name, buf, count); + + ts->force_update = true; + retval = gup_update_proc(update_file_name); + if (retval == FAIL) + dev_err(&ts->client->dev, "Fail to update GTP firmware.\n"); + else + dev_info(&ts->client->dev, "Update success\n"); + + return count; + +exit: + return retval; +} +static DEVICE_ATTR(dofwupdate, 0664, NULL, gtp_dofwupdate_store); +#endif + +static ssize_t gtp_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct goodix_ts_data *data = dev_get_drvdata(dev); + struct goodix_fw_info *fw_info = &data->fw_info; + + return scnprintf(buf, PAGE_SIZE, "GT%s_%x_%d\n", + fw_info->pid, fw_info->version, fw_info->sensor_id); +} +static DEVICE_ATTR(productinfo, 0444, gtp_productinfo_show, NULL); + +static ssize_t gtp_drv_irq_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long value = 0; + int err = 0; + struct goodix_ts_data *data = dev_get_drvdata(dev); + + err = kstrtoul(buf, 10, &value); + if (err < 0) { + dev_err(dev, "Failed to convert value\n"); + return -EINVAL; + } + + switch (value) { + case 0: + /* Disable irq */ + gtp_work_control_enable(data, false); + break; + case 1: + /* Enable irq */ + gtp_work_control_enable(data, true); + break; + default: + dev_err(dev, "Invalid value\n"); + return -EINVAL; + } + + return count; +} + +static ssize_t gtp_drv_irq_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct goodix_ts_data *data = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", + test_bit(WORK_THREAD_ENABLED, &data->flags) + ? "enabled" : "disabled"); +} +static DEVICE_ATTR(drv_irq, 0664, gtp_drv_irq_show, gtp_drv_irq_store); + +static ssize_t gtp_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct goodix_ts_data *data = dev_get_drvdata(dev); + + if ('1' != buf[0]) { + dev_err(dev, "Invalid argument for reset\n"); + return -EINVAL; + } + + gtp_reset_guitar(data->client, 20); + + return count; +} +static DEVICE_ATTR(reset, 0220, NULL, gtp_reset_store); + +static struct attribute *gtp_attrs[] = { + &dev_attr_workmode.attr, + &dev_attr_productinfo.attr, + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE + &dev_attr_dofwupdate.attr, +#endif + + &dev_attr_drv_irq.attr, + &dev_attr_reset.attr, + NULL +}; + +static const struct attribute_group gtp_attr_group = { + .attrs = gtp_attrs, +}; + +static int gtp_create_file(struct goodix_ts_data *ts) +{ + int ret; + struct i2c_client *client = ts->client; + + /* Create proc file system */ + gtp_config_proc = NULL; + gtp_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0664, + NULL, &config_proc_ops); + if (!gtp_config_proc) + dev_err(&client->dev, "create_proc_entry %s failed\n", + GT91XX_CONFIG_PROC_FILE); + else + dev_info(&client->dev, "create proc entry %s success\n", + GT91XX_CONFIG_PROC_FILE); + + ret = sysfs_create_group(&client->dev.kobj, >p_attr_group); + if (ret) { + dev_err(&client->dev, "Failure create sysfs group %d\n", ret); + /*TODO: debug change */ + goto exit_free_config_proc; + } + return 0; + +exit_free_config_proc: + remove_proc_entry(GT91XX_CONFIG_PROC_FILE, gtp_config_proc); + return -ENODEV; +} + +s32 gtp_get_fw_info(struct i2c_client *client, struct goodix_fw_info *fw_info) +{ + s32 ret = -1; + u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff}; + u8 buf2[3] = {GTP_READ_CFG_VER >> 8, GTP_READ_CFG_VER & 0xff}; + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) { + dev_err(&client->dev, "Failed read fw_info\n"); + return ret; + } + + /* product id */ + memset(fw_info, 0, sizeof(*fw_info)); + + if (buf[5] == 0x00) { + memcpy(fw_info->pid, buf + GTP_ADDR_LENGTH, 3); + dev_info(&client->dev, "IC Version: %c%c%c_%02X%02X\n", + buf[2], buf[3], buf[4], buf[7], buf[6]); + } else { + memcpy(fw_info->pid, buf + GTP_ADDR_LENGTH, 4); + dev_info(&client->dev, "IC Version: %c%c%c%c_%02X%02X\n", + buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]); + } + + /* current firmware version */ + fw_info->version = (buf[7] << 8) | buf[6]; + + /* read sensor id */ + fw_info->sensor_id = 0xff; + ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, + &fw_info->sensor_id, 1); + if (SUCCESS != ret || fw_info->sensor_id >= 0x06) { + dev_err(&client->dev, + "Failed get valid sensor_id(0x%02X), No Config Sent\n", + fw_info->sensor_id); + + fw_info->sensor_id = 0xff; + } + + /*Add by HQ-zmc [Date: 2018-03-03 17:32:03] + Read cfg version here + */ + ret = gtp_i2c_read(client, buf2, sizeof(buf2)); + if (ret < 0) { + dev_err(&client->dev, "Failed read cfg_info\n"); + return ret; + } + dev_info(&client->dev,"%x,%x,%x\n",buf2[0],buf2[1],buf2[2]); + fw_info->cfg_ver = buf2[2]; + + return ret; +} + +int gtp_i2c_test(struct i2c_client *client) +{ + u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff}; + u8 retry = 0; + int ret = -1; + + while (retry++ < 3) { + ret = gtp_i2c_read(client, test, 3); + if (ret == 2) + return 0; + + dev_err(&client->dev, "GTP i2c test failed time %d\n", retry); + usleep_range(10000, 11000); /* 10 ms */ + } + + return -EAGAIN; +} + +static int gtp_pinctrl_init(struct goodix_ts_data *ts) +{ + struct goodix_pinctrl *pinctrl = &ts->pinctrl; + + dev_info(&ts->client->dev,"%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + pinctrl->pinctrl = devm_pinctrl_get(&ts->client->dev); + if (IS_ERR_OR_NULL(pinctrl->pinctrl)) { + dev_info(&ts->client->dev, "No pinctrl found\n"); + pinctrl->pinctrl = NULL; + return 0; + } + + pinctrl->default_sta = pinctrl_lookup_state(pinctrl->pinctrl, + "default"); + if (IS_ERR_OR_NULL(pinctrl->default_sta)) { + dev_info(&ts->client->dev, + "Failed get pinctrl state:default state\n"); + goto exit_pinctrl_init; + } + + pinctrl->int_out_high = pinctrl_lookup_state(pinctrl->pinctrl, + "int-output-high"); + if (IS_ERR_OR_NULL(pinctrl->int_out_high)) { + dev_info(&ts->client->dev, + "Failed get pinctrl state:output_high\n"); + goto exit_pinctrl_init; + } + + pinctrl->int_out_low = pinctrl_lookup_state(pinctrl->pinctrl, + "int-output-low"); + if (IS_ERR_OR_NULL(pinctrl->int_out_low)) { + dev_info(&ts->client->dev, + "Failed get pinctrl state:output_low\n"); + goto exit_pinctrl_init; + } + + pinctrl->int_input = pinctrl_lookup_state(pinctrl->pinctrl, + "int-input"); + if (IS_ERR_OR_NULL(pinctrl->int_input)) { + dev_info(&ts->client->dev, + "Failed get pinctrl state:int-input\n"); + goto exit_pinctrl_init; + } + dev_info(&ts->client->dev, "Success init pinctrl\n"); + return 0; +exit_pinctrl_init: + devm_pinctrl_put(pinctrl->pinctrl); + pinctrl->pinctrl = NULL; + pinctrl->int_out_high = NULL; + pinctrl->int_out_low = NULL; + pinctrl->int_input = NULL; + return 0; +} + +static void gtp_pinctrl_deinit(struct goodix_ts_data *ts) +{ + if (ts->pinctrl.pinctrl) + devm_pinctrl_put(ts->pinctrl.pinctrl); +} + +static int gtp_request_io_port(struct goodix_ts_data *ts) +{ + int ret = 0; + + dev_info(&ts->client->dev,"%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + if (gpio_is_valid(ts->pdata->irq_gpio)) { + ret = gpio_request(ts->pdata->irq_gpio, "goodix_ts_int"); + if (ret < 0) { + dev_err(&ts->client->dev, + "Failed to request GPIO:%d, ERRNO:%d\n", + (s32)ts->pdata->irq_gpio, ret); + return -ENODEV; + } + + gpio_direction_input(ts->pdata->irq_gpio); + dev_info(&ts->client->dev, "Success request irq-gpio\n"); + } + + if (gpio_is_valid(ts->pdata->rst_gpio)) { + ret = gpio_request(ts->pdata->rst_gpio, "goodix_ts_rst"); + if (ret < 0) { + dev_err(&ts->client->dev, + "Failed to request GPIO:%d, ERRNO:%d\n", + (s32)ts->pdata->rst_gpio, ret); + + if (gpio_is_valid(ts->pdata->irq_gpio)) + gpio_free(ts->pdata->irq_gpio); + + return -ENODEV; + } + + gpio_direction_input(ts->pdata->rst_gpio); + dev_info(&ts->client->dev, "Success request rst-gpio\n"); + } + + return 0; +} + + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-01-18 19:04:43 + * @func: get_lockdown_info + * ============================ + */ + +int gtp_read_Color(struct i2c_client *client,struct goodix_ts_data *ts) +{ + int ret = -1; + u8 buf[10] = {0} ; + u8 esd_buf[5]={0x42,0x26}; + char *page = NULL; + char * temp= NULL; + + buf[0] =GTP_REG_COLOR_GT917 >> 8 ; + buf[1] = GTP_REG_COLOR_GT917& 0xff; + + page = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!page) { + kfree(page); + return -ENOMEM; + } + + temp = page; + GTP_DEBUG_FUNC(); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) + { + dev_err(&ts->client->dev,"GTP read color failed"); + return ret; + } + + if((buf[2]!=0x31)||(buf[3]!=0x37)) + { + dev_err(&ts->client->dev,"IC lockdown info error!buf[2] = %02x,buf[3] = %02x, Process reset guitar.",buf[2],buf[3]); + esd_buf[0] = 0x42; + esd_buf[1] = 0x26; + esd_buf[2] = 0x01; + esd_buf[3] = 0x01; + esd_buf[4] = 0x01; + gtp_i2c_write_no_rst(client, esd_buf, 5); + msleep(GTP_50_DLY_MS); + gtp_power_off(ts); + msleep(GTP_20_DLY_MS); + gtp_power_on(ts); + msleep(GTP_20_DLY_MS); + gtp_reset_guitar(client, 50); + msleep(GTP_50_DLY_MS); + gtp_send_cfg(client); + msleep(GTP_20_DLY_MS); + + ret = gtp_i2c_read(client, buf, sizeof(buf)); + if (ret < 0) + { + dev_err(&ts->client->dev,"GTP read color failed"); + return ret; + } + } + sprintf(temp,"%02x%02x%02x%02x%02x%02x%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[6],buf[7],buf[8],buf[9]); + dev_err(&ts->client->dev,"Color : %s\n",temp ); + strcpy(tp_lockdown_info,temp); + + return ret; +} + +static int gtp_lockdown_proc_show(struct seq_file *file, void* data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int gtp_lockdown_proc_open (struct inode* inode, struct file* file) +{ + return single_open(file, gtp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations lockdown_proc_ops = { + .owner = THIS_MODULE, + .open = gtp_lockdown_proc_open, + .read = seq_read, +}; + + +int gt_create_lockdown_proc(struct i2c_client *client,struct goodix_ts_data *ts){ + int ret = 0; + + ret = gtp_read_Color(client,ts); + if (ret < 0) + { + dev_err(&ts->client->dev,"GTP read color failed"); + return ret; + } + + gtp_locdown_proc = proc_create(GT9XX_LOCKDOWN_PROC_FILE, 0444, + NULL, &lockdown_proc_ops); + if (!gtp_locdown_proc) + dev_err(&client->dev, "create_proc_entry %s failed\n", + GT9XX_LOCKDOWN_PROC_FILE); + else + dev_info(&client->dev, "create proc entry %s success\n", + GT9XX_LOCKDOWN_PROC_FILE); + return ret; +} + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-01-18 19:48:18 + * @func: get fw info + * ============================ + */ +void ctp_vendor_info(struct i2c_client *client, struct goodix_fw_info *gt_fw_info){ + struct goodix_fw_info *fw_info = gt_fw_info; + char temp[10]; + + if(fw_info->sensor_id == 0) + { + strcpy(tp_info_summary,"[Vendor]Biel(TP) + EBBG(LCD), [TP-IC]GT917D,[FW]Ver"); + } + if(fw_info->sensor_id == 1) + { + strcpy(tp_info_summary,"[Vendor]xxx(TP) + xxx(LCD), [TP-IC]xxx,[FW]Ver"); + } + sprintf(temp,"%x,[CFG]Ver0x",fw_info->version); + strcat(tp_info_summary,temp); + sprintf(temp,"%x",fw_info->cfg_ver); + strcat(tp_info_summary,temp); + strcat(tp_info_summary,"\0"); + hq_regiser_hw_info(HWID_CTP,tp_info_summary); +} + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-02-01 17:23:49 + * @input: + * @output: + * ============================ + */ +static ssize_t gtp_wakeup_gesture_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + char mode = -1; + + if (count > 0) { + if (get_user(mode, buffer)) + return -EFAULT; + if(mode == '1') + GTP_gesture_func_on = true; + else + GTP_gesture_func_on = false; + } + + return count; +} + +static int gtp_wakeup_gesture_show(struct seq_file *file, void* data) +{ + + seq_printf(file, "%c\n", GTP_gesture_func_on?'1':'0'); + + return 0; +} + +static int gtp_wakeup_gesture_open (struct inode* inode, struct file* file) +{ + return single_open(file, gtp_wakeup_gesture_show, NULL); +} + +static const struct file_operations wakeup_gesture_ops = { + .owner = THIS_MODULE, + .open = gtp_wakeup_gesture_open, + .read = seq_read, + .write = gtp_wakeup_gesture_write, +}; + + +int gtp_create_wakeup_gesture_proc(struct i2c_client *client,struct goodix_ts_data *ts){ + int ret = 0; + + gtp_wakeup_gesture_proc = proc_create(GT9XX_WAKEUP_GESTURE_PROC, 0666, + NULL, &wakeup_gesture_ops); + if (!gtp_wakeup_gesture_proc) + dev_err(&client->dev, "create_proc_entry %s failed\n", + GT9XX_WAKEUP_GESTURE_PROC); + else + dev_info(&client->dev, "create proc entry %s success\n", + GT9XX_WAKEUP_GESTURE_PROC); + return ret; +} + +/******************************************************* + * Function: + * Request interrupt if define irq pin, else use hrtimer + * as interrupt source + * Input: + * ts: private data. + * Output: + * Executive outcomes. + * 0: succeed, -1: failed. + *******************************************************/ +static int gtp_request_irq(struct goodix_ts_data *ts) +{ + int ret = -1; + + /* use irq */ + if (gpio_is_valid(ts->pdata->irq_gpio) || ts->client->irq > 0) { + if (gpio_is_valid(ts->pdata->irq_gpio)) + ts->client->irq = gpio_to_irq(ts->pdata->irq_gpio); + + dev_info(&ts->client->dev, "INT num %d, trigger type:%d\n", + ts->client->irq, ts->pdata->irq_flags); + ret = request_threaded_irq(ts->client->irq, NULL, + gtp_irq_handler, + ts->pdata->irq_flags | IRQF_ONESHOT, + ts->client->name, + ts); + if (ret < 0) { + dev_err(&ts->client->dev, + "Failed to request irq %d\n", ts->client->irq); + return ret; + } + } else { /* use hrtimer */ + dev_info(&ts->client->dev, "No hardware irq, use hrtimer\n"); + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = gtp_timer_handler; + hrtimer_start(&ts->timer, + ktime_set(0, (GTP_POLL_TIME + 6) * 1000000), + HRTIMER_MODE_REL); + set_bit(HRTIMER_USED, &ts->flags); + ret = 0; + } + return ret; +} + +static s8 gtp_request_input_dev(struct goodix_ts_data *ts) +{ + s8 ret = -1; + u8 index = 0; + + ts->input_dev = input_allocate_device(); + if (!ts->input_dev) { + dev_err(&ts->client->dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) + | BIT_MASK(EV_ABS); + if (!ts->pdata->type_a_report) { + input_mt_init_slots(ts->input_dev, 16, INPUT_MT_DIRECT); + dev_info(&ts->client->dev, "Use slot report protocol\n"); + } else { + __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); + __set_bit(BTN_TOUCH, ts->input_dev->keybit); + dev_info(&ts->client->dev, "Use type A report protocol\n"); + } + + input_set_capability(ts->input_dev, EV_KEY, GTP_PEN_BUTTON1); + input_set_capability(ts->input_dev, EV_KEY, GTP_PEN_BUTTON2); + + /* touch key register */ + for (index = 0; index < ts->pdata->key_nums; index++) + input_set_capability(ts->input_dev, EV_KEY, + ts->pdata->key_map[index]); + + if (ts->pdata->slide_wakeup) + input_set_capability(ts->input_dev, EV_KEY, KEY_WAKEUP); + + if (ts->pdata->swap_x2y) + GTP_SWAP(ts->pdata->abs_size_x, ts->pdata->abs_size_y); + + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, + ts->pdata->abs_size_x, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, + ts->pdata->abs_size_y, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, + ts->pdata->max_touch_width, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, + ts->pdata->max_touch_pressure, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, + ts->pdata->max_touch_id, 0, 0); + if (!ts->pdata->type_a_report) { + input_set_abs_params(ts->input_dev, ABS_MT_TOOL_TYPE, + 0, MT_TOOL_FINGER, 0, 0); + } else { + __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit); + __set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit); + } + + ts->input_dev->event = gtp_gesture_switch; + + ts->input_dev->name = goodix_ts_name; + ts->input_dev->phys = goodix_input_phys; + ts->input_dev->id.bustype = BUS_I2C; + ts->input_dev->id.vendor = 0xDEAD; + ts->input_dev->id.product = 0xBEEF; + ts->input_dev->id.version = 10427; + + ret = input_register_device(ts->input_dev); + if (ret) { + dev_err(&ts->client->dev, "Register %s input device failed\n", + ts->input_dev->name); + input_free_device(ts->input_dev); + return -ENODEV; + } + + return 0; +} + +/* + * Devices Tree support + */ +#ifdef CONFIG_OF +static void gtp_parse_dt_coords(struct device *dev, + struct goodix_ts_platform_data *pdata) +{ + struct device_node *np = dev->of_node; + int ret; + + ret = of_property_read_u32(np, "touchscreen-max-id", + &pdata->max_touch_id); + if (ret || pdata->max_touch_id > GTP_MAX_TOUCH_ID) { + dev_info(dev, "Unset touchscreen-max-id, use default\n"); + pdata->max_touch_id = GTP_MAX_TOUCH_ID; + } + + ret = of_property_read_u32(np, "touchscreen-size-x", + &pdata->abs_size_x); + if (ret) { + dev_info(dev, "Unset touchscreen-size-x, use default\n"); + pdata->abs_size_x = GTP_DEFAULT_MAX_X; + } + + ret = of_property_read_u32(np, "touchscreen-size-y", + &pdata->abs_size_y); + if (ret) { + dev_info(dev, "Unset touchscreen-size-y, use default\n"); + pdata->abs_size_y = GTP_DEFAULT_MAX_Y; + } + + ret = of_property_read_u32(np, "touchscreen-max-w", + &pdata->max_touch_width); + if (ret) { + dev_info(dev, "Unset touchscreen-max-w, use default\n"); + pdata->max_touch_width = GTP_DEFAULT_MAX_WIDTH; + } + + ret = of_property_read_u32(np, "touchscreen-max-p", + &pdata->max_touch_pressure); + if (ret) { + dev_info(dev, "Unset touchscreen-max-p, use default\n"); + pdata->max_touch_pressure = GTP_DEFAULT_MAX_PRESSURE; + } + dev_info(dev, "touch input parameters is [id x y w p]<%d %d %d %d %d>\n", + pdata->max_touch_id, pdata->abs_size_x, pdata->abs_size_y, + pdata->max_touch_width, pdata->max_touch_pressure); +} + +static int gtp_parse_dt(struct device *dev, + struct goodix_ts_platform_data *pdata) +{ + int ret; + u32 key_nums; + struct property *prop; + u32 key_map[MAX_KEY_NUMS]; + struct device_node *np = dev->of_node; + + gtp_parse_dt_coords(dev, pdata); + + ret = of_property_read_u32(np, "irq-flags", + &pdata->irq_flags); + if (ret) { + dev_info(dev, + "Failed get int-trigger-type from dts,set default\n"); + pdata->irq_flags = GTP_DEFAULT_INT_TRIGGER; + } + of_property_read_u32(np, "goodix,int-sync", &pdata->int_sync); + if (pdata->int_sync) + dev_info(dev, "int-sync enabled\n"); + + of_property_read_u32(np, "goodix,driver-send-cfg", + &pdata->driver_send_cfg); + if (pdata->driver_send_cfg) + dev_info(dev, "driver-send-cfg enabled\n"); + + of_property_read_u32(np, "goodix,swap-x2y", &pdata->swap_x2y); + if (pdata->swap_x2y) + dev_info(dev, "swap-x2y enabled\n"); + + of_property_read_u32(np, "goodix,slide-wakeup", &pdata->slide_wakeup); + if (pdata->slide_wakeup) + dev_info(dev, "slide-wakeup enabled\n"); + + of_property_read_u32(np, "goodix,auto-update", &pdata->auto_update); + if (pdata->auto_update) + dev_info(dev, "auto-update enabled\n"); + + of_property_read_u32(np, "goodix,auto-update-cfg", + &pdata->auto_update_cfg); + if (pdata->auto_update_cfg) + dev_info(dev, "auto-update-cfg enabled\n"); + + of_property_read_u32(np, "goodix,esd-protect", &pdata->esd_protect); + if (pdata->esd_protect) + dev_info(dev, "esd-protect enabled\n"); + +#if GTP_CHARGER_SWITCH + of_property_read_u32(np, "goodix,charger-cmd", &pdata->charger_cmd); + if (pdata->charger_cmd) + dev_info(dev, "charge switch enabled\n"); +#endif + + of_property_read_u32(np, "goodix,type-a-report", + &pdata->type_a_report); + if (pdata->type_a_report) + dev_info(dev, "type-a-report enabled\n"); + + of_property_read_u32(np, "goodix,resume-in-workqueue", + &pdata->resume_in_workqueue); + if (pdata->resume_in_workqueue) + dev_info(dev, "resume-in-workqueue enabled\n"); + + of_property_read_u32(np, "goodix,power-off-sleep", + &pdata->power_off_sleep); + if (pdata->power_off_sleep) + dev_info(dev, "power-off-sleep enabled\n"); + + of_property_read_u32(np, "goodix,pen-suppress-finger", + &pdata->pen_suppress_finger); + if (pdata->pen_suppress_finger) + dev_info(dev, "pen-suppress-finger enabled\n"); + + prop = of_find_property(np, "touchscreen-key-map", NULL); + if (prop) { + key_nums = prop->length / sizeof(key_map[0]); + key_nums = key_nums > MAX_KEY_NUMS ? MAX_KEY_NUMS : key_nums; + + dev_dbg(dev, "key nums %d\n", key_nums); + ret = of_property_read_u32_array(np, + "touchscreen-key-map", key_map, + key_nums); + if (ret) { + dev_err(dev, "Unable to read key codes\n"); + pdata->key_nums = 0; + memset(pdata->key_map, 0, + MAX_KEY_NUMS * sizeof(pdata->key_map[0])); + } + pdata->key_nums = key_nums; + memcpy(pdata->key_map, key_map, + key_nums * sizeof(pdata->key_map[0])); + dev_info(dev, "key-map is [%x %x %x %x]\n", + pdata->key_map[0], pdata->key_map[1], + pdata->key_map[2], pdata->key_map[3]); + } + + pdata->irq_gpio = of_get_named_gpio(np, "irq-gpios", 0); + if (!gpio_is_valid(pdata->irq_gpio)) + dev_err(dev, "No valid irq gpio"); + + pdata->rst_gpio = of_get_named_gpio(np, "reset-gpios", 0); + if (!gpio_is_valid(pdata->rst_gpio)) + dev_err(dev, "No valid rst gpio"); + + return 0; +} + +/******************************************************* + * Function: + * parse config data from devices tree. + * Input: + * dev: device that this driver attached. + * cfg: pointer of the config array. + * cfg_len: pointer of the config length. + * sid: sensor id. + * Output: + * Executive outcomes. + * 0-succeed, -1-faileds. + *******************************************************/ +int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid) +{ + struct device_node *np = dev->of_node; + struct property *prop; + char cfg_name[18]; + int ret; + + snprintf(cfg_name, sizeof(cfg_name), "goodix,cfg-group%d", sid); + prop = of_find_property(np, cfg_name, cfg_len); + if (!prop || !prop->value || *cfg_len == 0 || + *cfg_len > GTP_CONFIG_MAX_LENGTH) { + *cfg_len = 0; + ret = -EPERM;/* failed */ + } else { + memcpy(cfg, prop->value, *cfg_len); + ret = 0; + } + + return ret; +} + +#endif + +static int gtp_power_on(struct goodix_ts_data *ts) +{ + int ret = 0; + + dev_info(&ts->client->dev,"%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + if (ts->vdd_ana) { + ret = regulator_enable(ts->vdd_ana); + if (ret) { + dev_err(&ts->client->dev, + "Regulator vdd enable failed ret=%d\n", + ret); + goto err_enable_vdd_ana; + } + } + + if (ts->vcc_i2c) { + ret = regulator_enable(ts->vcc_i2c); + if (ret) { + dev_err(&ts->client->dev, + "Regulator vcc_i2c enable failed ret=%d\n", + ret); + goto err_enable_vcc_i2c; + } + } + clear_bit(POWER_OFF_MODE, &ts->flags); + return 0; + +err_enable_vcc_i2c: + if (ts->vdd_ana) + regulator_disable(ts->vdd_ana); +err_enable_vdd_ana: + set_bit(POWER_OFF_MODE, &ts->flags); + return ret; +} + +static int gtp_power_off(struct goodix_ts_data *ts) +{ + int ret = 0; + + if (ts->vcc_i2c) { + set_bit(POWER_OFF_MODE, &ts->flags); + ret = regulator_disable(ts->vcc_i2c); + if (ret) { + dev_err(&ts->client->dev, + "Regulator vcc_i2c disable failed ret=%d\n", + ret); + goto err_disable_vcc_i2c; + } + dev_info(&ts->client->dev, + "Regulator vcc_i2c disabled\n"); + } + + if (ts->vdd_ana) { + set_bit(POWER_OFF_MODE, &ts->flags); + ret = regulator_disable(ts->vdd_ana); + if (ret) { + dev_err(&ts->client->dev, + "Regulator vdd disable failed ret=%d\n", + ret); + goto err_disable_vdd_ana; + } + dev_info(&ts->client->dev, + "Regulator vdd_ana disabled\n"); + } + return ret; + +err_disable_vdd_ana: + if (ts->vcc_i2c) + ret = regulator_enable(ts->vcc_i2c); +err_disable_vcc_i2c: + clear_bit(POWER_OFF_MODE, &ts->flags); + return ret; +} + +static int gtp_power_init(struct goodix_ts_data *ts) +{ + int ret; + + ts->vdd_ana = regulator_get(&ts->client->dev, "vdd_ana"); + if (IS_ERR(ts->vdd_ana)) { + ts->vdd_ana = NULL; + ret = PTR_ERR(ts->vdd_ana); + dev_info(&ts->client->dev, + "Regulator get failed vdd ret=%d\n", ret); + } + + ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc_i2c"); + if (IS_ERR(ts->vcc_i2c)) { + ts->vcc_i2c = NULL; + ret = PTR_ERR(ts->vcc_i2c); + dev_info(&ts->client->dev, + "Regulator get failed vcc_i2c ret=%d\n", ret); + } + return 0; +} + +static int gtp_power_deinit(struct goodix_ts_data *ts) +{ + if (ts->vdd_ana) + regulator_put(ts->vdd_ana); + if (ts->vcc_i2c) + regulator_put(ts->vcc_i2c); + + return 0; +} + +static void gtp_shutdown(struct i2c_client *client) +{ + struct goodix_ts_data *data = i2c_get_clientdata(client); + + if (!data->init_done) + return; + + gtp_work_control_enable(data, false); + gtp_power_off(data); + + return; +} + +static int gtp_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = -1; + struct goodix_ts_data *ts; + struct goodix_ts_platform_data *pdata; + + dev_info(&client->dev,"%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + /* do NOT remove these logs */ + dev_info(&client->dev, "GTP Driver Version: %s\n", GTP_DRIVER_VERSION); + dev_info(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr); + + i2c_connect_client = client; + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "Failed check I2C functionality"); + return -ENODEV; + } + + ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) { + dev_err(&client->dev, "Failed alloc ts memory"); + return -ENOMEM; + } + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&client->dev, "Failed alloc pdata memory\n"); + devm_kfree(&client->dev, ts); + return -EINVAL; + } + + ts->init_done = false; + +#ifdef CONFIG_OF + if (client->dev.of_node) { + ret = gtp_parse_dt(&client->dev, pdata); + if (ret) { + dev_err(&client->dev, "Failed parse dts\n"); + goto exit_free_client_data; + } + } +#else + /* set parameters at here if you platform doesn't DTS */ + pdata->rst_gpio = GTP_RST_PORT; + pdata->irq_gpio = GTP_INT_PORT; + pdata->slide_wakeup = false; + pdata->auto_update = true; + pdata->auto_update_cfg = false; + pdata->type_a_report = false; + pdata->esd_protect = false; + pdata->max_touch_id = GTP_MAX_TOUCH_ID; + pdata->abs_size_x = GTP_DEFAULT_MAX_X; + pdata->abs_size_y = GTP_DEFAULT_MAX_Y; + pdata->max_touch_width = GTP_DEFAULT_MAX_WIDTH; + pdata->max_touch_pressure = GTP_DEFAULT_MAX_PRESSURE; +#endif + + ts->client = client; + ts->pdata = pdata; + + i2c_set_clientdata(client, ts); + + ret = gtp_power_init(ts); + if (ret) { + dev_err(&client->dev, "Failed get regulator\n"); + ret = -EINVAL; + goto exit_free_client_data; + } + + ret = gtp_power_on(ts); + if (ret) { + dev_err(&client->dev, "Failed power on device\n"); + ret = -EINVAL; + goto exit_deinit_power; + } + + ret = gtp_pinctrl_init(ts); + if (ret < 0) { + /* if define pinctrl must define the following state + * to let int-pin work normally: default, int_output_high, + * int_output_low, int_input + */ + dev_err(&client->dev, "Failed get wanted pinctrl state\n"); + goto exit_deinit_power; + } + + ret = gtp_request_io_port(ts); + if (ret < 0) { + dev_err(&client->dev, "Failed request IO port\n"); + goto exit_power_off; + } + + gtp_reset_guitar(ts->client, 20); + + ret = gtp_i2c_test(client); + if (ret) { + dev_err(&client->dev, "Failed communicate with IC use I2C\n"); + goto exit_free_io_port; + } + + dev_info(&client->dev, "I2C Addr is %x\n", client->addr); + + ret = gtp_get_fw_info(client, &ts->fw_info); + if (ret < 0) { + dev_err(&client->dev, "Failed read FW version\n"); + goto exit_free_io_port; + } + + pdata->config.data[0] = GTP_REG_CONFIG_DATA >> 8; + pdata->config.data[1] = GTP_REG_CONFIG_DATA & 0xff; + ret = gtp_init_panel(ts); + if (ret < 0) + dev_info(&client->dev, "Panel un-initialize\n"); + + ret = gtp_request_input_dev(ts); + if (ret < 0) { + dev_err(&client->dev, "Failed request input device\n"); + goto exit_free_io_port; + } + + mutex_init(&ts->lock); + + ret = gtp_request_irq(ts); + if (ret < 0) { + dev_err(&client->dev, "Failed create work thread"); + goto exit_unreg_input_dev; + } + gtp_work_control_enable(ts, false); + if (ts->pdata->slide_wakeup) { + dev_info(&client->dev, "slide wakeup enabled\n"); + ret = enable_irq_wake(client->irq); + if (ret < 0) + dev_err(&client->dev, "Failed set irq wake\n"); + } + + gtp_register_powermanager(ts); + + ret = gtp_create_file(ts); + if (ret) { + dev_info(&client->dev, "Failed create attributes file"); + goto exit_powermanager; + } + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL + init_wr_node(client);/*TODO judge return value */ +#endif + + gtp_esd_init(ts); + gtp_esd_on(ts); + +#if GTP_CHARGER_SWITCH + gtp_charger_init(ts); + gtp_charger_on(ts); +#endif + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE + if (ts->pdata->auto_update) { + ret = gup_init_update_proc(ts); + if (ret < 0) + dev_err(&client->dev, "Failed create update thread\n"); + } +#endif + + /* probe init finished */ + ts->init_done = true; + gtp_work_control_enable(ts, true); + + /*Add by HQ-zmc [Date: 2018-01-18 20:15:06]*/ + gt_create_lockdown_proc(client, ts); + + gtp_create_wakeup_gesture_proc(client, ts); + + gtp_test_sysfs_init(); + + dev_info(&client->dev,"%s:EXIT FUNC ---- %d\n",__func__,__LINE__); + + return 0; + +exit_powermanager: + gtp_unregister_powermanager(ts); +exit_unreg_input_dev: + input_unregister_device(ts->input_dev); +exit_free_io_port: + if (gpio_is_valid(ts->pdata->rst_gpio)){ + gpio_direction_output(ts->pdata->rst_gpio, 0); + gpio_free(ts->pdata->rst_gpio); + } + if (gpio_is_valid(ts->pdata->irq_gpio)){ + gpio_direction_output(ts->pdata->irq_gpio, 0); + gpio_free(ts->pdata->irq_gpio); + } +exit_power_off: + gtp_power_off(ts); + msleep(1); + gtp_pinctrl_deinit(ts); +exit_deinit_power: + gtp_power_deinit(ts); +exit_free_client_data: + devm_kfree(&client->dev, pdata); + devm_kfree(&client->dev, ts); + i2c_set_clientdata(client, NULL); + + return ret; +} + +static int gtp_drv_remove(struct i2c_client *client) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + + gtp_test_sysfs_deinit(); + gtp_work_control_enable(ts, false); + gtp_unregister_powermanager(ts); + + remove_proc_entry(GT91XX_CONFIG_PROC_FILE, gtp_config_proc); + + sysfs_remove_group(&client->dev.kobj, >p_attr_group); + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL + uninit_wr_node(); +#endif + + if (ts->pdata->esd_protect) + gtp_esd_off(ts); + + /* TODO: how to judge a irq numbers validity */ + if (ts->client->irq) + free_irq(client->irq, ts); + else + hrtimer_cancel(&ts->timer); + + if (gpio_is_valid(ts->pdata->rst_gpio)) + gpio_free(ts->pdata->rst_gpio); + + if (gpio_is_valid(ts->pdata->irq_gpio)) + gpio_free(ts->pdata->irq_gpio); + + gtp_power_off(ts); + gtp_power_deinit(ts); + gtp_pinctrl_deinit(ts); + dev_info(&client->dev, "goodix ts driver removed"); + i2c_set_clientdata(client, NULL); + input_unregister_device(ts->input_dev); + mutex_destroy(&ts->lock); + + devm_kfree(&client->dev, ts->pdata); + devm_kfree(&client->dev, ts); + + return 0; +} + +static void gtp_clear_touch_event(struct goodix_ts_data *ts){ + int i; + + dev_info(&ts->client->dev, "%s:ENTER ---- %d\n",__func__,__LINE__); + mutex_lock(&ts->lock); + for (i = 0; i < ts->pdata->max_touch_id; i++) { + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); + } + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); + ts->pre_touch = 0; + mutex_unlock(&ts->lock); + dev_info(&ts->client->dev, "%s:Exit ---- %d\n",__func__,__LINE__); + } + +static void gtp_suspend(struct goodix_ts_data *ts) +{ + int ret = -1; + + dev_info(&ts->client->dev, "%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + if (test_bit(FW_UPDATE_RUNNING, &ts->flags)) { + dev_warn(&ts->client->dev, + "Fw upgrade in progress, can't go to suspend\n"); + return; + } + + if (test_and_set_bit(SLEEP_MODE, &ts->flags)) { + dev_info(&ts->client->dev, "Already in suspend state\n"); + return; + } + + dev_dbg(&ts->client->dev, "Try enter suspend mode\n"); + + disable_irq(ts->client->irq); + gtp_clear_touch_event(ts); + + gtp_esd_off(ts); +#if GTP_CHARGER_SWITCH + gtp_charger_off(ts); +#endif + gtp_work_control_enable(ts, false); + if ((ts->pdata->slide_wakeup)&>P_gesture_func_on) { + dev_info(&ts->client->dev,"gesture func on\n"); + ret = gtp_enter_doze(ts); + gtp_work_control_enable(ts, true); + enable_irq(ts->client->irq); + } else if (ts->pdata->power_off_sleep) { + /*TODO: power off routine */ + gtp_power_off(ts); + ret = SUCCESS; + } else { + ret = gtp_enter_sleep(ts); + } + + if (ret < 0) + dev_err(&ts->client->dev, "Failed enter suspend\n"); + + /* to avoid waking up while not sleeping */ + /* delay 48 + 10ms to ensure reliability */ + msleep(GTP_58_DLY_MS); + + dev_info(&ts->client->dev, "%s:EXIT FUNC ---- %d\n",__func__,__LINE__); +} + +static int gtp_gesture_wakeup(struct goodix_ts_data *ts) +{ + int ret; + int retry = 10; + + do { + gtp_reset_guitar(ts->client, 10); + ret = gtp_i2c_test(ts->client); + if (!ret) + break; + } while (--retry); + + if (!retry) + ret = -EIO; + + clear_bit(DOZE_MODE, &ts->flags); + return ret; +} + +static void gtp_resume(struct goodix_ts_data *ts) +{ + int ret = 0; + + dev_info(&ts->client->dev, "%s:ENTER FUNC ---- %d\n",__func__,__LINE__); + + if (test_bit(FW_UPDATE_RUNNING, &ts->flags)) { + dev_info(&ts->client->dev, + "Fw upgrade in progress, can't do resume\n"); + return; + } + + if (!test_bit(SLEEP_MODE, &ts->flags)) { + dev_dbg(&ts->client->dev, "Already in awake state\n"); + return; + } + + dev_info(&ts->client->dev, "Try resume from sleep mode\n"); + + gtp_work_control_enable(ts, false); + + if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) { + ret = gtp_gesture_wakeup(ts); + if (ret) + dev_warn(&ts->client->dev, "Failed wake up from gesture mode\n"); + } else if (ts->pdata->power_off_sleep) { + ret = gtp_power_on(ts); + if (ret) { + dev_warn(&ts->client->dev, "Failed wake up from gesture mode\n"); + } else { + gtp_reset_guitar(ts->client, 20); + ret = gtp_i2c_test(ts->client); + if (ret) + dev_warn(&ts->client->dev, + "I2C communicate failed after power on\n"); + } + } else { + ret = gtp_wakeup_sleep(ts); + if (ret) + dev_warn(&ts->client->dev, + "Failed wakeup from sleep mode\n"); + } + enable_irq(ts->client->irq); + + if (ret) + dev_warn(&ts->client->dev, "Later resume failed\n"); + else + gtp_esd_on(ts); + + #if GTP_CHARGER_SWITCH + gtp_charger_updateconfig(ts, 1); + gtp_charger_on(ts); + #endif + + clear_bit(SLEEP_MODE, &ts->flags); + gtp_work_control_enable(ts, true); + dev_info(&ts->client->dev, "%s:EXIT FUNC ---- %d\n",__func__,__LINE__); +} + +#if defined(CONFIG_FB) +static void fb_notify_resume_work(struct work_struct *work) +{ + struct goodix_ts_data *ts = + container_of(work, struct goodix_ts_data, fb_notify_work); + dev_info(&ts->client->dev, "try resume in workqueue\n"); + gtp_resume(ts); +} + +/* frame buffer notifier block control the suspend/resume procedure */ +static int gtp_fb_notifier_callback(struct notifier_block *noti, + unsigned long event, void *data) +{ + struct fb_event *ev_data = data; + struct goodix_ts_data *ts = container_of(noti, + struct goodix_ts_data, notifier); + int *blank; + + if (ev_data && ev_data->data && event == FB_EVENT_BLANK && ts) { + blank = ev_data->data; + if (*blank == FB_BLANK_UNBLANK || + *blank == FB_BLANK_NORMAL) { + dev_dbg(&ts->client->dev, "ts_resume"); + if (ts->pdata->resume_in_workqueue) + schedule_work(&ts->fb_notify_work); + else + gtp_resume(ts); + } else if (*blank == FB_BLANK_POWERDOWN) { + dev_dbg(&ts->client->dev, "ts_suspend"); + if (ts->pdata->resume_in_workqueue) + flush_work(&ts->fb_notify_work); + gtp_suspend(ts); + } + } + + return 0; +} + +#if ((defined CONFIG_PM)&&(defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static int gtp_pm_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + dev_info(&ts->client->dev, "Enter %s\n",__func__); + + if (ts && lcm_ffbm_mode) { + dev_info(&ts->client->dev, "Suspend by i2c pm."); + gtp_suspend(ts); + }else if(!lcm_ffbm_mode){ + dev_info(&ts->client->dev, "We are not in ffbm mode\n"); + } + + return 0; +} + +static int gtp_pm_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + dev_info(&ts->client->dev, "Enter %s\n",__func__); + + if (ts && lcm_ffbm_mode) { + dev_info(&ts->client->dev, "Resume by i2c pm."); + gtp_resume(ts); + }else if(!lcm_ffbm_mode){ + dev_info(&ts->client->dev, "We are not in ffbm mode\n"); + } + + return 0; +} + +static const struct dev_pm_ops gtp_pm_ops = { + .suspend = gtp_pm_suspend, + .resume = gtp_pm_resume, +}; +#endif + +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void gtp_early_suspend(struct early_suspend *h) +{ + struct goodix_ts_data *ts = container_of(h, + struct goodix_ts_data, early_suspend); + + if (ts) { + dev_dbg(&ts->client->dev, "Suspend by earlysuspend module."); + gtp_suspend(ts); + } +} + +static void gtp_late_resume(struct early_suspend *h) +{ + struct goodix_ts_data *ts = container_of(h, + struct goodix_ts_data, early_suspend); + + if (ts) { + dev_dbg(&ts->client->dev, "Resume by earlysuspend module."); + gtp_resume(ts); + } +} +#endif + +static int gtp_register_powermanager(struct goodix_ts_data *ts) +{ + int ret; +#if defined(CONFIG_FB) + INIT_WORK(&ts->fb_notify_work, fb_notify_resume_work); + ts->notifier.notifier_call = gtp_fb_notifier_callback; + ret = fb_register_client(&ts->notifier); + if (ret) + dev_err(&ts->client->dev, + "Unable to register fb_notifier: %d\n", ret); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = goodix_ts_early_suspend; + ts->early_suspend.resume = goodix_ts_late_resume; + register_early_suspend(&ts->early_suspend); +#endif + + return ret; +} + +static int gtp_unregister_powermanager(struct goodix_ts_data *ts) +{ +#if defined(CONFIG_FB) + fb_unregister_client(&ts->notifier); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&ts->early_suspend); +#endif + + return 0; +} + +/******************************************************* + * Function: + * Initialize external watchdog for esd protect + * Input: + * client: i2c device. + * Output: + * result of i2c write operation. + * 0: succeed, otherwise: failed + ********************************************************/ +static int gtp_init_ext_watchdog(struct i2c_client *client) +{ + int ret; + u8 opr_buffer[3] = { (u8)(GTP_REG_ESD_CHECK >> 8), + (u8)GTP_REG_ESD_CHECK, + (u8)GTP_ESD_CHECK_VALUE }; + + dev_dbg(&client->dev, "[Esd]Init external watchdog\n"); + ret = gtp_i2c_write(client, opr_buffer, 3); + if (ret == 1) + return 0; + + dev_err(&client->dev, "Failed init ext watchdog\n"); + return -EINVAL; +} + +static void gtp_esd_check_func(struct work_struct *work) +{ + s32 i; + s32 ret = -1; + u8 esd_buf[5] = { (u8)(GTP_REG_COMMAND >> 8), (u8)GTP_REG_COMMAND }; + struct delayed_work *dwork = to_delayed_work(work); + struct goodix_ts_esd *ts_esd = container_of(dwork, struct goodix_ts_esd, + delayed_work); + struct goodix_ts_data *ts = container_of(ts_esd, struct goodix_ts_data, + ts_esd); + + if (test_bit(SLEEP_MODE, &ts->flags) || + test_bit(FW_UPDATE_RUNNING, &ts->flags)) { + dev_dbg(&ts->client->dev, + "Esd cancled by power_suspend or fw_update!"); + return; + } + + if (ts_esd->esd_on == false) + return; + + for (i = 0; i < 3; i++) { + ret = gtp_i2c_read(ts->client, esd_buf, 4); + if (ret < 0) + continue; + + dev_dbg(&ts->client->dev, + "[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X", + esd_buf[2], esd_buf[3]); + if (esd_buf[2] == (u8)GTP_ESD_CHECK_VALUE || + esd_buf[3] != (u8)GTP_ESD_CHECK_VALUE) { + gtp_i2c_read(ts->client, esd_buf, 4); + if (ret < 0) + continue; + + if (esd_buf[2] == (u8)GTP_ESD_CHECK_VALUE || + esd_buf[3] != (u8)GTP_ESD_CHECK_VALUE) { + i = 3; + break; + } + } else { + /* IC works normally, Write 0x8040 0xAA, feed the dog */ + esd_buf[2] = (u8)GTP_ESD_CHECK_VALUE; + gtp_i2c_write(ts->client, esd_buf, 3); + break; + } + } + if (i >= 3) { + dev_err(&ts->client->dev, "IC working abnormally! Reset IC\n"); + esd_buf[0] = 0x42; + esd_buf[1] = 0x26; + esd_buf[2] = 0x01; + esd_buf[3] = 0x01; + esd_buf[4] = 0x01; + gtp_i2c_write(ts->client, esd_buf, 5); + /* TODO: Is power off really need? */ + msleep(GTP_50_DLY_MS); + gtp_power_off(ts); + msleep(GTP_20_DLY_MS); + gtp_power_on(ts); + msleep(GTP_20_DLY_MS); + + gtp_reset_guitar(ts->client, 50); + msleep(GTP_50_DLY_MS); + gtp_send_cfg(ts->client); + } + + if (ts_esd->esd_on == true && !test_bit(SLEEP_MODE, &ts->flags)) { + schedule_delayed_work(&ts_esd->delayed_work, 2 * HZ); + dev_dbg(&ts->client->dev, "ESD work rescheduled\n"); + } +} + +static int gtp_esd_init(struct goodix_ts_data *ts) +{ + struct goodix_ts_esd *ts_esd = &ts->ts_esd; + + INIT_DELAYED_WORK(&ts_esd->delayed_work, gtp_esd_check_func); + mutex_init(&ts_esd->mutex); + ts_esd->esd_on = false; + + return 0; +} + +void gtp_esd_on(struct goodix_ts_data *ts) +{ + struct goodix_ts_esd *ts_esd = &ts->ts_esd; + + if (!ts->pdata->esd_protect) + return; + mutex_lock(&ts_esd->mutex); + if (ts_esd->esd_on == false) { + ts_esd->esd_on = true; + schedule_delayed_work(&ts_esd->delayed_work, 2 * HZ); + dev_info(&ts->client->dev, "ESD on"); + } + mutex_unlock(&ts_esd->mutex); +} + +void gtp_esd_off(struct goodix_ts_data *ts) +{ + struct goodix_ts_esd *ts_esd = &ts->ts_esd; + + if (!ts->pdata->esd_protect) + return; + mutex_lock(&ts_esd->mutex); + if (ts_esd->esd_on == true) { + ts_esd->esd_on = false; + cancel_delayed_work_sync(&ts_esd->delayed_work); + dev_info(&ts->client->dev, "ESD off"); + } + mutex_unlock(&ts_esd->mutex); +} + +#if GTP_CHARGER_SWITCH +extern bool* check_charge_mode(void); +bool gtp_get_charger_status(void) +{ + bool *g_chargerState = NULL; + g_chargerState = check_charge_mode(); + return *g_chargerState; +} +static void gtp_charger_updateconfig(struct goodix_ts_data *ts , s32 dir_update) +{ + u32 chr_status = 0; + u8 chr_cmd[3] = {0x80, 0x40}; + static u8 chr_pluggedin = 0; + + chr_status = gtp_get_charger_status(); + + if (chr_status) { /* charger plugged in */ + if (!chr_pluggedin || dir_update) { + dev_info(&ts->client->dev, "charging update charger cfg====="); + chr_cmd[2] = 6; + + gtp_i2c_write(ts->client, chr_cmd, 3); + mdelay(1); + chr_pluggedin = 1; + } + } else { /* charger plugged out */ + if (chr_pluggedin || dir_update) { + dev_info(&ts->client->dev, "discharging update normal cfg====="); + chr_cmd[2] = 7; + gtp_i2c_write(ts->client, chr_cmd, 3); + mdelay(1); + chr_pluggedin = 0; + } + } +} +static void gtp_charger_check_func(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct goodix_ts_charger *ts_charger = container_of(dwork, struct goodix_ts_charger, + delayed_work); + struct goodix_ts_data *ts =container_of(ts_charger, struct goodix_ts_data , ts_charger); + + gtp_charger_updateconfig(ts, 0); + + if(!test_bit(SLEEP_MODE, &ts->flags) ) + { + schedule_delayed_work(&ts_charger->delayed_work, 2* HZ); + } + else + { + dev_info(&ts->client->dev, "charger suspended!"); + } + +} + +static int gtp_charger_init(struct goodix_ts_data *ts) +{ + struct goodix_ts_charger *ts_charger = &ts->ts_charger; + + INIT_DELAYED_WORK(&ts_charger->delayed_work, gtp_charger_check_func); + mutex_init(&ts_charger->mutex); + ts_charger->charger_on= false; + + return 0; +} + +void gtp_charger_on(struct goodix_ts_data *ts) +{ + struct goodix_ts_charger *ts_charger = &ts->ts_charger; + + if (!ts->pdata->charger_cmd) + return; + mutex_lock(&ts_charger->mutex); + if (ts_charger->charger_on== false) { + ts_charger->charger_on = true; + schedule_delayed_work(&ts_charger->delayed_work, 1 * HZ); + dev_info(&ts->client->dev, "Charger on"); + } + mutex_unlock(&ts_charger->mutex); +} + +void gtp_charger_off(struct goodix_ts_data *ts) +{ + struct goodix_ts_charger *ts_charger = &ts->ts_charger; + + if (!ts->pdata->charger_cmd) + return; + mutex_lock(&ts_charger->mutex); + if (ts_charger->charger_on == true) { + ts_charger->charger_on = false; + cancel_delayed_work_sync(&ts_charger->delayed_work); + dev_info(&ts->client->dev, "Charger off"); + } + mutex_unlock(&ts_charger->mutex); +} +#endif + +#ifdef CONFIG_OF +static const struct of_device_id gtp_match_table[] = { + {.compatible = "goodix,gt9xx",}, + { }, +}; +#endif + +static const struct i2c_device_id gtp_device_id[] = { + { GTP_I2C_NAME, 0 }, + { } +}; + +static struct i2c_driver goodix_ts_driver = { + .probe = gtp_probe, + .remove = gtp_drv_remove, + .id_table = gtp_device_id, + .shutdown = gtp_shutdown, + .driver = { + .name = GTP_I2C_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = gtp_match_table, +#endif +#if ((defined CONFIG_PM)&&(defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) + .pm = >p_pm_ops, +#endif + }, +}; + +static int __init gtp_init(void) +{ + s32 ret; + + pr_info("Gt9xx driver installing..\n"); + ret = i2c_add_driver(&goodix_ts_driver); + + return ret; +} + +static void __exit gtp_exit(void) +{ + pr_info("Gt9xx driver exited\n"); + i2c_del_driver(&goodix_ts_driver); +} + +module_init(gtp_init); +module_exit(gtp_exit); + +MODULE_DESCRIPTION("GT9 serials touch controller Driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/input/touchscreen/gt917d/gt9xx.h b/drivers/input/touchscreen/gt917d/gt9xx.h new file mode 100644 index 0000000000000..c633106eef662 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx.h @@ -0,0 +1,414 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2016 - 2017 Goodix. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.8.0.2 + * Release Date: 2017/12/14 + */ + +#ifndef _GOODIX_GT9XX_H_ +#define _GOODIX_GT9XX_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#endif +#ifdef CONFIG_FB +#include +#include +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif +#include +#include + +#define CONFIG_TOUCHSCREEN_GT9XX_UPDATE +#define CONFIG_TOUCHSCREEN_GT9XX_TOOL + +#define GTP_TOOL_PEN 1 +#define GTP_TOOL_FINGER 2 + +#define MAX_KEY_NUMS 4 +#define GTP_CONFIG_MAX_LENGTH 240 +#define GTP_ADDR_LENGTH 2 + +/***************************PART1:ON/OFF define*******************************/ +#define GTP_DEBUG_ON 1 +#define GTP_DEBUG_ARRAY_ON 0 +#define GTP_DEBUG_FUNC_ON 1 + +#define GTP_CHARGER_SWITCH 1 + +struct goodix_point_t { + int id; + int x; + int y; + int w; + int p; + int tool_type; +}; + +struct goodix_config_data { + int length; + u8 data[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]; +}; + +struct goodix_ts_platform_data { + int irq_gpio; + int rst_gpio; + u32 irq_flags; + u32 abs_size_x; + u32 abs_size_y; + u32 max_touch_id; + u32 max_touch_width; + u32 max_touch_pressure; + u32 key_map[MAX_KEY_NUMS]; + u32 key_nums; + u32 int_sync; + u32 driver_send_cfg; + u32 swap_x2y; + u32 slide_wakeup; + u32 auto_update; + u32 auto_update_cfg; + u32 esd_protect; + u32 type_a_report; + u32 power_off_sleep; + u32 resume_in_workqueue; + u32 pen_suppress_finger; + u32 charger_cmd; + struct goodix_config_data config; +}; + +struct goodix_ts_esd { + struct delayed_work delayed_work; + struct mutex mutex; + bool esd_on; +}; +#if GTP_CHARGER_SWITCH +struct goodix_ts_charger{ + struct delayed_work delayed_work; + struct mutex mutex; + bool charger_on; +}; +#endif + +enum { + WORK_THREAD_ENABLED = 0, + HRTIMER_USED, + FW_ERROR, + + DOZE_MODE, + SLEEP_MODE, + POWER_OFF_MODE, + RAW_DATA_MODE, + + FW_UPDATE_RUNNING, + PANEL_RESETTING +}; + +struct goodix_pinctrl { + struct pinctrl *pinctrl; + struct pinctrl_state *default_sta; + struct pinctrl_state *int_out_high; + struct pinctrl_state *int_out_low; + struct pinctrl_state *int_input; +}; + +struct goodix_fw_info { + u8 pid[6]; + u16 version; + u8 sensor_id; + u16 cfg_ver; +}; + +struct goodix_ts_data { + unsigned long flags; /* This member record the device status */ + + struct goodix_ts_esd ts_esd; +#if GTP_CHARGER_SWITCH + struct goodix_ts_charger ts_charger; +#endif + struct i2c_client *client; + struct input_dev *input_dev; + struct input_dev *pen_dev; + struct goodix_ts_platform_data *pdata; + /* use pinctrl control int-pin output low or high */ + struct goodix_pinctrl pinctrl; + struct hrtimer timer; + struct mutex lock; + struct notifier_block ps_notif; + struct regulator *vdd_ana; + struct regulator *vcc_i2c; +#if defined(CONFIG_FB) + struct notifier_block notifier; + struct work_struct fb_notify_work; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + struct goodix_fw_info fw_info; + bool force_update; + bool init_done; + u16 pre_touch; +}; + +/************************* PART2:TODO define *******************************/ +/* STEP_1(REQUIRED): Define Configuration Information Group(s) + Sensor_ID Map: + sensor_opt1 sensor_opt2 Sensor_ID + GND GND 0 + VDDIO GND 1 + NC GND 2 + GND NC/300K 3 + VDDIO NC/300K 4 + NC NC/300K 5 +*/ +/* TODO: define your own default or for Sensor_ID == 0 config here. + The predefined one is just a sample config, + which is not suitable for your tp in most cases. */ +#define CTP_CFG_GROUP0 {\ + 0x41, 0xD0, 0x02, 0x00, 0x05, 0x0A, 0x34, \ + 0x00, 0x01, 0x08, 0x28, 0x05, 0x50, 0x32, \ + 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x17, 0x19, 0x1E, 0x14, 0x8C, \ + 0x2D, 0x0E, 0x3C, 0x3E, 0x82, 0x0A, 0x82, \ + 0x0A, 0x00, 0x99, 0x33, 0x1D, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x2B, 0x19, 0x64, 0x94, 0xC0, 0x02, \ + 0x08, 0x00, 0x00, 0x04, 0xF2, 0x1C, 0x00, \ + 0xB9, 0x26, 0x00, 0x93, 0x32, 0x00, 0x77, \ + 0x42, 0x00, 0x62, 0x57, 0x00, 0x62, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0xFF, 0x65, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x19, 0x46, 0x00, 0x00, 0x00, 0x00, 0x32, \ + 0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, \ + 0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, \ + 0x0A, 0x0C, 0x0F, 0x10, 0x12, 0x13, 0x14, \ + 0x18, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, \ + 0x22, 0x24, 0x26, 0x28, 0x29, 0x2A, 0xFF, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0xB8, 0x01\ +} + +/* TODO: define your config for Sensor_ID == 1 here, if needed */ +#define CTP_CFG_GROUP1 {\ +} + +/* TODO: define your config for Sensor_ID == 2 here, if needed */ +#define CTP_CFG_GROUP2 {\ +} + +/* TODO: define your config for Sensor_ID == 3 here, if needed */ +#define CTP_CFG_GROUP3 {\ +} +/* TODO: define your config for Sensor_ID == 4 here, if needed */ +#define CTP_CFG_GROUP4 {\ + 0x53, 0xD0, 0x02, 0x00, 0x05, 0x05, 0xF5, 0xD5, 0x21, 0x48, 0x2D, 0x0F, \ + 0x5A, 0x41, 0x0E, 0x05, 0x00, 0x00, 0x32, 0x32, 0x20, 0x00, 0x05, 0x14, \ + 0x14, 0x1A, 0x14, 0x8B, 0x2B, 0x0C, 0xB5, 0xB7, 0xEB, 0x04, 0xFF, 0xFE, \ + 0x00, 0x22, 0x33, 0x10, 0x3C, 0x80, 0x00, 0x00, 0x00, 0x1E, 0x12, 0x41, \ + 0x23, 0x12, 0x5A, 0xAA, 0xBE, 0x4A, 0x55, 0x04, 0x00, 0x14, 0x19, 0x04, \ + 0x80, 0xAB, 0x00, 0x7F, 0xAF, 0x64, 0x7E, 0xB3, 0x00, 0x7E, 0xB7, 0x00, \ + 0x7B, 0xBB, 0x3C, 0x7B, 0x08, 0x30, 0x00, 0x00, 0xF8, 0x70, 0x50, 0xFF, \ + 0xFF, 0x17, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, \ + 0x08, 0x46, 0x80, 0x08, 0x0A, 0x00, 0xA0, 0x00, 0x3C, 0x28, 0x19, 0x19, \ + 0x80, 0x11, 0x00, 0x00, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0E, 0x0C, 0x0A, \ + 0x08, 0x06, 0x04, 0x02, 0xFF, 0xFF, 0x28, 0x00, 0x32, 0x20, 0x00, 0x06, \ + 0x00, 0x00, 0x0A, 0x06, 0x10, 0x08, 0x0A, 0x22, 0xEB, 0x04, 0x26, 0x24, \ + 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x18, 0x16, 0x12, 0x10, 0x0F, \ + 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x00, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x28, 0x0B, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x10, 0xEF, 0x01\ +} + +/* TODO: define your config for Sensor_ID == 5 here, if needed */ +#define CTP_CFG_GROUP5 {\ +} + +/* STEP_2(REQUIRED): Customize your I/O ports & I/O operations */ +#define GTP_RST_PORT 64 /* EXYNOS4_GPX2(0) */ +#define GTP_INT_PORT 65 /* EXYNOS4_GPX2(1) */ + +#define GTP_GPIO_AS_INPUT(pin) (gpio_direction_input(pin)) +#define GTP_GPIO_AS_INT(pin) (GTP_GPIO_AS_INPUT(pin)) +#define GTP_GPIO_GET_VALUE(pin) gpio_get_value(pin) +#define GTP_GPIO_OUTPUT(pin, level) gpio_direction_output(pin, level) +#define GTP_GPIO_REQUEST(pin, label) gpio_request(pin, label) +#define GTP_GPIO_FREE(pin) gpio_free(pin) + +/* STEP_3(optional): Specify your special config info if needed */ +#define GTP_DEFAULT_MAX_X 720 /* default coordinate max values */ +#define GTP_DEFAULT_MAX_Y 1080 +#define GTP_DEFAULT_MAX_WIDTH 1024 +#define GTP_DEFAULT_MAX_PRESSURE 1024 +#define GTP_DEFAULT_INT_TRIGGER 1 /* 1 rising, 2 falling */ +#define GTP_MAX_TOUCH_ID 16 + +/* STEP_4(optional): If keys are available and reported as keys, +config your key info here */ +#define GTP_KEY_TAB {KEY_MENU, KEY_HOME, KEY_BACK, KEY_HOMEPAGE, \ + KEY_F1, KEY_F2, KEY_F3} + +/**************************PART3:OTHER define*******************************/ +#define GTP_DRIVER_VERSION "V2.8.0.2<2017/12/14>" +#define GTP_I2C_NAME "goodix-ts" +#define GT91XX_CONFIG_PROC_FILE "gt9xx_config" +#define GT9XX_LOCKDOWN_PROC_FILE "tp_lockdown_info" +#define GT9XX_WAKEUP_GESTURE_PROC "tp_wakeup_gesture" +#define GTP_POLL_TIME 10 +#define GTP_CONFIG_MIN_LENGTH 186 +#define GTP_ESD_CHECK_VALUE 0xAA +#define RETRY_MAX_TIMES 5 +#define PEN_TRACK_ID 9 +#define MASK_BIT_8 0x80 +#define FAIL 0 +#define SUCCESS 1 + +/* Registers define */ +#define GTP_REG_COMMAND 0x8040 +#define GTP_REG_ESD_CHECK 0x8041 +#define GTP_REG_COMMAND_CHECK 0x8046 +#define GTP_REG_CONFIG_DATA 0x8047 +#define GTP_REG_VERSION 0x8140 +#define GTP_REG_SENSOR_ID 0x814A +#define GTP_REG_DOZE_BUF 0x814B +#define GTP_READ_COOR_ADDR 0x814E +/*Add by HQ-zmc [Date: 2018-03-03 17:32:53]*/ +#define GTP_READ_CFG_VER 0x8047 + +/* Sleep time define */ +#define GTP_1_DLY_MS 1 +#define GTP_2_DLY_MS 2 +#define GTP_10_DLY_MS 10 +#define GTP_20_DLY_MS 20 +#define GTP_50_DLY_MS 50 +#define GTP_58_DLY_MS 58 +#define GTP_100_DLY_MS 100 +#define GTP_500_DLY_MS 500 +#define GTP_1000_DLY_MS 1000 +#define GTP_3000_DLY_MS 3000 + +#define RESOLUTION_LOC 3 +#define TRIGGER_LOC 8 + +/*Add by HQ-zmc [Date: 2018-01-19 09:28:17]*/ +#define GTP_REG_COLOR_GT915 0xc8a4 +#define GTP_REG_COLOR_GT917 0x81a0 + +#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0])) +/* Log define */ +#define GTP_DEBUG(fmt, arg...) \ +do { \ + if (GTP_DEBUG_ON) {\ + pr_info("<<-GTP-DEBUG->> [%d]"fmt"\n", __LINE__, ##arg);\ + } \ +} while (0) +#define GTP_DEBUG_ARRAY(array, num) \ +do { \ + s32 i;\ + u8 *a = array;\ + if (GTP_DEBUG_ARRAY_ON) {\ + pr_warn("<<-GTP-DEBUG-ARRAY->>\n");\ + for (i = 0; i < (num); i++) {\ + pr_warn("%02x ", (a)[i]);\ + if ((i + 1) % 10 == 0) {\ + pr_warn("\n");\ + } \ + } \ + pr_warn("\n");\ + } \ +} while (0) +#define GTP_DEBUG_FUNC() \ +do {\ + if (GTP_DEBUG_FUNC_ON) {\ + pr_warn("<<-GTP-FUNC->> Func:%s@Line:%d\n", \ + __func__, __LINE__);\ + } \ +} while (0) +#define GTP_SWAP(x, y) \ +do {\ + typeof(x) z = x;\ + x = y;\ + y = z;\ +} while (0) + +/******************************End of Part III********************************/ +#ifdef CONFIG_OF +extern int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid); +#endif + +extern void gtp_reset_guitar(struct i2c_client *client, s32 ms); +extern void gtp_int_sync(struct goodix_ts_data *ts, s32 ms); +extern void gtp_esd_on(struct goodix_ts_data *ts); +extern void gtp_esd_off(struct goodix_ts_data *ts); +extern void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable); +extern void gtp_charger_on(struct goodix_ts_data *ts); +extern void gtp_charger_off(struct goodix_ts_data *ts); + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE +extern u16 show_len; +extern u16 total_len; +extern u8 gup_init_update_proc(struct goodix_ts_data *); +extern s32 gup_update_proc(void *dir); +extern s32 gup_enter_update_mode(struct i2c_client *client); +extern void gup_leave_update_mode(struct i2c_client *client); +#endif + +#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL +extern s32 init_wr_node(struct i2c_client *); +extern void uninit_wr_node(void); +#endif + +/*********** For gt9xx_update Start *********/ +extern struct i2c_client *i2c_connect_client; +extern void gtp_reset_guitar(struct i2c_client *client, s32 ms); +extern void gtp_int_output(struct goodix_ts_data *ts, int level); +extern s32 gtp_send_cfg(struct i2c_client *client); +extern s32 gtp_get_fw_info(struct i2c_client *, struct goodix_fw_info *fw_info); +extern s32 gtp_i2c_read_dbl_check(struct i2c_client *, u16, u8 *, int); +extern int gtp_i2c_read(struct i2c_client *, u8 *, int); +extern int gtp_i2c_write(struct i2c_client *, u8 *, int); +extern s32 gtp_fw_startup(struct i2c_client *client); +extern int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf); +extern void ctp_vendor_info(struct i2c_client *client, struct goodix_fw_info *gt_fw_info); +/*********** For gt9xx_update End *********/ +extern int gtp_i2c_test(struct i2c_client *client); + +#endif /* _GOODIX_GT9XX_H_ */ diff --git a/drivers/input/touchscreen/gt917d/gt9xx_openshort.c b/drivers/input/touchscreen/gt917d/gt9xx_openshort.c new file mode 100644 index 0000000000000..b8a01592d0f85 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx_openshort.c @@ -0,0 +1,868 @@ +/* drivers/input/touchscreen/gt9xx_shorttp.c + * + * 2010 - 2012 Goodix Technology. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version:1.0 + * Author: meta@goodix.com + * Accomplished Date:2012/10/20 + * Revision record: + * + */ + +#include +#include +#include +#include "gt9xx_openshort.h" + +#define _BEYOND_INFO_MAX 20 +#define GTP_OPEN_SAMPLE_NUM 1 +#define GTP_TEST_INFO_MAX 200 + + + +extern s32 gtp_i2c_read(struct i2c_client *, u8 *, s32); +extern s32 gtp_i2c_write(struct i2c_client *, u8 *, s32); +extern void gtp_reset_guitar(struct i2c_client*, s32); + +extern struct i2c_client *i2c_connect_client; + +u8 gt9xx_drv_num = MAX_DRIVER_NUM; +u8 gt9xx_sen_num = MAX_SENSOR_NUM; +u16 gt9xx_pixel_cnt = MAX_DRIVER_NUM * MAX_SENSOR_NUM; +u16 gt9xx_sc_pxl_cnt = MAX_DRIVER_NUM * MAX_SENSOR_NUM; +struct gt9xx_short_info *short_sum; + +u8 chip_type_gt9f = 0; +u8 have_key = 0; +u8 gt9xx_sc_drv_num; +u8 key_is_isolated; +u8 key_iso_pos[5]; +static u8 raw_data[MAX_DRIVER_NUM*MAX_SENSOR_NUM*2+20]; +static u8 diff_data[MAX_DRIVER_NUM*MAX_SENSOR_NUM*2+20]; +static u8 refraw_data[MAX_DRIVER_NUM*MAX_SENSOR_NUM*2+20]; + +struct kobject *goodix_debug_kobj; + +static s32 *test_rslt_buf; +static struct gt9xx_open_info *touchpad_sum; + +#define _MIN_ERROR_NUM (GTP_OPEN_SAMPLE_NUM * 9 / 10) + + +static s32 gtp_i2c_end_cmd(struct i2c_client *client) +{ + u8 end_cmd[3] = {GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0}; + s32 ret = 0; + + ret = gtp_i2c_write(client, end_cmd, 3); + if (ret < 0) + { + GTP_DEBUG("I2C write end_cmd error!"); + } + return ret; +} + +s32 gtp_parse_config(struct i2c_client *client) +{ + u8 i = 0; + u8 key_pos = 0; + u8 key_val = 0; + u8 config[256] = {(u8)(GTP_REG_CONFIG_DATA >> 8), (u8)GTP_REG_CONFIG_DATA, 0}; + u8 type_buf[12] = {0x80, 0x00}; + + if (gtp_i2c_read(client, config, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH) <= 0) + { + GTP_DEBUG("Failed to read config!"); + return FAIL; + } + + gt9xx_drv_num = (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT-GT9_REG_CFG_BEG] & 0x1F) + + (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT+1 -GT9_REG_CFG_BEG] & 0x1F); + gt9xx_sen_num = (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT+2-GT9_REG_CFG_BEG] & 0x0F) + + ((config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT+2-GT9_REG_CFG_BEG]>>4) & 0x0F); + + GTP_DEBUG("Driver num: %d, Sensor Num: %d", gt9xx_drv_num, gt9xx_sen_num); + if (gt9xx_drv_num < MIN_DRIVER_NUM || gt9xx_drv_num > MAX_DRIVER_NUM) + { + GTP_DEBUG("driver number error!"); + return FAIL; + } + if (gt9xx_sen_num < MIN_SENSOR_NUM || gt9xx_sen_num > MAX_SENSOR_NUM) + { + GTP_DEBUG("sensor number error!"); + return FAIL; + } + gt9xx_sc_pxl_cnt = gt9xx_pixel_cnt = gt9xx_drv_num * gt9xx_sen_num; + + gtp_i2c_read(client, type_buf, 12); + if (!memcmp(&type_buf[2], "GOODIX_GT9", 10)) + { + chip_type_gt9f = 0; + GTP_DEBUG("Chip type: GT9XX"); + } + else + { + chip_type_gt9f = 1; + GTP_DEBUG("Chip type: GT9XXF"); + } + + have_key = config[0x804E - GT9_REG_CFG_BEG + GTP_ADDR_LENGTH] & 0x01; + + if (!have_key) + { + GTP_DEBUG("No key"); + return SUCCESS; + } + GTP_DEBUG("Have Key"); + gt9xx_sc_drv_num = gt9xx_drv_num - 1; + + for (i = 0; i < 5; ++i) + { + key_iso_pos[i] = 0; + } + + key_is_isolated = 0; + for (i = 0; i < 4; ++i) + { + + key_val = config[GTP_ADDR_LENGTH + GT9_REG_KEY_VAL - GT9_REG_CFG_BEG + i]; + key_pos = key_val%0x08; + GTP_DEBUG("key_val[%d] = 0x%02x", i+1, key_val); + if ((key_pos != 0)) + { + key_is_isolated = 0; + GTP_DEBUG("Key is not isolated!"); + break; + } + else if (key_val == 0x00) + { + continue; + } + else + { + key_iso_pos[0]++; + key_iso_pos[i+1] = key_val/0x08 - 1; + key_is_isolated = 1; + } + } + + gt9xx_sc_pxl_cnt = gt9xx_pixel_cnt - (gt9xx_drv_num-gt9xx_sc_drv_num) * gt9xx_sen_num; + GTP_DEBUG("drv num: %d, sen num: %d, sc drv num: %d", gt9xx_drv_num, gt9xx_sen_num, gt9xx_sc_drv_num); + if (key_is_isolated) + { + GTP_DEBUG("Isolated [%d key(s)]: %d, %d, %d, %d", key_iso_pos[0], key_iso_pos[1], key_iso_pos[2], key_iso_pos[3], key_iso_pos[4]); + } + + return SUCCESS; +} + +u32 endian_mode(void) +{ + union {s32 i; s8 c; }endian; + + endian.i = 1; + + if (1 == endian.c) + { + return MYBIG_ENDIAN; + } + else + { + return MYLITLE_ENDIAN; + } +} +/* +********************************************************************************************************* +* Function: +* send read rawdata cmd +* Input: +* i2c_client* client: i2c device +* Return: +* SUCCESS: send process succeed, FAIL: failed +********************************************************************************************************* +*/ +s32 gt9_read_raw_cmd(struct i2c_client *client) +{ + u8 raw_cmd[3] = {(u8)(GTP_REG_READ_RAW >> 8), (u8)GTP_REG_READ_RAW, 0x01}; + s32 ret = -1; + GTP_DEBUG("Send read raw data command"); + ret = gtp_i2c_write(client, raw_cmd, 3); + if (ret <= 0) + { + GTP_DEBUG("i2c write failed."); + return FAIL; + } + msleep(10); + return SUCCESS; +} + +s32 gt9_read_coor_cmd(struct i2c_client *client) +{ + u8 raw_cmd[3] = {(u8)(GTP_REG_READ_RAW >> 8), (u8)GTP_REG_READ_RAW, 0x0}; + s32 ret = -1; + + ret = gtp_i2c_write(client, raw_cmd, 3); + if (ret < 0) + { + GTP_DEBUG("i2c write coor cmd failed!"); + return FAIL; + } + msleep(10); + return SUCCESS; +} + + +s32 gtp_read_diffdata(struct i2c_client *client, u16 *data) +{ + s32 ret = -1; + u16 retry = 0; + u8 read_state[3] = {(u8)(GTP_REG_RAW_READY>>8), (u8)GTP_REG_RAW_READY, 0}; + u16 i = 0, j = 0; + u8 *read_diffbuf; + u8 tail, head; + u8 temp[20]; + + read_diffbuf = (u8*)kmalloc(sizeof(u8) * (gt9xx_drv_num*gt9xx_sen_num * 2 + GTP_ADDR_LENGTH), GFP_KERNEL); + + if (NULL == read_diffbuf) + { + GTP_DEBUG("failed to allocate for read diffbuf"); + return FAIL; + } + + if (data == NULL) + { + GTP_DEBUG("Invalid raw buffer."); + goto have_error; + } + + msleep(10); + while (retry++ < GTP_WAIT_RAW_MAX_TIMES) + { + ret = gtp_i2c_read(client, read_state, 3); + if (ret <= 0) + { + GTP_DEBUG("i2c read failed.return: %d", ret); + continue; + } + if ((read_state[GTP_ADDR_LENGTH] & 0x80) == 0x80) + { + GTP_DEBUG("Raw data is ready."); + break; + } + if ((retry%20) == 0) + { + GTP_DEBUG("(%d)read_state[2] = 0x%02X", retry, read_state[GTP_ADDR_LENGTH]); + if (retry == 100) + { + gt9_read_raw_cmd(client); + } + } + msleep(5); + } + if (retry >= GTP_WAIT_RAW_MAX_TIMES) + { + GTP_DEBUG("Wait raw data ready timeout."); + goto have_error; + } + + if (chip_type_gt9f) + { + read_diffbuf[0] = (u8)(GTP_REG_RAW_DATA_GT9F >> 8); + read_diffbuf[1] = (u8)(GTP_REG_RAW_DATA_GT9F); + } + else + { + read_diffbuf[0] = (u8)(GTP_REG_DIFF_DATA >> 8); + read_diffbuf[1] = (u8)(GTP_REG_DIFF_DATA); + } + + ret = gtp_i2c_read(client, read_diffbuf, GTP_ADDR_LENGTH + ((gt9xx_drv_num*gt9xx_sen_num)*2)); + if (ret <= 0) + { + GTP_DEBUG("i2c read rawdata failed."); + goto have_error; + } + gtp_i2c_end_cmd(client); + + if (endian_mode() == MYBIG_ENDIAN) + { + head = 0; + tail = 1; + GTP_DEBUG("Big Endian."); + } + else + { + head = 1; + tail = 0; + GTP_DEBUG("Little Endian."); + } + + + GTP_DEBUG("---read diff data-----\n"); + + sprintf(temp, "tx: %d\n", gt9xx_drv_num); + sprintf(diff_data, temp); + sprintf(temp, "rx: %d\n", gt9xx_sen_num); + strcat(diff_data, temp); + + for (i = 0, j = 0; i < ((gt9xx_drv_num*gt9xx_sen_num)*2); i+=2) + { + data[i/2] = (u16)(read_diffbuf[i+head+GTP_ADDR_LENGTH]<<8) + (u16)read_diffbuf[GTP_ADDR_LENGTH+i+tail]; + sprintf(temp, "%-5d ", (short)data[i/2]); + strcat(diff_data, temp); + ++j; + if ((j%28) == 0){ + sprintf(temp, "\n"); + strcat(diff_data, temp); + } + } + + kfree(read_diffbuf); + return SUCCESS; +have_error: + kfree(read_diffbuf); + return FAIL; +} + +/* +********************************************************************************************************* +* Function: +* read rawdata from ic registers +* Input: +* u16* data: rawdata buffer +* i2c_client* client: i2c device +* Return: +* SUCCESS: read process succeed, FAIL: failed +********************************************************************************************************* +*/ +s32 gtp_read_rawdata(struct i2c_client *client, u16 *data) +{ + s32 ret = -1; + u16 retry = 0; + u8 read_state[3] = {(u8)(GTP_REG_RAW_READY>>8), (u8)GTP_REG_RAW_READY, 0}; + u16 i = 0, j = 0; + u8 *read_rawbuf; + u8 tail, head; + u8 temp[20]; + + read_rawbuf = (u8*)kmalloc(sizeof(u8) * (gt9xx_drv_num*gt9xx_sen_num * 2 + GTP_ADDR_LENGTH), GFP_KERNEL); + + if (NULL == read_rawbuf) + { + GTP_DEBUG("failed to allocate for read_rawbuf"); + return FAIL; + } + + if (data == NULL) + { + GTP_DEBUG("Invalid raw buffer."); + goto have_error; + } + + msleep(10); + while (retry++ < GTP_WAIT_RAW_MAX_TIMES) + { + ret = gtp_i2c_read(client, read_state, 3); + if (ret <= 0) + { + GTP_DEBUG("i2c read failed.return: %d", ret); + continue; + } + if ((read_state[GTP_ADDR_LENGTH] & 0x80) == 0x80) + { + GTP_DEBUG("Raw data is ready."); + break; + } + if ((retry%20) == 0) + { + GTP_DEBUG("(%d)read_state[2] = 0x%02X", retry, read_state[GTP_ADDR_LENGTH]); + if (retry == 100) + { + gt9_read_raw_cmd(client); + } + } + msleep(5); + } + if (retry >= GTP_WAIT_RAW_MAX_TIMES) + { + GTP_DEBUG("Wait raw data ready timeout."); + goto have_error; + } + + if (chip_type_gt9f) + { + read_rawbuf[0] = (u8)(GTP_REG_RAW_DATA_GT9F >> 8); + read_rawbuf[1] = (u8)(GTP_REG_RAW_DATA_GT9F); + } + else + { + read_rawbuf[0] = (u8)(GTP_REG_RAW_DATA >> 8); + read_rawbuf[1] = (u8)(GTP_REG_RAW_DATA); + } + + ret = gtp_i2c_read(client, read_rawbuf, GTP_ADDR_LENGTH + ((gt9xx_drv_num*gt9xx_sen_num)*2)); + if (ret <= 0) + { + GTP_DEBUG("i2c read rawdata failed."); + goto have_error; + } + gtp_i2c_end_cmd(client); + + if (endian_mode() == MYBIG_ENDIAN) + { + head = 0; + tail = 1; + GTP_DEBUG("Big Endian."); + } + else + { + head = 1; + tail = 0; + GTP_DEBUG("Little Endian."); + } + + GTP_DEBUG("---read raw data-----\n"); + + sprintf(temp, "tx: %d\n", gt9xx_drv_num); + sprintf(raw_data, temp); + sprintf(temp, "rx: %d\n", gt9xx_sen_num); + strcat(raw_data, temp); + + for (i = 0, j = 0; i < ((gt9xx_drv_num*gt9xx_sen_num)*2); i+=2) + { + data[i/2] = (u16)(read_rawbuf[i+head+GTP_ADDR_LENGTH]<<8) + (u16)read_rawbuf[GTP_ADDR_LENGTH+i+tail]; + #if 1 + sprintf(temp, "%-5d ", data[i/2]); + strcat(raw_data, temp); + ++j; + if ((j%28) == 0){ + sprintf(temp, "\n"); + strcat(raw_data, temp); + } + #endif + } + + kfree(read_rawbuf); + return SUCCESS; +have_error: + kfree(read_rawbuf); + return FAIL; +} + +s32 gtp_read_refrawdata(struct i2c_client *client, u16 *data) +{ + s32 ret = -1; + u16 retry = 0; + u8 read_state[3] = {(u8)(GTP_REG_RAW_READY>>8), (u8)GTP_REG_RAW_READY, 0}; + u16 i = 0, j = 0; + u8 *read_rawbuf; + u8 tail, head; + u8 temp[20]; + + read_rawbuf = (u8*)kmalloc(sizeof(u8) * (gt9xx_drv_num*gt9xx_sen_num * 2 + GTP_ADDR_LENGTH), GFP_KERNEL); + + if (NULL == read_rawbuf) + { + GTP_DEBUG("failed to allocate for read_rawbuf"); + return FAIL; + } + + if (data == NULL) + { + GTP_DEBUG("Invalid raw buffer."); + goto have_error; + } + + msleep(10); + while (retry++ < GTP_WAIT_RAW_MAX_TIMES) + { + ret = gtp_i2c_read(client, read_state, 3); + if (ret <= 0) + { + GTP_DEBUG("i2c read failed.return: %d", ret); + continue; + } + if ((read_state[GTP_ADDR_LENGTH] & 0x80) == 0x80) + { + GTP_DEBUG("Raw data is ready."); + break; + } + if ((retry%20) == 0) + { + GTP_DEBUG("(%d)read_state[2] = 0x%02X", retry, read_state[GTP_ADDR_LENGTH]); + if (retry == 100) + { + gt9_read_raw_cmd(client); + } + } + msleep(5); + } + if (retry >= GTP_WAIT_RAW_MAX_TIMES) + { + GTP_DEBUG("Wait raw data ready timeout."); + goto have_error; + } + + if (chip_type_gt9f) + { + read_rawbuf[0] = (u8)(GTP_REG_RAW_DATA_GT9F >> 8); + read_rawbuf[1] = (u8)(GTP_REG_RAW_DATA_GT9F); + } + else + { + read_rawbuf[0] = (u8)(GTP_REG_REFRAW_DATA >> 8); + read_rawbuf[1] = (u8)(GTP_REG_REFRAW_DATA); + } + + ret = gtp_i2c_read(client, read_rawbuf, GTP_ADDR_LENGTH + ((gt9xx_drv_num*gt9xx_sen_num)*2)); + GTP_DEBUG("%x-%x:\n", read_rawbuf[i], read_rawbuf[i+1]); + for (i = 0, j = 0; i < ((gt9xx_drv_num*gt9xx_sen_num)*2); i+=2) + { + GTP_DEBUG("%d-%d ", read_rawbuf[i+2], read_rawbuf[i+3]); + ++j; + if ((j%28) == 0) + GTP_DEBUG("\n"); + } + if (ret <= 0) + { + GTP_DEBUG("i2c read rawdata failed."); + goto have_error; + } + gtp_i2c_end_cmd(client); + + if (endian_mode() == MYBIG_ENDIAN) + { + head = 0; + tail = 1; + GTP_DEBUG("Big Endian."); + } + else + { + head = 1; + tail = 0; + GTP_DEBUG("Little Endian."); + } + + GTP_DEBUG("---read refraw data-----\n"); + + sprintf(temp, "tx: %d\n", gt9xx_drv_num); + sprintf(refraw_data, temp); + sprintf(temp, "rx: %d\n", gt9xx_sen_num); + strcat(refraw_data, temp); + + for (i = 0, j = 0; i < ((gt9xx_drv_num*gt9xx_sen_num)*2); i+=2) + { + data[i/2] = (u16)(read_rawbuf[i+head+GTP_ADDR_LENGTH]<<8) + (u16)read_rawbuf[GTP_ADDR_LENGTH+i+tail]; + #if 1 + sprintf(temp, "%-5d ", data[i/2]); + strcat(refraw_data, temp); + ++j; + if ((j%28) == 0){ + sprintf(temp, "\n"); + strcat(refraw_data, temp); + } + #endif + } + + kfree(read_rawbuf); + return SUCCESS; +have_error: + kfree(read_rawbuf); + return FAIL; +} + +/* +********************************************************************************************************* +* Function: +* rawdata test initilization function +* Input: +* u32 check_types: test items +********************************************************************************************************* +*/ +static s32 gtp_raw_test_init(void) +{ + u16 i = 0; + + test_rslt_buf = (s32*) kmalloc(sizeof(s32)*GTP_OPEN_SAMPLE_NUM, GFP_ATOMIC); + touchpad_sum = (struct gt9xx_open_info*) kmalloc(sizeof(struct gt9xx_open_info) * (4 * _BEYOND_INFO_MAX + 1), GFP_ATOMIC); + if (NULL == test_rslt_buf || NULL == touchpad_sum) + { + return FAIL; + } + memset(touchpad_sum, 0, sizeof(struct gt9xx_open_info) * (4 * _BEYOND_INFO_MAX + 1)); + + for (i = 0; i < (4 * _BEYOND_INFO_MAX); ++i) + { + touchpad_sum[i].driver = 0xFF; + } + + for (i = 0; i < GTP_OPEN_SAMPLE_NUM; i++) + { + test_rslt_buf[i] = _CHANNEL_PASS; + } + return SUCCESS; +} + +/** + * ============================ + * @Author: HQ-zmc + * @Version: 1.0 + * @DateTime: 2018-01-31 19:44:25 + * @input: + * @output: + * ============================ + */ +/*Modifiy by HQ-zmc [Date: 2018-04-10 11:46:05]*/ +#define HQ_GTP_TP_DATA_DUMP "hq_tp_data_dump" +static struct proc_dir_entry *hq_gtp_data_dump_proc = NULL; + +static int hq_tp_data_dump_proc_show(struct seq_file *m, void *v) { + seq_printf(m, "%s\n", diff_data); + seq_printf(m, "%s\n", raw_data); + seq_printf(m, "%s\n", refraw_data); + + return 0; +} + +static int hq_tp_data_dump_proc_open(struct inode *inode, struct file *file) { + s32 ret = FAIL; + struct goodix_ts_data *ts; + u16 *raw_buf = NULL; + struct i2c_client *client = i2c_connect_client; + + + + ts = i2c_get_clientdata(client); + + GTP_DEBUG("---gtp open test---"); + GTP_DEBUG("Parsing configuration..."); + + ret = gtp_parse_config(client); + if (ret == FAIL) + { + GTP_DEBUG("failed to parse config..."); + ret = FAIL; + goto open_test_exit; + } + raw_buf = (u16*)kmalloc(sizeof(u16)* (gt9xx_drv_num*gt9xx_sen_num), GFP_KERNEL); + if (NULL == raw_buf) + { + GTP_DEBUG("failed to allocate mem for raw_buf!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("\nStep 1: Send Rawdata Cmd"); + + ret = gtp_raw_test_init(); + if (FAIL == ret) + { + GTP_DEBUG("Allocate memory for open test failed!"); + ret = FAIL; + goto open_test_exit; + } + ret = gt9_read_raw_cmd(client); + if (ret == FAIL) + { + GTP_DEBUG("Send Read Rawdata Cmd failed!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("Step 2: Sample Diffdata"); + + ret = gtp_read_diffdata(client, raw_buf); + if (ret == FAIL) + { + GTP_DEBUG("Read Diffdata failed!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("Step 3: Sample Rawdata"); + ret = gtp_read_rawdata(client, raw_buf); + if (ret == FAIL) + { + GTP_DEBUG("Read Rawdata failed!"); + ret = FAIL; + goto open_test_exit; + } + + + GTP_DEBUG("Step 4: Sample RefRawdata"); + ret = gtp_read_refrawdata(client, raw_buf); + if (ret == FAIL) + { + GTP_DEBUG("Read RefRawdata failed!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("Step 5: Analyse Result"); + GTP_DEBUG("Total %d Sample Data, Max Show %d Info for each Test Item", GTP_OPEN_SAMPLE_NUM, _BEYOND_INFO_MAX); +open_test_exit: + if (raw_buf) + { + kfree(raw_buf); + } + if (test_rslt_buf) + { + kfree(test_rslt_buf); + test_rslt_buf = NULL; + } + if (touchpad_sum) + { + kfree(touchpad_sum); + touchpad_sum = NULL; + } + + gt9_read_coor_cmd(client); + GTP_DEBUG("---gtp open test end---"); + + return single_open(file, hq_tp_data_dump_proc_show, NULL); +} + +static const struct file_operations hq_tp_data_dump_proc_fops = { + .owner = THIS_MODULE, + .open = hq_tp_data_dump_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + + + +#define GTP_TP_DATA_DUMP "tp_data_dump" +static struct proc_dir_entry *gtp_data_dump_proc = NULL; + +static int tp_data_dump_proc_show(struct seq_file *m, void *v) { + seq_printf(m, "%s\n", diff_data); + seq_printf(m, "%s\n", raw_data); + + return 0; +} + +static int tp_data_dump_proc_open(struct inode *inode, struct file *file) { + s32 ret = FAIL; + struct goodix_ts_data *ts; + short *raw_buf = NULL; + struct i2c_client *client = i2c_connect_client; + + + + ts = i2c_get_clientdata(client); + + GTP_DEBUG("---gtp open test---"); + GTP_DEBUG("Parsing configuration..."); + + ret = gtp_parse_config(client); + if (ret == FAIL) + { + GTP_DEBUG("failed to parse config..."); + ret = FAIL; + goto open_test_exit; + } + raw_buf = (short*)kmalloc(sizeof(short)* (gt9xx_drv_num*gt9xx_sen_num), GFP_KERNEL); + if (NULL == raw_buf) + { + GTP_DEBUG("failed to allocate mem for raw_buf!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("\nStep 1: Send Rawdata Cmd"); + + ret = gtp_raw_test_init(); + if (FAIL == ret) + { + GTP_DEBUG("Allocate memory for open test failed!"); + ret = FAIL; + goto open_test_exit; + } + ret = gt9_read_raw_cmd(client); + if (ret == FAIL) + { + GTP_DEBUG("Send Read Rawdata Cmd failed!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("Step 2: Sample Diffdata"); + + ret = gtp_read_diffdata(client, raw_buf); + if (ret == FAIL) + { + GTP_DEBUG("Read Diffdata failed!"); + ret = FAIL; + goto open_test_exit; + } + + GTP_DEBUG("Step 3: Sample Rawdata"); + ret = gtp_read_rawdata(client, raw_buf); + if (ret == FAIL) + { + GTP_DEBUG("Read Rawdata failed!"); + ret = FAIL; + goto open_test_exit; + } + GTP_DEBUG("Step 4: Analyse Result"); + GTP_DEBUG("Total %d Sample Data, Max Show %d Info for each Test Item", GTP_OPEN_SAMPLE_NUM, _BEYOND_INFO_MAX); +open_test_exit: + if (raw_buf) + { + kfree(raw_buf); + } + if (test_rslt_buf) + { + kfree(test_rslt_buf); + test_rslt_buf = NULL; + } + if (touchpad_sum) + { + kfree(touchpad_sum); + touchpad_sum = NULL; + } + + gt9_read_coor_cmd(client); + GTP_DEBUG("---gtp open test end---"); + + return single_open(file, tp_data_dump_proc_show, NULL); +} + +static const struct file_operations tp_data_dump_proc_fops = { + .owner = THIS_MODULE, + .open = tp_data_dump_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int create_gtp_data_dump_proc(void){ + int ret = 0; + + GTP_DEBUG("%s:ENTER FUNC ---- %d\n", __func__, __LINE__); + gtp_data_dump_proc = proc_create(GTP_TP_DATA_DUMP, 0444, NULL, &tp_data_dump_proc_fops); + if (gtp_data_dump_proc == NULL){ + GTP_DEBUG("fts, create_proc_entry tp_data_dump_proc failed\n"); + ret = -1; + } + + hq_gtp_data_dump_proc = proc_create(HQ_GTP_TP_DATA_DUMP, 0444, NULL, &hq_tp_data_dump_proc_fops); + if (hq_gtp_data_dump_proc == NULL){ + GTP_DEBUG("fts, create_proc_entry hq_gtp_data_dump_proc failed\n"); + ret = -1; + } + return ret; +} diff --git a/drivers/input/touchscreen/gt917d/gt9xx_openshort.h b/drivers/input/touchscreen/gt917d/gt9xx_openshort.h new file mode 100644 index 0000000000000..f84347a59bb08 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx_openshort.h @@ -0,0 +1,105 @@ +/* drivers/input/touchscreen/gt9xx_shorttp.h + * + * 2010 - 2012 Goodix Technology. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version:1.0 + * V1.0:2012/10/20 + */ + + +#ifndef _GT9XX_OPEN_SHORT_H_ +#define _GT9XX_OPEN_SHORT_H_ + +#include "gt9xx.h" + +#define MIN_DRIVER_NUM 10 +#define MAX_DRIVER_NUM 42 +#define MIN_SENSOR_NUM 5 +#define MAX_SENSOR_NUM 30 + +#define GT9_DRV_HEAD 0x80 +#define GT9_SEN_HEAD 0x00 + +#define _bRW_MISCTL__SRAM_BANK 0x4048 +#define _bRW_MISCTL__MEM_CD_EN 0x4049 +#define _bRW_MISCTL__CACHE_EN 0x404b +#define _bRW_MISCTL__TMR0_EN 0x40b0 +#define _rRW_MISCTL__SWRST_B0_ 0x4180 +#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184 +#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190 +#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218 +#define _bRW_MISCTL__RG_OSC_CALIB 0x4268 +#define _rRW_MISCTL__BOOT_CTL_ 0x5094 +#define _rRW_MISCTL__SHORT_BOOT_FLAG 0x5095 + + +#define GTP_REG_DSP_SHORT 0xc000 + +#define GT9_REG_SEN_DRV_CNT 0x8062 +#define GT9_REG_CFG_BEG 0x8047 +#define GT9_REG_KEY_VAL 0x8093 + +#define GT9_REG_SEN_ORD 0x80B7 +#define GT9_REG_DRV_ORD 0x80D5 + + +struct gt9xx_short_info +{ + u8 master; + u8 master_is_driver; + u8 slave; + u8 slave_is_driver; + u16 short_code; + u16 self_data; + u16 impedance; +}; + +#define MYBIG_ENDIAN 1 +#define MYLITLE_ENDIAN 0 + +#define _BEYOND_MAX_LIMIT 0x0001 +#define _BEYOND_MIN_LIMIT 0x0002 +#define _BEYOND_KEY_MAX_LMT 0x0004 +#define _BEYOND_KEY_MIN_LMT 0x0008 +#define _BEYOND_UNIFORMITY_LMT 0x0010 + +#define _MAX_TEST 0x0001 +#define _MIN_TEST 0x0002 +#define _KEY_MAX_TEST 0x0004 +#define _KEY_MIN_TEST 0x0008 +#define _UNIFORMITY_TEST 0x0010 + +#define _CHANNEL_PASS 0x0000 + +#define GTP_WAIT_RAW_MAX_TIMES 200 +#define GTP_REG_RAW_DATA 0x9b60 +#define GTP_REG_READ_RAW 0x8040 +#define GTP_REG_RAW_READY 0x814E +#define GTP_REG_RAW_DATA_GT9F 0x87C0 +#define GTP_REG_DIFF_DATA 0xA160 +#define GTP_REG_REFRAW_DATA 0x9560 + +struct gt9xx_open_info +{ + u8 driver; + u8 sensor; + u16 raw_val; + s32 beyond_type; + u8 times; + u8 key; +}; + + +#endif + diff --git a/drivers/input/touchscreen/gt917d/gt9xx_selftest.c b/drivers/input/touchscreen/gt917d/gt9xx_selftest.c new file mode 100644 index 0000000000000..ceba67adcb2db --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx_selftest.c @@ -0,0 +1,2263 @@ +/* drivers/input/touchscreen/gt9xx_shorttp.c + * + * 2010 - 2012 Goodix Technology. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version:1.0 + * Author: meta@goodix.com + * Accomplished Date:2012/10/20 + * Revision record: + * + */ + +#include "gt9xx_selftest.h" +#include "gt9xx.h" + +/************** Customer Config Start ***********************/ +#define GTP_SHORT_GND +#define GTP_VDD 33 + +#define DEFAULT_TEST_ITEMS (_MAX_TEST | _MIN_TEST | _KEY_MAX_TEST | _KEY_MIN_TEST /*| _UNIFORMITY_TEST*/) + +u16 max_limit_value = 6000; +u16 min_limit_value = 2500; +u16 min_limit_value_LH = 800; +u16 max_limit_key = 1500; +u16 min_limit_key = 800; +u16 uniformity_lmt = 50; +#define DSP_SHORT_BURN_CHK 256 +#define _SHORT_INFO_MAX 50 +#define _BEYOND_INFO_MAX 20 +#define GTP_OPEN_SAMPLE_NUM 16 +#define GTP_TEST_INFO_MAX 200 + +static struct proc_dir_entry *gt9xx_selftest_proc; +static struct proc_dir_entry *gt9xx_datadump_proc; +int gt9xx_test_result = RESULT_INVALID; +extern s32 gtp_read_version(struct i2c_client *client, u16 *version); + +extern struct i2c_client *i2c_connect_client; + +u8 gt9xx_drv_num = MAX_DRIVER_NUM; +u8 gt9xx_sen_num = MAX_SENSOR_NUM; +u16 gt9xx_pixel_cnt = MAX_DRIVER_NUM * MAX_SENSOR_NUM; +u16 gt9xx_sc_pxl_cnt = MAX_DRIVER_NUM * MAX_SENSOR_NUM; +struct gt9xx_short_info *short_sum; + +u8 chip_type_gt9f; +u8 have_key; +u8 gt9xx_sc_drv_num; +u8 key_is_isolated; +u8 key_iso_pos[5]; + +struct kobject *goodix_debug_kobj; +static u8 rslt_buf_idx; +static s32 *test_rslt_buf; +static struct gt9xx_open_info *touchpad_sum; + +#define _MIN_ERROR_NUM (GTP_OPEN_SAMPLE_NUM * 9 / 10) + +static char *result_lines[GTP_TEST_INFO_MAX]; +static char tmp_info_line[80]; +static u16 RsltIndex; + +static void append_info_line(void) +{ + if (strlen(tmp_info_line) != 0) { + result_lines[RsltIndex] = (char *)kzalloc(strlen(tmp_info_line) + 1, GFP_KERNEL); + memcpy(result_lines[RsltIndex], tmp_info_line, strlen(tmp_info_line)); + } + + if (RsltIndex != (GTP_TEST_INFO_MAX - 1)) + ++RsltIndex; + else { + kfree(result_lines[RsltIndex]); + } +} + + +#define SET_INFO_LINE_INFO(fmt, args...) do { memset(tmp_info_line, '\0', 80);\ + snprintf(tmp_info_line, 80, ""fmt"\n", ##args);\ + pr_info(fmt, ##args);\ + append_info_line();\ + } while (0) + +#define SET_INFO_LINE_ERR(fmt, args...) do { memset(tmp_info_line, '\0', 80);\ + snprintf(tmp_info_line, 80, ""fmt"\n", ##args);\ + pr_err(fmt, ##args);\ + append_info_line();\ + } while (0) + + +static u8 cfg_drv_order[MAX_DRIVER_NUM]; +static u8 cfg_sen_order[MAX_SENSOR_NUM]; + +static s32 gt9xx_open_send_cfg(struct i2c_client *client) +{ + u32 ret = 0, i = 0; + int retry = 0; + u8 check_sum; + struct goodix_ts_data *ts = i2c_get_clientdata(client); + struct goodix_config_data *cfg = &ts->pdata->config; + + check_sum = 0; + + for (i = GTP_ADDR_LENGTH; i < cfg->length; i++) + check_sum += config[i]; + config[cfg->length] = (~check_sum) + 1; + dev_info(&ts->client->dev, "Driver send config\n"); + for (retry = 0; retry < RETRY_MAX_TIMES; retry++) { + ret = gtp_i2c_write(client, config, + GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + + if (ret > 0) + break; + } + return ret; +} +/* + * Initialize cfg_drv_order and cfg_sen_order, which is used for report short channels + * + */ + +static s32 gt9xx_short_parse_cfg(void) +{ + u8 i = 0; + u8 drv_num = 0, sen_num = 0; + + drv_num = (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT - GT9_REG_CFG_BEG] & 0x1F) + + (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT + 1 - GT9_REG_CFG_BEG] & 0x1F); + sen_num = (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT + 2 - GT9_REG_CFG_BEG] & 0x0F) + + ((config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT + 2 - GT9_REG_CFG_BEG] >> 4) & 0x0F); + + if (drv_num < MIN_DRIVER_NUM || drv_num > MAX_DRIVER_NUM) { + pr_err("driver number error!"); + return FAIL; + } + + if (sen_num < MIN_SENSOR_NUM || sen_num > MAX_SENSOR_NUM) { + pr_err("sensor number error!"); + return FAIL; + } + + memset(cfg_sen_order, 0xFF, MAX_SENSOR_NUM); + + for (i = 0; i < sen_num; ++i) { + cfg_sen_order[i] = config[GTP_ADDR_LENGTH + GT9_REG_SEN_ORD - GT9_REG_CFG_BEG + i]; + } + + memset(cfg_drv_order, 0xFF, MAX_DRIVER_NUM); + + for (i = 0; i < drv_num; ++i) { + cfg_drv_order[i] = config[GTP_ADDR_LENGTH + GT9_REG_DRV_ORD - GT9_REG_CFG_BEG + i]; + } + + return SUCCESS; +} + +/* + * @param: + * phy_chnl: ic detected short channel, is_driver: it's driver or not + * @Return: + * 0xff: the ic channel is not used, otherwise: the tp short channel + */ +static u8 gt9_get_short_tp_chnl(u8 phy_chnl, u8 is_driver) +{ + u8 i = 0; + + if (is_driver) { + for (i = 0; i < MAX_DRIVER_NUM; ++i) { + if (cfg_drv_order[i] == phy_chnl) { + return i; + } else if (cfg_drv_order[i] == 0xFF) { + return 0xFF; + } + } + } else { + for (i = 0; i < MAX_SENSOR_NUM; ++i) { + if (cfg_sen_order[i] == phy_chnl) { + return i; + } else if (cfg_sen_order[i] == 0xFF) { + return 0xFF; + } + } + } + + return 0xFF; +} + +static s32 gtp_i2c_end_cmd(struct i2c_client *client) +{ + u8 end_cmd[3] = {GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0}; + s32 ret = 0; + + ret = gtp_i2c_write(client, end_cmd, 3); + + if (ret < 0) { + SET_INFO_LINE_INFO("I2C write end_cmd error!"); + } + + return ret; +} + +static void gtp_hopping_switch(struct i2c_client *client, s32 on) +{ + s32 j = 0; + u8 hopping_enabled = 0; + u8 chksum = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(client); + struct goodix_config_data *cfg = &ts->pdata->config; + + if (!on) { + if (config[GTP_ADDR_LENGTH + 0x807D - GTP_REG_CONFIG_DATA] & 0x80) { + pr_info("Disable hopping."); + config[GTP_ADDR_LENGTH + 0x807D - GTP_REG_CONFIG_DATA] &= 0x7F; + + for (j = 0; j < (cfg->length - 2); ++j) { + chksum += config[GTP_ADDR_LENGTH + j]; + } + + config[cfg->length] = (~chksum) + 1; + config[cfg->length + 1] = 0x01; + gtp_i2c_write(client, config, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + hopping_enabled = 1; + msleep(300); + } + } else if (hopping_enabled) { + if (0x00 == (config[GTP_ADDR_LENGTH + 0x807D - GTP_REG_CONFIG_DATA] & 0x80)) { + pr_info("Enable hopping."); + config[GTP_ADDR_LENGTH + 0x807D - GTP_REG_CONFIG_DATA] |= 0x80; + + for (j = 0; j < (cfg->length - 2); ++j) { + chksum += config[GTP_ADDR_LENGTH + j]; + } + + config[cfg->length] = (~chksum) + 1; + config[cfg->length + 1] = 0x01; + gtp_i2c_write(client, config, GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH); + hopping_enabled = 0; + msleep(300); + } + } +} + +static s32 gtp_parse_config(struct i2c_client *client) +{ + u8 i = 0; + u8 key_pos = 0; + u8 key_val = 0; + u8 type_buf[12] = {0x80, 0x00}; + + gt9xx_drv_num = (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT - GT9_REG_CFG_BEG] & 0x1F) + + (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT + 1 - GT9_REG_CFG_BEG] & 0x1F); + gt9xx_sen_num = (config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT + 2 - GT9_REG_CFG_BEG] & 0x0F) + + ((config[GTP_ADDR_LENGTH + GT9_REG_SEN_DRV_CNT + 2 - GT9_REG_CFG_BEG] >> 4) & 0x0F); + pr_info("Driver num: %d, Sensor Num: %d", gt9xx_drv_num, gt9xx_sen_num); + + if (gt9xx_drv_num < MIN_DRIVER_NUM || gt9xx_drv_num > MAX_DRIVER_NUM) { + SET_INFO_LINE_ERR("driver number error!"); + return FAIL; + } + + if (gt9xx_sen_num < MIN_SENSOR_NUM || gt9xx_sen_num > MAX_SENSOR_NUM) { + SET_INFO_LINE_ERR("sensor number error!"); + return FAIL; + } + + gt9xx_sc_pxl_cnt = gt9xx_pixel_cnt = gt9xx_drv_num * gt9xx_sen_num; + gtp_i2c_read(client, type_buf, 12); + + if (!memcmp(&type_buf[2], "GOODIX_GT9", 10)) { + chip_type_gt9f = 0; + pr_info("Chip type: GT9XX"); + } else { + chip_type_gt9f = 1; + pr_info("Chip type: GT9XXF"); + } + + have_key = config[0x804E - GT9_REG_CFG_BEG + GTP_ADDR_LENGTH] & 0x01; + + if (!have_key) { + pr_info("No key"); + return SUCCESS; + } + + pr_info("Have Key"); + gt9xx_sc_drv_num = gt9xx_drv_num - 1; + + for (i = 0; i < 5; ++i) { + key_iso_pos[i] = 0; + } + + key_is_isolated = 0; + + for (i = 0; i < 4; ++i) { + /* all keys are multiples of 0x08 -> isolated keys */ + key_val = config[GTP_ADDR_LENGTH + GT9_REG_KEY_VAL - GT9_REG_CFG_BEG + i]; + key_pos = key_val % 0x08; + GTP_DEBUG("key_val[%d] = 0x%02x", i + 1, key_val); + + if ((key_pos != 0)) { + key_is_isolated = 0; + GTP_DEBUG("Key is not isolated!"); + break; + } else if (key_val == 0x00) { + continue; + } else { + key_iso_pos[0]++; + key_iso_pos[i + 1] = key_val / 0x08 - 1; + key_is_isolated = 1; + } + } + + gt9xx_sc_pxl_cnt = gt9xx_pixel_cnt - (gt9xx_drv_num - gt9xx_sc_drv_num) * gt9xx_sen_num; + GTP_DEBUG("drv num: %d, sen num: %d, sc drv num: %d", gt9xx_drv_num, gt9xx_sen_num, gt9xx_sc_drv_num); + + if (key_is_isolated) { + GTP_DEBUG("Isolated [%d key(s)]: %d, %d, %d, %d", key_iso_pos[0], key_iso_pos[1], key_iso_pos[2], key_iso_pos[3], key_iso_pos[4]); + } + + return SUCCESS; +} + +/* + * Function: + * write one byte to specified register + * Input: + * reg: the register address + * val: the value to write into + * Return: + * i2c_write function return + */ +static s32 gtp_write_register(struct i2c_client *client, u16 reg, u8 val) +{ + u8 buf[3]; + + buf[0] = (u8)(reg >> 8); + buf[1] = (u8) reg; + buf[2] = val; + return gtp_i2c_write(client, buf, 3); +} + +/* + * Function: + * read one byte from specified register into buf + * Input: + * reg: the register + * buf: the buffer for one byte + * Return: + * i2c_read function return + */ +static s32 gtp_read_register(struct i2c_client *client, u16 reg, u8 *buf) +{ + buf[0] = (u8)(reg >> 8); + buf[1] = (u8)reg; + return gtp_i2c_read(client, buf, 3); +} + +/* + * Function: + * burn dsp_short code + * Input: + * i2c_client + * Return: + * SUCCESS: burning succeed, FAIL: burning failed + */ +static s32 gtp_burn_dsp_short(struct i2c_client *client) +{ + s32 ret = 0; + u8 *opr_buf; + u16 i = 0; + u16 addr = GTP_REG_DSP_SHORT; + u16 opr_len = 0; + u16 left = 0; + u16 retry = 0; + u8 read_buf[3] = {0x00}; + + GTP_DEBUG("Start writing dsp_short code"); + opr_buf = (u8 *)kzalloc(sizeof(u8) * (DSP_SHORT_BURN_CHK + 2), GFP_KERNEL); + + if (!opr_buf) { + SET_INFO_LINE_ERR("failed to allocate memory for check buffer!"); + return FAIL; + } + + left = sizeof(dsp_short); + + while (left > 0) { + opr_buf[0] = (u8)(addr >> 8); + opr_buf[1] = (u8)(addr); + + if (left > DSP_SHORT_BURN_CHK) { + opr_len = DSP_SHORT_BURN_CHK; + } else { + opr_len = left; + } + + memcpy(&opr_buf[2], &dsp_short[addr - GTP_REG_DSP_SHORT], opr_len); + ret = gtp_i2c_write(client, opr_buf, 2 + opr_len); + + if (ret < 0) { + pr_err("write dsp_short code failed!"); + kfree(opr_buf); + return FAIL; + } + + addr += opr_len; + left -= opr_len; + } + + /* check code: 0xC000~0xCFFF */ + GTP_DEBUG("Start checking dsp_short code"); + addr = GTP_REG_DSP_SHORT; + left = sizeof(dsp_short); + + while (left > 0) { + memset(opr_buf, 0, opr_len + 2); + opr_buf[0] = (u8)(addr >> 8); + opr_buf[1] = (u8)(addr); + + if (left > DSP_SHORT_BURN_CHK) { + opr_len = DSP_SHORT_BURN_CHK; + } else { + opr_len = left; + } + + ret = gtp_i2c_read(client, opr_buf, opr_len + 2); + + if (ret < 0) { + kfree(opr_buf); + return FAIL; + } + + for (i = 0; i < opr_len; ++i) { + if (opr_buf[i + 2] != dsp_short[addr - GTP_REG_DSP_SHORT + i]) { + pr_err("check dsp_short code failed!"); + gtp_write_register(client, addr + i, dsp_short[addr - GTP_REG_DSP_SHORT + i]); + GTP_DEBUG("(%d)Location: %d, 0x%02X, 0x%02X", retry + 1, addr - GTP_REG_DSP_SHORT + i, opr_buf[i + 2], dsp_short[addr - GTP_REG_DSP_SHORT + i]); + msleep(1); + gtp_read_register(client, addr + i, read_buf); + opr_buf[i + 2] = read_buf[2]; + i--; + retry++; + + if (retry >= 200) { + GTP_DEBUG("Burn dsp retry timeout!"); + kfree(opr_buf); + return FAIL; + } + } + } + + addr += opr_len; + left -= opr_len; + } + + kfree(opr_buf); + return SUCCESS; +} + +/* + * Function: + * check the resistor between shortlike channels if less than threshold confirm as short + * INPUT: + * Short like Information struct pointer + * Returns: + * SUCCESS: it's shorted FAIL: otherwise + */ + +static s32 gtp_short_resist_check(struct gt9xx_short_info *short_node) +{ + s32 short_resist = 0; + struct gt9xx_short_info *node = short_node; + u8 master = node->master; + u8 slave = node->slave; + u8 chnnl_tx[4] = { GT9_DRV_HEAD | 13, GT9_DRV_HEAD | 28, + GT9_DRV_HEAD | 29, GT9_DRV_HEAD | 42}; + s32 numberator = 0; + u32 amplifier = 1000; + + /* Tx-ABIST & Tx_ABIST */ + if ((((master > chnnl_tx[0]) && (master <= chnnl_tx[1])) && + ((slave > chnnl_tx[0]) && (slave <= chnnl_tx[1]))) || + (((master >= chnnl_tx[2]) && (master <= chnnl_tx[3])) && + ((slave >= chnnl_tx[2]) && (slave <= chnnl_tx[3])))) { + numberator = node->self_data * 40 * amplifier; + short_resist = numberator / (node->short_code) - 40 * amplifier; + } + /* Receiver is Rx-odd(1,3,5) */ + else if ((node->slave & (GT9_DRV_HEAD | 0x01)) == 0x01) { + numberator = node->self_data * 60 * amplifier; + short_resist = numberator / node->short_code - 40 * amplifier; + } else { + numberator = node->self_data * 60 * amplifier; + short_resist = numberator / node->short_code - 60 * amplifier; + } + + GTP_DEBUG("self_data = %d", node->self_data); + GTP_DEBUG("master = 0x%02X, slave = 0x%02X", node->master, node->slave); + GTP_DEBUG("short_code = %d, short_resist = %d", node->short_code, short_resist); + + if (short_resist < 0) { + short_resist = 0; + } + + if (short_resist < (gt900_resistor_threshold * amplifier)) { + node->impedance = short_resist / amplifier; + return SUCCESS; + } else { + return FAIL; + } +} + +/* + * Function: + * compute the result, whether there are shorts or not + * Input: + * i2c_client + * Return: + * SUCCESS + */ +static s32 gtp_compute_rslt(struct i2c_client *client) +{ + u16 short_code; + u8 i = 0, j = 0; + u16 result_addr; + u8 *result_buf; + u16 *self_data; + s32 ret = 0; + u16 data_len = 3 + (MAX_DRIVER_NUM + MAX_SENSOR_NUM) * 2 + 2; + struct gt9xx_short_info short_node; + u16 node_idx = 0; + u8 tx_short_num = 0; + u8 rx_short_num = 0; + u8 master, slave; + + self_data = (u16 *)kzalloc(sizeof(u16) * ((MAX_DRIVER_NUM + MAX_SENSOR_NUM)), GFP_KERNEL); + result_buf = (u8 *)kzalloc(sizeof(u8) * (data_len + 2), GFP_KERNEL); + short_sum = (struct gt9xx_short_info *) kzalloc(sizeof(struct gt9xx_short_info) * _SHORT_INFO_MAX, GFP_KERNEL); + + if (!self_data || !result_buf || !short_sum) { + SET_INFO_LINE_ERR("allocate memory for short result failed!"); + + if (self_data) { + kfree(self_data); + } + + if (result_buf) { + kfree(self_data); + } + + if (short_sum) { + kfree(short_sum); + } + + return FAIL; + } + + /* Get Selfdata */ + result_buf[0] = 0xA4; + result_buf[1] = 0xA1; + gtp_i2c_read(client, result_buf, 2 + 144); + + for (i = 0, j = 0; i < 144; i += 2) { + self_data[j++] = (u16)(result_buf[2 + i] << 8) + (u16)(result_buf[2 + i + 1]); + } + + GTP_DEBUG("Self Data:"); + GTP_DEBUG_ARRAY(result_buf + 2, 144); + result_buf[0] = 0x88; + result_buf[1] = 0x02; + gtp_i2c_read(client, result_buf, 2 + 2); + tx_short_num = result_buf[2]; + rx_short_num = result_buf[3]; + GTP_DEBUG("Tx Short Num: %d, Rx Short Num: %d", tx_short_num, rx_short_num); + result_addr = 0x8860; + data_len = 3 + (MAX_DRIVER_NUM + MAX_SENSOR_NUM) * 2 + 2; + + for (i = 0; i < tx_short_num; ++i) { + result_buf[0] = (u8)(result_addr >> 8); + result_buf[1] = (u8)(result_addr); + ret = gtp_i2c_read(client, result_buf, data_len + 2); + + if (ret < 0) { + SET_INFO_LINE_ERR("read result data failed!"); + } + + GTP_DEBUG("Result Buffer: "); + GTP_DEBUG_ARRAY(result_buf + 2, data_len); + short_node.master_is_driver = 1; + short_node.master = result_buf[2]; + + /* Tx - Tx */ + for (j = i + 1; j < MAX_DRIVER_NUM; ++j) { + short_code = (result_buf[2 + 3 + j * 2] << 8) + result_buf[2 + 3 + j * 2 + 1]; + + if (short_code > gt900_short_threshold) { + short_node.slave_is_driver = 1; + short_node.slave = ChannelPackage_TX[j] | GT9_DRV_HEAD; + short_node.self_data = self_data[j]; + short_node.short_code = short_code; + ret = gtp_short_resist_check(&short_node); + + if (ret == SUCCESS) { + if (node_idx < _SHORT_INFO_MAX) { + short_sum[node_idx++] = short_node; + } + } + } + } + + /* Tx - Rx */ + for (j = 0; j < MAX_SENSOR_NUM; ++j) { + short_code = (result_buf[2 + 3 + 84 + j * 2] << 8) + result_buf[2 + 3 + 84 + j * 2 + 1]; + + if (short_code > gt900_short_threshold) { + short_node.slave_is_driver = 0; + short_node.slave = j | GT9_SEN_HEAD; + short_node.self_data = self_data[MAX_DRIVER_NUM + j]; + short_node.short_code = short_code; + ret = gtp_short_resist_check(&short_node); + + if (ret == SUCCESS) { + if (node_idx < _SHORT_INFO_MAX) { + short_sum[node_idx++] = short_node; + } + } + } + } + + result_addr += data_len; + } + + result_addr = 0xA0D2; + data_len = 3 + MAX_SENSOR_NUM * 2 + 2; + + for (i = 0; i < rx_short_num; ++i) { + result_buf[0] = (u8)(result_addr >> 8); + result_buf[1] = (u8)(result_addr); + ret = gtp_i2c_read(client, result_buf, data_len + 2); + + if (ret < 0) { + SET_INFO_LINE_ERR("read result data failed!"); + } + + GTP_DEBUG("Result Buffer: "); + GTP_DEBUG_ARRAY(result_buf + 2, data_len); + short_node.master_is_driver = 0; + short_node.master = result_buf[2]; + + /* Rx - Rx */ + for (j = 0; j < MAX_SENSOR_NUM; ++j) { + if ((j == i) || ((j < i) && (j & 0x01) == 0)) { + continue; + } + + short_code = (result_buf[2 + 3 + j * 2] << 8) + result_buf[2 + 3 + j * 2 + 1]; + + if (short_code > gt900_short_threshold) { + short_node.slave_is_driver = 0; + short_node.slave = j | GT9_SEN_HEAD; + short_node.self_data = self_data[MAX_DRIVER_NUM + j]; + short_node.short_code = short_code; + ret = gtp_short_resist_check(&short_node); + + if (ret == SUCCESS) { + if (node_idx < _SHORT_INFO_MAX) { + short_sum[node_idx++] = short_node; + } + } + } + } + + result_addr += data_len; + } + + if (node_idx == 0) { + ret = SUCCESS; + } else { + for (i = 0, j = 0; i < node_idx; ++i) { + GTP_DEBUG("Orignal Shorted Channels: %s%d, %s%d", + (short_sum[i].master_is_driver) ? "Drv" : "Sen", short_sum[i].master & (~GT9_DRV_HEAD), + (short_sum[i].slave_is_driver) ? "Drv" : "Sen", short_sum[i].slave & (~GT9_DRV_HEAD)); + + if ((short_sum[i].master_is_driver)) { + master = gt9_get_short_tp_chnl(short_sum[i].master - GT9_DRV_HEAD, 1); + } else { + master = gt9_get_short_tp_chnl(short_sum[i].master, 0); + } + + if ((short_sum[i].slave_is_driver)) { + slave = gt9_get_short_tp_chnl(short_sum[i].slave - GT9_DRV_HEAD, 1); + } else { + slave = gt9_get_short_tp_chnl(short_sum[i].slave, 0); + } + + if (master == 0xFF && slave == 0xFF) { + GTP_DEBUG("unbonded channel (%d, %d) shorted!", short_sum[i].master, short_sum[i].slave); + continue; + } else { + short_sum[j].slave = slave; + short_sum[j].master = master; + short_sum[j].slave_is_driver = short_sum[i].slave_is_driver; + short_sum[j].master_is_driver = short_sum[i].master_is_driver; + short_sum[j].impedance = short_sum[i].impedance; + short_sum[j].self_data = short_sum[i].self_data; + short_sum[j].short_code = short_sum[i].short_code; + ++j; + } + } + + node_idx = j; + + if (node_idx == 0) { + ret = SUCCESS; + } else { + for (i = 0; i < node_idx; ++i) { + SET_INFO_LINE_INFO(" %s%02d & %s%02d Shorted! (R = %dKOhm)", + (short_sum[i].master_is_driver) ? "Drv" : "Sen", short_sum[i].master, + (short_sum[i].slave_is_driver) ? "Drv" : "Sen", short_sum[i].slave, + short_sum[i].impedance); + } + + ret = FAIL; + } + } + + kfree(self_data); + kfree(short_sum); + kfree(result_buf); + return ret; +} + +static s32 gt9_test_gnd_vdd_short(struct i2c_client *client) +{ + u8 *data; + s32 ret = 0; + s32 i = 0; + u16 len = (MAX_DRIVER_NUM + MAX_SENSOR_NUM) * 2; + u16 short_code = 0; + s32 r = -1; + u32 short_res = 0; + u8 short_chnl = 0; + u16 amplifier = 1000; + + data = (u8 *)kzalloc(sizeof(u8) * (len + 2), GFP_KERNEL); + if (NULL == data) { + SET_INFO_LINE_ERR("failed to allocate memory for gnd vdd test data buffer"); + return FAIL; + } + + data[0] = 0xA5; + data[1] = 0x31; + gtp_i2c_read(client, data, 2 + len); + GTP_DEBUG_ARRAY(data + 2, len); + ret = SUCCESS; + + for (i = 0; i < len; i += 2) { + short_code = (data[2 + i] << 8) + (data[2 + i + 1]); + + if (short_code == 0) { + continue; + } +/* short wirh GND*/ + if ((short_code & 0x8000) == 0) { +#ifdef GTP_SHORT_GND + r = 5266285 * 10 / (short_code & (~0x8000)) - 40 * amplifier; +#endif + /* short with VDD */ + } else { + /*r = ( 1/(((float)(short_code&(~0x8000)))/0.9*0.7/1024/(sys.avdd-0.9)/40) ) -40; */ +#ifdef GTP_VDD + r = 40 * 9 * 1024 * (100 * GTP_VDD - 900) / ((short_code & (~0x8000)) * 7) - 40 * 1000; + GTP_DEBUG("vdd short_code: %d", short_code & (~0x8000)); +#endif + } + + GTP_DEBUG("resistor: %d, short_code: %d", r, short_code); + short_res = (r >= 0) ? r : 0xFFFF; + + if (short_res == 0xFFFF) { + } else { + if (short_res < (gt900_gnd_resistor_threshold * amplifier)) { + if (i < MAX_DRIVER_NUM * 2) { + short_chnl = gt9_get_short_tp_chnl(ChannelPackage_TX[i / 2], 1); + pr_info("driver%02d & gnd/vdd shorted!", short_chnl); + + if (short_chnl == 0xFF) { + pr_info("unbonded channel"); + } else { + SET_INFO_LINE_INFO(" Drv%02d & GND/VDD Shorted! (R = %dKOhm)", short_chnl, short_res / amplifier); + } + } else { + short_chnl = gt9_get_short_tp_chnl((i / 2) - MAX_DRIVER_NUM, 0); + pr_info("sensor%02d & gnd/vdd shorted!", short_chnl); + + if (short_chnl == 0xFF) { + pr_info("unbonded channel"); + } else { + SET_INFO_LINE_INFO(" Sen%02d & GND/VDD Shorted! (R = %dKOhm)", short_chnl, short_res / amplifier); + } + } + + ret = FAIL; + } + } + } + + return ret; +} + +static void gt9xx_leave_short_test(struct i2c_client *client) +{ + gtp_reset_guitar(client, 20); + msleep(100); + gtp_send_cfg(client); + SET_INFO_LINE_INFO(""); + SET_INFO_LINE_INFO("---gtp short test end---"); +} + +/* + * Function: + * gt9 series ic short test function + * Input: + * I2c_client, i2c device + * Return: + * SUCCESS: test succeed, FAIL: test failed + */ +static s32 gt9xx_short_test(struct i2c_client *client) +{ + s32 ret = 0; + s32 ret2 = 0; + u8 i = 0; + u8 opr_buf[60] = {0}; + u8 retry = 0; + u8 drv_sen_chksum = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + u8 retry_load = 0; + u8 old_i2c_addr = client->addr; + + disable_irq(client->irq); +#ifdef GTP_ESD_PROTECT + ts->gtp_is_suspend = 1; +#endif + /* step 1: reset guitar, delay 1ms, hang up ss51 and dsp */ + SET_INFO_LINE_INFO("---gtp short test---"); + SET_INFO_LINE_INFO("Step 1: reset guitar, hang up ss51 dsp"); + ret = gt9xx_short_parse_cfg(); + + if (FAIL == ret) { + SET_INFO_LINE_ERR("You May check your IIC connection."); + goto short_test_exit; + } + +load_dsp_again: + gpio_direction_output(ts->pdata->rst_gpio, 0); + msleep(30); + gtp_int_output(ts, client->addr == 0x14); + usleep_range(2000, 3000); /* T3: > 100us (2ms)*/ + gpio_direction_output(ts->pdata->rst_gpio, 1); + usleep_range(6000, 7000); /* T4: > 5ms */ + msleep((retry_load) * 10); + + for (i = 0; i < 200; ++i) { + /* Hold ss51 & dsp */ + ret = gtp_write_register(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + /* DSP_CK and DSP_ALU_CK PowerOn*/ + ret2 = gtp_write_register(client, 0x4010, 0x00); + + if ((ret > 0) && (ret2 > 0)) { + break; + } + + msleep(2); + } + + if (i >= 200) { + SET_INFO_LINE_ERR("Failed to init short test mode"); + goto short_test_exit; + } + + msleep(10); + + while (retry++ < 200) { + /* Confirm hold */ + opr_buf[GTP_ADDR_LENGTH] = 0x00; + ret = gtp_read_register(client, _rRW_MISCTL__SWRST_B0_, opr_buf); + + if (ret <= 0) { + GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry); + gtp_reset_guitar(client, 10); + continue; + } + + if (0x0C == opr_buf[GTP_ADDR_LENGTH]) { + GTP_DEBUG("Hold ss51 & dsp confirm SUCCESS"); + break; + } + + ret = gtp_write_register(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + + if ((ret <= 0)) { + GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry); + gtp_reset_guitar(client, 10); + continue; + } + + GTP_DEBUG("Hold ss51 & dsp confirm 0x4180 failed,value:%d", opr_buf[GTP_ADDR_LENGTH]); + msleep(2); + } + + if (retry >= 200) { + SET_INFO_LINE_ERR("Enter update Hold ss51 failed."); + goto short_test_exit; + } + + /* step2: burn dsp_short code */ + pr_info("step 2: burn dsp_short code"); + /* clear watchdog */ + gtp_write_register(client, _bRW_MISCTL__TMR0_EN, 0x00); + /* clear cache */ + gtp_write_register(client, _bRW_MISCTL__CACHE_EN, 0x00); + /* boot from sram */ + gtp_write_register(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); + /* reset software + gtp_write_register(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); + */ + /* select bank0 */ + gtp_write_register(client, _bRW_MISCTL__SRAM_BANK, 0x00); + /* allow AHB bus accessing code sram */ + gtp_write_register(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + /* burn dsp_short code */ + ret = gtp_burn_dsp_short(client); + + if (ret != SUCCESS) { + if (retry_load++ < 5) { + pr_err("Load dsp failed,times %d retry load!", retry_load); + goto load_dsp_again; + } else { + SET_INFO_LINE_INFO("Step 2: burn dsp_short code"); + SET_INFO_LINE_ERR("burn dsp_short Timeout!"); + goto short_test_exit; + } + } + + SET_INFO_LINE_INFO("Step 2: burn dsp_short code"); + /* step3: run dsp_short, read results */ + SET_INFO_LINE_INFO("Step 3: run dsp_short code, confirm it's runnin'"); + /* clear dsp_short running flag */ + gtp_write_register(client, _rRW_MISCTL__SHORT_BOOT_FLAG, 0x00); + /* set scramble */ + gtp_write_register(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x03); + /* reset software */ + gtp_write_register(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); + /* release dsp */ + gtp_write_register(client, _rRW_MISCTL__SWRST_B0_, 0x08); + /* for constant iic address */ + client->addr = 0x14; + msleep(50); + /* confirm dsp is running*/ + i = 0; + + while (1) { + opr_buf[2] = 0x00; + gtp_read_register(client, _rRW_MISCTL__SHORT_BOOT_FLAG, opr_buf); + + if (opr_buf[2] == 0xAA) { + break; + } + + ++i; + + if (i >= 20) { + SET_INFO_LINE_ERR("step 3: dsp is not running!"); + goto short_test_exit; + } + + msleep(10); + } + + /* step4: host configure ic, get test result */ + SET_INFO_LINE_INFO("Step 4: host config ic, get test result"); + /* Short Threshold */ + GTP_DEBUG(" Short Threshold: 10"); + opr_buf[0] = 0x88; + opr_buf[1] = 0x04; + opr_buf[2] = 0; + opr_buf[3] = 10; + gtp_i2c_write(client, opr_buf, 4); + /* ADC Read Delay */ + GTP_DEBUG(" ADC Read Delay: 150"); + opr_buf[0] = 0x88; + opr_buf[1] = 0x06; + opr_buf[2] = (u8)(150 >> 8); + opr_buf[3] = (u8)(150); + gtp_i2c_write(client, opr_buf, 4); + /* DiffCode Short Threshold */ + GTP_DEBUG(" DiffCode Short Threshold: 20"); + opr_buf[0] = 0x88; + opr_buf[1] = 0x51; + opr_buf[2] = (u8)(20 >> 8); + opr_buf[3] = (u8)(20); + gtp_i2c_write(client, opr_buf, 4); + /* Config Driver & Sensor Order */ +#if GTP_DEBUG_ON + printk("<<-GTP-DEBUG->> Driver Map:\n"); + printk("IC Driver:"); + + for (i = 0; i < MAX_DRIVER_NUM; ++i) { + printk(" %2d", cfg_drv_order[i]); + } + + printk("\n"); + printk("TP Driver:"); + + for (i = 0; i < MAX_DRIVER_NUM; ++i) { + printk(" %2d", i); + } + + printk("\n"); + printk("<<-GTP-DEBUG->> Sensor Map:\n"); + printk("IC Sensor:"); + + for (i = 0; i < MAX_SENSOR_NUM; ++i) { + printk(" %2d", cfg_sen_order[i]); + } + + printk("\n"); + printk("TP Sensor:"); + + for (i = 0; i < MAX_SENSOR_NUM; ++i) { + printk(" %2d", i); + } + + printk("\n"); +#endif + opr_buf[0] = 0x88; + opr_buf[1] = 0x08; + + for (i = 0; i < MAX_DRIVER_NUM; ++i) { + opr_buf[2 + i] = cfg_drv_order[i]; + drv_sen_chksum += cfg_drv_order[i]; + } + + gtp_i2c_write(client, opr_buf, MAX_DRIVER_NUM + 2); + opr_buf[0] = 0x88; + opr_buf[1] = 0x32; + + for (i = 0; i < MAX_SENSOR_NUM; ++i) { + opr_buf[2 + i] = cfg_sen_order[i]; + drv_sen_chksum += cfg_sen_order[i]; + } + + gtp_i2c_write(client, opr_buf, MAX_SENSOR_NUM + 2); + opr_buf[0] = 0x88; + opr_buf[1] = 0x50; + opr_buf[2] = 0 - drv_sen_chksum; + gtp_i2c_write(client, opr_buf, 2 + 1); + /* clear waiting flag, run dsp */ + gtp_write_register(client, _rRW_MISCTL__SHORT_BOOT_FLAG, 0x04); + + /* inquirying test status until it's okay */ + for (i = 0;; ++i) { + gtp_read_register(client, 0x8800, opr_buf); + + if (opr_buf[2] == 0x88) { + break; + } + + msleep(50); + + if (i > 100) { + SET_INFO_LINE_ERR("step 4: inquiry test status timeout!"); + goto short_test_exit; + } + } + + /* step 5: compute the result + short flag: + bit0: Rx & Rx + bit1: Tx & Tx + bit2: Tx & Rx + bit3: Tx/Rx & GND/VDD + */ + gtp_read_register(client, 0x8801, opr_buf); + GTP_DEBUG("short_flag = 0x%02X", opr_buf[2]); + SET_INFO_LINE_INFO(""); + SET_INFO_LINE_INFO("Short Test Result:"); + + if ((opr_buf[2] & 0x0f) == 0) { + SET_INFO_LINE_INFO(" PASS!"); + ret = SUCCESS; + } else { + ret2 = SUCCESS; + + if ((opr_buf[2] & 0x08) == 0x08) { + ret2 = gt9_test_gnd_vdd_short(client); + } + + ret = gtp_compute_rslt(client); + + if (ret == SUCCESS && ret2 == SUCCESS) { + SET_INFO_LINE_INFO(" PASS!"); + ret = SUCCESS; + } else { + ret = FAIL; + } + } + + /* boot from rom and download code from flash to ram*/ + gtp_write_register(client, _rRW_MISCTL__BOOT_CTL_, 0x99); + gtp_write_register(client, _rRW_MISCTL__BOOTCTL_B0_, 0x08); + client->addr = old_i2c_addr; + gt9xx_leave_short_test(client); + enable_irq(client->irq); +#ifdef GTP_ESD_PROTECT + ts->gtp_is_suspend = 0; +#endif + return ret; +short_test_exit: + /* boot from rom and download code from flash to ram */ + gtp_write_register(client, _rRW_MISCTL__BOOT_CTL_, 0x99); + gtp_write_register(client, _rRW_MISCTL__BOOTCTL_B0_, 0x08); + client->addr = old_i2c_addr; + gt9xx_leave_short_test(client); + enable_irq(client->irq); +#ifdef GTP_ESD_PROTECT + ts->gtp_is_suspend = 0; +#endif + return FAIL; +} + +static u32 endian_mode(void) +{ + union { + s32 i; + s8 c; + } endian; + endian.i = 1; + + if (1 == endian.c) { + return MYBIG_ENDIAN; + } else { + return MYLITLE_ENDIAN; + } +} + +/* +********************************************************************************************************* +* Function: +* send read rawdata cmd +* Input: +* i2c_client* client: i2c device +* Return: +* SUCCESS: send process succeed, FAIL: failed +********************************************************************************************************* +*/ +static s32 gt9_read_raw_cmd(struct i2c_client *client) +{ + u8 raw_cmd[3] = {(u8)(GTP_REG_READ_RAW >> 8), (u8)GTP_REG_READ_RAW, 0x01}; + s32 ret = -1; + + GTP_DEBUG("Send read raw data command"); + ret = gtp_i2c_write(client, raw_cmd, 3); + + if (ret <= 0) { + SET_INFO_LINE_ERR("i2c write failed."); + return FAIL; + } + + msleep(10); + return SUCCESS; +} + +static s32 gt9_read_coor_cmd(struct i2c_client *client) +{ + u8 raw_cmd[3] = {(u8)(GTP_REG_READ_RAW >> 8), (u8)GTP_REG_READ_RAW, 0x0}; + s32 ret = -1; + + ret = gtp_i2c_write(client, raw_cmd, 3); + + if (ret < 0) { + SET_INFO_LINE_ERR("i2c write coor cmd failed!"); + return FAIL; + } + + msleep(10); + return SUCCESS; +} + +/* +********************************************************************************************************* +* Function: +* read rawdata from ic registers +* Input: +* u16* data: rawdata buffer +* i2c_client* client: i2c device +* Return: +* SUCCESS: read process succeed, FAIL: failed +********************************************************************************************************* +*/ +static s32 gtp_read_rawdata(struct i2c_client *client, u16 *data) +{ + s32 ret = -1; + u16 retry = 0; + u8 read_state[3] = {(u8)(GTP_REG_RAW_READY >> 8), (u8)GTP_REG_RAW_READY, 0}; + u16 i = 0, j = 0; + u8 *read_rawbuf; + u8 tail, head; + + read_rawbuf = (u8 *)kzalloc(sizeof(u8) * (gt9xx_drv_num * gt9xx_sen_num * 2 + GTP_ADDR_LENGTH), GFP_KERNEL); + + if (NULL == read_rawbuf) { + SET_INFO_LINE_ERR("failed to allocate for read_rawbuf"); + return FAIL; + } + + if (data == NULL) { + SET_INFO_LINE_ERR("Invalid raw buffer."); + goto have_error; + } + + msleep(10); + + while (retry++ < GTP_WAIT_RAW_MAX_TIMES) { + ret = gtp_i2c_read(client, read_state, 3); + + if (ret <= 0) { + SET_INFO_LINE_ERR("i2c read failed.return: %d", ret); + continue; + } + + if ((read_state[GTP_ADDR_LENGTH] & 0x80) == 0x80) { + GTP_DEBUG("Raw data is ready."); + break; + } + + if ((retry % 20) == 0) { + GTP_DEBUG("(%d)read_state[2] = 0x%02X", retry, read_state[GTP_ADDR_LENGTH]); + + if (retry == 100) { + gt9_read_raw_cmd(client); + } + } + + msleep(5); + } + + if (retry >= GTP_WAIT_RAW_MAX_TIMES) { + SET_INFO_LINE_ERR("Wait raw data ready timeout."); + goto have_error; + } + if (chip_type_gt9f) { + read_rawbuf[0] = (u8)(GTP_REG_RAW_DATA_GT9F >> 8); + read_rawbuf[1] = (u8)(GTP_REG_RAW_DATA_GT9F); + } else { + read_rawbuf[0] = (u8)(GTP_REG_RAW_DATA >> 8); + read_rawbuf[1] = (u8)(GTP_REG_RAW_DATA); + } + ret = gtp_i2c_read(client, read_rawbuf, GTP_ADDR_LENGTH + ((gt9xx_drv_num * gt9xx_sen_num) * 2)); + + if (ret <= 0) { + SET_INFO_LINE_ERR("i2c read rawdata failed."); + goto have_error; + } + + gtp_i2c_end_cmd(client); + + if (endian_mode() == MYBIG_ENDIAN) { + head = 0; + tail = 1; + GTP_DEBUG("Big Endian."); + } else { + head = 1; + tail = 0; + GTP_DEBUG("Little Endian."); + } + + for (i = 0, j = 0; i < ((gt9xx_drv_num * gt9xx_sen_num) * 2); i += 2) { + data[i / 2] = (u16)(read_rawbuf[i + head + GTP_ADDR_LENGTH] << 8) + (u16)read_rawbuf[GTP_ADDR_LENGTH + i + tail]; +#if GTP_DEBUG_ARRAY_ON + printk("%4d ", data[i / 2]); + ++j; + + if ((j % 10) == 0) + printk("\n"); + +#endif + } + + kfree(read_rawbuf); + return SUCCESS; +have_error: + kfree(read_rawbuf); + return FAIL; +} + +static s32 gtp_read_diffdata(struct i2c_client *client, int *data) +{ + s32 ret = -1; + u16 retry = 0; + u8 read_state[3] = {(u8)(GTP_REG_RAW_READY >> 8), (u8)GTP_REG_RAW_READY, 0}; + u16 i = 0, j = 0; + u8 *read_rawbuf; + u8 tail, head; + + read_rawbuf = (u8 *)kzalloc(sizeof(u8) * (gt9xx_drv_num * gt9xx_sen_num * 2 + GTP_ADDR_LENGTH), GFP_KERNEL); + + if (NULL == read_rawbuf) { + SET_INFO_LINE_ERR("failed to allocate for read_rawbuf"); + return FAIL; + } + + if (data == NULL) { + SET_INFO_LINE_ERR("Invalid raw buffer."); + goto have_error; + } + + msleep(10); + + while (retry++ < GTP_WAIT_RAW_MAX_TIMES) { + ret = gtp_i2c_read(client, read_state, 3); + + if (ret <= 0) { + SET_INFO_LINE_ERR("i2c read failed.return: %d", ret); + continue; + } + + if ((read_state[GTP_ADDR_LENGTH] & 0x80) == 0x80) { + GTP_DEBUG("Raw data is ready."); + break; + } + + if ((retry % 20) == 0) { + GTP_DEBUG("(%d)read_state[2] = 0x%02X", retry, read_state[GTP_ADDR_LENGTH]); + + if (retry == 100) { + gt9_read_raw_cmd(client); + } + } + + msleep(5); + } + + if (retry >= GTP_WAIT_RAW_MAX_TIMES) { + SET_INFO_LINE_ERR("Wait raw data ready timeout."); + goto have_error; + } + read_rawbuf[0] = (u8)(GTP_REG_DIFF_DATA >> 8); + read_rawbuf[1] = (u8)(GTP_REG_DIFF_DATA); + ret = gtp_i2c_read(client, read_rawbuf, GTP_ADDR_LENGTH + ((gt9xx_drv_num * gt9xx_sen_num) * 2)); + + if (ret <= 0) { + SET_INFO_LINE_ERR("i2c read rawdata failed."); + goto have_error; + } + + gtp_i2c_end_cmd(client); + + if (endian_mode() == MYBIG_ENDIAN) { + head = 0; + tail = 1; + GTP_DEBUG("Big Endian."); + } else { + head = 1; + tail = 0; + GTP_DEBUG("Little Endian."); + } + + for (i = 0, j = 0; i < ((gt9xx_drv_num * gt9xx_sen_num) * 2); i += 2) { + data[i / 2] = (int)((read_rawbuf[i + head + GTP_ADDR_LENGTH] << 8) + read_rawbuf[GTP_ADDR_LENGTH + i + tail]); +#if GTP_DEBUG_ARRAY_ON + printk("%4d ", data[i / 2]); + ++j; + + if ((j % 10) == 0) + printk("\n"); + +#endif + } + + kfree(read_rawbuf); + return SUCCESS; +have_error: + kfree(read_rawbuf); + return FAIL; +} + +/* +********************************************************************************************************* +* Function: +* rawdata test initilization function +* Input: +* u32 check_types: test items +********************************************************************************************************* +*/ +static s32 gtp_raw_test_init(void) +{ + u16 i = 0; + + test_rslt_buf = (s32 *) kzalloc(sizeof(s32) * GTP_OPEN_SAMPLE_NUM, GFP_ATOMIC); + touchpad_sum = (struct gt9xx_open_info *) kzalloc(sizeof(struct gt9xx_open_info) * (4 * _BEYOND_INFO_MAX + 1), GFP_ATOMIC); + + if (NULL == test_rslt_buf || NULL == touchpad_sum) { + return FAIL; + } + + memset(touchpad_sum, 0, sizeof(struct gt9xx_open_info) * (4 * _BEYOND_INFO_MAX + 1)); + + for (i = 0; i < (4 * _BEYOND_INFO_MAX); ++i) { + touchpad_sum[i].driver = 0xFF; + } + + for (i = 0; i < GTP_OPEN_SAMPLE_NUM; i++) { + test_rslt_buf[i] = _CHANNEL_PASS; + } + + return SUCCESS; +} + +/* +********************************************************************************************************* +* Function: +* touchscreen rawdata min limit test +* Input: +* u16* raw_buf: rawdata buffer +********************************************************************************************************* +*/ +static void gtp_raw_min_test(u16 *raw_buf) +{ + u16 i, j = 0; + u8 driver, sensor; + u8 sum_base = 1 * _BEYOND_INFO_MAX; + u8 new_flag = 0; + + for (i = 0; i < gt9xx_sc_pxl_cnt; i++) { + if (raw_buf[i] < min_limit_value) { + if ((i % gt9xx_sen_num == 0) && ((i / gt9xx_sen_num == 5) || (i / gt9xx_sen_num == 6) || (i / gt9xx_sen_num == 7) || (i / gt9xx_sen_num == 8))){ + if (raw_buf[i] > min_limit_value_LH){ + continue; + } + } + test_rslt_buf[rslt_buf_idx] |= _BEYOND_MIN_LIMIT; + driver = (i / gt9xx_sen_num); + sensor = (i % gt9xx_sen_num); + new_flag = 0; + + for (j = sum_base; j < (sum_base + _BEYOND_INFO_MAX); ++j) { + if (touchpad_sum[j].driver == 0xFF) { + new_flag = 1; + break; + } + + if ((driver == touchpad_sum[j].driver) && (sensor == touchpad_sum[j].sensor)) { + touchpad_sum[j].times++; + new_flag = 0; + break; + } + } + + if (new_flag) { + touchpad_sum[j].driver = driver; + touchpad_sum[j].sensor = sensor; + touchpad_sum[j].beyond_type |= _BEYOND_MIN_LIMIT; + touchpad_sum[j].raw_val = raw_buf[i]; + touchpad_sum[j].times = 1; + GTP_DEBUG("[%d, %d]rawdata: %d, raw min limit: %d", driver, sensor, raw_buf[i], min_limit_value); + } else { + continue; + } + } + } +} + +/* +********************************************************************************************************* +* Function: +* touchscreen rawdata max limit test +* Input: +* u16* raw_buf: rawdata buffer +********************************************************************************************************* +*/ +static void gtp_raw_max_test(u16 *raw_buf) +{ + u16 i, j; + u8 driver, sensor; + u8 sum_base = 0 * _BEYOND_INFO_MAX; + u8 new_flag = 0; + + for (i = 0; i < gt9xx_sc_pxl_cnt; i++) { + if (raw_buf[i] > max_limit_value) { + test_rslt_buf[rslt_buf_idx] |= _BEYOND_MAX_LIMIT; + driver = (i / gt9xx_sen_num); + sensor = (i % gt9xx_sen_num); + new_flag = 0; + + for (j = sum_base; j < (sum_base + _BEYOND_INFO_MAX); ++j) { + if (touchpad_sum[j].driver == 0xFF) { + new_flag = 1; + break; + } + + if ((driver == touchpad_sum[j].driver) && (sensor == touchpad_sum[j].sensor)) { + touchpad_sum[j].times++; + new_flag = 0; + break; + } + } + + if (new_flag) { + touchpad_sum[j].driver = driver; + touchpad_sum[j].sensor = sensor; + touchpad_sum[j].beyond_type |= _BEYOND_MAX_LIMIT; + touchpad_sum[j].raw_val = raw_buf[i]; + touchpad_sum[j].times = 1; + GTP_DEBUG("[%d, %d]rawdata: %d, raw max limit: %d", driver, sensor, raw_buf[i], max_limit_value); + } else { + continue; + } + } + } +} + +/* +********************************************************************************************************* +* Function: +* key rawdata max limit test +* Input: +* u16* raw_buf: rawdata buffer +********************************************************************************************************* +*/ +static void gtp_key_max_test(u16 *raw_buf) +{ + u16 i = 0, j = 1, k = 0; + u8 key_cnt = key_iso_pos[0]; + u8 driver, sensor; + u8 sum_base = 2 * _BEYOND_INFO_MAX; + u8 new_flag = 0; + + driver = gt9xx_drv_num - 1; + + for (i = gt9xx_sc_pxl_cnt; i < gt9xx_pixel_cnt; ++i) { + sensor = ((i) % gt9xx_sen_num); + + if (key_is_isolated) { + if ((key_iso_pos[j] != sensor) || (key_cnt == 0)) { + continue; + } else { + --key_cnt; + ++j; + } + } + + if (raw_buf[i] > max_limit_key) { + test_rslt_buf[rslt_buf_idx] |= _BEYOND_KEY_MAX_LMT; + new_flag = 0; + + for (k = sum_base; k < (sum_base + _BEYOND_INFO_MAX); ++k) { + if (touchpad_sum[k].driver == 0xFF) { + new_flag = 1; + break; + } + + if (touchpad_sum[k].sensor == sensor) { + touchpad_sum[k].times++; + new_flag = 0; + break; + } + } + + if (new_flag) { + touchpad_sum[k].driver = driver; + touchpad_sum[k].sensor = sensor; + touchpad_sum[k].beyond_type |= _BEYOND_KEY_MAX_LMT; + touchpad_sum[k].raw_val = raw_buf[i]; + touchpad_sum[k].times = 1; + + if (key_is_isolated) { + touchpad_sum[k].key = j - 1; + } + + GTP_DEBUG("[%d, %d]key rawdata: %d, key max limit: %d", driver, sensor, raw_buf[i], max_limit_key); + } else { + continue; + } + } + } +} + +/* +********************************************************************************************************* +* Function: +* key rawdata min limit test +* Input: +* u16* raw_buf: rawdata buffer +********************************************************************************************************* +*/ +static void gtp_key_min_test(u16 *raw_buf) +{ + u16 i = 0, j = 1, k = 0; + u8 key_cnt = key_iso_pos[0]; + u8 driver, sensor; + u8 sum_base = 3 * _BEYOND_INFO_MAX; + u8 new_flag = 0; + + driver = gt9xx_drv_num - 1; + + for (i = gt9xx_sc_pxl_cnt; i < gt9xx_pixel_cnt; ++i) { + sensor = (i % gt9xx_sen_num); + + if (key_is_isolated) { + /*GTP_DEBUG("sensor: %d, key_iso_pos[j]: %d", sensor, key_iso_pos[j]);*/ + if ((key_iso_pos[j] != sensor) || (key_cnt == 0)) { + continue; + } else { + --key_cnt; + ++j; + } + } + + if (raw_buf[i] < min_limit_key) { + test_rslt_buf[rslt_buf_idx] |= _BEYOND_KEY_MIN_LMT; + new_flag = 0; + + for (k = sum_base; k < (sum_base + _BEYOND_INFO_MAX); ++k) { + if (touchpad_sum[k].driver == 0xFF) { + new_flag = 1; + break; + } + + if (sensor == touchpad_sum[k].sensor) { + touchpad_sum[k].times++; + break; + } + } + + if (new_flag) { + touchpad_sum[k].driver = driver; + touchpad_sum[k].sensor = sensor; + touchpad_sum[k].beyond_type |= _BEYOND_KEY_MIN_LMT; + touchpad_sum[k].raw_val = raw_buf[i]; + touchpad_sum[k].times = 1; + + if (key_is_isolated) { + touchpad_sum[k].key = j - 1; + } + + GTP_DEBUG("[%d, %d]key rawdata: %d, key min limit: %d", driver, sensor, raw_buf[i], min_limit_key); + } else { + continue; + } + } + } +} + +static void gtp_uniformity_test(u16 *raw_buf) +{ + u16 i = 0; + u8 sum_base = 4 * _BEYOND_INFO_MAX; + u16 min_val = 0, max_val = 0; + u16 uniformity = 0; + + min_val = raw_buf[0]; + max_val = raw_buf[0]; + + for (i = 1; i < gt9xx_sc_pxl_cnt; i++) { + if (raw_buf[i] > max_val) { + max_val = raw_buf[i]; + } + + if (raw_buf[i] < min_val) { + min_val = raw_buf[i]; + } + } + + if (0 == max_val) { + uniformity = 0; + } else { + uniformity = (min_val * 100) / max_val; + } + + GTP_DEBUG("min_val: %d, max_val: %d, tp uniformity: %d%%", min_val, max_val, uniformity); + + if (uniformity < uniformity_lmt) { + test_rslt_buf[rslt_buf_idx] |= _BEYOND_UNIFORMITY_LMT; + touchpad_sum[sum_base].beyond_type |= _BEYOND_UNIFORMITY_LMT; + touchpad_sum[sum_base].times++; + touchpad_sum[sum_base].raw_val += uniformity; + pr_info("min_val: %d, max_val: %d, uniformity: %d%%, times: %d", min_val, max_val, uniformity, touchpad_sum[sum_base].times); + } +} + +/* +********************************************************************************************************* +* Function: +* analyse rawdata retrived from ic registers +* Input: +* u16 *raw_buf, buffer for rawdata, +* u32 check_types, test items +* Return: +* SUCCESS: test process succeed, FAIL: failed +********************************************************************************************************* +*/ +static u32 gtp_raw_test(u16 *raw_buf, u32 check_types) +{ + if (raw_buf == NULL) { + GTP_DEBUG("Invalid raw buffer pointer!"); + return FAIL; + } + + if (check_types & _MAX_TEST) { + gtp_raw_max_test(raw_buf); + } + + if (check_types & _MIN_TEST) { + gtp_raw_min_test(raw_buf); + } + + if (have_key) { + if (check_types & _KEY_MAX_TEST) { + gtp_key_max_test(raw_buf); + } + + if (check_types & _KEY_MIN_TEST) { + gtp_key_min_test(raw_buf); + } + } + + if (check_types & _UNIFORMITY_TEST) { + gtp_uniformity_test(raw_buf); + } + + return SUCCESS; +} + +/* +==================================================================================================== +* Function: +* output the test result +* Return: +* return the result. if result == 0, the TP is ok, otherwise list the beyonds +==================================================================================================== +*/ + +static s32 gtp_get_test_result(void) +{ + u16 i = 0, j = 0; + u16 beyond_max_num = 0; + u16 beyond_min_num = 0; + u16 beyond_key_max = 0; + u16 beyond_key_min = 0; + u16 beyond_uniformity = 0; + u32 result = _CHANNEL_PASS; + +#if GTP_DEBUG_ON + for (i = 0; i < 4 * _BEYOND_INFO_MAX; ++i) { + printk("(%2d, %2d)[%2d] ", touchpad_sum[i].driver, touchpad_sum[i].sensor, touchpad_sum[i].times); + + if (i && ((i + 1) % 5 == 0)) { + printk("\n"); + } + } + + printk("\n"); +#endif + + for (i = 0; i < GTP_OPEN_SAMPLE_NUM; ++i) { + if (test_rslt_buf[i] & _BEYOND_MAX_LIMIT) { + beyond_max_num++; + } + + if (test_rslt_buf[i] & _BEYOND_MIN_LIMIT) { + beyond_min_num++; + } + + if (have_key) { + if (test_rslt_buf[i] & _BEYOND_KEY_MAX_LMT) { + beyond_key_max++; + } + + if (test_rslt_buf[i] & _BEYOND_KEY_MIN_LMT) { + beyond_key_min++; + } + } + + if (test_rslt_buf[i] & _BEYOND_UNIFORMITY_LMT) { + beyond_uniformity++; + } + } + + if (beyond_max_num > _MIN_ERROR_NUM) { + result |= _BEYOND_MAX_LIMIT; + j = 0; + SET_INFO_LINE_INFO("Beyond Max Limit Points Info: "); + + for (i = 0; i < _BEYOND_INFO_MAX; ++i) { + if (touchpad_sum[i].driver == 0xFF) { + break; + } + + SET_INFO_LINE_INFO(" Drv: %d, Sen: %d RawVal: %d", touchpad_sum[i].driver, touchpad_sum[i].sensor, touchpad_sum[i].raw_val); + } + } + + if (beyond_min_num > _MIN_ERROR_NUM) { + result |= _BEYOND_MIN_LIMIT; + SET_INFO_LINE_INFO("Beyond Min Limit Points Info:"); + j = 0; + + for (i = _BEYOND_INFO_MAX; i < (2 * _BEYOND_INFO_MAX); ++i) { + if (touchpad_sum[i].driver == 0xFF) { + break; + } + + SET_INFO_LINE_INFO(" Drv: %d, Sen: %d RawVal: %d", touchpad_sum[i].driver, touchpad_sum[i].sensor, touchpad_sum[i].raw_val); + } + } + + if (have_key) { + if (beyond_key_max > _MIN_ERROR_NUM) { + result |= _BEYOND_KEY_MAX_LMT; + SET_INFO_LINE_INFO("Beyond Key Max Limit Key Info:"); + + for (i = 2 * _BEYOND_INFO_MAX; i < (3 * _BEYOND_INFO_MAX); ++i) { + if (touchpad_sum[i].driver == 0xFF) { + break; + } + + SET_INFO_LINE_INFO(" Drv: %d, Sen: %d RawVal: %d", touchpad_sum[i].driver, touchpad_sum[i].sensor, touchpad_sum[i].raw_val); + } + } + + if (beyond_key_min > _MIN_ERROR_NUM) { + result |= _BEYOND_KEY_MIN_LMT; + SET_INFO_LINE_INFO("Beyond Key Min Limit Key Info:"); + + for (i = 3 * _BEYOND_INFO_MAX; i < (4 * _BEYOND_INFO_MAX); ++i) { + if (touchpad_sum[i].driver == 0xFF) { + break; + } + + SET_INFO_LINE_INFO(" Drv: %d, Sen: %d RawVal: %d", touchpad_sum[i].driver, touchpad_sum[i].sensor, touchpad_sum[i].raw_val); + } + } + } + + if (beyond_uniformity > _MIN_ERROR_NUM) { + result |= _BEYOND_UNIFORMITY_LMT; + SET_INFO_LINE_INFO("Beyond Uniformity Limit Info: "); + SET_INFO_LINE_INFO(" Uniformity Limit: %d%%, Tp Uniformity: %d%%", uniformity_lmt, touchpad_sum[4 * _BEYOND_INFO_MAX].raw_val / touchpad_sum[4 * _BEYOND_INFO_MAX].times); + } + + if (result == 0) { + SET_INFO_LINE_INFO("[TEST SUCCEED]: "); + SET_INFO_LINE_INFO("\tThe TP is OK!"); + return result; + } + + SET_INFO_LINE_INFO("[TEST FAILED]:"); + + if (result & _BEYOND_MAX_LIMIT) { + SET_INFO_LINE_INFO(" Beyond Raw Max Limit [Max Limit: %d]", max_limit_value); + } + + if (result & _BEYOND_MIN_LIMIT) { + SET_INFO_LINE_INFO(" Beyond Raw Min Limit [Min Limit: %d]", min_limit_value); + } + + if (have_key) { + if (result & _BEYOND_KEY_MAX_LMT) { + SET_INFO_LINE_INFO(" Beyond KeyVal Max Limit [Key Max Limit: %d]", max_limit_key); + } + + if (result & _BEYOND_KEY_MIN_LMT) { + SET_INFO_LINE_INFO(" Beyond KeyVal Min Limit [Key Min Limit: %d]", min_limit_key); + } + } + + if (result & _BEYOND_UNIFORMITY_LMT) { + SET_INFO_LINE_INFO(" Beyond Uniformity Limit [Uniformity Limit: %d%%]", uniformity_lmt); + } + + return result; +} + +/* + =================================================== + * Function: + * test gt9 series ic open test + * Input: + * client, i2c_client + * Return: + * SUCCESS: test process success, FAIL, test process failed + * + =================================================== +*/ +static s32 gt9xx_open_test(struct i2c_client *client) +{ + u16 i = 0; + s32 ret = FAIL; + + u16 *raw_buf = NULL; + + disable_irq(client->irq); +#ifdef GTP_ESD_PROTECT + ts->gtp_is_suspend = 1; +#endif + /* ts->gtp_rawdiff_mode = 1;*/ + SET_INFO_LINE_INFO("---gtp open test---"); + pr_info("Parsing configuration..."); + gtp_hopping_switch(client, 0); + ret = gtp_parse_config(client); + + if (ret == FAIL) { + SET_INFO_LINE_ERR("failed to parse config..."); + ret = FAIL; + goto open_test_exit; + } + gt9xx_open_send_cfg(client); + + raw_buf = (u16 *)kzalloc(sizeof(u16) * (gt9xx_drv_num * gt9xx_sen_num), GFP_KERNEL); + + if (NULL == raw_buf) { + SET_INFO_LINE_ERR("failed to allocate mem for raw_buf!"); + ret = FAIL; + goto open_test_exit; + } + + pr_info("Step 1: Send Rawdata Cmd"); + ret = gtp_raw_test_init(); + + if (FAIL == ret) { + SET_INFO_LINE_ERR("Allocate memory for open test failed!"); + ret = FAIL; + goto open_test_exit; + } + + ret = gt9_read_raw_cmd(client); + + if (ret == FAIL) { + SET_INFO_LINE_ERR("Send Read Rawdata Cmd failed!"); + ret = FAIL; + goto open_test_exit; + } + + pr_info("Step 2: Sample Rawdata"); + + for (i = 0; i < GTP_OPEN_SAMPLE_NUM; ++i) { + rslt_buf_idx = i; + ret = gtp_read_rawdata(client, raw_buf); + + if (ret == FAIL) { + SET_INFO_LINE_ERR("Read Rawdata failed!"); + ret = FAIL; + goto open_test_exit; + } + + ret = gtp_raw_test(raw_buf, DEFAULT_TEST_ITEMS); + + if (ret == FAIL) { + gtp_i2c_end_cmd(client); + continue; + } + } + + pr_info("Step 3: Analyse Result"); + SET_INFO_LINE_INFO("Total %d Sample Data, Max Show %d Info for each Test Item", GTP_OPEN_SAMPLE_NUM, _BEYOND_INFO_MAX); + + if (0 == gtp_get_test_result()) { + ret = SUCCESS; + } else { + ret = FAIL; + } + +open_test_exit: + + if (raw_buf) { + kfree(raw_buf); + } + + if (test_rslt_buf) { + kfree(test_rslt_buf); + test_rslt_buf = NULL; + } + + if (touchpad_sum) { + kfree(touchpad_sum); + touchpad_sum = NULL; + } + + enable_irq(client->irq); +#ifdef GTP_ESD_PROTECT + ts->gtp_is_suspend = 0; +#endif + /* ts->gtp_rawdiff_mode = 0;*/ + gt9_read_coor_cmd(client); + SET_INFO_LINE_INFO("---gtp open test end---"); + gtp_hopping_switch(client, 1); + gtp_reset_guitar(client, 20); + gtp_send_cfg(client); + return ret; +} + +static int gt9xx_get_and_format_rawdata(u8 *buff, struct i2c_client *client) +{ + int ret = 0, j = 0; + u16 *raw_buf = NULL; + u8 *temp_buf = NULL; + + ret = gtp_parse_config(client); + if (ret == FAIL) { + SET_INFO_LINE_ERR("parse config failed!"); + return 0; + } + + raw_buf = (u16 *)vmalloc(sizeof(u16) * (gt9xx_drv_num * gt9xx_sen_num)); + if (raw_buf == NULL) { + SET_INFO_LINE_ERR("alloc memory err!"); + return 0; + } + temp_buf = vmalloc(6); + + if (temp_buf == NULL) { + SET_INFO_LINE_ERR("alloc memory err!"); + ret = FAIL; + goto fail; + } + + ret = gt9_read_raw_cmd(client); + if (ret == FAIL) { + SET_INFO_LINE_ERR("Send Read Rawdata Cmd failed!"); + goto fail; + } + + ret = gtp_read_rawdata(client, raw_buf); + + if (ret == FAIL) { + SET_INFO_LINE_ERR("Read Rawdata failed!"); + goto fail; + } + snprintf(buff, 9, "rawdata\n"); + for (j = 0; j < gt9xx_drv_num * gt9xx_sen_num; j++) { + if ((j + 1) % gt9xx_sen_num) + snprintf(temp_buf, 6, "%4d ", *raw_buf); + else + snprintf(temp_buf, 6, "%4d\n", *raw_buf); + + strlcat(buff, temp_buf, 6 * gt9xx_drv_num * gt9xx_sen_num); + raw_buf++; + } +fail: + if (raw_buf) { + vfree(raw_buf); + raw_buf = NULL; + } + if (temp_buf) { + vfree(temp_buf); + temp_buf = NULL; + } + if (ret == FAIL) + return 0; + else + return strlen(buff); + +} + +static int gt9xx_get_and_format_diffdata(u8 *buff, struct i2c_client *client) +{ + int ret = 0, j = 0; + int *raw_buf = NULL; + u8 *temp_buf = NULL; + + ret = gtp_parse_config(client); + if (ret == FAIL) { + SET_INFO_LINE_ERR("parse config failed!"); + return 0; + } + + raw_buf = (int *)vmalloc(sizeof(int) * (gt9xx_drv_num * gt9xx_sen_num)); + if (raw_buf == NULL) { + SET_INFO_LINE_ERR("alloc memory err!"); + return 0; + } + temp_buf = vmalloc(6); + + if (temp_buf == NULL) { + SET_INFO_LINE_ERR("alloc memory err!"); + ret = FAIL; + goto fail; + } + ret = gt9_read_raw_cmd(client); + + if (ret == FAIL) { + SET_INFO_LINE_ERR("Send Read Rawdata Cmd failed!"); + goto fail; + } + + ret = gtp_read_diffdata(client, raw_buf); + + if (ret == FAIL) { + SET_INFO_LINE_ERR("Read Rawdata failed!"); + goto fail; + } + snprintf(buff, 10, "diffdata\n"); + for (j = 0; j < gt9xx_drv_num * gt9xx_sen_num; j++) { + if ((j + 1) % gt9xx_sen_num) + snprintf(temp_buf, 6, "%4d ", *raw_buf); + else + snprintf(temp_buf, 6, "%4d\n", *raw_buf); + + strlcat(buff, temp_buf, 6 * gt9xx_drv_num * gt9xx_sen_num); + raw_buf++; + } +fail: + if (raw_buf) { + vfree(raw_buf); + raw_buf = NULL; + } + if (temp_buf) { + vfree(temp_buf); + temp_buf = NULL; + } + if (ret == FAIL) + return 0; + else + return strlen(buff); +} + +static ssize_t gt9xx_tp_selftest_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + char tmp[5]; + int cnt; + + if (*pos != 0) + return 0; + + cnt = snprintf(tmp, sizeof(gt9xx_test_result), "%d\n", gt9xx_test_result); + + if (copy_to_user(buf, tmp, strlen(tmp))) + return -EFAULT; + + *pos += cnt; + return cnt; +} + +static int gt9xx_i2c_test(struct i2c_client *client) +{ + if (gtp_i2c_test(client)) + return FAIL; + else + return SUCCESS; +} + +static ssize_t gt9xx_tp_selftest_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + char tmp[6]; + int retval; + struct goodix_ts_data *ts = NULL; + + if (!i2c_connect_client || count > sizeof(tmp)) { + retval = -EINVAL; + gt9xx_test_result = RESULT_INVALID; + goto out; + } + + if (copy_from_user(tmp, buf, count)) { + retval = -EFAULT; + gt9xx_test_result = RESULT_INVALID; + goto out; + } + + ts = i2c_get_clientdata(i2c_connect_client); + gtp_esd_off(ts); + + if (!strncmp(tmp, "short", 5)) { + retval = gt9xx_short_test(i2c_connect_client); + } else if (!strncmp(tmp, "open", 4)) + retval = gt9xx_open_test(i2c_connect_client); + else if (!strncmp(tmp, "i2c", 3)) + retval = gt9xx_i2c_test(i2c_connect_client); + + if (retval == FAIL) + gt9xx_test_result = RESULT_NG; + else + gt9xx_test_result = RESULT_PASS; + + gtp_esd_on(ts); +out: + + if (retval >= 0) + retval = count; + + return retval; +} + +static const struct file_operations tp_selftest_ops = { + .read = gt9xx_tp_selftest_read, + .write = gt9xx_tp_selftest_write, +}; + +static ssize_t gt9xx_tp_datadump_read(struct file *file, char __user *buf, size_t count, loff_t *pos) +{ + int ret = 0, cnt = 0; + char *tmp = NULL; + struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client); + + if (*pos != 0) + return 0; + tmp = vmalloc(PAGE_SIZE + PAGE_SIZE / 2); + if (tmp == NULL) + return 0; + disable_irq(ts->client->irq); + + snprintf(tmp, 16, "Tx: %2d, Rx: %2d\n", gt9xx_drv_num, gt9xx_sen_num); + cnt = gt9xx_get_and_format_diffdata(tmp, i2c_connect_client); + if (cnt == 0) + goto out; + + ret = gt9xx_get_and_format_rawdata(tmp + cnt, i2c_connect_client); + if (ret == 0) + goto out; + if (copy_to_user(buf, tmp, cnt + ret)) + ret = -EFAULT; +out: + enable_irq(ts->client->irq); + if (tmp) { + vfree(tmp); + tmp = NULL; + } + if (ret < 0) + return ret; + *pos += (cnt + ret); + return cnt + ret; +} + +static const struct file_operations gt9xx_tp_datadump_ops = { + .read = gt9xx_tp_datadump_read, +}; + +void gtp_test_sysfs_init(void) +{ + gt9xx_selftest_proc = proc_create("tp_selftest", 0664, NULL, &tp_selftest_ops); + gt9xx_datadump_proc = proc_create("tp_data_dump", 0444, NULL, >9xx_tp_datadump_ops); +} + +void gtp_test_sysfs_deinit(void) +{ + if (gt9xx_selftest_proc) + remove_proc_entry("tp_selftest", NULL); + if (gt9xx_datadump_proc) + remove_proc_entry("tp_data_dump", NULL); +} diff --git a/drivers/input/touchscreen/gt917d/gt9xx_selftest.h b/drivers/input/touchscreen/gt917d/gt9xx_selftest.h new file mode 100644 index 0000000000000..794e349be4afd --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx_selftest.h @@ -0,0 +1,465 @@ +/* drivers/input/touchscreen/gt9xx_shorttp.h + * + * 2010 - 2012 Goodix Technology. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version:1.0 + * V1.0:2012/10/20 + */ + + +#ifndef _GT9XX_OPEN_SHORT_H_ +#define _GT9XX_OPEN_SHORT_H_ + +#include "gt9xx.h" + +#define RESULT_INVALID 0 +#define RESULT_PASS 2 +#define RESULT_NG 1 + +const u8 dsp_short[] = { + 0x02, 0x09, 0xac, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, + 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, + 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, + 0xe8, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, 0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, + 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, 0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, + 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, 0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, + 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, 0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, + 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, 0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, + 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, + 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, + 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, + 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, + 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, + 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, + 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, + 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, + 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, + 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, + 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, + 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, + 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xeb, + 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0, 0x22, + 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff, + 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, + 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, + 0xf0, 0x22, 0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0x01, 0xa9, 0x12, 0x01, + 0xa9, 0x12, 0x01, 0xa9, 0x12, 0x01, 0xa9, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, + 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, + 0x82, 0xc8, 0x22, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x90, + 0x50, 0x96, 0x74, 0xaa, 0xf0, 0x90, 0x41, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x7d, 0x48, 0x7f, 0x01, + 0x12, 0x12, 0x20, 0x90, 0x42, 0x07, 0x74, 0x0f, 0xf0, 0x90, 0x42, 0x06, 0xe0, 0x44, 0x02, 0xf0, + 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0x42, 0x51, 0x74, 0x03, 0xf0, 0xc2, 0xaf, 0x12, 0x14, 0x43, 0x12, + 0x0d, 0x3f, 0x12, 0x14, 0x19, 0x90, 0xbf, 0xfe, 0xe4, 0xf0, 0x12, 0x0c, 0xdc, 0x90, 0x42, 0x3a, + 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0x50, 0x8b, 0x74, 0x14, 0xf0, 0x90, 0x50, 0x8a, 0xf0, 0x12, + 0x07, 0x21, 0x90, 0x60, 0x2f, 0x74, 0x07, 0xf0, 0x7f, 0x3b, 0x12, 0x14, 0x67, 0x90, 0x50, 0x96, + 0xe0, 0xb4, 0xaa, 0x03, 0x00, 0x80, 0xf6, 0x12, 0x0a, 0x51, 0x90, 0x88, 0x04, 0xe0, 0x70, 0x02, + 0xa3, 0xe0, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x40, 0x08, 0x90, 0x88, 0x01, 0x74, 0x10, 0xf0, + 0x80, 0x75, 0x90, 0x88, 0x04, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x80, 0x58, 0xcf, 0xf0, 0xa3, 0xef, + 0xf0, 0x7b, 0x6a, 0x7d, 0x02, 0x7f, 0x1d, 0x7e, 0x00, 0x12, 0x0a, 0xe1, 0xe4, 0x90, 0x88, 0x00, + 0xf0, 0x90, 0x42, 0x07, 0x74, 0x0f, 0xf0, 0x90, 0x42, 0x06, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x44, + 0x01, 0xf0, 0xe4, 0xff, 0xef, 0x25, 0xe0, 0x24, 0xa1, 0xf5, 0x82, 0xe4, 0x34, 0xa4, 0xf5, 0x83, + 0xe4, 0xf0, 0xa3, 0xf0, 0xef, 0x25, 0xe0, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0xa5, 0xf5, 0x83, + 0xe4, 0xf0, 0xa3, 0xf0, 0x0f, 0xbf, 0x48, 0xdc, 0xe4, 0x90, 0x88, 0x01, 0xf0, 0x12, 0x04, 0xb0, + 0x12, 0x03, 0x50, 0x12, 0x08, 0xfb, 0x90, 0x88, 0x00, 0xe0, 0x44, 0x08, 0xf0, 0x12, 0x08, 0x0e, + 0x90, 0x88, 0x00, 0xe0, 0x44, 0x80, 0xf0, 0x90, 0x88, 0x00, 0x74, 0x88, 0xf0, 0x90, 0x41, 0xef, + 0x74, 0x0f, 0xf0, 0x90, 0x41, 0xee, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0xff, 0x54, 0x01, 0xf4, 0x54, + 0x01, 0xfe, 0xef, 0x54, 0xfe, 0x4e, 0xf0, 0xe0, 0xff, 0x54, 0x01, 0xf4, 0x54, 0x01, 0xfe, 0xef, + 0x54, 0xfe, 0x4e, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x42, 0x07, 0x74, 0x0f, 0xf0, 0x90, 0x42, + 0x06, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0x70, 0xfe, 0x60, 0xfc, 0x60, 0x40, 0x70, + 0x3e, 0x12, 0x13, 0xa8, 0x12, 0x13, 0xc1, 0x12, 0x14, 0x73, 0xe4, 0xff, 0x12, 0x14, 0x36, 0x12, + 0x13, 0x8d, 0x12, 0x14, 0x4f, 0xe4, 0xfb, 0xfd, 0xfc, 0xff, 0xfe, 0x12, 0x10, 0xb4, 0xe4, 0xfb, + 0xfd, 0xfc, 0xff, 0xfe, 0x12, 0x10, 0x66, 0xe4, 0xfb, 0xfd, 0xfc, 0xff, 0xfe, 0x12, 0x11, 0x35, + 0xe4, 0xff, 0xfe, 0x12, 0x12, 0x7f, 0x12, 0x13, 0xc1, 0x12, 0x13, 0xa8, 0x12, 0x14, 0x73, 0x22, + 0xe4, 0xf5, 0x0b, 0xf5, 0x0c, 0x90, 0x42, 0x5d, 0xe0, 0xf5, 0x09, 0x90, 0x42, 0x62, 0xe0, 0xf5, + 0x0a, 0x12, 0x0d, 0x9f, 0xc2, 0x0b, 0x12, 0x12, 0xd7, 0xe4, 0x90, 0x88, 0x03, 0xf0, 0xf5, 0x08, + 0xe5, 0x08, 0x30, 0xe0, 0x03, 0x02, 0x04, 0x93, 0x74, 0x0b, 0x25, 0x08, 0x12, 0x06, 0xa8, 0xe0, + 0x70, 0x03, 0x02, 0x04, 0x93, 0x90, 0x42, 0x0f, 0x74, 0x0f, 0xf0, 0x90, 0x42, 0x0e, 0x12, 0x06, + 0x07, 0xc2, 0x08, 0xad, 0x08, 0x90, 0x88, 0x03, 0xe0, 0x75, 0xf0, 0x41, 0xa4, 0x24, 0xd2, 0xf5, + 0x82, 0xe5, 0xf0, 0x34, 0xa0, 0xaf, 0x82, 0xf5, 0x0b, 0x8f, 0x0c, 0xf5, 0x83, 0xe0, 0x54, 0x7f, + 0xf0, 0xed, 0x54, 0x7f, 0xff, 0xe0, 0x54, 0x80, 0x4f, 0xf0, 0xed, 0xc3, 0x13, 0xfc, 0x12, 0x06, + 0x67, 0x74, 0x02, 0xf0, 0xed, 0xc3, 0x94, 0x10, 0x50, 0x1a, 0x90, 0x32, 0x46, 0xc0, 0x83, 0xc0, + 0x82, 0x74, 0x01, 0x7e, 0x00, 0xc8, 0xed, 0xc8, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, + 0xd8, 0xf9, 0x80, 0x1c, 0x90, 0x32, 0x44, 0xc0, 0x83, 0xc0, 0x82, 0xed, 0x24, 0xf0, 0xff, 0x74, + 0x01, 0x7e, 0x00, 0xc8, 0xef, 0xc8, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, + 0xff, 0xe0, 0x4e, 0xfe, 0xa3, 0xe0, 0x4f, 0xff, 0xd0, 0x82, 0xd0, 0x83, 0xee, 0xf0, 0xa3, 0xef, + 0xf0, 0xcf, 0xec, 0xcf, 0x7d, 0x01, 0x12, 0x0e, 0xb8, 0x12, 0x06, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, + 0xef, 0xf0, 0x12, 0x06, 0xf0, 0xa3, 0xa3, 0xa3, 0xe5, 0x08, 0x12, 0x06, 0xc4, 0xee, 0xf0, 0xa3, + 0xef, 0xf0, 0x90, 0x32, 0x44, 0x12, 0x01, 0x92, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x0b, 0xe5, 0x0c, + 0x24, 0x03, 0xf5, 0x12, 0xe4, 0x35, 0x0b, 0xf5, 0x11, 0x85, 0x08, 0x13, 0x12, 0x0b, 0x68, 0xaf, + 0x0c, 0xae, 0x0b, 0x12, 0x0f, 0xc1, 0x12, 0x06, 0xf0, 0x12, 0x06, 0x37, 0xe5, 0x08, 0x25, 0xe0, + 0x24, 0xf5, 0xf5, 0x82, 0xe4, 0x34, 0xa4, 0x12, 0x06, 0x2a, 0x12, 0x06, 0xf0, 0x12, 0x06, 0x37, + 0xe5, 0x08, 0x25, 0xe0, 0x24, 0xf7, 0xf5, 0x82, 0xe4, 0x34, 0xa4, 0x12, 0x06, 0x2a, 0x30, 0x08, + 0x09, 0x12, 0x05, 0xfe, 0x90, 0x88, 0x03, 0xe0, 0x04, 0xf0, 0xe5, 0x08, 0xc3, 0x13, 0x12, 0x06, + 0x67, 0xe4, 0xf0, 0x05, 0x08, 0xe5, 0x08, 0xc3, 0x94, 0x1d, 0x50, 0x03, 0x02, 0x03, 0x70, 0x90, + 0x42, 0x5d, 0xe5, 0x09, 0xf0, 0x90, 0x42, 0x62, 0xe5, 0x0a, 0x12, 0x06, 0x7a, 0x02, 0x12, 0xab, + 0xe4, 0xf5, 0x0f, 0xf5, 0x10, 0x90, 0x42, 0x5d, 0xe0, 0xf5, 0x0a, 0x90, 0x42, 0x62, 0xe0, 0xf5, + 0x0b, 0x12, 0x0d, 0x9f, 0xc2, 0x0b, 0x12, 0x12, 0xd7, 0xe4, 0x90, 0x88, 0x02, 0xf0, 0xf5, 0x08, + 0x12, 0x06, 0xff, 0x12, 0x06, 0x43, 0xe0, 0x70, 0x03, 0x02, 0x05, 0xd6, 0xc2, 0x08, 0x12, 0x06, + 0xff, 0xff, 0x12, 0x06, 0x58, 0x74, 0x02, 0xf0, 0x8f, 0x0c, 0x90, 0x88, 0x02, 0xe0, 0x75, 0xf0, + 0x95, 0xa4, 0x24, 0x60, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x88, 0xaf, 0x82, 0xf5, 0x0f, 0x8f, 0x10, + 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x0c, 0x54, 0x7f, 0xff, 0xe0, 0x54, 0x80, 0x4f, 0xf0, + 0xaf, 0x0c, 0x12, 0x05, 0xef, 0x12, 0x07, 0x06, 0xa3, 0xe5, 0x0d, 0xf0, 0xa3, 0xe5, 0x0e, 0xf0, + 0x12, 0x07, 0x06, 0xe5, 0x08, 0x12, 0x06, 0x21, 0xe5, 0x0d, 0xf0, 0xe5, 0x0e, 0x12, 0x06, 0x82, + 0xf5, 0x09, 0xe5, 0x08, 0x24, 0x01, 0xff, 0xe4, 0x33, 0xfe, 0xc3, 0xe5, 0x09, 0x9f, 0xee, 0x64, + 0x80, 0xf8, 0x74, 0x80, 0x98, 0x50, 0x0b, 0x12, 0x06, 0x19, 0xe4, 0xf0, 0xa3, 0xf0, 0x05, 0x09, + 0x80, 0xe0, 0xe5, 0x08, 0x04, 0xf5, 0x09, 0xe5, 0x09, 0xc3, 0x94, 0x2a, 0x50, 0x34, 0xe5, 0x09, + 0x12, 0x06, 0x3e, 0xe0, 0x60, 0x28, 0x12, 0x05, 0xef, 0x12, 0x06, 0x19, 0xe5, 0x0d, 0xf0, 0xa3, + 0xe5, 0x0e, 0xf0, 0xc3, 0x90, 0x88, 0x05, 0xe0, 0x95, 0x0e, 0x90, 0x88, 0x04, 0xe0, 0x95, 0x0d, + 0x50, 0x09, 0xd2, 0x08, 0x90, 0x88, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x06, 0x84, 0x05, 0x09, + 0x80, 0xc5, 0xd2, 0x0b, 0xe5, 0x10, 0x24, 0x57, 0xf5, 0x12, 0xe4, 0x35, 0x0f, 0xf5, 0x11, 0x85, + 0x08, 0x13, 0x12, 0x0b, 0x68, 0xaf, 0x10, 0xae, 0x0f, 0x12, 0x0f, 0x6b, 0x12, 0x07, 0x06, 0x12, + 0x06, 0x37, 0xe5, 0x08, 0x25, 0xe0, 0x24, 0xa1, 0xf5, 0x82, 0xe4, 0x34, 0xa4, 0x12, 0x06, 0x2a, + 0x30, 0x08, 0x09, 0x12, 0x05, 0xfe, 0x90, 0x88, 0x02, 0xe0, 0x04, 0xf0, 0x12, 0x06, 0xff, 0x24, + 0x00, 0x12, 0x06, 0x69, 0xe4, 0xf0, 0x05, 0x08, 0xe5, 0x08, 0xc3, 0x94, 0x2a, 0x50, 0x03, 0x02, + 0x04, 0xd0, 0xe5, 0x0a, 0x12, 0x06, 0xf7, 0xe5, 0x0b, 0x12, 0x06, 0x7a, 0x02, 0x12, 0xab, 0x12, + 0x0e, 0x5d, 0x8f, 0x0c, 0x7d, 0x01, 0x12, 0x0e, 0xb8, 0x8e, 0x0d, 0x8f, 0x0e, 0x22, 0x90, 0x42, + 0x0b, 0x74, 0x0f, 0xf0, 0x90, 0x42, 0x0a, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0xff, 0x54, 0x01, 0xf4, + 0x54, 0x01, 0xfe, 0xef, 0x54, 0xfe, 0x4e, 0xf0, 0x22, 0x85, 0x10, 0x82, 0x85, 0x0f, 0x83, 0xe5, + 0x09, 0xa3, 0xa3, 0xa3, 0x75, 0xf0, 0x02, 0x02, 0x01, 0xc3, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, + 0xf0, 0x22, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x22, 0x90, 0x11, + 0x85, 0x93, 0xff, 0x24, 0x29, 0xf5, 0x82, 0xe4, 0x34, 0x80, 0xf5, 0x83, 0x22, 0x74, 0x08, 0x2c, + 0xf5, 0x82, 0xe4, 0x34, 0x88, 0xf5, 0x83, 0x22, 0x24, 0x00, 0xfd, 0xe4, 0x34, 0x32, 0xfc, 0xed, + 0x64, 0x03, 0xf5, 0x82, 0x8c, 0x83, 0x22, 0x24, 0x2c, 0xff, 0xe4, 0x34, 0x32, 0xfe, 0xef, 0x64, + 0x03, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0xe0, 0x90, 0x42, 0x62, 0xf0, 0x90, 0x42, 0x7d, 0x74, 0x02, + 0xf0, 0x22, 0xa3, 0xf0, 0x90, 0x32, 0x42, 0xe4, 0xf0, 0xa3, 0xf0, 0x90, 0x42, 0x82, 0xf0, 0x22, + 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xee, 0x54, 0x7f, 0xfe, 0xc3, 0x90, 0x88, 0x52, 0xe0, 0x9f, 0x90, + 0x88, 0x51, 0xe0, 0x9e, 0x22, 0x74, 0x0b, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x80, 0xf5, 0x83, 0x22, + 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x85, 0x12, 0x82, 0x85, + 0x11, 0x83, 0xe5, 0x14, 0x75, 0xf0, 0x02, 0x02, 0x01, 0xc3, 0x74, 0x32, 0x2c, 0xf5, 0x82, 0xe4, + 0x34, 0x88, 0xf5, 0x83, 0x22, 0xf8, 0xeb, 0x4f, 0xff, 0xea, 0x4e, 0xfe, 0xe9, 0x4d, 0xfd, 0xe8, + 0x4c, 0xfc, 0x22, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0xe8, 0x22, + 0x85, 0x0c, 0x82, 0x85, 0x0b, 0x83, 0x22, 0x90, 0x42, 0x5d, 0xf0, 0x90, 0x42, 0x62, 0x22, 0xe5, + 0x08, 0x90, 0x11, 0x85, 0x93, 0x22, 0x85, 0x10, 0x82, 0x85, 0x0f, 0x83, 0x22, 0x25, 0xe0, 0x24, + 0x31, 0xf5, 0x82, 0xe4, 0x34, 0xa5, 0x22, 0x25, 0xe0, 0x24, 0x85, 0xf5, 0x82, 0xe4, 0x34, 0xa5, + 0x22, 0x90, 0x40, 0x13, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x30, 0x10, 0x74, + 0x0f, 0xf0, 0x90, 0x30, 0xaa, 0xe0, 0x54, 0xf0, 0x44, 0x07, 0xf0, 0x90, 0x42, 0x7d, 0x74, 0x02, + 0xf0, 0x90, 0x42, 0x82, 0xe4, 0xf0, 0x90, 0x32, 0x42, 0xf0, 0xa3, 0xf0, 0xa3, 0x12, 0x01, 0x92, + 0x15, 0x55, 0x55, 0x55, 0x90, 0x30, 0x15, 0x74, 0x01, 0xf0, 0x90, 0x30, 0x13, 0x74, 0x07, 0xf0, + 0x90, 0x30, 0x0c, 0x74, 0x03, 0xf0, 0x90, 0x42, 0x5f, 0x74, 0x01, 0xf0, 0x90, 0x30, 0xab, 0xe0, + 0x44, 0x40, 0xf0, 0x90, 0x30, 0x06, 0x74, 0x0f, 0xf0, 0x90, 0x30, 0x0b, 0xe0, 0x54, 0xf0, 0xf0, + 0x90, 0x30, 0x1b, 0x74, 0x04, 0xf0, 0x90, 0x30, 0x11, 0x74, 0x1d, 0x12, 0x14, 0x29, 0x90, 0x42, + 0x56, 0xe4, 0xf0, 0x90, 0x42, 0x5a, 0xf0, 0x90, 0x42, 0x62, 0x74, 0x04, 0xf0, 0x90, 0x42, 0x77, + 0x74, 0x2b, 0xf0, 0x90, 0x30, 0x1c, 0xe4, 0xf0, 0x90, 0x60, 0x2f, 0xe0, 0x54, 0xc7, 0x44, 0x08, + 0xf0, 0xe0, 0x54, 0xf8, 0xf0, 0x90, 0x37, 0x33, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0x42, 0x5b, 0xe4, + 0xf0, 0x90, 0x42, 0x60, 0xf0, 0xa3, 0xf0, 0x90, 0x42, 0x5e, 0x04, 0xf0, 0x90, 0x42, 0x7a, 0xf0, + 0x90, 0x42, 0x79, 0xf0, 0x90, 0x42, 0x7f, 0xe4, 0xf0, 0x90, 0x42, 0x7e, 0x04, 0xf0, 0x90, 0x42, + 0x80, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0x37, 0x33, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, + 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xfa, 0x12, 0x13, 0xd9, 0x7f, 0x08, 0x12, 0x0f, 0x12, 0x7f, 0x0b, + 0x12, 0x0d, 0xff, 0x90, 0x30, 0x22, 0xe4, 0xf0, 0x90, 0x40, 0x48, 0x04, 0xf0, 0x22, 0x90, 0x42, + 0x5d, 0xe0, 0x90, 0x80, 0x86, 0xf0, 0x90, 0x42, 0x62, 0xe0, 0x90, 0x80, 0x87, 0xf0, 0x12, 0x0d, + 0x9f, 0xc2, 0x0b, 0x12, 0x12, 0xd7, 0x12, 0x06, 0x7b, 0xe4, 0x90, 0x80, 0x84, 0xf0, 0x90, 0x80, + 0x84, 0xe0, 0xff, 0xc3, 0x94, 0x1e, 0x40, 0x03, 0x02, 0x08, 0xdf, 0xef, 0x12, 0x07, 0x17, 0x12, + 0x06, 0xb5, 0x12, 0x06, 0xa5, 0xe0, 0x70, 0x03, 0x02, 0x08, 0xd6, 0x90, 0x80, 0x84, 0xe0, 0xa3, + 0xf0, 0x90, 0x32, 0x44, 0xc0, 0x83, 0xc0, 0x82, 0x12, 0x06, 0xe3, 0xc0, 0xe0, 0xe9, 0xc0, 0xe0, + 0xe4, 0x7f, 0x01, 0xfe, 0xfd, 0xfc, 0x90, 0x80, 0x85, 0xe0, 0xf9, 0xf8, 0x12, 0x01, 0x73, 0xd0, + 0xe0, 0xf9, 0xd0, 0xe0, 0x12, 0x06, 0xd5, 0xd0, 0x82, 0xd0, 0x83, 0x12, 0x01, 0x86, 0x90, 0x42, + 0x81, 0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x08, 0xf0, 0x90, 0x80, 0x88, 0xee, 0xf0, 0xa3, 0xef, 0xf0, + 0x90, 0x32, 0x44, 0x12, 0x01, 0x92, 0x00, 0x00, 0x00, 0x00, 0x12, 0x08, 0xf0, 0x90, 0x80, 0x8a, + 0xee, 0xf0, 0xfc, 0xa3, 0xef, 0xf0, 0x90, 0x80, 0x88, 0x12, 0x11, 0xe8, 0x90, 0x80, 0x8c, 0x12, + 0x06, 0x90, 0x50, 0x09, 0x90, 0x88, 0x01, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x07, 0xe4, 0x90, 0x80, + 0x8c, 0xf0, 0xa3, 0xf0, 0x90, 0x80, 0x8c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x80, 0x84, 0xe0, + 0x12, 0x07, 0x17, 0x12, 0x06, 0x2a, 0x90, 0x80, 0x84, 0xe0, 0x04, 0xf0, 0x02, 0x08, 0x2e, 0x90, + 0x80, 0x86, 0xe0, 0x90, 0x42, 0x5d, 0xf0, 0x90, 0x80, 0x87, 0x12, 0x06, 0x76, 0x02, 0x12, 0xab, + 0x90, 0x80, 0x85, 0xe0, 0xc3, 0x13, 0xff, 0x12, 0x0b, 0xee, 0x22, 0x90, 0x42, 0x5d, 0xe0, 0x90, + 0x80, 0x86, 0xf0, 0x90, 0x42, 0x62, 0xe0, 0x90, 0x80, 0x87, 0xf0, 0x12, 0x0d, 0x9f, 0xc2, 0x0b, + 0x12, 0x12, 0xd7, 0x90, 0x42, 0x7d, 0x74, 0x01, 0xf0, 0xe4, 0x90, 0x80, 0x84, 0xf0, 0x90, 0x80, + 0x84, 0xe0, 0xff, 0xc3, 0x94, 0x2a, 0x50, 0x73, 0xef, 0x12, 0x07, 0x0d, 0x12, 0x06, 0xb5, 0xef, + 0x12, 0x06, 0x3e, 0xe0, 0x60, 0x5c, 0x12, 0x0e, 0x5d, 0x90, 0x80, 0x85, 0xef, 0xf0, 0x90, 0x42, + 0x81, 0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x0b, 0xee, 0x90, 0x80, 0x88, 0xee, 0xf0, 0xef, 0x12, 0x06, + 0x82, 0x90, 0x80, 0x85, 0xe0, 0xff, 0x12, 0x0b, 0xee, 0x90, 0x80, 0x8a, 0xee, 0xf0, 0xfc, 0xa3, + 0xef, 0xf0, 0x90, 0x80, 0x88, 0x12, 0x11, 0xe8, 0x90, 0x80, 0x8c, 0x12, 0x06, 0x90, 0x50, 0x09, + 0x90, 0x88, 0x01, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x07, 0xe4, 0x90, 0x80, 0x8c, 0xf0, 0xa3, 0xf0, + 0x90, 0x80, 0x8c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x80, 0x84, 0xe0, 0x12, 0x07, 0x0d, 0x12, + 0x06, 0x2a, 0x90, 0x80, 0x84, 0xe0, 0x04, 0xf0, 0x02, 0x09, 0x1e, 0x90, 0x80, 0x86, 0xe0, 0x90, + 0x42, 0x5d, 0xf0, 0x90, 0x80, 0x87, 0x12, 0x06, 0x76, 0x02, 0x12, 0xab, 0xc2, 0xaf, 0x12, 0x14, + 0x43, 0x78, 0xff, 0xe4, 0xf6, 0xd8, 0xfd, 0x90, 0x80, 0x00, 0x7f, 0x00, 0x7e, 0x50, 0xe4, 0xf0, + 0xa3, 0xdf, 0xfc, 0xde, 0xfa, 0x75, 0xa0, 0xbe, 0x75, 0x89, 0x00, 0x75, 0x81, 0xff, 0x02, 0x0a, + 0x0c, 0x02, 0x01, 0xcf, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, + 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, + 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, + 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x13, 0xef, 0xe4, + 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, + 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, + 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, + 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, + 0xbe, 0xe4, 0xfe, 0xfd, 0xfc, 0x12, 0x06, 0x4d, 0xe0, 0x2d, 0xfd, 0x0c, 0xbc, 0x2a, 0xf6, 0xe4, + 0xfc, 0x12, 0x06, 0xca, 0xe0, 0x2d, 0xfd, 0x0c, 0xbc, 0x1e, 0xf6, 0xed, 0x70, 0x02, 0x7e, 0x01, + 0x90, 0x88, 0x50, 0xe0, 0x2d, 0x60, 0x02, 0x7e, 0x01, 0xee, 0x60, 0x21, 0xe4, 0xfc, 0x12, 0x06, + 0x4d, 0xec, 0xf0, 0xd3, 0x94, 0x19, 0x40, 0x06, 0x12, 0x06, 0x4d, 0xe0, 0x04, 0xf0, 0x0c, 0xbc, + 0x2a, 0xec, 0xe4, 0xfc, 0x12, 0x06, 0xca, 0xec, 0xf0, 0x0c, 0xbc, 0x1e, 0xf7, 0x7c, 0x2b, 0x90, + 0x80, 0x29, 0xe4, 0xf0, 0xa3, 0xdc, 0xfc, 0x7c, 0x1e, 0x90, 0x80, 0x0b, 0xe4, 0xf0, 0xa3, 0xdc, + 0xfc, 0xe4, 0xfc, 0x12, 0x06, 0x4d, 0xe0, 0xff, 0xc3, 0x94, 0x2b, 0x50, 0x09, 0x74, 0x29, 0x2f, + 0x12, 0x06, 0x45, 0x74, 0x01, 0xf0, 0x0c, 0xbc, 0x2a, 0xe9, 0xe4, 0xfc, 0x12, 0x06, 0xca, 0xe0, + 0xff, 0xc3, 0x94, 0x1e, 0x50, 0x06, 0x12, 0x06, 0xa5, 0x74, 0x01, 0xf0, 0x0c, 0xbc, 0x1e, 0xec, + 0x22, 0xd3, 0x10, 0xaf, 0x01, 0xc3, 0xc0, 0xd0, 0x90, 0x80, 0x54, 0xee, 0xf0, 0xa3, 0xef, 0xf0, + 0xa3, 0xed, 0xf0, 0xa3, 0xeb, 0xf0, 0x90, 0x80, 0x80, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x80, 0xf0, + 0xa3, 0x74, 0x58, 0xf0, 0x7f, 0xfe, 0x7e, 0xbf, 0x12, 0x11, 0xaf, 0xef, 0x60, 0xf6, 0x90, 0x80, + 0x56, 0xe0, 0x24, 0xe3, 0xff, 0x90, 0x80, 0x83, 0xf0, 0x12, 0x13, 0x02, 0x90, 0x80, 0x54, 0xe0, + 0xff, 0x12, 0x13, 0x02, 0x90, 0x80, 0x55, 0xe0, 0xff, 0x12, 0x13, 0x02, 0x90, 0x80, 0x57, 0xe0, + 0x80, 0x1d, 0x90, 0x80, 0x56, 0xe0, 0xff, 0x14, 0xf0, 0xef, 0x60, 0x19, 0x90, 0x80, 0x80, 0xe0, + 0xfb, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x00, 0x1c, 0xa9, 0xf0, 0xfa, 0x12, 0x00, 0x03, 0xff, + 0x12, 0x13, 0x02, 0x80, 0xdd, 0x90, 0x80, 0x83, 0xe0, 0xf4, 0xff, 0x12, 0x13, 0x02, 0x90, 0xbf, + 0xfe, 0xe4, 0xf0, 0xd0, 0xd0, 0x92, 0xaf, 0x22, 0xe4, 0xf5, 0x14, 0x12, 0x06, 0xbc, 0xe4, 0xf0, + 0xa3, 0xf0, 0x05, 0x14, 0xe5, 0x14, 0xb4, 0x1e, 0xf2, 0xe4, 0xf5, 0x14, 0x74, 0x0b, 0x25, 0x14, + 0x12, 0x06, 0xa8, 0xe0, 0x60, 0x5e, 0x20, 0x0b, 0x06, 0xe5, 0x13, 0x65, 0x14, 0x60, 0x55, 0x20, + 0x0b, 0x0c, 0xe5, 0x14, 0xc3, 0x95, 0x13, 0x50, 0x05, 0xe5, 0x14, 0x30, 0xe0, 0x46, 0xaf, 0x14, + 0x12, 0x10, 0xf5, 0x7d, 0x01, 0x12, 0x0e, 0xb8, 0x12, 0x06, 0xbc, 0xee, 0xf0, 0xa3, 0xef, 0xf0, + 0xc3, 0x90, 0x88, 0x05, 0xe0, 0x9f, 0x90, 0x88, 0x04, 0xe0, 0x9e, 0x50, 0x16, 0xd2, 0x08, 0x90, + 0x88, 0x01, 0xe0, 0xff, 0x30, 0x0b, 0x04, 0x7e, 0x04, 0x80, 0x02, 0x7e, 0x02, 0xef, 0x4e, 0x90, + 0x88, 0x01, 0xf0, 0x90, 0x42, 0x7d, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x32, 0x44, 0x12, 0x01, 0x92, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x14, 0xe5, 0x14, 0xc3, 0x94, 0x1e, 0x40, 0x8f, 0x22, 0xef, 0x54, + 0x0f, 0xff, 0x90, 0x30, 0x38, 0xe0, 0x54, 0xf0, 0x4f, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x90, 0x30, + 0x18, 0x74, 0xc0, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0x80, 0x0a, 0x04, 0xf0, 0x90, 0x88, 0x06, 0xe0, + 0xfe, 0xa3, 0xe0, 0xff, 0x12, 0x13, 0x2b, 0x90, 0x30, 0x03, 0xe4, 0xf0, 0x30, 0xff, 0xfd, 0x90, + 0x30, 0x03, 0x74, 0x01, 0xf0, 0x7f, 0x96, 0x12, 0x13, 0xd9, 0xe4, 0xf5, 0x1b, 0xf5, 0x1c, 0xfd, + 0x7c, 0xc0, 0x7b, 0xc8, 0xfa, 0xeb, 0x25, 0xe0, 0xff, 0xea, 0x33, 0xfe, 0xed, 0x2f, 0xf5, 0x82, + 0xec, 0x3e, 0xf5, 0x83, 0xe0, 0xa2, 0xe7, 0x13, 0xfe, 0xa3, 0xe0, 0x13, 0x25, 0x1c, 0xf5, 0x1c, + 0xee, 0x35, 0x1b, 0xf5, 0x1b, 0x0b, 0xbb, 0x00, 0x01, 0x0a, 0xba, 0x01, 0xd8, 0xbb, 0x08, 0xd5, + 0xe5, 0x1c, 0xae, 0x1b, 0x78, 0x05, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xf5, 0x1c, + 0x8e, 0x1b, 0xff, 0x22, 0xcb, 0xef, 0xcb, 0xca, 0xee, 0xca, 0xe4, 0xf5, 0x0b, 0xf5, 0x0a, 0xf5, + 0x09, 0xf5, 0x08, 0x8b, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xff, 0x60, 0x47, 0xc3, 0x94, 0x30, 0x40, + 0x3b, 0xef, 0xd3, 0x94, 0x39, 0x50, 0x35, 0xaf, 0x0b, 0xae, 0x0a, 0xad, 0x09, 0xac, 0x08, 0x78, + 0x04, 0x12, 0x01, 0x73, 0x8f, 0x0b, 0x8e, 0x0a, 0x8d, 0x09, 0x8c, 0x08, 0xe4, 0x93, 0x24, 0xd0, + 0xff, 0xe4, 0x34, 0xff, 0xfe, 0xe4, 0xfc, 0xfd, 0xe5, 0x0b, 0x2f, 0xf5, 0x0b, 0xe5, 0x0a, 0x3e, + 0xf5, 0x0a, 0xed, 0x35, 0x09, 0xf5, 0x09, 0xec, 0x35, 0x08, 0xf5, 0x08, 0x0b, 0xbb, 0x00, 0x01, + 0x0a, 0x80, 0xb0, 0xaf, 0x0b, 0xae, 0x0a, 0xad, 0x09, 0xac, 0x08, 0x22, 0x7e, 0x11, 0x7f, 0x73, + 0x12, 0x0c, 0x74, 0x90, 0x80, 0x02, 0x12, 0x01, 0x86, 0x7e, 0x11, 0x7f, 0x7c, 0x12, 0x0c, 0x74, + 0x90, 0x80, 0x06, 0x12, 0x01, 0x86, 0x90, 0x80, 0x02, 0x12, 0x06, 0x32, 0x90, 0x80, 0x58, 0x12, + 0x01, 0x86, 0x90, 0x80, 0x06, 0x12, 0x06, 0x32, 0x90, 0x80, 0x5c, 0x12, 0x01, 0x86, 0x7b, 0xfa, + 0x7d, 0x08, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x0a, 0xe1, 0x90, 0x80, 0x00, 0xe0, 0xfc, 0xa3, 0xe0, + 0xfd, 0xec, 0xff, 0x90, 0x80, 0x58, 0xe4, 0xf0, 0xa3, 0xef, 0xf0, 0xcf, 0xed, 0xcf, 0xa3, 0xe4, + 0xf0, 0xa3, 0xef, 0xf0, 0x7b, 0x5a, 0x7d, 0x04, 0x7f, 0x02, 0x7e, 0x00, 0x02, 0x0a, 0xe1, 0xae, + 0x2d, 0xaf, 0x2e, 0xe4, 0xfc, 0xfd, 0x7b, 0xfe, 0x7a, 0x04, 0xf9, 0xf8, 0x12, 0x00, 0x32, 0x7b, + 0x00, 0x7a, 0xc2, 0x79, 0x01, 0x78, 0x00, 0x12, 0x00, 0xbd, 0x8f, 0x0b, 0x8e, 0x0a, 0x8d, 0x09, + 0x8c, 0x08, 0xe4, 0x78, 0x00, 0xf2, 0xe4, 0xff, 0x7e, 0x01, 0xfd, 0xfc, 0xab, 0x0b, 0xaa, 0x0a, + 0xa9, 0x09, 0xa8, 0x08, 0xc3, 0x12, 0x01, 0x4f, 0x40, 0x1c, 0xaf, 0x0b, 0xae, 0x0a, 0xad, 0x09, + 0xac, 0x08, 0x78, 0x01, 0x12, 0x01, 0x60, 0x8f, 0x0b, 0x8e, 0x0a, 0x8d, 0x09, 0x8c, 0x08, 0x78, + 0x00, 0xe2, 0x04, 0xf2, 0x80, 0xd0, 0x78, 0x01, 0xe5, 0x0b, 0xf2, 0xe2, 0x14, 0xf2, 0x22, 0x90, + 0x42, 0x56, 0xe4, 0xf0, 0x90, 0x42, 0x5a, 0xf0, 0x90, 0x42, 0x60, 0xf0, 0xa3, 0xf0, 0x74, 0x03, + 0x12, 0x06, 0xf7, 0x04, 0xf0, 0x90, 0x30, 0x16, 0xe4, 0xf0, 0xa3, 0x74, 0x75, 0xf0, 0x90, 0x30, + 0x09, 0x74, 0x06, 0xf0, 0x90, 0x42, 0x7d, 0x74, 0x01, 0xf0, 0x90, 0x30, 0x1f, 0xe0, 0x44, 0x01, + 0xf0, 0x90, 0x37, 0x33, 0xe0, 0x44, 0x04, 0xf0, 0x90, 0x30, 0x1e, 0x74, 0x05, 0xf0, 0x90, 0x32, + 0x42, 0xe4, 0xf0, 0xa3, 0xf0, 0xa3, 0x12, 0x01, 0x92, 0x00, 0x00, 0x00, 0x00, 0x90, 0x42, 0x82, + 0xe4, 0xf0, 0x90, 0x42, 0x5f, 0x04, 0xf0, 0x90, 0x42, 0x81, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0xef, + 0xb4, 0x0c, 0x00, 0x50, 0x4b, 0x90, 0x0e, 0x0c, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x0e, 0x30, 0x02, + 0x0e, 0x30, 0x02, 0x0e, 0x30, 0x02, 0x0e, 0x30, 0x02, 0x0e, 0x30, 0x02, 0x0e, 0x30, 0x02, 0x0e, + 0x30, 0x02, 0x0e, 0x36, 0x02, 0x0e, 0x3c, 0x02, 0x0e, 0x42, 0x02, 0x0e, 0x48, 0x02, 0x0e, 0x4e, + 0x7c, 0x0f, 0x7d, 0xe0, 0x80, 0x1e, 0x7c, 0x07, 0x7d, 0xf0, 0x80, 0x18, 0x7c, 0x07, 0x7d, 0xf8, + 0x80, 0x12, 0x7c, 0x07, 0x7d, 0xfc, 0x80, 0x0c, 0x7c, 0x07, 0x7d, 0xfe, 0x80, 0x06, 0x80, 0x00, + 0x7c, 0x07, 0x7d, 0xff, 0x90, 0x37, 0x26, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x22, 0xcd, 0xef, 0xcd, + 0xed, 0xd3, 0x94, 0x0e, 0x50, 0x2d, 0x90, 0x32, 0x42, 0xc0, 0x83, 0xc0, 0x82, 0x74, 0x01, 0x7e, + 0x00, 0xc8, 0xed, 0xc8, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe0, + 0x4e, 0xfe, 0xa3, 0xe0, 0x4f, 0xff, 0xd0, 0x82, 0xd0, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xcf, + 0xed, 0xcf, 0x22, 0xed, 0xd3, 0x94, 0x1c, 0x50, 0x0b, 0x90, 0x42, 0x82, 0x74, 0x02, 0xf0, 0xed, + 0x24, 0xf2, 0xff, 0x22, 0xed, 0xd3, 0x94, 0x2a, 0x50, 0x0b, 0x90, 0x42, 0x82, 0x74, 0x01, 0xf0, + 0xed, 0x24, 0xe3, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x8f, 0x15, 0x8d, 0x16, 0xe4, 0xf5, 0x17, 0xf5, + 0x18, 0xf5, 0x19, 0xf5, 0x1a, 0x12, 0x0b, 0xee, 0x8e, 0x17, 0x8f, 0x18, 0xe5, 0x16, 0x60, 0x0f, + 0x90, 0x30, 0x1e, 0x74, 0x86, 0xf0, 0xaf, 0x15, 0x12, 0x0b, 0xee, 0x8e, 0x19, 0x8f, 0x1a, 0xd3, + 0xe5, 0x18, 0x95, 0x1a, 0xe5, 0x19, 0x64, 0x80, 0xf8, 0xe5, 0x17, 0x64, 0x80, 0x98, 0x40, 0x0c, + 0xe5, 0x18, 0x95, 0x1a, 0xff, 0xe5, 0x17, 0x95, 0x19, 0xfe, 0x80, 0x0b, 0xc3, 0xe5, 0x1a, 0x95, + 0x18, 0xff, 0xe5, 0x19, 0x95, 0x17, 0xfe, 0x8e, 0x17, 0x8f, 0x18, 0x90, 0x30, 0x1e, 0x74, 0x05, + 0xf0, 0x22, 0xef, 0xb4, 0x09, 0x00, 0x50, 0x46, 0x90, 0x0f, 0x1f, 0xf8, 0x28, 0x28, 0x73, 0x02, + 0x0f, 0x3a, 0x02, 0x0f, 0x3a, 0x02, 0x0f, 0x3a, 0x02, 0x0f, 0x3a, 0x02, 0x0f, 0x40, 0x02, 0x0f, + 0x46, 0x02, 0x0f, 0x4c, 0x02, 0x0f, 0x52, 0x02, 0x0f, 0x58, 0x7c, 0x00, 0x7d, 0xe0, 0x80, 0x22, + 0x7c, 0x00, 0x7d, 0xf0, 0x80, 0x1c, 0x7c, 0x00, 0x7d, 0xf8, 0x80, 0x16, 0x7c, 0x00, 0x7d, 0xfc, + 0x80, 0x10, 0x7c, 0x00, 0x7d, 0xfe, 0x80, 0x0a, 0x7c, 0x00, 0x7d, 0xff, 0x80, 0x04, 0x7c, 0x0f, + 0x7d, 0xff, 0x90, 0x37, 0x24, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x22, 0x8e, 0x11, 0x8f, 0x12, 0xe4, + 0xf5, 0x13, 0xf5, 0x14, 0xca, 0xee, 0xca, 0xc9, 0xef, 0xc9, 0x75, 0x15, 0x01, 0x8a, 0x16, 0x89, + 0x17, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x24, 0x93, 0x12, 0x06, 0xb0, 0xff, 0xab, 0x15, 0x05, + 0x17, 0xe5, 0x17, 0xaa, 0x16, 0x70, 0x02, 0x05, 0x16, 0x14, 0xf9, 0x12, 0x00, 0x03, 0x25, 0x14, + 0xf5, 0x14, 0xe4, 0x35, 0x13, 0xf5, 0x13, 0x0f, 0xbf, 0x95, 0xe2, 0xc3, 0xe4, 0x95, 0x14, 0xff, + 0xe4, 0x95, 0x13, 0xfe, 0xe5, 0x12, 0x24, 0x93, 0xf5, 0x82, 0xe4, 0x35, 0x11, 0x12, 0x06, 0x2a, + 0x22, 0x8e, 0x0d, 0x8f, 0x0e, 0xe4, 0xf5, 0x0f, 0xf5, 0x10, 0xca, 0xee, 0xca, 0xc9, 0xef, 0xc9, + 0x75, 0x11, 0x01, 0x8a, 0x12, 0x89, 0x13, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x24, 0x3f, 0x12, + 0x06, 0xb0, 0xff, 0xab, 0x11, 0x05, 0x13, 0xe5, 0x13, 0xaa, 0x12, 0x70, 0x02, 0x05, 0x12, 0x14, + 0xf9, 0x12, 0x00, 0x03, 0x25, 0x10, 0xf5, 0x10, 0xe4, 0x35, 0x0f, 0xf5, 0x0f, 0x0f, 0xbf, 0x41, + 0xe2, 0xc3, 0xe4, 0x95, 0x10, 0xff, 0xe4, 0x95, 0x0f, 0xfe, 0xe5, 0x0e, 0x24, 0x3f, 0xf5, 0x82, + 0xe4, 0x35, 0x0d, 0x12, 0x06, 0x2a, 0x22, 0x90, 0x60, 0x01, 0xe4, 0xf0, 0x90, 0x60, 0x00, 0xf0, + 0x90, 0x60, 0x03, 0xef, 0xf0, 0x90, 0x60, 0x02, 0xed, 0xf0, 0x90, 0x60, 0x07, 0x74, 0x02, 0xf0, + 0x90, 0x60, 0x06, 0x14, 0xf0, 0x90, 0x60, 0x12, 0x74, 0xbd, 0xf0, 0xa3, 0x74, 0xc0, 0xf0, 0x90, + 0x60, 0x22, 0x74, 0xbd, 0xf0, 0xa3, 0x74, 0xa0, 0xf0, 0x90, 0x60, 0x10, 0xe4, 0xf0, 0xa3, 0xf0, + 0x90, 0x60, 0x20, 0xf0, 0xa3, 0xf0, 0x90, 0xbf, 0xfd, 0xf0, 0xf5, 0x30, 0x90, 0x60, 0x01, 0x04, + 0xf0, 0x90, 0x60, 0x00, 0xf0, 0x22, 0x8e, 0x08, 0x8f, 0x09, 0x8c, 0x0a, 0x8d, 0x0b, 0xd2, 0xb5, + 0xc2, 0xb2, 0xc2, 0xb1, 0x7f, 0x3b, 0x12, 0x14, 0x36, 0xe4, 0xff, 0x12, 0x14, 0x36, 0xaf, 0x08, + 0x12, 0x14, 0x36, 0xaf, 0x09, 0x12, 0x14, 0x36, 0x7f, 0x08, 0xd2, 0xb0, 0xc2, 0xb0, 0xdf, 0xfa, + 0xc2, 0xb5, 0x85, 0x0b, 0x82, 0x85, 0x0a, 0x83, 0x7e, 0x80, 0x7f, 0x04, 0xd2, 0xb0, 0xa2, 0xb4, + 0x33, 0xa2, 0xb7, 0x33, 0xc2, 0xb0, 0xdf, 0xf4, 0x12, 0x14, 0x73, 0xde, 0xed, 0xdb, 0xe9, 0xc2, + 0xb0, 0xd2, 0xb1, 0x22, 0x8e, 0x08, 0x8f, 0x09, 0x8c, 0x0a, 0x8d, 0x0b, 0xd2, 0xb5, 0xc2, 0xb2, + 0xc2, 0xb1, 0x7f, 0x03, 0x12, 0x14, 0x36, 0xe4, 0xff, 0x12, 0x14, 0x36, 0xaf, 0x08, 0x12, 0x14, + 0x36, 0xaf, 0x09, 0x12, 0x14, 0x36, 0x85, 0x0b, 0x82, 0x85, 0x0a, 0x83, 0x7f, 0x80, 0x7e, 0x08, + 0xd2, 0xb0, 0xa2, 0xb4, 0x33, 0xc2, 0xb0, 0xde, 0xf7, 0x12, 0x14, 0x73, 0xdf, 0xf0, 0xdb, 0xec, + 0xc2, 0xb0, 0xd2, 0xb1, 0x22, 0x8f, 0x15, 0xe5, 0x15, 0x30, 0xe0, 0x07, 0x90, 0x42, 0x7d, 0xe0, + 0x44, 0x02, 0xf0, 0x90, 0x32, 0x44, 0xc0, 0x83, 0xc0, 0x82, 0x12, 0x06, 0xe3, 0xc0, 0xe0, 0xe9, + 0xc0, 0xe0, 0xe4, 0x7f, 0x01, 0xfe, 0xfd, 0xfc, 0xa9, 0x15, 0xc8, 0xe9, 0xc8, 0x12, 0x01, 0x73, + 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0x12, 0x06, 0xd5, 0xd0, 0x82, 0xd0, 0x83, 0x12, 0x01, 0x86, 0xe5, + 0x15, 0xc3, 0x13, 0xff, 0x22, 0x8e, 0x08, 0x8f, 0x09, 0x8c, 0x0a, 0x8d, 0x0b, 0xd2, 0xb5, 0xc2, + 0xb2, 0x12, 0x14, 0x4f, 0xc2, 0xb1, 0x7f, 0x02, 0x12, 0x14, 0x36, 0xe4, 0xff, 0x12, 0x14, 0x36, + 0xaf, 0x0a, 0x12, 0x14, 0x36, 0xaf, 0x0b, 0x12, 0x14, 0x36, 0x85, 0x09, 0x82, 0x85, 0x08, 0x83, + 0xe0, 0xa3, 0xff, 0x12, 0x14, 0x36, 0xdb, 0xf8, 0xc2, 0xb0, 0xd2, 0xb1, 0x12, 0x13, 0x8d, 0x12, + 0x14, 0x5b, 0x22, 0x30, 0x37, 0x2f, 0x31, 0x39, 0x2f, 0x31, 0x33, 0x00, 0x31, 0x38, 0x3a, 0x30, + 0x38, 0x3a, 0x34, 0x36, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xd3, + 0x10, 0xaf, 0x01, 0xc3, 0xc0, 0xd0, 0x8e, 0x1d, 0x8f, 0x1e, 0x12, 0x13, 0x6e, 0xef, 0x60, 0xfa, + 0x85, 0x1e, 0x82, 0x85, 0x1d, 0x83, 0xe0, 0x70, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x30, + 0x0a, 0x09, 0x85, 0x1e, 0x82, 0x85, 0x1d, 0x83, 0x74, 0x01, 0xf0, 0x12, 0x14, 0x6d, 0xa2, 0x0a, + 0xe4, 0x33, 0xff, 0xd0, 0xd0, 0x92, 0xaf, 0x22, 0xfd, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0xef, + 0x9d, 0xec, 0x64, 0x80, 0xf8, 0xee, 0x64, 0x80, 0x98, 0x40, 0x08, 0xef, 0x9d, 0xfb, 0xee, 0x9c, + 0xfa, 0x80, 0x07, 0xc3, 0xed, 0x9f, 0xfb, 0xec, 0x9e, 0xfa, 0xd3, 0xef, 0x94, 0x00, 0xee, 0x64, + 0x80, 0x94, 0x80, 0x40, 0x04, 0xca, 0x44, 0x80, 0xca, 0xcf, 0xeb, 0xcf, 0xce, 0xea, 0xce, 0x22, + 0xce, 0xed, 0xce, 0xef, 0x14, 0x60, 0x09, 0x04, 0x70, 0x26, 0x90, 0x40, 0x33, 0xe4, 0xf0, 0x22, + 0x90, 0x42, 0x53, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0x42, 0x6c, 0xe4, 0xf0, 0x90, 0x42, 0x69, 0xf0, + 0xa3, 0x12, 0x14, 0x29, 0xcf, 0xee, 0xcf, 0x12, 0x12, 0x51, 0x90, 0x40, 0x33, 0x74, 0x01, 0xf0, + 0x22, 0xcd, 0xef, 0xcd, 0xed, 0x54, 0x03, 0x75, 0xf0, 0x10, 0xa4, 0xff, 0x90, 0x42, 0x80, 0xe0, + 0xfa, 0xa3, 0xe0, 0x54, 0xcf, 0xfb, 0xea, 0x45, 0xf0, 0xfe, 0xeb, 0x4f, 0xff, 0x90, 0x42, 0x80, + 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xed, 0x13, 0x13, 0x54, 0x3f, 0x90, 0x42, 0x6b, 0xf0, 0x22, 0x8e, + 0x08, 0x8f, 0x09, 0xd2, 0xb5, 0xc2, 0xb2, 0x12, 0x14, 0x4f, 0xc2, 0xb1, 0x7f, 0x20, 0x12, 0x14, + 0x36, 0xe4, 0xff, 0x12, 0x14, 0x36, 0xaf, 0x08, 0x12, 0x14, 0x36, 0xaf, 0x09, 0x12, 0x14, 0x36, + 0xc2, 0xb0, 0xd2, 0xb1, 0x12, 0x13, 0x8d, 0x12, 0x14, 0x5b, 0x22, 0x90, 0x30, 0x1f, 0xe0, 0x54, + 0xfe, 0xf0, 0x90, 0x37, 0x33, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x30, 0x39, 0xe4, 0xf0, 0x90, 0x30, + 0x05, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x42, 0x5f, 0x74, 0x03, 0xf0, 0x90, + 0x42, 0x81, 0xe0, 0x54, 0xfe, 0xf0, 0x22, 0xe4, 0xff, 0xa2, 0x0b, 0xe4, 0x33, 0xfe, 0xef, 0xc3, + 0x13, 0x24, 0x2c, 0x12, 0x06, 0x5a, 0xee, 0xf0, 0x0f, 0xbf, 0x1e, 0xed, 0xe4, 0xff, 0xa2, 0x0b, + 0xe4, 0x33, 0xfe, 0xef, 0x90, 0x11, 0x85, 0x93, 0x12, 0x06, 0x58, 0xee, 0xf0, 0x0f, 0xbf, 0x2a, + 0xed, 0x22, 0x90, 0x60, 0x15, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0xf7, 0x90, 0xbf, 0xfd, 0xe0, 0x24, + 0xc0, 0xf5, 0x82, 0xe4, 0x34, 0xbd, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0xbf, 0xfd, 0xe0, 0x04, 0xf0, + 0xe0, 0x54, 0x3f, 0xf0, 0x90, 0x60, 0x1b, 0x74, 0x01, 0xf0, 0x22, 0xcd, 0xef, 0xcd, 0xcc, 0xee, + 0xcc, 0xd3, 0xed, 0x94, 0xfa, 0xec, 0x94, 0x00, 0x40, 0x0f, 0x7f, 0xfa, 0x12, 0x13, 0xd9, 0x74, + 0x06, 0x2d, 0xfd, 0x74, 0xff, 0x3c, 0xfc, 0x80, 0xe8, 0xcf, 0xed, 0xcf, 0x02, 0x13, 0xd9, 0xd3, + 0x10, 0xaf, 0x01, 0xc3, 0x90, 0x40, 0xa4, 0xe0, 0xf5, 0x33, 0x85, 0xdd, 0x34, 0x85, 0xde, 0x35, + 0x85, 0xdf, 0x36, 0x92, 0xaf, 0xaf, 0x36, 0xae, 0x35, 0xad, 0x34, 0xac, 0x33, 0x22, 0xd3, 0x10, + 0xaf, 0x01, 0xc3, 0xc0, 0xd0, 0x90, 0x40, 0xdf, 0x74, 0x0d, 0xf0, 0x90, 0x40, 0xfd, 0xe0, 0xb4, + 0x0d, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xd0, 0xd0, 0x92, 0xaf, 0x22, 0xc2, 0xb1, 0x7f, + 0x05, 0x12, 0x14, 0x36, 0x7f, 0x07, 0xd2, 0xb0, 0xc2, 0xb0, 0xdf, 0xfa, 0xd2, 0xb0, 0xa2, 0xb4, + 0x92, 0x0b, 0xc2, 0xb0, 0x20, 0x0b, 0xe6, 0x22, 0xd2, 0xb5, 0xc2, 0xb2, 0x12, 0x14, 0x4f, 0xc2, + 0xb1, 0x7f, 0x60, 0x12, 0x14, 0x36, 0xc2, 0xb0, 0xd2, 0xb1, 0x12, 0x13, 0x8d, 0x12, 0x14, 0x5b, + 0x22, 0xc2, 0xb1, 0x7f, 0x05, 0x12, 0x14, 0x36, 0x7f, 0x08, 0xd2, 0xb0, 0xa2, 0xb4, 0x33, 0xc2, + 0xb0, 0xdf, 0xf7, 0xc2, 0xb0, 0xd2, 0xb1, 0xff, 0x22, 0x90, 0x40, 0xa7, 0xe0, 0xfe, 0x90, 0x40, + 0xa7, 0xe0, 0xc3, 0x9e, 0xc3, 0x9f, 0x40, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x50, 0xf0, 0x22, 0x02, + 0x2d, 0xbb, 0x80, 0x01, 0x20, 0x00, 0x4a, 0x80, 0x00, 0x42, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xd3, 0x10, 0xaf, 0x01, 0xc3, 0x90, 0x40, 0xa6, 0xe0, 0xf5, 0x37, 0x85, + 0xdf, 0x38, 0x92, 0xaf, 0xae, 0x37, 0xaf, 0x38, 0x22, 0x78, 0x00, 0xe2, 0xff, 0x08, 0xe2, 0xfd, + 0x12, 0x10, 0x17, 0xe4, 0xf5, 0x22, 0xf5, 0x2f, 0x22, 0xf0, 0x90, 0x42, 0x53, 0xe0, 0x54, 0xfe, + 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0xef, 0x7f, 0x08, 0x33, 0x92, 0xb6, 0xd2, 0xb0, 0xc2, 0xb0, + 0xdf, 0xf7, 0x22, 0x90, 0x40, 0x4b, 0x74, 0x03, 0xf0, 0x90, 0x40, 0x4a, 0xe4, 0xf0, 0x22, 0xc2, + 0xb1, 0x7f, 0x06, 0x12, 0x14, 0x36, 0xc2, 0xb0, 0xd2, 0xb1, 0x22, 0xc2, 0xb1, 0x7f, 0x04, 0x12, + 0x14, 0x36, 0xc2, 0xb0, 0xd2, 0xb1, 0x22, 0x90, 0x40, 0xe3, 0xef, 0xf0, 0x22, 0x90, 0x40, 0xdf, + 0xe4, 0xf0, 0x22, 0xf0, 0xa3, 0x22, +}; + +u8 config[256] = {(u8)(GTP_REG_CONFIG_DATA >> 8), (u8)GTP_REG_CONFIG_DATA, + 0x00, 0x38, 0x04, 0xE8, 0x08, 0x0A, 0x0C, 0x00, 0x01, 0x08, 0x28, 0x0D, 0x5A, 0x41, 0x03, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x14, 0x87, 0x27, 0xEE, 0x4B, 0x4D, 0x31, 0x0D, 0x31, 0x0D, 0x00, 0x02, + 0x03, 0x11, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x32, 0x00, 0x00, 0x00, 0x1E, 0x5A, 0x94, 0x00, 0x03, 0x05, + 0x1E, 0x00, 0x04, 0xCA, 0x21, 0x00, 0xAB, 0x29, 0x00, 0x91, 0x34, 0x00, 0x7E, 0x41, 0x00, 0x71, 0x51, 0x00, 0x71, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x17, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x18, 0x19, 0x1A, 0x1B, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0x08, 0x06, 0x05, 0x04, 0x0A, 0x0C, 0x0E, 0x1E, 0x1F, 0x20, + 0x22, 0x24, 0x29, 0x2A, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01}; + +#define MIN_DRIVER_NUM 10 +#define MAX_DRIVER_NUM 42 +#define MIN_SENSOR_NUM 5 +#define MAX_SENSOR_NUM 30 + +unsigned short gt900_short_threshold = 10; +unsigned short gt900_resistor_threshold = 800; +unsigned short gt900_resistor_warn_threshold = 500; +unsigned short gt900_gnd_resistor_threshold = 500; + +/*QFN88 package TX Pin, used for get channel number from Chip to Pad*/ +const u8 ChannelPackage_TX[MAX_DRIVER_NUM] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25,/*26,*/27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42 +}; + +#define GT9_DRV_HEAD 0x80 +#define GT9_SEN_HEAD 0x00 + + +/* register defines for burning of dsp_short*/ +#define _bRW_MISCTL__SRAM_BANK 0x4048 +#define _bRW_MISCTL__MEM_CD_EN 0x4049 +#define _bRW_MISCTL__CACHE_EN 0x404b +#define _bRW_MISCTL__TMR0_EN 0x40b0 +#define _rRW_MISCTL__SWRST_B0_ 0x4180 +#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184 +#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190 +#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218 +#define _bRW_MISCTL__RG_OSC_CALIB 0x4268 +#define _rRW_MISCTL__BOOT_CTL_ 0x5094 +#define _rRW_MISCTL__SHORT_BOOT_FLAG 0x5095 + + +#define GTP_REG_DSP_SHORT 0xc000 + +#define GT9_REG_SEN_DRV_CNT 0x8062 +#define GT9_REG_CFG_BEG 0x8047 +#define GT9_REG_KEY_VAL 0x8093 + +#define GT9_REG_SEN_ORD 0x80B7 +#define GT9_REG_DRV_ORD 0x80D5 + + +struct gt9xx_short_info { + u8 master; + u8 master_is_driver; + u8 slave; + u8 slave_is_driver; + u16 short_code; + u16 self_data; + u16 impedance; +}; + +#define MYBIG_ENDIAN 1 +#define MYLITLE_ENDIAN 0 + +#define _BEYOND_MAX_LIMIT 0x0001 +#define _BEYOND_MIN_LIMIT 0x0002 +#define _BEYOND_KEY_MAX_LMT 0x0004 +#define _BEYOND_KEY_MIN_LMT 0x0008 +#define _BEYOND_UNIFORMITY_LMT 0x0010 + +#define _MAX_TEST 0x0001 +#define _MIN_TEST 0x0002 +#define _KEY_MAX_TEST 0x0004 +#define _KEY_MIN_TEST 0x0008 +#define _UNIFORMITY_TEST 0x0010 + +#define _CHANNEL_PASS 0x0000 + +#define GTP_WAIT_RAW_MAX_TIMES 200 +#define GTP_REG_RAW_DATA 0x9b60 +#define GTP_REG_DIFF_DATA 0xa160 +#define GTP_REG_READ_RAW 0x8040 +#define GTP_REG_RAW_READY 0x814E +#define GTP_REG_RAW_DATA_GT9F 0x87C0 + +struct gt9xx_open_info { + u8 driver; + u8 sensor; + u16 raw_val; + s32 beyond_type; + u8 times; + u8 key; +}; + + +#endif + diff --git a/drivers/input/touchscreen/gt917d/gt9xx_update.c b/drivers/input/touchscreen/gt917d/gt9xx_update.c new file mode 100644 index 0000000000000..d06b449b6c262 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/gt9xx_update.c @@ -0,0 +1,2109 @@ +/* + * Goodix GT9xx touchscreen driver + * + * Copyright (C) 2016 - 2017 Goodix. Ltd. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be a reference + * to you, when you are integrating the GOODiX's CTP IC into your system, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * Version: 2.8.0.1 + * Release Date: 2017/11/24 + */ + +#include +#include "gt9xx.h" + +#include +#include +#include +#include + +#define GUP_REG_HW_INFO 0x4220 +#define GUP_REG_FW_MSG 0x41E4 +#define GUP_REG_PID_VID 0x8140 + +#define FIRMWARE_NAME_LEN_MAX 256 +#define GOODIX_FIRMWARE_FILE_NAME "goodix_firmware.bin" +#define GOODIX_CONFIG_FILE_NAME "goodix_config.cfg" + +#define FW_HEAD_LENGTH 14 +#define FW_SECTION_LENGTH 0x2000 /* 8K */ +#define FW_DSP_ISP_LENGTH 0x1000 /* 4K */ +#define FW_DSP_LENGTH 0x1000 /* 4K */ +#define FW_BOOT_LENGTH 0x800 /* 2K */ +#define FW_SS51_LENGTH (4 * FW_SECTION_LENGTH) /* 32K */ +#define FW_BOOT_ISP_LENGTH 0x800 /* 2k */ +#define FW_GLINK_LENGTH 0x3000 /* 12k */ +#define FW_GWAKE_LENGTH (4 * FW_SECTION_LENGTH) /* 32k */ + +#define PACK_SIZE 256 +#define MAX_FRAME_CHECK_TIME 5 + + +#define _bRW_MISCTL__SRAM_BANK 0x4048 +#define _bRW_MISCTL__MEM_CD_EN 0x4049 +#define _bRW_MISCTL__CACHE_EN 0x404B +#define _bRW_MISCTL__TMR0_EN 0x40B0 +#define _rRW_MISCTL__SWRST_B0_ 0x4180 +#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184 +#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190 +#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218 +#define _rRW_MISCTL__BOOT_CTL_ 0x5094 + +#pragma pack(1) +struct st_fw_head { + u8 hw_info[4]; /* hardware info */ + u8 pid[8]; /* product id */ + u16 vid; /* version id */ +}; +#pragma pack() + +struct st_update_msg { + u8 fw_damaged; + u8 fw_flag; + const u8 *fw_data; + struct file *cfg_file; + struct st_fw_head ic_fw_msg; + u32 fw_total_len; + u32 fw_burned_len; + const struct firmware *fw; +} update_msg; + +struct st_update_msg update_msg; + +u16 show_len; +u16 total_len; + +static u8 gup_burn_fw_gwake_section(struct i2c_client *client, + u8 *fw_section, u16 start_addr, + u32 len, u8 bank_cmd); + +static s32 gup_init_panel(struct goodix_ts_data *ts) +{ + s32 ret = 0; + u8 opr_buf[16]; + u8 sensor_id = 0; + u8 drv_cfg_version; + u8 flash_cfg_version; + struct goodix_config_data *cfg = &ts->pdata->config; + + if (cfg->length < GTP_CONFIG_MIN_LENGTH) { + dev_err(&ts->client->dev, + "No valid config with sensor_ID(%d) ", + sensor_id); + + return -EPERM; + } + + ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, + &opr_buf[0], 1); + if (ret == SUCCESS) { + dev_dbg(&ts->client->dev, + "CFG_GROUP%d Config Version: %d, IC Config Version: %d", + sensor_id, cfg->data[GTP_ADDR_LENGTH], opr_buf[0]); + + flash_cfg_version = opr_buf[0]; + drv_cfg_version = cfg->data[GTP_ADDR_LENGTH]; + + if (flash_cfg_version < 90 && + flash_cfg_version > drv_cfg_version) + cfg->data[GTP_ADDR_LENGTH] = 0x00; + } else { + dev_err(&ts->client->dev, + "Failed to get ic config version!No config sent!"); + return -EPERM; + } + + ret = gtp_send_cfg(ts->client); + if (ret < 0) + dev_err(&ts->client->dev, "Send config error."); + else + usleep_range(10000, 11000); + + /* restore config vrsion */ + cfg->data[GTP_ADDR_LENGTH] = drv_cfg_version; + + return 0; +} + + +static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len) +{ + s32 i = 0; + + msg[0] = (addr >> 8) & 0xff; + msg[1] = addr & 0xff; + + for (i = 0; i < 5; i++) { + if (gtp_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0) + break; + } + + if (i >= 5) { + dev_err(&client->dev, + "Read data from 0x%02x%02x failed!", + msg[0], msg[1]); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val) +{ + s32 i = 0; + u8 msg[3]; + + msg[0] = (addr >> 8) & 0xff; + msg[1] = addr & 0xff; + msg[2] = val; + + for (i = 0; i < 5; i++) { + if (gtp_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0) + break; + } + + if (i >= 5) { + dev_err(&client->dev, + "Set data to 0x%02x%02x failed!", msg[0], msg[1]); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_get_ic_fw_msg(struct i2c_client *client) +{ + s32 ret = -1; + u8 retry = 0; + u8 buf[16]; + u8 i; + + /* step1:get hardware info */ + ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO, + &buf[GTP_ADDR_LENGTH], 4); + if (FAIL == ret) { + dev_err(&client->dev, "[get_ic_fw_msg]get hw_info failed,exit"); + return FAIL; + } + + /* buf[2~5]: 00 06 90 00 + * hw_info: 00 90 06 00 + */ + for (i = 0; i < 4; i++) + update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i]; + dev_dbg(&client->dev, + "IC Hardware info:%02x%02x%02x%02x", + update_msg.ic_fw_msg.hw_info[0], + update_msg.ic_fw_msg.hw_info[1], + update_msg.ic_fw_msg.hw_info[2], + update_msg.ic_fw_msg.hw_info[3]); + /* step2:get firmware message */ + for (retry = 0; retry < 2; retry++) { + ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1); + if (FAIL == ret) { + dev_err(&client->dev, "Read firmware message fail."); + return ret; + } + + update_msg.fw_damaged = buf[GTP_ADDR_LENGTH]; + if ((0xBE != update_msg.fw_damaged) && (!retry)) { + dev_info(&client->dev, "The check sum in ic is error."); + dev_info(&client->dev, "The IC will be updated by force."); + continue; + } + break; + } + dev_dbg(&client->dev, + "IC force update flag:0x%x", update_msg.fw_damaged); + + /* step3:get pid & vid */ + ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID, + &buf[GTP_ADDR_LENGTH], 6); + if (FAIL == ret) { + dev_err(&client->dev, "[get_ic_fw_msg]get pid & vid failed,exit"); + return FAIL; + } + + memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid)); + memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4); + dev_dbg(&client->dev, "IC Product id:%s", update_msg.ic_fw_msg.pid); + + /* GT9XX PID MAPPING */ + /*|-----FLASH-----RAM-----| + *|------918------918-----| + *|------968------968-----| + *|------913------913-----| + *|------913P-----913P----| + *|------927------927-----| + *|------927P-----927P----| + *|------9110-----9110----| + *|------9110P----9111----|*/ + if (update_msg.ic_fw_msg.pid[0] != 0) { + if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) { + dev_dbg(&client->dev, "IC Mapping Product id:%s", + update_msg.ic_fw_msg.pid); + memcpy(update_msg.ic_fw_msg.pid, "9110P", 5); + } + } + + update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] + + (buf[GTP_ADDR_LENGTH + 5] << 8); + dev_dbg(&client->dev, "IC version id:%04x", update_msg.ic_fw_msg.vid); + + return SUCCESS; +} + +s32 gup_enter_update_mode(struct i2c_client *client) +{ + s32 ret = -1; + s32 retry = 0; + u8 rd_buf[3]; + + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + /* step1:RST output low last at least 2ms */ + if (!gpio_is_valid(ts->pdata->rst_gpio)) { + dev_err(&ts->client->dev, "update failed, no rst pin\n"); + return FAIL; + } + gpio_direction_output(ts->pdata->rst_gpio, 0); + usleep_range(2000, 3000); + + /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */ + gtp_int_output(ts, client->addr == 0x14); + usleep_range(2000, 3000); + + /* step3:RST output high reset guitar */ + gpio_direction_output(ts->pdata->rst_gpio, 1); + + /* 20121211 modify start */ + usleep_range(5000, 6000); + while (retry++ < 200) { + /* step4:Hold ss51 & dsp */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_dbg(&client->dev, + "Hold ss51 & dsp I2C error,retry:%d", + retry); + continue; + } + + /* step5:Confirm hold */ + ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1); + if (ret <= 0) { + dev_dbg(&client->dev, + "Hold ss51 & dsp I2C error,retry:%d", + retry); + continue; + } + if (0x0C == rd_buf[GTP_ADDR_LENGTH]) { + dev_dbg(&client->dev, "Hold ss51 & dsp confirm SUCCESS"); + break; + } + dev_dbg(&client->dev, + "Hold ss51 & dsp confirm 0x4180 failed,value:%d", + rd_buf[GTP_ADDR_LENGTH]); + } + if (retry >= 200) { + dev_err(&client->dev, "Enter update Hold ss51 failed."); + return FAIL; + } + + /* step6:DSP_CK and DSP_ALU_CK PowerOn */ + ret = gup_set_ic_msg(client, 0x4010, 0x00); + + /* 20121211 modify end */ + return ret; +} + +void gup_leave_update_mode(struct i2c_client *client) +{ + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + if (ts->pdata->int_sync && ts->pinctrl.pinctrl) + pinctrl_select_state(ts->pinctrl.pinctrl, + ts->pinctrl.int_input); + else if (ts->pdata->int_sync && gpio_is_valid(ts->pdata->irq_gpio)) + gpio_direction_input(ts->pdata->irq_gpio); + dev_dbg(&client->dev, "[leave_update_mode]reset chip."); + gtp_reset_guitar(i2c_connect_client, 20); +} + +static u8 gup_enter_update_judge(struct i2c_client *client, + struct st_fw_head *fw_head) +{ + u16 u16_tmp; + s32 i = 0; + u32 fw_len = 0; + s32 pid_cmp_len = 0; + + u16_tmp = fw_head->vid; + fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8); + + dev_info(&client->dev, "FILE HARDWARE INFO:%*ph\n", 4, + &fw_head->hw_info[0]); + dev_info(&client->dev, "FILE PID:%s\n", fw_head->pid); + dev_info(&client->dev, "FILE VID:%04x\n", fw_head->vid); + + dev_info(&client->dev, "IC HARDWARE INFO:%*ph\n", 4, + &update_msg.ic_fw_msg.hw_info[0]); + dev_info(&client->dev, "IC PID:%s\n", update_msg.ic_fw_msg.pid); + dev_info(&client->dev, "IC VID:%04x\n", update_msg.ic_fw_msg.vid); + + if (!memcmp(fw_head->pid, "9158", 4) && + !memcmp(update_msg.ic_fw_msg.pid, "915S", 4)) { + dev_info(&client->dev, "Update GT915S to GT9158 directly!"); + return SUCCESS; + } + /* First two conditions */ + if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info, + sizeof(update_msg.ic_fw_msg.hw_info))) { + fw_len = 42 * 1024; + } else { + fw_len = fw_head->hw_info[3]; + fw_len += (((u32)fw_head->hw_info[2]) << 8); + fw_len += (((u32)fw_head->hw_info[1]) << 16); + fw_len += (((u32)fw_head->hw_info[0]) << 24); + } + if (update_msg.fw_total_len != fw_len) { + dev_err(&client->dev, + "Inconsistent firmware size, Update aborted!"); + dev_err(&client->dev, + " Default size: %d(%dK), actual size: %d(%dK)", + fw_len, fw_len/1024, update_msg.fw_total_len, + update_msg.fw_total_len/1024); + return FAIL; + } + dev_info(&client->dev, "Firmware length:%d(%dK)", + update_msg.fw_total_len, + update_msg.fw_total_len/1024); + + if (update_msg.fw_damaged != 0xBE) { + dev_info(&client->dev, "FW chksum error,need enter update."); + return SUCCESS; + } + + /* 20130523 start */ + if (strlen(update_msg.ic_fw_msg.pid) < 3) { + dev_info(&client->dev, "Illegal IC pid, need enter update"); + return SUCCESS; + } + + /* check pid legality */ + for (i = 0; i < 3; i++) { + if (!isdigit(update_msg.ic_fw_msg.pid[i])) { + dev_info(&client->dev, + "Illegal IC pid, need enter update"); + return SUCCESS; + } + } + /* 20130523 end */ + + pid_cmp_len = strlen(fw_head->pid); + if (pid_cmp_len < strlen(update_msg.ic_fw_msg.pid)) + pid_cmp_len = strlen(update_msg.ic_fw_msg.pid); + + if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, pid_cmp_len)) || + (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) || + (!memcmp(fw_head->pid, "91XX", 4))) { + if (!memcmp(fw_head->pid, "91XX", 4)) + dev_dbg(&client->dev, + "Force none same pid update mode."); + else + dev_dbg(&client->dev, "Get the same pid."); + + /* The third condition */ + if (fw_head->vid != update_msg.ic_fw_msg.vid) { + dev_info(&client->dev, "Need enter update."); + return SUCCESS; + } + dev_err(&client->dev, "File VID == Ic VID, update aborted!"); + } else { + dev_err(&client->dev, "File PID != Ic PID, update aborted!"); + } + + return FAIL; +} + +static int gup_update_config(struct i2c_client *client) +{ + s32 ret = 0; + s32 i = 0; + s32 file_cfg_len = 0; + u8 *file_config; + const struct firmware *fw_cfg; + + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + ret = request_firmware(&fw_cfg, GOODIX_CONFIG_FILE_NAME, + &client->dev); + if (ret < 0) { + dev_err(&client->dev, + "Cannot get config file - %s (%d)\n", + GOODIX_CONFIG_FILE_NAME, ret); + return -EFAULT; + } + if (!fw_cfg || !fw_cfg->data || fw_cfg->size > PAGE_SIZE) { + dev_err(&client->dev, "config file illegal"); + ret = -EFAULT; + goto cfg_fw_err; + } + + dev_dbg(&client->dev, "config firmware file len:%zu", fw_cfg->size); + + file_config = kzalloc(GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, + GFP_KERNEL); + if (!file_config) { + dev_err(&ts->client->dev, "failed alloc memory"); + ret = -ENOMEM; + goto cfg_fw_err; + } + file_config[0] = GTP_REG_CONFIG_DATA >> 8; + file_config[1] = GTP_REG_CONFIG_DATA & 0xff; + file_cfg_len = gtp_ascii_to_array(fw_cfg->data, fw_cfg->size, + &file_config[GTP_ADDR_LENGTH]); + if (file_cfg_len < 0) { + dev_err(&client->dev, "failed covert ascii to hex"); + ret = -EFAULT; + goto update_cfg_file_failed; + } + + GTP_DEBUG_ARRAY(file_config + GTP_ADDR_LENGTH, file_cfg_len); + + i = 0; + while (i++ < 5) { + ret = gtp_i2c_write(client, file_config, file_cfg_len + 2); + if (ret > 0) { + dev_info(&client->dev, "Send config SUCCESS."); + msleep(500); + break; + } + dev_err(&ts->client->dev, "Send config i2c error."); + } + +update_cfg_file_failed: + kfree(file_config); +cfg_fw_err: + release_firmware(fw_cfg); + return ret; +} + +static u8 gup_check_firmware_name(struct i2c_client *client, + u8 **path_p) +{ + u8 len; + u8 *fname; + + printk("Enter %s --- Line : %d\n", __func__, __LINE__); + + if (!(*path_p)) { + *path_p = GOODIX_FIRMWARE_FILE_NAME; + return 0; + } + + len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX); + if (len >= FIRMWARE_NAME_LEN_MAX) { + dev_err(&client->dev, "firmware name too long!"); + return -EINVAL; + } + + fname = strrchr(*path_p, '/'); + if (fname) { + fname = fname + 1; + *path_p = fname; + } + + return 0; +} + +static u8 gup_get_update_file(struct i2c_client *client, + struct st_fw_head *fw_head, u8 *path) +{ + s32 ret = 0; + s32 i = 0; + s32 fw_checksum = 0; + struct goodix_ts_data *ts = i2c_get_clientdata(client); + + printk("Enter %s --- Line : %d\n", __func__, __LINE__); + + if (ts->pdata->auto_update_cfg) { + ret = gup_update_config(client); + if (ret <= 0) + dev_err(&client->dev, "Update config failed."); + } + + ret = gup_check_firmware_name(client, &path); + if (ret < 0) + return FAIL; + + ret = request_firmware(&update_msg.fw, path, &client->dev); + if (ret < 0) { + dev_err(&client->dev, "Failed get firmware:%d\n", ret); + return FAIL; + } + + dev_info(&client->dev, "FW File: %s size=%zu", + path, update_msg.fw->size); + update_msg.fw_data = update_msg.fw->data; + update_msg.fw_total_len = update_msg.fw->size; + + if (update_msg.fw_total_len < + FW_HEAD_LENGTH + FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH + + FW_DSP_LENGTH + FW_BOOT_LENGTH) { + dev_err(&client->dev, + "INVALID bin file(size: %d), update aborted.", + update_msg.fw_total_len); + goto invalied_fw; + } + + update_msg.fw_total_len -= FW_HEAD_LENGTH; + + dev_dbg(&client->dev, "Bin firmware actual size: %d(%dK)", + update_msg.fw_total_len, update_msg.fw_total_len/1024); + + memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH); + + /* check firmware legality */ + fw_checksum = 0; + for (i = 0; i < update_msg.fw_total_len; i += 2) { + u16 temp; + + temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) + + update_msg.fw_data[FW_HEAD_LENGTH + i + 1]; + fw_checksum += temp; + } + + dev_dbg(&client->dev, "firmware checksum:%x", fw_checksum&0xFFFF); + if (fw_checksum & 0xFFFF) { + dev_err(&client->dev, "Illegal firmware file."); + goto invalied_fw; + } + + return SUCCESS; + +invalied_fw: + update_msg.fw_data = NULL; + update_msg.fw_total_len = 0; + release_firmware(update_msg.fw); + return FAIL; +} + +static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, + u16 start_addr, u16 total_length) +{ + s32 ret = 0; + u16 burn_addr = start_addr; + u16 frame_length = 0; + u16 burn_length = 0; + u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH]; + u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; + u8 retry = 0; + + dev_dbg(&client->dev, "Begin burn %dk data to addr 0x%x", + total_length / 1024, start_addr); + while (burn_length < total_length) { + dev_dbg(&client->dev, + "B/T:%04d/%04d", burn_length, total_length); + frame_length = ((total_length - burn_length) + > PACK_SIZE) ? PACK_SIZE : (total_length - burn_length); + wr_buf[0] = (u8)(burn_addr>>8); + rd_buf[0] = wr_buf[0]; + wr_buf[1] = (u8)burn_addr; + rd_buf[1] = wr_buf[1]; + memcpy(&wr_buf[GTP_ADDR_LENGTH], + &burn_buf[burn_length], frame_length); + + for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) { + ret = gtp_i2c_write(client, + wr_buf, GTP_ADDR_LENGTH + frame_length); + if (ret <= 0) { + dev_err(&client->dev, + "Write frame data i2c error."); + continue; + } + ret = gtp_i2c_read(client, rd_buf, + GTP_ADDR_LENGTH + frame_length); + if (ret <= 0) { + dev_err(&client->dev, + "Read back frame data i2c error."); + continue; + } + if (memcmp(&wr_buf[GTP_ADDR_LENGTH], + &rd_buf[GTP_ADDR_LENGTH], frame_length)) { + dev_err(&client->dev, + "Check frame data fail,not equal."); + dev_dbg(&client->dev, "write array:"); + GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH], + frame_length); + dev_dbg(&client->dev, "read array:"); + GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], + frame_length); + continue; + } else { + /* dev_dbg(&client->dev, + * "Check frame data success."); + */ + break; + } + } + if (retry >= MAX_FRAME_CHECK_TIME) { + dev_err(&client->dev, + "Burn frame data time out,exit."); + return FAIL; + } + burn_length += frame_length; + burn_addr += frame_length; + } + + return SUCCESS; +} + +static u8 gup_load_section_file(u8 *buf, u32 offset, u16 length, u8 set_or_end) +{ + if (!update_msg.fw_data || + update_msg.fw_total_len < FW_HEAD_LENGTH + offset + length) { + pr_err("<<-GTP->> cannot load section data. fw_len=%d read end=%d\n", + update_msg.fw_total_len, + FW_HEAD_LENGTH + offset + length); + return FAIL; + } + + + if (SEEK_SET == set_or_end) { + memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], + length); + } else { + /* seek end */ + memcpy(buf, &update_msg.fw_data[update_msg.fw_total_len + + FW_HEAD_LENGTH - offset], length); + } + + return SUCCESS; +} + +static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src, + u16 start_rd_addr, u16 chk_length) +{ + u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; + s32 ret = 0; + u16 recall_addr = start_rd_addr; + u16 recall_length = 0; + u16 frame_length = 0; + + while (recall_length < chk_length) { + frame_length = ((chk_length - recall_length) + > PACK_SIZE) ? PACK_SIZE : + (chk_length - recall_length); + ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length); + if (ret <= 0) { + dev_err(&client->dev, "recall i2c error,exit"); + return FAIL; + } + + if (memcmp(&rd_buf[GTP_ADDR_LENGTH], + &chk_src[recall_length], frame_length)) { + dev_err(&client->dev, "Recall frame data fail,not equal."); + dev_dbg(&client->dev, "chk_src array:"); + GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length); + dev_dbg(&client->dev, "recall array:"); + GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length); + return FAIL; + } + + recall_length += frame_length; + recall_addr += frame_length; + } + dev_dbg(&client->dev, + "Recall check %dk firmware success.", + (chk_length/1024)); + + return SUCCESS; +} + +static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, + u16 start_addr, u8 bank_cmd) +{ + s32 ret = 0; + u8 rd_buf[5]; + + /* step1:hold ss51 & dsp */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_section]hold ss51 & dsp fail."); + return FAIL; + } + + /* step2:set scramble */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_section]set scramble fail."); + return FAIL; + } + + /* step3:select bank */ + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, + (bank_cmd >> 4)&0x0F); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]select bank %d fail.", + (bank_cmd >> 4)&0x0F); + return FAIL; + } + + /* step4:enable accessing code */ + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]enable accessing code fail."); + return FAIL; + } + + /* step5:burn 8k fw section */ + ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_section]burn fw_section fail."); + return FAIL; + } + + /* step6:hold ss51 & release dsp */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]hold ss51 & release dsp fail."); + return FAIL; + } + /* must delay */ + usleep_range(10000, 20000); + + /* step7:send burn cmd to move data to flash from sram */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_section]send burn cmd fail."); + return FAIL; + } + dev_dbg(&client->dev, + "[burn_fw_section]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]Get burn state fail"); + return FAIL; + } + usleep_range(10000, 11000); + /* dev_dbg(&client->dev, "[burn_fw_section]Get burn state:%d.", + * rd_buf[GTP_ADDR_LENGTH]); + */ + } while (rd_buf[GTP_ADDR_LENGTH]); + + /* step8:select bank */ + ret = gup_set_ic_msg(client, + _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4) & 0x0F); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]select bank %d fail.", + (bank_cmd >> 4)&0x0F); + return FAIL; + } + + /* step9:enable accessing code */ + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]enable accessing code fail."); + return FAIL; + } + + /* step10:recall 8k fw section */ + ret = gup_recall_check(client, + fw_section, start_addr, FW_SECTION_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_section]recall check %dk firmware fail.", + FW_SECTION_LENGTH / 1024); + return FAIL; + } + + /* step11:disable accessing code */ + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]disable accessing code fail."); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_burn_dsp_isp(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_dsp_isp = NULL; + u8 retry = 0; + + dev_info(&client->dev, "[burn_dsp_isp]Begin burn dsp isp---->>"); + + /* step1:alloc memory */ + dev_dbg(&client->dev, "[burn_dsp_isp]step1:alloc memory"); + while (retry++ < 5) { + fw_dsp_isp = kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL); + if (fw_dsp_isp == NULL) { + continue; + } else { + dev_info(&client->dev, + "[burn_dsp_isp]Alloc %dk byte memory success.", + FW_DSP_ISP_LENGTH / 1024); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, "[burn_dsp_isp]Alloc memory fail,exit."); + return FAIL; + } + + /* step2:load dsp isp file data */ + dev_dbg(&client->dev, "[burn_dsp_isp]step2:load dsp isp file data"); + ret = gup_load_section_file(fw_dsp_isp, + FW_DSP_ISP_LENGTH, FW_DSP_ISP_LENGTH, SEEK_END); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_dsp_isp]load firmware dsp_isp fail."); + goto exit_burn_dsp_isp; + } + + /* step3:disable wdt,clear cache enable */ + dev_dbg(&client->dev, + "[burn_dsp_isp]step3:disable wdt,clear cache enable"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_dsp_isp]disable wdt fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_dsp_isp]clear cache enable fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + /* step4:hold ss51 & dsp */ + dev_dbg(&client->dev, "[burn_dsp_isp]step4:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_err(&client->dev, "[burn_dsp_isp]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + /* step5:set boot from sram */ + dev_dbg(&client->dev, "[burn_dsp_isp]step5:set boot from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); + if (ret <= 0) { + dev_err(&client->dev, "[burn_dsp_isp]set boot from sram fail"); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + /* step6:software reboot */ + dev_dbg(&client->dev, "[burn_dsp_isp]step6:software reboot"); + ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); + if (ret <= 0) { + dev_err(&client->dev, "[burn_dsp_isp]software reboot fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + /* step7:select bank2 */ + dev_dbg(&client->dev, "[burn_dsp_isp]step7:select bank2"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02); + if (ret <= 0) { + dev_err(&client->dev, "[burn_dsp_isp]select bank2 fail"); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + /* step8:enable accessing code */ + dev_dbg(&client->dev, "[burn_dsp_isp]step8:enable accessing code"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_dsp_isp]enable accessing code fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + + /* step9:burn 4k dsp_isp */ + dev_dbg(&client->dev, "[burn_dsp_isp]step9:burn 4k dsp_isp"); + ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, "[burn_dsp_isp]burn dsp_isp fail."); + goto exit_burn_dsp_isp; + } + + /* step10:set scramble */ + dev_dbg(&client->dev, "[burn_dsp_isp]step10:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_dsp_isp]set scramble fail."); + ret = FAIL; + goto exit_burn_dsp_isp; + } + update_msg.fw_burned_len += FW_DSP_ISP_LENGTH; + dev_dbg(&client->dev, "[burn_dsp_isp]Burned length:%d", + update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_dsp_isp: + kfree(fw_dsp_isp); + + return ret; +} + +static u8 gup_burn_fw_ss51(struct i2c_client *client) +{ + u8 *fw_ss51 = NULL; + u8 retry = 0; + s32 ret = 0; + + dev_info(&client->dev, "[burn_fw_ss51]Begin burn ss51 firmware---->>"); + + /* step1:alloc memory */ + dev_dbg(&client->dev, "[burn_fw_ss51]step1:alloc memory"); + while (retry++ < 5) { + fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_ss51 == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_ss51]Alloc %dk byte memory success.", + (FW_SECTION_LENGTH / 1024)); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, "[burn_fw_ss51]Alloc memory fail,exit."); + return FAIL; + } + + dev_info(&client->dev, "[burn_fw_ss51]Reset first 8K of ss51 to 0xFF."); + dev_dbg(&client->dev, "[burn_fw_ss51]step2: reset bank0 0xC000~0xD000"); + memset(fw_ss51, 0xFF, FW_SECTION_LENGTH); + + /* step3:clear control flag */ + dev_dbg(&client->dev, "[burn_fw_ss51]step3:clear control flag"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_ss51]clear control flag fail."); + ret = FAIL; + goto exit_burn_fw_ss51; + } + + /* step4:burn ss51 firmware section 1 */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step4:burn ss51 firmware section 1"); + ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]burn ss51 firmware section 1 fail."); + goto exit_burn_fw_ss51; + } + + /* step5:load ss51 firmware section 2 file data */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step5:load ss51 firmware section 2 file data"); + ret = gup_load_section_file(fw_ss51, + FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]load ss51 firmware section 2 fail."); + goto exit_burn_fw_ss51; + } + + /* step6:burn ss51 firmware section 2 */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step6:burn ss51 firmware section 2"); + ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]burn ss51 firmware section 2 fail."); + goto exit_burn_fw_ss51; + } + + /* step7:load ss51 firmware section 3 file data */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step7:load ss51 firmware section 3 file data"); + ret = gup_load_section_file(fw_ss51, + 2 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]load ss51 firmware section 3 fail."); + goto exit_burn_fw_ss51; + } + + /* step8:burn ss51 firmware section 3 */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step8:burn ss51 firmware section 3"); + ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]burn ss51 firmware section 3 fail."); + goto exit_burn_fw_ss51; + } + + /* step9:load ss51 firmware section 4 file data */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step9:load ss51 firmware section 4 file data"); + ret = gup_load_section_file(fw_ss51, + 3 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]load ss51 firmware section 4 fail."); + goto exit_burn_fw_ss51; + } + + /* step10:burn ss51 firmware section 4 */ + dev_dbg(&client->dev, + "[burn_fw_ss51]step10:burn ss51 firmware section 4"); + ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_ss51]burn ss51 firmware section 4 fail."); + goto exit_burn_fw_ss51; + } + + update_msg.fw_burned_len += (FW_SECTION_LENGTH*4); + dev_dbg(&client->dev, "[burn_fw_ss51]Burned length:%d", + update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_ss51: + kfree(fw_ss51); + return ret; +} + +static u8 gup_burn_fw_dsp(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_dsp = NULL; + u8 retry = 0; + u8 rd_buf[5]; + + dev_info(&client->dev, "[burn_fw_dsp]Begin burn dsp firmware---->>"); + /* step1:alloc memory */ + dev_dbg(&client->dev, "[burn_fw_dsp]step1:alloc memory"); + while (retry++ < 5) { + fw_dsp = kzalloc(FW_DSP_LENGTH, GFP_KERNEL); + if (fw_dsp == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_dsp]Alloc %dk byte memory success.", + FW_SECTION_LENGTH / 1024); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, "[burn_fw_dsp]Alloc memory fail,exit."); + return FAIL; + } + + /* step2:load firmware dsp */ + dev_dbg(&client->dev, "[burn_fw_dsp]step2:load firmware dsp"); + ret = gup_load_section_file(fw_dsp, + 4 * FW_SECTION_LENGTH, FW_DSP_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, "[burn_fw_dsp]load firmware dsp fail."); + goto exit_burn_fw_dsp; + } + + /* step3:select bank3 */ + dev_dbg(&client->dev, "[burn_fw_dsp]step3:select bank3"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_dsp]select bank3 fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + /* step4:hold ss51 & dsp */ + dev_dbg(&client->dev, "[burn_fw_dsp]step4:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_dsp]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + /* step5:set scramble */ + dev_dbg(&client->dev, "[burn_fw_dsp]step5:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_dsp]set scramble fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + + /* step6:release ss51 & dsp */ + dev_dbg(&client->dev, "[burn_fw_dsp]step6:release ss51 & dsp"); + ret = gup_set_ic_msg( + client, _rRW_MISCTL__SWRST_B0_, 0x04);/* 20121211 */ + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_dsp]release ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_dsp; + } + /* must delay */ + usleep_range(10000, 11000); + + /* step7:burn 4k dsp firmware */ + dev_dbg(&client->dev, "[burn_fw_dsp]step7:burn 4k dsp firmware"); + ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, "[burn_fw_dsp]burn fw_section fail."); + goto exit_burn_fw_dsp; + } + + /* step8:send burn cmd to move data to flash from sram */ + dev_dbg(&client->dev, + "[burn_fw_dsp]step8:send burn cmd to move data to flash from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_dsp]send burn cmd fail."); + goto exit_burn_fw_dsp; + } + dev_dbg(&client->dev, "[burn_fw_dsp]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_dsp]Get burn state fail"); + goto exit_burn_fw_dsp; + } + usleep_range(10000, 11000); + /* dev_dbg(&client->dev, "[burn_fw_dsp]Get burn state:%d.", + rd_buf[GTP_ADDR_LENGTH]); */ + } while (rd_buf[GTP_ADDR_LENGTH]); + + /* step9:recall check 4k dsp firmware */ + dev_dbg(&client->dev, + "[burn_fw_dsp]step9:recall check 4k dsp firmware"); + ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_dsp]recall check 4k dsp firmware fail."); + goto exit_burn_fw_dsp; + } + + update_msg.fw_burned_len += FW_DSP_LENGTH; + dev_dbg(&client->dev, "[burn_fw_dsp]Burned length:%d", + update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_dsp: + kfree(fw_dsp); + + return ret; +} + +static u8 gup_burn_fw_boot(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_boot = NULL; + u8 retry = 0; + u8 rd_buf[5]; + + dev_info(&client->dev, + "[burn_fw_boot]Begin burn bootloader firmware---->>"); + + /* step1:Alloc memory */ + dev_dbg(&client->dev, "[burn_fw_boot]step1:Alloc memory"); + while (retry++ < 5) { + fw_boot = kzalloc(FW_BOOT_LENGTH, GFP_KERNEL); + if (fw_boot == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_boot]Alloc %dk byte memory success.", + FW_BOOT_LENGTH / 1024); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, "[burn_fw_boot]Alloc memory fail,exit."); + return FAIL; + } + + /* step2:load firmware bootloader */ + dev_dbg(&client->dev, "[burn_fw_boot]step2:load firmware bootloader"); + ret = gup_load_section_file(fw_boot, + (4 * FW_SECTION_LENGTH + FW_DSP_LENGTH), FW_BOOT_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_boot]load firmware bootcode fail."); + goto exit_burn_fw_boot; + } + + /* step3:hold ss51 & dsp */ + dev_dbg(&client->dev, "[burn_fw_boot]step3:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot]hold ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + /* step4:set scramble */ + dev_dbg(&client->dev, "[burn_fw_boot]step4:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot]set scramble fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + /* step5:hold ss51 & release dsp */ + dev_dbg(&client->dev, "[burn_fw_boot]step5:hold ss51 & release dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + /* 20121211 */ + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot]release ss51 & dsp fail"); + ret = FAIL; + goto exit_burn_fw_boot; + } + /* must delay */ + usleep_range(10000, 11000); + + /* step6:select bank3 */ + dev_dbg(&client->dev, "[burn_fw_boot]step6:select bank3"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot]select bank3 fail."); + ret = FAIL; + goto exit_burn_fw_boot; + } + + /* step6:burn 2k bootloader firmware */ + dev_dbg(&client->dev, + "[burn_fw_boot]step6:burn 2k bootloader firmware"); + ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, "[burn_fw_boot]burn fw_boot fail."); + goto exit_burn_fw_boot; + } + + /* step7:send burn cmd to move data to flash from sram */ + dev_dbg(&client->dev, + "[burn_fw_boot]step7:send burn cmd to move data to flash from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot]send burn cmd fail."); + goto exit_burn_fw_boot; + } + dev_dbg(&client->dev, + "[burn_fw_boot]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_boot]Get burn state fail"); + goto exit_burn_fw_boot; + } + usleep_range(10000, 11000); + /* dev_dbg(&client->dev, "[burn_fw_boot]Get burn state:%d.", + * rd_buf[GTP_ADDR_LENGTH]); + */ + } while (rd_buf[GTP_ADDR_LENGTH]); + + /* step8:recall check 2k bootloader firmware */ + dev_dbg(&client->dev, + "[burn_fw_boot]step8:recall check 2k bootloader firmware"); + ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_boot]recall check 2k bootcode firmware fail"); + goto exit_burn_fw_boot; + } + + update_msg.fw_burned_len += FW_BOOT_LENGTH; + dev_dbg(&client->dev, "[burn_fw_boot]Burned length:%d", + update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_boot: + kfree(fw_boot); + + return ret; +} +static u8 gup_burn_fw_boot_isp(struct i2c_client *client) +{ + s32 ret = 0; + u8 *fw_boot_isp = NULL; + u8 retry = 0; + u8 rd_buf[5]; + + if (update_msg.fw_burned_len >= update_msg.fw_total_len) { + dev_dbg(&client->dev, "No need to upgrade the boot_isp code!"); + return SUCCESS; + } + dev_info(&client->dev, + "[burn_fw_boot_isp]Begin burn boot_isp firmware---->>"); + + /* step1:Alloc memory */ + dev_dbg(&client->dev, "[burn_fw_boot_isp]step1:Alloc memory"); + while (retry++ < 5) { + fw_boot_isp = kzalloc(FW_BOOT_ISP_LENGTH, GFP_KERNEL); + if (fw_boot_isp == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_boot_isp]Alloc %dk byte memory success.", + (FW_BOOT_ISP_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, + "[burn_fw_boot_isp]Alloc memory fail,exit."); + return FAIL; + } + + /* step2:load firmware bootloader */ + dev_dbg(&client->dev, + "[burn_fw_boot_isp]step2:load firmware bootloader isp"); + /* ret = gup_load_section_file(fw_boot_isp, + * (4*FW_SECTION_LENGTH+FW_DSP_LENGTH + + * FW_BOOT_LENGTH+FW_DSP_ISP_LENGTH), FW_BOOT_ISP_LENGTH, SEEK_SET); + */ + ret = gup_load_section_file(fw_boot_isp, + (update_msg.fw_burned_len - FW_DSP_ISP_LENGTH), + FW_BOOT_ISP_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_boot_isp]load firmware boot_isp fail."); + goto exit_burn_fw_boot_isp; + } + + /* step3:hold ss51 & dsp */ + dev_dbg(&client->dev, "[burn_fw_boot_isp]step3:hold ss51 & dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot_isp]hold ss51 & dsp fail"); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + /* step4:set scramble */ + dev_dbg(&client->dev, "[burn_fw_boot_isp]step4:set scramble"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot_isp]set scramble fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + + /* step5:hold ss51 & release dsp */ + dev_dbg(&client->dev, + "[burn_fw_boot_isp]step5:hold ss51 & release dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + /* 20121211 */ + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_boot_isp]release ss51 & dsp fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + /* must delay */ + usleep_range(10000, 20000); + + /* step6:select bank3 */ + dev_dbg(&client->dev, "[burn_fw_boot_isp]step6:select bank3"); + ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot_isp]select bank3 fail."); + ret = FAIL; + goto exit_burn_fw_boot_isp; + } + + /* step7:burn 2k bootload_isp firmware */ + dev_dbg(&client->dev, + "[burn_fw_boot_isp]step7:burn 2k bootloader firmware"); + ret = gup_burn_proc(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_boot_isp]burn fw_section fail."); + goto exit_burn_fw_boot_isp; + } + + /* step7:send burn cmd to move data to flash from sram */ + dev_dbg(&client->dev, + "[burn_fw_boot_isp]step8:send burn cmd to move data to flash from sram"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x07); + if (ret <= 0) { + dev_err(&client->dev, "[burn_fw_boot_isp]send burn cmd fail."); + goto exit_burn_fw_boot_isp; + } + dev_dbg(&client->dev, + "[burn_fw_boot_isp]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_boot_isp]Get burn state fail"); + goto exit_burn_fw_boot_isp; + } + usleep_range(10000, 11000); + /* dev_dbg(&client->dev, "[burn_fw_boot_isp]Get + * burn state:%d.", rd_buf[GTP_ADDR_LENGTH]); + */ + } while (rd_buf[GTP_ADDR_LENGTH]); + + /* step8:recall check 2k bootload_isp firmware */ + dev_dbg(&client->dev, + "[burn_fw_boot_isp]step9:recall check 2k bootloader firmware"); + ret = gup_recall_check(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_boot_isp]recall check 2k bootcode_isp firmware fail."); + goto exit_burn_fw_boot_isp; + } + + update_msg.fw_burned_len += FW_BOOT_ISP_LENGTH; + dev_dbg(&client->dev, + "[burn_fw_boot_isp]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_boot_isp: + kfree(fw_boot_isp); + + return ret; +} + +static u8 gup_burn_fw_link(struct i2c_client *client) +{ + u8 *fw_link = NULL; + u8 retry = 0; + s32 ret = 0; + u32 offset; + + if (update_msg.fw_burned_len >= update_msg.fw_total_len) { + dev_dbg(&client->dev, "No need to upgrade the link code!"); + return SUCCESS; + } + dev_info(&client->dev, "[burn_fw_link]Begin burn link firmware---->>"); + + /* step1:Alloc memory */ + dev_dbg(&client->dev, "[burn_fw_link]step1:Alloc memory"); + while (retry++ < 5) { + fw_link = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_link == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_link]Alloc %dk byte memory success.", + (FW_SECTION_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, "[burn_fw_link]Alloc memory fail,exit."); + return FAIL; + } + + /* step2:load firmware link section 1 */ + dev_dbg(&client->dev, + "[burn_fw_link]step2:load firmware link section 1"); + offset = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH; + ret = gup_load_section_file( + fw_link, offset, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_link]load firmware link section 1 fail."); + goto exit_burn_fw_link; + } + + /* step3:burn link firmware section 1 */ + dev_dbg(&client->dev, + "[burn_fw_link]step3:burn link firmware section 1"); + ret = gup_burn_fw_gwake_section( + client, fw_link, 0x9000, FW_SECTION_LENGTH, 0x38); + + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_link]burn link firmware section 1 fail."); + goto exit_burn_fw_link; + } + + /* step4:load link firmware section 2 file data */ + dev_dbg(&client->dev, + "[burn_fw_link]step4:load link firmware section 2 file data"); + offset += FW_SECTION_LENGTH; + ret = gup_load_section_file( + fw_link, offset, FW_GLINK_LENGTH - FW_SECTION_LENGTH, SEEK_SET); + + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_link]load link firmware section 2 fail."); + goto exit_burn_fw_link; + } + + /* step5:burn link firmware section 2 */ + dev_dbg(&client->dev, + "[burn_fw_link]step4:burn link firmware section 2"); + ret = gup_burn_fw_gwake_section(client, + fw_link, 0x9000, FW_GLINK_LENGTH - FW_SECTION_LENGTH, 0x39); + + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_link]burn link firmware section 2 fail."); + goto exit_burn_fw_link; + } + + update_msg.fw_burned_len += FW_GLINK_LENGTH; + dev_dbg(&client->dev, + "[burn_fw_link]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_link: + kfree(fw_link); + + return ret; +} + +static u8 gup_burn_fw_gwake_section(struct i2c_client *client, + u8 *fw_section, u16 start_addr, u32 len, u8 bank_cmd) +{ + s32 ret = 0; + u8 rd_buf[5]; + + /* step1:hold ss51 & dsp */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_app_section]hold ss51 & dsp fail."); + return FAIL; + } + + /* step2:set scramble */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_app_section]set scramble fail."); + return FAIL; + } + + /* step3:hold ss51 & release dsp */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_app_section]hold ss51 & release dsp fail."); + return FAIL; + } + /* must delay */ + usleep_range(10000, 20000); + + /* step4:select bank */ + ret = gup_set_ic_msg( + client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_section]select bank %d fail.", + (bank_cmd >> 4)&0x0F); + return FAIL; + } + + /* step5:burn fw section */ + ret = gup_burn_proc(client, fw_section, start_addr, len); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_app_section]burn fw_section fail."); + return FAIL; + } + + /* step6:send burn cmd to move data to flash from sram */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0F); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_app_section]send burn cmd fail."); + return FAIL; + } + dev_dbg(&client->dev, + "[burn_fw_section]Wait for the burn is complete......"); + do { + ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_app_section]Get burn state fail"); + return FAIL; + } + usleep_range(10000, 11000); + /* dev_dbg(&client->dev, "[burn_fw_app_section]Get burn state:%d." + * rd_buf[GTP_ADDR_LENGTH]); + */ + } while (rd_buf[GTP_ADDR_LENGTH]); + + /* step7:recall fw section */ + ret = gup_recall_check(client, fw_section, start_addr, len); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_app_section]recall check %dk firmware fail.", + len/1024); + return FAIL; + } + + return SUCCESS; +} + +static u8 gup_burn_fw_gwake(struct i2c_client *client) +{ + u8 *fw_gwake = NULL; + u8 retry = 0; + s32 ret = 0; + u16 start_index = 4*FW_SECTION_LENGTH + + FW_DSP_LENGTH + FW_BOOT_LENGTH + + FW_BOOT_ISP_LENGTH + FW_GLINK_LENGTH;/* 32 + 4 + 2 + 4 = 42K */ + /* u16 start_index; */ + + if (start_index >= update_msg.fw_total_len) { + dev_dbg(&client->dev, "No need to upgrade the gwake code!"); + return SUCCESS; + } + /* start_index = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH; */ + dev_info(&client->dev, + "[burn_fw_gwake]Begin burn gwake firmware---->>"); + + /* step1:alloc memory */ + dev_dbg(&client->dev, "[burn_fw_gwake]step1:alloc memory"); + while (retry++ < 5) { + fw_gwake = + kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_gwake == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_gwake]Alloc %dk byte memory success.", + (FW_SECTION_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, "[burn_fw_gwake]Alloc memory fail,exit."); + return FAIL; + } + + /* clear control flag */ + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_finish]clear control flag fail."); + goto exit_burn_fw_gwake; + } + + /* step2:load app_code firmware section 1 file data */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step2:load app_code firmware section 1 file data"); + ret = gup_load_section_file(fw_gwake, + start_index, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]load app_code firmware section 1 fail."); + goto exit_burn_fw_gwake; + } + + /* step3:burn app_code firmware section 1 */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step3:burn app_code firmware section 1"); + ret = gup_burn_fw_gwake_section(client, + fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3A); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]burn app_code firmware section 1 fail."); + goto exit_burn_fw_gwake; + } + + /* step5:load app_code firmware section 2 file data */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step5:load app_code firmware section 2 file data"); + ret = gup_load_section_file( + fw_gwake, start_index+FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]load app_code firmware section 2 fail."); + goto exit_burn_fw_gwake; + } + + /* step6:burn app_code firmware section 2 */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step6:burn app_code firmware section 2"); + ret = gup_burn_fw_gwake_section(client, + fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3B); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]burn app_code firmware section 2 fail."); + goto exit_burn_fw_gwake; + } + + /* step7:load app_code firmware section 3 file data */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step7:load app_code firmware section 3 file data"); + ret = gup_load_section_file( + fw_gwake, start_index + 2*FW_SECTION_LENGTH, + FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]load app_code firmware section 3 fail."); + goto exit_burn_fw_gwake; + } + + /* step8:burn app_code firmware section 3 */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step8:burn app_code firmware section 3"); + ret = gup_burn_fw_gwake_section( + client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3C); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]burn app_code firmware section 3 fail."); + goto exit_burn_fw_gwake; + } + + /* step9:load app_code firmware section 4 file data */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step9:load app_code firmware section 4 file data"); + ret = gup_load_section_file(fw_gwake, + start_index + 3*FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]load app_code firmware section 4 fail."); + goto exit_burn_fw_gwake; + } + + /* step10:burn app_code firmware section 4 */ + dev_dbg(&client->dev, + "[burn_fw_gwake]step10:burn app_code firmware section 4"); + ret = gup_burn_fw_gwake_section( + client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3D); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_gwake]burn app_code firmware section 4 fail."); + goto exit_burn_fw_gwake; + } + + /* update_msg.fw_burned_len += FW_GWAKE_LENGTH; */ + dev_dbg(&client->dev, + "[burn_fw_gwake]Burned length:%d", update_msg.fw_burned_len); + ret = SUCCESS; + +exit_burn_fw_gwake: + kfree(fw_gwake); + + return ret; +} + +static u8 gup_burn_fw_finish(struct i2c_client *client) +{ + u8 *fw_ss51 = NULL; + u8 retry = 0; + s32 ret = 0; + + dev_info(&client->dev, + "[burn_fw_finish]burn first 8K of ss51 and finish update."); + /* step1:alloc memory */ + dev_dbg(&client->dev, "[burn_fw_finish]step1:alloc memory"); + while (retry++ < 5) { + fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL); + if (fw_ss51 == NULL) { + continue; + } else { + dev_dbg(&client->dev, + "[burn_fw_finish]Alloc %dk byte memory success.", + (FW_SECTION_LENGTH/1024)); + break; + } + } + if (retry >= 5) { + dev_err(&client->dev, + "[burn_fw_finish]Alloc memory fail,exit."); + return FAIL; + } + + dev_dbg(&client->dev, "[burn_fw_finish]step2: burn ss51 first 8K."); + ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH, SEEK_SET); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_finish]load ss51 firmware section 1 fail."); + goto exit_burn_fw_finish; + } + + dev_dbg(&client->dev, "[burn_fw_finish]step3:clear control flag"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_finish]clear control flag fail."); + goto exit_burn_fw_finish; + } + + dev_dbg(&client->dev, + "[burn_fw_finish]step4:burn ss51 firmware section 1"); + ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); + if (FAIL == ret) { + dev_err(&client->dev, + "[burn_fw_finish]burn ss51 firmware section 1 fail."); + goto exit_burn_fw_finish; + } + + /* step11:enable download DSP code */ + dev_dbg(&client->dev, + "[burn_fw_finish]step5:enable download DSP code "); + ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_finish]enable download DSP code fail."); + goto exit_burn_fw_finish; + } + + /* step12:release ss51 & hold dsp */ + dev_dbg(&client->dev, "[burn_fw_finish]step6:release ss51 & hold dsp"); + ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08); + if (ret <= 0) { + dev_err(&client->dev, + "[burn_fw_finish]release ss51 & hold dsp fail."); + goto exit_burn_fw_finish; + } + + if (fw_ss51 != NULL) + kfree(fw_ss51); + return SUCCESS; + +exit_burn_fw_finish: + if (fw_ss51 != NULL) + kfree(fw_ss51); + + return FAIL; +} + +/* return 0 can update, else no update condition */ +static int gup_update_condition_check(struct goodix_ts_data *ts) +{ + if (test_bit(SLEEP_MODE, &ts->flags)) { + dev_info(&ts->client->dev, "Update abort, tp in sleep mode\n"); + return -EINVAL; + } + + return 0; +} +s32 gup_update_proc(void *dir) +{ + s32 ret = 0; + s32 update_ret = FAIL; + u8 retry = 0; + struct st_fw_head fw_head; + struct goodix_ts_data *ts = NULL; + + ts = i2c_get_clientdata(i2c_connect_client); + + printk("Enter %s --- Line : %d\n", __func__, __LINE__); + + dev_dbg(&ts->client->dev, "[update_proc]Begin update ......\n"); + + show_len = 1; + total_len = 100; + + ret = gup_update_condition_check(ts); + if (ret) { + dev_warn(&ts->client->dev, "Update start failed\n"); + return FAIL; + } + + if (test_and_set_bit(FW_UPDATE_RUNNING, &ts->flags)) { + dev_warn(&ts->client->dev, "FW update may already running\n"); + return FAIL; + } + + ret = gup_get_update_file(i2c_connect_client, &fw_head, (u8 *)dir); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "Failed get valied firmware data\n"); + clear_bit(FW_UPDATE_RUNNING, &ts->flags); + return FAIL; + } + + gtp_work_control_enable(ts, false); + gtp_esd_off(ts); +#if GTP_CHARGER_SWITCH + gtp_charger_off(ts); +#endif + + ret = gup_get_ic_fw_msg(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, "[update_proc]get ic message fail."); + goto file_fail; + } + + if (ts->force_update || dir) { + dev_dbg(&ts->client->dev, "Enter force update."); + } else { + ret = gup_enter_update_judge(i2c_connect_client, &fw_head); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]Doesn't meet update condition\n"); + goto file_fail; + } + } + + ret = gup_enter_update_mode(ts->client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]enter update mode fail."); + goto update_fail; + } + + while (retry++ < 5) { + show_len = 10; + total_len = 100; + update_msg.fw_burned_len = 0; + ret = gup_burn_dsp_isp(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn dsp isp fail."); + continue; + } + + show_len = 20; + ret = gup_burn_fw_gwake(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn app_code firmware fail."); + continue; + } + + show_len = 30; + ret = gup_burn_fw_ss51(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn ss51 firmware fail."); + continue; + } + + show_len = 40; + ret = gup_burn_fw_dsp(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn dsp firmware fail."); + continue; + } + + show_len = 50; + ret = gup_burn_fw_boot(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn bootloader firmware fail."); + continue; + } + show_len = 60; + + ret = gup_burn_fw_boot_isp(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn boot_isp firmware fail."); + continue; + } + + show_len = 70; + ret = gup_burn_fw_link(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn link firmware fail."); + continue; + } + + show_len = 80; + ret = gup_burn_fw_finish(i2c_connect_client); + if (FAIL == ret) { + dev_err(&ts->client->dev, + "[update_proc]burn finish fail."); + continue; + } + show_len = 90; + dev_info(&ts->client->dev, "[update_proc]UPDATE SUCCESS."); + retry = 0; + break; + } + + if (retry >= 5) { + dev_err(&ts->client->dev, + "[update_proc]retry timeout,UPDATE FAIL."); + update_ret = FAIL; + } else { + update_ret = SUCCESS; + } + +update_fail: + dev_dbg(&ts->client->dev, "[update_proc]leave update mode."); + gup_leave_update_mode(i2c_connect_client); + + msleep(GTP_100_DLY_MS); + + if (SUCCESS == update_ret) { + dev_info(&ts->client->dev, + "firmware error auto update, resent config!\n"); + gup_init_panel(ts); + } + gtp_get_fw_info(ts->client, &ts->fw_info); + +file_fail: + + update_msg.fw_data = NULL; + update_msg.fw_total_len = 0; + release_firmware(update_msg.fw); + + clear_bit(FW_UPDATE_RUNNING, &ts->flags); + gtp_work_control_enable(ts, true); + gtp_esd_on(ts); + gtp_charger_on(ts); + total_len = 100; + ts->force_update = false; + + /*Add by HQ-zmc [Date: 2018-03-14 18:01:19] + show FW & CFG info after upgrade + */ + ctp_vendor_info(ts->client, &ts->fw_info); + + if (SUCCESS == update_ret) { + show_len = 100; + clear_bit(FW_ERROR, &ts->flags); + return SUCCESS; + } else { + show_len = 200; + return FAIL; + } +} + +u8 gup_init_update_proc(struct goodix_ts_data *ts) +{ + struct task_struct *thread = NULL; + + dev_info(&ts->client->dev, "Ready to run update thread."); + + thread = kthread_run(gup_update_proc, + (void *)NULL, "guitar_update"); + + if (IS_ERR(thread)) { + dev_err(&ts->client->dev, + "Failed to create update thread.\n"); + return -EPERM; + } + + return 0; +} diff --git a/drivers/input/touchscreen/gt917d/ito_cfg/test_sensor_0_20180118.ini b/drivers/input/touchscreen/gt917d/ito_cfg/test_sensor_0_20180118.ini new file mode 100644 index 0000000000000..107f3e8084182 --- /dev/null +++ b/drivers/input/touchscreen/gt917d/ito_cfg/test_sensor_0_20180118.ini @@ -0,0 +1,486 @@ +[Device] +DeviceMode =0 +DeviceType =53 +SampleBoard=2 +MainBoard=1 +AVDD=2.800000 +EVDD=2.800000 +VDDIO=1.800000 +IcName=GT917D + +[System] +Language =0 +User=33 +crc=0xd87cf881 + +[Test Parameter] +module_cfg=0x00,0x38,0x04,0xE8,0x08,0x0A,0x0C,0x00,0x01,0x08,0x28,0x0D,0x5A,0x41,0x03,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x14,0x87,0x27,0xEE,0x4B,0x4D,0x31,0x0D,0x31,0x0D,0x00,0x02,0x03,0x11,0x0A,0x00,0x00,0x00,0x00,0x03,0x00,0x32,0x00,0x00,0x00,0x1E,0x5A,0x94,0x00,0x03,0x05,0x1E,0x00,0x04,0xCA,0x21,0x00,0xAB,0x29,0x00,0x91,0x34,0x00,0x7E,0x41,0x00,0x71,0x51,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x17,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x18,0x19,0x1A,0x1B,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0x08,0x06,0x05,0x04,0x0A,0x0C,0x0E,0x1E,0x1F,0x20,0x22,0x24,0x29,0x2A,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x01 + +max_limit_value=6128 +min_limit_value=2981 +permit_jitter_limit=96 +accord_limit=0.400000 +offset_limit=0.162706 +special_limit=0.458947 +max_linearity_limit=0.500000 +driver_short_circuit_limit=1.400000 +driver_short_circuit_limit2=1.250000 +sensor_short_circuit_limit=0.500000 +max_key_limit_value=1508 +min_key_limit_value=968 +mst_pass_percent=0.550000 +mst_short_percent=0.850000 +version_equ=917D_501C +version_greater=917D_501C +version_between1=917D_501C +version_between2=917D_501C +max_current_limit=18.000000 +module_type=0 +fpc_open_threshold=60 +accord_or_offset=0 +fixed_cfg_module_id=0x31,0x31,0x41,0x41 +TestChkCfg=0 +#diff_test_min=80 +#diff_test_timeout=26 +max_shdn_current=0 +i2c_voltage_ratio=0.000000 +#rawdata_uniformity=0.87 +min_stylus_drv_limit_value=110 +min_stylus_sen_limit_value=120 + +gt900_short_threshold=10 +gt900_resistor_threshold=150 +gt900_resistor_warn_threshold=800 +gt900_gnd_resistor_threshold=100 +gt900_c_resistor_threshold=50 +gt900_drv_drv_resistor_threshold=150 +gt900_drv_sen_resistor_threshold=150 +gt900_sen_sen_resistor_threshold=150 +gt900_drv_gnd_resistor_threshold=100 +gt900_sen_gnd_resistor_threshold=100 +gt900_adc_offset_front=200 +gt900_adc_offset_middle=1000 +gt900_adc_R1_R2=1.200000 +gt900_short_test_times=1 + +tri_pattern_r_ratio=1.500000 +tri_pattern_r_ratio_left_right =1.040000 +tri_pattern_r_ratio_up_down =1.130000 +tri_pattern_r_ratio_middle =1.400000 + +resistanceChannel=D30,D5,198,161,2.07,1.28,D0,D5,105,86,1.13,1.28,D1,D5,107,88,1.13,1.28,D2,D6,107,87,1.13,1.28,D3,D6,105,85,1.13,1.28,D4,D6,196,161,2.07,1.28,D9,D7,199,161,2.07,1.28,D10,D7,105,86,1.13,1.28,D11,D7,107,87,1.13,1.28,D12,D8,106,86,1.13,1.28,D13,D8,105,85,1.13,1.28,D14,D8,195,159,2.07,1.28,D5,D6,9,8,1.13,1.28,D7,D8,8,7,1.13,1.28, +GT950SenserTest =0 +TestShowRadioMax =0 +GT950MiddleBreak =0 +TestSaveCoor =0 + +accord_col=0 +NoTestKey= + +#LinePos=200,500,0,0,0,0 +#LineDelta=200 +#LineRetryCnt=5 + +LineNumber=6 +LineTestOK=0 +LineTestNG=1 +DisplayTestMsg=0 +LimitType=1 + +Size_X=40.549999 +Size_Y=80.559998 +Size_DeltaLimit=2.000000 +Size_LineDeltaV=1.000000 +Size_DeltaWidthV=7.000000 +Size_LineDiscard=0.000000 +Size_LineQuickLimit=1.000000 + +DeltaLimit=30 +LineDeltaV=10 +DeltaWidthV=60 +LineDiscard=0 +LineQuickLimit=10 + +line_check_type=0 +line_check_margin=240 +line_check_fourBorder_time=120 +line_check_fourBorder_checkType=2 +line_check_fourPoint_time=120 +line_check_fourPoint_radius=100 +line_check_fourPoint_distance=0 +line_check_diagonal_time=90 +line_check_diagonal_checkType=0 +line_check_diagonal_distance=22 +line_check_fourBorder_fingerNum=2 +line_check_fourBorder_two_finger_time=90 +line_check_fourBorder_two_finger_margin=90 +line_check_dis_to_border=0 +line_check_fourBorder_time_two_finger=90 +line_check_fourBorder_dis_to_border_two_finger=20 +line_check_fourBorder_finger_move_two_finger=35 +line_check_fourBorder_finger_interval_two_finger=10 + +gt900_check_cfg=0 +jitter_check_data=1 +rawdata_uniformity=0.000000 +jitter_check_diff=0 +diff_test_min=0 +diff_test_timeout=0 +LineMode=0 +Size_LinePos= +Size_LineDistanceMinLimit=0.000000 +Size_HalfTPLineDistanceMinLimit=0.000000 +Sample_LineMode=0 +Sample_LinePos= +Sample_LineNumber=0 +Sample_X=0.000000 +Sample_Y=0.000000 +Sample_DeltaLimit=0.000000 +Sample_LineDeltaV=0.000000 +Sample_DeltaWidthV=0.000000 +Sample_LineDiscard=0.000000 +Sample_LineQuickLimit=0.000000 +Sample_LineDistanceMinLimit=0.000000 +Sample_HalfTPLineDistanceMinLimit=0.000000 +tri_pattern_r_ratio_retest=0.000000 +gt900_short_retest_times=0 +INT_Cap_Test=1 +INT_Adc_T1=2 +INT_Adc_T2=18 +INT_Radio_Threshold_18V=2.400000 +INT_Radio_Threshold_33V=3.000000 +INT_Radio_Threshold_Range=0.250000 +rst_voltage_ratio=0.000000 +key_wait_time=0 +GestureTest=1 +bAllChnShortTest=0 +press_data_num=0 +press_data_col=0 +press_max_limit_value=0 +press_min_limit_value=0 +press_accord_limit=0.000000 +press_special_node= +press_need_check=0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xec,0xf0,0x00 +IntCntTest=0x1 +FlashTest=1 +TestFirmware=0 +press_mutual_max_limit_value=0 +press_mutual_min_limit_value=0 +press_mutual_accord_limit=0.000000 +press_mutual_special_node= +press_mutual_need_check=0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +press_d_test=0 +rawdata_cnt=16 +km_data_addr=16384 +d_data_addr=16640 +d_threshold_lower_limit=150 +d_threshold_upper_limit=600 +WriteLog2Chip=0 +permit_jitter_warning_limit=96 +i2c_gnd_voltage_sw=1 +i2c_vddio_voltage_sw=1 +rst_voltage_sw=1 +int_voltage_sw=1 +int_gnd_voltage_ratio=0.697000 +int_vddio_voltage_ratio=0.500000 +SendSpecCfgAfterTest=0 + + + + +[FW Para] +MultiWrite=2 +IC_Keyword0=0x31,°×É« +IC_Keyword1=0x37 +IC_Keyword2=0x31 +IC_Keyword3=0x01 +IC_Keyword4=0xD1 +IC_Keyword5=0x53 +IC_Keyword6=0x31 +IC_Keyword7=0x01 + +[Config] +SendConfig=0 +Debug=0 +MaskFromConfig=1 +SaveCoordinate=0 +SaveCoordinateCnt=100 +test_types =0x690007 +samping_num = 64 +NC=0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +MaxProtectCurrent=0 +CoordAfterTest=0 +Debuger=1 +SepcialTestNode=0,3959,2132,0.576,1,5483,2952,0.429,2,5601,3016,0.300,3,5583,3006,0.300,4,5049,2718,0.815,5,2083,1122,2.471,6,1721,926,3.271,7,1671,900,3.395,8,2044,1101,2.620,9,5006,2695,0.821,10,5727,3084,0.300,11,5831,3140,0.300,12,5779,3112,0.378,13,4475,2410,0.696,14,5547,2986,0.437,15,5730,3085,0.300,16,5764,3103,0.300,17,5782,3113,0.300,18,5904,3179,0.300,19,5938,3197,0.845,20,5953,3205,0.925,21,5930,3193,0.935,22,6055,3260,0.863,23,6135,3303,0.300,24,6202,3339,0.300,25,6382,3436,0.300,26,6471,3484,0.300,27,6607,3558,0.474,28,5472,2946,0.300,29,5623,3028,0.300,30,5658,3047,0.300,31,5675,3056,0.300,32,5821,3134,0.300,33,6039,3252,0.300,34,6112,3291,0.300,35,6090,3279,0.300,36,6159,3316,0.300,37,6054,3259,0.300,38,6090,3279,0.300,39,6275,3378,0.300,40,6363,3426,0.300,41,6533,3518,0.300,42,5476,2949,0.300,43,5670,3053,0.300,44,5704,3071,0.300,45,5716,3077,0.300,46,5844,3147,0.300,47,5960,3209,0.300,48,6026,3245,0.300,49,6002,3231,0.300,50,6076,3271,0.300,51,6069,3268,0.300,52,6120,3295,0.300,53,6303,3394,0.300,54,6388,3439,0.300,55,6516,3509,0.300,56,5476,2949,0.300,57,5634,3033,0.300,58,5667,3051,0.300,59,5683,3060,0.300,60,5827,3138,0.300,61,6035,3250,0.300,62,6106,3287,0.300,63,6083,3275,0.300,64,6151,3312,0.300,65,6054,3259,0.300,66,6087,3278,0.300,67,6271,3376,0.300,68,6356,3422,0.300,69,6518,3509,0.300,70,5471,2946,0.300,71,5665,3050,0.300,72,5695,3066,0.300,73,5708,3073,0.300,74,5833,3140,0.300,75,5939,3198,0.300,76,6003,3232,0.300,77,5978,3219,0.300,78,6051,3258,0.300,79,6047,3256,0.300,80,6095,3282,0.300,81,6276,3379,0.300,82,6358,3423,0.300,83,6479,3488,0.300,84,5485,2953,0.300,85,5649,3042,0.300,86,5680,3058,0.300,87,5695,3066,0.300,88,5833,3140,0.300,89,6026,3245,0.300,90,6095,3282,0.300,91,6070,3268,0.300,92,6137,3304,0.300,93,6048,3257,0.300,94,6081,3274,0.300,95,6260,3371,0.300,96,6342,3415,0.300,97,6492,3495,0.300,98,5480,2951,0.300,99,5677,3056,0.300,100,5706,3072,0.300,101,5718,3079,0.300,102,5836,3142,0.300,103,5933,3194,0.300,104,5994,3227,0.300,105,5966,3212,0.300,106,6037,3250,0.300,107,6039,3252,0.300,108,6087,3278,0.300,109,6262,3371,0.300,110,6338,3413,0.300,111,6454,3475,0.300,112,5509,2966,0.300,113,5675,3056,0.300,114,5705,3072,0.300,115,5718,3079,0.300,116,5851,3150,0.300,117,6028,3245,0.300,118,6094,3281,0.300,119,6069,3268,0.300,120,6133,3302,0.300,121,6054,3259,0.300,122,6085,3276,0.300,123,6259,3370,0.300,124,6336,3411,0.300,125,6476,3487,0.300,126,5500,2961,0.300,127,5699,3068,0.300,128,5726,3083,0.300,129,5736,3089,0.300,130,5849,3149,0.300,131,5934,3195,0.300,132,5990,3225,0.300,133,5965,3212,0.300,134,6031,3247,0.300,135,6037,3250,0.300,136,6081,3274,0.300,137,6251,3366,0.300,138,6323,3404,0.300,139,6431,3462,0.300,140,5535,2980,0.300,141,5706,3072,0.300,142,5732,3086,0.300,143,5744,3093,0.300,144,5870,3161,0.300,145,6033,3248,0.300,146,6094,3281,0.300,147,6069,3268,0.300,148,6130,3301,0.300,149,6057,3261,0.300,150,6086,3277,0.300,151,6255,3368,0.300,152,6328,3407,0.300,153,6463,3480,0.300,154,5531,2978,0.300,155,5732,3086,0.300,156,5755,3098,0.300,157,5764,3103,0.300,158,5870,3161,0.300,159,5943,3200,0.300,160,5995,3228,0.300,161,5969,3214,0.300,162,6033,3248,0.300,163,6039,3252,0.300,164,6080,3273,0.300,165,6246,3363,0.300,166,6311,3398,0.300,167,6415,3454,0.300,168,5592,3011,0.300,169,5768,3105,0.300,170,5790,3117,0.300,171,5800,3123,0.300,172,5918,3187,0.300,173,6064,3265,0.300,174,6120,3295,0.300,175,6096,3282,0.300,176,6155,3314,0.300,177,6086,3277,0.300,178,6112,3291,0.300,179,6275,3378,0.300,180,6341,3414,0.300,181,6476,3487,0.300,182,5396,2905,0.300,183,5589,3009,0.300,184,5606,3019,0.300,185,5617,3024,0.300,186,5710,3075,0.300,187,5779,3112,0.300,188,5826,3137,0.300,189,5801,3124,0.300,190,5861,3156,0.300,191,5860,3155,0.300,192,5895,3174,0.300,193,6048,3257,0.300,194,6109,3289,0.300,195,6256,3369,0.300,196,6093,3280,0.300,197,6022,3243,0.300,198,5933,3194,0.300,199,5844,3147,0.300,200,5853,3152,0.300,201,5857,3154,0.300,202,5810,3128,0.300,203,5690,3063,0.300,204,5658,3047,0.300,205,5552,2989,0.300,206,5485,2953,0.300,207,5537,2981,0.300,208,5492,2957,0.300,209,5323,2866,0.300,210,6310,3397,0.300,211,6282,3383,0.300,212,6194,3335,0.300,213,6111,3290,0.300,214,6108,3289,0.300,215,6076,3271,0.300,216,6037,3250,0.300,217,5914,3184,0.300,218,5882,3167,0.300,219,5812,3129,0.300,220,5765,3104,0.300,221,5812,3129,0.300,222,5766,3105,0.300,223,5580,3005,0.300,224,6336,3411,0.300,225,6301,3392,0.300,226,6211,3344,0.300,227,6128,3299,0.300,228,6134,3303,0.300,229,6164,3319,0.300,230,6126,3299,0.300,231,6005,3233,0.300,232,5970,3215,0.300,233,5836,3142,0.300,234,5779,3112,0.300,235,5823,3135,0.300,236,5775,3110,0.300,237,5604,3017,0.300,238,6368,3429,0.300,239,6360,3425,0.300,240,6273,3378,0.300,241,6190,3333,0.300,242,6189,3332,0.300,243,6151,3312,0.300,244,6111,3290,0.300,245,5992,3226,0.300,246,5960,3209,0.300,247,5896,3175,0.300,248,5848,3149,0.300,249,5892,3173,0.300,250,5843,3146,0.300,251,5645,3040,0.300,252,6354,3421,0.300,253,6341,3414,0.300,254,6259,3370,0.300,255,6165,3320,0.300,256,6190,3333,0.300,257,6206,3341,0.300,258,6172,3323,0.300,259,6055,3260,0.300,260,6020,3241,0.300,261,5903,3178,0.300,262,5826,3137,0.300,263,5891,3172,0.300,264,5840,3145,0.300,265,5660,3047,0.300,266,6379,3434,0.300,267,6395,3443,0.300,268,6314,3399,0.300,269,6221,3350,0.300,270,6238,3359,0.300,271,6197,3336,0.300,272,6159,3316,0.300,273,6042,3253,0.300,274,6013,3238,0.300,275,5957,3208,0.300,276,5894,3173,0.300,277,5956,3207,0.300,278,5905,3180,0.300,279,5700,3069,0.300,280,6458,3477,0.300,281,6468,3483,0.300,282,6389,3440,0.300,283,6317,3401,0.300,284,6325,3406,0.300,285,6333,3410,0.300,286,6299,3392,0.300,287,6187,3331,0.300,288,6158,3315,0.300,289,6054,3259,0.300,290,6000,3231,0.300,291,6043,3254,0.300,292,5992,3226,0.300,293,5799,3122,0.300,294,6472,3485,0.300,295,6509,3504,0.300,296,6432,3463,0.300,297,6364,3427,0.300,298,6363,3426,0.300,299,6319,3402,0.300,300,6282,3383,0.300,301,6176,3325,0.300,302,6148,3310,0.300,303,6099,3284,0.300,304,6056,3261,0.300,305,6098,3283,0.300,306,6048,3257,0.300,307,5833,3140,0.300,308,6532,3517,0.300,309,6568,3537,0.300,310,6494,3497,0.300,311,6432,3463,0.300,312,6436,3465,0.300,313,6437,3466,0.300,314,6403,3448,0.300,315,6302,3393,0.300,316,6275,3378,0.300,317,6184,3329,0.300,318,6135,3303,0.300,319,6176,3325,0.300,320,6124,3297,0.300,321,5917,3186,0.300,322,6568,3537,0.300,323,6628,3569,0.300,324,6555,3530,0.300,325,6497,3498,0.300,326,6494,3497,0.300,327,6450,3473,0.300,328,6415,3454,0.300,329,6319,3402,0.300,330,6295,3390,0.300,331,6252,3366,0.300,332,6215,3346,0.300,333,6254,3367,0.300,334,6202,3339,0.300,335,5976,3217,0.300,336,6645,3578,0.300,337,6705,3610,0.300,338,6636,3573,0.300,339,6577,3541,0.300,340,6585,3546,0.300,341,6576,3541,0.300,342,6546,3525,0.300,343,6455,3476,0.300,344,6432,3463,0.300,345,6358,3423,0.300,346,6311,3398,0.300,347,6354,3421,0.300,348,6303,3394,0.300,349,6082,3275,0.300,350,6681,3597,0.300,351,6765,3642,0.300,352,6698,3607,0.300,353,6644,3577,0.300,354,6646,3579,0.300,355,6602,3555,0.300,356,6571,3538,0.300,357,6485,3492,0.300,358,6467,3482,0.300,359,6431,3462,0.300,360,6392,3441,0.300,361,6434,3464,0.300,362,6382,3436,0.300,363,6146,3309,0.300,364,6788,3655,0.300,365,6875,3702,0.300,366,6809,3666,0.300,367,6761,3640,0.300,368,6769,3644,0.300,369,6753,3636,0.300,370,6726,3621,0.300,371,6645,3578,0.300,372,6626,3567,0.300,373,6566,3535,0.300,374,6522,3511,0.300,375,6570,3537,0.300,376,6518,3509,0.300,377,6284,3383,0.300,378,6460,3478,0.300,379,6802,3663,0.300,380,6748,3633,0.300,381,6698,3607,0.300,382,6700,3607,0.300,383,6661,3586,0.300,384,6629,3569,0.300,385,6549,3526,0.300,386,6533,3518,0.300,387,6502,3501,0.300,388,6463,3480,0.300,389,6512,3506,0.300,390,6457,3476,0.300,391,5914,3184,0.300, +AutoUpdateNewFW=1 +AutoSaveTestResult=1 +StartTest=0 +ExitAfterTest=0 +CapShortTest=0 +Gt9P_Bin_Type=0x2 +MapDisable=0 +KEY_NC=0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +NeedBatch=0 +ClrBatchAfterTest=0 +ShowDlgAfterTestNg=0 +TestBoardCtrl=0 +ok_io_reverse=0 +TestPowerCtrl=0 +RadiusVal=20 +RadiusStep=20 + +#×¢ÒâÏÂÃæµÄÁ½¸ö²ÎÊý²»ÄܳöÏÖ"//"×¢ÊÍ +#Factory= +#ProjectInfo= +ShortTest1Plus1=0 +ForceUpdateNewFw=0 +testParamMode=0 +CobCheck=0 +CofCob=0 +SepcialTestNodeDir= +UpdateHidI2CFW=0 +DstVersion= +HardWareID=elan1300 + + + + +[Interface] +NetEnable=0 + +[Net Setting] +Port=12345 +Protocol=TCP +ProtocolVer=0 + +[Customer] +Innolux=0 + +[Debug] +SensorTestDebugSW=0 +Debuger=0 +I2CLogAddr=0x86d4 +pwd= + +[Auto Config] +max_data_limit=12000 +min_data_limit=6000 +max_offset_limit=0.25 +min_snr_limit=30.0 +RawData_MaxLimit=2610 +RawData_MinLimit=921 +RawData_Offset_MaxLimit=0.200000 +DiffData_Offset_MaxLimit=0.200000 +RawData_Shake_MaxLimit=0.200000 +SNR_MinLimit=30.000000 +GT_Check_Edge=1 +GT_Tool_Livitated=0 +GT_Line_Adjust=1 +GT_Check_Diff=1 +GT_Output_Midcfg=1 +GT_Info_To_Text=0 +GT_TouchKeyStyle=2 +GT_TouchKeyCnt=3 +GT_DriverNum=20 +GT_SensorNum=12 +GT_IntMode=0 +GT_FixFreq=0 +GT_DCDC=1 +GT_Display_Time=500 +GT_RawdataMax=8050 +GT_RawdataMin=800 +GT_RawdataOffset=0.400000 +GT_DiffdataOffset=0.400000 +GT_PulseTime=7.000000 +GT_XOutputMax=4096 +GT_YOutputMax=4096 +GT_Driver_Pitch=5.000000 +GT_Sensor_Pitch=5.000000 +GT_DiffTailValueLimit=0.950000 +GT_RT=0 +GT818X_UpRadix=1.200000 +GT_Check_Pen=0 +GT_Check_Hopping=1 +GT_Check_Proximity=0 +GT_STP_SE=0 +GT_New_Hopping=1 +GT_CfgHighFreq=1 +GT_MakeTestParameter=1 +GT_ExportDriverCode=1 +GT_MaxMainFreqInit=80000 +GT_HoppingFlag=1 + +[SampleBoard Setting] +GT818_1_Config=0x12,0x10,0x0e,0x0c,0x0a,0x08,0x06,0x04,0x02,0x00,0x06,0x66,0x16,0x66,0x26,0x66,0x36,0x66,0x46,0x66,0x56,0x66,0x66,0x66,0x76,0x66,0x86,0x66,0x96,0x66,0xa6,0x66,0xb6,0x66,0xc6,0x66,0xd6,0x66,0xe6,0x66,0xf6,0x66,0x3f,0x03,0x00,0x00,0x00,0x23,0x23,0x23,0x0d,0x0d,0x0a,0x30,0x20,0x09,0x03,0x00,0x05,0x40,0x01,0xe0,0x01,0x00,0x00,0x66,0x66,0x60,0x60,0x00,0x00,0x03,0x14,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x14,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + +GT818_N_Config=0x65,0x00,0x10,0x00,0x10,0x00,0x0a,0x6d,0x01,0x00,0x0f,0x14,0x03,0x10,0x10,0x00,0x00,0x24,0x00,0x00,0x68,0x10,0x10,0x43,0x17,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0xff,0xff,0x00,0x00,0x3c,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + +[GT801 Setting] +I2CAddr=0xaa,0xa0 +FirmwareType=0 +I2CAddr16=0 +Config=0x19,0x05,0x04,0x28,0x02,0x14,0x14,0x10,0x3c,0x98,0x14,0x00,0x1e,0x00,0x02,0x46,0x8a,0xce,0xdb,0x97,0x53,0x11,0x00,0x00,0x00,0x00,0x4d,0xcf,0x20,0x01,0x01,0x83,0x38,0x3c,0x1e,0x28,0x10,0x0a,0x3c,0x64,0x1e,0x28,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + +[GT801PLUS Setting] +I2CAddr=0xaa,0xb8 +I2CAddr16=0 +FirmwareType=2 +Config=0x65,0xa0,0x25,0x80,0x19,0x00,0xaa,0x0c,0x00,0x00,0x00,0x02,0x05,0x10,0x4a,0x4f,0x4f,0x20,0x00,0x05,0x80,0x80,0x46,0x69,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,0x5f,0x4b,0x80,0xb9,0x00,0x00,0x00,0x00,0x00,0x16,0x19,0x19,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + +[GT818 Setting] +I2CAddr=0xba,0x6e,0xa0 +I2CAddr16=1 +FirmwareType=1 +Config=0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00,0x90,0x00,0xa0,0x00,0xb9,0x99,0xc8,0x88,0xd8,0x88,0xe0,0x00,0xf1,0x11,0x1b,0x03,0x80,0x80,0x80,0x20,0x20,0x20,0x0f,0x0e,0x0a,0x46,0x28,0x05,0x03,0x00,0x05,0xde,0x01,0x20,0x03,0x00,0x00,0x50,0x50,0x46,0x46,0x00,0x00,0x43,0x14,0x25,0x0a,0x80,0x0e,0x0e,0x00,0x03,0x14,0x10,0x00,0x00,0xbf,0x40,0x1b,0x80,0x20,0x03,0x30,0x40,0x90,0x00,0x0f,0x40,0x20,0x30,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + +[GT8110 Setting] +I2CAddr=0xaa,0xb8 +I2CAddr16=0 +FirmwareType=2 +Config=0x65,0x01,0x04,0x00,0x03,0x00,0x05,0xa1,0x01,0x00,0x00,0x14,0x00,0x10,0x10,0x00,0x00,0x20,0x00,0x00,0x80,0x00,0x00,0x03,0x37,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x32,0x78,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e + +[GT8105 Setting] +I2CAddr=0xaa,0xb8 +I2CAddr16=0 +FirmwareType=2 +Config=0x65,0x00,0x05,0x00,0x03,0x84,0x0a,0x2f,0x21,0x00,0x00,0x20,0x02,0x08,0x10,0x00,0x00,0x20,0x00,0x00,0x88,0x88,0x88,0x03,0x13,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0xff,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0xff,0xff,0xff,0x00,0x00,0x3c,0x50,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + +[GT819 Setting] +I2CAddr=0xaa,0xb8 +I2CAddr16=0 +FirmwareType=2 +Config=0x65,0x01,0x05,0x00,0x03,0x00,0x05,0x8d,0x01,0x00,0x0f,0x0c,0x02,0x08,0x10,0x00,0x00,0x20,0x00,0x00,0x80,0x80,0x80,0x00,0x1f,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x46,0x78,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20 + +[GT828 Setting] +I2CAddr=0xba,0x6e,0x28 +I2CAddr16=1 +FirmwareType=1 +Config=0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,0xff,0x17,0x16,0x15,0x14,0x13,0xff,0x11,0x10,0x0f,0x0e,0x0d,0x0b,0xff,0x03,0x0d,0x04,0x0e,0x05,0x0f,0x06,0x10,0x07,0x11,0xff,0x05,0xff,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0f,0x03,0x10,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x20,0x38,0x03,0x00,0x05,0x00,0x01,0x40,0x01,0xe0,0x66,0x66,0x60,0x60,0x05,0x00,0x23,0x19,0x05,0x14,0x10,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x28,0x60,0x20,0x2a,0x2a,0x00,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + + +[GT900 Setting] +I2CAddr=0xba,0x28 +I2CAddr16=1 +FirmwareType=1 +Config=0x41,0x1c,0x02,0xc0,0x03,0x0a,0x35,0x04,0x01,0x08,0x1e,0x05,0x50,0x3c,0x03,0x05,0x00,0x00,0xff,0x7f,0x00,0x00,0x00,0x17,0x19,0x1c,0x14,0x8c,0x0e,0x0e,0x26,0x28,0x73,0x13,0x03,0x00,0x00,0x9b,0x33,0x1d,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x19,0x3c,0x94,0xc5,0x02,0x00,0x00,0x00,0x04,0xa4,0x1b,0x00,0x90,0x20,0x00,0x80,0x26,0x00,0x71,0x2e,0x00,0x66,0x37,0x00,0x66,0x00,0x00,0x00,0x00,0xf0,0x40,0x32,0xff,0xff,0x27,0x00,0x00,0x00,0x00,0x1e,0x01,0x15,0x3c,0x30,0x0f,0x00,0x00,0x01,0x0f,0x19,0x03,0x06,0x10,0x42,0x86,0x0e,0x05,0x00,0x00,0x50,0x46,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x02,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x16,0x14,0x13,0x12,0x10,0x0f,0x0c,0x0a,0x08,0x06,0x04,0x02,0x00,0x18,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x24,0x26,0x28,0x29,0x2a,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x12,0x01 + +[GT968 Setting] +I2CAddr=0xba,0x28 +I2CAddr16=1 +FirmwareType=1 +Config=0x45,0x38,0x04,0xe8,0x08,0x0a,0x0c,0x00,0x01,0x08,0x28,0x0d,0x5a,0x41,0x03,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x14,0x87,0x27,0xee,0x4b,0x4d,0x31,0x0d,0x31,0x0d,0x00,0x02,0x03,0x11,0x0a,0x00,0x00,0x00,0x00,0x03,0x00,0x32,0x00,0x00,0x00,0x1e,0x5a,0x94,0x00,0x03,0x05,0x1e,0x00,0x04,0xca,0x21,0x00,0xab,0x29,0x00,0x91,0x34,0x00,0x7e,0x41,0x00,0x71,0x51,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0x17,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x18,0x19,0x1a,0x1b,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xff,0xff,0x08,0x06,0x05,0x04,0x0a,0x0c,0x0e,0x1e,0x1f,0x20,0x22,0x24,0x29,0x2a,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc5,0x01 + +[GT9115 Setting] +I2CAddr=0xba,0x28 +I2CAddr16=1 +FirmwareType=2 +Config=0x41,0x40,0x0b,0x08,0x07,0x0a,0x74,0xa0,0x11,0x0a,0x1e,0x09,0x64,0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x01,0xa5,0x00,0x00,0x24,0x3c,0x20,0x1e,0x8b,0x20,0x00,0x00,0x00,0x9b,0x03,0x1d,0x00,0x00,0x00,0x00,0x00,0x03,0x64,0x3c,0x48,0x00,0x33,0x12,0x32,0x54,0xc5,0x03,0x08,0x00,0x00,0x01,0xb3,0x14,0x82,0x93,0x18,0x00,0x80,0x1e,0x00,0x74,0x24,0x00,0x6c,0x2a,0x00,0x6c,0x00,0x00,0x00,0x00,0x57,0x14,0x17,0x19,0x1f,0x14,0x03,0x04,0x00,0x00,0x00,0xff,0xff,0x7f,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x15,0x16,0x17,0x18,0x19,0x1b,0x1c,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x15,0x16,0x17,0x18,0x19,0x1b,0x1c,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd8,0x01 + +[GT9P Setting] +I2CAddr=0xba,0x28 +I2CAddr16=1 +FirmwareType=1 +Config=0x80,0x38,0x04,0x80,0x07,0x0a,0x0d,0x12,0xa0,0xa0,0x02,0x0f,0x50,0x32,0x23,0x01,0x11,0x00,0x10,0x01,0x28,0x8c,0xa0,0xdc,0x08,0x04,0x00,0x01,0x08,0x0a,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x27,0x18,0x5a,0x5c,0x82,0x06,0x38,0x7e,0x38,0x8d,0x43,0x24,0x22,0x02,0x32,0x96,0xa0,0x94,0x58,0x78,0x11,0x02,0x89,0x42,0x88,0x53,0x82,0x63,0x80,0x74,0x7f,0x85,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x00,0x0d,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x01,0x6e,0x01,0x6e,0xfc,0x9f,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0x07,0x46,0x28,0x1d,0x1f,0x1e,0x1c,0x1b,0x1a,0x19,0x17,0x15,0x14,0x12,0x13,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0f,0x0e,0x10,0x0c,0x03,0x02,0x01,0xff,0xff,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x96,0x00,0x00,0x00,0x13,0x86,0x70,0x00,0x14,0x6a,0x6e,0x31,0x14,0x37,0x85,0x60,0x00,0x90,0x19,0xdf,0x07,0x37,0x46,0x14,0x01 + +[Designer] +para1=0x11 +para2=0x10 +CoordReadDelay=0 #¸ßµÍµçƽ¶ÁÈ¡×ø±ê¼ä¸ôʱ¼ä»òÖжϺóÑÓʱʱ¼ä,us +CoordChksumSW=1 #×ø±êУÑéºÍ¿ª¹Ø +DeviceCheckSW=1 +INTHighTime=0 +INTLowTime=0 +ThreadSleepTime=0 +DebugCount=0 +DebugData=0 +#GT8Clr4000=1 +úúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúúñúúú¥wÓžúÃD?gÁ®k §²Ÿ™NýÁ?fÒçNP!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v½ƒ_bÈ¢ƒŸB¾™äo"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—ç~je`À†–ŠeñÅ??…Êy-Whô•ŽUú™æ[ö‘7$ 3ƒÎÊß®”÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚÏ*”á?FŠõ]X1ÆÊϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ©? FóŽ<]/•ÆÊß®„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v½çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷v"—çS@!ÖÚϾ„÷[ì” +[Custom] +CustomString= +[Press] +RadiusVal=20 +RadiusStep=20 +LineWidthMin=10 +LineWidthMax=30 +DataLen=15 +TouchDownSampleDelayTime=500 +TouchDownSampleFrame=50 +TouchUpSampleTime1=1000 +TouchUpSampleInterval1=100 +TouchUpSampleTime2=10000 +TouchUpSampleInterval2=1000 +CalcPointNum=5 +PreViewDataNum=0 +PreViewMatrixColNum=0 +[Stylus Test Parameter] +OscMode=0 +WriteTestFlag=0 +WriteFreqParam=0 +FreqParam=250 +AutoUpdateFW=0 +ForceUpdateFW=0 +fw_bin_path= +VersionComp=0 +versionCompMode=0 +version_greater= +version_between1= +version_between2= +TipVoltTest=0 +TipVoltUpperLimit=0x0 +TipVoltLowerLimit=0x0 +TipVoltUpper=33.000000 +TipVoltLower=27.000000 +TiltVoltTest=0 +TiltVoltUpperLimit=0x0 +TiltVoltLowerLimit=0x0 +TiltVoltUpper=33.000000 +TiltVoltLower=27.000000 +ActiveCurrentTest=0 +ActiveCurrentUpperLimit=0x0 +ActiveCurrentLowerLimit=0x0 +SleepCurrentTest=0 +SleepCurrentUpperLimit=0x0 +SleepCurrentLowerLimit=0x0 +Power18VoltTest=0 +Power22VoltTest=0 +PrePressVoltTest=0 +GSensorTest=0 +PressCalibration=0 +PressRangeTest=0 +PressRangeUpperLimit=1000 +PressRangeLowerLimit=0 +PressResolutionTest=0 +PressResolutionUpperLimit=10.000000 +PressResolutionLowerLimit=1.000000 +Motor2PwmFreq=34000 +Motor2PauseCnt=34000 +StylusPressSensorJitterChk=0 +PressSensorJitterLowerLimit=0 +PressSensorJitterUpperLimit=10 +TouchKeyTest=0 +LowPowerTest=0 +ChargeTest=0 +StylusCfgWrite=0 +StylusBleTest=0 +StylusPreTestChk=0 +Config=0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +CaliSetValue1=0 +CaliLimitValue1=0 +CaliSetValue2=0 +CaliLimitValue2=0 +CaliSetValue3=0 +CaliLimitValue3=0 +CaliSetValue4=0 +CaliLimitValue4=0 +CaliSetValue5=0 +CaliLimitValue5=0 +CaliSetValue6=0 +CaliLimitValue6=0 +CaliSetValue7=0 +CaliLimitValue7=0 +CaliSetValue8=0 +CaliLimitValue8=0 +[StylusDevice] +ChipId=0 +PowerVolt=1.500000 +CommVolt=1.800000 diff --git a/drivers/input/touchscreen/gt9xx/Kconfig b/drivers/input/touchscreen/gt9xx/Kconfig deleted file mode 100644 index 2e1b5ba567a08..0000000000000 --- a/drivers/input/touchscreen/gt9xx/Kconfig +++ /dev/null @@ -1,51 +0,0 @@ -# -# Goodix GT9xx Touchscreen driver -# - -config GT9XX_TOUCHPANEL_DRIVER - tristate "Goodix GT9xx touchpanel driver" - depends on TOUCHSCREEN_GT9XX - default n - help - This is the main file for touchpanel driver for Goodix GT9xx - touchscreens. - - Say Y here if you have a Goodix GT9xx touchscreen connected - to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gt9xx. - -config GT9XX_TOUCHPANEL_UPDATE - tristate "Goodix GT9xx touchpanel auto update support" - depends on GT9XX_TOUCHPANEL_DRIVER - default n - help - This enables support for firmware update for Goodix GT9xx - touchscreens. - - Say Y here if you have a Goodix GT9xx touchscreen connected - to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gt9xx_update. - -config GT9XX_TOUCHPANEL_DEBUG - tristate "Goodix GT9xx Tools for debuging" - depends on GT9XX_TOUCHPANEL_DRIVER - default n - help - This is application debug interface support for Goodix GT9xx - touchscreens. - - Say Y here if you want to have a Android app debug interface - to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gt9xx_tool. diff --git a/drivers/input/touchscreen/gt9xx/Makefile b/drivers/input/touchscreen/gt9xx/Makefile deleted file mode 100644 index 482d869a2d37d..0000000000000 --- a/drivers/input/touchscreen/gt9xx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -#gt915 touchpanel driver - - -obj-$(CONFIG_GT9XX_TOUCHPANEL_DRIVER) += gt9xx.o -#gt915 update file -obj-$(CONFIG_GT9XX_TOUCHPANEL_UPDATE) += gt9xx_update.o -#debug tool -obj-$(CONFIG_GT9XX_TOUCHPANEL_DEBUG) += goodix_tool.o diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c deleted file mode 100644 index f8cfd688feb11..0000000000000 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ /dev/null @@ -1,608 +0,0 @@ -/* drivers/input/touchscreen/goodix_tool.c - * - * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Version:1.6 - * V1.0:2012/05/01,create file. - * V1.2:2012/06/08,modify some warning. - * V1.4:2012/08/28,modified to support GT9XX - * V1.6:new proc name - */ - -#include "gt9xx.h" -#include -#include -#include - -#define DATA_LENGTH_UINT 512 -#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head)) -static char procname[20] = {0}; - -struct st_cmd_head { - u8 wr; /* write read flag 0:R 1:W 2:PID 3: */ - u8 flag; /* 0:no need flag/int 1: need flag 2:need int */ - u8 flag_addr[2];/* flag address */ - u8 flag_val; /* flag val */ - u8 flag_relation; /* flag_val:flag 0:not equal 1:equal 2:> 3:< */ - u16 circle; /* polling cycle */ - u8 times; /* plling times */ - u8 retry; /* I2C retry times */ - u16 delay; /* delay before read or after write */ - u16 data_len; /* data length */ - u8 addr_len; /* address length */ - u8 addr[2]; /* address */ - u8 res[3]; /* reserved */ -} __packed; - -static struct st_cmd_head cmd_head; -static u8 *cmd_data; - -static struct i2c_client *gt_client; - -static struct proc_dir_entry *goodix_proc_entry; - -static struct mutex lock; - -static s32 (*tool_i2c_read)(u8 *, u16); -static s32 (*tool_i2c_write)(u8 *, u16); - -s32 data_length; -s8 ic_type[16] = {0}; - -static void tool_set_proc_name(char *procname) -{ - char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - char date[20] = {0}; - char month[4] = {0}; - int i = 0, n_month = 1, n_day = 0, n_year = 0, ret; - - ret = sscanf(date, "%s %d %d", month, &n_day, &n_year); - if (!ret) - return; - for (i = 0; i < 12; ++i) { - if (!memcmp(months[i], month, 3)) { - n_month = i+1; - break; - } - } - - snprintf(procname, 20, "gmnode%04d%02d%02d", n_year, n_month, n_day); - /* pr_debug("procname = %s", procname); */ -} - -static s32 tool_i2c_read_no_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 i = 0; - struct i2c_msg msgs[2] = { - { - .flags = !I2C_M_RD, - .addr = gt_client->addr, - .len = cmd_head.addr_len, - .buf = &buf[0], - }, - { - .flags = I2C_M_RD, - .addr = gt_client->addr, - .len = len, - .buf = &buf[GTP_ADDR_LENGTH], - }, - }; - - for (i = 0; i < cmd_head.retry; i++) { - ret = i2c_transfer(gt_client->adapter, msgs, 2); - if (ret > 0) - break; - } - - if (i == cmd_head.retry) { - dev_err(>_client->dev, "I2C read retry limit over.\n"); - ret = -EIO; - } - - return ret; -} - -static s32 tool_i2c_write_no_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 i = 0; - struct i2c_msg msg = { - .flags = !I2C_M_RD, - .addr = gt_client->addr, - .len = len, - .buf = buf, - }; - - for (i = 0; i < cmd_head.retry; i++) { - ret = i2c_transfer(gt_client->adapter, &msg, 1); - if (ret > 0) - break; - } - - if (i == cmd_head.retry) { - dev_err(>_client->dev, "I2C write retry limit over.\n"); - ret = -EIO; - } - - return ret; -} - -static s32 tool_i2c_read_with_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 pre[2] = {0x0f, 0xff}; - u8 end[2] = {0x80, 0x00}; - - tool_i2c_write_no_extra(pre, 2); - ret = tool_i2c_read_no_extra(buf, len); - tool_i2c_write_no_extra(end, 2); - - return ret; -} - -static s32 tool_i2c_write_with_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 pre[2] = {0x0f, 0xff}; - u8 end[2] = {0x80, 0x00}; - - tool_i2c_write_no_extra(pre, 2); - ret = tool_i2c_write_no_extra(buf, len); - tool_i2c_write_no_extra(end, 2); - - return ret; -} - -static void register_i2c_func(void) -{ - if (strcmp(ic_type, "GT8110") && strcmp(ic_type, "GT8105") - && strcmp(ic_type, "GT801") && strcmp(ic_type, "GT800") - && strcmp(ic_type, "GT801PLUS") && strcmp(ic_type, "GT811") - && strcmp(ic_type, "GTxxx")) { - tool_i2c_read = tool_i2c_read_with_extra; - tool_i2c_write = tool_i2c_write_with_extra; - pr_debug("I2C function: with pre and end cmd!"); - } else { - tool_i2c_read = tool_i2c_read_no_extra; - tool_i2c_write = tool_i2c_write_no_extra; - pr_info("I2C function: without pre and end cmd!"); - } -} - -static void unregister_i2c_func(void) -{ - tool_i2c_read = NULL; - tool_i2c_write = NULL; - pr_info("I2C function: unregister i2c transfer function!"); -} - -void uninit_wr_node(void) -{ - cmd_data = NULL; - unregister_i2c_func(); - proc_remove(goodix_proc_entry); -} - -static u8 relation(u8 src, u8 dst, u8 rlt) -{ - u8 ret = 0; - - switch (rlt) { - - case 0: - ret = (src != dst) ? true : false; - break; - - case 1: - ret = (src == dst) ? true : false; - pr_debug("equal:src:0x%02x dst:0x%02x ret:%d.", - src, dst, (s32)ret); - break; - - case 2: - ret = (src > dst) ? true : false; - break; - - case 3: - ret = (src < dst) ? true : false; - break; - - case 4: - ret = (src & dst) ? true : false; - break; - - case 5: - ret = (!(src | dst)) ? true : false; - break; - - default: - ret = false; - break; - } - - return ret; -} - -/******************************************************* -Function: - Comfirm function. -Input: - None. -Output: - Return write length. -********************************************************/ -static u8 comfirm(void) -{ - s32 i = 0; - u8 buf[32]; - - memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len); - - for (i = 0; i < cmd_head.times; i++) { - if (tool_i2c_read(buf, 1) <= 0) { - dev_err(>_client->dev, "Read flag data failed!"); - return FAIL; - } - if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, - cmd_head.flag_relation)) { - pr_debug("value at flag addr:0x%02x.", - buf[GTP_ADDR_LENGTH]); - pr_debug("flag value:0x%02x.", cmd_head.flag_val); - break; - } - - msleep(cmd_head.circle); - } - - if (i >= cmd_head.times) { - dev_err(>_client->dev, "Didn't get the flag to continue!"); - return FAIL; - } - - return SUCCESS; -} - -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE -static s32 fill_update_info(char __user *user_buf, - size_t count, loff_t *ppos) -{ - u8 buf[4]; - - buf[0] = show_len >> 8; - buf[1] = show_len & 0xff; - buf[2] = total_len >> 8; - buf[3] = total_len & 0xff; - return simple_read_from_buffer(user_buf, count, ppos, - buf, sizeof(buf)); -} -#else -static s32 fill_update_info(char __user *user_buf, - size_t count, loff_t *ppos) -{ - return -ENODEV; -} -#endif - -/******************************************************** -Function: - Goodix tool write function. -Input: - standard proc write function param. -Output: - Return write length. -********************************************************/ -static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - s32 ret = 0; - - mutex_lock(&lock); - ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed."); - ret = -EACCES; - goto exit; - } - - dev_dbg(>_client->dev, - "wr: 0x%02x, flag:0x%02x, flag addr:0x%02x%02x\n", cmd_head.wr, - cmd_head.flag, cmd_head.flag_addr[0], cmd_head.flag_addr[1]); - dev_dbg(>_client->dev, - "flag val:0x%02x, flag rel:0x%02x,\n", cmd_head.flag_val, - cmd_head.flag_relation); - dev_dbg(>_client->dev, "circle:%u, times:%u, retry:%u, delay:%u\n", - (s32) cmd_head.circle, (s32) cmd_head.times, - (s32) cmd_head.retry, (s32)cmd_head.delay); - dev_dbg(>_client->dev, - "data len:%u, addr len:%u, addr:0x%02x%02x, write len: %u\n", - (s32)cmd_head.data_len, (s32)cmd_head.addr_len, - cmd_head.addr[0], cmd_head.addr[1], (s32)count); - - if (cmd_head.data_len > (data_length - GTP_ADDR_LENGTH)) { - dev_err(>_client->dev, "data len %u > data buff %d, rejected!\n", - cmd_head.data_len, (data_length - GTP_ADDR_LENGTH)); - ret = -EINVAL; - goto exit; - } - if (cmd_head.addr_len > GTP_ADDR_LENGTH) { - dev_err(>_client->dev, "addr len %u > data buff %d, rejected!\n", - cmd_head.addr_len, GTP_ADDR_LENGTH); - ret = -EINVAL; - goto exit; - } - - if (cmd_head.wr == GTP_RW_WRITE) { - ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH], - &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed."); - goto exit; - } - - memcpy(&cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len], - cmd_head.addr, cmd_head.addr_len); - - if (cmd_head.flag == GTP_NEED_FLAG) { - if (comfirm() == FAIL) { - dev_err(>_client->dev, "Comfirm fail!"); - ret = -EINVAL; - goto exit; - } - } else if (cmd_head.flag == GTP_NEED_INTERRUPT) { - /* Need interrupt! */ - } - if (tool_i2c_write( - &cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len], - cmd_head.data_len + cmd_head.addr_len) <= 0) { - dev_err(>_client->dev, "Write data failed!"); - ret = -EIO; - goto exit; - } - - if (cmd_head.delay) - msleep(cmd_head.delay); - - ret = cmd_head.data_len + CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) { /* Write ic type */ - ret = copy_from_user(&cmd_data[0], - &userbuf[CMD_HEAD_LENGTH], - cmd_head.data_len); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed."); - goto exit; - } - - if (cmd_head.data_len > sizeof(ic_type)) { - dev_err(>_client->dev, - "data len %u > data buff %zu, rejected!\n", - cmd_head.data_len, sizeof(ic_type)); - ret = -EINVAL; - goto exit; - } - memcpy(ic_type, cmd_data, cmd_head.data_len); - - register_i2c_func(); - - ret = cmd_head.data_len + CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_NO_WRITE) { - ret = cmd_head.data_len + CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_DISABLE_IRQ) { /* disable irq! */ - gtp_irq_disable(i2c_get_clientdata(gt_client)); - - #if GTP_ESD_PROTECT - gtp_esd_switch(gt_client, SWITCH_OFF); - #endif - ret = CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_ENABLE_IRQ) { /* enable irq! */ - gtp_irq_enable(i2c_get_clientdata(gt_client)); - - #if GTP_ESD_PROTECT - gtp_esd_switch(gt_client, SWITCH_ON); - #endif - ret = CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) { - struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); - - ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH], - &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) { - pr_debug("copy_from_user failed."); - goto exit; - } - if (cmd_data[GTP_ADDR_LENGTH]) { - pr_debug("gtp enter rawdiff."); - ts->gtp_rawdiff_mode = true; - } else { - ts->gtp_rawdiff_mode = false; - pr_debug("gtp leave rawdiff."); - } - ret = CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_ENTER_UPDATE_MODE) { - /* Enter update mode! */ - if (gup_enter_update_mode(gt_client) == FAIL) { - ret = -EBUSY; - goto exit; - } - } else if (cmd_head.wr == GTP_RW_LEAVE_UPDATE_MODE) { - /* Leave update mode! */ - gup_leave_update_mode(gt_client); - } else if (cmd_head.wr == GTP_RW_UPDATE_FW) { - /* Update firmware! */ - show_len = 0; - total_len = 0; - if (cmd_head.data_len + 1 > data_length) { - dev_err(>_client->dev, "data len %u > data buff %d, rejected!\n", - cmd_head.data_len + 1, data_length); - ret = -EINVAL; - goto exit; - } - memset(cmd_data, 0, cmd_head.data_len + 1); - memcpy(cmd_data, &userbuf[CMD_HEAD_LENGTH], - cmd_head.data_len); - - if (gup_update_proc((void *)cmd_data) == FAIL) { - ret = -EBUSY; - goto exit; - } - } - ret = CMD_HEAD_LENGTH; - -exit: - memset(&cmd_head, 0, sizeof(cmd_head)); - cmd_head.wr = 0xFF; - - mutex_unlock(&lock); - return ret; -} - -/******************************************************* -Function: - Goodix tool read function. -Input: - standard seq file read function param. -Output: - Return read length. -********************************************************/ -static ssize_t goodix_tool_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - u16 data_len = 0; - s32 ret; - u8 buf[32]; - - mutex_lock(&lock); - if (cmd_head.wr & 0x1) { - dev_err(>_client->dev, "command head wrong\n"); - ret = -EINVAL; - goto exit; - } - - switch (cmd_head.wr) { - case GTP_RW_READ: - if (cmd_head.flag == GTP_NEED_FLAG) { - if (comfirm() == FAIL) { - dev_err(>_client->dev, "Comfirm fail!"); - ret = -EINVAL; - goto exit; - } - } else if (cmd_head.flag == GTP_NEED_INTERRUPT) { - /* Need interrupt! */ - } - - memcpy(cmd_data, cmd_head.addr, cmd_head.addr_len); - - pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_data[0], - cmd_data[1]); - pr_debug("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0], - cmd_head.addr[1]); - - if (cmd_head.delay) - msleep(cmd_head.delay); - - data_len = cmd_head.data_len; - if (data_len <= 0 || (data_len > data_length)) { - dev_err(>_client->dev, "Invalid data length %d\n", - data_len); - ret = -EINVAL; - goto exit; - } - if (data_len > count) - data_len = count; - - if (tool_i2c_read(cmd_data, data_len) <= 0) { - dev_err(>_client->dev, "Read data failed!\n"); - ret = -EIO; - goto exit; - } - ret = simple_read_from_buffer(user_buf, count, ppos, - &cmd_data[GTP_ADDR_LENGTH], data_len); - break; - case GTP_RW_FILL_INFO: - ret = fill_update_info(user_buf, count, ppos); - break; - case GTP_RW_READ_VERSION: - /* Read driver version */ - data_len = scnprintf(buf, sizeof(buf), "%s\n", - GTP_DRIVER_VERSION); - ret = simple_read_from_buffer(user_buf, count, ppos, - buf, data_len); - break; - default: - ret = -EINVAL; - break; - } - -exit: - mutex_unlock(&lock); - return ret; -} - -static const struct file_operations goodix_proc_fops = { - .write = goodix_tool_write, - .read = goodix_tool_read, - .open = simple_open, - .owner = THIS_MODULE, -}; - -s32 init_wr_node(struct i2c_client *client) -{ - u8 i; - - gt_client = client; - memset(&cmd_head, 0, sizeof(cmd_head)); - cmd_data = NULL; - - i = GTP_I2C_RETRY_5; - while ((!cmd_data) && i) { - cmd_data = devm_kzalloc(&client->dev, - i * DATA_LENGTH_UINT, GFP_KERNEL); - if (cmd_data) - break; - i--; - } - if (i) { - data_length = i * DATA_LENGTH_UINT; - dev_dbg(&client->dev, "Applied memory size:%d.", data_length); - } else { - dev_err(&client->dev, "Apply for memory failed."); - return FAIL; - } - - cmd_head.addr_len = 2; - cmd_head.retry = GTP_I2C_RETRY_5; - - register_i2c_func(); - - mutex_init(&lock); - tool_set_proc_name(procname); - goodix_proc_entry = proc_create(procname, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - goodix_proc_entry, - &goodix_proc_fops); - if (goodix_proc_entry == NULL) { - dev_err(&client->dev, "Couldn't create proc entry!"); - return FAIL; - } - - return SUCCESS; -} diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c deleted file mode 100644 index 8b61f3a26a66a..0000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ /dev/null @@ -1,2564 +0,0 @@ -/* drivers/input/touchscreen/gt9xx.c - * - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. - * - * Linux Foundation chooses to take subject only to the GPLv2 license - * terms, and distributes only under these terms. - * - * 2010 - 2013 Goodix Technology. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Version: 1.8 - * Authors: andrew@goodix.com, meta@goodix.com - * Release Date: 2013/04/25 - * Revision record: - * V1.0: - * first Release. By Andrew, 2012/08/31 - * V1.2: - * modify gtp_reset_guitar,slot report,tracking_id & 0x0F. - * By Andrew, 2012/10/15 - * V1.4: - * modify gt9xx_update.c. By Andrew, 2012/12/12 - * V1.6: - * 1. new heartbeat/esd_protect mechanism(add external watchdog) - * 2. doze mode, sliding wakeup - * 3. 3 more cfg_group(GT9 Sensor_ID: 0~5) - * 3. config length verification - * 4. names & comments - * By Meta, 2013/03/11 - * V1.8: - * 1. pen/stylus identification - * 2. read double check & fixed config support - * 2. new esd & slide wakeup optimization - * By Meta, 2013/06/08 - */ - -#include -#include "gt9xx.h" - -#include -#include -#include -#include -#include -#include -#include - -#define GOODIX_DEV_NAME "Goodix-CTP" -#define CFG_MAX_TOUCH_POINTS 5 -#define GOODIX_COORDS_ARR_SIZE 4 -#define MAX_BUTTONS 4 - -#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0])) - -#define GOODIX_VTG_MIN_UV 2600000 -#define GOODIX_VTG_MAX_UV 3300000 -#define GOODIX_I2C_VTG_MIN_UV 1800000 -#define GOODIX_I2C_VTG_MAX_UV 1800000 -#define GOODIX_VDD_LOAD_MIN_UA 0 -#define GOODIX_VDD_LOAD_MAX_UA 10000 -#define GOODIX_VIO_LOAD_MIN_UA 0 -#define GOODIX_VIO_LOAD_MAX_UA 10000 - -#define RESET_DELAY_T3_US 200 /* T3: > 100us */ -#define RESET_DELAY_T4 20 /* T4: > 5ms */ - -#define PHY_BUF_SIZE 32 -#define PROP_NAME_SIZE 24 - -#define GTP_MAX_TOUCH 5 -#define GTP_ESD_CHECK_CIRCLE_MS 2000 - -static void gtp_int_sync(struct goodix_ts_data *ts, int ms); -static int gtp_i2c_test(struct i2c_client *client); -static int goodix_power_off(struct goodix_ts_data *ts); -static int goodix_power_on(struct goodix_ts_data *ts); - -#if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -static int goodix_ts_suspend(struct device *dev); -static int goodix_ts_resume(struct device *dev); -#elif defined(CONFIG_HAS_EARLYSUSPEND) -static void goodix_ts_early_suspend(struct early_suspend *h); -static void goodix_ts_late_resume(struct early_suspend *h); -#endif - -#if GTP_ESD_PROTECT -static struct delayed_work gtp_esd_check_work; -static struct workqueue_struct *gtp_esd_check_workqueue; -static void gtp_esd_check_func(struct work_struct *work); -static int gtp_init_ext_watchdog(struct i2c_client *client); -#endif - -enum doze { - DOZE_DISABLED = 0, - DOZE_ENABLED = 1, - DOZE_WAKEUP = 2, -}; -static enum doze doze_status = DOZE_DISABLED; -static s8 gtp_enter_doze(struct goodix_ts_data *ts); - -bool init_done; -static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */ -u8 grp_cfg_version; -struct i2c_client *i2c_connect_client; - -#define GTP_DEBUGFS_DIR "ts_debug" -#define GTP_DEBUGFS_FILE_SUSPEND "suspend" -#define GTP_DEBUGFS_FILE_DATA "data" -#define GTP_DEBUGFS_FILE_ADDR "addr" - -/******************************************************* -Function: - Read data from the i2c slave device. -Input: - client: i2c device. - buf[0~1]: read start address. - buf[2~len-1]: read data buffer. - len: GTP_ADDR_LENGTH + read bytes count -Output: - numbers of i2c_msgs to transfer: - 2: succeed, otherwise: failed -*********************************************************/ -int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - int ret = -EIO; - u8 retries; - struct i2c_msg msgs[2] = { - { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = GTP_ADDR_LENGTH, - .buf = &buf[0], - }, - { - .flags = I2C_M_RD, - .addr = client->addr, - .len = len - GTP_ADDR_LENGTH, - .buf = &buf[GTP_ADDR_LENGTH], - }, - }; - - for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) { - ret = i2c_transfer(client->adapter, msgs, 2); - if (ret == 2) - break; - dev_err(&client->dev, "I2C retry: %d\n", retries + 1); - } - if (retries == GTP_I2C_RETRY_5) { - if (ts->pdata->slide_wakeup) - /* reset chip would quit doze mode */ - if (DOZE_ENABLED == doze_status) - return ret; - - if (init_done) - gtp_reset_guitar(ts, 10); - else - dev_warn(&client->dev, - "gtp_reset_guitar exit init_done=%d:\n", - init_done); - } - return ret; -} - -/******************************************************* -Function: - Write data to the i2c slave device. -Input: - client: i2c device. - buf[0~1]: write start address. - buf[2~len-1]: data buffer - len: GTP_ADDR_LENGTH + write bytes count -Output: - numbers of i2c_msgs to transfer: - 1: succeed, otherwise: failed -*********************************************************/ -int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - int ret = -EIO; - u8 retries; - struct i2c_msg msg = { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = len, - .buf = buf, - }; - - for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) { - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) - break; - dev_err(&client->dev, "I2C retry: %d\n", retries + 1); - } - if (retries == GTP_I2C_RETRY_5) { - if (ts->pdata->slide_wakeup) - if (DOZE_ENABLED == doze_status) - return ret; - - if (init_done) - gtp_reset_guitar(ts, 10); - else - dev_warn(&client->dev, - "gtp_reset_guitar exit init_done=%d:\n", - init_done); - } - return ret; -} - -/******************************************************* -Function: - i2c read twice, compare the results -Input: - client: i2c device - addr: operate address - rxbuf: read data to store, if compare successful - len: bytes to read -Output: - FAIL: read failed - SUCCESS: read successful -*********************************************************/ -int gtp_i2c_read_dbl_check(struct i2c_client *client, - u16 addr, u8 *rxbuf, int len) -{ - u8 buf[16] = {0}; - u8 confirm_buf[16] = {0}; - u8 retry = 0; - - while (retry++ < GTP_I2C_RETRY_3) { - memset(buf, 0xAA, 16); - buf[0] = (u8)(addr >> 8); - buf[1] = (u8)(addr & 0xFF); - gtp_i2c_read(client, buf, len + 2); - - memset(confirm_buf, 0xAB, 16); - confirm_buf[0] = (u8)(addr >> 8); - confirm_buf[1] = (u8)(addr & 0xFF); - gtp_i2c_read(client, confirm_buf, len + 2); - - if (!memcmp(buf, confirm_buf, len + 2)) - break; - } - if (retry < GTP_I2C_RETRY_3) { - memcpy(rxbuf, confirm_buf + 2, len); - return SUCCESS; - } - dev_err(&client->dev, - "i2c read 0x%04X, %d bytes, double check failed!", addr, len); - return FAIL; -} - -/******************************************************* -Function: - Send config data. -Input: - client: i2c device. -Output: - result of i2c write operation. - > 0: succeed, otherwise: failed -*********************************************************/ -int gtp_send_cfg(struct goodix_ts_data *ts) -{ - int ret = 0; - int retry; - - if (ts->pdata->driver_send_cfg) { - if (ts->fixed_cfg) { - dev_dbg(&ts->client->dev, - "Ic fixed config, no config sent!"); - ret = 2; - } else { - for (retry = 0; retry < GTP_I2C_RETRY_5; retry++) { - ret = gtp_i2c_write(ts->client, - ts->config_data, - GTP_CONFIG_MAX_LENGTH + - GTP_ADDR_LENGTH); - if (ret > 0) - break; - } - } - } - - return ret; -} - -/******************************************************* -Function: - Disable irq function -Input: - ts: goodix i2c_client private data -Output: - None. -*********************************************************/ -void gtp_irq_disable(struct goodix_ts_data *ts) -{ - unsigned long irqflags; - - spin_lock_irqsave(&ts->irq_lock, irqflags); - if (!ts->irq_is_disabled) { - ts->irq_is_disabled = true; - disable_irq_nosync(ts->client->irq); - } - spin_unlock_irqrestore(&ts->irq_lock, irqflags); -} - -/******************************************************* -Function: - Enable irq function -Input: - ts: goodix i2c_client private data -Output: - None. -*********************************************************/ -void gtp_irq_enable(struct goodix_ts_data *ts) -{ - unsigned long irqflags = 0; - - spin_lock_irqsave(&ts->irq_lock, irqflags); - if (ts->irq_is_disabled) { - enable_irq(ts->client->irq); - ts->irq_is_disabled = false; - } - spin_unlock_irqrestore(&ts->irq_lock, irqflags); -} - -/******************************************************* -Function: - Report touch point event -Input: - ts: goodix i2c_client private data - id: trackId - x: input x coordinate - y: input y coordinate - w: input pressure -Output: - None. -*********************************************************/ -static void gtp_touch_down(struct goodix_ts_data *ts, int id, int x, int y, - int w) -{ - if (ts->pdata->change_x2y) - swap(x, y); - - input_mt_slot(ts->input_dev, id); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); -} - -/******************************************************* -Function: - Report touch release event -Input: - ts: goodix i2c_client private data -Output: - None. -*********************************************************/ -static void gtp_touch_up(struct goodix_ts_data *ts, int id) -{ - input_mt_slot(ts->input_dev, id); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); -} - - - -/******************************************************* -Function: - Goodix touchscreen work function -Input: - work: work struct of goodix_workqueue -Output: - None. -*********************************************************/ -static void goodix_ts_work_func(struct work_struct *work) -{ - u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8, - GTP_READ_COOR_ADDR & 0xFF, 0}; - u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = { - GTP_READ_COOR_ADDR >> 8, - GTP_READ_COOR_ADDR & 0xFF}; - u8 touch_num = 0; - u8 finger = 0; - static u16 pre_touch; - static u8 pre_key; - static u8 pre_pen; - u8 key_value = 0; - u8 *coor_data = NULL; - s32 input_x = 0; - s32 input_y = 0; - s32 input_w = 0; - s32 id = 0; - s32 i = 0; - int ret = -1; - struct goodix_ts_data *ts = NULL; - u8 doze_buf[3] = {0x81, 0x4B}; - - ts = container_of(work, struct goodix_ts_data, work); -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE - if (ts->enter_update) - return; -#endif - - if (ts->pdata->slide_wakeup) { - if (DOZE_ENABLED == doze_status) { - ret = gtp_i2c_read(ts->client, doze_buf, 3); - if (ret > 0) { - if (doze_buf[2] == 0xAA) { - dev_dbg(&ts->client->dev, - "Slide(0xAA) To Light up the screen!"); - doze_status = DOZE_WAKEUP; - input_report_key( - ts->input_dev, KEY_POWER, 1); - input_sync(ts->input_dev); - input_report_key( - ts->input_dev, KEY_POWER, 0); - input_sync(ts->input_dev); - /* clear 0x814B */ - doze_buf[2] = 0x00; - gtp_i2c_write(ts->client, doze_buf, 3); - } else if (doze_buf[2] == 0xBB) { - dev_dbg(&ts->client->dev, - "Slide(0xBB) To Light up the screen!"); - doze_status = DOZE_WAKEUP; - input_report_key(ts->input_dev, - KEY_POWER, 1); - input_sync(ts->input_dev); - input_report_key(ts->input_dev, - KEY_POWER, 0); - input_sync(ts->input_dev); - /* clear 0x814B*/ - doze_buf[2] = 0x00; - gtp_i2c_write(ts->client, doze_buf, 3); - } else if (0xC0 == (doze_buf[2] & 0xC0)) { - dev_dbg(&ts->client->dev, - "double click to light up the screen!"); - doze_status = DOZE_WAKEUP; - input_report_key(ts->input_dev, - KEY_POWER, 1); - input_sync(ts->input_dev); - input_report_key(ts->input_dev, - KEY_POWER, 0); - input_sync(ts->input_dev); - /* clear 0x814B */ - doze_buf[2] = 0x00; - gtp_i2c_write(ts->client, doze_buf, 3); - } else { - gtp_enter_doze(ts); - } - } - if (ts->use_irq) - gtp_irq_enable(ts); - - return; - } - } - - ret = gtp_i2c_read(ts->client, point_data, 12); - if (ret < 0) { - dev_err(&ts->client->dev, - "I2C transfer error. errno:%d\n ", ret); - goto exit_work_func; - } - - finger = point_data[GTP_ADDR_LENGTH]; - if ((finger & 0x80) == 0) - goto exit_work_func; - - touch_num = finger & 0x0f; - if (touch_num > GTP_MAX_TOUCH) - goto exit_work_func; - - if (touch_num > 1) { - u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8, - (GTP_READ_COOR_ADDR + 10) & 0xff }; - - ret = gtp_i2c_read(ts->client, buf, - 2 + 8 * (touch_num - 1)); - memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1)); - } - - - key_value = point_data[3 + 8 * touch_num]; - - if (key_value || pre_key) { - for (i = 0; i < ts->pdata->num_button; i++) { - input_report_key(ts->input_dev, - ts->pdata->button_map[i], - key_value & (0x01<pdata->with_pen) { - if (pre_pen && (touch_num == 0)) { - dev_dbg(&ts->client->dev, "Pen touch UP(Slot)!"); - input_report_key(ts->input_dev, BTN_TOOL_PEN, 0); - input_mt_slot(ts->input_dev, 5); - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); - pre_pen = 0; - } - } - - if (pre_touch || touch_num) { - s32 pos = 0; - u16 touch_index = 0; - - coor_data = &point_data[3]; - if (touch_num) { - id = coor_data[pos] & 0x0F; - if (ts->pdata->with_pen) { - id = coor_data[pos]; - if (id == 128) { - dev_dbg(&ts->client->dev, - "Pen touch DOWN(Slot)!"); - input_x = coor_data[pos + 1] - | (coor_data[pos + 2] << 8); - input_y = coor_data[pos + 3] - | (coor_data[pos + 4] << 8); - input_w = coor_data[pos + 5] - | (coor_data[pos + 6] << 8); - - input_report_key(ts->input_dev, - BTN_TOOL_PEN, 1); - input_mt_slot(ts->input_dev, 5); - input_report_abs(ts->input_dev, - ABS_MT_TRACKING_ID, 5); - input_report_abs(ts->input_dev, - ABS_MT_POSITION_X, input_x); - input_report_abs(ts->input_dev, - ABS_MT_POSITION_Y, input_y); - input_report_abs(ts->input_dev, - ABS_MT_TOUCH_MAJOR, input_w); - dev_dbg(&ts->client->dev, - "Pen/Stylus: (%d, %d)[%d]", - input_x, input_y, input_w); - pre_pen = 1; - pre_touch = 0; - } - } - - touch_index |= (0x01<pdata->with_pen) - if (pre_pen == 1) - break; - - if (touch_index & (0x01<input_dev); - -exit_work_func: - if (!ts->gtp_rawdiff_mode) { - ret = gtp_i2c_write(ts->client, end_cmd, 3); - if (ret < 0) - dev_warn(&ts->client->dev, "I2C write end_cmd error!\n"); - - } - if (ts->use_irq) - gtp_irq_enable(ts); - - return; -} - -/******************************************************* -Function: - External interrupt service routine for interrupt mode. -Input: - irq: interrupt number. - dev_id: private data pointer -Output: - Handle Result. - IRQ_HANDLED: interrupt handled successfully -*********************************************************/ -static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) -{ - struct goodix_ts_data *ts = dev_id; - - gtp_irq_disable(ts); - - queue_work(ts->goodix_wq, &ts->work); - - return IRQ_HANDLED; -} -/******************************************************* -Function: - Synchronization. -Input: - ms: synchronization time in millisecond. -Output: - None. -*******************************************************/ -void gtp_int_sync(struct goodix_ts_data *ts, int ms) -{ - gpio_direction_output(ts->pdata->irq_gpio, 0); - msleep(ms); - gpio_direction_input(ts->pdata->irq_gpio); -} - -/******************************************************* -Function: - Reset chip. -Input: - ms: reset time in millisecond, must >10ms -Output: - None. -*******************************************************/ -void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) -{ - /* This reset sequence will selcet I2C slave address */ - gpio_direction_output(ts->pdata->reset_gpio, 0); - msleep(ms); - - if (ts->client->addr == GTP_I2C_ADDRESS_HIGH) - gpio_direction_output(ts->pdata->irq_gpio, 1); - else - gpio_direction_output(ts->pdata->irq_gpio, 0); - - usleep_range(200, 250); - gpio_direction_output(ts->pdata->reset_gpio, 1); - msleep(RESET_DELAY_T4); - - gpio_direction_input(ts->pdata->reset_gpio); - - gtp_int_sync(ts, 50); - -#if GTP_ESD_PROTECT - gtp_init_ext_watchdog(ts->client); -#endif -} - -#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) -/******************************************************* -Function: - Enter doze mode for sliding wakeup. -Input: - ts: goodix tp private data -Output: - 1: succeed, otherwise failed -*******************************************************/ -static s8 gtp_enter_doze(struct goodix_ts_data *ts) -{ - int ret = -1; - s8 retry = 0; - u8 i2c_control_buf[3] = { - (u8)(GTP_REG_SLEEP >> 8), - (u8)GTP_REG_SLEEP, 8}; - - if (ts->pdata->dbl_clk_wakeup) - i2c_control_buf[2] = 0x09; - - gtp_irq_disable(ts); - - while (retry++ < GTP_I2C_RETRY_3) { - i2c_control_buf[0] = 0x80; - i2c_control_buf[1] = 0x46; - ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); - if (ret < 0) { - dev_err(&ts->client->dev, - "failed to set doze flag into 0x8046, %d", - retry); - continue; - } - i2c_control_buf[0] = 0x80; - i2c_control_buf[1] = 0x40; - ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); - if (ret > 0) { - doze_status = DOZE_ENABLED; - dev_dbg(&ts->client->dev, - "GTP has been working in doze mode!"); - gtp_irq_enable(ts); - return ret; - } - msleep(20); - } - dev_err(&ts->client->dev, "GTP send doze cmd failed.\n"); - gtp_irq_enable(ts); - return ret; -} -/** - * gtp_enter_sleep - Enter sleep mode - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static u8 gtp_enter_sleep(struct goodix_ts_data *ts) -{ - int ret = -1; - s8 retry = 0; - u8 i2c_control_buf[3] = { - (u8)(GTP_REG_SLEEP >> 8), - (u8)GTP_REG_SLEEP, 5}; - - ret = gpio_direction_output(ts->pdata->irq_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP sleep: Cannot reconfig gpio %d.\n", - ts->pdata->irq_gpio); - if (ts->pdata->enable_power_off) { - ret = gpio_direction_output(ts->pdata->reset_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP sleep: Cannot reconfig gpio %d.\n", - ts->pdata->reset_gpio); - ret = goodix_power_off(ts); - if (ret) { - dev_err(&ts->client->dev, "GTP power off failed.\n"); - return ret; - } - return 0; - } - usleep_range(5000, 5500); - while (retry++ < GTP_I2C_RETRY_5) { - ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); - if (ret == 1) { - dev_dbg(&ts->client->dev, "GTP enter sleep!"); - return 0; - } - msleep(20); - } - dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n"); - return ret; -} - -/******************************************************* -Function: - Wakeup from sleep. -Input: - ts: private data. -Output: - Executive outcomes. - >0: succeed, otherwise: failed. -*******************************************************/ -static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) -{ - u8 retry = 0; - s8 ret = -1; - - if (ts->pdata->enable_power_off) { - ret = gpio_direction_output(ts->pdata->irq_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP wakeup: Cannot reconfig gpio %d.\n", - ts->pdata->irq_gpio); - ret = gpio_direction_output(ts->pdata->reset_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP wakeup: Cannot reconfig gpio %d.\n", - ts->pdata->reset_gpio); - ret = goodix_power_on(ts); - if (ret) { - dev_err(&ts->client->dev, "GTP power on failed.\n"); - return 0; - } - - gtp_reset_guitar(ts, 20); - - ret = gtp_send_cfg(ts); - if (ret <= 0) { - dev_err(&ts->client->dev, - "GTP wakeup sleep failed.\n"); - return ret; - } - - dev_dbg(&ts->client->dev, - "Wakeup sleep send config success."); - } else { -err_retry: - if (ts->pdata->slide_wakeup) { /* wakeup not by slide */ - if (DOZE_WAKEUP != doze_status) - gtp_reset_guitar(ts, 10); - else - /* wakeup by slide */ - doze_status = DOZE_DISABLED; - } else { - if (chip_gt9xxs == 1) { - gtp_reset_guitar(ts, 10); - } else { - ret = gpio_direction_output( - ts->pdata->irq_gpio, 1); - usleep_range(5000, 5500); - } - } - ret = gtp_i2c_test(ts->client); - if (ret == 2) { - dev_dbg(&ts->client->dev, "GTP wakeup sleep."); - if (!ts->pdata->slide_wakeup) { - if (chip_gt9xxs == 0) { - gtp_int_sync(ts, 25); - msleep(20); -#if GTP_ESD_PROTECT - gtp_init_ext_watchdog(ts->client); -#endif - } - } - return ret; - } - gtp_reset_guitar(ts, 20); - if (retry++ < GTP_I2C_RETRY_10) - goto err_retry; - dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n"); - } - return ret; -} -#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ - -/******************************************************* -Function: - Initialize gtp. -Input: - ts: goodix private data -Output: - Executive outcomes. - > =0: succeed, otherwise: failed -*******************************************************/ -static int gtp_init_panel(struct goodix_ts_data *ts) -{ - struct i2c_client *client = ts->client; - unsigned char *config_data = NULL; - int ret = -EIO; - int i; - u8 check_sum = 0; - u8 opr_buf[16]; - u8 sensor_id = 0; - - if (ts->pdata->driver_send_cfg) { - for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) - dev_dbg(&client->dev, "Config Groups(%d) Lengths: %zu", - i, ts->pdata->config_data_len[i]); - - ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1); - if (SUCCESS == ret) { - if (opr_buf[0] != 0xBE) { - ts->fw_error = 1; - dev_err(&client->dev, - "Firmware error, no config sent!"); - return -EINVAL; - } - } - - for (i = 1; i < GOODIX_MAX_CFG_GROUP; i++) { - if (ts->pdata->config_data_len[i]) - break; - } - - if (i == GOODIX_MAX_CFG_GROUP) { - sensor_id = 0; - } else { - ret = gtp_i2c_read_dbl_check(ts->client, - GTP_REG_SENSOR_ID, &sensor_id, 1); - if (SUCCESS == ret) { - if (sensor_id >= GOODIX_MAX_CFG_GROUP) { - dev_err(&client->dev, - "Invalid sensor_id(0x%02X), No Config Sent!", - sensor_id); - return -EINVAL; - } - } else { - dev_err(&client->dev, - "Failed to get sensor_id, No config sent!"); - return -EINVAL; - } - } - - dev_info(&client->dev, "Sensor ID selected: %d", sensor_id); - - if (ts->pdata->config_data_len[sensor_id] < - GTP_CONFIG_MIN_LENGTH || - !ts->pdata->config_data[sensor_id]) { - dev_err(&client->dev, - "Sensor_ID(%d) matches with NULL or invalid config group!\n", - sensor_id); - return -EINVAL; - } - - ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, - &opr_buf[0], 1); - if (ret == SUCCESS) { - if (opr_buf[0] < 90) { - /* backup group config version */ - grp_cfg_version = - ts->pdata-> - config_data[sensor_id][GTP_ADDR_LENGTH]; - ts->pdata-> - config_data[sensor_id][GTP_ADDR_LENGTH] - = 0x00; - ts->fixed_cfg = 0; - } else { - /* treated as fixed config, not send config */ - dev_warn(&client->dev, - "Ic fixed config with config version(%d, 0x%02X)", - opr_buf[0], opr_buf[0]); - ts->fixed_cfg = 1; - } - } else { - dev_err(&client->dev, - "Failed to get ic config version!No config sent!"); - return -EINVAL; - } - - config_data = ts->pdata->config_data[sensor_id]; - ts->config_data = ts->pdata->config_data[sensor_id]; - ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id]; - -#if GTP_CUSTOM_CFG - config_data[RESOLUTION_LOC] = - (unsigned char)(GTP_MAX_WIDTH && 0xFF); - config_data[RESOLUTION_LOC + 1] = - (unsigned char)(GTP_MAX_WIDTH >> 8); - config_data[RESOLUTION_LOC + 2] = - (unsigned char)(GTP_MAX_HEIGHT && 0xFF); - config_data[RESOLUTION_LOC + 3] = - (unsigned char)(GTP_MAX_HEIGHT >> 8); - - if (GTP_INT_TRIGGER == 0) - config_data[TRIGGER_LOC] &= 0xfe; - else if (GTP_INT_TRIGGER == 1) - config_data[TRIGGER_LOC] |= 0x01; -#endif /* !GTP_CUSTOM_CFG */ - - check_sum = 0; - for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) - check_sum += config_data[i]; - - config_data[ts->gtp_cfg_len] = (~check_sum) + 1; - - } else { /* DRIVER NOT SEND CONFIG */ - ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH; - ret = gtp_i2c_read(ts->client, config_data, - ts->gtp_cfg_len + GTP_ADDR_LENGTH); - if (ret < 0) { - dev_err(&client->dev, - "Read Config Failed, Using DEFAULT Resolution & INT Trigger!\n"); - ts->abs_x_max = GTP_MAX_WIDTH; - ts->abs_y_max = GTP_MAX_HEIGHT; - ts->int_trigger_type = GTP_INT_TRIGGER; - } - } /* !DRIVER NOT SEND CONFIG */ - - if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0) && - (config_data != NULL)) { - ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8) - + config_data[RESOLUTION_LOC]; - ts->abs_y_max = (config_data[RESOLUTION_LOC + 3] << 8) - + config_data[RESOLUTION_LOC + 2]; - ts->int_trigger_type = (config_data[TRIGGER_LOC]) & 0x03; - } - ret = gtp_send_cfg(ts); - if (ret < 0) - dev_err(&client->dev, "%s: Send config error.\n", __func__); - - msleep(20); - return ret; -} - -/******************************************************* -Function: - Read firmware version -Input: - client: i2c device - version: buffer to keep ic firmware version -Output: - read operation return. - 0: succeed, otherwise: failed -*******************************************************/ -static int gtp_read_fw_version(struct i2c_client *client, u16 *version) -{ - int ret = 0; - u8 buf[GTP_FW_VERSION_BUFFER_MAXSIZE] = { - GTP_REG_FW_VERSION >> 8, GTP_REG_FW_VERSION & 0xff }; - - ret = gtp_i2c_read(client, buf, sizeof(buf)); - if (ret < 0) { - dev_err(&client->dev, "GTP read version failed.\n"); - return -EIO; - } - - if (version) - *version = (buf[3] << 8) | buf[2]; - - return ret; -} -/******************************************************* -Function: - Read and check chip id. -Input: - client: i2c device -Output: - read operation return. - 0: succeed, otherwise: failed -*******************************************************/ -static int gtp_check_product_id(struct i2c_client *client) -{ - int ret = 0; - char product_id[GTP_PRODUCT_ID_MAXSIZE]; - struct goodix_ts_data *ts = i2c_get_clientdata(client); - /* 04 bytes are used for the Product-id in the register space.*/ - u8 buf[GTP_PRODUCT_ID_BUFFER_MAXSIZE] = { - GTP_REG_PRODUCT_ID >> 8, GTP_REG_PRODUCT_ID & 0xff }; - - ret = gtp_i2c_read(client, buf, sizeof(buf)); - if (ret < 0) { - dev_err(&client->dev, "GTP read product_id failed.\n"); - return -EIO; - } - - if (buf[5] == 0x00) { - /* copy (GTP_PRODUCT_ID_MAXSIZE - 1) from buffer. Ex: 915 */ - strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE - 1); - } else { - if (buf[5] == 'S' || buf[5] == 's') - chip_gt9xxs = 1; - /* copy GTP_PRODUCT_ID_MAXSIZE from buffer. Ex: 915s */ - strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE); - } - - dev_info(&client->dev, "Goodix Product ID = %s\n", product_id); - - ret = strcmp(product_id, ts->pdata->product_id); - if (ret != 0) - return -EINVAL; - - return ret; -} - -/******************************************************* -Function: - I2c test Function. -Input: - client:i2c client. -Output: - Executive outcomes. - 2: succeed, otherwise failed. -*******************************************************/ -static int gtp_i2c_test(struct i2c_client *client) -{ - u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff }; - int retry = GTP_I2C_RETRY_5; - int ret = -EIO; - - while (retry--) { - ret = gtp_i2c_read(client, buf, 3); - if (ret > 0) - return ret; - dev_err(&client->dev, "GTP i2c test failed time %d.\n", retry); - msleep(20); - } - return ret; -} - -/******************************************************* -Function: - Request gpio(INT & RST) ports. -Input: - ts: private data. -Output: - Executive outcomes. - = 0: succeed, != 0: failed -*******************************************************/ -static int gtp_request_io_port(struct goodix_ts_data *ts) -{ - struct i2c_client *client = ts->client; - struct goodix_ts_platform_data *pdata = ts->pdata; - int ret; - - if (gpio_is_valid(pdata->irq_gpio)) { - ret = gpio_request(pdata->irq_gpio, "goodix_ts_irq_gpio"); - if (ret) { - dev_err(&client->dev, "Unable to request irq gpio [%d]\n", - pdata->irq_gpio); - goto err_pwr_off; - } - ret = gpio_direction_input(pdata->irq_gpio); - if (ret) { - dev_err(&client->dev, "Unable to set direction for irq gpio [%d]\n", - pdata->irq_gpio); - goto err_free_irq_gpio; - } - } else { - dev_err(&client->dev, "Invalid irq gpio [%d]!\n", - pdata->irq_gpio); - ret = -EINVAL; - goto err_pwr_off; - } - - if (gpio_is_valid(pdata->reset_gpio)) { - ret = gpio_request(pdata->reset_gpio, "goodix_ts_reset_gpio"); - if (ret) { - dev_err(&client->dev, "Unable to request reset gpio [%d]\n", - pdata->reset_gpio); - goto err_free_irq_gpio; - } - - ret = gpio_direction_output(pdata->reset_gpio, 0); - if (ret) { - dev_err(&client->dev, "Unable to set direction for reset gpio [%d]\n", - pdata->reset_gpio); - goto err_free_reset_gpio; - } - } else { - dev_err(&client->dev, "Invalid irq gpio [%d]!\n", - pdata->reset_gpio); - ret = -EINVAL; - goto err_free_irq_gpio; - } - /* IRQ GPIO is an input signal, but we are setting it to output - * direction and pulling it down, to comply with power up timing - * requirements, mentioned in power up timing section of device - * datasheet. - */ - ret = gpio_direction_output(pdata->irq_gpio, 0); - if (ret) - dev_warn(&client->dev, - "pull down interrupt gpio failed\n"); - ret = gpio_direction_output(pdata->reset_gpio, 0); - if (ret) - dev_warn(&client->dev, - "pull down reset gpio failed\n"); - - return ret; - -err_free_reset_gpio: - if (gpio_is_valid(pdata->reset_gpio)) - gpio_free(pdata->reset_gpio); -err_free_irq_gpio: - if (gpio_is_valid(pdata->irq_gpio)) - gpio_free(pdata->irq_gpio); -err_pwr_off: - return ret; -} - -/******************************************************* -Function: - Request interrupt. -Input: - ts: private data. -Output: - Executive outcomes. - 0: succeed, -1: failed. -*******************************************************/ -static int gtp_request_irq(struct goodix_ts_data *ts) -{ - int ret = 0; - - ret = request_threaded_irq(ts->client->irq, NULL, - goodix_ts_irq_handler, - ts->pdata->irq_gpio_flags, - ts->client->name, ts); - if (ret) { - ts->use_irq = false; - return ret; - } - gtp_irq_disable(ts); - ts->use_irq = true; - return ret; -} - -/******************************************************* -Function: - Request input device Function. -Input: - ts:private data. -Output: - Executive outcomes. - 0: succeed, otherwise: failed. -*******************************************************/ -static int gtp_request_input_dev(struct goodix_ts_data *ts) -{ - int ret; - char phys[PHY_BUF_SIZE]; - int index = 0; - - ts->input_dev = input_allocate_device(); - if (ts->input_dev == NULL) { - dev_err(&ts->client->dev, - "Failed to allocate input device.\n"); - return -ENOMEM; - } - - ts->input_dev->evbit[0] = - BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit); - __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); - /* in case of "out of memory" */ - input_mt_init_slots(ts->input_dev, 10, 0); - - if (ts->pdata->have_touch_key) { - for (index = 0; index < ts->pdata->num_button; index++) { - input_set_capability(ts->input_dev, - EV_KEY, ts->pdata->button_map[index]); - } - } - - if (ts->pdata->slide_wakeup) - input_set_capability(ts->input_dev, EV_KEY, KEY_POWER); - - if (ts->pdata->with_pen) { /* pen support */ - __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit); - __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); - __set_bit(INPUT_PROP_POINTER, ts->input_dev->propbit); - } - - if (ts->pdata->change_x2y) - swap(ts->abs_x_max, ts->abs_y_max); - - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, - 0, ts->abs_x_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, - 0, ts->abs_y_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, - 0, 255, 0, 0); - - snprintf(phys, PHY_BUF_SIZE, "input/ts"); - ts->input_dev->name = GOODIX_DEV_NAME; - ts->input_dev->phys = phys; - ts->input_dev->id.bustype = BUS_I2C; - ts->input_dev->id.vendor = 0xDEAD; - ts->input_dev->id.product = 0xBEEF; - ts->input_dev->id.version = 10427; - - ret = input_register_device(ts->input_dev); - if (ret) { - dev_err(&ts->client->dev, - "Register %s input device failed.\n", - ts->input_dev->name); - goto exit_free_inputdev; - } - - return 0; - -exit_free_inputdev: - input_free_device(ts->input_dev); - ts->input_dev = NULL; - return ret; -} - -static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA) -{ - return (regulator_count_voltages(reg) > 0) ? - regulator_set_optimum_mode(reg, load_uA) : 0; -} - -/** - * goodix_power_on - Turn device power ON - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_on(struct goodix_ts_data *ts) -{ - int ret; - - if (ts->power_on) { - dev_info(&ts->client->dev, - "Device already power on\n"); - return 0; - } - - if (!IS_ERR(ts->avdd)) { - ret = reg_set_optimum_mode_check(ts->avdd, - GOODIX_VDD_LOAD_MAX_UA); - if (ret < 0) { - dev_err(&ts->client->dev, - "Regulator avdd set_opt failed rc=%d\n", ret); - goto err_set_opt_avdd; - } - ret = regulator_enable(ts->avdd); - if (ret) { - dev_err(&ts->client->dev, - "Regulator avdd enable failed ret=%d\n", ret); - goto err_enable_avdd; - } - } - - if (!IS_ERR(ts->vdd)) { - ret = regulator_set_voltage(ts->vdd, GOODIX_VTG_MIN_UV, - GOODIX_VTG_MAX_UV); - if (ret) { - dev_err(&ts->client->dev, - "Regulator set_vtg failed vdd ret=%d\n", ret); - goto err_set_vtg_vdd; - } - ret = reg_set_optimum_mode_check(ts->vdd, - GOODIX_VDD_LOAD_MAX_UA); - if (ret < 0) { - dev_err(&ts->client->dev, - "Regulator vdd set_opt failed rc=%d\n", ret); - goto err_set_opt_vdd; - } - ret = regulator_enable(ts->vdd); - if (ret) { - dev_err(&ts->client->dev, - "Regulator vdd enable failed ret=%d\n", ret); - goto err_enable_vdd; - } - } - - if (!IS_ERR(ts->vcc_i2c)) { - ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV, - GOODIX_I2C_VTG_MAX_UV); - if (ret) { - dev_err(&ts->client->dev, - "Regulator set_vtg failed vcc_i2c ret=%d\n", - ret); - goto err_set_vtg_vcc_i2c; - } - ret = reg_set_optimum_mode_check(ts->vcc_i2c, - GOODIX_VIO_LOAD_MAX_UA); - if (ret < 0) { - dev_err(&ts->client->dev, - "Regulator vcc_i2c set_opt failed rc=%d\n", - ret); - goto err_set_opt_vcc_i2c; - } - ret = regulator_enable(ts->vcc_i2c); - if (ret) { - dev_err(&ts->client->dev, - "Regulator vcc_i2c enable failed ret=%d\n", - ret); - regulator_disable(ts->vdd); - goto err_enable_vcc_i2c; - } - } - - ts->power_on = true; - return 0; - -err_enable_vcc_i2c: -err_set_opt_vcc_i2c: - if (!IS_ERR(ts->vcc_i2c)) - regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); -err_set_vtg_vcc_i2c: - if (!IS_ERR(ts->vdd)) - regulator_disable(ts->vdd); -err_enable_vdd: -err_set_opt_vdd: - if (!IS_ERR(ts->vdd)) - regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); -err_set_vtg_vdd: - if (!IS_ERR(ts->avdd)) - regulator_disable(ts->avdd); -err_enable_avdd: -err_set_opt_avdd: - ts->power_on = false; - return ret; -} - -/** - * goodix_power_off - Turn device power OFF - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_off(struct goodix_ts_data *ts) -{ - int ret; - - if (!ts->power_on) { - dev_info(&ts->client->dev, - "Device already power off\n"); - return 0; - } - - if (!IS_ERR(ts->vcc_i2c)) { - ret = regulator_set_voltage(ts->vcc_i2c, 0, - GOODIX_I2C_VTG_MAX_UV); - if (ret < 0) - dev_err(&ts->client->dev, - "Regulator vcc_i2c set_vtg failed ret=%d\n", - ret); - ret = regulator_disable(ts->vcc_i2c); - if (ret) - dev_err(&ts->client->dev, - "Regulator vcc_i2c disable failed ret=%d\n", - ret); - } - - if (!IS_ERR(ts->vdd)) { - ret = regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); - if (ret < 0) - dev_err(&ts->client->dev, - "Regulator vdd set_vtg failed ret=%d\n", ret); - ret = regulator_disable(ts->vdd); - if (ret) - dev_err(&ts->client->dev, - "Regulator vdd disable failed ret=%d\n", ret); - } - - if (!IS_ERR(ts->avdd)) { - ret = regulator_disable(ts->avdd); - if (ret) - dev_err(&ts->client->dev, - "Regulator avdd disable failed ret=%d\n", ret); - } - - ts->power_on = false; - return 0; -} - -/** - * goodix_power_init - Initialize device power - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_init(struct goodix_ts_data *ts) -{ - int ret; - - ts->avdd = regulator_get(&ts->client->dev, "avdd"); - if (IS_ERR(ts->avdd)) { - ret = PTR_ERR(ts->avdd); - dev_info(&ts->client->dev, - "Regulator get failed avdd ret=%d\n", ret); - } - - ts->vdd = regulator_get(&ts->client->dev, "vdd"); - if (IS_ERR(ts->vdd)) { - ret = PTR_ERR(ts->vdd); - dev_info(&ts->client->dev, - "Regulator get failed vdd ret=%d\n", ret); - } - - ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc_i2c"); - if (IS_ERR(ts->vcc_i2c)) { - ret = PTR_ERR(ts->vcc_i2c); - dev_info(&ts->client->dev, - "Regulator get failed vcc_i2c ret=%d\n", ret); - } - - return 0; -} - -/** - * goodix_power_deinit - Deinitialize device power - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_deinit(struct goodix_ts_data *ts) -{ - regulator_put(ts->vdd); - regulator_put(ts->vcc_i2c); - regulator_put(ts->avdd); - - return 0; -} - -static ssize_t gtp_fw_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - - if (!strlen(ts->fw_name)) - return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1, - "No fw name has been given."); - else - return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1, - "%s\n", ts->fw_name); -} - -static ssize_t gtp_fw_name_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - - if (size > GTP_FW_NAME_MAXSIZE - 1) { - dev_err(dev, "FW name size exceeds the limit."); - return -EINVAL; - } - - strlcpy(ts->fw_name, buf, size); - if (ts->fw_name[size-1] == '\n') - ts->fw_name[size-1] = '\0'; - - return size; -} - -static ssize_t gtp_fw_upgrade_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - - return snprintf(buf, 2, "%d\n", ts->fw_loading); -} - -static ssize_t gtp_fw_upgrade_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - unsigned int val; - int ret; - - if (size > 2) - return -EINVAL; - - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; - - if (ts->gtp_is_suspend) { - dev_err(&ts->client->dev, - "Can't start fw upgrade. Device is in suspend state."); - return -EBUSY; - } - - mutex_lock(&ts->input_dev->mutex); - if (!ts->fw_loading && val) { - disable_irq(ts->client->irq); - ts->fw_loading = true; - if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { - ret = gup_update_proc(NULL); - if (ret == FAIL) - dev_err(&ts->client->dev, - "Fail to update GTP firmware.\n"); - } - ts->fw_loading = false; - enable_irq(ts->client->irq); - } - mutex_unlock(&ts->input_dev->mutex); - - return size; -} - -static ssize_t gtp_force_fw_upgrade_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - unsigned int val; - int ret; - - if (size > 2) - return -EINVAL; - - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; - - if (ts->gtp_is_suspend) { - dev_err(&ts->client->dev, - "Can't start fw upgrade. Device is in suspend state."); - return -EBUSY; - } - - mutex_lock(&ts->input_dev->mutex); - if (!ts->fw_loading && val) { - disable_irq(ts->client->irq); - ts->fw_loading = true; - ts->force_update = true; - if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { - ret = gup_update_proc(NULL); - if (ret == FAIL) - dev_err(&ts->client->dev, - "Fail to force update GTP firmware.\n"); - } - ts->force_update = false; - ts->fw_loading = false; - enable_irq(ts->client->irq); - } - mutex_unlock(&ts->input_dev->mutex); - - return size; -} - -static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP), - gtp_fw_name_show, - gtp_fw_name_store); -static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP), - gtp_fw_upgrade_show, - gtp_fw_upgrade_store); -static DEVICE_ATTR(force_fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP), - gtp_fw_upgrade_show, - gtp_force_fw_upgrade_store); - -static struct attribute *gtp_attrs[] = { - &dev_attr_fw_name.attr, - &dev_attr_fw_upgrade.attr, - &dev_attr_force_fw_upgrade.attr, - NULL -}; - -static const struct attribute_group gtp_attr_grp = { - .attrs = gtp_attrs, -}; - -static int gtp_debug_addr_is_valid(u16 addr) -{ - if (addr < GTP_VALID_ADDR_START || addr > GTP_VALID_ADDR_END) { - pr_err("GTP reg address is invalid: 0x%x\n", addr); - return false; - } - - return true; -} - -static int gtp_debug_data_set(void *_data, u64 val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - if (gtp_debug_addr_is_valid(ts->addr)) - dev_err(&ts->client->dev, - "Writing to GTP registers not supported.\n"); - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -static int gtp_debug_data_get(void *_data, u64 *val) -{ - struct goodix_ts_data *ts = _data; - int ret; - u8 buf[3] = {0}; - - mutex_lock(&ts->input_dev->mutex); - buf[0] = ts->addr >> 8; - buf[1] = ts->addr & 0x00ff; - - if (gtp_debug_addr_is_valid(ts->addr)) { - ret = gtp_i2c_read(ts->client, buf, 3); - if (ret < 0) - dev_err(&ts->client->dev, - "GTP read register 0x%x failed (%d)\n", - ts->addr, ret); - else - *val = buf[2]; - } - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, gtp_debug_data_get, - gtp_debug_data_set, "%llx\n"); - -static int gtp_debug_addr_set(void *_data, u64 val) -{ - struct goodix_ts_data *ts = _data; - - if (gtp_debug_addr_is_valid(val)) { - mutex_lock(&ts->input_dev->mutex); - ts->addr = val; - mutex_unlock(&ts->input_dev->mutex); - } - - return 0; -} - -static int gtp_debug_addr_get(void *_data, u64 *val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - if (gtp_debug_addr_is_valid(ts->addr)) - *val = ts->addr; - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, gtp_debug_addr_get, - gtp_debug_addr_set, "%llx\n"); - -static int gtp_debug_suspend_set(void *_data, u64 val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - if (val) - goodix_ts_suspend(&ts->client->dev); - else - goodix_ts_resume(&ts->client->dev); - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -static int gtp_debug_suspend_get(void *_data, u64 *val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - *val = ts->gtp_is_suspend; - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, gtp_debug_suspend_get, - gtp_debug_suspend_set, "%lld\n"); - -static int gtp_debugfs_init(struct goodix_ts_data *data) -{ - data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL); - - if (IS_ERR_OR_NULL(data->debug_base)) { - dev_err(&data->client->dev, "Failed to create debugfs dir.\n"); - return -EINVAL; - } - - if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_SUSPEND, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - data->debug_base, - data, - &debug_suspend_fops)))) { - dev_err(&data->client->dev, "Failed to create suspend file.\n"); - debugfs_remove_recursive(data->debug_base); - return -EINVAL; - } - - if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_DATA, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - data->debug_base, - data, - &debug_data_fops)))) { - dev_err(&data->client->dev, "Failed to create data file.\n"); - debugfs_remove_recursive(data->debug_base); - return -EINVAL; - } - - if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_ADDR, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - data->debug_base, - data, - &debug_addr_fops)))) { - dev_err(&data->client->dev, "Failed to create addr file.\n"); - debugfs_remove_recursive(data->debug_base); - return -EINVAL; - } - - return 0; -} - -static int goodix_ts_get_dt_coords(struct device *dev, char *name, - struct goodix_ts_platform_data *pdata) -{ - struct property *prop; - struct device_node *np = dev->of_node; - int rc; - u32 coords[GOODIX_COORDS_ARR_SIZE]; - - prop = of_find_property(np, name, NULL); - if (!prop) - return -EINVAL; - if (!prop->value) - return -ENODATA; - - rc = of_property_read_u32_array(np, name, coords, - GOODIX_COORDS_ARR_SIZE); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Unable to read %s\n", name); - return rc; - } - - if (!strcmp(name, "goodix,panel-coords")) { - pdata->panel_minx = coords[0]; - pdata->panel_miny = coords[1]; - pdata->panel_maxx = coords[2]; - pdata->panel_maxy = coords[3]; - } else if (!strcmp(name, "goodix,display-coords")) { - pdata->x_min = coords[0]; - pdata->y_min = coords[1]; - pdata->x_max = coords[2]; - pdata->y_max = coords[3]; - } else { - dev_err(dev, "unsupported property %s\n", name); - return -EINVAL; - } - - return 0; -} - -static int goodix_parse_dt(struct device *dev, - struct goodix_ts_platform_data *pdata) -{ - int rc; - struct device_node *np = dev->of_node; - struct property *prop; - u32 temp_val, num_buttons; - u32 button_map[MAX_BUTTONS]; - char prop_name[PROP_NAME_SIZE]; - int i, read_cfg_num, temp; - - rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata); - if (rc && (rc != -EINVAL)) - return rc; - - rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata); - if (rc) - return rc; - - pdata->i2c_pull_up = of_property_read_bool(np, - "goodix,i2c-pull-up"); - - pdata->force_update = of_property_read_bool(np, - "goodix,force-update"); - - pdata->enable_power_off = of_property_read_bool(np, - "goodix,enable-power-off"); - - pdata->have_touch_key = of_property_read_bool(np, - "goodix,have-touch-key"); - - pdata->driver_send_cfg = of_property_read_bool(np, - "goodix,driver-send-cfg"); - - pdata->change_x2y = of_property_read_bool(np, - "goodix,change-x2y"); - - pdata->with_pen = of_property_read_bool(np, - "goodix,with-pen"); - - pdata->slide_wakeup = of_property_read_bool(np, - "goodix,slide-wakeup"); - - pdata->dbl_clk_wakeup = of_property_read_bool(np, - "goodix,dbl_clk_wakeup"); - - /* reset, irq gpio info */ - pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", - 0, &pdata->reset_gpio_flags); - if (pdata->reset_gpio < 0) - return pdata->reset_gpio; - - pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios", - 0, &pdata->irq_gpio_flags); - if (pdata->irq_gpio < 0) - return pdata->irq_gpio; - - rc = of_property_read_string(np, "goodix,product-id", - &pdata->product_id); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Failed to parse product_id."); - return -EINVAL; - } - - rc = of_property_read_string(np, "goodix,fw_name", - &pdata->fw_name); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Failed to parse firmware name.\n"); - return -EINVAL; - } - - prop = of_find_property(np, "goodix,button-map", NULL); - if (prop) { - num_buttons = prop->length / sizeof(temp_val); - if (num_buttons > MAX_BUTTONS) - return -EINVAL; - - rc = of_property_read_u32_array(np, - "goodix,button-map", button_map, - num_buttons); - if (rc) { - dev_err(dev, "Unable to read key codes\n"); - return rc; - } - pdata->num_button = num_buttons; - memcpy(pdata->button_map, button_map, - pdata->num_button * sizeof(u32)); - } - - read_cfg_num = 0; - for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) { - temp = 0; - snprintf(prop_name, sizeof(prop_name), "goodix,cfg-data%d", i); - prop = of_find_property(np, prop_name, &temp); - if (!prop || !prop->value) { - pdata->config_data_len[i] = 0; - pdata->config_data[i] = NULL; - continue; - } - pdata->config_data_len[i] = temp; - pdata->config_data[i] = devm_kzalloc(dev, - GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, - GFP_KERNEL); - if (!pdata->config_data[i]) { - dev_err(dev, - "Not enough memory for panel config data %d\n", - i); - return -ENOMEM; - } - pdata->config_data[i][0] = GTP_REG_CONFIG_DATA >> 8; - pdata->config_data[i][1] = GTP_REG_CONFIG_DATA & 0xff; - memcpy(&pdata->config_data[i][GTP_ADDR_LENGTH], - prop->value, pdata->config_data_len[i]); - read_cfg_num++; - } - dev_dbg(dev, "%d config data read from device tree.\n", read_cfg_num); - - return 0; -} - -/******************************************************* -Function: - I2c probe. -Input: - client: i2c device struct. - id: device id. -Output: - Executive outcomes. - 0: succeed. -*******************************************************/ - -static int goodix_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct goodix_ts_platform_data *pdata; - struct goodix_ts_data *ts; - u16 version_info; - int ret; - - dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr); - if (client->dev.of_node) { - pdata = devm_kzalloc(&client->dev, - sizeof(struct goodix_ts_platform_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - ret = goodix_parse_dt(&client->dev, pdata); - if (ret) - return ret; - } else { - pdata = client->dev.platform_data; - } - - if (!pdata) { - dev_err(&client->dev, "GTP invalid pdata\n"); - return -EINVAL; - } - - i2c_connect_client = client; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "GTP I2C not supported\n"); - return -ENODEV; - } - - ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - memset(ts, 0, sizeof(*ts)); - ts->client = client; - ts->pdata = pdata; - /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock) - * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED - */ - spin_lock_init(&ts->irq_lock); - i2c_set_clientdata(client, ts); - ts->gtp_rawdiff_mode = 0; - ts->power_on = false; - - ret = gtp_request_io_port(ts); - if (ret) { - dev_err(&client->dev, "GTP request IO port failed.\n"); - goto exit_free_client_data; - } - - ret = goodix_power_init(ts); - if (ret) { - dev_err(&client->dev, "GTP power init failed\n"); - goto exit_free_io_port; - } - - ret = goodix_power_on(ts); - if (ret) { - dev_err(&client->dev, "GTP power on failed\n"); - goto exit_deinit_power; - } - - gtp_reset_guitar(ts, 20); - - ret = gtp_i2c_test(client); - if (ret != 2) { - dev_err(&client->dev, "I2C communication ERROR!\n"); - goto exit_power_off; - } - - if (pdata->force_update) - ts->force_update = true; - - if (pdata->fw_name) - strlcpy(ts->fw_name, pdata->fw_name, - strlen(pdata->fw_name) + 1); - - if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { - ret = gup_init_update_proc(ts); - if (ret < 0) { - dev_err(&client->dev, - "GTP Create firmware update thread error.\n"); - goto exit_power_off; - } - } - ret = gtp_init_panel(ts); - if (ret < 0) { - dev_err(&client->dev, "GTP init panel failed.\n"); - ts->abs_x_max = GTP_MAX_WIDTH; - ts->abs_y_max = GTP_MAX_HEIGHT; - ts->int_trigger_type = GTP_INT_TRIGGER; - } - - ret = gtp_request_input_dev(ts); - if (ret) { - dev_err(&client->dev, "GTP request input dev failed.\n"); - goto exit_free_inputdev; - } - input_set_drvdata(ts->input_dev, ts); - - mutex_init(&ts->lock); -#if defined(CONFIG_FB) - ts->fb_notif.notifier_call = fb_notifier_callback; - ret = fb_register_client(&ts->fb_notif); - if (ret) - dev_err(&ts->client->dev, - "Unable to register fb_notifier: %d\n", - ret); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - ts->early_suspend.suspend = goodix_ts_early_suspend; - ts->early_suspend.resume = goodix_ts_late_resume; - register_early_suspend(&ts->early_suspend); -#endif - - ts->goodix_wq = create_singlethread_workqueue("goodix_wq"); - INIT_WORK(&ts->work, goodix_ts_work_func); - - ret = gtp_request_irq(ts); - if (ret) - dev_info(&client->dev, "GTP request irq failed %d.\n", ret); - else - dev_info(&client->dev, "GTP works in interrupt mode.\n"); - - ret = gtp_read_fw_version(client, &version_info); - if (ret != 2) - dev_err(&client->dev, "GTP firmware version read failed.\n"); - - ret = gtp_check_product_id(client); - if (ret != 0) { - dev_err(&client->dev, "GTP Product id doesn't match.\n"); - goto exit_free_irq; - } - if (ts->use_irq) - gtp_irq_enable(ts); - -#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG - init_wr_node(client); -#endif - -#if GTP_ESD_PROTECT - gtp_esd_switch(client, SWITCH_ON); -#endif - ret = sysfs_create_group(&client->dev.kobj, >p_attr_grp); - if (ret < 0) { - dev_err(&client->dev, "sys file creation failed.\n"); - goto exit_free_irq; - } - - ret = gtp_debugfs_init(ts); - if (ret != 0) { - dev_err(&client->dev, "Failed to create debugfs entries, %d\n", - ret); - goto exit_remove_sysfs; - } - - init_done = true; - return 0; -exit_free_irq: - mutex_destroy(&ts->lock); -#if defined(CONFIG_FB) - if (fb_unregister_client(&ts->fb_notif)) - dev_err(&client->dev, - "Error occurred while unregistering fb_notifier.\n"); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - unregister_early_suspend(&ts->early_suspend); -#endif - if (ts->use_irq) - free_irq(client->irq, ts); - cancel_work_sync(&ts->work); - flush_workqueue(ts->goodix_wq); - destroy_workqueue(ts->goodix_wq); - - if (ts->input_dev) { - input_unregister_device(ts->input_dev); - input_free_device(ts->input_dev); - ts->input_dev = NULL; - } -exit_remove_sysfs: - sysfs_remove_group(&ts->input_dev->dev.kobj, >p_attr_grp); -exit_free_inputdev: - kfree(ts->config_data); -exit_power_off: - goodix_power_off(ts); -exit_deinit_power: - goodix_power_deinit(ts); -exit_free_io_port: - if (gpio_is_valid(pdata->reset_gpio)) - gpio_free(pdata->reset_gpio); - if (gpio_is_valid(pdata->irq_gpio)) - gpio_free(pdata->irq_gpio); -exit_free_client_data: - i2c_set_clientdata(client, NULL); - return ret; -} - -/******************************************************* -Function: - Goodix touchscreen driver release function. -Input: - client: i2c device struct. -Output: - Executive outcomes. 0---succeed. -*******************************************************/ -static int goodix_ts_remove(struct i2c_client *client) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - - if (ts) { - sysfs_remove_group(&ts->input_dev->dev.kobj, >p_attr_grp); - -#if defined(CONFIG_FB) - fb_unregister_client(&ts->fb_notif); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - unregister_early_suspend(&ts->early_suspend); -#endif - mutex_destroy(&ts->lock); - -#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG - uninit_wr_node(); -#endif - -#if GTP_ESD_PROTECT - cancel_work_sync(gtp_esd_check_workqueue); - flush_workqueue(gtp_esd_check_workqueue); - destroy_workqueue(gtp_esd_check_workqueue); -#endif - - if (ts->use_irq) - free_irq(client->irq, ts); - - cancel_work_sync(&ts->work); - flush_workqueue(ts->goodix_wq); - destroy_workqueue(ts->goodix_wq); - - if (ts->input_dev) { - input_unregister_device(ts->input_dev); - input_free_device(ts->input_dev); - ts->input_dev = NULL; - } - - if (gpio_is_valid(ts->pdata->reset_gpio)) - gpio_free(ts->pdata->reset_gpio); - if (gpio_is_valid(ts->pdata->irq_gpio)) - gpio_free(ts->pdata->irq_gpio); - - goodix_power_off(ts); - goodix_power_deinit(ts); - i2c_set_clientdata(client, NULL); - debugfs_remove_recursive(ts->debug_base); - } - - return 0; -} - -#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) -/******************************************************* -Function: - Early suspend function. -Input: - h: early_suspend struct. -Output: - None. -*******************************************************/ -static int goodix_ts_suspend(struct device *dev) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - int ret = 0, i; - - if (ts->gtp_is_suspend) { - dev_dbg(&ts->client->dev, "Already in suspend state.\n"); - return 0; - } - - mutex_lock(&ts->lock); - - if (ts->fw_loading) { - dev_info(&ts->client->dev, - "Fw upgrade in progress, can't go to suspend."); - mutex_unlock(&ts->lock); - return 0; - } - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_OFF); -#endif - - if (ts->pdata->slide_wakeup) { - ret = gtp_enter_doze(ts); - } else { - if (ts->use_irq) - gtp_irq_disable(ts); - - for (i = 0; i < GTP_MAX_TOUCH; i++) - gtp_touch_up(ts, i); - - input_sync(ts->input_dev); - - ret = gtp_enter_sleep(ts); - if (ret < 0) - dev_err(&ts->client->dev, "GTP early suspend failed.\n"); - } - /* to avoid waking up while not sleeping, - * delay 48 + 10ms to ensure reliability - */ - msleep(58); - mutex_unlock(&ts->lock); - ts->gtp_is_suspend = 1; - - return ret; -} - -/******************************************************* -Function: - Late resume function. -Input: - h: early_suspend struct. -Output: - None. -*******************************************************/ -static int goodix_ts_resume(struct device *dev) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - int ret = 0; - - if (!ts->gtp_is_suspend) { - dev_dbg(&ts->client->dev, "Already in awake state.\n"); - return 0; - } - - mutex_lock(&ts->lock); - ret = gtp_wakeup_sleep(ts); - - if (ts->pdata->slide_wakeup) - doze_status = DOZE_DISABLED; - - if (ret <= 0) - dev_err(&ts->client->dev, "GTP resume failed.\n"); - - if (ts->use_irq) - gtp_irq_enable(ts); - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_ON); -#endif - mutex_unlock(&ts->lock); - ts->gtp_is_suspend = 0; - - return ret; -} - -#if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct fb_event *evdata = data; - int *blank; - struct goodix_ts_data *ts = - container_of(self, struct goodix_ts_data, fb_notif); - - if (evdata && evdata->data && event == FB_EVENT_BLANK && - ts && ts->client) { - blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - goodix_ts_resume(&ts->client->dev); - else if (*blank == FB_BLANK_POWERDOWN) - goodix_ts_suspend(&ts->client->dev); - } - - return 0; -} -#elif defined(CONFIG_HAS_EARLYSUSPEND) -/******************************************************* -Function: - Early suspend function. -Input: - h: early_suspend struct. -Output: - None. -*******************************************************/ -static void goodix_ts_early_suspend(struct early_suspend *h) -{ - struct goodix_ts_data *ts; - - ts = container_of(h, struct goodix_ts_data, early_suspend); - goodix_ts_suspend(&ts->client->dev); - return; -} - -/******************************************************* -Function: - Late resume function. -Input: - h: early_suspend struct. -Output: - None. -*******************************************************/ -static void goodix_ts_late_resume(struct early_suspend *h) -{ - struct goodix_ts_data *ts; - - ts = container_of(h, struct goodix_ts_data, early_suspend); - goodix_ts_late_resume(ts); -} -#endif -#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ - -#if GTP_ESD_PROTECT -/******************************************************* -Function: - switch on & off esd delayed work -Input: - client: i2c device - on: SWITCH_ON / SWITCH_OFF -Output: - void -*********************************************************/ -void gtp_esd_switch(struct i2c_client *client, int on) -{ - struct goodix_ts_data *ts; - - ts = i2c_get_clientdata(client); - if (SWITCH_ON == on) { - /* switch on esd */ - if (!ts->esd_running) { - ts->esd_running = 1; - dev_dbg(&client->dev, "Esd started\n"); - queue_delayed_work(gtp_esd_check_workqueue, - >p_esd_check_work, GTP_ESD_CHECK_CIRCLE); - } - } else { - /* switch off esd */ - if (ts->esd_running) { - ts->esd_running = 0; - dev_dbg(&client->dev, "Esd cancelled\n"); - cancel_delayed_work_sync(>p_esd_check_work); - } - } -} - -/******************************************************* -Function: - Initialize external watchdog for esd protect -Input: - client: i2c device. -Output: - result of i2c write operation. - 1: succeed, otherwise: failed -*********************************************************/ -static int gtp_init_ext_watchdog(struct i2c_client *client) -{ - /* in case of recursively reset by calling gtp_i2c_write*/ - struct i2c_msg msg; - u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA}; - int ret; - int retries = 0; - - msg.flags = !I2C_M_RD; - msg.addr = client->addr; - msg.len = 4; - msg.buf = opr_buffer; - - while (retries < GTP_I2C_RETRY_5) { - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) - return 1; - retries++; - } - if (retries == GTP_I2C_RETRY_5) - dev_err(&client->dev, "init external watchdog failed!"); - return 0; -} - -/******************************************************* -Function: - Esd protect function. - Added external watchdog by meta, 2013/03/07 -Input: - work: delayed work -Output: - None. -*******************************************************/ -static void gtp_esd_check_func(struct work_struct *work) -{ - s32 retry; - s32 ret = -1; - struct goodix_ts_data *ts = NULL; - u8 test[4] = {0x80, 0x40}; - - ts = i2c_get_clientdata(i2c_connect_client); - - if (ts->gtp_is_suspend) { - dev_dbg(&ts->client->dev, "Esd terminated!\n"); - ts->esd_running = 0; - return; - } -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE - if (ts->enter_update) - return; -#endif - - for (retry = 0; retry < GTP_I2C_RETRY_3; retry++) { - ret = gtp_i2c_read(ts->client, test, 4); - - if ((ret < 0)) { - /* IC works abnormally..*/ - continue; - } else { - if ((test[2] == 0xAA) || (test[3] != 0xAA)) { - /* IC works abnormally..*/ - retry = GTP_I2C_RETRY_3; - break; - } - /* IC works normally, Write 0x8040 0xAA*/ - test[2] = 0xAA; - gtp_i2c_write(ts->client, test, 3); - break; - } - } - if (retry == GTP_I2C_RETRY_3) { - dev_err(&ts->client->dev, - "IC Working ABNORMALLY, Resetting Guitar...\n"); - gtp_reset_guitar(ts, 50); - } - - if (!ts->gtp_is_suspend) - queue_delayed_work(gtp_esd_check_workqueue, - >p_esd_check_work, GTP_ESD_CHECK_CIRCLE); - else { - dev_dbg(&ts->client->dev, "Esd terminated!\n"); - ts->esd_running = 0; - } - - return; -} -#endif - -#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) -static const struct dev_pm_ops goodix_ts_dev_pm_ops = { - .suspend = goodix_ts_suspend, - .resume = goodix_ts_resume, -}; -#else -static const struct dev_pm_ops goodix_ts_dev_pm_ops = { -}; -#endif - -static const struct i2c_device_id goodix_ts_id[] = { - { GTP_I2C_NAME, 0 }, - { } -}; - -static struct of_device_id goodix_match_table[] = { - { .compatible = "goodix,gt9xx", }, - { }, -}; - -static struct i2c_driver goodix_ts_driver = { - .probe = goodix_ts_probe, - .remove = goodix_ts_remove, -#ifdef CONFIG_HAS_EARLYSUSPEND - .suspend = goodix_ts_early_suspend, - .resume = goodix_ts_late_resume, -#endif - .id_table = goodix_ts_id, - .driver = { - .name = GTP_I2C_NAME, - .owner = THIS_MODULE, - .of_match_table = goodix_match_table, -#if CONFIG_PM - .pm = &goodix_ts_dev_pm_ops, -#endif - }, -}; - -/******************************************************* -Function: - Driver Install function. -Input: - None. -Output: - Executive Outcomes. 0---succeed. -********************************************************/ -static int __init goodix_ts_init(void) -{ - int ret; - -#if GTP_ESD_PROTECT - INIT_DELAYED_WORK(>p_esd_check_work, gtp_esd_check_func); - gtp_esd_check_workqueue = create_workqueue("gtp_esd_check"); -#endif - ret = i2c_add_driver(&goodix_ts_driver); - return ret; -} - -/******************************************************* -Function: - Driver uninstall function. -Input: - None. -Output: - Executive Outcomes. 0---succeed. -********************************************************/ -static void __exit goodix_ts_exit(void) -{ - i2c_del_driver(&goodix_ts_driver); -} - -module_init(goodix_ts_init); -module_exit(goodix_ts_exit); - -MODULE_DESCRIPTION("GTP Series Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h deleted file mode 100644 index 9cac7a33c33e4..0000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ /dev/null @@ -1,225 +0,0 @@ -/* drivers/input/touchscreen/gt9xx.h - * - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. - * - * Linux Foundation chooses to take subject only to the GPLv2 license - * terms, and distributes only under these terms. - * - * 2010 - 2013 Goodix Technology. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#ifndef _GOODIX_GT9XX_H_ -#define _GOODIX_GT9XX_H_ - -#include -#include -#include -#include -#include - -#if defined(CONFIG_FB) -#include -#include -#elif defined(CONFIG_HAS_EARLYSUSPEND) -#include -#define GOODIX_SUSPEND_LEVEL 1 -#endif - -#define MAX_BUTTONS 4 -#define GOODIX_MAX_CFG_GROUP 6 -#define GTP_FW_NAME_MAXSIZE 50 - -struct goodix_ts_platform_data { - int irq_gpio; - u32 irq_gpio_flags; - int reset_gpio; - u32 reset_gpio_flags; - const char *product_id; - const char *fw_name; - u32 x_max; - u32 y_max; - u32 x_min; - u32 y_min; - u32 panel_minx; - u32 panel_miny; - u32 panel_maxx; - u32 panel_maxy; - bool force_update; - bool i2c_pull_up; - bool enable_power_off; - size_t config_data_len[GOODIX_MAX_CFG_GROUP]; - u8 *config_data[GOODIX_MAX_CFG_GROUP]; - u32 button_map[MAX_BUTTONS]; - u8 num_button; - bool have_touch_key; - bool driver_send_cfg; - bool change_x2y; - bool with_pen; - bool slide_wakeup; - bool dbl_clk_wakeup; -}; -struct goodix_ts_data { - spinlock_t irq_lock; - struct i2c_client *client; - struct input_dev *input_dev; - struct goodix_ts_platform_data *pdata; - struct hrtimer timer; - struct workqueue_struct *goodix_wq; - struct work_struct work; - char fw_name[GTP_FW_NAME_MAXSIZE]; - struct delayed_work goodix_update_work; - s32 irq_is_disabled; - s32 use_irq; - u16 abs_x_max; - u16 abs_y_max; - u16 addr; - u8 max_touch_num; - u8 int_trigger_type; - u8 green_wake_mode; - u8 chip_type; - u8 *config_data; - u8 enter_update; - u8 gtp_is_suspend; - u8 gtp_rawdiff_mode; - u8 gtp_cfg_len; - u8 fixed_cfg; - u8 esd_running; - u8 fw_error; - bool power_on; - struct mutex lock; - bool fw_loading; - bool force_update; - struct regulator *avdd; - struct regulator *vdd; - struct regulator *vcc_i2c; -#if defined(CONFIG_FB) - struct notifier_block fb_notif; -#elif defined(CONFIG_HAS_EARLYSUSPEND) - struct early_suspend early_suspend; -#endif - struct dentry *debug_base; -}; - -extern u16 show_len; -extern u16 total_len; - -/***************************PART1:ON/OFF define*******************************/ -#define GTP_CUSTOM_CFG 1 -#define GTP_ESD_PROTECT 0 - -#define GTP_IRQ_TAB {\ - IRQ_TYPE_EDGE_RISING,\ - IRQ_TYPE_EDGE_FALLING,\ - IRQ_TYPE_LEVEL_LOW,\ - IRQ_TYPE_LEVEL_HIGH\ - } - - -#define GTP_IRQ_TAB_RISING 0 -#define GTP_IRQ_TAB_FALLING 1 -#if GTP_CUSTOM_CFG -#define GTP_MAX_HEIGHT 864 -#define GTP_MAX_WIDTH 480 -#define GTP_INT_TRIGGER GTP_IRQ_TAB_RISING -#else -#define GTP_MAX_HEIGHT 4096 -#define GTP_MAX_WIDTH 4096 -#define GTP_INT_TRIGGER GTP_IRQ_TAB_FALLING -#endif - -#define GTP_PRODUCT_ID_MAXSIZE 5 -#define GTP_PRODUCT_ID_BUFFER_MAXSIZE 6 -#define GTP_FW_VERSION_BUFFER_MAXSIZE 4 -#define GTP_MAX_TOUCH 5 -#define GTP_ESD_CHECK_CIRCLE 2000 /* jiffy: ms */ - -/***************************PART3:OTHER define*********************************/ -#define GTP_DRIVER_VERSION "V1.8.1<2013/09/01>" -#define GTP_I2C_NAME "Goodix-TS" -#define GTP_POLL_TIME 10 /* jiffy: ms*/ -#define GTP_ADDR_LENGTH 2 -#define GTP_CONFIG_MIN_LENGTH 186 -#define GTP_CONFIG_MAX_LENGTH 240 -#define FAIL 0 -#define SUCCESS 1 -#define SWITCH_OFF 0 -#define SWITCH_ON 1 - -/* Registers define */ -#define GTP_READ_COOR_ADDR 0x814E -#define GTP_REG_SLEEP 0x8040 -#define GTP_REG_SENSOR_ID 0x814A -#define GTP_REG_CONFIG_DATA 0x8047 -#define GTP_REG_FW_VERSION 0x8144 -#define GTP_REG_PRODUCT_ID 0x8140 - -#define GTP_I2C_RETRY_3 3 -#define GTP_I2C_RETRY_5 5 -#define GTP_I2C_RETRY_10 10 - -#define RESOLUTION_LOC 3 -#define TRIGGER_LOC 8 - -/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ -#define GTP_I2C_ADDRESS_HIGH 0x14 -#define GTP_I2C_ADDRESS_LOW 0x5D -#define GTP_VALID_ADDR_START 0x8040 -#define GTP_VALID_ADDR_END 0x8177 - -#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0])) - -/* GTP CM_HEAD RW flags */ -#define GTP_RW_READ 0 -#define GTP_RW_WRITE 1 -#define GTP_RW_READ_IC_TYPE 2 -#define GTP_RW_WRITE_IC_TYPE 3 -#define GTP_RW_FILL_INFO 4 -#define GTP_RW_NO_WRITE 5 -#define GTP_RW_READ_ERROR 6 -#define GTP_RW_DISABLE_IRQ 7 -#define GTP_RW_READ_VERSION 8 -#define GTP_RW_ENABLE_IRQ 9 -#define GTP_RW_ENTER_UPDATE_MODE 11 -#define GTP_RW_LEAVE_UPDATE_MODE 13 -#define GTP_RW_UPDATE_FW 15 -#define GTP_RW_CHECK_RAWDIFF_MODE 17 - -/* GTP need flag or interrupt */ -#define GTP_NO_NEED 0 -#define GTP_NEED_FLAG 1 -#define GTP_NEED_INTERRUPT 2 - -/*****************************End of Part III********************************/ - -void gtp_esd_switch(struct i2c_client *client, int on); - -int gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, - u8 *rxbuf, int len); -int gtp_send_cfg(struct goodix_ts_data *ts); -void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); -void gtp_irq_disable(struct goodix_ts_data *ts); -void gtp_irq_enable(struct goodix_ts_data *ts); - -#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG -s32 init_wr_node(struct i2c_client *client); -void uninit_wr_node(void); -#endif - -u8 gup_init_update_proc(struct goodix_ts_data *ts); -s32 gup_enter_update_mode(struct i2c_client *client); -void gup_leave_update_mode(struct i2c_client *client); -s32 gup_update_proc(void *dir); -extern struct i2c_client *i2c_connect_client; -#endif /* _GOODIX_GT9XX_H_ */ diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c deleted file mode 100644 index 26edab3c87a14..0000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c +++ /dev/null @@ -1,1495 +0,0 @@ -/* drivers/input/touchscreen/gt9xx_update.c - * - * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Latest Version:1.6 - * Author: andrew@goodix.com - * Revision Record: - * V1.0: - * first release. By Andrew, 2012/08/31 - * V1.2: - * add force update,GT9110P pid map. By Andrew, 2012/10/15 - * V1.4: - * 1. add config auto update function; - * 2. modify enter_update_mode; - * 3. add update file cal checksum. - * By Andrew, 2012/12/12 - * V1.6: - * 1. replace guitar_client with i2c_connect_client; - * 2. support firmware header array update. - * By Meta, 2013/03/11 - */ -#include "gt9xx.h" -#include -#include -#include - -#define FIRMWARE_NAME_LEN_MAX 256 - -#define GUP_REG_HW_INFO 0x4220 -#define GUP_REG_FW_MSG 0x41E4 -#define GUP_REG_PID_VID 0x8140 - -#define GOODIX_FIRMWARE_FILE_NAME "_goodix_update_.bin" -#define GOODIX_CONFIG_FILE_NAME "_goodix_config_.cfg" - -#define FW_HEAD_LENGTH 14 -#define FW_SECTION_LENGTH 0x2000 -#define FW_DSP_ISP_LENGTH 0x1000 -#define FW_DSP_LENGTH 0x1000 -#define FW_BOOT_LENGTH 0x800 - -#define PACK_SIZE 256 -#define MAX_FRAME_CHECK_TIME 5 - -#define _bRW_MISCTL__SRAM_BANK 0x4048 -#define _bRW_MISCTL__MEM_CD_EN 0x4049 -#define _bRW_MISCTL__CACHE_EN 0x404B -#define _bRW_MISCTL__TMR0_EN 0x40B0 -#define _rRW_MISCTL__SWRST_B0_ 0x4180 -#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184 -#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190 -#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218 -#define _rRW_MISCTL__BOOT_CTL_ 0x5094 - -#define FAIL 0 -#define SUCCESS 1 - -struct st_fw_head { - u8 hw_info[4]; /* hardware info */ - u8 pid[8]; /* product id */ - u16 vid; /* version id */ -} __packed; - -struct st_update_msg { - u8 force_update; - u8 fw_flag; - bool need_free; - u8 *fw_data; - u32 fw_len; - struct st_fw_head ic_fw_msg; -}; - -static struct st_update_msg update_msg; -u16 show_len; -u16 total_len; -u8 got_file_flag; -u8 searching_file; -/******************************************************* -Function: - Read data from the i2c slave device. -Input: - client: i2c device. - buf[0~1]: read start address. - buf[2~len-1]: read data buffer. - len: GTP_ADDR_LENGTH + read bytes count -Output: - numbers of i2c_msgs to transfer: - 2: succeed, otherwise: failed -*********************************************************/ -static s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len) -{ - s32 ret = -1; - u8 retries = 0; - struct i2c_msg msgs[2] = { - { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = GTP_ADDR_LENGTH, - .buf = &buf[0], - }, - { - .flags = I2C_M_RD, - .addr = client->addr, - .len = len - GTP_ADDR_LENGTH, - .buf = &buf[GTP_ADDR_LENGTH], - }, - }; - - while (retries < 5) { - ret = i2c_transfer(client->adapter, msgs, 2); - if (ret == 2) - break; - retries++; - } - - if (retries == 5) { - dev_err(&client->dev, "I2C read retry limit over.\n"); - ret = -EIO; - } - - return ret; -} - -/******************************************************* -Function: - Write data to the i2c slave device. -Input: - client: i2c device. - buf[0~1]: write start address. - buf[2~len-1]: data buffer - len: GTP_ADDR_LENGTH + write bytes count -Output: - numbers of i2c_msgs to transfer: - 1: succeed, otherwise: failed -*********************************************************/ -s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len) -{ - s32 ret = -1; - u8 retries = 0; - struct i2c_msg msg = { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = len, - .buf = buf, - }; - - while (retries < 5) { - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) - break; - retries++; - } - - if (retries == 5) { - dev_err(&client->dev, "I2C write retry limit over.\n"); - ret = -EIO; - } - - return ret; -} - -static s32 gup_init_panel(struct goodix_ts_data *ts) -{ - struct i2c_client *client = ts->client; - u8 *config_data; - s32 ret = 0; - s32 i = 0; - u8 check_sum = 0; - u8 opr_buf[16]; - u8 sensor_id = 0; - - for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) - if (ts->pdata->config_data_len[i]) - break; - - if (i == GOODIX_MAX_CFG_GROUP) { - sensor_id = 0; - } else { - ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, - &sensor_id, 1); - if (SUCCESS == ret) { - if (sensor_id >= GOODIX_MAX_CFG_GROUP) { - pr_err("Invalid sensor_id(0x%02X), No Config Sent!", - sensor_id); - return -EINVAL; - } - } else { - pr_err("Failed to get sensor_id, No config sent!"); - return -EINVAL; - } - } - - pr_debug("Sensor ID selected: %d", sensor_id); - - if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH || - !ts->pdata->config_data_len[sensor_id]) { - pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP!", - sensor_id); - return -EINVAL; - } - - ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, - &opr_buf[0], 1); - if (ret == SUCCESS) { - pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d", - sensor_id + 1, - ts->pdata->config_data[sensor_id][0], - opr_buf[0]); - - ts->pdata->config_data[sensor_id][0] = opr_buf[0]; - ts->fixed_cfg = 0; - } else { - pr_err("Failed to get ic config version!No config sent!"); - return -EINVAL; - } - - config_data = ts->pdata->config_data[sensor_id]; - ts->config_data = ts->pdata->config_data[sensor_id]; - ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id]; - - pr_debug("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x", - ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); - - config_data[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH; - config_data[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8); - config_data[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT; - config_data[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8); - - if (GTP_INT_TRIGGER == 0) /* RISING */ - config_data[TRIGGER_LOC] &= 0xfe; - else if (GTP_INT_TRIGGER == 1) /* FALLING */ - config_data[TRIGGER_LOC] |= 0x01; - - check_sum = 0; - for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) - check_sum += config_data[i]; - - config_data[ts->gtp_cfg_len] = (~check_sum) + 1; - - ret = gtp_send_cfg(ts); - if (ret < 0) - pr_err("Send config error."); - - ts->config_data = NULL; - ts->gtp_cfg_len = 0; - msleep(20); - return 0; -} - -static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len) -{ - u8 i = 0; - - msg[0] = (addr >> 8) & 0xff; - msg[1] = addr & 0xff; - - for (i = 0; i < 5; i++) - if (gup_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0) - break; - - if (i >= 5) { - pr_err("Read data from 0x%02x%02x failed!", msg[0], msg[1]); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val) -{ - u8 i = 0; - u8 msg[3] = { - (addr >> 8) & 0xff, - addr & 0xff, - val, - }; - - for (i = 0; i < 5; i++) - if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0) - break; - - if (i >= 5) { - pr_err("Set data to 0x%02x%02x failed!", msg[0], msg[1]); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_get_ic_fw_msg(struct i2c_client *client) -{ - s32 ret = -1; - u8 retry = 0; - u8 buf[16]; - u8 i; - - /* step1:get hardware info */ - ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO, - &buf[GTP_ADDR_LENGTH], 4); - if (ret == FAIL) { - pr_err("get hw_info failed,exit"); - return FAIL; - } - - /* buf[2~5]: 00 06 90 00 */ - /* hw_info: 00 90 06 00 */ - for (i = 0; i < 4; i++) - update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i]; - - pr_debug("IC Hardware info:%02x%02x%02x%02x", - update_msg.ic_fw_msg.hw_info[0], - update_msg.ic_fw_msg.hw_info[1], - update_msg.ic_fw_msg.hw_info[2], - update_msg.ic_fw_msg.hw_info[3]); - - /* step2:get firmware message */ - for (retry = 0; retry < 2; retry++) { - ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1); - if (ret == FAIL) { - pr_err("Read firmware message fail."); - return ret; - } - - update_msg.force_update = buf[GTP_ADDR_LENGTH]; - if ((0xBE != update_msg.force_update) && (!retry)) { - pr_info("The check sum in ic is error."); - pr_info("The IC will be updated by force."); - continue; - } - break; - } - pr_debug("IC force update flag:0x%x", update_msg.force_update); - - /* step3:get pid & vid */ - ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID, - &buf[GTP_ADDR_LENGTH], 6); - if (ret == FAIL) { - pr_err("get pid & vid failed,exit"); - return FAIL; - } - - memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid)); - memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4); - pr_debug("IC Product id:%s", update_msg.ic_fw_msg.pid); - - /* GT9XX PID MAPPING - |-----FLASH-----RAM-----| - |------918------918-----| - |------968------968-----| - |------913------913-----| - |------913P-----913P----| - |------927------927-----| - |------927P-----927P----| - |------9110-----9110----| - |------9110P----9111----|*/ - if (update_msg.ic_fw_msg.pid[0] != 0) { - if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) { - pr_debug("IC Mapping Product id:%s", - update_msg.ic_fw_msg.pid); - memcpy(update_msg.ic_fw_msg.pid, "9110P", 5); - } - } - - update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] + - (buf[GTP_ADDR_LENGTH + 5] << 8); - pr_debug("IC version id:%04x", update_msg.ic_fw_msg.vid); - - return SUCCESS; -} - -s32 gup_enter_update_mode(struct i2c_client *client) -{ - s32 ret = -1; - u8 retry = 0; - u8 rd_buf[3]; - struct goodix_ts_data *ts = i2c_get_clientdata(client); - - /* step1:RST output low last at least 2ms */ - gpio_direction_output(ts->pdata->reset_gpio, 0); - msleep(20); - - /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */ - gpio_direction_output(ts->pdata->irq_gpio, - (client->addr == GTP_I2C_ADDRESS_HIGH)); - msleep(20); - - /* step3:RST output high reset guitar */ - gpio_direction_output(ts->pdata->reset_gpio, 1); - - /* 20121211 modify start */ - msleep(20); - while (retry++ < 200) { - /* step4:Hold ss51 & dsp */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_debug("Hold ss51 & dsp I2C error,retry:%d", retry); - continue; - } - - /* step5:Confirm hold */ - ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1); - if (ret <= 0) { - pr_debug("Hold ss51 & dsp I2C error,retry:%d", retry); - continue; - } - if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) { - pr_debug("Hold ss51 & dsp confirm SUCCESS"); - break; - } - pr_debug("Hold ss51 & dsp confirm 0x4180 failed,value:%d", - rd_buf[GTP_ADDR_LENGTH]); - } - if (retry >= 200) { - pr_err("Enter update Hold ss51 failed."); - return FAIL; - } - - /* step6:DSP_CK and DSP_ALU_CK PowerOn */ - ret = gup_set_ic_msg(client, 0x4010, 0x00); - - /* 20121211 modify end */ - return ret; -} - -void gup_leave_update_mode(struct i2c_client *client) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - - gpio_direction_input(ts->pdata->irq_gpio); - pr_debug("reset chip."); - gtp_reset_guitar(ts, 20); -} - -/* Get the correct nvram data - The correct conditions: - 1. the hardware info is the same - 2. the product id is the same - 3. the firmware version in update file is greater than the firmware - version in ic or the check sum in ic is wrong - - Update Conditions: - 1. Same hardware info - 2. Same PID - 3. File PID > IC PID - - Force Update Conditions: - 1. Wrong ic firmware checksum - 2. INVALID IC PID or VID - 3. IC PID == 91XX || File PID == 91XX -*/ - -static u8 gup_enter_update_judge(struct i2c_client *client, - struct st_fw_head *fw_head) -{ - u16 u16_tmp; - s32 i = 0; - - u16_tmp = fw_head->vid; - fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8); - - pr_debug("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0], - fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]); - pr_debug("FILE PID:%s", fw_head->pid); - pr_debug("FILE VID:%04x", fw_head->vid); - - pr_debug("IC HARDWARE INFO:%02x%02x%02x%02x", - update_msg.ic_fw_msg.hw_info[0], - update_msg.ic_fw_msg.hw_info[1], - update_msg.ic_fw_msg.hw_info[2], - update_msg.ic_fw_msg.hw_info[3]); - pr_debug("IC PID:%s", update_msg.ic_fw_msg.pid); - pr_debug("IC VID:%04x", update_msg.ic_fw_msg.vid); - - /* First two conditions */ - if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info, - sizeof(update_msg.ic_fw_msg.hw_info))) { - pr_debug("Get the same hardware info."); - if (update_msg.force_update != 0xBE) { - pr_info("FW chksum error,need enter update."); - return SUCCESS; - } - - /* 20130523 start */ - if (strlen(update_msg.ic_fw_msg.pid) < 3) { - pr_info("Illegal IC pid, need enter update"); - return SUCCESS; - } - for (i = 0; i < 3; i++) { - if ((update_msg.ic_fw_msg.pid[i] < 0x30) || - (update_msg.ic_fw_msg.pid[i] > 0x39)) { - pr_info("Illegal IC pid, out of bound, need enter update"); - return SUCCESS; - } - } - /* 20130523 end */ - - if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, - (strlen(fw_head->pid) < 3 ? 3 : strlen(fw_head->pid)))) || - (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) || - (!memcmp(fw_head->pid, "91XX", 4))) { - if (!memcmp(fw_head->pid, "91XX", 4)) - pr_debug("Force none same pid update mode."); - else - pr_debug("Get the same pid."); - - /* The third condition */ - if (fw_head->vid > update_msg.ic_fw_msg.vid) { - pr_info("Need enter update."); - return SUCCESS; - } - pr_err("Don't meet the third condition."); - pr_err("File VID <= Ic VID, update aborted!"); - } else { - pr_err("File PID != Ic PID, update aborted!"); - } - } else { - pr_err("Different Hardware, update aborted!"); - } - - return FAIL; -} - -static s8 gup_update_config(struct i2c_client *client, - const struct firmware *cfg) -{ - s32 ret = 0; - s32 i = 0; - s32 file_cfg_len = 0; - u32 chip_cfg_len = 0; - s32 count = 0; - u8 *buf; - u8 *file_config; - u8 pid[8]; - u8 high, low; - - if (!cfg || !cfg->data) { - pr_err("No need to upgrade config!"); - return FAIL; - } - - ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6); - if (ret == FAIL) { - pr_err("Read product id & version id fail."); - return FAIL; - } - pid[5] = '\0'; - pr_debug("update cfg get pid:%s", &pid[GTP_ADDR_LENGTH]); - - chip_cfg_len = 186; - if (!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) || - !memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) || - !memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) { - chip_cfg_len = 228; - } - pr_debug("config file ASCII len: %zu", cfg->size); - pr_debug("need config binary len: %u", chip_cfg_len); - if ((cfg->size + 5) < chip_cfg_len * 5) { - pr_err("Config length error"); - return -EINVAL; - } - - buf = devm_kzalloc(&client->dev, cfg->size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - file_config = devm_kzalloc(&client->dev, chip_cfg_len + GTP_ADDR_LENGTH, - GFP_KERNEL); - if (!file_config) - return -ENOMEM; - - pr_debug("Delete illegal character."); - for (i = 0, count = 0; i < cfg->size; i++) { - if (cfg->data[i] == ' ' || cfg->data[i] == '\r' - || cfg->data[i] == '\n') - continue; - buf[count++] = cfg->data[i]; - } - - pr_debug("Ascii to hex."); - file_config[0] = GTP_REG_CONFIG_DATA >> 8; - file_config[1] = GTP_REG_CONFIG_DATA & 0xff; - for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i = i + 5) { - if ((buf[i] == '0') && ((buf[i + 1] == 'x') || - (buf[i + 1] == 'X'))) { - ret = hex2bin(&high, &buf[i + 2], 1); - if (ret) { - pr_err("Failed to convert high address from hex2bin"); - return ret; - } - ret = hex2bin(&low, &buf[i + 3], 1); - if (ret) { - pr_err("Failed to convert low address from hex2bin"); - return ret; - } - - if ((high == 0xFF) || (low == 0xFF)) { - ret = 0; - pr_err("Illegal config file."); - return ret; - } - file_config[file_cfg_len++] = (high<<4) + low; - } else { - ret = 0; - pr_err("Illegal config file."); - return ret; - } - } - - i = 0; - while (i++ < 5) { - ret = gup_i2c_write(client, file_config, file_cfg_len); - if (ret > 0) { - pr_info("Send config SUCCESS."); - break; - } - pr_err("Send config i2c error."); - } - - return ret; -} - -static s32 gup_get_firmware_file(struct i2c_client *client, - struct st_update_msg *msg, u8 *path) -{ - s32 ret; - const struct firmware *fw = NULL; - - ret = request_firmware(&fw, path, &client->dev); - if (ret < 0) { - dev_info(&client->dev, "Cannot get firmware - %s (%d)\n", - path, ret); - return -EEXIST; - } - - dev_dbg(&client->dev, "Config File: %s size: %zu", path, fw->size); - msg->fw_data = - devm_kzalloc(&client->dev, fw->size, GFP_KERNEL); - if (!msg->fw_data) { - dev_err(&client->dev, - "Not enough memory for firmware data."); - release_firmware(fw); - return -ENOMEM; - } - - memcpy(msg->fw_data, fw->data, fw->size); - msg->fw_len = fw->size; - msg->need_free = true; - release_firmware(fw); - return 0; -} - -static u8 gup_check_firmware_name(struct i2c_client *client, - u8 **path_p) -{ - u8 len; - u8 *fname; - - if (!(*path_p)) { - *path_p = GOODIX_FIRMWARE_FILE_NAME; - return 0; - } - - len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX); - if (len >= FIRMWARE_NAME_LEN_MAX) { - dev_err(&client->dev, "firmware name too long!"); - return -EINVAL; - } - - fname = strrchr(*path_p, '/'); - if (fname) { - fname = fname + 1; - *path_p = fname; - } - return 0; -} - -static u8 gup_check_update_file(struct i2c_client *client, - struct st_fw_head *fw_head, u8 *path) -{ - s32 ret = 0; - s32 i = 0; - s32 fw_checksum = 0; - u16 temp; - const struct firmware *fw = NULL; - - ret = request_firmware(&fw, GOODIX_CONFIG_FILE_NAME, &client->dev); - if (ret < 0) { - dev_info(&client->dev, "Cannot get config file - %s (%d)\n", - GOODIX_CONFIG_FILE_NAME, ret); - } else { - dev_dbg(&client->dev, - "Update config File: %s", GOODIX_CONFIG_FILE_NAME); - ret = gup_update_config(client, fw); - if (ret <= 0) - dev_err(&client->dev, "Update config failed."); - release_firmware(fw); - } - - update_msg.need_free = false; - update_msg.fw_len = 0; - - if (gup_check_firmware_name(client, &path)) - goto load_failed; - - if (gup_get_firmware_file(client, &update_msg, path)) - goto load_failed; - - memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH); - - /* check firmware legality */ - fw_checksum = 0; - for (i = 0; i < FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH + - FW_DSP_LENGTH + FW_BOOT_LENGTH; i += 2) { - temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) + - update_msg.fw_data[FW_HEAD_LENGTH + i + 1]; - fw_checksum += temp; - } - - pr_debug("firmware checksum:%x", fw_checksum & 0xFFFF); - if (fw_checksum & 0xFFFF) { - dev_err(&client->dev, "Illegal firmware file."); - goto load_failed; - } - - return SUCCESS; - -load_failed: - if (update_msg.need_free) { - devm_kfree(&client->dev, update_msg.fw_data); - update_msg.need_free = false; - } - return FAIL; -} - -static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, - u16 total_length) -{ - s32 ret = 0; - u16 burn_addr = start_addr; - u16 frame_length = 0; - u16 burn_length = 0; - u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH]; - u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; - u8 retry = 0; - - pr_debug("Begin burn %dk data to addr 0x%x", (total_length / 1024), - start_addr); - while (burn_length < total_length) { - pr_debug("B/T:%04d/%04d", burn_length, total_length); - frame_length = ((total_length - burn_length) > PACK_SIZE) - ? PACK_SIZE : (total_length - burn_length); - wr_buf[0] = (u8)(burn_addr>>8); - rd_buf[0] = wr_buf[0]; - wr_buf[1] = (u8)burn_addr; - rd_buf[1] = wr_buf[1]; - memcpy(&wr_buf[GTP_ADDR_LENGTH], &burn_buf[burn_length], - frame_length); - - for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) { - ret = gup_i2c_write(client, wr_buf, - GTP_ADDR_LENGTH + frame_length); - if (ret <= 0) { - pr_err("Write frame data i2c error."); - continue; - } - ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH + - frame_length); - if (ret <= 0) { - pr_err("Read back frame data i2c error."); - continue; - } - - if (memcmp(&wr_buf[GTP_ADDR_LENGTH], - &rd_buf[GTP_ADDR_LENGTH], frame_length)) { - pr_err("Check frame data fail,not equal."); - continue; - } else { - break; - } - } - if (retry >= MAX_FRAME_CHECK_TIME) { - pr_err("Burn frame data time out,exit."); - return FAIL; - } - burn_length += frame_length; - burn_addr += frame_length; - } - return SUCCESS; -} - -static u8 gup_load_section_file(u8 *buf, u16 offset, u16 length) -{ - if (!update_msg.fw_data || - update_msg.fw_len < FW_HEAD_LENGTH + offset + length) { - pr_err( - "<<-GTP->> cannot load section data. fw_len=%d read end=%d\n", - update_msg.fw_len , - FW_HEAD_LENGTH + offset + length); - return FAIL; - } - memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], length); - - return SUCCESS; -} - -static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src, - u16 start_rd_addr, u16 chk_length) -{ - u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; - s32 ret = 0; - u16 recall_addr = start_rd_addr; - u16 recall_length = 0; - u16 frame_length = 0; - - while (recall_length < chk_length) { - frame_length = ((chk_length - recall_length) > PACK_SIZE) - ? PACK_SIZE : (chk_length - recall_length); - ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length); - if (ret <= 0) { - pr_err("recall i2c error,exit"); - return FAIL; - } - - if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length], - frame_length)) { - pr_err("Recall frame data fail,not equal."); - return FAIL; - } - - recall_length += frame_length; - recall_addr += frame_length; - } - pr_debug("Recall check %dk firmware success.", (chk_length/1024)); - - return SUCCESS; -} - -static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, - u16 start_addr, u8 bank_cmd) -{ - s32 ret = 0; - u8 rd_buf[5]; - - /* step1:hold ss51 & dsp */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail."); - return FAIL; - } - - /* step2:set scramble */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail."); - return FAIL; - } - - /* step3:select bank */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, - (bank_cmd >> 4)&0x0F); - if (ret <= 0) { - pr_err("select bank %d fail.", - (bank_cmd >> 4)&0x0F); - return FAIL; - } - - /* step4:enable accessing code */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); - if (ret <= 0) { - pr_err("enable accessing code fail."); - return FAIL; - } - - /* step5:burn 8k fw section */ - ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("burn fw_section fail."); - return FAIL; - } - - /* step6:hold ss51 & release dsp */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); - if (ret <= 0) { - pr_err("hold ss51 & release dsp fail."); - return FAIL; - } - /* must delay */ - msleep(20); - - /* step7:send burn cmd to move data to flash from sram */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f); - if (ret <= 0) { - pr_err("send burn cmd fail."); - return FAIL; - } - pr_debug("Wait for the burn is complete."); - do { - ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); - if (ret <= 0) { - pr_err("Get burn state fail"); - return FAIL; - } - msleep(20); - } while (rd_buf[GTP_ADDR_LENGTH]); - - /* step8:select bank */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, - (bank_cmd >> 4)&0x0F); - if (ret <= 0) { - pr_err("select bank %d fail.", - (bank_cmd >> 4)&0x0F); - return FAIL; - } - - /* step9:enable accessing code */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); - if (ret <= 0) { - pr_err("enable accessing code fail."); - return FAIL; - } - - /* step10:recall 8k fw section */ - ret = gup_recall_check(client, fw_section, start_addr, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("recall check 8k firmware fail."); - return FAIL; - } - - /* step11:disable accessing code */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00); - if (ret <= 0) { - pr_err("disable accessing code fail."); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_burn_dsp_isp(struct i2c_client *client) -{ - s32 ret = 0; - u8 *fw_dsp_isp = NULL; - - pr_debug("Begin burn dsp isp."); - - /* step1:alloc memory */ - pr_debug("step1:alloc memory"); - fw_dsp_isp = devm_kzalloc(&client->dev, FW_DSP_ISP_LENGTH, GFP_KERNEL); - if (fw_dsp_isp == NULL) - return FAIL; - - /* step2:load dsp isp file data */ - pr_debug("step2:load dsp isp file data"); - ret = gup_load_section_file(fw_dsp_isp, (4 * FW_SECTION_LENGTH + - FW_DSP_LENGTH + FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH); - if (ret == FAIL) { - pr_err("load firmware dsp_isp fail."); - return FAIL; - } - - /* step3:disable wdt,clear cache enable */ - pr_debug("step3:disable wdt,clear cache enable"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00); - if (ret <= 0) { - pr_err("disable wdt fail."); - return FAIL; - } - ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00); - if (ret <= 0) { - pr_err("clear cache enable fail."); - return FAIL; - } - - /* step4:hold ss51 & dsp */ - pr_debug("step4:hold ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail."); - return FAIL; - } - - /* step5:set boot from sram */ - pr_debug("step5:set boot from sram"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); - if (ret <= 0) { - pr_err("set boot from sram fail."); - return FAIL; - } - - /* step6:software reboot */ - pr_debug("step6:software reboot"); - ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); - if (ret <= 0) { - pr_err("software reboot fail."); - return FAIL; - } - - /* step7:select bank2 */ - pr_debug("step7:select bank2"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02); - if (ret <= 0) { - pr_err("select bank2 fail."); - return FAIL; - } - - /* step8:enable accessing code */ - pr_debug("step8:enable accessing code"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); - if (ret <= 0) { - pr_err("enable accessing code fail."); - return FAIL; - } - - /* step9:burn 4k dsp_isp */ - pr_debug("step9:burn 4k dsp_isp"); - ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH); - if (ret == FAIL) { - pr_err("burn dsp_isp fail."); - return FAIL; - } - - /* step10:set scramble */ - pr_debug("step10:set scramble"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail."); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_burn_fw_ss51(struct i2c_client *client) -{ - u8 *fw_ss51 = NULL; - s32 ret = 0; - - pr_debug("Begin burn ss51 firmware."); - - /* step1:alloc memory */ - pr_debug("step1:alloc memory"); - fw_ss51 = devm_kzalloc(&client->dev, FW_SECTION_LENGTH, GFP_KERNEL); - if (fw_ss51 == NULL) - return FAIL; - - /* step2:load ss51 firmware section 1 file data */ - pr_debug("step2:load ss51 firmware section 1 file data"); - ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("load ss51 firmware section 1 fail."); - return FAIL; - } - - /* step3:clear control flag */ - pr_debug("step3:clear control flag"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); - if (ret <= 0) { - pr_err("clear control flag fail."); - return FAIL; - } - - /* step4:burn ss51 firmware section 1 */ - pr_debug("step4:burn ss51 firmware section 1"); - ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 1 fail."); - return FAIL; - } - - /* step5:load ss51 firmware section 2 file data */ - pr_debug("step5:load ss51 firmware section 2 file data"); - ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail."); - return FAIL; - } - - /* step6:burn ss51 firmware section 2 */ - pr_debug("step6:burn ss51 firmware section 2"); - ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 2 fail."); - return FAIL; - } - - /* step7:load ss51 firmware section 3 file data */ - pr_debug("step7:load ss51 firmware section 3 file data"); - ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("load ss51 firmware section 3 fail."); - return FAIL; - } - - /* step8:burn ss51 firmware section 3 */ - pr_debug("step8:burn ss51 firmware section 3"); - ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 3 fail."); - return FAIL; - } - - /* step9:load ss51 firmware section 4 file data */ - pr_debug("step9:load ss51 firmware section 4 file data"); - ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("load ss51 firmware section 4 fail."); - return FAIL; - } - - /* step10:burn ss51 firmware section 4 */ - pr_debug("step10:burn ss51 firmware section 4"); - ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 4 fail."); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_burn_fw_dsp(struct i2c_client *client) -{ - s32 ret = 0; - u8 *fw_dsp = NULL; - u8 rd_buf[5]; - - pr_debug("Begin burn dsp firmware."); - /* step1:alloc memory */ - pr_debug("step1:alloc memory"); - fw_dsp = devm_kzalloc(&client->dev, FW_DSP_LENGTH, GFP_KERNEL); - if (fw_dsp == NULL) - return FAIL; - - /* step2:load firmware dsp */ - pr_debug("step2:load firmware dsp"); - ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH); - if (ret == FAIL) { - pr_err("load firmware dsp fail."); - return ret; - } - - /* step3:select bank3 */ - pr_debug("step3:select bank3"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); - if (ret <= 0) { - pr_err("select bank3 fail."); - return FAIL; - } - - /* Step4:hold ss51 & dsp */ - pr_debug("step4:hold ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail."); - return FAIL; - } - - /* step5:set scramble */ - pr_debug("step5:set scramble"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail."); - return FAIL; - } - - /* step6:release ss51 & dsp */ - pr_debug("step6:release ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); - if (ret <= 0) { - pr_err("release ss51 & dsp fail."); - return FAIL; - } - /* must delay */ - msleep(20); - - /* step7:burn 4k dsp firmware */ - pr_debug("step7:burn 4k dsp firmware"); - ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH); - if (ret == FAIL) { - pr_err("[burn_fw_dsp]burn fw_section fail."); - return ret; - } - - /* step8:send burn cmd to move data to flash from sram */ - pr_debug("step8:send burn cmd to move data to flash from sram"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05); - if (ret <= 0) { - pr_err("send burn cmd fail."); - return ret; - } - pr_debug("Wait for the burn is complete."); - do { - ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); - if (ret <= 0) { - pr_err("Get burn state fail"); - return ret; - } - msleep(20); - } while (rd_buf[GTP_ADDR_LENGTH]); - - /* step9:recall check 4k dsp firmware */ - pr_debug("step9:recall check 4k dsp firmware"); - ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH); - if (ret == FAIL) { - pr_err("recall check 4k dsp firmware fail."); - return ret; - } - - return SUCCESS; -} - -static u8 gup_burn_fw_boot(struct i2c_client *client) -{ - s32 ret = 0; - u8 *fw_boot = NULL; - u8 rd_buf[5]; - - pr_debug("Begin burn bootloader firmware."); - - /* step1:Alloc memory */ - pr_debug("step1:Alloc memory"); - fw_boot = devm_kzalloc(&client->dev, FW_BOOT_LENGTH, GFP_KERNEL); - if (fw_boot == NULL) - return FAIL; - - /* step2:load firmware bootloader */ - pr_debug("step2:load firmware bootloader"); - ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH + - FW_DSP_LENGTH), FW_BOOT_LENGTH); - if (ret == FAIL) { - pr_err("load firmware dsp fail."); - return ret; - } - - /* step3:hold ss51 & dsp */ - pr_debug("step3:hold ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail."); - return FAIL; - } - - /* step4:set scramble */ - pr_debug("step4:set scramble"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail."); - return FAIL; - } - - /* step5:release ss51 & dsp */ - pr_debug("step5:release ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); - if (ret <= 0) { - pr_err("release ss51 & dsp fail."); - return FAIL; - } - /* must delay */ - msleep(20); - - /* step6:select bank3 */ - pr_debug("step6:select bank3"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); - if (ret <= 0) { - pr_err("select bank3 fail."); - return FAIL; - } - - /* step7:burn 2k bootloader firmware */ - pr_debug("step7:burn 2k bootloader firmware"); - ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH); - if (ret == FAIL) { - pr_err("burn fw_section fail."); - return ret; - } - - /* step7:send burn cmd to move data to flash from sram */ - pr_debug("step7:send burn cmd to flash data from sram"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06); - if (ret <= 0) { - pr_err("send burn cmd fail."); - return ret; - } - pr_debug("Wait for the burn is complete."); - do { - ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); - if (ret <= 0) { - pr_err("Get burn state fail"); - return ret; - } - msleep(20); - } while (rd_buf[GTP_ADDR_LENGTH]); - - /* step8:recall check 2k bootloader firmware */ - pr_debug("step8:recall check 2k bootloader firmware"); - ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH); - if (ret == FAIL) { - pr_err("recall check 4k dsp firmware fail."); - return ret; - } - - /* step9:enable download DSP code */ - pr_debug("step9:enable download DSP code "); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99); - if (ret <= 0) { - pr_err("enable download DSP code fail."); - return FAIL; - } - - /* step10:release ss51 & hold dsp */ - pr_debug("step10:release ss51 & hold dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08); - if (ret <= 0) { - pr_err("release ss51 & hold dsp fail."); - return FAIL; - } - - return SUCCESS; -} - -s32 gup_update_proc(void *dir) -{ - s32 ret = 0; - u8 retry = 0; - struct st_fw_head fw_head; - struct goodix_ts_data *ts = NULL; - - pr_debug("Begin update."); - - if (!i2c_connect_client) { - pr_err("No i2c connect client for %s\n", __func__); - return -EIO; - } - - show_len = 1; - total_len = 100; - - ts = i2c_get_clientdata(i2c_connect_client); - - if (searching_file) { - /* exit .bin update file searching */ - searching_file = 0; - pr_info("Exiting searching .bin update file."); - /* wait for auto update quitted completely */ - while ((show_len != 200) && (show_len != 100)) - msleep(100); - } - - ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir); - if (ret == FAIL) { - pr_err("check update file fail."); - goto file_fail; - } - - /* gtp_reset_guitar(i2c_connect_client, 20); */ - ret = gup_get_ic_fw_msg(i2c_connect_client); - if (ret == FAIL) { - pr_err("get ic message fail."); - goto file_fail; - } - - if (ts->force_update) { - dev_dbg(&ts->client->dev, "Enter force update."); - } else { - ret = gup_enter_update_judge(ts->client, &fw_head); - if (ret == FAIL) { - dev_err(&ts->client->dev, - "Check *.bin file fail."); - goto file_fail; - } - } - - ts->enter_update = 1; - gtp_irq_disable(ts); -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_OFF); -#endif - ret = gup_enter_update_mode(i2c_connect_client); - if (ret == FAIL) { - pr_err("enter update mode fail."); - goto update_fail; - } - - while (retry++ < 5) { - show_len = 10; - total_len = 100; - ret = gup_burn_dsp_isp(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn dsp isp fail."); - continue; - } - - show_len += 10; - ret = gup_burn_fw_ss51(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn ss51 firmware fail."); - continue; - } - - show_len += 40; - ret = gup_burn_fw_dsp(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn dsp firmware fail."); - continue; - } - - show_len += 20; - ret = gup_burn_fw_boot(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn bootloader fw fail."); - continue; - } - show_len += 10; - pr_info("UPDATE SUCCESS."); - break; - } - if (retry >= 5) { - pr_err("retry timeout,UPDATE FAIL."); - goto update_fail; - } - - pr_debug("leave update mode."); - gup_leave_update_mode(i2c_connect_client); - - msleep(100); - - if (ts->fw_error) { - pr_info("firmware error auto update, resent config!"); - gup_init_panel(ts); - } - show_len = 100; - total_len = 100; - ts->enter_update = 0; - gtp_irq_enable(ts); - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_ON); -#endif - if (update_msg.need_free) { - devm_kfree(&ts->client->dev, update_msg.fw_data); - update_msg.need_free = false; - } - - return SUCCESS; - -update_fail: - ts->enter_update = 0; - gtp_irq_enable(ts); - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_ON); -#endif - -file_fail: - show_len = 200; - total_len = 100; - if (update_msg.need_free) { - devm_kfree(&ts->client->dev, update_msg.fw_data); - update_msg.need_free = false; - } - return FAIL; -} - -static void gup_update_work(struct work_struct *work) -{ - if (gup_update_proc(NULL) == FAIL) - pr_err("Goodix update work fail!\n"); -} - -u8 gup_init_update_proc(struct goodix_ts_data *ts) -{ - dev_dbg(&ts->client->dev, "Ready to run update work."); - - INIT_DELAYED_WORK(&ts->goodix_update_work, gup_update_work); - schedule_delayed_work(&ts->goodix_update_work, - msecs_to_jiffies(3000)); - - return 0; -} diff --git a/drivers/input/touchscreen/nt36672/Makefile b/drivers/input/touchscreen/nt36672/Makefile new file mode 100755 index 0000000000000..f0522b15b5dfe --- /dev/null +++ b/drivers/input/touchscreen/nt36672/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Novatek NT36xxx touchscreen driver. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_NT36672) += nt36xxx.o nt36xxx_fw_update.o nt36xxx_ext_proc.o nt36xxx_mp_ctrlram.o diff --git a/drivers/input/touchscreen/nt36672/nt36xxx.c b/drivers/input/touchscreen/nt36672/nt36xxx.c new file mode 100755 index 0000000000000..d5d094a00d4e9 --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nt36xxx.c @@ -0,0 +1,1970 @@ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * $Revision: 15234 $ + * $Date: 2017-08-09 11:34:54 +0800 (週三, 09 八月 2017) $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_FB) +#include +#include +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif + +#include "nt36xxx.h" +#if NVT_TOUCH_ESD_PROTECT +#include +#endif + +/*Add by HQ-zmc [Date: 2017-12-18 11:34:22]*/ +#include "../../../video/msm/mdss/mdss_dsi.h" + +#if NVT_TOUCH_ESD_PROTECT +static struct delayed_work nvt_esd_check_work; +static struct workqueue_struct *nvt_esd_check_wq; +static unsigned long irq_timer; +uint8_t esd_check = false; +uint8_t esd_retry = 0; +uint8_t esd_retry_max = 5; +#endif + +#if NVT_TOUCH_EXT_PROC +extern int32_t nvt_extra_proc_init(void); +#endif + +#if NVT_TOUCH_MP +extern int32_t nvt_mp_proc_init(void); +#endif + +struct nvt_ts_data *ts; + +static struct workqueue_struct *nvt_wq; + +#if BOOT_UPDATE_FIRMWARE +static struct workqueue_struct *nvt_fwu_wq; +extern void Boot_Update_Firmware(struct work_struct *work); +extern int32_t Init_BootLoader(void); +extern int32_t Resume_PD(void); +#endif + +#if defined(CONFIG_FB) +static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void nvt_ts_early_suspend(struct early_suspend *h); +static void nvt_ts_late_resume(struct early_suspend *h); +#endif + +static const struct nvt_ts_mem_map NT36772_memory_map = { + .EVENT_BUF_ADDR = 0x11E00, + .RAW_PIPE0_ADDR = 0x10000, + .RAW_PIPE0_Q_ADDR = 0, + .RAW_PIPE1_ADDR = 0x12000, + .RAW_PIPE1_Q_ADDR = 0, + .BASELINE_ADDR = 0x10E70, + .BASELINE_Q_ADDR = 0, + .BASELINE_BTN_ADDR = 0x12E70, + .BASELINE_BTN_Q_ADDR = 0, + .DIFF_PIPE0_ADDR = 0x10830, + .DIFF_PIPE0_Q_ADDR = 0, + .DIFF_PIPE1_ADDR = 0x12830, + .DIFF_PIPE1_Q_ADDR = 0, + .RAW_BTN_PIPE0_ADDR = 0x10E60, + .RAW_BTN_PIPE0_Q_ADDR = 0, + .RAW_BTN_PIPE1_ADDR = 0x12E60, + .RAW_BTN_PIPE1_Q_ADDR = 0, + .DIFF_BTN_PIPE0_ADDR = 0x10E68, + .DIFF_BTN_PIPE0_Q_ADDR = 0, + .DIFF_BTN_PIPE1_ADDR = 0x12E68, + .DIFF_BTN_PIPE1_Q_ADDR = 0, + .READ_FLASH_CHECKSUM_ADDR = 0x14000, + .RW_FLASH_DATA_ADDR = 0x14002, +}; + +static const struct nvt_ts_mem_map NT36525_memory_map = { + .EVENT_BUF_ADDR = 0x11A00, + .RAW_PIPE0_ADDR = 0x10000, + .RAW_PIPE0_Q_ADDR = 0, + .RAW_PIPE1_ADDR = 0x12000, + .RAW_PIPE1_Q_ADDR = 0, + .BASELINE_ADDR = 0x10B08, + .BASELINE_Q_ADDR = 0, + .BASELINE_BTN_ADDR = 0x12B08, + .BASELINE_BTN_Q_ADDR = 0, + .DIFF_PIPE0_ADDR = 0x1064C, + .DIFF_PIPE0_Q_ADDR = 0, + .DIFF_PIPE1_ADDR = 0x1264C, + .DIFF_PIPE1_Q_ADDR = 0, + .RAW_BTN_PIPE0_ADDR = 0x10634, + .RAW_BTN_PIPE0_Q_ADDR = 0, + .RAW_BTN_PIPE1_ADDR = 0x12634, + .RAW_BTN_PIPE1_Q_ADDR = 0, + .DIFF_BTN_PIPE0_ADDR = 0x10AFC, + .DIFF_BTN_PIPE0_Q_ADDR = 0, + .DIFF_BTN_PIPE1_ADDR = 0x12AFC, + .DIFF_BTN_PIPE1_Q_ADDR = 0, + .READ_FLASH_CHECKSUM_ADDR = 0x14000, + .RW_FLASH_DATA_ADDR = 0x14002, +}; + +static const struct nvt_ts_mem_map NT36870_memory_map = { + .EVENT_BUF_ADDR = 0x25000, + .RAW_PIPE0_ADDR = 0x20000, + .RAW_PIPE0_Q_ADDR = 0x204C8, + .RAW_PIPE1_ADDR = 0x23000, + .RAW_PIPE1_Q_ADDR = 0x234C8, + .BASELINE_ADDR = 0x21350, + .BASELINE_Q_ADDR = 0x21818, + .BASELINE_BTN_ADDR = 0x24350, + .BASELINE_BTN_Q_ADDR = 0x24358, + .DIFF_PIPE0_ADDR = 0x209B0, + .DIFF_PIPE0_Q_ADDR = 0x20E78, + .DIFF_PIPE1_ADDR = 0x239B0, + .DIFF_PIPE1_Q_ADDR = 0x23E78, + .RAW_BTN_PIPE0_ADDR = 0x20990, + .RAW_BTN_PIPE0_Q_ADDR = 0x20998, + .RAW_BTN_PIPE1_ADDR = 0x23990, + .RAW_BTN_PIPE1_Q_ADDR = 0x23998, + .DIFF_BTN_PIPE0_ADDR = 0x21340, + .DIFF_BTN_PIPE0_Q_ADDR = 0x21348, + .DIFF_BTN_PIPE1_ADDR = 0x24340, + .DIFF_BTN_PIPE1_Q_ADDR = 0x24348, + .READ_FLASH_CHECKSUM_ADDR = 0x24000, + .RW_FLASH_DATA_ADDR = 0x24002, +}; + +static const struct nvt_ts_mem_map NT36676F_memory_map = { + .EVENT_BUF_ADDR = 0x11A00, + .RAW_PIPE0_ADDR = 0x10000, + .RAW_PIPE0_Q_ADDR = 0, + .RAW_PIPE1_ADDR = 0x12000, + .RAW_PIPE1_Q_ADDR = 0, + .BASELINE_ADDR = 0x10B08, + .BASELINE_Q_ADDR = 0, + .BASELINE_BTN_ADDR = 0x12B08, + .BASELINE_BTN_Q_ADDR = 0, + .DIFF_PIPE0_ADDR = 0x1064C, + .DIFF_PIPE0_Q_ADDR = 0, + .DIFF_PIPE1_ADDR = 0x1264C, + .DIFF_PIPE1_Q_ADDR = 0, + .RAW_BTN_PIPE0_ADDR = 0x10634, + .RAW_BTN_PIPE0_Q_ADDR = 0, + .RAW_BTN_PIPE1_ADDR = 0x12634, + .RAW_BTN_PIPE1_Q_ADDR = 0, + .DIFF_BTN_PIPE0_ADDR = 0x10AFC, + .DIFF_BTN_PIPE0_Q_ADDR = 0, + .DIFF_BTN_PIPE1_ADDR = 0x12AFC, + .DIFF_BTN_PIPE1_Q_ADDR = 0, + .READ_FLASH_CHECKSUM_ADDR = 0x14000, + .RW_FLASH_DATA_ADDR = 0x14002, +}; + +#define NVT_ID_BYTE_MAX 6 +struct nvt_ts_trim_id_table { + uint8_t id[NVT_ID_BYTE_MAX]; + uint8_t mask[NVT_ID_BYTE_MAX]; + const struct nvt_ts_mem_map *mmap; + uint8_t carrier_system; +}; + +static const struct nvt_ts_trim_id_table trim_id_table[] = { + {.id = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0x55, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36772_memory_map, .carrier_system = 0}, + {.id = {0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36525_memory_map, .carrier_system = 0}, + {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x68, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36870_memory_map, .carrier_system = 1}, + {.id = {0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1}, + .mmap = &NT36676F_memory_map, .carrier_system = 0} +}; + +#if TOUCH_KEY_NUM > 0 +const uint16_t touch_key_array[TOUCH_KEY_NUM] = { + KEY_BACK, + KEY_HOME, + KEY_MENU +}; +#endif + +bool NVT_gesture_func_on = true; +#if WAKEUP_GESTURE +/*add by HQ-zmc 20170923*/ +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 + +/*Add by HQ-zmc [Date: 2017-11-14 20:53:50]*/ +/*DOUBLE_CLICK ID in register is 15, but the +system only recognises 143*/ +#define GESTURE_DOUBLE_CLICK 143 +#define REGISTER_DOUBLE_CLICK 15 + +const uint16_t gesture_key_array[] = { + GESTURE_DOUBLE_CLICK, +}; + +int NVT_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + + unsigned int input ; + if (type == EV_SYN && code == SYN_CONFIG) + { + if (value == WAKEUP_OFF){ + NVT_gesture_func_on = false; + input = 0; + }else if (value == WAKEUP_ON){ + NVT_gesture_func_on = true; + input = 1; + } + } + return 0; +} + +#endif + +static uint8_t bTouchIsAwake; + +/******************************************************* +Description: + Novatek touchscreen i2c read function. + +return: + Executive outcomes. 2---succeed. -5---I/O error +*******************************************************/ +int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len) +{ + struct i2c_msg msgs[2]; + int32_t ret = -1; + int32_t retries = 0; + + msgs[0].flags = !I2C_M_RD; + msgs[0].addr = address; + msgs[0].len = 1; + msgs[0].buf = &buf[0]; + + msgs[1].flags = I2C_M_RD; + msgs[1].addr = address; + msgs[1].len = len - 1; + msgs[1].buf = &buf[1]; + + while (retries < 5) { + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) break; + retries++; + } + + if (unlikely(retries == 5)) { + NVT_ERR("error, ret=%d\n", ret); + ret = -EIO; + } + + return ret; +} + +/******************************************************* +Description: + Novatek touchscreen i2c dummy read function. + +return: + Executive outcomes. 1---succeed. -5---I/O error +*******************************************************/ +int32_t CTP_I2C_READ_DUMMY(struct i2c_client *client, uint16_t address) +{ + uint8_t buf[8] = {0}; + int32_t ret = -1; + + ret = CTP_I2C_READ(client, address, buf, 2); + if (ret < 0) + NVT_ERR("CTP_I2C_READ_DUMMY failed.(%d)\n", ret); + + return ret; +} + +/******************************************************* +Description: + Novatek touchscreen i2c write function. + +return: + Executive outcomes. 1---succeed. -5---I/O error +*******************************************************/ +int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len) +{ + struct i2c_msg msg; + int32_t ret = -1; + int32_t retries = 0; + + msg.flags = !I2C_M_RD; + msg.addr = address; + msg.len = len; + msg.buf = buf; + + while (retries < 5) { + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret == 1) break; + retries++; + } + + if (unlikely(retries == 5)) { + NVT_ERR("error, ret=%d\n", ret); + ret = -EIO; + } + + return ret; +} + + +/******************************************************* +Description: + Novatek touchscreen reset MCU then into idle mode + function. + +return: + n.a. +*******************************************************/ +void nvt_sw_reset_idle(void) +{ + uint8_t buf[4] = {0}; + + + buf[0] = 0x00; + buf[1] = 0xA5; + CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + + msleep(15); +} + +/******************************************************* +Description: + Novatek touchscreen reset MCU (boot) function. + +return: + n.a. +*******************************************************/ +void nvt_bootloader_reset(void) +{ + uint8_t buf[8] = {0}; + + //---write i2c cmds to reset--- + buf[0] = 0x00; + buf[1] = 0x69; + CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + + + msleep(35); +} + +/******************************************************* +Description: + Novatek touchscreen clear FW status function. + +return: + Executive outcomes. 0---succeed. -1---fail. +*******************************************************/ +int32_t nvt_clear_fw_status(void) +{ + uint8_t buf[8] = {0}; + int32_t i = 0; + const int32_t retry = 20; + + for (i = 0; i < retry; i++) { + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; + buf[1] = 0x00; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + + + buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; + buf[1] = 0xFF; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2); + + if (buf[1] == 0x00) + break; + + msleep(10); + } + + if (i >= retry) { + NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]); + return -1; + } else { + return 0; + } +} + +/******************************************************* +Description: + Novatek touchscreen check FW status function. + +return: + Executive outcomes. 0---succeed. -1---failed. +*******************************************************/ +int32_t nvt_check_fw_status(void) +{ + uint8_t buf[8] = {0}; + int32_t i = 0; + const int32_t retry = 50; + + for (i = 0; i < retry; i++) { + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; + buf[1] = 0x00; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2); + + if ((buf[1] & 0xF0) == 0xA0) + break; + + msleep(10); + } + + if (i >= retry) { + NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]); + return -1; + } else { + return 0; + } +} + +/******************************************************* +Description: + Novatek touchscreen check FW reset state function. + +return: + Executive outcomes. 0---succeed. -1---failed. +*******************************************************/ +int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state) +{ + uint8_t buf[8] = {0}; + int32_t ret = 0; + int32_t retry = 0; + + while (1) { + msleep(10); + + //---read reset state--- + buf[0] = EVENT_MAP_RESET_COMPLETE; + buf[1] = 0x00; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 6); + + if ((buf[1] >= check_reset_state) && (buf[1] < 0xFF)) { + ret = 0; + break; + } + + retry++; + if (check_reset_state <= RESET_STATE_REK) { + if (unlikely(retry > 50)) { + NVT_ERR("error, retry=%d, buf[1]=0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", retry, buf[1], buf[2], buf[3], buf[4], buf[5]); + ret = -1; + break; + } + } else { + if (unlikely(retry > 100)) { + NVT_ERR("error, retry=%d, buf[1]=0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", retry, buf[1], buf[2], buf[3], buf[4], buf[5]); + ret = -1; + break; + } + } + + } + + return ret; +} + +/******************************************************* +Description: + Novatek touchscreen get novatek project id information + function. + +return: + Executive outcomes. 0---success. -1---fail. +*******************************************************/ +int32_t nvt_read_pid(void) +{ + uint8_t buf[3] = {0}; + int32_t ret = 0; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_PROJECTID; + buf[1] = 0x00; + buf[2] = 0x00; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 3); + + ts->nvt_pid = (buf[2] << 8) + buf[1]; + + + NVT_LOG("PID=%04X\n", ts->nvt_pid); + + return ret; +} + +/******************************************************* +Description: + Novatek touchscreen get firmware related information + function. + +return: + Executive outcomes. 0---success. -1---fail. +*******************************************************/ +int32_t nvt_get_fw_info(void) +{ + uint8_t buf[64] = {0}; + uint32_t retry_count = 0; + int32_t ret = 0; + +info_retry: + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_FWINFO; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 17); + ts->fw_ver = buf[1]; + ts->x_num = buf[3]; + ts->y_num = buf[4]; + ts->abs_x_max = (uint16_t)((buf[5] << 8) | buf[6]); + ts->abs_y_max = (uint16_t)((buf[7] << 8) | buf[8]); + ts->max_button_num = buf[11]; + + + if ((buf[1] + buf[2]) != 0xFF) { + NVT_ERR("FW info is broken! fw_ver=0x%02X, ~fw_ver=0x%02X\n", buf[1], buf[2]); + ts->fw_ver = 0; + ts->x_num = 18; + ts->y_num = 32; + ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH; + ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT; + ts->max_button_num = TOUCH_KEY_NUM; + + if (retry_count < 3) { + retry_count++; + NVT_ERR("retry_count=%d\n", retry_count); + goto info_retry; + } else { + NVT_ERR("Set default fw_ver=%d, x_num=%d, y_num=%d, \ + abs_x_max=%d, abs_y_max=%d, max_button_num=%d!\n", + ts->fw_ver, ts->x_num, ts->y_num, + ts->abs_x_max, ts->abs_y_max, ts->max_button_num); + ret = -1; + } + } else { + ret = 0; + } + + + nvt_read_pid(); + + return ret; +} + +int32_t nvt_get_oem_data(uint8_t *data, uint32_t flash_address, int32_t size) +{ + uint8_t buf[64] = {0}; + uint8_t tmp_data[512] = {0}; + int32_t count_256 = 0; + uint32_t cur_flash_addr = 0; + uint32_t cur_sram_addr = 0; + uint16_t checksum_get = 0; + uint16_t checksum_cal = 0; + int32_t i = 0; + int32_t j = 0; + int32_t ret = 0; + int32_t retry = 0; + + NVT_LOG("++\n"); + + + if (size % 256) + count_256 = size / 256 + 1; + else + count_256 = size / 256; + +get_oem_data_retry: + nvt_sw_reset_idle(); + + + ret = Init_BootLoader(); + if (ret < 0) { + goto get_oem_data_out; + } + + + ret = Resume_PD(); + if (ret < 0) { + goto get_oem_data_out; + } + + + buf[0] = 0x00; + buf[1] = 0x35; + CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + msleep(10); + + for (i = 0; i < count_256; i++) { + cur_flash_addr = flash_address + i * 256; + // Step 4: Flash Read Command + buf[0] = 0x00; + buf[1] = 0x03; + buf[2] = ((cur_flash_addr >> 16) & 0xFF); + buf[3] = ((cur_flash_addr >> 8) & 0xFF); + buf[4] = (cur_flash_addr & 0xFF); + buf[5] = 0x00; + buf[6] = 0xFF; + CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7); + msleep(10); + // Check 0xAA (Read Command) + buf[0] = 0x00; + buf[2] = 0x00; + CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (buf[1] != 0xAA) { + NVT_ERR("Check 0xAA (Read Command) error!! status=0x%02X\n", buf[1]); + ret = -1; + goto get_oem_data_out; + } + msleep(10); + + // Step 5: Read Data and Checksum + for (j = 0; j < ((256 / 32) + 1); j++) { + cur_sram_addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR + j * 32; + buf[0] = 0xFF; + buf[1] = (cur_sram_addr >> 16) & 0xFF; + buf[2] = (cur_sram_addr >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + + buf[0] = cur_sram_addr & 0xFF; + CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 33); + + memcpy(tmp_data + j * 32, buf + 1, 32); + } + + checksum_get = (uint16_t)((tmp_data[1] << 8) | tmp_data[0]); + + checksum_cal = (uint16_t)((cur_flash_addr >> 16) & 0xFF) + (uint16_t)((cur_flash_addr >> 8) & 0xFF) + (cur_flash_addr & 0xFF) + 0x00 + 0xFF; + for (j = 0; j < 256; j++) { + checksum_cal += tmp_data[j + 2]; + } + checksum_cal = 65535 - checksum_cal + 1; + + + if (checksum_get != checksum_cal) { + if (retry < 3) { + retry++; + goto get_oem_data_retry; + } else { + NVT_ERR("Checksum not match error! checksum_get=0x%04X, checksum_cal=0x%04X, i=%d\n", checksum_get, checksum_cal, i); + ret = -2; + goto get_oem_data_out; + } + } + + + if ((i + 1) * 256 > size) { + memcpy(data + i * 256, tmp_data + 2, size - i * 256); + } else { + memcpy(data + i * 256, tmp_data + 2, 256); + } + } + +#if 0 + for (i = 0; i < size; i++) { + if (i % 16 == 0) + printk("\n"); + printk("%02X ", data[i]); + } + printk("\n"); +#endif + +get_oem_data_out: + nvt_bootloader_reset(); + nvt_check_fw_reset_state(RESET_STATE_INIT); + + NVT_LOG("--\n"); + + return ret; +} + +char nvt_tp_lockdown_info[128]; +int32_t nvt_get_xiaomi_lockdown_info(void) +{ + uint8_t data_buf[8] = {0}; + int ret = 0; + char temp[40] = {0}; + + ret = nvt_get_oem_data(data_buf, 0x1E000, 8); + + if (ret < 0) { + NVT_ERR("get oem data failed!\n"); + } else { + NVT_LOG("The maker of Touch Panel & CG Lamination: 0x%02X\n", data_buf[0]); + NVT_LOG("Display maker: 0x%02X\n", data_buf[1]); + NVT_LOG("CG ink color: 0x%02X\n", data_buf[2]); + NVT_LOG("HW version: 0x%02X\n", data_buf[3]); + NVT_LOG("Project ID: 0x%04X\n", ((data_buf[4] << 8) | data_buf[5])); + NVT_LOG("CG maker: 0x%02X\n", data_buf[6]); + NVT_LOG("Reservation byte: 0x%02X\n", data_buf[7]); + + sprintf(temp, "%02x%02x%02x%02x%02x%02x%02x%02x", data_buf[0], data_buf[1], data_buf[2], data_buf[3], data_buf[4], data_buf[5], data_buf[6], data_buf[7]); + printk("tp_lockdown info : %s\n", temp); + strcpy(nvt_tp_lockdown_info, temp); + } + + return ret; +} + +static char tp_info_summary[80] = ""; +static void nvt_register_hw_info(void) +{ + char tp_temp_info[80]; + + strcpy(tp_info_summary, "[Vendor]CSOT, [IC]NT36672(Novatek), [FW]Ver"); + sprintf(tp_temp_info, "%02x", ts->fw_ver); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + hq_regiser_hw_info(HWID_CTP, tp_info_summary); +} +/******************************************************* + Create Device Node (Proc Entry) +*******************************************************/ +#if NVT_TOUCH_PROC +static struct proc_dir_entry *NVT_proc_entry; +#define DEVICE_NAME "NVTflash" + +/******************************************************* +Description: + Novatek touchscreen /proc/NVTflash read function. + +return: + Executive outcomes. 2---succeed. -5,-14---failed. +*******************************************************/ +static ssize_t nvt_flash_read(struct file *file, char __user *buff, size_t count, loff_t *offp) +{ + uint8_t str[68] = {0}; + int32_t ret = -1; + int32_t retries = 0; + int8_t i2c_wr = 0; + + if (count > sizeof(str)) { + NVT_ERR("error count=%zu\n", count); + return -EFAULT; + } + + if (copy_from_user(str, buff, count)) { + NVT_ERR("copy from user error\n"); + return -EFAULT; + } + +#if NVT_TOUCH_ESD_PROTECT + cancel_delayed_work_sync(&nvt_esd_check_work); + nvt_esd_check_enable(false); +#endif + + i2c_wr = str[0] >> 7; + + if (i2c_wr == 0) { + while (retries < 20) { + ret = CTP_I2C_WRITE(ts->client, (str[0] & 0x7F), &str[2], str[1]); + if (ret == 1) + break; + else + NVT_ERR("error, retries=%d, ret=%d\n", retries, ret); + + retries++; + } + + if (unlikely(retries == 20)) { + NVT_ERR("error, ret = %d\n", ret); + return -EIO; + } + + return ret; + } else if (i2c_wr == 1) { + while (retries < 20) { + ret = CTP_I2C_READ(ts->client, (str[0] & 0x7F), &str[2], str[1]); + if (ret == 2) + break; + else + NVT_ERR("error, retries=%d, ret=%d\n", retries, ret); + + retries++; + } + + + if (retries < 20) { + if (copy_to_user(buff, str, count)) + return -EFAULT; + } + + if (unlikely(retries == 20)) { + NVT_ERR("error, ret = %d\n", ret); + return -EIO; + } + + return ret; + } else { + NVT_ERR("Call error, str[0]=%d\n", str[0]); + return -EFAULT; + } +} + +/******************************************************* +Description: + Novatek touchscreen /proc/NVTflash open function. + +return: + Executive outcomes. 0---succeed. -12---failed. +*******************************************************/ +static int32_t nvt_flash_open(struct inode *inode, struct file *file) +{ + struct nvt_flash_data *dev; + + dev = kmalloc(sizeof(struct nvt_flash_data), GFP_KERNEL); + if (dev == NULL) { + NVT_ERR("Failed to allocate memory for nvt flash data\n"); + return -ENOMEM; + } + + rwlock_init(&dev->lock); + file->private_data = dev; + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen /proc/NVTflash close function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t nvt_flash_close(struct inode *inode, struct file *file) +{ + struct nvt_flash_data *dev = file->private_data; + + if (dev) + kfree(dev); + + return 0; +} + +static const struct file_operations nvt_flash_fops = { + .owner = THIS_MODULE, + .open = nvt_flash_open, + .release = nvt_flash_close, + .read = nvt_flash_read, +}; + +/******************************************************* +Description: + Novatek touchscreen /proc/NVTflash initial function. + +return: + Executive outcomes. 0---succeed. -12---failed. +*******************************************************/ +static int32_t nvt_flash_proc_init(void) +{ + NVT_proc_entry = proc_create(DEVICE_NAME, 0444, NULL, &nvt_flash_fops); + if (NVT_proc_entry == NULL) { + NVT_ERR("Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("Succeeded!\n"); + } + + NVT_LOG("============================================================\n"); + NVT_LOG("Create /proc/NVTflash\n"); + NVT_LOG("============================================================\n"); + + return 0; +} +#endif + +#if WAKEUP_GESTURE + + +static struct wake_lock gestrue_wakelock; + +/******************************************************* +Description: + Novatek touchscreen wake up gesture key report function. + +return: + n.a. +*******************************************************/ +void nvt_ts_wakeup_gesture_report(uint8_t gesture_id) +{ + uint32_t keycode = 0; + + NVT_LOG("gesture_id = %d\n", gesture_id); + + /*Add by HQ-zmc [Date: 2017-11-15 13:57:23]*/ + /*rm gestures not used*/ + switch (gesture_id) { + case REGISTER_DOUBLE_CLICK: + NVT_LOG("Gesture : Double Click.\n"); + keycode = gesture_key_array[0]; + break; + default: + break; + } + + if (keycode > 0) { + input_report_key(ts->input_dev, keycode, 1); + input_sync(ts->input_dev); + input_report_key(ts->input_dev, keycode, 0); + input_sync(ts->input_dev); + } +} +#endif + +/******************************************************* +Description: + Novatek touchscreen parse device tree function. + +return: + n.a. +*******************************************************/ +#ifdef CONFIG_OF +static void nvt_parse_dt(struct device *dev) +{ + const char *name; + int retval; + struct device_node *np = dev->of_node; + + ts->irq_gpio = of_get_named_gpio_flags(np, "novatek,irq-gpio", 0, &ts->irq_flags); + NVT_LOG("novatek,irq-gpio=%d\n", ts->irq_gpio); + + /*Modifiy by HQ-zmc [Date: 2018-04-23 21:18:18]*/ + retval = of_property_read_string(np, "nvt,pwr-reg-name", &name); + if (retval < 0) + ts->pwr_reg_name = NULL; + else + ts->pwr_reg_name = name; + +} +#else +static void nvt_parse_dt(struct device *dev) +{ + ts->irq_gpio = NVTTOUCH_INT_PIN; +} +#endif + +/******************************************************* +Description: + Novatek touchscreen config and request gpio + +return: + Executive outcomes. 0---succeed. not 0---failed. +*******************************************************/ +static int nvt_gpio_config(struct nvt_ts_data *ts) +{ + int32_t ret = 0; + + /* request INT-pin (Input) */ + if (gpio_is_valid(ts->irq_gpio)) { + ret = gpio_request_one(ts->irq_gpio, GPIOF_IN, "NVT-int"); + if (ret) { + NVT_ERR("Failed to request NVT-int GPIO\n"); + goto err_request_irq_gpio; + } + } + + if ((ts->pwr_reg_name != NULL) && (*ts->pwr_reg_name != 0)) { + ts->pwr_reg = regulator_get(&ts->client->dev,\ + ts->pwr_reg_name); + if (IS_ERR(ts->pwr_reg)) { + NVT_ERR("%s: Failed to get power regulator\n", + __func__); + goto regulator_put; + } + } + + if (ts->pwr_reg) { + ret = regulator_enable(ts->pwr_reg); + if (ret < 0) { + NVT_ERR("%s: Failed to enable power regulator\n", + __func__); + goto disable_pwr_reg; + } + } + + return ret; + +disable_pwr_reg: + if (ts->pwr_reg) + regulator_disable(ts->pwr_reg); +regulator_put: + if (ts->pwr_reg) { + regulator_put(ts->pwr_reg); + ts->pwr_reg = NULL; + } +err_request_irq_gpio: + return ret; +} + +#if NVT_TOUCH_ESD_PROTECT +void nvt_esd_check_enable(uint8_t enable) +{ + /* enable/disable esd check flag */ + esd_check = enable; + /* update interrupt timer */ + irq_timer = jiffies; + /* clear esd_retry counter, if protect function is enabled */ + esd_retry = enable ? 0 : esd_retry; +} + +static uint8_t nvt_fw_recovery(uint8_t *point_data) +{ + uint8_t i = 0; + uint8_t detected = true; + + /* check pattern */ + for (i = 1 ; i < 7 ; i++) { + if (point_data[i] != 0x77) { + detected = false; + break; + } + } + + return detected; +} + +static void nvt_esd_check_func(struct work_struct *work) +{ + unsigned int timer = jiffies_to_msecs(jiffies - irq_timer); + + NVT_ERR("esd_check = %d (retry %d/%d)\n", esd_check, esd_retry, esd_retry_max); + + if (esd_retry >= esd_retry_max) + nvt_esd_check_enable(false); + + if ((timer > NVT_TOUCH_ESD_CHECK_PERIOD) && esd_check) { + NVT_ERR("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry); + /* do esd recovery, bootloader reset */ + nvt_bootloader_reset(); + /* update interrupt timer */ + irq_timer = jiffies; + /* update esd_retry counter */ + esd_retry++; + } + + queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, + msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); +} +#endif + +#define POINT_DATA_LEN 65 +/******************************************************* +Description: + Novatek touchscreen work function. + +return: + n.a. +*******************************************************/ +static void nvt_ts_work_func(struct work_struct *work) +{ + int32_t ret = -1; + uint8_t point_data[POINT_DATA_LEN + 1] = {0}; + uint32_t position = 0; + uint32_t input_x = 0; + uint32_t input_y = 0; + uint32_t input_w = 0; + uint32_t input_p = 0; + uint8_t input_id = 0; +#if MT_PROTOCOL_B + uint8_t press_id[TOUCH_MAX_FINGER_NUM] = {0}; +#endif /* MT_PROTOCOL_B */ + int32_t i = 0; + int32_t finger_cnt = 0; + + mutex_lock(&ts->lock); + + + ret = CTP_I2C_READ(ts->client, I2C_FW_Address, point_data, POINT_DATA_LEN + 1); + if (ret < 0) { + NVT_ERR("CTP_I2C_READ failed.(%d)\n", ret); + goto XFER_ERROR; + } +/* + //--- dump I2C buf --- + for (i = 0; i < 10; i++) { + printk("%02X %02X %02X %02X %02X %02X ", point_data[1+i*6], point_data[2+i*6], point_data[3+i*6], point_data[4+i*6], point_data[5+i*6], point_data[6+i*6]); + } + printk("\n"); +*/ + +#if NVT_TOUCH_ESD_PROTECT + if (nvt_fw_recovery(point_data)) { + nvt_esd_check_enable(true); + goto XFER_ERROR; + } +#endif + +#if WAKEUP_GESTURE + if (bTouchIsAwake == 0) { + input_id = (uint8_t)(point_data[1] >> 3); + nvt_ts_wakeup_gesture_report(input_id); + enable_irq(ts->client->irq); + mutex_unlock(&ts->lock); + return; + } +#endif + + finger_cnt = 0; + + for (i = 0; i < ts->max_touch_num; i++) { + position = 1 + 6 * i; + input_id = (uint8_t)(point_data[position + 0] >> 3); + if ((input_id == 0) || (input_id > ts->max_touch_num)) + continue; + + if (((point_data[position] & 0x07) == 0x01) || ((point_data[position] & 0x07) == 0x02)) { +#if NVT_TOUCH_ESD_PROTECT + /* update interrupt timer */ + irq_timer = jiffies; +#endif + input_x = (uint32_t)(point_data[position + 1] << 4) + (uint32_t) (point_data[position + 3] >> 4); + input_y = (uint32_t)(point_data[position + 2] << 4) + (uint32_t) (point_data[position + 3] & 0x0F); + if ((input_x < 0) || (input_y < 0)) + continue; + if ((input_x > ts->abs_x_max) || (input_y > ts->abs_y_max)) + continue; + input_w = (uint32_t)(point_data[position + 4]); + if (input_w == 0) + input_w = 1; + if (i < 2) { + input_p = (uint32_t)(point_data[position + 5]) + (uint32_t)(point_data[i + 63] << 8); + if (input_p > TOUCH_FORCE_NUM) + input_p = TOUCH_FORCE_NUM; + } else { + input_p = (uint32_t)(point_data[position + 5]); + } + if (input_p == 0) + input_p = 1; + +#if MT_PROTOCOL_B + press_id[input_id - 1] = 1; + input_mt_slot(ts->input_dev, input_id - 1); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); +#else /* MT_PROTOCOL_B */ + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, input_id - 1); + input_report_key(ts->input_dev, BTN_TOUCH, 1); +#endif /* MT_PROTOCOL_B */ + + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, input_p); + +#if MT_PROTOCOL_B +#else /* MT_PROTOCOL_B */ + input_mt_sync(ts->input_dev); +#endif /* MT_PROTOCOL_B */ + + finger_cnt++; + } + } + +#if MT_PROTOCOL_B + for (i = 0; i < ts->max_touch_num; i++) { + if (press_id[i] != 1) { + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); + } + } + + input_report_key(ts->input_dev, BTN_TOUCH, (finger_cnt > 0)); +#else /* MT_PROTOCOL_B */ + if (finger_cnt == 0) { + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_mt_sync(ts->input_dev); + } +#endif /* MT_PROTOCOL_B */ + +#if TOUCH_KEY_NUM > 0 + if (point_data[61] == 0xF8) { + for (i = 0; i < ts->max_button_num; i++) { + input_report_key(ts->input_dev, touch_key_array[i], ((point_data[62] >> i) & 0x01)); + } + } else { + for (i = 0; i < ts->max_button_num; i++) { + input_report_key(ts->input_dev, touch_key_array[i], 0); + } + } +#endif + + input_sync(ts->input_dev); + +XFER_ERROR: + enable_irq(ts->client->irq); + + mutex_unlock(&ts->lock); +} + +/******************************************************* +Description: + External interrupt service routine. + +return: + irq execute status. +*******************************************************/ +static irqreturn_t nvt_ts_irq_handler(int32_t irq, void *dev_id) +{ + disable_irq_nosync(ts->client->irq); + + +#if WAKEUP_GESTURE + if (bTouchIsAwake == 0) { + wake_lock_timeout(&gestrue_wakelock, msecs_to_jiffies(5000)); + } +#endif + + queue_work(nvt_wq, &ts->nvt_work); + + return IRQ_HANDLED; +} + +/******************************************************* +Description: + Novatek touchscreen check chip version trim function. + +return: + Executive outcomes. 0---NVT IC. -1---not NVT IC. +*******************************************************/ +static int8_t nvt_ts_check_chip_ver_trim(void) +{ + uint8_t buf[8] = {0}; + int32_t retry = 0; + int32_t list = 0; + int32_t i = 0; + int32_t found_nvt_chip = 0; + int32_t ret = -1; + + + for (retry = 5; retry > 0; retry--) { + nvt_bootloader_reset(); + nvt_sw_reset_idle(); + + buf[0] = 0x00; + buf[1] = 0x35; + CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + msleep(10); + + buf[0] = 0xFF; + buf[1] = 0x01; + buf[2] = 0xF6; + CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + + buf[0] = 0x4E; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x00; + CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 7); + NVT_LOG("buf[1]=0x%02X, buf[2]=0x%02X, buf[3]=0x%02X, buf[4]=0x%02X, buf[5]=0x%02X, buf[6]=0x%02X\n", + buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + + + for (list = 0; list < (sizeof(trim_id_table) / sizeof(struct nvt_ts_trim_id_table)); list++) { + found_nvt_chip = 0; + + + for (i = 0; i < NVT_ID_BYTE_MAX; i++) { + if (trim_id_table[list].mask[i]) { + if (buf[i + 1] != trim_id_table[list].id[i]) + break; + } + } + + if (i == NVT_ID_BYTE_MAX) { + found_nvt_chip = 1; + } + + if (found_nvt_chip) { + NVT_LOG("This is NVT touch IC\n"); + ts->mmap = trim_id_table[list].mmap; + ts->carrier_system = trim_id_table[list].carrier_system; + ret = 0; + goto out; + } else { + ts->mmap = NULL; + ret = -1; + } + } + + msleep(10); + } + +out: + return ret; +} + + +/******************************************************* +Description: + Novatek touchscreen driver probe function. + +return: + Executive outcomes. 0---succeed. negative---failed +*******************************************************/ +static int32_t nvt_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int32_t ret = 0; +#if ((TOUCH_KEY_NUM > 0) || WAKEUP_GESTURE) + int32_t retry = 0; +#endif + + NVT_LOG("start\n"); + + ts = kmalloc(sizeof(struct nvt_ts_data), GFP_KERNEL); + if (ts == NULL) { + NVT_ERR("failed to allocated memory for nvt ts data\n"); + return -ENOMEM; + } + + ts->client = client; + i2c_set_clientdata(client, ts); + + + nvt_parse_dt(&client->dev); + + + ret = nvt_gpio_config(ts); + if (ret) { + NVT_ERR("gpio config error!\n"); + goto err_gpio_config_failed; + } + + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + NVT_ERR("i2c_check_functionality failed. (no I2C_FUNC_I2C)\n"); + ret = -ENODEV; + goto err_check_functionality_failed; + } + + + msleep(10); + + //---check chip version trim--- + ret = nvt_ts_check_chip_ver_trim(); + if (ret) { + NVT_ERR("chip is not identified\n"); + ret = -EINVAL; + goto err_chipvertrim_failed; + } + + mutex_init(&ts->lock); + + mutex_lock(&ts->lock); + nvt_bootloader_reset(); + nvt_check_fw_reset_state(RESET_STATE_INIT); + nvt_get_fw_info(); + mutex_unlock(&ts->lock); + + + nvt_wq = create_workqueue("nvt_wq"); + if (!nvt_wq) { + NVT_ERR("nvt_wq create workqueue failed\n"); + ret = -ENOMEM; + goto err_create_nvt_wq_failed; + } + INIT_WORK(&ts->nvt_work, nvt_ts_work_func); + + + + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL) { + NVT_ERR("allocate input device failed\n"); + ret = -ENOMEM; + goto err_input_dev_alloc_failed; + } + + ts->max_touch_num = TOUCH_MAX_FINGER_NUM; + +#if TOUCH_KEY_NUM > 0 + ts->max_button_num = TOUCH_KEY_NUM; +#endif + + ts->int_trigger_type = INT_TRIGGER_TYPE; + + + + ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ; + ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + ts->input_dev->propbit[0] = BIT(INPUT_PROP_DIRECT); + +#if MT_PROTOCOL_B + input_mt_init_slots(ts->input_dev, ts->max_touch_num, 0); +#endif + + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, TOUCH_FORCE_NUM, 0, 0); + +#if TOUCH_MAX_FINGER_NUM > 1 + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max - 1, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max - 1, 0, 0); +#if MT_PROTOCOL_B + +#else + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, ts->max_touch_num, 0, 0); +#endif +#endif + +#if TOUCH_KEY_NUM > 0 + for (retry = 0; retry < ts->max_button_num; retry++) { + input_set_capability(ts->input_dev, EV_KEY, touch_key_array[retry]); + } +#endif + +#if WAKEUP_GESTURE + for (retry = 0; retry < (sizeof(gesture_key_array) / sizeof(gesture_key_array[0])); retry++) { + input_set_capability(ts->input_dev, EV_KEY, gesture_key_array[retry]); + } + wake_lock_init(&gestrue_wakelock, WAKE_LOCK_SUSPEND, "poll-wake-lock"); + /*add by zmc 20170923*/ + ts->input_dev->event = NVT_gesture_switch; + +#endif + + sprintf(ts->phys, "input/ts"); + ts->input_dev->name = NVT_TS_NAME; + ts->input_dev->phys = ts->phys; + ts->input_dev->id.bustype = BUS_I2C; + + + ret = input_register_device(ts->input_dev); + if (ret) { + NVT_ERR("register input device (%s) failed. ret=%d\n", ts->input_dev->name, ret); + goto err_input_register_device_failed; + } + + + client->irq = gpio_to_irq(ts->irq_gpio); + if (client->irq) { + NVT_LOG("int_trigger_type=%d\n", ts->int_trigger_type); + +#if WAKEUP_GESTURE + ret = request_irq(client->irq, nvt_ts_irq_handler, ts->int_trigger_type | IRQF_NO_SUSPEND, client->name, ts); +#else + ret = request_irq(client->irq, nvt_ts_irq_handler, ts->int_trigger_type, client->name, ts); +#endif + if (ret != 0) { + NVT_ERR("request irq failed. ret=%d\n", ret); + goto err_int_request_failed; + } else { + disable_irq(client->irq); + NVT_LOG("request irq %d succeed\n", client->irq); + } + } + +#if BOOT_UPDATE_FIRMWARE + nvt_fwu_wq = create_singlethread_workqueue("nvt_fwu_wq"); + if (!nvt_fwu_wq) { + NVT_ERR("nvt_fwu_wq create workqueue failed\n"); + ret = -ENOMEM; + goto err_create_nvt_fwu_wq_failed; + } + INIT_DELAYED_WORK(&ts->nvt_fwu_work, Boot_Update_Firmware); + + queue_delayed_work(nvt_fwu_wq, &ts->nvt_fwu_work, msecs_to_jiffies(14000)); +#endif + +#if NVT_TOUCH_ESD_PROTECT + INIT_DELAYED_WORK(&nvt_esd_check_work, nvt_esd_check_func); + nvt_esd_check_wq = create_workqueue("nvt_esd_check_wq"); + queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, + msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); +#endif + + +#if NVT_TOUCH_PROC + ret = nvt_flash_proc_init(); + if (ret != 0) { + NVT_ERR("nvt flash proc init failed. ret=%d\n", ret); + goto err_init_NVT_ts; + } +#endif + +#if NVT_TOUCH_EXT_PROC + ret = nvt_extra_proc_init(); + if (ret != 0) { + NVT_ERR("nvt extra proc init failed. ret=%d\n", ret); + goto err_init_NVT_ts; + } +#endif + +#if NVT_TOUCH_MP + ret = nvt_mp_proc_init(); + if (ret != 0) { + NVT_ERR("nvt mp proc init failed. ret=%d\n", ret); + goto err_init_NVT_ts; + } +#endif + +#if defined(CONFIG_FB) + ts->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts->fb_notif); + if (ret) { + NVT_ERR("register fb_notifier failed. ret=%d\n", ret); + goto err_register_fb_notif_failed; + } +#elif defined(CONFIG_HAS_EARLYSUSPEND) + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = nvt_ts_early_suspend; + ts->early_suspend.resume = nvt_ts_late_resume; + ret = register_early_suspend(&ts->early_suspend); + if (ret) { + NVT_ERR("register early suspend failed. ret=%d\n", ret); + goto err_register_early_suspend_failed; + } +#endif + + bTouchIsAwake = 1; + + /*Modifiy by HQ-zmc [Date: 2018-04-09 12:02:43]*/ + NVT_gesture_func_on = false; + + NVT_LOG("end\n"); + + mutex_lock(&ts->lock); + nvt_get_xiaomi_lockdown_info(); + mutex_unlock(&ts->lock); + + mutex_lock(&ts->lock); + nvt_register_hw_info(); + mutex_unlock(&ts->lock); + + enable_irq(client->irq); + + return 0; + +#if defined(CONFIG_FB) +err_register_fb_notif_failed: +#elif defined(CONFIG_HAS_EARLYSUSPEND) +err_register_early_suspend_failed: +#endif +#if (NVT_TOUCH_PROC || NVT_TOUCH_EXT_PROC || NVT_TOUCH_MP) +err_init_NVT_ts: +#endif + free_irq(client->irq, ts); +#if BOOT_UPDATE_FIRMWARE +err_create_nvt_fwu_wq_failed: +#endif +err_int_request_failed: +err_input_register_device_failed: + input_free_device(ts->input_dev); +err_input_dev_alloc_failed: +err_create_nvt_wq_failed: + mutex_destroy(&ts->lock); +err_chipvertrim_failed: +err_check_functionality_failed: + gpio_free(ts->irq_gpio); + if (ts->pwr_reg) + regulator_disable(ts->pwr_reg); + if (ts->pwr_reg) { + regulator_put(ts->pwr_reg); + ts->pwr_reg = NULL; + } +err_gpio_config_failed: + i2c_set_clientdata(client, NULL); + kfree(ts); + return ret; +} + +/******************************************************* +Description: + Novatek touchscreen driver release function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t nvt_ts_remove(struct i2c_client *client) +{ + + +#if defined(CONFIG_FB) + if (fb_unregister_client(&ts->fb_notif)) + NVT_ERR("Error occurred while unregistering fb_notifier.\n"); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&ts->early_suspend); +#endif + + mutex_destroy(&ts->lock); + + NVT_LOG("Removing driver...\n"); + + free_irq(client->irq, ts); + input_unregister_device(ts->input_dev); + i2c_set_clientdata(client, NULL); + kfree(ts); + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen driver suspend function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t nvt_ts_suspend(struct device *dev) +{ + uint8_t buf[4] = {0}; +#if MT_PROTOCOL_B + uint32_t i = 0; +#endif + + if (!bTouchIsAwake) { + NVT_LOG("Touch is already suspend\n"); + return 0; + } + + mutex_lock(&ts->lock); + + NVT_LOG("start\n"); + + bTouchIsAwake = 0; + +#if NVT_TOUCH_ESD_PROTECT + cancel_delayed_work_sync(&nvt_esd_check_work); + nvt_esd_check_enable(false); +#endif + +#if WAKEUP_GESTURE + if (NVT_gesture_func_on){ + /*add by HQ-zmc 20170923*/ + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x13; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + + enable_irq_wake(ts->client->irq); + NVT_LOG("Enabled touch wakeup gesture\n"); + } + else{ + disable_irq(ts->client->irq); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x11; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + NVT_LOG("Disabled touch wakeup gesture because of NVT_gesture_func_off\n"); + } + +#else + disable_irq(ts->client->irq); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x11; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + NVT_LOG("Disabled touch wakeup gesture because of WAKEUP_GESTURE_OFF\n"); +#endif + + /* release all touches */ +#if MT_PROTOCOL_B + for (i = 0; i < ts->max_touch_num; i++) { + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } +#endif + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#if !MT_PROTOCOL_B + input_mt_sync(ts->input_dev); +#endif + input_sync(ts->input_dev); + + msleep(50); + + mutex_unlock(&ts->lock); + + NVT_LOG("end\n"); + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen driver resume function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t nvt_ts_resume(struct device *dev) +{ + if (bTouchIsAwake) { + NVT_LOG("Touch is already resume\n"); + return 0; + } + + mutex_lock(&ts->lock); + + NVT_LOG("start\n"); + + + nvt_bootloader_reset(); + nvt_check_fw_reset_state(RESET_STATE_REK); + +#if 1 + enable_irq(ts->client->irq); +#endif + +#if NVT_TOUCH_ESD_PROTECT + queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, + msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); +#endif + + bTouchIsAwake = 1; + + mutex_unlock(&ts->lock); + + NVT_LOG("end\n"); + + return 0; +} + + +#if defined(CONFIG_FB) + +#ifdef CONFIG_PROJECT_VINCE + static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) + { + struct fb_event *evdata = data; + int *blank; + struct nvt_ts_data *ts = + container_of(self, struct nvt_ts_data, fb_notif); + + /*Add by HQ-zmc [Date: 2018-03-14 19:24:52]*/ + struct NVT_CSOT_ESD *nvt_csot_esd_status = get_nvt_csot_esd_status(); + + if (evdata && evdata->data && event == FB_EARLY_EVENT_BLANK) { + blank = evdata->data; + if ((*blank == FB_BLANK_POWERDOWN) && (nvt_csot_esd_status->ESD_TE_status == false)) { + nvt_ts_suspend(&ts->client->dev); + } + } else if (evdata && evdata->data && event == FB_EVENT_BLANK) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) { + nvt_ts_resume(&ts->client->dev); + } + } + + return 0; + } +#else + static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) + { + struct fb_event *evdata = data; + int *blank; + struct nvt_ts_data *ts = + container_of(self, struct nvt_ts_data, fb_notif); + + if (evdata && evdata->data && event == FB_EARLY_EVENT_BLANK) { + blank = evdata->data; + if (*blank == FB_BLANK_POWERDOWN) { + nvt_ts_suspend(&ts->client->dev); + } + } else if (evdata && evdata->data && event == FB_EVENT_BLANK) { + blank = evdata->data; + if (*blank == FB_BLANK_UNBLANK) { + nvt_ts_resume(&ts->client->dev); + } + } + + return 0; + } +#endif + +#elif defined(CONFIG_HAS_EARLYSUSPEND) +/******************************************************* +Description: + Novatek touchscreen driver early suspend function. + +return: + n.a. +*******************************************************/ +static void nvt_ts_early_suspend(struct early_suspend *h) +{ + nvt_ts_suspend(ts->client, PMSG_SUSPEND); +} + +/******************************************************* +Description: + Novatek touchscreen driver late resume function. + +return: + n.a. +*******************************************************/ +static void nvt_ts_late_resume(struct early_suspend *h) +{ + nvt_ts_resume(ts->client); +} +#endif + +#if 0 +static const struct dev_pm_ops nvt_ts_dev_pm_ops = { + .suspend = nvt_ts_suspend, + .resume = nvt_ts_resume, +}; +#endif + +static const struct i2c_device_id nvt_ts_id[] = { + { NVT_I2C_NAME, 0 }, + { } +}; + +#ifdef CONFIG_OF +static struct of_device_id nvt_match_table[] = { + { .compatible = "novatek,NVT-ts",}, + { }, +}; +#endif +/* +static struct i2c_board_info __initdata nvt_i2c_boardinfo[] = { + { + I2C_BOARD_INFO(NVT_I2C_NAME, I2C_FW_Address), + }, +}; +*/ + +static struct i2c_driver nvt_i2c_driver = { + .probe = nvt_ts_probe, + .remove = nvt_ts_remove, + + + .id_table = nvt_ts_id, + .driver = { + .name = NVT_I2C_NAME, + .owner = THIS_MODULE, +#if 0 +#ifdef CONFIG_PM + .pm = &nvt_ts_dev_pm_ops, +#endif +#endif +#ifdef CONFIG_OF + .of_match_table = nvt_match_table, +#endif + }, +}; + +/******************************************************* +Description: + Driver Install function. + +return: + Executive Outcomes. 0---succeed. not 0---failed. +********************************************************/ +static int32_t __init nvt_driver_init(void) +{ + int32_t ret = 0; + + NVT_LOG("start\n"); + + ret = i2c_add_driver(&nvt_i2c_driver); + if (ret) { + pr_err("%s: failed to add i2c driver", __func__); + goto err_driver; + } + + pr_info("%s: finished\n", __func__); + +err_driver: + return ret; +} + +/******************************************************* +Description: + Driver uninstall function. + +return: + n.a. +********************************************************/ +static void __exit nvt_driver_exit(void) +{ + i2c_del_driver(&nvt_i2c_driver); + + if (nvt_wq) + destroy_workqueue(nvt_wq); + +#if BOOT_UPDATE_FIRMWARE + if (nvt_fwu_wq) + destroy_workqueue(nvt_fwu_wq); +#endif + +#if NVT_TOUCH_ESD_PROTECT + if (nvt_esd_check_wq) + destroy_workqueue(nvt_esd_check_wq); +#endif +} + + +module_init(nvt_driver_init); +module_exit(nvt_driver_exit); + +MODULE_DESCRIPTION("Novatek Touchscreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/nt36672/nt36xxx.h b/drivers/input/touchscreen/nt36672/nt36xxx.h new file mode 100755 index 0000000000000..330b509339b44 --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nt36xxx.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * $Revision: 15234 $ + * $Date: 2017-08-09 11:34:54 +0800 (週三, 09 八月 2017) $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#ifndef _LINUX_NVT_TOUCH_H +#define _LINUX_NVT_TOUCH_H + +#include +#include +#include + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +#define NVT_DEBUG 1 + + +#define NVTTOUCH_INT_PIN 943 + + + + + +#define INT_TRIGGER_TYPE IRQ_TYPE_EDGE_RISING + + + +#define NVT_I2C_NAME "NVT-ts" +#define I2C_BLDR_Address 0x01 +#define I2C_FW_Address 0x01 +#define I2C_HW_Address 0x62 + +#if NVT_DEBUG +#define NVT_LOG(fmt, args...) pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args) +#else +#define NVT_LOG(fmt, args...) pr_info("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args) +#endif +#define NVT_ERR(fmt, args...) pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args) + + +#define NVT_TS_NAME "NVTCapacitiveTouchScreen" + + + +#define TOUCH_DEFAULT_MAX_WIDTH 1080 +#define TOUCH_DEFAULT_MAX_HEIGHT 2160 +#define TOUCH_MAX_FINGER_NUM 10 +#define TOUCH_KEY_NUM 0 +#if TOUCH_KEY_NUM > 0 +extern const uint16_t touch_key_array[TOUCH_KEY_NUM]; +#endif +#define TOUCH_FORCE_NUM 1000 + + +#define NVT_TOUCH_PROC 1 +#define NVT_TOUCH_EXT_PROC 1 +#define NVT_TOUCH_MP 1 +#define MT_PROTOCOL_B 1 +#define WAKEUP_GESTURE 1 +#if WAKEUP_GESTURE +extern const uint16_t gesture_key_array[]; +extern bool NVT_gesture_func_on; +#endif +#define BOOT_UPDATE_FIRMWARE 1 +#define BOOT_UPDATE_FIRMWARE_NAME "novatek_ts_fw.bin" + + +#define NVT_TOUCH_ESD_PROTECT 1 +#define NVT_TOUCH_ESD_CHECK_PERIOD 1500 /* ms */ + +struct nvt_ts_mem_map { + uint32_t EVENT_BUF_ADDR; + uint32_t RAW_PIPE0_ADDR; + uint32_t RAW_PIPE0_Q_ADDR; + uint32_t RAW_PIPE1_ADDR; + uint32_t RAW_PIPE1_Q_ADDR; + uint32_t BASELINE_ADDR; + uint32_t BASELINE_Q_ADDR; + uint32_t BASELINE_BTN_ADDR; + uint32_t BASELINE_BTN_Q_ADDR; + uint32_t DIFF_PIPE0_ADDR; + uint32_t DIFF_PIPE0_Q_ADDR; + uint32_t DIFF_PIPE1_ADDR; + uint32_t DIFF_PIPE1_Q_ADDR; + uint32_t RAW_BTN_PIPE0_ADDR; + uint32_t RAW_BTN_PIPE0_Q_ADDR; + uint32_t RAW_BTN_PIPE1_ADDR; + uint32_t RAW_BTN_PIPE1_Q_ADDR; + uint32_t DIFF_BTN_PIPE0_ADDR; + uint32_t DIFF_BTN_PIPE0_Q_ADDR; + uint32_t DIFF_BTN_PIPE1_ADDR; + uint32_t DIFF_BTN_PIPE1_Q_ADDR; + uint32_t READ_FLASH_CHECKSUM_ADDR; + uint32_t RW_FLASH_DATA_ADDR; +}; + +struct nvt_ts_data { + struct i2c_client *client; + struct input_dev *input_dev; + struct work_struct nvt_work; + struct delayed_work nvt_fwu_work; + uint16_t addr; + int8_t phys[32]; +#if defined(CONFIG_FB) + struct notifier_block fb_notif; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + uint8_t fw_ver; + uint8_t x_num; + uint8_t y_num; + uint16_t abs_x_max; + uint16_t abs_y_max; + uint8_t max_touch_num; + uint8_t max_button_num; + uint32_t int_trigger_type; + int32_t irq_gpio; + uint32_t irq_flags; + int32_t reset_gpio; + /*Modifiy by HQ-zmc [Date: 2018-04-23 21:14:58]*/ + const char *pwr_reg_name; + struct regulator *pwr_reg; + + uint32_t reset_flags; + struct mutex lock; + const struct nvt_ts_mem_map *mmap; + uint8_t carrier_system; + uint16_t nvt_pid; +}; + +#if NVT_TOUCH_PROC +struct nvt_flash_data{ + rwlock_t lock; + struct i2c_client *client; +}; +#endif + +typedef enum { + RESET_STATE_INIT = 0xA0, + RESET_STATE_REK, + RESET_STATE_REK_FINISH, + RESET_STATE_NORMAL_RUN +} RST_COMPLETE_STATE; + +typedef enum { + EVENT_MAP_HOST_CMD = 0x50, + EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE = 0x51, + EVENT_MAP_RESET_COMPLETE = 0x60, + EVENT_MAP_FWINFO = 0x78, + EVENT_MAP_PROJECTID = 0x9A, +} I2C_EVENT_MAP; + + +extern struct nvt_ts_data *ts; + + +extern int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len); +extern int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len); +extern void nvt_bootloader_reset(void); +extern void nvt_sw_reset_idle(void); +extern int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state); +extern int32_t nvt_get_fw_info(void); +extern int32_t nvt_clear_fw_status(void); +extern int32_t nvt_check_fw_status(void); +#if NVT_TOUCH_ESD_PROTECT +extern void nvt_esd_check_enable(uint8_t enable); +#endif + +#endif /* _LINUX_NVT_TOUCH_H */ diff --git a/drivers/input/touchscreen/nt36672/nt36xxx_ext_proc.c b/drivers/input/touchscreen/nt36672/nt36xxx_ext_proc.c new file mode 100755 index 0000000000000..c0fd5a52d3ed2 --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nt36xxx_ext_proc.c @@ -0,0 +1,909 @@ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * $Revision: 15234 $ + * $Date: 2017-08-09 11:34:54 +0800 (週三, 09 八月 2017) $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + + +#include +#include +#include + +#include "nt36xxx.h" + +#if NVT_TOUCH_EXT_PROC +#define NVT_FW_VERSION "nvt_fw_version" +#define NVT_BASELINE "nvt_baseline" +#define NVT_RAW "nvt_raw" +#define NVT_DIFF "nvt_diff" +#define NVT_XIAOMI_CONFIG_INFO "nvt_xiaomi_config_info" +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +#define TP_DATA_DUMP "tp_data_dump" +#define TP_WAKEUP_SWITCH "tp_wakeup_switch" /*add by HQ-zmc 20170926*/ + +#define I2C_TANSFER_LENGTH 64 + +#define NORMAL_MODE 0x00 +#define TEST_MODE_1 0x21 +#define TEST_MODE_2 0x22 +#define HANDSHAKING_HOST_READY 0xBB + +#define XDATA_SECTOR_SIZE 256 + +extern char nvt_tp_lockdown_info[128]; +static uint8_t xdata_tmp[2048] = {0}; +static int32_t xdata[2048] = {0}; +static int32_t xdata_i[2048] = {0}; +static int32_t xdata_q[2048] = {0}; + + +static int32_t read_Diff[40 * 40] = {0}; +static int32_t read_RawData[40 * 40] = {0}; + +static struct proc_dir_entry *NVT_proc_fw_version_entry; +static struct proc_dir_entry *NVT_proc_baseline_entry; +static struct proc_dir_entry *NVT_proc_raw_entry; +static struct proc_dir_entry *NVT_proc_diff_entry; +static struct proc_dir_entry *NVT_proc_xiaomi_config_info_entry; +static struct proc_dir_entry *NVT_ctp_lockdown_status_proc; +static struct proc_dir_entry *NVT_ctp_data_dump_proc; /*add by HQ-zmc*/ +static struct proc_dir_entry *NVT_ctp_wakeup_switch; /*add by HQ-zmc 20170926*/ + + +static uint8_t nvt_xiaomi_conf_info_fw_ver; +static uint8_t nvt_xiaomi_conf_info_fae_id; +static uint64_t nvt_xiaomi_conf_info_reservation; + +/******************************************************* +Description: + Novatek touchscreen change mode function. + +return: + n.a. +*******************************************************/ +void nvt_change_mode(uint8_t mode) +{ + uint8_t buf[8] = {0}; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = mode; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + + if (mode == NORMAL_MODE) { + buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; + buf[1] = HANDSHAKING_HOST_READY; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + msleep(20); + } +} + +/******************************************************* +Description: + Novatek touchscreen get firmware pipe function. + +return: + Executive outcomes. 0---pipe 0. 1---pipe 1. +*******************************************************/ +uint8_t nvt_get_fw_pipe(void) +{ + uint8_t buf[8] = {0}; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; + buf[1] = 0x00; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2); + + + + return (buf[1] & 0x01); +} + +/******************************************************* +Description: + Novatek touchscreen read meta data function. + +return: + n.a. +*******************************************************/ +void nvt_read_mdata(uint32_t xdata_addr, uint32_t xdata_btn_addr) +{ + int32_t i = 0; + int32_t j = 0; + int32_t k = 0; + uint8_t buf[I2C_TANSFER_LENGTH + 1] = {0}; + uint32_t head_addr = 0; + int32_t dummy_len = 0; + int32_t data_len = 0; + int32_t residual_len = 0; + + + head_addr = xdata_addr - (xdata_addr % XDATA_SECTOR_SIZE); + dummy_len = xdata_addr - head_addr; + data_len = ts->x_num * ts->y_num * 2; + residual_len = (head_addr + dummy_len + data_len) % XDATA_SECTOR_SIZE; + + + + + for (i = 0; i < ((dummy_len + data_len) / XDATA_SECTOR_SIZE); i++) { + + buf[0] = 0xFF; + buf[1] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 16) & 0xFF; + buf[2] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + for (j = 0; j < (XDATA_SECTOR_SIZE / I2C_TANSFER_LENGTH); j++) { + + buf[0] = I2C_TANSFER_LENGTH * j; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, I2C_TANSFER_LENGTH + 1); + + + for (k = 0; k < I2C_TANSFER_LENGTH; k++) { + xdata_tmp[XDATA_SECTOR_SIZE * i + I2C_TANSFER_LENGTH * j + k] = buf[k + 1]; + + } + } + + } + + + if (residual_len != 0) { + + buf[0] = 0xFF; + buf[1] = ((xdata_addr + data_len - residual_len) >> 16) & 0xFF; + buf[2] = ((xdata_addr + data_len - residual_len) >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + for (j = 0; j < (residual_len / I2C_TANSFER_LENGTH + 1); j++) { + + buf[0] = I2C_TANSFER_LENGTH * j; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, I2C_TANSFER_LENGTH + 1); + + + for (k = 0; k < I2C_TANSFER_LENGTH; k++) { + xdata_tmp[(dummy_len + data_len - residual_len) + I2C_TANSFER_LENGTH * j + k] = buf[k + 1]; + + } + } + + } + + + for (i = 0; i < (data_len / 2); i++) { + xdata[i] = (int16_t)(xdata_tmp[dummy_len + i * 2] + 256 * xdata_tmp[dummy_len + i * 2 + 1]); + } + +#if TOUCH_KEY_NUM > 0 + + + buf[0] = 0xFF; + buf[1] = (xdata_btn_addr >> 16) & 0xFF; + buf[2] = ((xdata_btn_addr >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = (xdata_btn_addr & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, (TOUCH_KEY_NUM * 2 + 1)); + + + for (i = 0; i < TOUCH_KEY_NUM; i++) { + xdata[ts->x_num * ts->y_num + i] = (int16_t)(buf[1 + i * 2] + 256 * buf[1 + i * 2 + 1]); + } +#endif + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); +} + +/******************************************************* +Description: + Novatek touchscreen read meta data from IQ to rss function. + +return: + n.a. +*******************************************************/ +void nvt_read_mdata_rss(uint32_t xdata_i_addr, uint32_t xdata_q_addr, uint32_t xdata_btn_i_addr, uint32_t xdata_btn_q_addr) +{ + int i = 0; + + nvt_read_mdata(xdata_i_addr, xdata_btn_i_addr); + memcpy(xdata_i, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t))); + + nvt_read_mdata(xdata_q_addr, xdata_btn_q_addr); + memcpy(xdata_q, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t))); + + for (i = 0; i < (ts->x_num * ts->y_num + TOUCH_KEY_NUM); i++) { + xdata[i] = (int32_t)int_sqrt((unsigned long)(xdata_i[i] * xdata_i[i]) + (unsigned long)(xdata_q[i] * xdata_q[i])); + } +} + +/******************************************************* +Description: + Novatek touchscreen get meta data function. + +return: + n.a. +*******************************************************/ +void nvt_get_mdata(int32_t *buf, uint8_t *m_x_num, uint8_t *m_y_num) +{ + *m_x_num = ts->x_num; + *m_y_num = ts->y_num; + memcpy(buf, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t))); +} + +/******************************************************* +Description: + Novatek touchscreen firmware version show function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t c_fw_version_show(struct seq_file *m, void *v) +{ + seq_printf(m, "fw_ver=%d, x_num=%d, y_num=%d, button_num=%d\n", ts->fw_ver, ts->x_num, ts->y_num, ts->max_button_num); + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen xdata sequence print show + function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t c_show(struct seq_file *m, void *v) +{ + int32_t i = 0; + int32_t j = 0; + + for (i = 0; i < ts->y_num; i++) { + for (j = 0; j < ts->x_num; j++) { + seq_printf(m, "%5d, ", xdata[i * ts->x_num + j]); + } + seq_puts(m, "\n"); + } + +#if TOUCH_KEY_NUM > 0 + for (i = 0; i < TOUCH_KEY_NUM; i++) { + seq_printf(m, "%5d, ", xdata[ts->x_num * ts->y_num + i]); + } + seq_puts(m, "\n"); +#endif + + seq_printf(m, "\n\n"); + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen xdata sequence print start + function. + +return: + Executive outcomes. 1---call next function. + NULL---not call next function and sequence loop + stop. +*******************************************************/ +static void *c_start(struct seq_file *m, loff_t *pos) +{ + return *pos < 1 ? (void *)1 : NULL; +} + +/******************************************************* +Description: + Novatek touchscreen xdata sequence print next + function. + +return: + Executive outcomes. NULL---no next and call sequence + stop function. +*******************************************************/ +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return NULL; +} + +/******************************************************* +Description: + Novatek touchscreen xdata sequence print stop + function. + +return: + n.a. +*******************************************************/ +static void c_stop(struct seq_file *m, void *v) +{ + return; +} + +const struct seq_operations nvt_fw_version_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_fw_version_show +}; + +const struct seq_operations nvt_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show +}; + +/******************************************************* +Description: + Novatek touchscreen /proc/nvt_fw_version open + function. + +return: + n.a. +*******************************************************/ +static int32_t nvt_fw_version_open(struct inode *inode, struct file *file) +{ + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } + + NVT_LOG("++\n"); + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + if (nvt_get_fw_info()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + mutex_unlock(&ts->lock); + + NVT_LOG("--\n"); + + return seq_open(file, &nvt_fw_version_seq_ops); +} + +static const struct file_operations nvt_fw_version_fops = { + .owner = THIS_MODULE, + .open = nvt_fw_version_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/******************************************************* +Description: + Novatek touchscreen /proc/nvt_baseline open function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t nvt_baseline_open(struct inode *inode, struct file *file) +{ + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } + + NVT_LOG("++\n"); + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + if (nvt_clear_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + nvt_change_mode(TEST_MODE_2); + + if (nvt_check_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (nvt_get_fw_info()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (ts->carrier_system) { + nvt_read_mdata_rss(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_Q_ADDR, + ts->mmap->BASELINE_BTN_ADDR, ts->mmap->BASELINE_BTN_Q_ADDR); + } else { + nvt_read_mdata(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_BTN_ADDR); + } + + nvt_change_mode(NORMAL_MODE); + + mutex_unlock(&ts->lock); + + NVT_LOG("--\n"); + + return seq_open(file, &nvt_seq_ops); +} + +static const struct file_operations nvt_baseline_fops = { + .owner = THIS_MODULE, + .open = nvt_baseline_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/******************************************************* +Description: + Novatek touchscreen /proc/nvt_raw open function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t nvt_raw_open(struct inode *inode, struct file *file) +{ + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } + + NVT_LOG("++\n"); + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + if (nvt_clear_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + nvt_change_mode(TEST_MODE_2); + + if (nvt_check_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (nvt_get_fw_info()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (ts->carrier_system) { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata_rss(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_PIPE0_Q_ADDR, + ts->mmap->RAW_BTN_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_Q_ADDR); + else + nvt_read_mdata_rss(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_PIPE1_Q_ADDR, + ts->mmap->RAW_BTN_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_Q_ADDR); + } else { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_ADDR); + else + nvt_read_mdata(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_ADDR); + } + + nvt_change_mode(NORMAL_MODE); + + NVT_LOG("--\n"); + + mutex_unlock(&ts->lock); + + return seq_open(file, &nvt_seq_ops); +} + +static const struct file_operations nvt_raw_fops = { + .owner = THIS_MODULE, + .open = nvt_raw_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/******************************************************* +Description: + Novatek touchscreen /proc/nvt_diff open function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +static int32_t nvt_diff_open(struct inode *inode, struct file *file) +{ + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } + + NVT_LOG("++\n"); + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + if (nvt_clear_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + nvt_change_mode(TEST_MODE_2); + + if (nvt_check_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (nvt_get_fw_info()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (ts->carrier_system) { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata_rss(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_PIPE0_Q_ADDR, + ts->mmap->DIFF_BTN_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_Q_ADDR); + else + nvt_read_mdata_rss(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_PIPE1_Q_ADDR, + ts->mmap->DIFF_BTN_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_Q_ADDR); + } else { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR); + else + nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR); + } + + nvt_change_mode(NORMAL_MODE); + + mutex_unlock(&ts->lock); + + NVT_LOG("--\n"); + + return seq_open(file, &nvt_seq_ops); +} + +static const struct file_operations nvt_diff_fops = { + .owner = THIS_MODULE, + .open = nvt_diff_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int nvt_xiaomi_config_info_show(struct seq_file *m, void *v) +{ + seq_printf(m, "FW version/Config version, Debug version: 0x%02X\n", nvt_xiaomi_conf_info_fw_ver); + seq_printf(m, "FAE ID: 0x%02X\n", nvt_xiaomi_conf_info_fae_id); + seq_printf(m, "Reservation byte: 0x%012llX\n", nvt_xiaomi_conf_info_reservation); + + return 0; +} + +static int32_t nvt_xiaomi_config_info_open(struct inode *inode, struct file *file) +{ + uint8_t buf[16] = {0}; + + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } + + NVT_LOG("++\n"); + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + buf[0] = 0x9C; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 9); + + nvt_xiaomi_conf_info_fw_ver = buf[1]; + nvt_xiaomi_conf_info_fae_id = buf[2]; + nvt_xiaomi_conf_info_reservation = (((uint64_t)buf[3] << 40) | ((uint64_t)buf[4] << 32) | ((uint64_t)buf[5] << 24) | ((uint64_t)buf[6] << 16) | ((uint64_t)buf[7] << 8) | (uint64_t)buf[8]); + + mutex_unlock(&ts->lock); + + NVT_LOG("--\n"); + + return single_open(file, nvt_xiaomi_config_info_show, NULL); +} + +static const struct file_operations nvt_xiaomi_config_info_fops = { + .owner = THIS_MODULE, + .open = nvt_xiaomi_config_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%s\n", nvt_tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = +{ + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; + + + +static int nvt_xiaomi_Raw_Diff_info_show(struct seq_file *m, void *v) { + int i, j; + + + + seq_printf(m, "tx:%d\n", ts->x_num); + seq_printf(m, "rx:%d\n", ts->y_num); + + NVT_LOG("read_Diff data report start\n"); + for (i = 0; i < ts->y_num; i++) { + for (j = 0; j < ts->x_num; j++) { + seq_printf(m, "%-5d ", read_Diff[i * ts->x_num + j]); + } + seq_printf(m, "\n"); + } + + + + + seq_printf(m, "tx:%d\n", ts->x_num); + seq_printf(m, "rx:%d\n", ts->y_num); + + NVT_LOG("read_RawData data report start\n"); + for (i = 0; i < ts->y_num; i++) { + for (j = 0; j < ts->x_num; j++) { + seq_printf(m, "%-5d ", read_RawData[i * ts->x_num + j]); + } + seq_printf(m, "\n"); + } + + return 0; +} + +static int32_t nvt_xiaomi_read_rawdiff_open(struct inode *inode, struct file *file) +{ +#if 0 + NVT_LOG("HQ-zmc test\n"); + return single_open(file, nvt_xiaomi_Raw_Diff_info_show, NULL); +#endif + uint8_t x_num = 0; + uint8_t y_num = 0; + + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + NVT_LOG("++\n"); + + if (nvt_clear_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + nvt_change_mode(TEST_MODE_2); + + if (nvt_check_fw_status()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + if (nvt_get_fw_info()) { + mutex_unlock(&ts->lock); + return -EAGAIN; + } + + + if (ts->carrier_system) { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata_rss(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_PIPE0_Q_ADDR, + ts->mmap->RAW_BTN_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_Q_ADDR); + else + nvt_read_mdata_rss(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_PIPE1_Q_ADDR, + ts->mmap->RAW_BTN_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_Q_ADDR); + } else { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_ADDR); + else + nvt_read_mdata(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_ADDR); + } + + nvt_get_mdata(read_RawData, &x_num, &y_num); + + + if (ts->carrier_system) { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata_rss(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_PIPE0_Q_ADDR, + ts->mmap->DIFF_BTN_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_Q_ADDR); + else + nvt_read_mdata_rss(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_PIPE1_Q_ADDR, + ts->mmap->DIFF_BTN_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_Q_ADDR); + } else { + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR); + else + nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR); + } + + nvt_get_mdata(read_Diff, &x_num, &y_num); + + + nvt_change_mode(NORMAL_MODE); + + mutex_unlock(&ts->lock); + + NVT_LOG("--\n"); + + return single_open(file, nvt_xiaomi_Raw_Diff_info_show, NULL); +} + +static const struct file_operations nvt_xiaomi_read_rawdiff_fops = { + .owner = THIS_MODULE, + .open = nvt_xiaomi_read_rawdiff_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/*add by HQ-zmc 20170926*/ +static ssize_t nvt_xiaomi_wakeup_switch_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos){ + + char input = -1; + + if (count > 0) { + if (get_user(input, buffer)) + return -EFAULT; + if (input != '0') + NVT_gesture_func_on = true; + else + NVT_gesture_func_on = false; + } + + return count; +} + +static int nvt_xiaomi_wakeup_switch_show(struct seq_file *m, void *v) { + seq_printf(m, "%d\n", NVT_gesture_func_on); + return 0; +} + +static int32_t nvt_xiaomi_wakeup_switch_open(struct inode *inode, struct file *file){ + return single_open(file, nvt_xiaomi_wakeup_switch_show, NULL); +} + +static const struct file_operations nvt_xiaomi_wakeup_switch_fops = { + .owner = THIS_MODULE, + .open = nvt_xiaomi_wakeup_switch_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = nvt_xiaomi_wakeup_switch_write, +}; + +/******************************************************* +Description: + Novatek touchscreen extra function proc. file node + initial function. + +return: + Executive outcomes. 0---succeed. -12---failed. +*******************************************************/ +int32_t nvt_extra_proc_init(void) +{ + NVT_proc_fw_version_entry = proc_create(NVT_FW_VERSION, 0444, NULL, &nvt_fw_version_fops); + if (NVT_proc_fw_version_entry == NULL) { + NVT_ERR("create proc/nvt_fw_version Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("create proc/nvt_fw_version Succeeded!\n"); + } + + NVT_proc_baseline_entry = proc_create(NVT_BASELINE, 0444, NULL, &nvt_baseline_fops); + if (NVT_proc_baseline_entry == NULL) { + NVT_ERR("create proc/nvt_baseline Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("create proc/nvt_baseline Succeeded!\n"); + } + + NVT_proc_raw_entry = proc_create(NVT_RAW, 0444, NULL, &nvt_raw_fops); + if (NVT_proc_raw_entry == NULL) { + NVT_ERR("create proc/nvt_raw Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("create proc/nvt_raw Succeeded!\n"); + } + + NVT_proc_diff_entry = proc_create(NVT_DIFF, 0444, NULL, &nvt_diff_fops); + if (NVT_proc_diff_entry == NULL) { + NVT_ERR("create proc/nvt_diff Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("create proc/nvt_diff Succeeded!\n"); + } + + NVT_proc_xiaomi_config_info_entry = proc_create(NVT_XIAOMI_CONFIG_INFO, 0444, NULL, &nvt_xiaomi_config_info_fops); + if (NVT_proc_xiaomi_config_info_entry == NULL) { + NVT_ERR("create proc/nvt_xiaomi_config_info Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("create proc/nvt_xiaomi_config_info Succeeded!\n"); + } + + NVT_ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0444, NULL, &ctp_lockdown_proc_fops); + if (NVT_ctp_lockdown_status_proc == NULL) { + NVT_ERR("create proc/tp_lockdown_info Failed!\n"); + return -ENOMEM; + } else { + NVT_LOG("create proc/tp_lockdown_info Succeeded!\n"); + } + + + /********add read raw+diff func for xiaomi E7, wlb 20170829********/ + NVT_ctp_data_dump_proc = proc_create(TP_DATA_DUMP, 0444, NULL, &nvt_xiaomi_read_rawdiff_fops); + if (NVT_ctp_data_dump_proc == NULL) { + NVT_ERR("create proc/%s Failed!\n", TP_DATA_DUMP); + return -ENOMEM; + } else { + NVT_LOG("create proc/%s Succeeded!\n", TP_DATA_DUMP); + } + + /*add by HQ-zmc 20170926*/ + NVT_ctp_wakeup_switch = proc_create(TP_WAKEUP_SWITCH, 0666, NULL, &nvt_xiaomi_wakeup_switch_fops); + if (NVT_ctp_wakeup_switch == NULL){ + NVT_ERR("create proc/%s Failed!\n", TP_WAKEUP_SWITCH); + return -ENOMEM; + }else{ + NVT_LOG("create proc/%s Succeeded!\n", TP_WAKEUP_SWITCH); + } + + return 0; +} +#endif diff --git a/drivers/input/touchscreen/nt36672/nt36xxx_fw_update.c b/drivers/input/touchscreen/nt36672/nt36xxx_fw_update.c new file mode 100755 index 0000000000000..583842d63c49b --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nt36xxx_fw_update.c @@ -0,0 +1,1025 @@ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * $Revision: 15234 $ + * $Date: 2017-08-09 11:34:54 +0800 (週三, 09 八月 2017) $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include + +#include "nt36xxx.h" + +#if BOOT_UPDATE_FIRMWARE + +#define FW_BIN_SIZE_116KB 118784 +#define FW_BIN_SIZE FW_BIN_SIZE_116KB +#define FW_BIN_VER_OFFSET 0x1A000 +#define FW_BIN_VER_BAR_OFFSET 0x1A001 +#define FLASH_SECTOR_SIZE 4096 +#define SIZE_64KB 65536 +#define BLOCK_64KB_NUM 4 + +const struct firmware *fw_entry = NULL; + +/******************************************************* +Description: + Novatek touchscreen request update firmware function. + +return: + Executive outcomes. 0---succeed. -1,-22---failed. +*******************************************************/ +int32_t update_firmware_request(char *filename) +{ + int32_t ret = 0; + + if (NULL == filename) { + return -EPERM; + } + + NVT_LOG("filename is %s\n", filename); + + ret = request_firmware(&fw_entry, filename, &ts->client->dev); + if (ret) { + NVT_ERR("firmware load failed, ret=%d\n", ret); + return ret; + } + + + if (fw_entry->size != FW_BIN_SIZE) { + NVT_ERR("bin file size not match. (%zu)\n", fw_entry->size); + return -EINVAL; + } + + + if (*(fw_entry->data + FW_BIN_VER_OFFSET) + *(fw_entry->data + FW_BIN_VER_BAR_OFFSET) != 0xFF) { + NVT_ERR("bin file FW_VER + FW_VER_BAR should be 0xFF!\n"); + NVT_ERR("FW_VER=0x%02X, FW_VER_BAR=0x%02X\n", *(fw_entry->data+FW_BIN_VER_OFFSET), *(fw_entry->data+FW_BIN_VER_BAR_OFFSET)); + return -EINVAL; + } + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen release update firmware function. + +return: + n.a. +*******************************************************/ +void update_firmware_release(void) +{ + if (fw_entry) { + release_firmware(fw_entry); + } + fw_entry = NULL; +} + +/******************************************************* +Description: + Novatek touchscreen check firmware version function. + +return: + Executive outcomes. 0---need update. 1---need not + update. +*******************************************************/ +int32_t Check_FW_Ver(void) +{ + uint8_t buf[16] = {0}; + int32_t ret = 0; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("i2c write error!(%d)\n", ret); + return ret; + } + + + buf[0] = EVENT_MAP_FWINFO; + buf[1] = 0x00; + buf[2] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("i2c read error!(%d)\n", ret); + return ret; + } + + NVT_LOG("IC FW Ver = 0x%02X, FW Ver Bar = 0x%02X\n", buf[1], buf[2]); + NVT_LOG("Bin FW Ver = 0x%02X, FW ver Bar = 0x%02X\n", + fw_entry->data[FW_BIN_VER_OFFSET], fw_entry->data[FW_BIN_VER_BAR_OFFSET]); + + + if ((buf[1] + buf[2]) != 0xFF) { + NVT_ERR("IC FW_VER + FW_VER_BAR not equals to 0xFF!\n"); + return 0; + } + + + if (buf[1] > fw_entry->data[FW_BIN_VER_OFFSET]) + return 1; + else + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen resume from deep power down function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +int32_t Resume_PD(void) +{ + uint8_t buf[8] = {0}; + int32_t ret = 0; + int32_t retry = 0; + + + buf[0] = 0x00; + buf[1] = 0xAB; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Write Enable error!!(%d)\n", ret); + return ret; + } + + + retry = 0; + while(1) { + msleep(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Resume Command) error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Resume Command) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + } + msleep(10); + + NVT_LOG("Resume PD OK\n"); + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen check firmware checksum function. + +return: + Executive outcomes. 0---checksum not match. + 1---checksum match. -1--- checksum read failed. +*******************************************************/ +int32_t Check_CheckSum(void) +{ + uint8_t buf[64] = {0}; + uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR; + int32_t ret = 0; + int32_t i = 0; + int32_t k = 0; + uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0}; + uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0}; + size_t fw_bin_size = 0; + size_t len_in_blk = 0; + int32_t retry = 0; + + if (Resume_PD()) { + NVT_ERR("Resume PD error!!\n"); + return -1; + } + + fw_bin_size = fw_entry->size; + + for (i = 0; i < BLOCK_64KB_NUM; i++) { + if (fw_bin_size > (i * SIZE_64KB)) { + + len_in_blk = min(fw_bin_size - i * SIZE_64KB, (size_t)SIZE_64KB); + WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF); + for (k = 0; k < len_in_blk; k++) { + WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB]; + } + WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1; + + + buf[0] = 0x00; + buf[1] = 0x07; + buf[2] = i; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = ((len_in_blk - 1) >> 8) & 0xFF; + buf[6] = (len_in_blk - 1) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7); + if (ret < 0) { + NVT_ERR("Fast Read Command error!!(%d)\n", ret); + return ret; + } + + retry = 0; + while (1) { + msleep(80); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 5)) { + NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry); + return -EPERM; + } + } + + buf[0] = 0xFF; + buf[1] = XDATA_Addr >> 16; + buf[2] = (XDATA_Addr >> 8) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret); + return ret; + } + + buf[0] = (XDATA_Addr) & 0xFF; + buf[1] = 0x00; + buf[2] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Read Checksum error!!(%d)\n", ret); + return ret; + } + + RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]); + if (WR_Filechksum[i] != RD_Filechksum[i]) { + NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]); + NVT_ERR("firmware checksum not match!!\n"); + return 0; + } + } + } + + NVT_LOG("firmware checksum match\n"); + return 1; +} + +/******************************************************* +Description: + Novatek touchscreen initial bootloader and flash + block function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +int32_t Init_BootLoader(void) +{ + uint8_t buf[64] = {0}; + int32_t ret = 0; + int32_t retry = 0; + + + nvt_sw_reset_idle(); + + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = I2C_FW_Address; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Inittial Flash Block error!!(%d)\n", ret); + return ret; + } + + + retry = 0; + while(1) { + msleep(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Inittial Flash Block) error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Inittial Flash Block) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + } + + NVT_LOG("Init OK \n"); + msleep(20); + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen erase flash sectors function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +int32_t Erase_Flash(void) +{ + uint8_t buf[64] = {0}; + int32_t ret = 0; + int32_t count = 0; + int32_t i = 0; + int32_t Flash_Address = 0; + int32_t retry = 0; + + + buf[0] = 0x00; + buf[1] = 0x06; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Write Enable (for Write Status Register) error!!(%d)\n", ret); + return ret; + } + + retry = 0; + while (1) { + mdelay(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + } + + + buf[0] = 0x00; + buf[1] = 0x01; + buf[2] = 0x00; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Write Status Register error!!(%d)\n", ret); + return ret; + } + + retry = 0; + while (1) { + mdelay(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Write Status Register) error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Write Status Register) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + } + + + retry = 0; + while (1) { + mdelay(5); + buf[0] = 0x00; + buf[1] = 0x05; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Read Status (for Write Status Register) error!!(%d)\n", ret); + return ret; + } + + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Check 0xAA (Read Status for Write Status Register) error!!(%d)\n", ret); + return ret; + } + if ((buf[1] == 0xAA) && (buf[2] == 0x00)) { + break; + } + retry++; + if (unlikely(retry > 100)) { + NVT_ERR("Check 0xAA (Read Status for Write Status Register) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry); + return -EPERM; + } + } + + if (fw_entry->size % FLASH_SECTOR_SIZE) + count = fw_entry->size / FLASH_SECTOR_SIZE + 1; + else + count = fw_entry->size / FLASH_SECTOR_SIZE; + + for (i = 0; i < count; i++) { + + buf[0] = 0x00; + buf[1] = 0x06; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Write Enable error!!(%d,%d)\n", ret, i); + return ret; + } + + retry = 0; + while (1) { + mdelay(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + } + + Flash_Address = i * FLASH_SECTOR_SIZE; + + + buf[0] = 0x00; + buf[1] = 0x20; + buf[2] = ((Flash_Address >> 16) & 0xFF); + buf[3] = ((Flash_Address >> 8) & 0xFF); + buf[4] = (Flash_Address & 0xFF); + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 5); + if (ret < 0) { + NVT_ERR("Sector Erase error!!(%d,%d)\n", ret, i); + return ret; + } + + retry = 0; + while (1) { + mdelay(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Sector Erase) error!!(%d,%d)\n", ret, i); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Sector Erase) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry); + return -EPERM; + } + } + + + retry = 0; + while (1) { + mdelay(5); + buf[0] = 0x00; + buf[1] = 0x05; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Read Status error!!(%d,%d)\n", ret, i); + return ret; + } + + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Check 0xAA (Read Status) error!!(%d,%d)\n", ret, i); + return ret; + } + if ((buf[1] == 0xAA) && (buf[2] == 0x00)) { + break; + } + retry++; + if (unlikely(retry > 100)) { + NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry); + return -EPERM; + } + } + } + + NVT_LOG("Erase OK \n"); + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen write flash sectors function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +int32_t Write_Flash(void) +{ + uint8_t buf[64] = {0}; + uint32_t XDATA_Addr = ts->mmap->RW_FLASH_DATA_ADDR; + uint32_t Flash_Address = 0; + int32_t i = 0, j = 0, k = 0; + uint8_t tmpvalue = 0; + int32_t count = 0; + int32_t ret = 0; + int32_t retry = 0; + + + buf[0] = 0xFF; + buf[1] = XDATA_Addr >> 16; + buf[2] = (XDATA_Addr >> 8) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("change I2C buffer index error!!(%d)\n", ret); + return ret; + } + + if (fw_entry->size % 256) + count = fw_entry->size / 256 + 1; + else + count = fw_entry->size / 256; + + for (i = 0; i < count; i++) { + Flash_Address = i * 256; + + + buf[0] = 0x00; + buf[1] = 0x06; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Write Enable error!!(%d)\n", ret); + return ret; + } + + retry = 0; + while (1) { + udelay(100); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + } + + + for (j = 0; j < min(fw_entry->size - i * 256, (size_t)256); j += 32) { + buf[0] = (XDATA_Addr + j) & 0xFF; + for (k = 0; k < 32; k++) { + buf[1 + k] = fw_entry->data[Flash_Address + j + k]; + } + ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 33); + if (ret < 0) { + NVT_ERR("Write Page error!!(%d), j=%d\n", ret, j); + return ret; + } + } + if (fw_entry->size - Flash_Address >= 256) + tmpvalue = (Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (255); + else + tmpvalue = (Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (fw_entry->size - Flash_Address - 1); + + for (k = 0; k < min(fw_entry->size - Flash_Address, (size_t)256); k++) + tmpvalue += fw_entry->data[Flash_Address + k]; + + tmpvalue = 255 - tmpvalue + 1; + + + buf[0] = 0x00; + buf[1] = 0x02; + buf[2] = ((Flash_Address >> 16) & 0xFF); + buf[3] = ((Flash_Address >> 8) & 0xFF); + buf[4] = (Flash_Address & 0xFF); + buf[5] = 0x00; + buf[6] = min(fw_entry->size - Flash_Address, (size_t)256) - 1; + buf[7] = tmpvalue; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 8); + if (ret < 0) { + NVT_ERR("Page Program error!!(%d), i=%d\n", ret, i); + return ret; + } + + retry = 0; + while (1) { + mdelay(1); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Page Program error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA || buf[1] == 0xEA) { + break; + } + retry++; + if (unlikely(retry > 20)) { + NVT_ERR("Check 0xAA (Page Program) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry); + return -EPERM; + } + } + if (buf[1] == 0xEA) { + NVT_ERR("Page Program error!! i=%d\n", i); + return -3; + } + + + retry = 0; + while (1) { + mdelay(5); + buf[0] = 0x00; + buf[1] = 0x05; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Read Status error!!(%d)\n", ret); + return ret; + } + + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Check 0xAA (Read Status) error!!(%d)\n", ret); + return ret; + } + if (((buf[1] == 0xAA) && (buf[2] == 0x00)) || (buf[1] == 0xEA)) { + break; + } + retry++; + if (unlikely(retry > 100)) { + NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry); + return -EPERM; + } + } + if (buf[1] == 0xEA) { + NVT_ERR("Page Program error!! i=%d\n", i); + return -4; + } + + NVT_LOG("Programming...%2d%%\r", ((i * 100) / count)); + } + + NVT_LOG("Programming...%2d%%\r", 100); + NVT_LOG("Program OK \n"); + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen verify checksum of written + flash function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +int32_t Verify_Flash(void) +{ + uint8_t buf[64] = {0}; + uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR; + int32_t ret = 0; + int32_t i = 0; + int32_t k = 0; + uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0}; + uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0}; + size_t fw_bin_size = 0; + size_t len_in_blk = 0; + int32_t retry = 0; + + fw_bin_size = fw_entry->size; + + for (i = 0; i < BLOCK_64KB_NUM; i++) { + if (fw_bin_size > (i * SIZE_64KB)) { + + len_in_blk = min(fw_bin_size - i * SIZE_64KB, (size_t)SIZE_64KB); + WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF); + for (k = 0; k < len_in_blk; k++) { + WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB]; + } + WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1; + + + buf[0] = 0x00; + buf[1] = 0x07; + buf[2] = i; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = ((len_in_blk - 1) >> 8) & 0xFF; + buf[6] = (len_in_blk - 1) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7); + if (ret < 0) { + NVT_ERR("Fast Read Command error!!(%d)\n", ret); + return ret; + } + + retry = 0; + while (1) { + msleep(80); + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret); + return ret; + } + if (buf[1] == 0xAA) { + break; + } + retry++; + if (unlikely(retry > 5)) { + NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry); + return -EPERM; + } + } + + buf[0] = 0xFF; + buf[1] = XDATA_Addr >> 16; + buf[2] = (XDATA_Addr >> 8) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret); + return ret; + } + + buf[0] = (XDATA_Addr) & 0xFF; + buf[1] = 0x00; + buf[2] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("Read Checksum error!!(%d)\n", ret); + return ret; + } + + RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]); + if (WR_Filechksum[i] != RD_Filechksum[i]) { + NVT_ERR("Verify Fail%d!!\n", i); + NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]); + return -EPERM; + } + } + } + + NVT_LOG("Verify OK \n"); + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen update firmware function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +int32_t Update_Firmware(void) +{ + int32_t ret = 0; + + + ret = Init_BootLoader(); + if (ret) { + return ret; + } + + + ret = Resume_PD(); + if (ret) { + return ret; + } + + + ret = Erase_Flash(); + if (ret) { + return ret; + } + + + ret = Write_Flash(); + if (ret) { + return ret; + } + + + ret = Verify_Flash(); + if (ret) { + return ret; + } + + + nvt_bootloader_reset(); + nvt_check_fw_reset_state(RESET_STATE_INIT); + + return ret; +} + +/******************************************************* +Description: + Novatek touchscreen check flash end flag function. + +return: + Executive outcomes. 0---succeed. 1,negative---failed. +*******************************************************/ +#define NVT_FLASH_END_FLAG_LEN 3 +#define NVT_FLASH_END_FLAG_ADDR 0x1AFFD +int32_t nvt_check_flash_end_flag(void) +{ + uint8_t buf[8] = {0}; + uint8_t nvt_end_flag[NVT_FLASH_END_FLAG_LEN + 1] = {0}; + int32_t ret = 0; + + + ret = Init_BootLoader(); + if (ret) { + return ret; + } + + + ret = Resume_PD(); + if (ret) { + return ret; + } + + + buf[0] = 0x00; + buf[1] = 0x35; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("write unlock error!!(%d)\n", ret); + return ret; + } + msleep(10); + + //Step 4 : Flash Read Command + buf[0] = 0x00; + buf[1] = 0x03; + buf[2] = (NVT_FLASH_END_FLAG_ADDR >> 16) & 0xFF; + buf[3] = (NVT_FLASH_END_FLAG_ADDR >> 8) & 0xFF; + buf[4] = NVT_FLASH_END_FLAG_ADDR & 0xFF; + buf[5] = (NVT_FLASH_END_FLAG_LEN >> 8) & 0xFF; + buf[6] = NVT_FLASH_END_FLAG_LEN & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7); + if (ret < 0) { + NVT_ERR("write Read Command error!!(%d)\n", ret); + return ret; + } + msleep(10); + + // Check 0xAA (Read Command) + buf[0] = 0x00; + buf[1] = 0x00; + ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2); + if (ret < 0) { + NVT_ERR("Check 0xAA (Read Command) error!!(%d)\n", ret); + return ret; + } + if (buf[1] != 0xAA) { + NVT_ERR("Check 0xAA (Read Command) error!! status=0x%02X\n", buf[1]); + return -EPERM; + } + + msleep(10); + + //Step 5 : Read Flash Data + buf[0] = 0xFF; + buf[1] = (ts->mmap->READ_FLASH_CHECKSUM_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->READ_FLASH_CHECKSUM_ADDR >> 8) & 0xFF; + ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3); + if (ret < 0) { + NVT_ERR("change index error!! (%d)\n", ret); + return ret; + } + msleep(10); + + // Read Back + buf[0] = ts->mmap->READ_FLASH_CHECKSUM_ADDR & 0xFF; + ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 6); + if (ret < 0) { + NVT_ERR("Read Back error!! (%d)\n", ret); + return ret; + } + + + strncpy(nvt_end_flag, &buf[3], NVT_FLASH_END_FLAG_LEN); + NVT_LOG("nvt_end_flag=%s (%02X %02X %02X)\n", nvt_end_flag, buf[3], buf[4], buf[5]); + + if (strncmp(nvt_end_flag, "NVT", 3) == 0) { + return 0; + } else { + NVT_ERR("\"NVT\" end flag not found!\n"); + return 1; + } +} + +/******************************************************* +Description: + Novatek touchscreen update firmware when booting + function. + +return: + n.a. +*******************************************************/ +void Boot_Update_Firmware(struct work_struct *work) +{ + int32_t ret = 0; + + char firmware_name[256] = ""; + sprintf(firmware_name, BOOT_UPDATE_FIRMWARE_NAME); + + + ret = update_firmware_request(firmware_name); + if (ret) { + NVT_ERR("update_firmware_request failed. (%d)\n", ret); + return; + } + + mutex_lock(&ts->lock); + +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + nvt_sw_reset_idle(); + + ret = Check_CheckSum(); + + if (ret < 0) { + NVT_ERR("read firmware checksum failed\n"); + Update_Firmware(); + } else if ((ret == 0) && (Check_FW_Ver() == 0)) { + NVT_LOG("firmware version not match\n"); + Update_Firmware(); + } else if (nvt_check_flash_end_flag()) { + NVT_LOG("check flash end flag failed\n"); + Update_Firmware(); + } else { + + nvt_bootloader_reset(); + ret = nvt_check_fw_reset_state(RESET_STATE_INIT); + if (ret) { + NVT_LOG("check fw reset state failed\n"); + Update_Firmware(); + } + } + + mutex_unlock(&ts->lock); + + update_firmware_release(); +} +#endif /* BOOT_UPDATE_FIRMWARE */ diff --git a/drivers/input/touchscreen/nt36672/nt36xxx_mp_ctrlram.c b/drivers/input/touchscreen/nt36672/nt36xxx_mp_ctrlram.c new file mode 100755 index 0000000000000..7eefaa0e48822 --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nt36xxx_mp_ctrlram.c @@ -0,0 +1,1909 @@ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * $Revision: 15234 $ + * $Date: 2017-08-09 11:34:54 +0800 (週三, 09 八月 2017) $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include + +#include "nt36xxx.h" +#include "nt36xxx_mp_ctrlram.h" + +#if NVT_TOUCH_MP + +#define NORMAL_MODE 0x00 +#define TEST_MODE_1 0x21 +#define TEST_MODE_2 0x22 +#define MP_MODE_CC 0x41 +#define FREQ_HOP_DISABLE 0x66 +#define FREQ_HOP_ENABLE 0x65 + +#define SHORT_TEST_CSV_FILE "/sdcard/ShortTest.csv" +#define OPEN_TEST_CSV_FILE "/sdcard/OpenTest.csv" +#define FW_RAWDATA_CSV_FILE "/sdcard/FWMutualTest.csv" +#define FW_CC_CSV_FILE "/sdcard/FWCCTest.csv" +#define NOISE_TEST_CSV_FILE "/sdcard/NoiseTest.csv" + +#define nvt_mp_seq_printf(m, fmt, args...) do { \ + seq_printf(m, fmt, ##args); \ + if (!nvt_mp_test_result_printed) \ + printk(fmt, ##args); \ +} while (0) + +static uint8_t *RecordResult_Short; +static uint8_t *RecordResult_Short_Diff; +static uint8_t *RecordResult_Short_Base; +static uint8_t *RecordResult_Open; +static uint8_t *RecordResult_FWMutual; +static uint8_t *RecordResult_FW_CC; +static uint8_t *RecordResult_FW_CC_I; +static uint8_t *RecordResult_FW_CC_Q; +static uint8_t *RecordResult_FW_DiffMax; +static uint8_t *RecordResult_FW_DiffMin; + +static int32_t TestResult_Short; +static int32_t TestResult_Short_Diff; +static int32_t TestResult_Short_Base; +static int32_t TestResult_Open; +static int32_t TestResult_FW_Rawdata; +static int32_t TestResult_FWMutual; +static int32_t TestResult_FW_CC; +static int32_t TestResult_FW_CC_I; +static int32_t TestResult_FW_CC_Q; +static int32_t TestResult_Noise; +static int32_t TestResult_FW_DiffMax; +static int32_t TestResult_FW_DiffMin; + +static int32_t *RawData_Short; +static int32_t *RawData_Short_Diff; +static int32_t *RawData_Short_Base; +static int32_t *RawData_Open; +static int32_t *RawData_Diff; +static int32_t *RawData_Diff_Min; +static int32_t *RawData_Diff_Max; +static int32_t *RawData_FWMutual; +static int32_t *RawData_FW_CC; +static int32_t *RawData_FW_CC_I; +static int32_t *RawData_FW_CC_Q; + +static struct proc_dir_entry *NVT_proc_selftest_entry; +static struct proc_dir_entry *NVT_ito_test_result_entry; +static int8_t nvt_mp_test_result_printed; +static int8_t nvt_ito_test_result = 1; + +extern void nvt_change_mode(uint8_t mode); +extern uint8_t nvt_get_fw_pipe(void); +extern void nvt_read_mdata(uint32_t xdata_addr, uint32_t xdata_btn_addr); +extern void nvt_get_mdata(int32_t *buf, uint8_t *m_x_num, uint8_t *m_y_num); + +/******************************************************* +Description: + Novatek touchscreen allocate buffer for mp selftest. + +return: + Executive outcomes. 0---succeed. -12---Out of memory +*******************************************************/ +static int nvt_mp_buffer_init(void) +{ + size_t RecordResult_BufSize = IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE; + size_t RawData_BufSize = (IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE) * sizeof(int32_t); + + RecordResult_Short = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_Short) { + NVT_ERR("kzalloc for RecordResult_Short failed!\n"); + return -ENOMEM; + } + + RecordResult_Short_Diff = RecordResult_Short; + + RecordResult_Short_Base = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_Short_Base) { + NVT_ERR("kzalloc for RecordResult_Short_Base failed!\n"); + return -ENOMEM; + } + + RecordResult_Open = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_Open) { + NVT_ERR("kzalloc for RecordResult_Open failed!\n"); + return -ENOMEM; + } + + RecordResult_FWMutual = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_FWMutual) { + NVT_ERR("kzalloc for RecordResult_FWMutual failed!\n"); + return -ENOMEM; + } + + RecordResult_FW_CC = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_FW_CC) { + NVT_ERR("kzalloc for RecordResult_FW_CC failed!\n"); + return -ENOMEM; + } + + RecordResult_FW_CC_I = RecordResult_FW_CC; + + RecordResult_FW_CC_Q = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_FW_CC_Q) { + NVT_ERR("kzalloc for RecordResult_FW_CC_Q failed!\n"); + return -ENOMEM; + } + + RecordResult_FW_DiffMax = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_FW_DiffMax) { + NVT_ERR("kzalloc for RecordResult_FW_DiffMax failed!\n"); + return -ENOMEM; + } + + RecordResult_FW_DiffMin = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL); + if (!RecordResult_FW_DiffMin) { + NVT_ERR("kzalloc for RecordResult_FW_DiffMin failed!\n"); + return -ENOMEM; + } + + RawData_Short = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_Short) { + NVT_ERR("kzalloc for RawData_Short failed!\n"); + return -ENOMEM; + } + + RawData_Short_Diff = RawData_Short; + + RawData_Short_Base = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_Short_Base) { + NVT_ERR("kzalloc for RawData_Short_Base failed!\n"); + return -ENOMEM; + } + + RawData_Open = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_Open) { + NVT_ERR("kzalloc for RawData_Open failed!\n"); + return -ENOMEM; + } + + RawData_Diff = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_Diff) { + NVT_ERR("kzalloc for RawData_Diff failed!\n"); + return -ENOMEM; + } + + RawData_Diff_Min = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_Diff_Min) { + NVT_ERR("kzalloc for RawData_Diff_Min failed!\n"); + return -ENOMEM; + } + + RawData_Diff_Max = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_Diff_Max) { + NVT_ERR("kzalloc for RawData_Diff_Max failed!\n"); + return -ENOMEM; + } + + RawData_FWMutual = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_FWMutual) { + NVT_ERR("kzalloc for RawData_FWMutual failed!\n"); + return -ENOMEM; + } + + RawData_FW_CC = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_FW_CC) { + NVT_ERR("kzalloc for RawData_FW_CC failed!\n"); + return -ENOMEM; + } + + RawData_FW_CC_I = RawData_FW_CC; + + RawData_FW_CC_Q = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL); + if (!RawData_FW_CC_Q) { + NVT_ERR("kzalloc for RawData_FW_CC_Q failed!\n"); + return -ENOMEM; + } + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen self-test criteria print function. + +return: + n.a. +*******************************************************/ +static void nvt_print_lmt_array(int32_t *array, int32_t x_ch, int32_t y_ch) +{ + int32_t i = 0; + int32_t j = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + + for (j = 0; j < y_ch; j++) { + for (i = 0; i < x_ch; i++) { + printk("%5d, ", array[j * x_ch + i]); + } + printk("\n"); + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + printk("%5d, ", array[y_ch * x_ch + k]); + } + printk("\n"); +#endif /* #if TOUCH_KEY_NUM > 0 */ +} + +static void nvt_print_criteria(void) +{ + NVT_LOG("++\n"); + + if (ts->carrier_system) { + + printk("PS_Config_Lmt_Short_Diff_P: %5d\n", PS_Config_Lmt_Short_Diff_P); + printk("PS_Config_Lmt_Short_Diff_N: %5d\n", PS_Config_Lmt_Short_Diff_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_Short_Diff_P: %5d\n", PS_Config_Lmt_Key_Short_Diff_P); + printk("PS_Config_Lmt_Key_Short_Diff_N: %5d\n", PS_Config_Lmt_Key_Short_Diff_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + printk("PS_Config_Lmt_Short_Base_P: %5d\n", PS_Config_Lmt_Short_Base_P); + printk("PS_Config_Lmt_Short_Base_N: %5d\n", PS_Config_Lmt_Short_Base_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_Short_Base_P: %5d\n", PS_Config_Lmt_Key_Short_Base_P); + printk("PS_Config_Lmt_Key_Short_Base_N: %5d\n", PS_Config_Lmt_Key_Short_Base_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + } else { + + printk("PS_Config_Lmt_Short_Rawdata_P: %5d\n", PS_Config_Lmt_Short_Rawdata_P); + printk("PS_Config_Lmt_Short_Rawdata_N: %5d\n", PS_Config_Lmt_Short_Rawdata_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_Short_Rawdata_P: %5d\n", PS_Config_Lmt_Key_Short_Rawdata_P); + printk("PS_Config_Lmt_Key_Short_Rawdata_N: %5d\n", PS_Config_Lmt_Key_Short_Rawdata_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + } + + + printk("PS_Config_Lmt_Open_Rawdata_P:\n"); + nvt_print_lmt_array(PS_Config_Lmt_Open_Rawdata_P, X_Channel, Y_Channel); + printk("PS_Config_Lmt_Open_Rawdata_N:\n"); + nvt_print_lmt_array(PS_Config_Lmt_Open_Rawdata_N, X_Channel, Y_Channel); + + + printk("PS_Config_Lmt_FW_Rawdata_P:\n"); + nvt_print_lmt_array(PS_Config_Lmt_FW_Rawdata_P, X_Channel, Y_Channel); + printk("PS_Config_Lmt_FW_Rawdata_N:\n"); + nvt_print_lmt_array(PS_Config_Lmt_FW_Rawdata_N, X_Channel, Y_Channel); + + if (ts->carrier_system) { + + printk("PS_Config_Lmt_FW_CC_I_P: %5d\n", PS_Config_Lmt_FW_CC_I_P); + printk("PS_Config_Lmt_FW_CC_I_N: %5d\n", PS_Config_Lmt_FW_CC_I_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_FW_CC_I_P: %5d\n", PS_Config_Lmt_Key_FW_CC_I_P); + printk("PS_Config_Lmt_Key_FW_CC_I_N: %5d\n", PS_Config_Lmt_Key_FW_CC_I_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + printk("PS_Config_Lmt_FW_CC_Q_P: %5d\n", PS_Config_Lmt_FW_CC_Q_P); + printk("PS_Config_Lmt_FW_CC_Q_N: %5d\n", PS_Config_Lmt_FW_CC_Q_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_FW_CC_Q_P: %5d\n", PS_Config_Lmt_Key_FW_CC_Q_P); + printk("PS_Config_Lmt_Key_FW_CC_Q_N: %5d\n", PS_Config_Lmt_Key_FW_CC_Q_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + } else { + + printk("PS_Config_Lmt_FW_CC_P: %5d\n", PS_Config_Lmt_FW_CC_P); + printk("PS_Config_Lmt_FW_CC_N: %5d\n", PS_Config_Lmt_FW_CC_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_FW_CC_P: %5d\n", PS_Config_Lmt_Key_FW_CC_P); + printk("PS_Config_Lmt_Key_FW_CC_N: %5d\n", PS_Config_Lmt_Key_FW_CC_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + } + + + printk("PS_Config_Lmt_FW_Diff_P: %5d\n", PS_Config_Lmt_FW_Diff_P); + printk("PS_Config_Lmt_FW_Diff_N: %5d\n", PS_Config_Lmt_FW_Diff_N); +#if TOUCH_KEY_NUM > 0 + printk("PS_Config_Lmt_Key_FW_Diff_P: %5d\n", PS_Config_Lmt_Key_FW_Diff_P); + printk("PS_Config_Lmt_Key_FW_Diff_N: %5d\n", PS_Config_Lmt_Key_FW_Diff_N); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + NVT_LOG("--\n"); +} + +static int32_t nvt_save_rawdata_to_csv(int32_t *rawdata, uint8_t x_ch, uint8_t y_ch, const char *file_path, uint32_t offset) +{ + int32_t x = 0; + int32_t y = 0; + int32_t iArrayIndex = 0; + struct file *fp = NULL; + char *fbufp = NULL; + mm_segment_t org_fs; + int32_t write_ret = 0; + uint32_t output_len = 0; + loff_t pos = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; + int32_t keydata_output_offset = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + + printk("%s:++\n", __func__); + fbufp = (char *)kzalloc(8192, GFP_KERNEL); + if (!fbufp) { + NVT_ERR("kzalloc for fbufp failed!\n"); + return -ENOMEM; + } + + for (y = 0; y < y_ch; y++) { + for (x = 0; x < x_ch; x++) { + iArrayIndex = y * x_ch + x; + /*changed by HQ-zmc 20171103*/ + /*printk("%5d, ", rawdata[iArrayIndex]);*/ + sprintf(fbufp + iArrayIndex * 7 + y * 2, "%5d, ", rawdata[iArrayIndex]); + } + /*changed by HQ-zmc 20171103*/ + /*printk("\n");*/ + sprintf(fbufp + (iArrayIndex + 1) * 7 + y * 2, "\r\n"); + } +#if TOUCH_KEY_NUM > 0 + keydata_output_offset = y_ch * x_ch * 7 + y_ch * 2; + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_ch * x_ch + k; + /*changed by HQ-zmc 20171103*/ + /*printk("%5d, ", rawdata[iArrayIndex]);*/ + sprintf(fbufp + keydata_output_offset + k * 7, "%5d, ", rawdata[iArrayIndex]); + } + /*changed by HQ-zmc 20171103*/ + /*printk("\n");*/ + sprintf(fbufp + y_ch * x_ch * 7 + y_ch * 2 + Key_Channel * 7, "\r\n"); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + org_fs = get_fs(); + set_fs(KERNEL_DS); + fp = filp_open(file_path, O_RDWR | O_CREAT, 0644); + if (fp == NULL || IS_ERR(fp)) { + NVT_ERR("open %s failed\n", file_path); + set_fs(org_fs); + if (fbufp) { + kfree(fbufp); + fbufp = NULL; + } + return -EPERM; + } + +#if TOUCH_KEY_NUM > 0 + output_len = y_ch * x_ch * 7 + y_ch * 2 + Key_Channel * 7 + 2; +#else + output_len = y_ch * x_ch * 7 + y_ch * 2; +#endif /* #if TOUCH_KEY_NUM > 0 */ + pos = offset; + write_ret = vfs_write(fp, (char __user *)fbufp, output_len, &pos); + if (write_ret <= 0) { + NVT_ERR("write %s failed\n", file_path); + set_fs(org_fs); + if (fp) { + filp_close(fp, NULL); + fp = NULL; + } + if (fbufp) { + kfree(fbufp); + fbufp = NULL; + } + return -EPERM; + } + + set_fs(org_fs); + if (fp) { + filp_close(fp, NULL); + fp = NULL; + } + if (fbufp) { + kfree(fbufp); + fbufp = NULL; + } + + printk("%s:--\n", __func__); + + return 0; +} + +static int32_t nvt_polling_hand_shake_status(void) +{ + uint8_t buf[8] = {0}; + int32_t i = 0; + const int32_t retry = 50; + + for (i = 0; i < retry; i++) { + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE; + buf[1] = 0x00; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2); + + if ((buf[1] == 0xA0) || (buf[1] == 0xA1)) + break; + + msleep(10); + } + + if (i >= retry) { + NVT_ERR("polling hand shake status failed, buf[1]=0x%02X\n", buf[1]); + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 6); + NVT_ERR("Read back 5 bytes from offset EVENT_MAP_HOST_CMD: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", buf[1], buf[2], buf[3], buf[4], buf[5]); + + return -EPERM; + } else { + return 0; + } +} + +static int8_t nvt_switch_FreqHopEnDis(uint8_t FreqHopEnDis) +{ + uint8_t buf[8] = {0}; + uint8_t retry = 0; + int8_t ret = 0; + + NVT_LOG("++\n"); + + for (retry = 0; retry < 20; retry++) { + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = FreqHopEnDis; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2); + + msleep(35); + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0xFF; + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2); + + if (buf[1] == 0x00) + break; + } + + if (unlikely(retry == 20)) { + NVT_ERR("switch FreqHopEnDis 0x%02X failed, buf[1]=0x%02X\n", FreqHopEnDis, buf[1]); + ret = -1; + } + + NVT_LOG("--\n"); + + return ret; +} + +static int32_t nvt_read_baseline(int32_t *xdata) +{ + uint8_t x_num = 0; + uint8_t y_num = 0; + uint32_t x = 0; + uint32_t y = 0; + int32_t iArrayIndex = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + + NVT_LOG("++\n"); + + nvt_read_mdata(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_BTN_ADDR); + + nvt_get_mdata(xdata, &x_num, &y_num); + + for (y = 0; y < y_num; y++) { + for (x = 0; x < x_num; x++) { + iArrayIndex = y * x_num + x; + if (ts->carrier_system) { + xdata[iArrayIndex] = (uint16_t)xdata[iArrayIndex]; + } else { + xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex]; + } + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = Y_Channel * X_Channel + k; + if (ts->carrier_system) { + xdata[iArrayIndex] = (uint16_t)xdata[iArrayIndex]; + } else { + xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex]; + } + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + printk("%s:\n", __func__); + + if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, FW_RAWDATA_CSV_FILE, 0) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + + NVT_LOG("--\n"); + + return 0; +} + +static int32_t nvt_read_CC(int32_t *xdata) +{ + uint8_t x_num = 0; + uint8_t y_num = 0; + uint32_t x = 0; + uint32_t y = 0; + int32_t iArrayIndex = 0; + int32_t xdata_tmp = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + uint32_t rawdata_cc_q_offset = 0; + + NVT_LOG("++\n"); + + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR); + else + nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR); + + nvt_get_mdata(xdata, &x_num, &y_num); + + for (y = 0; y < y_num; y++) { + for (x = 0; x < x_num; x++) { + iArrayIndex = y * x_num + x; + if (ts->carrier_system) { + xdata_tmp = xdata[iArrayIndex]; + RawData_FW_CC_I[iArrayIndex] = (uint8_t)(xdata_tmp & 0xFF); + RawData_FW_CC_Q[iArrayIndex] = (uint8_t)((xdata_tmp >> 8) & 0xFF); + } else { + xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex]; + } + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = Y_Channel * X_Channel + k; + if (ts->carrier_system) { + xdata_tmp = xdata[iArrayIndex]; + RawData_FW_CC_I[iArrayIndex] = (uint8_t)(xdata_tmp & 0xFF); + RawData_FW_CC_Q[iArrayIndex] = (uint8_t)((xdata_tmp >> 8) & 0xFF); + } else { + xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex]; + } + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + printk("%s:\n", __func__); + if (ts->carrier_system) { + printk("%s:RawData_CC_I:\n", __func__); + + if (nvt_save_rawdata_to_csv(RawData_FW_CC_I, X_Channel, Y_Channel, FW_CC_CSV_FILE, 0) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } +#if TOUCH_KEY_NUM > 0 + rawdata_cc_q_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2; +#else + rawdata_cc_q_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2; +#endif /* #if TOUCH_KEY_NUM > 0 */ + printk("%s:RawData_CC_Q:\n", __func__); + + if (nvt_save_rawdata_to_csv(RawData_FW_CC_Q, X_Channel, Y_Channel, FW_CC_CSV_FILE, rawdata_cc_q_offset) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + } else { + + if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, FW_CC_CSV_FILE, 0) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + } + + NVT_LOG("--\n"); + + return 0; +} + +static void nvt_enable_noise_collect(int32_t frame_num) +{ + uint8_t buf[8] = {0}; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x47; + buf[2] = 0xAA; + buf[3] = frame_num; + buf[4] = 0x00; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5); +} + +static int32_t nvt_read_fw_noise(int32_t *xdata) +{ + uint8_t x_num = 0; + uint8_t y_num = 0; + uint32_t x = 0; + uint32_t y = 0; + int32_t iArrayIndex = 0; + int32_t frame_num = 0; + uint32_t rawdata_diff_min_offset = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + + NVT_LOG("++\n"); + + + if (nvt_clear_fw_status()) { + return -EAGAIN; + } + + frame_num = PS_Config_Diff_Test_Frame / 10; + if (frame_num <= 0) + frame_num = 1; + printk("%s: frame_num=%d\n", __func__, frame_num); + nvt_enable_noise_collect(frame_num); + + msleep(frame_num * 83); + + if (nvt_polling_hand_shake_status()) { + return -EAGAIN; + } + + if (nvt_get_fw_info()) { + return -EAGAIN; + } + + if (nvt_get_fw_pipe() == 0) + nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR); + else + nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR); + + nvt_get_mdata(xdata, &x_num, &y_num); + + for (y = 0; y < y_num; y++) { + for (x = 0; x < x_num; x++) { + iArrayIndex = y * x_num + x; + if (ts->carrier_system) { + RawData_Diff_Max[iArrayIndex] = (uint16_t)xdata[iArrayIndex]; + RawData_Diff_Min[iArrayIndex] = 0; + } else { + RawData_Diff_Max[iArrayIndex] = (int8_t)((xdata[iArrayIndex] >> 8) & 0xFF); + RawData_Diff_Min[iArrayIndex] = (int8_t)(xdata[iArrayIndex] & 0xFF); + } + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = Y_Channel * X_Channel + k; + if (ts->carrier_system) { + RawData_Diff_Max[iArrayIndex] = (uint16_t)xdata[iArrayIndex]; + RawData_Diff_Min[iArrayIndex] = 0; + } else { + RawData_Diff_Max[iArrayIndex] = (int8_t)((xdata[iArrayIndex] >> 8) & 0xFF); + RawData_Diff_Min[iArrayIndex] = (int8_t)(xdata[iArrayIndex] & 0xFF); + } + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + + nvt_change_mode(NORMAL_MODE); + + printk("%s:RawData_Diff_Max:\n", __func__); + + if (nvt_save_rawdata_to_csv(RawData_Diff_Max, X_Channel, Y_Channel, NOISE_TEST_CSV_FILE, 0) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + + if (!ts->carrier_system) { +#if TOUCH_KEY_NUM > 0 + rawdata_diff_min_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2; +#else + rawdata_diff_min_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2; +#endif /* #if TOUCH_KEY_NUM > 0 */ + printk("%s:RawData_Diff_Min:\n", __func__); + + if (nvt_save_rawdata_to_csv(RawData_Diff_Min, X_Channel, Y_Channel, NOISE_TEST_CSV_FILE, rawdata_diff_min_offset) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + } + + NVT_LOG("--\n"); + + return 0; +} + +static void nvt_enable_open_test(void) +{ + uint8_t buf[8] = {0}; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x45; + buf[2] = 0xAA; + buf[3] = 0x02; + buf[4] = 0x00; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5); +} + +static void nvt_enable_short_test(void) +{ + uint8_t buf[8] = {0}; + + + buf[0] = 0xFF; + buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF; + buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + + + buf[0] = EVENT_MAP_HOST_CMD; + buf[1] = 0x43; + buf[2] = 0xAA; + buf[3] = 0x02; + buf[4] = 0x00; + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5); +} + +static int32_t nvt_read_fw_open(int32_t *xdata) +{ + uint32_t raw_pipe_addr = 0; + uint8_t *rawdata_buf = NULL; + uint32_t x = 0; + uint32_t y = 0; + uint8_t buf[128] = {0}; +#if TOUCH_KEY_NUM > 0 + uint32_t raw_btn_pipe_addr = 0; + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + + NVT_LOG("++\n"); + + + if (nvt_clear_fw_status()) { + return -EAGAIN; + } + + nvt_enable_open_test(); + + if (nvt_polling_hand_shake_status()) { + return -EAGAIN; + } + +#if TOUCH_KEY_NUM > 0 + rawdata_buf = (uint8_t *)kzalloc((IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE) * 2, GFP_KERNEL); +#else + rawdata_buf = (uint8_t *)kzalloc(IC_X_CFG_SIZE * IC_Y_CFG_SIZE * 2, GFP_KERNEL); +#endif /* #if TOUCH_KEY_NUM > 0 */ + if (!rawdata_buf) { + NVT_ERR("kzalloc for rawdata_buf failed!\n"); + return -ENOMEM; + } + + if (nvt_get_fw_pipe() == 0) + raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR; + else + raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR; + + for (y = 0; y < IC_Y_CFG_SIZE; y++) { + + buf[0] = 0xFF; + buf[1] = (uint8_t)(((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) >> 16) & 0xFF); + buf[2] = (uint8_t)(((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + buf[0] = (uint8_t)((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, IC_X_CFG_SIZE * 2 + 1); + memcpy(rawdata_buf + y * IC_X_CFG_SIZE * 2, buf + 1, IC_X_CFG_SIZE * 2); + } +#if TOUCH_KEY_NUM > 0 + if (nvt_get_fw_pipe() == 0) + raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR; + else + raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR; + + + buf[0] = 0xFF; + buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF); + buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, IC_KEY_CFG_SIZE * 2 + 1); + memcpy(rawdata_buf + IC_Y_CFG_SIZE * IC_X_CFG_SIZE * 2, buf + 1, IC_KEY_CFG_SIZE * 2); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + for (y = 0; y < IC_Y_CFG_SIZE; y++) { + for (x = 0; x < IC_X_CFG_SIZE; x++) { + if ((AIN_Y[y] != 0xFF) && (AIN_X[x] != 0xFF)) { + xdata[AIN_Y[y] * X_Channel + AIN_X[x]] = (int16_t)((rawdata_buf[(y * IC_X_CFG_SIZE + x) * 2] + 256 * rawdata_buf[(y * IC_X_CFG_SIZE + x) * 2 + 1])); + } + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < IC_KEY_CFG_SIZE; k++) { + if (AIN_KEY[k] != 0xFF) + xdata[Y_Channel * X_Channel + AIN_KEY[k]] = (int16_t)(rawdata_buf[(IC_Y_CFG_SIZE * IC_X_CFG_SIZE + k) * 2] + 256 * rawdata_buf[(IC_Y_CFG_SIZE * IC_X_CFG_SIZE + k) * 2 + 1]); + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + if (rawdata_buf) { + kfree(rawdata_buf); + rawdata_buf = NULL; + } + + + nvt_change_mode(NORMAL_MODE); + + + printk("%s:RawData_Open\n", __func__); + + if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, OPEN_TEST_CSV_FILE, 0) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + + NVT_LOG("--\n"); + + return 0; +} + +static int32_t nvt_read_fw_short(int32_t *xdata) +{ + uint32_t raw_pipe_addr = 0; + uint8_t *rawdata_buf = NULL; + uint32_t x = 0; + uint32_t y = 0; + uint8_t buf[128] = {0}; + int32_t iArrayIndex = 0; +#if TOUCH_KEY_NUM > 0 + uint32_t raw_btn_pipe_addr = 0; + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + uint32_t rawdata_short_base_offset = 0; + + NVT_LOG("++\n"); + + + if (nvt_clear_fw_status()) { + return -EAGAIN; + } + + nvt_enable_short_test(); + + if (nvt_polling_hand_shake_status()) { + return -EAGAIN; + } + +#if TOUCH_KEY_NUM > 0 + rawdata_buf = (uint8_t *)kzalloc((X_Channel * Y_Channel + Key_Channel) * 2, GFP_KERNEL); +#else + rawdata_buf = (uint8_t *)kzalloc(X_Channel * Y_Channel * 2, GFP_KERNEL); +#endif /* #if TOUCH_KEY_NUM > 0 */ + if (!rawdata_buf) { + NVT_ERR("kzalloc for rawdata_buf failed!\n"); + return -ENOMEM; + } + + if (ts->carrier_system) { + + raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR; + } else { + if (nvt_get_fw_pipe() == 0) + raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR; + else + raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR; + } + + for (y = 0; y < Y_Channel; y++) { + + buf[0] = 0xFF; + buf[1] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 16) & 0xFF); + buf[2] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + buf[0] = (uint8_t)((raw_pipe_addr + y * X_Channel * 2) & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, X_Channel * 2 + 1); + memcpy(rawdata_buf + y * X_Channel * 2, buf + 1, X_Channel * 2); + } +#if TOUCH_KEY_NUM > 0 + if (ts->carrier_system) { + + raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR; + } else { + if (nvt_get_fw_pipe() == 0) + raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR; + else + raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR; + } + + + buf[0] = 0xFF; + buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF); + buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, Key_Channel * 2 + 1); + memcpy(rawdata_buf + Y_Channel * X_Channel * 2, buf + 1, Key_Channel * 2); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + for (y = 0; y < Y_Channel; y++) { + for (x = 0; x < X_Channel; x++) { + iArrayIndex = y * X_Channel + x; + xdata[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]); + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = Y_Channel * X_Channel + k; + xdata[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]); + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + + if (ts->carrier_system) { + + raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR; + + for (y = 0; y < Y_Channel; y++) { + + buf[0] = 0xFF; + buf[1] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 16) & 0xFF); + buf[2] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + buf[0] = (uint8_t)((raw_pipe_addr + y * X_Channel * 2) & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, X_Channel * 2 + 1); + memcpy(rawdata_buf + y * X_Channel * 2, buf + 1, X_Channel * 2); + } +#if TOUCH_KEY_NUM > 0 + + raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR; + + + buf[0] = 0xFF; + buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF); + buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF); + CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3); + buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF); + CTP_I2C_READ(ts->client, I2C_FW_Address, buf, Key_Channel * 2 + 1); + memcpy(rawdata_buf + Y_Channel * X_Channel * 2, buf + 1, Key_Channel * 2); +#endif /* #if TOUCH_KEY_NUM > 0 */ + + for (y = 0; y < Y_Channel; y++) { + for (x = 0; x < X_Channel; x++) { + iArrayIndex = y * X_Channel + x; + RawData_Short_Base[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]); + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = Y_Channel * X_Channel + k; + RawData_Short_Base[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]); + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + } + + if (rawdata_buf) { + kfree(rawdata_buf); + rawdata_buf = NULL; + } + + + nvt_change_mode(NORMAL_MODE); + + if (ts->carrier_system) + printk("%s:RawData_Short_Diff:\n", __func__); + else + printk("%s:RawData_Short\n", __func__); + + if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, SHORT_TEST_CSV_FILE, 0) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + if (ts->carrier_system) { +#if TOUCH_KEY_NUM > 0 + rawdata_short_base_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2; +#else + rawdata_short_base_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2; +#endif /* #if TOUCH_KEY_NUM > 0 */ + printk("%s:RawData_Short_Base:\n", __func__); + + if (nvt_save_rawdata_to_csv(RawData_Short_Base, X_Channel, Y_Channel, SHORT_TEST_CSV_FILE, rawdata_short_base_offset) < 0) { + NVT_ERR("save rawdata to CSV file failed\n"); + return -EAGAIN; + } + } + + NVT_LOG("--\n"); + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen raw data test function. + +return: + Executive outcomes. 0---passed. negative---failed. +*******************************************************/ +static int32_t RawDataTest_Sub(int32_t rawdata[], uint8_t RecordResult[], uint8_t x_ch, uint8_t y_ch, int32_t Rawdata_Limit_Postive, int32_t Rawdata_Limit_Negative, + int32_t Rawdata_Limit_Key_Postive, int32_t Rawdata_Limit_Key_Negative) +{ + int32_t i = 0; + int32_t j = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + int32_t iArrayIndex = 0; + bool isPass = true; + + for (j = 0; j < y_ch; j++) { + for (i = 0; i < x_ch; i++) { + iArrayIndex = j * x_ch + i; + + RecordResult[iArrayIndex] = 0x00; + + if (rawdata[iArrayIndex] > Rawdata_Limit_Postive) + RecordResult[iArrayIndex] |= 0x01; + + if (rawdata[iArrayIndex] < Rawdata_Limit_Negative) + RecordResult[iArrayIndex] |= 0x02; + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_ch * x_ch + k; + + RecordResult[iArrayIndex] = 0x00; + + if (rawdata[iArrayIndex] > Rawdata_Limit_Key_Postive) + RecordResult[iArrayIndex] |= 0x01; + + if (rawdata[iArrayIndex] < Rawdata_Limit_Key_Negative) + RecordResult[iArrayIndex] |= 0x02; + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + + for (j = 0; j < y_ch; j++) { + for (i = 0; i < x_ch; i++) { + if (RecordResult[j * x_ch + i] != 0) { + isPass = false; + break; + } + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_ch * x_ch + k; + if (RecordResult[iArrayIndex] != 0) { + isPass = false; + break; + } + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + if (isPass == false) { + return -EPERM; + } else { + return 0; + } +} + +/******************************************************* +Description: + Novatek touchscreen raw data test for each single point function. + +return: + Executive outcomes. 0---passed. negative---failed. +*******************************************************/ +static int32_t RawDataTest_SinglePoint_Sub(int32_t rawdata[], uint8_t RecordResult[], uint8_t x_ch, uint8_t y_ch, int32_t Rawdata_Limit_Postive[], int32_t Rawdata_Limit_Negative[]) +{ + int32_t i = 0; + int32_t j = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + int32_t iArrayIndex = 0; + bool isPass = true; + + for (j = 0; j < y_ch; j++) { + for (i = 0; i < x_ch; i++) { + iArrayIndex = j * x_ch + i; + + RecordResult[iArrayIndex] = 0x00; + + if (rawdata[iArrayIndex] > Rawdata_Limit_Postive[iArrayIndex]) + RecordResult[iArrayIndex] |= 0x01; + + if (rawdata[iArrayIndex] < Rawdata_Limit_Negative[iArrayIndex]) + RecordResult[iArrayIndex] |= 0x02; + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_ch * x_ch + k; + + RecordResult[iArrayIndex] = 0x00; + + if (rawdata[iArrayIndex] > Rawdata_Limit_Postive[iArrayIndex]) + RecordResult[iArrayIndex] |= 0x01; + + if (rawdata[iArrayIndex] < Rawdata_Limit_Negative[iArrayIndex]) + RecordResult[iArrayIndex] |= 0x02; + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + + for (j = 0; j < y_ch; j++) { + for (i = 0; i < x_ch; i++) { + if (RecordResult[j * x_ch + i] != 0) { + isPass = false; + break; + } + } + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_ch * x_ch + k; + if (RecordResult[iArrayIndex] != 0) { + isPass = false; + break; + } + } +#endif /* #if TOUCH_KEY_NUM > 0 */ + + if (isPass == false) { + return -EPERM; + } else { + return 0; + } +} + +/******************************************************* +Description: + Novatek touchscreen print self-test result function. + +return: + n.a. +*******************************************************/ +void print_selftest_result(struct seq_file *m, int32_t TestResult, uint8_t RecordResult[], int32_t rawdata[], uint8_t x_len, uint8_t y_len) +{ + int32_t i = 0; + int32_t j = 0; + int32_t iArrayIndex = 0; +#if TOUCH_KEY_NUM > 0 + int32_t k = 0; +#endif /* #if TOUCH_KEY_NUM > 0 */ + + switch (TestResult) { + case 0: + nvt_mp_seq_printf(m, " PASS!\n"); + break; + + case 1: + nvt_mp_seq_printf(m, " ERROR! Read Data FAIL!\n"); + nvt_ito_test_result = 0; + break; + + case -1: + nvt_ito_test_result = 0; + nvt_mp_seq_printf(m, " FAIL!\n"); + nvt_mp_seq_printf(m, "RecordResult:\n"); + for (i = 0; i < y_len; i++) { + for (j = 0; j < x_len; j++) { + iArrayIndex = i * x_len + j; + nvt_mp_seq_printf(m, "0x%02X, ", RecordResult[iArrayIndex]); + } + nvt_mp_seq_printf(m, "\n"); + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_len * x_len + k; + nvt_mp_seq_printf(m, "0x%02X, ", RecordResult[iArrayIndex]); + } + nvt_mp_seq_printf(m, "\n"); +#endif /* #if TOUCH_KEY_NUM > 0 */ + nvt_mp_seq_printf(m, "ReadData:\n"); + for (i = 0; i < y_len; i++) { + for (j = 0; j < x_len; j++) { + iArrayIndex = i * x_len + j; + nvt_mp_seq_printf(m, "%5d, ", rawdata[iArrayIndex]); + } + nvt_mp_seq_printf(m, "\n"); + } +#if TOUCH_KEY_NUM > 0 + for (k = 0; k < Key_Channel; k++) { + iArrayIndex = y_len * x_len + k; + nvt_mp_seq_printf(m, "%5d, ", rawdata[iArrayIndex]); + } + nvt_mp_seq_printf(m, "\n"); +#endif /* #if TOUCH_KEY_NUM > 0 */ + break; + } + nvt_mp_seq_printf(m, "\n"); +} + +/******************************************************* +Description: + Novatek touchscreen self-test sequence print show + function. + +return: + Executive outcomes. 0---succeed. +*******************************************************/ +static int32_t c_show_selftest(struct seq_file *m, void *v) +{ + NVT_LOG("++\n"); + + nvt_mp_seq_printf(m, "FW Version: %d\n\n", ts->fw_ver); + + nvt_mp_seq_printf(m, "Short Test"); + if ((TestResult_Short == 0) || (TestResult_Short == 1)) { + print_selftest_result(m, TestResult_Short, RecordResult_Short, RawData_Short, X_Channel, Y_Channel); + } else { + if (ts->carrier_system) { + nvt_mp_seq_printf(m, " FAIL!\n"); + if (TestResult_Short_Diff == -1) { + nvt_mp_seq_printf(m, "Short Diff"); + print_selftest_result(m, TestResult_Short_Diff, RecordResult_Short_Diff, RawData_Short_Diff, X_Channel, Y_Channel); + } + if (TestResult_Short_Base == -1) { + nvt_mp_seq_printf(m, "Short Base"); + print_selftest_result(m, TestResult_Short_Base, RecordResult_Short_Base, RawData_Short_Base, X_Channel, Y_Channel); + } + } else { + print_selftest_result(m, TestResult_Short, RecordResult_Short, RawData_Short, X_Channel, Y_Channel); + } + } + + nvt_mp_seq_printf(m, "Open Test"); + print_selftest_result(m, TestResult_Open, RecordResult_Open, RawData_Open, X_Channel, Y_Channel); + + nvt_mp_seq_printf(m, "FW Rawdata Test"); + if ((TestResult_FW_Rawdata == 0) || (TestResult_FW_Rawdata == 1)) { + print_selftest_result(m, TestResult_FWMutual, RecordResult_FWMutual, RawData_FWMutual, X_Channel, Y_Channel); + } else { + nvt_mp_seq_printf(m, " FAIL!\n"); + if (TestResult_FWMutual == -1) { + nvt_mp_seq_printf(m, "FW Mutual"); + print_selftest_result(m, TestResult_FWMutual, RecordResult_FWMutual, RawData_FWMutual, X_Channel, Y_Channel); + } + if (TestResult_FW_CC == -1) { + if (ts->carrier_system) { + if (TestResult_FW_CC_I == -1) { + nvt_mp_seq_printf(m, "FW CC_I"); + print_selftest_result(m, TestResult_FW_CC_I, RecordResult_FW_CC_I, RawData_FW_CC_I, X_Channel, Y_Channel); + } + if (TestResult_FW_CC_Q == -1) { + nvt_mp_seq_printf(m, "FW CC_Q"); + print_selftest_result(m, TestResult_FW_CC_Q, RecordResult_FW_CC_Q, RawData_FW_CC_Q, X_Channel, Y_Channel); + } + } else { + nvt_mp_seq_printf(m, "FW CC"); + print_selftest_result(m, TestResult_FW_CC, RecordResult_FW_CC, RawData_FW_CC, X_Channel, Y_Channel); + } + } + } + + nvt_mp_seq_printf(m, "Noise Test"); + if ((TestResult_Noise == 0) || (TestResult_Noise == 1)) { + print_selftest_result(m, TestResult_FW_DiffMax, RecordResult_FW_DiffMax, RawData_Diff_Max, X_Channel, Y_Channel); + } else { + nvt_mp_seq_printf(m, " FAIL!\n"); + + if (TestResult_FW_DiffMax == -1) { + nvt_mp_seq_printf(m, "FW Diff Max"); + print_selftest_result(m, TestResult_FW_DiffMax, RecordResult_FW_DiffMax, RawData_Diff_Max, X_Channel, Y_Channel); + } + if (TestResult_FW_DiffMin == -1) { + nvt_mp_seq_printf(m, "FW Diff Min"); + print_selftest_result(m, TestResult_FW_DiffMin, RecordResult_FW_DiffMin, RawData_Diff_Min, X_Channel, Y_Channel); + } + } + + nvt_mp_test_result_printed = 1; + + NVT_LOG("--\n"); + + return 0; +} + +/******************************************************* +Description: + Novatek touchscreen self-test sequence print start + function. + +return: + Executive outcomes. 1---call next function. + NULL---not call next function and sequence loop + stop. +*******************************************************/ +static void *c_start(struct seq_file *m, loff_t *pos) +{ + return *pos < 1 ? (void *)1 : NULL; +} + +/******************************************************* +Description: + Novatek touchscreen self-test sequence print next + function. + +return: + Executive outcomes. NULL---no next and call sequence + stop function. +*******************************************************/ +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return NULL; +} + +/******************************************************* +Description: + Novatek touchscreen self-test sequence print stop + function. + +return: + n.a. +*******************************************************/ +static void c_stop(struct seq_file *m, void *v) +{ + return; +} + +const struct seq_operations nvt_selftest_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show_selftest +}; + +/******************************************************* +Description: + Novatek touchscreen /proc/nvt_selftest open function. + +return: + Executive outcomes. 0---succeed. negative---failed. +*******************************************************/ +static int32_t nvt_selftest_open(struct inode *inode, struct file *file) +{ + TestResult_Short = 0; + TestResult_Short_Diff = 0; + TestResult_Short_Base = 0; + TestResult_Open = 0; + TestResult_FW_Rawdata = 0; + TestResult_FWMutual = 0; + TestResult_FW_CC = 0; + TestResult_FW_CC_I = 0; + TestResult_FW_CC_Q = 0; + TestResult_Noise = 0; + TestResult_FW_DiffMax = 0; + TestResult_FW_DiffMin = 0; + + nvt_ito_test_result = 1; + + NVT_LOG("++\n"); + + if (mutex_lock_interruptible(&ts->lock)) { + return -ERESTARTSYS; + } +#if NVT_TOUCH_ESD_PROTECT + nvt_esd_check_enable(false); +#endif + + + nvt_print_criteria(); + + if (nvt_switch_FreqHopEnDis(FREQ_HOP_DISABLE)) { + mutex_unlock(&ts->lock); + NVT_ERR("switch frequency hopping disable failed!\n"); + return -EAGAIN; + } + + if (nvt_check_fw_reset_state(RESET_STATE_NORMAL_RUN)) { + mutex_unlock(&ts->lock); + NVT_ERR("check fw reset state failed!\n"); + return -EAGAIN; + } + + msleep(100); + + + if (nvt_clear_fw_status()) { + mutex_unlock(&ts->lock); + NVT_ERR("clear fw status failed!\n"); + return -EAGAIN; + } + + nvt_change_mode(MP_MODE_CC); + + if (nvt_check_fw_status()) { + mutex_unlock(&ts->lock); + NVT_ERR("check fw status failed!\n"); + return -EAGAIN; + } + + if (nvt_get_fw_info()) { + mutex_unlock(&ts->lock); + NVT_ERR("get fw info failed!\n"); + return -EAGAIN; + } + + + if (nvt_read_baseline(RawData_FWMutual) != 0) { + TestResult_FWMutual = 1; + } else { + TestResult_FWMutual = RawDataTest_SinglePoint_Sub(RawData_FWMutual, RecordResult_FWMutual, X_Channel, Y_Channel, + PS_Config_Lmt_FW_Rawdata_P, PS_Config_Lmt_FW_Rawdata_N); + } + if (nvt_read_CC(RawData_FW_CC) != 0) { + TestResult_FW_CC = 1; + if (ts->carrier_system) { + TestResult_FW_CC_I = 1; + TestResult_FW_CC_Q = 1; + } + } else { + if (ts->carrier_system) { + TestResult_FW_CC_I = RawDataTest_Sub(RawData_FW_CC_I, RecordResult_FW_CC_I, X_Channel, Y_Channel, + PS_Config_Lmt_FW_CC_I_P, PS_Config_Lmt_FW_CC_I_N, + PS_Config_Lmt_Key_FW_CC_I_P, PS_Config_Lmt_Key_FW_CC_I_N); + TestResult_FW_CC_Q = RawDataTest_Sub(RawData_FW_CC_Q, RecordResult_FW_CC_Q, X_Channel, Y_Channel, + PS_Config_Lmt_FW_CC_Q_P, PS_Config_Lmt_FW_CC_Q_N, + PS_Config_Lmt_Key_FW_CC_Q_P, PS_Config_Lmt_Key_FW_CC_Q_N); + if ((TestResult_FW_CC_I == -1) || (TestResult_FW_CC_Q == -1)) + TestResult_FW_CC = -1; + else + TestResult_FW_CC = 0; + } else { + TestResult_FW_CC = RawDataTest_Sub(RawData_FW_CC, RecordResult_FW_CC, X_Channel, Y_Channel, + PS_Config_Lmt_FW_CC_P, PS_Config_Lmt_FW_CC_N, + PS_Config_Lmt_Key_FW_CC_P, PS_Config_Lmt_Key_FW_CC_N); + } + } + + if ((TestResult_FWMutual == 1) || (TestResult_FW_CC == 1)) { + TestResult_FW_Rawdata = 1; + } else { + if ((TestResult_FWMutual == -1) || (TestResult_FW_CC == -1)) + TestResult_FW_Rawdata = -1; + else + TestResult_FW_Rawdata = 0; + } + + + nvt_change_mode(NORMAL_MODE); + + + if (nvt_read_fw_noise(RawData_Diff) != 0) { + TestResult_Noise = 1; + TestResult_FW_DiffMax = 1; + TestResult_FW_DiffMin = 1; + } else { + TestResult_FW_DiffMax = RawDataTest_Sub(RawData_Diff_Max, RecordResult_FW_DiffMax, X_Channel, Y_Channel, + PS_Config_Lmt_FW_Diff_P, PS_Config_Lmt_FW_Diff_N, + PS_Config_Lmt_Key_FW_Diff_P, PS_Config_Lmt_Key_FW_Diff_N); + + + if (ts->carrier_system) { + TestResult_FW_DiffMin = 0; + } else { + TestResult_FW_DiffMin = RawDataTest_Sub(RawData_Diff_Min, RecordResult_FW_DiffMin, X_Channel, Y_Channel, + PS_Config_Lmt_FW_Diff_P, PS_Config_Lmt_FW_Diff_N, + PS_Config_Lmt_Key_FW_Diff_P, PS_Config_Lmt_Key_FW_Diff_N); + } + + if ((TestResult_FW_DiffMax == -1) || (TestResult_FW_DiffMin == -1)) + TestResult_Noise = -1; + else + TestResult_Noise = 0; + } + + + if (nvt_read_fw_short(RawData_Short) != 0) { + TestResult_Short = 1; + if (ts->carrier_system) { + TestResult_Short_Diff = 1; + TestResult_Short_Base = 1; + } + } else { + + if (ts->carrier_system) { + TestResult_Short_Diff = RawDataTest_Sub(RawData_Short_Diff, RecordResult_Short_Diff, X_Channel, Y_Channel, + PS_Config_Lmt_Short_Diff_P, PS_Config_Lmt_Short_Diff_N, + PS_Config_Lmt_Key_Short_Diff_P, PS_Config_Lmt_Key_Short_Diff_N); + TestResult_Short_Base = RawDataTest_Sub(RawData_Short_Base, RecordResult_Short_Base, X_Channel, Y_Channel, + PS_Config_Lmt_Short_Base_P, PS_Config_Lmt_Short_Base_N, + PS_Config_Lmt_Key_Short_Base_P, PS_Config_Lmt_Key_Short_Base_N); + + if ((TestResult_Short_Diff == -1) || (TestResult_Short_Base == -1)) + TestResult_Short = -1; + else + TestResult_Short = 0; + } else { + TestResult_Short = RawDataTest_Sub(RawData_Short, RecordResult_Short, X_Channel, Y_Channel, + PS_Config_Lmt_Short_Rawdata_P, PS_Config_Lmt_Short_Rawdata_N, + PS_Config_Lmt_Key_Short_Rawdata_P, PS_Config_Lmt_Key_Short_Rawdata_N); + } + } + + + if (nvt_read_fw_open(RawData_Open) != 0) { + TestResult_Open = 1; + } else { + + TestResult_Open = RawDataTest_SinglePoint_Sub(RawData_Open, RecordResult_Open, X_Channel, Y_Channel, + PS_Config_Lmt_Open_Rawdata_P, PS_Config_Lmt_Open_Rawdata_N); + } + + + nvt_bootloader_reset(); + + mutex_unlock(&ts->lock); + + NVT_LOG("--\n"); + + nvt_mp_test_result_printed = 0; + + return seq_open(file, &nvt_selftest_seq_ops); +} + +static const struct file_operations nvt_selftest_fops = { + .owner = THIS_MODULE, + .open = nvt_selftest_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/******************************************************* +Description: + Novatek touchscreen parse AIN setting for array type. + +return: + n.a. +*******************************************************/ +void nvt_mp_parse_ain(struct device_node *np, const char *name, uint8_t *array, int32_t size) +{ + struct property *data; + int32_t len, ret; + int32_t tmp[40]; + int32_t i; + + data = of_find_property(np, name, &len); + len /= sizeof(u32); + if ((!data) || (!len) || (len != size)) { + NVT_ERR("error find %s. len=%d\n", name, len); + } else { + NVT_LOG("%s. len=%d\n", name, len); + ret = of_property_read_u32_array(np, name, tmp, len); + if (ret) { + NVT_ERR("error reading %s. ret=%d\n", name, ret); + return; + } + + for (i = 0; i < len; i++) + array[i] = tmp[i]; + +#if NVT_DEBUG + printk("[NVT-ts] %s = ", name); + for (i = 0; i < len; i++) { + printk("%02d ", array[i]); + } + printk("\n"); +#endif + } +} + +/******************************************************* +Description: + Novatek touchscreen parse criterion for u32 type. + +return: + n.a. +*******************************************************/ +void nvt_mp_parse_u32(struct device_node *np, const char *name, int32_t *para) +{ + int32_t ret; + + ret = of_property_read_u32(np, name, para); + if (ret) + NVT_ERR("error reading %s. ret=%d\n", name, ret); + else { +#if NVT_DEBUG + NVT_LOG("%s=%d\n", name, *para); +#endif + } +} + +/******************************************************* +Description: + Novatek touchscreen parse criterion for array type. + +return: + n.a. +*******************************************************/ +void nvt_mp_parse_array(struct device_node *np, const char *name, int32_t *array, + int32_t size) +{ + struct property *data; + int32_t len, ret; +#if NVT_DEBUG + int32_t i, j, iArrayIndex = 0; +#endif + + data = of_find_property(np, name, &len); + len /= sizeof(u32); + if ((!data) || (!len) || (len < size)) { + NVT_ERR("error find %s. len=%d\n", name, len); + } else { + NVT_LOG("%s. len=%d\n", name, len); + ret = of_property_read_u32_array(np, name, array, len); + if (ret) { + NVT_ERR("error reading %s. ret=%d\n", name, ret); + return; + } + +#if NVT_DEBUG + NVT_LOG("%s =\n", name); + for (j = 0; j < Y_Channel; j++) { + printk("[NVT-ts] "); + for (i = 0; i < X_Channel; i++) { + iArrayIndex = j * X_Channel + i; + printk("%d ", array[iArrayIndex]); + } + printk("\n"); + } + + for (i = 0; i < Key_Channel; i++) { + iArrayIndex++; + printk("%d ", array[iArrayIndex]); + } + + printk("\n"); +#endif + } +} + +/******************************************************* +Description: + Novatek touchscreen parse device tree mp function. + +return: + n.a. +*******************************************************/ +void nvt_mp_parse_dt(struct device_node *root, const char *node_compatible) +{ + struct device_node *np = root; + struct device_node *child = NULL; + + NVT_LOG("Parse mp criteria for node %s\n", node_compatible); + + /* find each MP sub-nodes */ + for_each_child_of_node(root, child) { + /* find the specified node */ + if (of_device_is_compatible(child, node_compatible)) { + NVT_LOG("found child node %s\n", node_compatible); + np = child; + break; + } + } + + /* MP Config*/ + nvt_mp_parse_u32(np, "IC_X_CFG_SIZE", &IC_X_CFG_SIZE); + + nvt_mp_parse_u32(np, "IC_Y_CFG_SIZE", &IC_Y_CFG_SIZE); + + nvt_mp_parse_u32(np, "IC_KEY_CFG_SIZE", &IC_KEY_CFG_SIZE); + + nvt_mp_parse_u32(np, "X_Channel", &X_Channel); + + nvt_mp_parse_u32(np, "Y_Channel", &Y_Channel); + + nvt_mp_parse_ain(np, "AIN_X", AIN_X, IC_X_CFG_SIZE); + + nvt_mp_parse_ain(np, "AIN_Y", AIN_Y, IC_Y_CFG_SIZE); + +#if TOUCH_KEY_NUM > 0 + nvt_mp_parse_ain(np, "AIN_KEY", AIN_KEY, IC_KEY_CFG_SIZE); +#endif + + /* MP Criteria */ + nvt_mp_parse_u32(np, "PS_Config_Lmt_Short_Rawdata_P", &PS_Config_Lmt_Short_Rawdata_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Short_Rawdata_N", &PS_Config_Lmt_Short_Rawdata_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_Short_Rawdata_P", &PS_Config_Lmt_Key_Short_Rawdata_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_Short_Rawdata_N", &PS_Config_Lmt_Key_Short_Rawdata_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Short_Diff_P", &PS_Config_Lmt_Short_Diff_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Short_Diff_N", &PS_Config_Lmt_Short_Diff_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_Short_Diff_P", &PS_Config_Lmt_Key_Short_Diff_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_Short_Diff_N", &PS_Config_Lmt_Key_Short_Diff_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Short_Base_P", &PS_Config_Lmt_Short_Base_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Short_Base_N", &PS_Config_Lmt_Short_Base_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_Short_Base_P", &PS_Config_Lmt_Key_Short_Base_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_Short_Base_N", &PS_Config_Lmt_Key_Short_Base_N); + + nvt_mp_parse_array(np, "PS_Config_Lmt_Open_Rawdata_P", PS_Config_Lmt_Open_Rawdata_P, + X_Channel * Y_Channel + Key_Channel); + + nvt_mp_parse_array(np, "PS_Config_Lmt_Open_Rawdata_N", PS_Config_Lmt_Open_Rawdata_N, + X_Channel * Y_Channel + Key_Channel); + + nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Rawdata_P", PS_Config_Lmt_FW_Rawdata_P, + X_Channel * Y_Channel + Key_Channel); + + nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Rawdata_N", PS_Config_Lmt_FW_Rawdata_N, + X_Channel * Y_Channel + Key_Channel); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_CC_P", &PS_Config_Lmt_FW_CC_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_CC_N", &PS_Config_Lmt_FW_CC_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_FW_CC_P", &PS_Config_Lmt_Key_FW_CC_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_FW_CC_N", &PS_Config_Lmt_Key_FW_CC_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_CC_I_P", &PS_Config_Lmt_FW_CC_I_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_CC_I_N", &PS_Config_Lmt_FW_CC_I_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_CC_Q_P", &PS_Config_Lmt_FW_CC_Q_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_CC_Q_N", &PS_Config_Lmt_FW_CC_Q_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_FW_CC_I_P", &PS_Config_Lmt_Key_FW_CC_I_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_FW_CC_I_N", &PS_Config_Lmt_Key_FW_CC_I_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_FW_CC_Q_P", &PS_Config_Lmt_Key_FW_CC_Q_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_Key_FW_CC_Q_N", &PS_Config_Lmt_Key_FW_CC_Q_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_Diff_P", &PS_Config_Lmt_FW_Diff_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_Diff_N", &PS_Config_Lmt_FW_Diff_N); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_Diff_P", &PS_Config_Lmt_FW_Diff_P); + + nvt_mp_parse_u32(np, "PS_Config_Lmt_FW_Diff_N", &PS_Config_Lmt_FW_Diff_N); + + NVT_LOG("Parse mp criteria done!\n"); +} + +static int nvt_ito_test_result_show(struct seq_file *file, void *data) +{ + char temp[5] = {0}; + + if (1 == nvt_ito_test_result){ + strcpy(temp, "pass\n"); + printk("NVT ITO test pass\n"); + } + else{ + strcpy(temp, "fail\n"); + printk("NVT ITO test fail\n"); + } + + seq_printf(file, "%s\n", temp); + + return 0; +} + +static int nvt_ito_test_result_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, nvt_ito_test_result_show, inode->i_private); +} + +static const struct file_operations nvt_ito_test_result_proc_fops = +{ + .open = nvt_ito_test_result_proc_open, + .read = seq_read, +}; + +/******************************************************* +Description: + Novatek touchscreen MP function proc. file node + initial function. + +return: + Executive outcomes. 0---succeed. -1---failed. +*******************************************************/ +int32_t nvt_mp_proc_init(void) +{ + struct device_node *np = ts->client->dev.of_node; + unsigned char mpcriteria[32] = {0}; + + NVT_ito_test_result_entry = proc_create("ito_test_result", 0444, NULL, &nvt_ito_test_result_proc_fops); + if (NVT_ito_test_result_entry == NULL) { + NVT_ERR("create proc/ito_test_result Failed!\n"); + return -EPERM; + } else { + NVT_LOG("create proc/ito_test_result Succeeded!\n"); + } + + NVT_proc_selftest_entry = proc_create("nvt_selftest", 0444, NULL, &nvt_selftest_fops); + if (NVT_proc_selftest_entry == NULL) { + NVT_ERR("create /proc/nvt_selftest Failed!\n"); + return -EPERM; + } else { + if (nvt_mp_buffer_init()) { + NVT_ERR("Allocate mp memory failed\n"); + return -EPERM; + } + else { + /* Parsing criteria from dts */ + if (of_property_read_bool(np, "novatek,mp-support-dt")) { + /* + * Parsing Criteria by Novatek PID + * The string rule is "novatek-mp-criteria-" + * nvt_pid is 2 bytes (show hex). + * + * Ex. nvt_pid = 500A + * mpcriteria = "novatek-mp-criteria-500A" + */ + snprintf(mpcriteria, PAGE_SIZE, "novatek-mp-criteria-%04X", ts->nvt_pid); + + nvt_mp_parse_dt(np, mpcriteria); + } else { + NVT_LOG("Not found novatek,mp-support-dt, use default setting\n"); + } + + NVT_LOG("create /proc/nvt_selftest Succeeded!\n"); + } + return 0; + } +} + +#endif /* #if NVT_TOUCH_MP */ diff --git a/drivers/input/touchscreen/nt36672/nt36xxx_mp_ctrlram.h b/drivers/input/touchscreen/nt36672/nt36xxx_mp_ctrlram.h new file mode 100755 index 0000000000000..015dd54ae604f --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nt36xxx_mp_ctrlram.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2010 - 2017 Novatek, Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * $Revision: 15234 $ + * $Date: 2017-08-09 11:34:54 +0800 (週三, 09 八月 2017) $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#if NVT_TOUCH_MP + +static uint32_t IC_X_CFG_SIZE = 18; +static uint32_t IC_Y_CFG_SIZE = 32; +static uint32_t IC_KEY_CFG_SIZE = 4; +static uint32_t X_Channel = 18; +static uint32_t Y_Channel = 32; +static uint32_t Key_Channel = TOUCH_KEY_NUM; +static uint8_t AIN_X[40] = {17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; +static uint8_t AIN_Y[40] = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; +#if TOUCH_KEY_NUM > 0 +static uint8_t AIN_KEY[8] = {0, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +#endif /* #if TOUCH_KEY_NUM > 0 */ + +static int32_t PS_Config_Lmt_Short_Rawdata_P = 13500; +static int32_t PS_Config_Lmt_Short_Rawdata_N = 11500; +static int32_t PS_Config_Lmt_Key_Short_Rawdata_P = 20000; +static int32_t PS_Config_Lmt_Key_Short_Rawdata_N = 11550; +static int32_t PS_Config_Lmt_Short_Diff_P = 6300; +static int32_t PS_Config_Lmt_Short_Diff_N; +static int32_t PS_Config_Lmt_Key_Short_Diff_P = 6300; +static int32_t PS_Config_Lmt_Key_Short_Diff_N; +static int32_t PS_Config_Lmt_Short_Base_P = 2000; +static int32_t PS_Config_Lmt_Short_Base_N = -2000; +static int32_t PS_Config_Lmt_Key_Short_Base_P = 2000; +static int32_t PS_Config_Lmt_Key_Short_Base_N = -2000; + +static int32_t PS_Config_Lmt_Open_Rawdata_P[40 * 40] = { +10288, 10571, 10538, 10516, 10489, 10469, 10460, 10489, 10509, 10474, 10495, 10470, 10454, 10454, 10458, 10461, 10475, 10402, +10203, 10356, 10326, 10308, 10287, 10276, 10272, 10295, 10305, 10273, 10287, 10268, 10256, 10250, 10251, 10249, 10260, 10258, +10262, 10393, 10367, 10350, 10333, 10337, 10322, 10344, 10348, 10307, 10320, 10298, 10289, 10277, 10279, 10275, 10283, 10281, +10178, 10320, 10290, 10273, 10261, 10258, 10253, 10275, 10276, 10252, 10264, 10245, 10234, 10230, 10219, 10215, 10226, 10208, +10199, 10348, 10307, 10291, 10285, 10278, 10277, 10299, 10299, 10279, 10290, 10270, 10260, 10248, 10245, 10242, 10263, 10234, +10137, 10276, 10233, 10217, 10215, 10216, 10210, 10233, 10231, 10199, 10208, 10189, 10178, 10165, 10164, 10160, 10182, 10153, +10151, 10284, 10241, 10226, 10228, 10225, 10224, 10247, 10246, 10235, 10245, 10225, 10215, 10214, 10202, 10196, 10218, 10190, +10067, 10186, 10153, 10139, 10143, 10140, 10140, 10164, 10162, 10140, 10149, 10127, 10118, 10109, 10106, 10100, 10114, 10093, +10095, 10205, 10188, 10167, 10171, 10167, 10168, 10191, 10189, 10152, 10162, 10139, 10130, 10120, 10119, 10126, 10124, 10106, +9997, 10101, 10083, 10065, 10068, 10065, 10068, 10092, 10090, 10072, 10080, 10057, 10048, 10049, 10038, 10045, 10043, 10026, +10000, 10100, 10082, 10068, 10068, 10068, 10072, 10097, 10094, 10069, 10076, 10053, 10044, 10037, 10035, 10041, 10041, 10021, +9917, 10011, 9988, 9983, 9993, 9983, 9987, 10012, 10009, 9977, 9984, 9959, 9951, 9942, 9943, 9948, 9949, 9930, +9910, 9999, 9969, 9983, 9977, 9974, 9980, 10005, 10001, 9986, 9994, 9969, 9960, 9965, 9961, 9949, 9962, 9938, +9811, 9892, 9867, 9884, 9870, 9871, 9878, 9903, 9899, 9881, 9888, 9862, 9853, 9850, 9861, 9844, 9861, 9832, +9823, 9900, 9880, 9898, 9896, 9884, 9893, 9917, 9911, 9876, 9881, 9856, 9847, 9843, 9857, 9839, 9862, 9826, +9708, 9779, 9763, 9780, 9769, 9769, 9777, 9800, 9794, 9784, 9790, 9764, 9755, 9765, 9768, 9752, 9777, 9735, +9690, 9758, 9747, 9750, 9750, 9752, 9760, 9784, 9780, 9758, 9763, 9739, 9732, 9734, 9732, 9728, 9759, 9711, +9597, 9661, 9652, 9658, 9666, 9668, 9662, 9685, 9681, 9652, 9657, 9632, 9640, 9629, 9631, 9631, 9665, 9610, +9572, 9636, 9628, 9634, 9632, 9632, 9640, 9661, 9656, 9641, 9646, 9623, 9620, 9631, 9623, 9624, 9659, 9598, +9458, 9521, 9513, 9518, 9514, 9519, 9537, 9547, 9542, 9529, 9533, 9522, 9510, 9511, 9512, 9518, 9554, 9485, +9449, 9511, 9504, 9509, 9517, 9512, 9529, 9538, 9533, 9494, 9498, 9485, 9477, 9474, 9478, 9489, 9523, 9448, +9316, 9380, 9371, 9376, 9376, 9381, 9399, 9406, 9401, 9394, 9398, 9389, 9380, 9387, 9380, 9396, 9430, 9347, +9282, 9348, 9339, 9343, 9341, 9350, 9359, 9374, 9368, 9349, 9353, 9335, 9336, 9338, 9338, 9357, 9391, 9301, +9179, 9245, 9237, 9242, 9252, 9249, 9255, 9285, 9265, 9236, 9250, 9218, 9225, 9226, 9229, 9248, 9283, 9186, +9131, 9198, 9190, 9196, 9198, 9205, 9210, 9239, 9219, 9208, 9224, 9192, 9199, 9201, 9207, 9228, 9261, 9158, +9015, 9084, 9077, 9082, 9082, 9093, 9098, 9126, 9105, 9094, 9110, 9078, 9086, 9088, 9099, 9120, 9152, 9042, +8984, 9054, 9046, 9052, 9063, 9062, 9067, 9088, 9072, 9046, 9060, 9032, 9041, 9043, 9057, 9078, 9111, 8989, +8806, 8877, 8871, 8877, 8878, 8882, 8889, 8903, 8902, 8903, 8892, 8872, 8881, 8883, 8903, 8923, 8955, 8828, +8763, 8836, 8830, 8836, 8835, 8838, 8845, 8859, 8861, 8858, 8837, 8818, 8826, 8832, 8853, 8874, 8906, 8769, +8673, 8746, 8741, 8746, 8751, 8743, 8749, 8764, 8765, 8751, 8726, 8705, 8711, 8724, 8747, 8767, 8797, 8650, +8633, 8707, 8701, 8706, 8696, 8697, 8706, 8719, 8716, 8725, 8697, 8677, 8694, 8703, 8726, 8747, 8779, 8621, +10520, 10245, 10233, 10231, 10209, 10213, 10224, 10243, 10220, 10229, 10211, 10185, 10199, 10226, 10252, 10278, 10309, 9059 +#if TOUCH_KEY_NUM > 0 +, 13000, 13000, 13000 +#endif /* #if TOUCH_KEY_NUM > 0 */ +}; + +static int32_t PS_Config_Lmt_Open_Rawdata_N[40 * 40] = { +8578, 8744, 8725, 8712, 8696, 8684, 8679, 8696, 8708, 8687, 8699, 8685, 8675, 8675, 8678, 8679, 8688, 8645, +8528, 8617, 8600, 8590, 8577, 8571, 8568, 8582, 8588, 8569, 8577, 8566, 8559, 8556, 8556, 8555, 8561, 8560, +8562, 8640, 8624, 8614, 8604, 8607, 8598, 8611, 8613, 8589, 8597, 8584, 8578, 8571, 8572, 8570, 8575, 8574, +8513, 8597, 8579, 8569, 8562, 8560, 8557, 8570, 8571, 8556, 8564, 8553, 8546, 8544, 8537, 8535, 8541, 8531, +8525, 8613, 8589, 8579, 8576, 8572, 8571, 8584, 8584, 8572, 8579, 8567, 8561, 8554, 8553, 8551, 8563, 8546, +8489, 8571, 8546, 8536, 8535, 8536, 8532, 8546, 8544, 8525, 8531, 8519, 8513, 8506, 8505, 8502, 8515, 8499, +8497, 8576, 8550, 8541, 8543, 8541, 8540, 8554, 8553, 8547, 8553, 8541, 8535, 8534, 8527, 8524, 8537, 8520, +8448, 8518, 8499, 8490, 8493, 8491, 8491, 8505, 8504, 8491, 8496, 8483, 8478, 8472, 8471, 8467, 8476, 8463, +8464, 8529, 8519, 8507, 8509, 8507, 8507, 8521, 8520, 8498, 8504, 8491, 8485, 8479, 8478, 8483, 8482, 8471, +8407, 8468, 8458, 8447, 8449, 8447, 8448, 8463, 8461, 8451, 8456, 8442, 8437, 8438, 8431, 8435, 8434, 8424, +8409, 8467, 8457, 8449, 8448, 8449, 8451, 8466, 8464, 8449, 8454, 8440, 8435, 8430, 8429, 8433, 8433, 8421, +8360, 8415, 8402, 8399, 8405, 8399, 8401, 8416, 8414, 8395, 8399, 8384, 8380, 8375, 8375, 8378, 8379, 8368, +8356, 8408, 8390, 8398, 8395, 8393, 8397, 8411, 8409, 8401, 8405, 8390, 8385, 8388, 8386, 8379, 8386, 8372, +8297, 8345, 8330, 8340, 8332, 8333, 8337, 8352, 8349, 8339, 8343, 8328, 8322, 8321, 8327, 8317, 8327, 8310, +8304, 8350, 8338, 8349, 8347, 8340, 8346, 8360, 8357, 8336, 8339, 8324, 8319, 8316, 8325, 8314, 8328, 8306, +8237, 8279, 8269, 8279, 8273, 8273, 8277, 8291, 8288, 8282, 8285, 8270, 8265, 8270, 8272, 8263, 8278, 8253, +8227, 8266, 8260, 8262, 8262, 8263, 8268, 8282, 8280, 8266, 8270, 8255, 8251, 8252, 8251, 8249, 8267, 8239, +8172, 8209, 8204, 8208, 8212, 8214, 8210, 8224, 8221, 8204, 8207, 8193, 8197, 8191, 8192, 8192, 8212, 8180, +8157, 8195, 8190, 8193, 8192, 8193, 8197, 8210, 8207, 8198, 8201, 8187, 8186, 8192, 8187, 8188, 8208, 8172, +8090, 8127, 8123, 8126, 8123, 8126, 8137, 8143, 8140, 8132, 8134, 8128, 8121, 8121, 8122, 8126, 8147, 8106, +8085, 8122, 8117, 8120, 8125, 8122, 8132, 8137, 8135, 8111, 8114, 8106, 8101, 8100, 8102, 8109, 8129, 8085, +8007, 8044, 8039, 8042, 8042, 8045, 8056, 8060, 8057, 8053, 8055, 8050, 8044, 8048, 8044, 8054, 8074, 8025, +7987, 8025, 8020, 8023, 8022, 8027, 8032, 8041, 8038, 8027, 8028, 8018, 8019, 8020, 8020, 8031, 8051, 7998, +7926, 7966, 7961, 7964, 7970, 7968, 7971, 7989, 7977, 7960, 7968, 7950, 7954, 7954, 7956, 7967, 7988, 7931, +7898, 7938, 7933, 7936, 7937, 7942, 7945, 7962, 7950, 7944, 7953, 7934, 7938, 7939, 7943, 7955, 7975, 7914, +7830, 7871, 7867, 7870, 7869, 7876, 7879, 7895, 7883, 7877, 7886, 7867, 7872, 7873, 7880, 7892, 7911, 7846, +7812, 7853, 7849, 7852, 7858, 7858, 7861, 7873, 7864, 7848, 7857, 7840, 7846, 7847, 7855, 7867, 7886, 7815, +7708, 7749, 7746, 7749, 7750, 7752, 7756, 7765, 7764, 7765, 7758, 7746, 7751, 7752, 7764, 7776, 7795, 7720, +7682, 7725, 7722, 7725, 7724, 7726, 7730, 7738, 7740, 7738, 7726, 7714, 7719, 7723, 7735, 7747, 7766, 7685, +7629, 7672, 7669, 7672, 7675, 7670, 7674, 7683, 7683, 7675, 7660, 7648, 7652, 7659, 7673, 7684, 7702, 7616, +7606, 7649, 7646, 7648, 7643, 7643, 7649, 7656, 7655, 7660, 7643, 7632, 7642, 7647, 7660, 7673, 7692, 7599, +8714, 8553, 8545, 8545, 8531, 8534, 8540, 8551, 8538, 8543, 8533, 8518, 8525, 8542, 8556, 8572, 8590, 7856 +#if TOUCH_KEY_NUM > 0 +, 6500, 6500, 6500 +#endif /* #if TOUCH_KEY_NUM > 0 */ +}; + +static int32_t PS_Config_Lmt_FW_Rawdata_P[40 * 40] = { +1126, 1131, 1127, 1122, 1126, 1127, 1128, 1123, 1125, 1130, 1119, 1128, 1127, 1117, 1119, 1130, 1120, 1127, +1125, 1129, 1126, 1118, 1133, 1125, 1125, 1123, 1127, 1122, 1126, 1127, 1124, 1126, 1122, 1119, 1123, 1124, +1123, 1123, 1125, 1125, 1124, 1123, 1123, 1122, 1126, 1128, 1120, 1123, 1120, 1125, 1120, 1123, 1122, 1121, +1123, 1121, 1128, 1123, 1122, 1128, 1123, 1124, 1123, 1121, 1125, 1122, 1120, 1124, 1121, 1124, 1127, 1124, +1130, 1126, 1129, 1127, 1124, 1122, 1124, 1128, 1121, 1126, 1120, 1129, 1118, 1119, 1120, 1137, 1121, 1122, +1126, 1124, 1131, 1117, 1129, 1122, 1127, 1120, 1119, 1125, 1120, 1123, 1122, 1121, 1118, 1126, 1125, 1127, +1125, 1122, 1131, 1125, 1123, 1126, 1124, 1118, 1118, 1126, 1122, 1124, 1124, 1129, 1121, 1124, 1123, 1120, +1128, 1128, 1122, 1129, 1121, 1128, 1129, 1119, 1120, 1118, 1118, 1123, 1125, 1122, 1126, 1121, 1129, 1126, +1125, 1126, 1123, 1118, 1123, 1117, 1119, 1118, 1125, 1122, 1125, 1127, 1122, 1126, 1120, 1123, 1123, 1123, +1126, 1129, 1124, 1128, 1119, 1127, 1119, 1126, 1118, 1125, 1123, 1121, 1121, 1122, 1121, 1127, 1122, 1130, +1126, 1123, 1125, 1127, 1121, 1121, 1124, 1128, 1120, 1119, 1124, 1118, 1126, 1121, 1123, 1123, 1126, 1119, +1130, 1129, 1124, 1132, 1123, 1123, 1121, 1127, 1118, 1125, 1126, 1122, 1131, 1120, 1127, 1127, 1121, 1128, +1125, 1128, 1130, 1128, 1124, 1129, 1122, 1123, 1125, 1124, 1128, 1122, 1123, 1120, 1124, 1123, 1123, 1122, +1124, 1129, 1125, 1129, 1129, 1127, 1123, 1123, 1129, 1124, 1123, 1121, 1125, 1121, 1126, 1123, 1124, 1125, +1127, 1128, 1126, 1122, 1129, 1123, 1128, 1130, 1130, 1123, 1132, 1125, 1130, 1128, 1130, 1119, 1128, 1123, +1127, 1127, 1128, 1127, 1126, 1126, 1126, 1128, 1129, 1125, 1129, 1128, 1129, 1126, 1130, 1122, 1125, 1120, +1125, 1126, 1126, 1129, 1129, 1127, 1126, 1126, 1127, 1131, 1127, 1132, 1126, 1125, 1121, 1131, 1122, 1121, +1127, 1129, 1131, 1121, 1124, 1130, 1123, 1131, 1135, 1122, 1126, 1133, 1135, 1133, 1129, 1130, 1125, 1124, +1118, 1122, 1131, 1120, 1126, 1125, 1133, 1134, 1136, 1133, 1130, 1128, 1127, 1128, 1128, 1132, 1127, 1126, +1127, 1126, 1128, 1132, 1125, 1129, 1126, 1128, 1124, 1127, 1128, 1131, 1126, 1129, 1122, 1128, 1128, 1126, +1120, 1125, 1123, 1126, 1125, 1124, 1128, 1128, 1133, 1129, 1127, 1127, 1124, 1129, 1118, 1128, 1128, 1121, +1124, 1126, 1125, 1127, 1124, 1128, 1130, 1125, 1130, 1127, 1125, 1127, 1126, 1123, 1128, 1123, 1128, 1130, +1130, 1125, 1124, 1122, 1122, 1126, 1127, 1129, 1123, 1127, 1126, 1132, 1123, 1126, 1122, 1128, 1122, 1120, +1120, 1124, 1125, 1125, 1126, 1127, 1117, 1127, 1126, 1126, 1123, 1127, 1124, 1125, 1127, 1123, 1119, 1119, +1125, 1132, 1127, 1135, 1124, 1128, 1125, 1116, 1131, 1126, 1128, 1122, 1129, 1121, 1127, 1127, 1121, 1125, +1131, 1128, 1125, 1127, 1123, 1128, 1124, 1118, 1126, 1126, 1124, 1128, 1128, 1129, 1120, 1124, 1123, 1126, +1127, 1122, 1126, 1123, 1129, 1123, 1127, 1129, 1123, 1122, 1125, 1119, 1124, 1128, 1116, 1128, 1121, 1121, +1132, 1127, 1123, 1126, 1125, 1129, 1119, 1120, 1119, 1125, 1120, 1128, 1126, 1125, 1125, 1129, 1124, 1126, +1129, 1125, 1129, 1132, 1125, 1126, 1123, 1122, 1123, 1127, 1122, 1126, 1125, 1130, 1120, 1130, 1118, 1128, +1126, 1133, 1126, 1130, 1125, 1128, 1123, 1123, 1125, 1128, 1129, 1122, 1130, 1128, 1123, 1125, 1121, 1123, +1122, 1124, 1125, 1126, 1128, 1126, 1126, 1126, 1126, 1124, 1121, 1124, 1124, 1124, 1124, 1121, 1124, 1120, +1126, 1119, 1125, 1128, 1123, 1128, 1124, 1128, 1125, 1128, 1117, 1125, 1129, 1127, 1121, 1126, 1125, 1126 +#if TOUCH_KEY_NUM > 0 +, 2000, 2000, 2000 +#endif /* #if TOUCH_KEY_NUM > 0 */ +}; + +static int32_t PS_Config_Lmt_FW_Rawdata_N[40 * 40] = { +676, 678, 676, 673, 676, 676, 677, 674, 675, 678, 671, 677, 676, 670, 671, 678, 672, 676, +675, 677, 676, 671, 680, 675, 675, 674, 676, 673, 675, 676, 674, 676, 673, 672, 674, 675, +674, 674, 675, 675, 675, 674, 674, 673, 675, 677, 672, 674, 672, 675, 672, 674, 673, 673, +674, 673, 677, 674, 673, 677, 674, 675, 674, 672, 675, 673, 672, 674, 673, 675, 676, 674, +678, 676, 677, 676, 675, 673, 674, 677, 673, 676, 672, 678, 671, 671, 672, 682, 673, 673, +676, 674, 679, 670, 678, 673, 676, 672, 671, 675, 672, 674, 673, 673, 671, 676, 675, 676, +675, 673, 679, 675, 674, 675, 674, 671, 671, 676, 673, 674, 674, 677, 672, 675, 674, 672, +677, 677, 673, 677, 673, 677, 677, 671, 672, 671, 671, 674, 675, 673, 676, 673, 677, 676, +675, 676, 674, 671, 674, 670, 671, 671, 675, 673, 675, 676, 673, 675, 672, 674, 674, 674, +676, 677, 675, 677, 672, 676, 672, 676, 671, 675, 674, 673, 672, 673, 673, 676, 673, 678, +675, 674, 675, 676, 673, 673, 674, 677, 672, 671, 675, 671, 675, 672, 674, 674, 675, 672, +678, 677, 674, 679, 674, 674, 673, 676, 671, 675, 676, 673, 678, 672, 676, 676, 672, 677, +675, 677, 678, 677, 674, 677, 673, 674, 675, 675, 677, 673, 674, 672, 675, 674, 674, 673, +675, 678, 675, 677, 677, 676, 674, 674, 677, 674, 674, 672, 675, 673, 676, 674, 675, 675, +676, 677, 675, 673, 678, 674, 677, 678, 678, 674, 679, 675, 678, 677, 678, 672, 677, 674, +676, 676, 677, 676, 676, 676, 675, 677, 678, 675, 677, 677, 677, 675, 678, 673, 675, 672, +675, 675, 675, 677, 677, 676, 675, 676, 676, 679, 676, 679, 676, 675, 673, 678, 673, 673, +676, 678, 679, 673, 674, 678, 674, 679, 681, 673, 676, 680, 681, 680, 678, 678, 675, 675, +671, 673, 679, 672, 675, 675, 680, 681, 682, 680, 678, 677, 676, 677, 677, 679, 676, 675, +676, 676, 677, 679, 675, 677, 675, 677, 674, 676, 677, 679, 676, 677, 673, 677, 677, 676, +672, 675, 674, 676, 675, 675, 677, 677, 680, 677, 676, 676, 674, 677, 671, 677, 677, 673, +674, 676, 675, 676, 674, 677, 678, 675, 678, 676, 675, 676, 676, 674, 677, 674, 677, 678, +678, 675, 675, 673, 673, 676, 676, 677, 674, 676, 676, 679, 674, 676, 673, 677, 673, 672, +672, 674, 675, 675, 675, 676, 670, 676, 675, 675, 674, 676, 674, 675, 676, 674, 671, 672, +675, 679, 676, 681, 674, 677, 675, 670, 679, 675, 677, 673, 677, 673, 676, 676, 672, 675, +678, 677, 675, 676, 674, 677, 674, 671, 676, 675, 674, 677, 677, 677, 672, 674, 674, 676, +676, 673, 676, 674, 678, 674, 676, 678, 674, 673, 675, 672, 674, 677, 669, 677, 673, 673, +679, 676, 674, 676, 675, 677, 672, 672, 671, 675, 672, 677, 676, 675, 675, 677, 674, 675, +677, 675, 678, 679, 675, 676, 674, 673, 674, 676, 673, 676, 675, 678, 672, 678, 671, 677, +675, 680, 676, 678, 675, 677, 674, 674, 675, 677, 678, 673, 678, 677, 674, 675, 672, 674, +673, 674, 675, 676, 677, 676, 675, 675, 676, 674, 673, 674, 675, 675, 674, 672, 674, 672, +675, 671, 675, 677, 674, 677, 674, 677, 675, 677, 670, 675, 678, 676, 673, 676, 675, 676 +#if TOUCH_KEY_NUM > 0 +, 400, 400, 400 +#endif /* #if TOUCH_KEY_NUM > 0 */ +}; + +static int32_t PS_Config_Lmt_FW_CC_P = 112; +static int32_t PS_Config_Lmt_FW_CC_N = 72; +static int32_t PS_Config_Lmt_Key_FW_CC_P = 38; +static int32_t PS_Config_Lmt_Key_FW_CC_N = 9; +static int32_t PS_Config_Lmt_FW_CC_I_P = 25; +static int32_t PS_Config_Lmt_FW_CC_I_N; +static int32_t PS_Config_Lmt_FW_CC_Q_P = 25; +static int32_t PS_Config_Lmt_FW_CC_Q_N; +static int32_t PS_Config_Lmt_Key_FW_CC_I_P = 25; +static int32_t PS_Config_Lmt_Key_FW_CC_I_N; +static int32_t PS_Config_Lmt_Key_FW_CC_Q_P = 25; +static int32_t PS_Config_Lmt_Key_FW_CC_Q_N; + +static int32_t PS_Config_Lmt_FW_Diff_P = 35; +static int32_t PS_Config_Lmt_FW_Diff_N = -35; +static int32_t PS_Config_Lmt_Key_FW_Diff_P = 35; +static int32_t PS_Config_Lmt_Key_FW_Diff_N = -35; + +static int32_t PS_Config_Diff_Test_Frame = 50; + +#endif /* #if NVT_TOUCH_MP */ diff --git a/drivers/input/touchscreen/nt36672/nvt_run_mp_tests_get_samples.txt b/drivers/input/touchscreen/nt36672/nvt_run_mp_tests_get_samples.txt new file mode 100755 index 0000000000000..583c9572d7912 --- /dev/null +++ b/drivers/input/touchscreen/nt36672/nvt_run_mp_tests_get_samples.txt @@ -0,0 +1,22 @@ +@echo off + +REM To run this batch file, please rename this file from nvt_run_mp_tests_get_samples.txt to nvt_run_mp_tests_get_samples.bat + +FOR /F "tokens=1-3 delims=/ " %%a IN ("%date%") DO (SET _MyDate=%%a%%b%%c) +FOR /F "tokens=1-4 delims=:." %%a IN ("%time%") DO (SET _MyTime=%%a%%b%%c) + +echo ====== Run MP Self-Testing ... ====== +adb shell cat /proc/nvt_selftest +echo ====== Run MP Self-Test Done ====== +set myDIR=Samples +IF not exist %myDIR% (mkdir %myDIR%) +adb pull /data/local/tmp/ShortTest.csv .\Samples\ShortTest_"%_MyDate%%_MyTime%".csv +adb pull /data/local/tmp/OpenTest.csv .\Samples\OpenTest_"%_MyDate%%_MyTime%".csv +adb pull /data/local/tmp/FWMutualTest.csv .\Samples\FWMutualTest_"%_MyDate%%_MyTime%".csv +adb pull /data/local/tmp/FWCCTest.csv .\Samples\FWCCTest_"%_MyDate%%_MyTime%".csv +adb pull /data/local/tmp/NoiseTest.csv .\Samples\NoiseTest_"%_MyDate%%_MyTime%".csv +adb shell dmesg > .\Samples\dmesg_"%_MyDate%%_MyTime%".txt + +echo ====== Get MP Self-Test data files finished ====== +echo Press any key to exit... +pause \ No newline at end of file diff --git a/drivers/input/touchscreen/td4310_e7/Kconfig b/drivers/input/touchscreen/td4310_e7/Kconfig new file mode 100755 index 0000000000000..b2fa11501269d --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/Kconfig @@ -0,0 +1,128 @@ +# +# Synaptics DSX touchscreen driver configuration +# +menuconfig TOUCHSCREEN_SYNAPTICS_DSX + bool "Synaptics DSX touchscreen" + default y + help + Say Y here if you have a Synaptics DSX touchscreen connected + to your system. + + If unsure, say N. + +if TOUCHSCREEN_SYNAPTICS_DSX + +choice + default TOUCHSCREEN_SYNAPTICS_DSX_I2C + prompt "Synaptics DSX bus interface" +config TOUCHSCREEN_SYNAPTICS_DSX_I2C + bool "RMI over I2C" + depends on I2C +config TOUCHSCREEN_SYNAPTICS_DSX_SPI + bool "RMI over SPI" + depends on SPI_MASTER +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C + bool "HID over I2C" + depends on I2C +endchoice + +config TOUCHSCREEN_SYNAPTICS_DSX_CORE + tristate "Synaptics DSX core driver module" + depends on I2C || SPI_MASTER + help + Say Y here to enable basic touch reporting functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_core. + +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV + tristate "Synaptics DSX RMI device module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for direct RMI register access. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_rmi_dev. + +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + tristate "Synaptics DSX firmware update module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for doing firmware update. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + +config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING + tristate "Synaptics DSX test reporting module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for retrieving production test reports. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_test_reporting. + +config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY + tristate "Synaptics DSX proximity module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for proximity functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_proximity. + +config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN + tristate "Synaptics DSX active pen module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for active pen functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_active_pen. + +config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE + tristate "Synaptics DSX user defined gesture module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for user defined gesture functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_gesture. + +config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO + tristate "Synaptics DSX video module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for video communication functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_video. + +config TOUCHSCREEN_SYNAPTICS_DSX_DEBUG + tristate "Synaptics DSX debug module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for firmware debug functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_debug. + +endif diff --git a/drivers/input/touchscreen/td4310_e7/Makefile b/drivers/input/touchscreen/td4310_e7/Makefile new file mode 100755 index 0000000000000..99ea859aa2a6f --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the Synaptics DSX touchscreen driver. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_TD4310_E7) += synaptics_dsx_i2c.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI) += synaptics_dsx_spi.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C) += synaptics_dsx_rmi_hid_i2c.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_E7) += synaptics_dsx_core.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_E7) += synaptics_dsx_rmi_dev.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_E7) += synaptics_dsx_fw_update.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_E7) += synaptics_dsx_test_reporting.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY) += synaptics_dsx_proximity.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN) += synaptics_dsx_active_pen.o +#obj-$(CONFIG_TOUCHSCREEN_TD4310) += synaptics_dsx_gesture.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_VIDEO) += synaptics_dsx_video.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_DEBUG) += synaptics_dsx_debug.o diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_active_pen.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_active_pen.c new file mode 100755 index 0000000000000..fc0d8d6bc556c --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_active_pen.c @@ -0,0 +1,624 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define APEN_PHYS_NAME "synaptics_dsx/active_pen" + +#define ACTIVE_PEN_MAX_PRESSURE_16BIT 65535 +#define ACTIVE_PEN_MAX_PRESSURE_8BIT 255 + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + }; + unsigned char data[2]; + }; +}; + +struct apen_data_8b_pressure { + union { + struct { + unsigned char status_pen:1; + unsigned char status_invert:1; + unsigned char status_barrel:1; + unsigned char status_reserved:5; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; + unsigned char pressure_msb; + unsigned char battery_state; + unsigned char pen_id_0_7; + unsigned char pen_id_8_15; + unsigned char pen_id_16_23; + unsigned char pen_id_24_31; + } __packed; + unsigned char data[11]; + }; +}; + +struct apen_data { + union { + struct { + unsigned char status_pen:1; + unsigned char status_invert:1; + unsigned char status_barrel:1; + unsigned char status_reserved:5; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; + unsigned char pressure_lsb; + unsigned char pressure_msb; + unsigned char battery_state; + unsigned char pen_id_0_7; + unsigned char pen_id_8_15; + unsigned char pen_id_16_23; + unsigned char pen_id_24_31; + } __packed; + unsigned char data[12]; + }; +}; + +struct synaptics_rmi4_apen_handle { + bool apen_present; + unsigned char intr_mask; + unsigned char battery_state; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short apen_data_addr; + unsigned short max_pressure; + unsigned int pen_id; + struct input_dev *apen_dev; + struct apen_data *apen_data; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_apen_handle *apen; + +DECLARE_COMPLETION(apen_remove_complete); + +static void apen_lift(void) +{ + input_report_key(apen->apen_dev, BTN_TOUCH, 0); + input_report_key(apen->apen_dev, BTN_TOOL_PEN, 0); + input_report_key(apen->apen_dev, BTN_TOOL_RUBBER, 0); + input_sync(apen->apen_dev); + apen->apen_present = false; + + return; +} + +static void apen_report(void) +{ + int retval; + int x; + int y; + int pressure; + static int invert = -1; + struct apen_data_8b_pressure *apen_data_8b; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->apen_data_addr, + apen->apen_data->data, + sizeof(apen->apen_data->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read active pen data\n", + __func__); + return; + } + + if (apen->apen_data->status_pen == 0) { + if (apen->apen_present) + apen_lift(); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: No active pen data\n", + __func__); + + return; + } + + x = (apen->apen_data->x_msb << 8) | (apen->apen_data->x_lsb); + y = (apen->apen_data->y_msb << 8) | (apen->apen_data->y_lsb); + + if ((x == -1) && (y == -1)) { + if (apen->apen_present) + apen_lift(); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Active pen in range but no valid x & y\n", + __func__); + + return; + } + + if (!apen->apen_present) + invert = -1; + + if (invert != -1 && invert != apen->apen_data->status_invert) + apen_lift(); + + invert = apen->apen_data->status_invert; + + if (apen->max_pressure == ACTIVE_PEN_MAX_PRESSURE_16BIT) { + pressure = (apen->apen_data->pressure_msb << 8) | + apen->apen_data->pressure_lsb; + apen->battery_state = apen->apen_data->battery_state; + apen->pen_id = (apen->apen_data->pen_id_24_31 << 24) | + (apen->apen_data->pen_id_16_23 << 16) | + (apen->apen_data->pen_id_8_15 << 8) | + apen->apen_data->pen_id_0_7; + } else { + apen_data_8b = (struct apen_data_8b_pressure *)apen->apen_data; + pressure = apen_data_8b->pressure_msb; + apen->battery_state = apen_data_8b->battery_state; + apen->pen_id = (apen_data_8b->pen_id_24_31 << 24) | + (apen_data_8b->pen_id_16_23 << 16) | + (apen_data_8b->pen_id_8_15 << 8) | + apen_data_8b->pen_id_0_7; + } + + input_report_key(apen->apen_dev, BTN_TOUCH, pressure > 0 ? 1 : 0); + input_report_key(apen->apen_dev, + apen->apen_data->status_invert > 0 ? + BTN_TOOL_RUBBER : BTN_TOOL_PEN, 1); + input_report_key(apen->apen_dev, + BTN_STYLUS, apen->apen_data->status_barrel > 0 ? + 1 : 0); + input_report_abs(apen->apen_dev, ABS_X, x); + input_report_abs(apen->apen_dev, ABS_Y, y); + input_report_abs(apen->apen_dev, ABS_PRESSURE, pressure); + + input_sync(apen->apen_dev); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Active pen: status = %d, invert = %d, barrel = %d, x = %d, y = %d, pressure = %d\n", + __func__, + apen->apen_data->status_pen, + apen->apen_data->status_invert, + apen->apen_data->status_barrel, + x, y, pressure); + + apen->apen_present = true; + + return; +} + +static void apen_set_params(void) +{ + input_set_abs_params(apen->apen_dev, ABS_X, 0, + apen->rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(apen->apen_dev, ABS_Y, 0, + apen->rmi4_data->sensor_max_y, 0, 0); + input_set_abs_params(apen->apen_dev, ABS_PRESSURE, 0, + apen->max_pressure, 0, 0); + + return; +} + +static int apen_pressure(struct synaptics_rmi4_f12_query_8 *query_8) +{ + int retval; + unsigned char ii; + unsigned char data_reg_presence; + unsigned char size_of_query_9; + unsigned char *query_9; + unsigned char *data_desc; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + data_reg_presence = query_8->data[1]; + + size_of_query_9 = query_8->size_of_query9; + query_9 = kmalloc(size_of_query_9, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->query_base_addr + 9, + query_9, + size_of_query_9); + if (retval < 0) + goto exit; + + data_desc = query_9; + + for (ii = 0; ii < 6; ii++) { + if (!(data_reg_presence & (1 << ii))) + continue; /* The data register is not present */ + data_desc++; /* Jump over the size entry */ + while (*data_desc & (1 << 7)) + data_desc++; + data_desc++; /* Go to the next descriptor */ + } + + data_desc++; /* Jump over the size entry */ + /* Check for the presence of subpackets 1 and 2 */ + if ((*data_desc & (3 << 1)) == (3 << 1)) + apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_16BIT; + else + apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_8BIT; + +exit: + kfree(query_9); + + return retval; +} + +static int apen_reg_init(void) +{ + int retval; + unsigned char data_offset; + unsigned char size_of_query8; + struct synaptics_rmi4_f12_query_8 query_8; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->query_base_addr + 7, + &size_of_query8, + sizeof(size_of_query8)); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + apen->query_base_addr + 8, + query_8.data, + sizeof(query_8.data)); + if (retval < 0) + return retval; + + if ((size_of_query8 >= 2) && (query_8.data6_is_present)) { + data_offset = query_8.data0_is_present + + query_8.data1_is_present + + query_8.data2_is_present + + query_8.data3_is_present + + query_8.data4_is_present + + query_8.data5_is_present; + apen->apen_data_addr = apen->data_base_addr + data_offset; + retval = apen_pressure(&query_8); + if (retval < 0) + return retval; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Active pen support unavailable\n", + __func__); + retval = -ENODEV; + } + + return retval; +} + +static int apen_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char page; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + struct synaptics_rmi4_fn_desc fd; + struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&fd, + sizeof(fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, fd.fn_number); + switch (fd.fn_number) { + case SYNAPTICS_RMI4_F12: + goto f12_found; + break; + } + } else { + break; + } + + intr_count += fd.intr_src_count; + } + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F12\n", + __func__); + return -EINVAL; + +f12_found: + apen->query_base_addr = fd.query_base_addr | (page << 8); + apen->control_base_addr = fd.ctrl_base_addr | (page << 8); + apen->data_base_addr = fd.data_base_addr | (page << 8); + apen->command_base_addr = fd.cmd_base_addr | (page << 8); + + retval = apen_reg_init(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize active pen registers\n", + __func__); + return retval; + } + + apen->intr_mask = 0; + intr_src = fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + apen->intr_mask |= 1 << ii; + } + + rmi4_data->intr_mask[0] |= apen->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static void synaptics_rmi4_apen_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!apen) + return; + + if (apen->intr_mask & intr_mask) + apen_report(); + + return; +} + +static int synaptics_rmi4_apen_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (apen) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + apen = kzalloc(sizeof(*apen), GFP_KERNEL); + if (!apen) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for apen\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + apen->apen_data = kzalloc(sizeof(*(apen->apen_data)), GFP_KERNEL); + if (!apen->apen_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for apen_data\n", + __func__); + retval = -ENOMEM; + goto exit_free_apen; + } + + apen->rmi4_data = rmi4_data; + + retval = apen_scan_pdt(); + if (retval < 0) + goto exit_free_apen_data; + + apen->apen_dev = input_allocate_device(); + if (apen->apen_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate active pen device\n", + __func__); + retval = -ENOMEM; + goto exit_free_apen_data; + } + + apen->apen_dev->name = ACTIVE_PEN_DRIVER_NAME; + apen->apen_dev->phys = APEN_PHYS_NAME; + apen->apen_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + apen->apen_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + apen->apen_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(apen->apen_dev, rmi4_data); + + set_bit(EV_KEY, apen->apen_dev->evbit); + set_bit(EV_ABS, apen->apen_dev->evbit); + set_bit(BTN_TOUCH, apen->apen_dev->keybit); + set_bit(BTN_TOOL_PEN, apen->apen_dev->keybit); + set_bit(BTN_TOOL_RUBBER, apen->apen_dev->keybit); + set_bit(BTN_STYLUS, apen->apen_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, apen->apen_dev->propbit); +#endif + + apen_set_params(); + + retval = input_register_device(apen->apen_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register active pen device\n", + __func__); + goto exit_free_input_device; + } + + return 0; + +exit_free_input_device: + input_free_device(apen->apen_dev); + +exit_free_apen_data: + kfree(apen->apen_data); + +exit_free_apen: + kfree(apen); + apen = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_apen_remove(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + goto exit; + + input_unregister_device(apen->apen_dev); + kfree(apen->apen_data); + kfree(apen); + apen = NULL; + +exit: + complete(&apen_remove_complete); + + return; +} + +static void synaptics_rmi4_apen_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) { + synaptics_rmi4_apen_init(rmi4_data); + return; + } + + apen_lift(); + + apen_scan_pdt(); + + return; +} + +static void synaptics_rmi4_apen_reinit(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + return; + + apen_lift(); + + return; +} + +static void synaptics_rmi4_apen_e_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + return; + + apen_lift(); + + return; +} + +static void synaptics_rmi4_apen_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!apen) + return; + + apen_lift(); + + return; +} + +static struct synaptics_rmi4_exp_fn active_pen_module = { + .fn_type = RMI_ACTIVE_PEN, + .init = synaptics_rmi4_apen_init, + .remove = synaptics_rmi4_apen_remove, + .reset = synaptics_rmi4_apen_reset, + .reinit = synaptics_rmi4_apen_reinit, + .early_suspend = synaptics_rmi4_apen_e_suspend, + .suspend = synaptics_rmi4_apen_suspend, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_apen_attn, +}; + +static int __init rmi4_active_pen_module_init(void) +{ + synaptics_rmi4_new_function(&active_pen_module, true); + + return 0; +} + +static void __exit rmi4_active_pen_module_exit(void) +{ + synaptics_rmi4_new_function(&active_pen_module, false); + + wait_for_completion(&apen_remove_complete); + + return; +} + +module_init(rmi4_active_pen_module_init); +module_exit(rmi4_active_pen_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Active Pen Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_core.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_core.c new file mode 100755 index 0000000000000..aa242d67645d4 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_core.c @@ -0,0 +1,4934 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" +#include +#include +#include + +#ifdef KERNEL_ABOVE_2_6_38 +#include +#endif + +#define INPUT_PHYS_NAME "synaptics_dsx/touch_input" +#define STYLUS_PHYS_NAME "synaptics_dsx/stylus" + +#define VIRTUAL_KEY_MAP_FILE_NAME "virtualkeys." PLATFORM_DRIVER_NAME + +#ifdef KERNEL_ABOVE_2_6_38 +#define TYPE_B_PROTOCOL +#endif + +/* +#define USE_DATA_SERVER +*/ + +#define WAKEUP_GESTURE 1 + +#define NO_0D_WHILE_2D +#define REPORT_2D_Z +#define REPORT_2D_W +/* +#define REPORT_2D_PRESSURE +*/ + +#define F12_DATA_15_WORKAROUND + +#define IGNORE_FN_INIT_FAILURE +/* +#define FB_READY_RESET +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +*/ +#ifdef SYNA_TDDI +#define TDDI_LPWG_WAIT_US 100 +#endif +#define RPT_TYPE (1 << 0) +#define RPT_X_LSB (1 << 1) +#define RPT_X_MSB (1 << 2) +#define RPT_Y_LSB (1 << 3) +#define RPT_Y_MSB (1 << 4) +#define RPT_Z (1 << 5) +#define RPT_WX (1 << 6) +#define RPT_WY (1 << 7) +#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB) + +#define REBUILD_WORK_DELAY_MS 500 /* ms */ + +#define EXP_FN_WORK_DELAY_MS 500 /* ms */ +#define MAX_F11_TOUCH_WIDTH 15 +#define MAX_F12_TOUCH_WIDTH 255 + +#define CHECK_STATUS_TIMEOUT_MS 100 + +#define F01_STD_QUERY_LEN 21 +#define F01_BUID_ID_OFFSET 18 + +#define STATUS_NO_ERROR 0x00 +#define STATUS_RESET_OCCURRED 0x01 +#define STATUS_INVALID_CONFIG 0x02 +#define STATUS_DEVICE_FAILURE 0x03 +#define STATUS_CONFIG_CRC_FAILURE 0x04 +#define STATUS_FIRMWARE_CRC_FAILURE 0x05 +#define STATUS_CRC_IN_PROGRESS 0x06 + +#define NORMAL_OPERATION (0 << 0) +#define SENSOR_SLEEP (1 << 0) +#define NO_SLEEP_OFF (0 << 2) +#define NO_SLEEP_ON (1 << 2) +#define CONFIGURED (1 << 7) + +#define F11_CONTINUOUS_MODE 0x00 +#define F11_WAKEUP_GESTURE_MODE 0x04 +#define F12_CONTINUOUS_MODE 0x00 +#define F12_WAKEUP_GESTURE_MODE 0x02 +#define F12_UDG_DETECT 0x0f + +static struct synaptics_rmi4_data *rmi4_data; + +bool synaptics_gesture_func_on = false; +#if WAKEUP_GESTURE +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +extern bool lcm_ffbm_mode; +#endif +int synaptics_gesture_switch(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + unsigned int input ; + if (type == EV_SYN && code == SYN_CONFIG) + { + if (value == WAKEUP_OFF){ + synaptics_gesture_func_on = false; + input = 0; + }else if (value == WAKEUP_ON){ + synaptics_gesture_func_on = true; + input = 1; + } + } + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) + rmi4_data->enable_wakeup_gesture = input; + + return 0; +} +#endif + + +extern int get_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng); + +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, + bool *was_in_bl_mode); +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data); +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data); +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, + bool rebuild); + +#ifdef SYNAPTICS_ESD_CHECK +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +void synaptics_rmi4_esd_work(struct work_struct *work); +#if 1 +#define SYNAPTICS_ESD_CHECK_RETRY_TIME 5 +int touch_event_flag; +int fw_update_flag; + + + + +#endif +#endif + + +#ifdef CONFIG_FB +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self, + unsigned long event, void *data); +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +#ifndef CONFIG_FB +#define USE_EARLYSUSPEND +#endif +#endif + +#ifdef USE_EARLYSUSPEND +static void synaptics_rmi4_early_suspend(struct early_suspend *h); + +static void synaptics_rmi4_late_resume(struct early_suspend *h); +#endif + +static int synaptics_rmi4_suspend(struct device *dev); + +static int synaptics_rmi4_resume(struct device *dev); + +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_suspend_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +#ifdef USE_DATA_SERVER +static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); +#endif + +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf); + +struct synaptics_rmi4_f01_device_status { + union { + struct { + unsigned char status_code:4; + unsigned char reserved:2; + unsigned char flash_prog:1; + unsigned char unconfigured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_0_5 { + union { + struct { + /* query 0 */ + unsigned char f11_query0_b0__2:3; + unsigned char has_query_9:1; + unsigned char has_query_11:1; + unsigned char has_query_12:1; + unsigned char has_query_27:1; + unsigned char has_query_28:1; + + /* query 1 */ + unsigned char num_of_fingers:3; + unsigned char has_rel:1; + unsigned char has_abs:1; + unsigned char has_gestures:1; + unsigned char has_sensitibity_adjust:1; + unsigned char f11_query1_b7:1; + + /* query 2 */ + unsigned char num_of_x_electrodes; + + /* query 3 */ + unsigned char num_of_y_electrodes; + + /* query 4 */ + unsigned char max_electrodes:7; + unsigned char f11_query4_b7:1; + + /* query 5 */ + unsigned char abs_data_size:2; + unsigned char has_anchored_finger:1; + unsigned char has_adj_hyst:1; + unsigned char has_dribble:1; + unsigned char has_bending_correction:1; + unsigned char has_large_object_suppression:1; + unsigned char has_jitter_filter:1; + } __packed; + unsigned char data[6]; + }; +}; + +struct synaptics_rmi4_f11_query_7_8 { + union { + struct { + /* query 7 */ + unsigned char has_single_tap:1; + unsigned char has_tap_and_hold:1; + unsigned char has_double_tap:1; + unsigned char has_early_tap:1; + unsigned char has_flick:1; + unsigned char has_press:1; + unsigned char has_pinch:1; + unsigned char has_chiral_scroll:1; + + /* query 8 */ + unsigned char has_palm_detect:1; + unsigned char has_rotate:1; + unsigned char has_touch_shapes:1; + unsigned char has_scroll_zones:1; + unsigned char individual_scroll_zones:1; + unsigned char has_multi_finger_scroll:1; + unsigned char has_multi_finger_scroll_edge_motion:1; + unsigned char has_multi_finger_scroll_inertia:1; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f11_query_9 { + union { + struct { + unsigned char has_pen:1; + unsigned char has_proximity:1; + unsigned char has_large_object_sensitivity:1; + unsigned char has_suppress_on_large_object_detect:1; + unsigned char has_two_pen_thresholds:1; + unsigned char has_contact_geometry:1; + unsigned char has_pen_hover_discrimination:1; + unsigned char has_pen_hover_and_edge_filters:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_12 { + union { + struct { + unsigned char has_small_object_detection:1; + unsigned char has_small_object_detection_tuning:1; + unsigned char has_8bit_w:1; + unsigned char has_2d_adjustable_mapping:1; + unsigned char has_general_information_2:1; + unsigned char has_physical_properties:1; + unsigned char has_finger_limit:1; + unsigned char has_linear_cofficient_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_27 { + union { + struct { + unsigned char f11_query27_b0:1; + unsigned char has_pen_position_correction:1; + unsigned char has_pen_jitter_filter_coefficient:1; + unsigned char has_group_decomposition:1; + unsigned char has_wakeup_gesture:1; + unsigned char has_small_finger_correction:1; + unsigned char has_data_37:1; + unsigned char f11_query27_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_ctrl_6_9 { + union { + struct { + unsigned char sensor_max_x_pos_7_0; + unsigned char sensor_max_x_pos_11_8:4; + unsigned char f11_ctrl7_b4__7:4; + unsigned char sensor_max_y_pos_7_0; + unsigned char sensor_max_y_pos_11_8:4; + unsigned char f11_ctrl9_b4__7:4; + } __packed; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f11_data_1_5 { + union { + struct { + unsigned char x_position_11_4; + unsigned char y_position_11_4; + unsigned char x_position_3_0:4; + unsigned char y_position_3_0:4; + unsigned char wx:4; + unsigned char wy:4; + unsigned char z; + } __packed; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + struct { + unsigned char ctrl24_is_present:1; + unsigned char ctrl25_is_present:1; + unsigned char ctrl26_is_present:1; + unsigned char ctrl27_is_present:1; + unsigned char ctrl28_is_present:1; + unsigned char ctrl29_is_present:1; + unsigned char ctrl30_is_present:1; + unsigned char ctrl31_is_present:1; + } __packed; + struct { + unsigned char ctrl32_is_present:1; + unsigned char ctrl33_is_present:1; + unsigned char ctrl34_is_present:1; + unsigned char ctrl35_is_present:1; + unsigned char ctrl36_is_present:1; + unsigned char ctrl37_is_present:1; + unsigned char ctrl38_is_present:1; + unsigned char ctrl39_is_present:1; + } __packed; + struct { + unsigned char ctrl40_is_present:1; + unsigned char ctrl41_is_present:1; + unsigned char ctrl42_is_present:1; + unsigned char ctrl43_is_present:1; + unsigned char ctrl44_is_present:1; + unsigned char ctrl45_is_present:1; + unsigned char ctrl46_is_present:1; + unsigned char ctrl47_is_present:1; + } __packed; + struct { + unsigned char ctrl48_is_present:1; + unsigned char ctrl49_is_present:1; + unsigned char ctrl50_is_present:1; + unsigned char ctrl51_is_present:1; + unsigned char ctrl52_is_present:1; + unsigned char ctrl53_is_present:1; + unsigned char ctrl54_is_present:1; + unsigned char ctrl55_is_present:1; + } __packed; + struct { + unsigned char ctrl56_is_present:1; + unsigned char ctrl57_is_present:1; + unsigned char ctrl58_is_present:1; + unsigned char ctrl59_is_present:1; + unsigned char ctrl60_is_present:1; + unsigned char ctrl61_is_present:1; + unsigned char ctrl62_is_present:1; + unsigned char ctrl63_is_present:1; + } __packed; + }; + unsigned char data[9]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + struct { + unsigned char data8_is_present:1; + unsigned char data9_is_present:1; + unsigned char data10_is_present:1; + unsigned char data11_is_present:1; + unsigned char data12_is_present:1; + unsigned char data13_is_present:1; + unsigned char data14_is_present:1; + unsigned char data15_is_present:1; + } __packed; + struct { + unsigned char data16_is_present:1; + unsigned char data17_is_present:1; + unsigned char data18_is_present:1; + unsigned char data19_is_present:1; + unsigned char data20_is_present:1; + unsigned char data21_is_present:1; + unsigned char data22_is_present:1; + unsigned char data23_is_present:1; + } __packed; + struct { + unsigned char data24_is_present:1; + unsigned char data25_is_present:1; + unsigned char data26_is_present:1; + unsigned char data27_is_present:1; + unsigned char data28_is_present:1; + unsigned char data29_is_present:1; + unsigned char data30_is_present:1; + unsigned char data31_is_present:1; + } __packed; + }; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_8 { + union { + struct { + unsigned char max_x_coord_lsb; + unsigned char max_x_coord_msb; + unsigned char max_y_coord_lsb; + unsigned char max_y_coord_msb; + unsigned char rx_pitch_lsb; + unsigned char rx_pitch_msb; + unsigned char tx_pitch_lsb; + unsigned char tx_pitch_msb; + unsigned char low_rx_clip; + unsigned char high_rx_clip; + unsigned char low_tx_clip; + unsigned char high_tx_clip; + unsigned char num_of_rx; + unsigned char num_of_tx; + }; + unsigned char data[14]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_23 { + union { + struct { + unsigned char finger_enable:1; + unsigned char active_stylus_enable:1; + unsigned char palm_enable:1; + unsigned char unclassified_object_enable:1; + unsigned char hovering_finger_enable:1; + unsigned char gloved_finger_enable:1; + unsigned char f12_ctr23_00_b6__7:2; + unsigned char max_reported_objects; + unsigned char f12_ctr23_02_b0:1; + unsigned char report_active_stylus_as_finger:1; + unsigned char report_palm_as_finger:1; + unsigned char report_unclassified_object_as_finger:1; + unsigned char report_hovering_finger_as_finger:1; + unsigned char report_gloved_finger_as_finger:1; + unsigned char report_narrow_object_swipe_as_finger:1; + unsigned char report_handedge_as_finger:1; + unsigned char cover_enable:1; + unsigned char stylus_enable:1; + unsigned char eraser_enable:1; + unsigned char small_object_enable:1; + unsigned char f12_ctr23_03_b4__7:4; + unsigned char report_cover_as_finger:1; + unsigned char report_stylus_as_finger:1; + unsigned char report_eraser_as_finger:1; + unsigned char report_small_object_as_finger:1; + unsigned char f12_ctr23_04_b4__7:4; + }; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_31 { + union { + struct { + unsigned char max_x_coord_lsb; + unsigned char max_x_coord_msb; + unsigned char max_y_coord_lsb; + unsigned char max_y_coord_msb; + unsigned char rx_pitch_lsb; + unsigned char rx_pitch_msb; + unsigned char rx_clip_low; + unsigned char rx_clip_high; + unsigned char wedge_clip_low; + unsigned char wedge_clip_high; + unsigned char num_of_p; + unsigned char num_of_q; + }; + unsigned char data[12]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_58 { + union { + struct { + unsigned char reporting_format; + unsigned char f12_ctr58_00_reserved; + unsigned char min_force_lsb; + unsigned char min_force_msb; + unsigned char max_force_lsb; + unsigned char max_force_msb; + unsigned char light_press_threshold_lsb; + unsigned char light_press_threshold_msb; + unsigned char light_press_hysteresis_lsb; + unsigned char light_press_hysteresis_msb; + unsigned char hard_press_threshold_lsb; + unsigned char hard_press_threshold_msb; + unsigned char hard_press_hysteresis_lsb; + unsigned char hard_press_hysteresis_msb; + }; + unsigned char data[14]; + }; +}; + +struct synaptics_rmi4_f12_finger_data { + unsigned char object_type_and_status; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; +#ifdef REPORT_2D_Z + unsigned char z; +#endif +#ifdef REPORT_2D_W + unsigned char wx; + unsigned char wy; +#endif +}; + +struct synaptics_rmi4_f1a_query { + union { + struct { + unsigned char max_button_count:3; + unsigned char f1a_query0_b3__4:2; + unsigned char has_query4:1; + unsigned char has_query3:1; + unsigned char has_query2:1; + unsigned char has_general_control:1; + unsigned char has_interrupt_enable:1; + unsigned char has_multibutton_select:1; + unsigned char has_tx_rx_map:1; + unsigned char has_perbutton_threshold:1; + unsigned char has_release_threshold:1; + unsigned char has_strongestbtn_hysteresis:1; + unsigned char has_filter_strength:1; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f1a_query_4 { + union { + struct { + unsigned char has_ctrl19:1; + unsigned char f1a_query4_b1__4:4; + unsigned char has_ctrl24:1; + unsigned char f1a_query4_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f1a_control_0 { + union { + struct { + unsigned char multibutton_report:2; + unsigned char filter_mode:2; + unsigned char reserved:4; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f1a_control { + struct synaptics_rmi4_f1a_control_0 general_control; + unsigned char button_int_enable; + unsigned char multi_button; + unsigned char *txrx_map; + unsigned char *button_threshold; + unsigned char button_release_threshold; + unsigned char strongest_button_hysteresis; + unsigned char filter_strength; +}; + +struct synaptics_rmi4_f1a_handle { + int button_bitmask_size; + unsigned char max_count; + unsigned char valid_button_count; + unsigned char *button_data_buffer; + unsigned char *button_map; + struct synaptics_rmi4_f1a_query button_query; + struct synaptics_rmi4_f1a_control button_control; +}; + +struct synaptics_rmi4_exp_fhandler { + struct synaptics_rmi4_exp_fn *exp_fn; + bool insert; + bool remove; + struct list_head link; +}; + +struct synaptics_rmi4_exp_fn_data { + bool initialized; + bool queue_work; + struct mutex mutex; + struct list_head list; + struct delayed_work work; + struct workqueue_struct *workqueue; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_exp_fn_data exp_data; + +static struct synaptics_dsx_button_map *vir_button_map; + +#ifdef USE_DATA_SERVER +static pid_t synad_pid; +static struct task_struct *synad_task; +static struct siginfo interrupt_signal; +#endif + +static struct device_attribute attrs[] = { + __ATTR(reset, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_f01_reset_store), + __ATTR(productinfo, S_IRUGO, + synaptics_rmi4_f01_productinfo_show, + synaptics_rmi4_store_error), + __ATTR(buildid, S_IRUGO, + synaptics_rmi4_f01_buildid_show, + synaptics_rmi4_store_error), + __ATTR(flashprog, S_IRUGO, + synaptics_rmi4_f01_flashprog_show, + synaptics_rmi4_store_error), + __ATTR(0dbutton, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_0dbutton_show, + synaptics_rmi4_0dbutton_store), + __ATTR(suspend, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_suspend_store), + __ATTR(wake_gesture, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_wake_gesture_show, + synaptics_rmi4_wake_gesture_store), +#ifdef USE_DATA_SERVER + __ATTR(synad_pid, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_synad_pid_store), +#endif +}; + +static struct kobj_attribute virtual_key_map_attr = { + .attr = { + .name = VIRTUAL_KEY_MAP_FILE_NAME, + .mode = S_IRUGO, + }, + .show = synaptics_rmi4_virtual_key_map_show, +}; + +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int reset; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + if (sscanf(buf, "%u", &reset) != 1) + return -EINVAL; + + if (reset != 1) + return -EINVAL; + + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command, error = %d\n", + __func__, retval); + return retval; + } + + return count; +} + +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n", + (rmi4_data->rmi4_mod_info.product_info[0]), + (rmi4_data->rmi4_mod_info.product_info[1])); +} + +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->firmware_id); +} + +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + struct synaptics_rmi4_f01_device_status device_status; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + device_status.data, + sizeof(device_status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device status, error = %d\n", + __func__, retval); + return retval; + } + + return snprintf(buf, PAGE_SIZE, "%u\n", + device_status.flash_prog); +} + +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->button_0d_enabled); +} + +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + unsigned char ii; + unsigned char intr_enable; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + input = input > 0 ? 1 : 0; + + if (rmi4_data->button_0d_enabled == input) + return count; + + if (list_empty(&rmi->support_fn_list)) + return -ENODEV; + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { + ii = fhandler->intr_reg_num; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr + 1 + ii, + &intr_enable, + sizeof(intr_enable)); + if (retval < 0) + return retval; + + if (input == 1) + intr_enable |= fhandler->intr_mask; + else + intr_enable &= ~fhandler->intr_mask; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr + 1 + ii, + &intr_enable, + sizeof(intr_enable)); + if (retval < 0) + return retval; + } + } + + rmi4_data->button_0d_enabled = input; + + return count; +} + +static ssize_t synaptics_rmi4_suspend_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + synaptics_rmi4_suspend(dev); + else if (input == 0) + synaptics_rmi4_resume(dev); + else + return -EINVAL; + + return count; +} + +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->enable_wakeup_gesture); +} + + +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned int input ; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input) + input = 1; + else + input = 0; + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) + { + rmi4_data->enable_wakeup_gesture = input; + synaptics_gesture_func_on = input; + } + + + return count; +} + +#ifdef USE_DATA_SERVER +static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + synad_pid = input; + + if (synad_pid) { + synad_task = pid_task(find_vpid(synad_pid), PIDTYPE_PID); + if (!synad_task) + return -EINVAL; + } + + return count; +} +#endif + +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int ii; + int cnt; + int count = 0; + + for (ii = 0; ii < vir_button_map->nbuttons; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "0x01:%d:%d:%d:%d:%d\n", + vir_button_map->map[ii * 5 + 0], + vir_button_map->map[ii * 5 + 1], + vir_button_map->map[ii * 5 + 2], + vir_button_map->map[ii * 5 + 3], + vir_button_map->map[ii * 5 + 4]); + buf += cnt; + count += cnt; + } + + return count; +} + +static void synaptics_rmi4_f11_wg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char reporting_control; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F11) + break; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base, + &reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + reporting_control = (reporting_control & ~MASK_3BIT); + if (enable) + reporting_control |= F11_WAKEUP_GESTURE_MODE; + else + reporting_control |= F11_CONTINUOUS_MODE; + + retval = synaptics_rmi4_reg_write(rmi4_data, + fhandler->full_addr.ctrl_base, + &reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + return; +} + +static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char offset; + unsigned char reporting_control[3]; + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) + break; + } + + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + offset = extra_data->ctrl20_offset; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + if (enable) + reporting_control[2] = F12_WAKEUP_GESTURE_MODE; + else + reporting_control[2] = F12_CONTINUOUS_MODE; + + retval = synaptics_rmi4_reg_write(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + return; +} + +static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + if (rmi4_data->f11_wakeup_gesture) + synaptics_rmi4_f11_wg(rmi4_data, enable); + else if (rmi4_data->f12_wakeup_gesture) + synaptics_rmi4_f12_wg(rmi4_data, enable); + + return; +} + +static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; /* number of touch points */ + unsigned char reg_index; + unsigned char finger; + unsigned char fingers_supported; + unsigned char num_of_finger_status_regs; + unsigned char finger_shift; + unsigned char finger_status; + unsigned char finger_status_reg[3]; + unsigned char detected_gestures; + unsigned short data_addr; + unsigned short data_offset; + int x; + int y; + int wx; + int wy; + int temp; + struct synaptics_rmi4_f11_data_1_5 data; + struct synaptics_rmi4_f11_extra_data *extra_data; + + /* + * The number of finger status registers is determined by the + * maximum number of fingers supported - 2 bits per finger. So + * the number of finger status registers to read is: + * register_count = ceil(max_num_of_fingers / 4) + */ + fingers_supported = fhandler->num_of_data_points; + num_of_finger_status_regs = (fingers_supported + 3) / 4; + data_addr = fhandler->full_addr.data_base; + + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra; + + if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data38_offset, + &detected_gestures, + sizeof(detected_gestures)); + if (retval < 0) + return 0; + + if (detected_gestures) { + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1); + input_sync(rmi4_data->input_dev); + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0); + input_sync(rmi4_data->input_dev); + rmi4_data->suspend = false; + } + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + return 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr, + finger_status_reg, + num_of_finger_status_regs); + if (retval < 0) + return 0; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (finger = 0; finger < fingers_supported; finger++) { + reg_index = finger / 4; + finger_shift = (finger % 4) * 2; + finger_status = (finger_status_reg[reg_index] >> finger_shift) + & MASK_2BIT; + + /* + * Each 2-bit finger status field represents the following: + * 00 = finger not present + * 01 = finger present and data accurate + * 10 = finger present but data may be inaccurate + * 11 = reserved + */ +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, finger_status); +#endif + + if (finger_status) { + data_offset = data_addr + + num_of_finger_status_regs + + (finger * sizeof(data.data)); + retval = synaptics_rmi4_reg_read(rmi4_data, + data_offset, + data.data, + sizeof(data.data)); + if (retval < 0) { + touch_count = 0; + goto exit; + } + + x = (data.x_position_11_4 << 4) | data.x_position_3_0; + y = (data.y_position_11_4 << 4) | data.y_position_3_0; + wx = data.wx; + wy = data.wy; + + if (rmi4_data->hw_if->board_data->swap_axes) { + temp = x; + x = y; + y = temp; + temp = wx; + wx = wy; + wy = temp; + } + + if (rmi4_data->hw_if->board_data->x_flip) + x = rmi4_data->sensor_max_x - x; + if (rmi4_data->hw_if->board_data->y_flip) + y = rmi4_data->sensor_max_y - y; + + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 1); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_Y, y); +#ifdef REPORT_2D_W + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, max(wx, wy)); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, min(wx, wy)); +#endif +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: status = 0x%02x, x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + finger_status, + x, y, wx, wy); + + touch_count++; + } + } + + if (touch_count == 0) { + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + } + + input_sync(rmi4_data->input_dev); + +exit: + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return touch_count; +} + +static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; /* number of touch points */ + unsigned char index; + unsigned char finger; + unsigned char fingers_to_process; + unsigned char finger_status; + unsigned char size_of_2d_data; + unsigned char gesture_type; + unsigned short data_addr; + int x; + int y; + int wx; + int wy; + int temp; +#if defined(REPORT_2D_PRESSURE) || defined(F51_DISCRETE_FORCE) + int pressure; +#endif +#ifdef REPORT_2D_PRESSURE + unsigned char f_fingers; + unsigned char f_lsb; + unsigned char f_msb; + unsigned char *f_data; +#endif +#ifdef F51_DISCRETE_FORCE + unsigned char force_level; +#endif + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_f12_finger_data *data; + struct synaptics_rmi4_f12_finger_data *finger_data; + static unsigned char finger_presence; + static unsigned char stylus_presence; +#ifdef F12_DATA_15_WORKAROUND + static unsigned char objects_already_present; +#endif + + fingers_to_process = fhandler->num_of_data_points; + data_addr = fhandler->full_addr.data_base; + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data); + + if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data4_offset, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) + return 0; + + gesture_type = rmi4_data->gesture_detection[0]; + + if (gesture_type && gesture_type != F12_UDG_DETECT) { + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1); + input_sync(rmi4_data->input_dev); + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0); + input_sync(rmi4_data->input_dev); + + rmi4_data->suspend = false; + } + + return 0; + } + + /* Determine the total number of fingers to process */ + if (extra_data->data15_size) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data15_offset, + extra_data->data15_data, + extra_data->data15_size); + if (retval < 0) + return 0; + + /* Start checking from the highest bit */ + index = extra_data->data15_size - 1; /* Highest byte */ + finger = (fingers_to_process - 1) % 8; /* Highest bit */ + do { + if (extra_data->data15_data[index] & (1 << finger)) + break; + + if (finger) { + finger--; + } else if (index > 0) { + index--; /* Move to the next lower byte */ + finger = 7; + } + + fingers_to_process--; + } while (fingers_to_process); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of fingers to process = %d\n", + __func__, fingers_to_process); + } + +#ifdef F12_DATA_15_WORKAROUND + fingers_to_process = max(fingers_to_process, objects_already_present); +#endif + + if (!fingers_to_process) { + synaptics_rmi4_free_fingers(rmi4_data); + finger_presence = 0; + stylus_presence = 0; + return 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data1_offset, + (unsigned char *)fhandler->data, + fingers_to_process * size_of_2d_data); + if (retval < 0) + return 0; + + data = (struct synaptics_rmi4_f12_finger_data *)fhandler->data; + +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data29_offset, + extra_data->data29_data, + extra_data->data29_size); + if (retval < 0) + return 0; + } +#endif + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (finger = 0; finger < fingers_to_process; finger++) { + finger_data = data + finger; + finger_status = finger_data->object_type_and_status; + +#ifdef F12_DATA_15_WORKAROUND + objects_already_present = finger + 1; +#endif + + x = (finger_data->x_msb << 8) | (finger_data->x_lsb); + y = (finger_data->y_msb << 8) | (finger_data->y_lsb); +#ifdef REPORT_2D_W + wx = finger_data->wx; + wy = finger_data->wy; +#endif + + if (rmi4_data->hw_if->board_data->swap_axes) { + temp = x; + x = y; + y = temp; + temp = wx; + wx = wy; + wy = temp; + } + + if (rmi4_data->hw_if->board_data->x_flip) + x = rmi4_data->sensor_max_x - x; + if (rmi4_data->hw_if->board_data->y_flip) + y = rmi4_data->sensor_max_y - y; + + switch (finger_status) { + case F12_FINGER_STATUS: + case F12_GLOVED_FINGER_STATUS: + /* Stylus has priority over fingers */ + if (stylus_presence) + break; +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 1); +#endif + + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 1); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_Y, y); +#ifdef REPORT_2D_W + if (rmi4_data->wedge_sensor) { + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, wx); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, wx); + } else { + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, + max(wx, wy)); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, + min(wx, wy)); + } +#endif +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + f_fingers = extra_data->data29_size / 2; + f_data = extra_data->data29_data; + if (finger + 1 > f_fingers) { + pressure = 1; + } else { + f_lsb = finger * 2; + f_msb = finger * 2 + 1; + pressure = (int)f_data[f_lsb] << 0 | + (int)f_data[f_msb] << 8; + } + pressure = pressure > 0 ? pressure : 1; + if (pressure > rmi4_data->force_max) + pressure = rmi4_data->force_max; + input_report_abs(rmi4_data->input_dev, + ABS_MT_PRESSURE, pressure); + } +#elif defined(F51_DISCRETE_FORCE) + if (finger == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + FORCE_LEVEL_ADDR, + &force_level, + sizeof(force_level)); + if (retval < 0) + return 0; + pressure = force_level > 0 ? force_level : 1; + } else { + pressure = 1; + } + input_report_abs(rmi4_data->input_dev, + ABS_MT_PRESSURE, pressure); +#endif +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: status = 0x%02x, x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + finger_status, + x, y, wx, wy); + + finger_presence = 1; + touch_count++; + break; + case F12_PALM_STATUS: + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + x, y, wx, wy); + break; + case F12_STYLUS_STATUS: + case F12_ERASER_STATUS: + if (!rmi4_data->stylus_enable) + break; + /* Stylus has priority over fingers */ + if (finger_presence) { + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + synaptics_rmi4_free_fingers(rmi4_data); + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + finger_presence = 0; + } + if (stylus_presence) {/* Allow one stylus at a timee */ + if (finger + 1 != stylus_presence) + break; + } + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 1); + if (finger_status == F12_STYLUS_STATUS) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 1); + } else { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 1); + } + input_report_abs(rmi4_data->stylus_dev, + ABS_X, x); + input_report_abs(rmi4_data->stylus_dev, + ABS_Y, y); + input_sync(rmi4_data->stylus_dev); + + stylus_presence = finger + 1; + touch_count++; + break; + default: +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 0); +#endif + break; + } + } + + if (touch_count == 0) { + finger_presence = 0; +#ifdef F12_DATA_15_WORKAROUND + objects_already_present = 0; +#endif + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + if (rmi4_data->stylus_enable) { + stylus_presence = 0; + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 0); + if (rmi4_data->eraser_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 0); + } + input_sync(rmi4_data->stylus_dev); + } + } + + input_sync(rmi4_data->input_dev); + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return touch_count; +} + +static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; + unsigned char button; + unsigned char index; + unsigned char shift; + unsigned char status; + unsigned char *data; + unsigned short data_addr = fhandler->full_addr.data_base; + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + static unsigned char do_once = 1; + static bool current_status[MAX_NUMBER_OF_BUTTONS]; +#ifdef NO_0D_WHILE_2D + static bool before_2d_status[MAX_NUMBER_OF_BUTTONS]; + static bool while_2d_status[MAX_NUMBER_OF_BUTTONS]; +#endif + + if (do_once) { + memset(current_status, 0, sizeof(current_status)); +#ifdef NO_0D_WHILE_2D + memset(before_2d_status, 0, sizeof(before_2d_status)); + memset(while_2d_status, 0, sizeof(while_2d_status)); +#endif + do_once = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr, + f1a->button_data_buffer, + f1a->button_bitmask_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read button data registers\n", + __func__); + return; + } + + data = f1a->button_data_buffer; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (button = 0; button < f1a->valid_button_count; button++) { + index = button / 8; + shift = button % 8; + status = ((data[index] >> shift) & MASK_1BIT); + + if (current_status[button] == status) + continue; + else + current_status[button] = status; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Button %d (code %d) ->%d\n", + __func__, button, + f1a->button_map[button], + status); +#ifdef NO_0D_WHILE_2D + if (rmi4_data->fingers_on_2d == false) { + if (status == 1) { + before_2d_status[button] = 1; + } else { + if (while_2d_status[button] == 1) { + while_2d_status[button] = 0; + continue; + } else { + before_2d_status[button] = 0; + } + } + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); + } else { + if (before_2d_status[button] == 1) { + before_2d_status[button] = 0; + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); + } else { + if (status == 1) + while_2d_status[button] = 1; + else + while_2d_status[button] = 0; + } + } +#else + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); +#endif + } + + if (touch_count) + input_sync(rmi4_data->input_dev); + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return; +} + +static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + unsigned char touch_count_2d; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x reporting\n", + __func__, fhandler->fn_number); + + switch (fhandler->fn_number) { + case SYNAPTICS_RMI4_F11: + touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data, + fhandler); + + if (touch_count_2d) + rmi4_data->fingers_on_2d = true; + else + rmi4_data->fingers_on_2d = false; + break; + case SYNAPTICS_RMI4_F12: + touch_count_2d = synaptics_rmi4_f12_abs_report(rmi4_data, + fhandler); + + if (touch_count_2d) + rmi4_data->fingers_on_2d = true; + else + rmi4_data->fingers_on_2d = false; + break; + case SYNAPTICS_RMI4_F1A: + synaptics_rmi4_f1a_report(rmi4_data, fhandler); + break; +#ifdef USE_DATA_SERVER + case SYNAPTICS_RMI4_F21: + if (synad_pid) + send_sig_info(SIGIO, &interrupt_signal, synad_task); + break; +#endif + default: + break; + } + + return; +} + +static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data, + bool report) +{ + int retval; + unsigned char data[MAX_INTR_REGISTERS + 1]; + unsigned char *intr = &data[1]; + bool was_in_bl_mode; + struct synaptics_rmi4_f01_device_status status; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + /* + * Get interrupt status information from F01 Data1 register to + * determine the source(s) that are flagging the interrupt. + */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + data, + rmi4_data->num_of_intr_regs + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read interrupt status\n", + __func__); + return; + } + + status.data[0] = data[0]; + if (status.status_code == STATUS_CRC_IN_PROGRESS) { + retval = synaptics_rmi4_check_status(rmi4_data, + &was_in_bl_mode); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to check status\n", + __func__); + return; + } + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device status\n", + __func__); + return; + } + } + if (status.unconfigured && !status.flash_prog) { + pr_notice("%s: spontaneous reset detected\n", __func__); + retval = synaptics_rmi4_reinit_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reinit device\n", + __func__); + } + } + + if (!report) + return; + + /* + * Traverse the function handler list and service the source(s) + * of the interrupt accordingly. + */ + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & + intr[fhandler->intr_reg_num]) { + + synaptics_rmi4_report_touch(rmi4_data, + fhandler); + + } + } + } + } + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) { + if (!exp_fhandler->insert && + !exp_fhandler->remove && + (exp_fhandler->exp_fn->attn != NULL)) + exp_fhandler->exp_fn->attn(rmi4_data, intr[0]); + } + } + mutex_unlock(&exp_data.mutex); + + return; +} + +static irqreturn_t synaptics_rmi4_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *rmi4_data = data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state) + goto exit; + + synaptics_rmi4_sensor_report(rmi4_data, true); + +exit: + return IRQ_HANDLED; +} + +static int synaptics_rmi4_int_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval = 0; + unsigned char ii; + unsigned char zero = 0x00; + unsigned char *intr_mask; + unsigned short intr_addr; + + intr_mask = rmi4_data->intr_mask; + + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { + if (intr_mask[ii] != 0x00) { + intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii; + if (enable) { + retval = synaptics_rmi4_reg_write(rmi4_data, + intr_addr, + &(intr_mask[ii]), + sizeof(intr_mask[ii])); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_write(rmi4_data, + intr_addr, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } + } + } + + return retval; +} + +static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable, bool attn_only) +{ + int retval = 0; + unsigned char data[MAX_INTR_REGISTERS]; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex)); + + if (attn_only) { + retval = synaptics_rmi4_int_enable(rmi4_data, enable); + goto exit; + } + + if (enable) { + if (rmi4_data->irq_enabled) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Interrupt already enabled\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_int_enable(rmi4_data, false); + if (retval < 0) + goto exit; + + /* Clear interrupts */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr + 1, + data, + rmi4_data->num_of_intr_regs); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read interrupt status\n", + __func__); + goto exit; + } + + retval = request_threaded_irq(rmi4_data->irq, NULL, + synaptics_rmi4_irq, bdata->irq_flags, + PLATFORM_DRIVER_NAME, rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create irq thread\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_int_enable(rmi4_data, true); + if (retval < 0) + goto exit; + + rmi4_data->irq_enabled = true; + } else { + if (rmi4_data->irq_enabled) { + disable_irq(rmi4_data->irq); + free_irq(rmi4_data->irq, rmi4_data); + rmi4_data->irq_enabled = false; + } + } + +exit: + mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex)); + + return retval; +} + +static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + unsigned char ii; + unsigned char intr_offset; + + fhandler->intr_reg_num = (intr_count + 7) / 8; + if (fhandler->intr_reg_num != 0) + fhandler->intr_reg_num -= 1; + + /* Set an enable bit for each data source */ + intr_offset = intr_count % 8; + fhandler->intr_mask = 0; + for (ii = intr_offset; + ii < (fd->intr_src_count + intr_offset); + ii++) + fhandler->intr_mask |= 1 << ii; + + return; +} + +static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->data = NULL; + fhandler->extra = NULL; + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + rmi4_data->f01_query_base_addr = fd->query_base_addr; + rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr; + rmi4_data->f01_data_base_addr = fd->data_base_addr; + rmi4_data->f01_cmd_base_addr = fd->cmd_base_addr; + + return 0; +} + +static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval; + int temp; + unsigned char offset; + unsigned char fingers_supported; + struct synaptics_rmi4_f11_extra_data *extra_data; + struct synaptics_rmi4_f11_query_0_5 query_0_5; + struct synaptics_rmi4_f11_query_7_8 query_7_8; + struct synaptics_rmi4_f11_query_9 query_9; + struct synaptics_rmi4_f11_query_12 query_12; + struct synaptics_rmi4_f11_query_27 query_27; + struct synaptics_rmi4_f11_ctrl_6_9 control_6_9; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL); + if (!fhandler->extra) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->extra\n", + __func__); + return -ENOMEM; + } + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base, + query_0_5.data, + sizeof(query_0_5.data)); + if (retval < 0) + return retval; + + /* Maximum number of fingers supported */ + if (query_0_5.num_of_fingers <= 4) + fhandler->num_of_data_points = query_0_5.num_of_fingers + 1; + else if (query_0_5.num_of_fingers == 5) + fhandler->num_of_data_points = 10; + + rmi4_data->num_of_fingers = fhandler->num_of_data_points; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + 6, + control_6_9.data, + sizeof(control_6_9.data)); + if (retval < 0) + return retval; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = control_6_9.sensor_max_x_pos_7_0 | + (control_6_9.sensor_max_x_pos_11_8 << 8); + rmi4_data->sensor_max_y = control_6_9.sensor_max_y_pos_7_0 | + (control_6_9.sensor_max_y_pos_11_8 << 8); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x max x = %d max y = %d\n", + __func__, fhandler->fn_number, + rmi4_data->sensor_max_x, + rmi4_data->sensor_max_y); + + rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH; + + if (bdata->swap_axes) { + temp = rmi4_data->sensor_max_x; + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y; + rmi4_data->sensor_max_y = temp; + } + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + fhandler->data = NULL; + + offset = sizeof(query_0_5.data); + + /* query 6 */ + if (query_0_5.has_rel) + offset += 1; + + /* queries 7 8 */ + if (query_0_5.has_gestures) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_7_8.data, + sizeof(query_7_8.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_7_8.data); + } + + /* query 9 */ + if (query_0_5.has_query_9) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_9.data, + sizeof(query_9.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_9.data); + } + + /* query 10 */ + if (query_0_5.has_gestures && query_7_8.has_touch_shapes) + offset += 1; + + /* query 11 */ + if (query_0_5.has_query_11) + offset += 1; + + /* query 12 */ + if (query_0_5.has_query_12) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_12.data, + sizeof(query_12.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_12.data); + } + + /* query 13 */ + if (query_0_5.has_jitter_filter) + offset += 1; + + /* query 14 */ + if (query_0_5.has_query_12 && query_12.has_general_information_2) + offset += 1; + + /* queries 15 16 17 18 19 20 21 22 23 24 25 26*/ + if (query_0_5.has_query_12 && query_12.has_physical_properties) + offset += 12; + + /* query 27 */ + if (query_0_5.has_query_27) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_27.data, + sizeof(query_27.data)); + if (retval < 0) + return retval; + + rmi4_data->f11_wakeup_gesture = query_27.has_wakeup_gesture; + } + + if (!rmi4_data->f11_wakeup_gesture) + return retval; + + /* data 0 */ + fingers_supported = fhandler->num_of_data_points; + offset = (fingers_supported + 3) / 4; + + /* data 1 2 3 4 5 */ + offset += 5 * fingers_supported; + + /* data 6 7 */ + if (query_0_5.has_rel) + offset += 2 * fingers_supported; + + /* data 8 */ + if (query_0_5.has_gestures && query_7_8.data[0]) + offset += 1; + + /* data 9 */ + if (query_0_5.has_gestures && (query_7_8.data[0] || query_7_8.data[1])) + offset += 1; + + /* data 10 */ + if (query_0_5.has_gestures && + (query_7_8.has_pinch || query_7_8.has_flick)) + offset += 1; + + /* data 11 12 */ + if (query_0_5.has_gestures && + (query_7_8.has_flick || query_7_8.has_rotate)) + offset += 2; + + /* data 13 */ + if (query_0_5.has_gestures && query_7_8.has_touch_shapes) + offset += (fingers_supported + 3) / 4; + + /* data 14 15 */ + if (query_0_5.has_gestures && + (query_7_8.has_scroll_zones || + query_7_8.has_multi_finger_scroll || + query_7_8.has_chiral_scroll)) + offset += 2; + + /* data 16 17 */ + if (query_0_5.has_gestures && + (query_7_8.has_scroll_zones && + query_7_8.individual_scroll_zones)) + offset += 2; + + /* data 18 19 20 21 22 23 24 25 26 27 */ + if (query_0_5.has_query_9 && query_9.has_contact_geometry) + offset += 10 * fingers_supported; + + /* data 28 */ + if (query_0_5.has_bending_correction || + query_0_5.has_large_object_suppression) + offset += 1; + + /* data 29 30 31 */ + if (query_0_5.has_query_9 && query_9.has_pen_hover_discrimination) + offset += 3; + + /* data 32 */ + if (query_0_5.has_query_12 && + query_12.has_small_object_detection_tuning) + offset += 1; + + /* data 33 34 */ + if (query_0_5.has_query_27 && query_27.f11_query27_b0) + offset += 2; + + /* data 35 */ + if (query_0_5.has_query_12 && query_12.has_8bit_w) + offset += fingers_supported; + + /* data 36 */ + if (query_0_5.has_bending_correction) + offset += 1; + + /* data 37 */ + if (query_0_5.has_query_27 && query_27.has_data_37) + offset += 1; + + /* data 38 */ + if (query_0_5.has_query_27 && query_27.has_wakeup_gesture) + extra_data->data38_offset = offset; + + return retval; +} + +static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data, + unsigned short ctrl28) +{ + int retval; + static unsigned short ctrl_28_address; + + if (ctrl28) + ctrl_28_address = ctrl28; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_28_address, + &rmi4_data->report_enable, + sizeof(rmi4_data->report_enable)); + if (retval < 0) + return retval; + + return retval; +} + +static int synaptics_rmi4_f12_find_sub(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + unsigned char *presence, unsigned char presence_size, + unsigned char structure_offset, unsigned char reg, + unsigned char sub) +{ + int retval; + unsigned char cnt; + unsigned char regnum; + unsigned char bitnum; + unsigned char p_index; + unsigned char s_index; + unsigned char offset; + unsigned char max_reg; + unsigned char *structure; + + max_reg = (presence_size - 1) * 8 - 1; + + if (reg > max_reg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Register number (%d) over limit\n", + __func__, reg); + return -EINVAL; + } + + p_index = reg / 8 + 1; + bitnum = reg % 8; + if ((presence[p_index] & (1 << bitnum)) == 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Register %d is not present\n", + __func__, reg); + return -EINVAL; + } + + structure = kmalloc(presence[0], GFP_KERNEL); + if (!structure) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for structure register\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + structure_offset, + structure, + presence[0]); + if (retval < 0) + goto exit; + + s_index = 0; + + for (regnum = 0; regnum < reg; regnum++) { + p_index = regnum / 8 + 1; + bitnum = regnum % 8; + if ((presence[p_index] & (1 << bitnum)) == 0x00) + continue; + + if (structure[s_index] == 0x00) + s_index += 3; + else + s_index++; + + while (structure[s_index] & ~MASK_7BIT) + s_index++; + + s_index++; + } + + cnt = 0; + s_index++; + offset = sub / 7; + bitnum = sub % 7; + + do { + if (cnt == offset) { + if (structure[s_index + cnt] & (1 << bitnum)) + retval = 1; + else + retval = 0; + goto exit; + } + cnt++; + } while (structure[s_index + cnt - 1] & ~MASK_7BIT); + + retval = 0; + +exit: + kfree(structure); + + return retval; +} + +static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval = 0; + int temp; + unsigned char subpacket; + unsigned char ctrl_23_size; + unsigned char size_of_2d_data; + unsigned char size_of_query5; + unsigned char size_of_query8; + unsigned char ctrl_8_offset; + unsigned char ctrl_20_offset; + unsigned char ctrl_23_offset; + unsigned char ctrl_28_offset; + unsigned char ctrl_31_offset; + unsigned char ctrl_58_offset; + unsigned char num_of_fingers; + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_f12_query_5 *query_5 = NULL; + struct synaptics_rmi4_f12_query_8 *query_8 = NULL; + struct synaptics_rmi4_f12_ctrl_8 *ctrl_8 = NULL; + struct synaptics_rmi4_f12_ctrl_23 *ctrl_23 = NULL; + struct synaptics_rmi4_f12_ctrl_31 *ctrl_31 = NULL; + struct synaptics_rmi4_f12_ctrl_58 *ctrl_58 = NULL; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL); + if (!fhandler->extra) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->extra\n", + __func__); + return -ENOMEM; + } + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data); + + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL); + if (!query_5) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_5\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + query_8 = kzalloc(sizeof(*query_8), GFP_KERNEL); + if (!query_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_8 = kzalloc(sizeof(*ctrl_8), GFP_KERNEL); + if (!ctrl_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_23 = kzalloc(sizeof(*ctrl_23), GFP_KERNEL); + if (!ctrl_23) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_23\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_31 = kzalloc(sizeof(*ctrl_31), GFP_KERNEL); + if (!ctrl_31) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_31\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_58 = kzalloc(sizeof(*ctrl_58), GFP_KERNEL); + if (!ctrl_58) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_58\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 4, + &size_of_query5, + sizeof(size_of_query5)); + if (retval < 0) + goto exit; + + if (size_of_query5 > sizeof(query_5->data)) + size_of_query5 = sizeof(query_5->data); + memset(query_5->data, 0x00, sizeof(query_5->data)); + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 5, + query_5->data, + size_of_query5); + if (retval < 0) + goto exit; + + ctrl_8_offset = query_5->ctrl0_is_present + + query_5->ctrl1_is_present + + query_5->ctrl2_is_present + + query_5->ctrl3_is_present + + query_5->ctrl4_is_present + + query_5->ctrl5_is_present + + query_5->ctrl6_is_present + + query_5->ctrl7_is_present; + + ctrl_20_offset = ctrl_8_offset + + query_5->ctrl8_is_present + + query_5->ctrl9_is_present + + query_5->ctrl10_is_present + + query_5->ctrl11_is_present + + query_5->ctrl12_is_present + + query_5->ctrl13_is_present + + query_5->ctrl14_is_present + + query_5->ctrl15_is_present + + query_5->ctrl16_is_present + + query_5->ctrl17_is_present + + query_5->ctrl18_is_present + + query_5->ctrl19_is_present; + + ctrl_23_offset = ctrl_20_offset + + query_5->ctrl20_is_present + + query_5->ctrl21_is_present + + query_5->ctrl22_is_present; + + ctrl_28_offset = ctrl_23_offset + + query_5->ctrl23_is_present + + query_5->ctrl24_is_present + + query_5->ctrl25_is_present + + query_5->ctrl26_is_present + + query_5->ctrl27_is_present; + + ctrl_31_offset = ctrl_28_offset + + query_5->ctrl28_is_present + + query_5->ctrl29_is_present + + query_5->ctrl30_is_present; + + ctrl_58_offset = ctrl_31_offset + + query_5->ctrl31_is_present + + query_5->ctrl32_is_present + + query_5->ctrl33_is_present + + query_5->ctrl34_is_present + + query_5->ctrl35_is_present + + query_5->ctrl36_is_present + + query_5->ctrl37_is_present + + query_5->ctrl38_is_present + + query_5->ctrl39_is_present + + query_5->ctrl40_is_present + + query_5->ctrl41_is_present + + query_5->ctrl42_is_present + + query_5->ctrl43_is_present + + query_5->ctrl44_is_present + + query_5->ctrl45_is_present + + query_5->ctrl46_is_present + + query_5->ctrl47_is_present + + query_5->ctrl48_is_present + + query_5->ctrl49_is_present + + query_5->ctrl50_is_present + + query_5->ctrl51_is_present + + query_5->ctrl52_is_present + + query_5->ctrl53_is_present + + query_5->ctrl54_is_present + + query_5->ctrl55_is_present + + query_5->ctrl56_is_present + + query_5->ctrl57_is_present; + + ctrl_23_size = 2; + for (subpacket = 2; subpacket <= 4; subpacket++) { + retval = synaptics_rmi4_f12_find_sub(rmi4_data, + fhandler, query_5->data, sizeof(query_5->data), + 6, 23, subpacket); + if (retval == 1) + ctrl_23_size++; + else if (retval < 0) + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_23_offset, + ctrl_23->data, + ctrl_23_size); + if (retval < 0) + goto exit; + + /* Maximum number of fingers supported */ + fhandler->num_of_data_points = min_t(unsigned char, + ctrl_23->max_reported_objects, + (unsigned char)F12_FINGERS_TO_SUPPORT); + + num_of_fingers = fhandler->num_of_data_points; + rmi4_data->num_of_fingers = num_of_fingers; + + rmi4_data->stylus_enable = ctrl_23->stylus_enable; + rmi4_data->eraser_enable = ctrl_23->eraser_enable; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 7, + &size_of_query8, + sizeof(size_of_query8)); + if (retval < 0) + goto exit; + + if (size_of_query8 > sizeof(query_8->data)) + size_of_query8 = sizeof(query_8->data); + memset(query_8->data, 0x00, sizeof(query_8->data)); + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 8, + query_8->data, + size_of_query8); + if (retval < 0) + goto exit; + + /* Determine the presence of the Data0 register */ + extra_data->data1_offset = query_8->data0_is_present; + + if ((size_of_query8 >= 3) && (query_8->data15_is_present)) { + extra_data->data15_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present + + query_8->data4_is_present + + query_8->data5_is_present + + query_8->data6_is_present + + query_8->data7_is_present + + query_8->data8_is_present + + query_8->data9_is_present + + query_8->data10_is_present + + query_8->data11_is_present + + query_8->data12_is_present + + query_8->data13_is_present + + query_8->data14_is_present; + extra_data->data15_size = (num_of_fingers + 7) / 8; + } else { + extra_data->data15_size = 0; + } + +#ifdef REPORT_2D_PRESSURE + if ((size_of_query8 >= 5) && (query_8->data29_is_present)) { + extra_data->data29_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present + + query_8->data4_is_present + + query_8->data5_is_present + + query_8->data6_is_present + + query_8->data7_is_present + + query_8->data8_is_present + + query_8->data9_is_present + + query_8->data10_is_present + + query_8->data11_is_present + + query_8->data12_is_present + + query_8->data13_is_present + + query_8->data14_is_present + + query_8->data15_is_present + + query_8->data16_is_present + + query_8->data17_is_present + + query_8->data18_is_present + + query_8->data19_is_present + + query_8->data20_is_present + + query_8->data21_is_present + + query_8->data22_is_present + + query_8->data23_is_present + + query_8->data24_is_present + + query_8->data25_is_present + + query_8->data26_is_present + + query_8->data27_is_present + + query_8->data28_is_present; + extra_data->data29_size = 0; + for (subpacket = 0; subpacket <= num_of_fingers; subpacket++) { + retval = synaptics_rmi4_f12_find_sub(rmi4_data, + fhandler, query_8->data, + sizeof(query_8->data), + 9, 29, subpacket); + if (retval == 1) + extra_data->data29_size += 2; + else if (retval < 0) + goto exit; + } + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_58_offset, + ctrl_58->data, + sizeof(ctrl_58->data)); + if (retval < 0) + goto exit; + rmi4_data->force_min = + (int)(ctrl_58->min_force_lsb << 0) | + (int)(ctrl_58->min_force_msb << 8); + rmi4_data->force_max = + (int)(ctrl_58->max_force_lsb << 0) | + (int)(ctrl_58->max_force_msb << 8); + rmi4_data->report_pressure = true; + } else { + extra_data->data29_size = 0; + rmi4_data->report_pressure = false; + } +#endif + + rmi4_data->report_enable = RPT_DEFAULT; +#ifdef REPORT_2D_Z + rmi4_data->report_enable |= RPT_Z; +#endif +#ifdef REPORT_2D_W + rmi4_data->report_enable |= (RPT_WX | RPT_WY); +#endif + + retval = synaptics_rmi4_f12_set_enables(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_28_offset); + if (retval < 0) + goto exit; + + if (query_5->ctrl8_is_present) { + rmi4_data->wedge_sensor = false; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_8_offset, + ctrl_8->data, + sizeof(ctrl_8->data)); + if (retval < 0) + goto exit; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = + ((unsigned int)ctrl_8->max_x_coord_lsb << 0) | + ((unsigned int)ctrl_8->max_x_coord_msb << 8); + rmi4_data->sensor_max_y = + ((unsigned int)ctrl_8->max_y_coord_lsb << 0) | + ((unsigned int)ctrl_8->max_y_coord_msb << 8); + + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH; + } else { + rmi4_data->wedge_sensor = true; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_31_offset, + ctrl_31->data, + sizeof(ctrl_31->data)); + if (retval < 0) + goto exit; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = + ((unsigned int)ctrl_31->max_x_coord_lsb << 0) | + ((unsigned int)ctrl_31->max_x_coord_msb << 8); + rmi4_data->sensor_max_y = + ((unsigned int)ctrl_31->max_y_coord_lsb << 0) | + ((unsigned int)ctrl_31->max_y_coord_msb << 8); + + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x max x = %d max y = %d\n", + __func__, fhandler->fn_number, + rmi4_data->sensor_max_x, + rmi4_data->sensor_max_y); + + if (bdata->swap_axes) { + temp = rmi4_data->sensor_max_x; + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y; + rmi4_data->sensor_max_y = temp; + } + + rmi4_data->f12_wakeup_gesture = query_5->ctrl27_is_present; + if (rmi4_data->f12_wakeup_gesture) { + extra_data->ctrl20_offset = ctrl_20_offset; + extra_data->data4_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present; + } + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + /* Allocate memory for finger data storage space */ + fhandler->data_size = num_of_fingers * size_of_2d_data; + fhandler->data = kmalloc(fhandler->data_size, GFP_KERNEL); + if (!fhandler->data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->data\n", + __func__); + retval = -ENOMEM; + goto exit; + } + +exit: + kfree(query_5); + kfree(query_8); + kfree(ctrl_8); + kfree(ctrl_23); + kfree(ctrl_31); + kfree(ctrl_58); + + return retval; +} + +static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + struct synaptics_rmi4_f1a_handle *f1a; + + f1a = kzalloc(sizeof(*f1a), GFP_KERNEL); + if (!f1a) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for function handle\n", + __func__); + return -ENOMEM; + } + + fhandler->data = (void *)f1a; + fhandler->extra = NULL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base, + f1a->button_query.data, + sizeof(f1a->button_query.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query registers\n", + __func__); + return retval; + } + + f1a->max_count = f1a->button_query.max_button_count + 1; + + f1a->button_control.txrx_map = kzalloc(f1a->max_count * 2, GFP_KERNEL); + if (!f1a->button_control.txrx_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tx rx mapping\n", + __func__); + return -ENOMEM; + } + + f1a->button_bitmask_size = (f1a->max_count + 7) / 8; + + f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size, + sizeof(*(f1a->button_data_buffer)), GFP_KERNEL); + if (!f1a->button_data_buffer) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", + __func__); + return -ENOMEM; + } + + f1a->button_map = kcalloc(f1a->max_count, + sizeof(*(f1a->button_map)), GFP_KERNEL); + if (!f1a->button_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for button map\n", + __func__); + return -ENOMEM; + } + + return 0; +} + +static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char ii; + unsigned char offset = 0; + struct synaptics_rmi4_f1a_query_4 query_4; + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + rmi4_data->valid_button_count = f1a->valid_button_count; + + offset = f1a->button_query.has_general_control + + f1a->button_query.has_interrupt_enable + + f1a->button_query.has_multibutton_select; + + if (f1a->button_query.has_tx_rx_map) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + f1a->button_control.txrx_map, + f1a->max_count * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tx rx mapping\n", + __func__); + return retval; + } + + rmi4_data->button_txrx_mapping = f1a->button_control.txrx_map; + } + + if (f1a->button_query.has_query4) { + offset = 2 + f1a->button_query.has_query2 + + f1a->button_query.has_query3; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_4.data, + sizeof(query_4.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read button features 4\n", + __func__); + return retval; + } + + if (query_4.has_ctrl24) + rmi4_data->external_afe_buttons = true; + else + rmi4_data->external_afe_buttons = false; + } + + if (!bdata->cap_button_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: cap_button_map is NULL in board file\n", + __func__); + return -ENODEV; + } else if (!bdata->cap_button_map->map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Button map is missing in board file\n", + __func__); + return -ENODEV; + } else { + if (bdata->cap_button_map->nbuttons != f1a->max_count) { + f1a->valid_button_count = min(f1a->max_count, + bdata->cap_button_map->nbuttons); + } else { + f1a->valid_button_count = f1a->max_count; + } + + for (ii = 0; ii < f1a->valid_button_count; ii++) + f1a->button_map[ii] = bdata->cap_button_map->map[ii]; + + rmi4_data->valid_button_count = f1a->valid_button_count; + } + + return 0; +} + +static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler) +{ + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + + if (f1a) { + kfree(f1a->button_control.txrx_map); + kfree(f1a->button_data_buffer); + kfree(f1a->button_map); + kfree(f1a); + fhandler->data = NULL; + } + + return; +} + +static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler); + if (retval < 0) + goto error_exit; + + retval = synaptics_rmi4_f1a_button_map(rmi4_data, fhandler); + if (retval < 0) + goto error_exit; + + rmi4_data->button_0d_enabled = 1; + + return 0; + +error_exit: + synaptics_rmi4_f1a_kfree(fhandler); + + return retval; +} + +static void synaptics_rmi4_empty_fn_list(struct synaptics_rmi4_data *rmi4_data) +{ + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_fn *fhandler_temp; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry_safe(fhandler, + fhandler_temp, + &rmi->support_fn_list, + link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { + synaptics_rmi4_f1a_kfree(fhandler); + } else { + kfree(fhandler->extra); + kfree(fhandler->data); + } + list_del(&fhandler->link); + kfree(fhandler); + } + } + INIT_LIST_HEAD(&rmi->support_fn_list); + + return; +} + +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, + bool *was_in_bl_mode) +{ + int retval; + int timeout = CHECK_STATUS_TIMEOUT_MS; + struct synaptics_rmi4_f01_device_status status; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) + return retval; + + while (status.status_code == STATUS_CRC_IN_PROGRESS) { + if (timeout > 0) + msleep(20); + else + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) + return retval; + + timeout -= 20; + } + + if (timeout != CHECK_STATUS_TIMEOUT_MS) + *was_in_bl_mode = true; + + if (status.flash_prog == 1) { + rmi4_data->flash_prog_mode = true; + pr_notice("%s: In flash prog mode, status = 0x%02x\n", + __func__, + status.status_code); + } else { + rmi4_data->flash_prog_mode = false; + } + + return 0; +} + +static void synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char device_ctrl; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set configured\n", + __func__); + return; + } + + rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON; + device_ctrl |= CONFIGURED; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set configured\n", + __func__); + } + + return; +} + +static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler, + struct synaptics_rmi4_fn_desc *rmi_fd, int page_number) +{ + *fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL); + if (!(*fhandler)) + return -ENOMEM; + + (*fhandler)->full_addr.data_base = + (rmi_fd->data_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.ctrl_base = + (rmi_fd->ctrl_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.cmd_base = + (rmi_fd->cmd_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.query_base = + (rmi_fd->query_base_addr | + (page_number << 8)); + + return 0; +} + +static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char page_number; + unsigned char intr_count; + unsigned char *f01_query; + unsigned short pdt_entry_addr; + bool f01found; + bool f35found; + bool was_in_bl_mode; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + +rescan_pdt: + f01found = false; + f35found = false; + was_in_bl_mode = false; + intr_count = 0; + INIT_LIST_HEAD(&rmi->support_fn_list); + + /* Scan the page description tables of the pages to service */ + for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) { + for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END; + pdt_entry_addr -= PDT_ENTRY_SIZE) { + pdt_entry_addr |= (page_number << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + pdt_entry_addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + pdt_entry_addr &= ~(MASK_8BIT << 8); + + fhandler = NULL; + + if (rmi_fd.fn_number == 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Reached end of PDT\n", + __func__); + break; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: F%02x found (page %d)\n", + __func__, rmi_fd.fn_number, + page_number); + + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + if (rmi_fd.intr_src_count == 0) + break; + + f01found = true; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f01_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_check_status(rmi4_data, + &was_in_bl_mode); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to check status\n", + __func__); + return retval; + } + + if (was_in_bl_mode) { + kfree(fhandler); + fhandler = NULL; + goto rescan_pdt; + } + + if (rmi4_data->flash_prog_mode) + goto flash_prog_mode; + + break; + case SYNAPTICS_RMI4_F11: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f11_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + break; + case SYNAPTICS_RMI4_F12: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f12_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + break; + case SYNAPTICS_RMI4_F1A: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f1a_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) { +#ifdef IGNORE_FN_INIT_FAILURE + kfree(fhandler); + fhandler = NULL; +#else + return retval; +#endif + } + break; +#ifdef USE_DATA_SERVER + case SYNAPTICS_RMI4_F21: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + fhandler->fn_number = rmi_fd.fn_number; + fhandler->num_of_data_sources = + rmi_fd.intr_src_count; + + synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd, + intr_count); + break; +#endif + case SYNAPTICS_RMI4_F35: + f35found = true; + break; +#ifdef F51_DISCRETE_FORCE + case SYNAPTICS_RMI4_F51: + rmi4_data->f51_query_base_addr = + rmi_fd.query_base_addr | + (page_number << 8); + break; +#endif + } + + /* Accumulate the interrupt count */ + intr_count += rmi_fd.intr_src_count; + + if (fhandler && rmi_fd.intr_src_count) { + list_add_tail(&fhandler->link, + &rmi->support_fn_list); + } + } + } + + if (!f01found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F01\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + pr_notice("%s: In microbootloader mode\n", + __func__); + return 0; + } + } + +flash_prog_mode: + rmi4_data->num_of_intr_regs = (intr_count + 7) / 8; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of interrupt registers = %d\n", + __func__, rmi4_data->num_of_intr_regs); + + f01_query = kmalloc(F01_STD_QUERY_LEN, GFP_KERNEL); + if (!f01_query) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for f01_query\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr, + f01_query, + F01_STD_QUERY_LEN); + if (retval < 0) { + kfree(f01_query); + return retval; + } + + /* RMI Version 4.0 currently supported */ + rmi->version_major = 4; + rmi->version_minor = 0; + + rmi->manufacturer_id = f01_query[0]; + rmi->product_props = f01_query[1]; + rmi->product_info[0] = f01_query[2]; + rmi->product_info[1] = f01_query[3]; + retval = secure_memcpy(rmi->product_id_string, + sizeof(rmi->product_id_string), + &f01_query[11], + F01_STD_QUERY_LEN - 11, + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + + kfree(f01_query); + + if (rmi->manufacturer_id != 1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Non-Synaptics device found, manufacturer ID = %d\n", + __func__, rmi->manufacturer_id); + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET, + rmi->build_id, + sizeof(rmi->build_id)); + if (retval < 0) + return retval; + + rmi4_data->firmware_id = (unsigned int)rmi->build_id[0] + + (unsigned int)rmi->build_id[1] * 0x100 + + (unsigned int)rmi->build_id[2] * 0x10000; + + memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask)); + + /* + * Map out the interrupt bit masks for the interrupt sources + * from the registered function handlers. + */ + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + rmi4_data->intr_mask[fhandler->intr_reg_num] |= + fhandler->intr_mask; + } + } + } + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture){ + rmi4_data->enable_wakeup_gesture = false; + synaptics_gesture_func_on = false; + } + rmi4_data->enable_wakeup_gesture = false; + + synaptics_rmi4_set_configured(rmi4_data); + + return 0; +} + +static int synaptics_rmi4_gpio_setup(int gpio, bool config, int dir, int state) +{ + int retval = 0; + unsigned char buf[16]; + + if (config) { + snprintf(buf, PAGE_SIZE, "dsx_gpio_%u\n", gpio); + + retval = gpio_request(gpio, buf); + if (retval) { + pr_err("%s: Failed to get gpio %d (code: %d)", + __func__, gpio, retval); + return retval; + } + + if (dir == 0) + retval = gpio_direction_input(gpio); + else + retval = gpio_direction_output(gpio, state); + if (retval) { + pr_err("%s: Failed to set gpio %d direction", + __func__, gpio); + return retval; + } + } else { + gpio_free(gpio); + } + + return retval; +} + +static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char ii; + struct synaptics_rmi4_f1a_handle *f1a; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_POSITION_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_POSITION_Y, 0, + rmi4_data->sensor_max_y, 0, 0); +#ifdef REPORT_2D_W + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, 0, + rmi4_data->max_touch_width, 0, 0); + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, 0, + rmi4_data->max_touch_width, 0, 0); +#endif + + rmi4_data->input_settings.sensor_max_x = rmi4_data->sensor_max_x; + rmi4_data->input_settings.sensor_max_y = rmi4_data->sensor_max_y; + rmi4_data->input_settings.max_touch_width = rmi4_data->max_touch_width; + +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_PRESSURE, rmi4_data->force_min, + rmi4_data->force_max, 0, 0); + + rmi4_data->input_settings.force_min = rmi4_data->force_min; + rmi4_data->input_settings.force_max = rmi4_data->force_max; + } +#elif defined(F51_DISCRETE_FORCE) + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_PRESSURE, 0, + FORCE_LEVEL_MAX, 0, 0); +#endif + +#ifdef TYPE_B_PROTOCOL +#ifdef KERNEL_ABOVE_3_6 + input_mt_init_slots(rmi4_data->input_dev, + rmi4_data->num_of_fingers, INPUT_MT_DIRECT); +#else + input_mt_init_slots(rmi4_data->input_dev, + rmi4_data->num_of_fingers); +#endif +#endif + + rmi4_data->input_settings.num_of_fingers = rmi4_data->num_of_fingers; + + f1a = NULL; + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) + f1a = fhandler->data; + } + } + + if (f1a) { + for (ii = 0; ii < f1a->valid_button_count; ii++) { + set_bit(f1a->button_map[ii], + rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, + EV_KEY, f1a->button_map[ii]); + } + + rmi4_data->input_settings.valid_button_count = + f1a->valid_button_count; + } + + if (vir_button_map->nbuttons) { + for (ii = 0; ii < vir_button_map->nbuttons; ii++) { + set_bit(vir_button_map->map[ii * 5], + rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, + EV_KEY, vir_button_map->map[ii * 5]); + } + } + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) { + set_bit(KEY_WAKEUP, rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP); + } + + return; +} + +static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + rmi4_data->input_dev = input_allocate_device(); + if (rmi4_data->input_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate input device\n", + __func__); + retval = -ENOMEM; + goto err_input_device; + } + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + goto err_query_device; + } + + rmi4_data->input_dev->name = PLATFORM_DRIVER_NAME; + rmi4_data->input_dev->phys = INPUT_PHYS_NAME; + rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + rmi4_data->input_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(rmi4_data->input_dev, rmi4_data); + + set_bit(EV_SYN, rmi4_data->input_dev->evbit); + set_bit(EV_KEY, rmi4_data->input_dev->evbit); + set_bit(EV_ABS, rmi4_data->input_dev->evbit); + set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit); + set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit); +#endif + + if (bdata->max_y_for_2d >= 0) + rmi4_data->sensor_max_y = bdata->max_y_for_2d; + + synaptics_rmi4_set_params(rmi4_data); + + retval = input_register_device(rmi4_data->input_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register input device\n", + __func__); + goto err_register_input; + } + + rmi4_data->input_settings.stylus_enable = rmi4_data->stylus_enable; + rmi4_data->input_settings.eraser_enable = rmi4_data->eraser_enable; + + if (!rmi4_data->stylus_enable) + return 0; + + rmi4_data->stylus_dev = input_allocate_device(); + if (rmi4_data->stylus_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate stylus device\n", + __func__); + retval = -ENOMEM; + goto err_stylus_device; + } + + rmi4_data->stylus_dev->name = STYLUS_DRIVER_NAME; + rmi4_data->stylus_dev->phys = STYLUS_PHYS_NAME; + rmi4_data->stylus_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + rmi4_data->stylus_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + rmi4_data->stylus_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(rmi4_data->stylus_dev, rmi4_data); + + set_bit(EV_KEY, rmi4_data->stylus_dev->evbit); + set_bit(EV_ABS, rmi4_data->stylus_dev->evbit); + set_bit(BTN_TOUCH, rmi4_data->stylus_dev->keybit); + set_bit(BTN_TOOL_PEN, rmi4_data->stylus_dev->keybit); + if (rmi4_data->eraser_enable) + set_bit(BTN_TOOL_RUBBER, rmi4_data->stylus_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, rmi4_data->stylus_dev->propbit); +#endif + + input_set_abs_params(rmi4_data->stylus_dev, ABS_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->stylus_dev, ABS_Y, 0, + rmi4_data->sensor_max_y, 0, 0); + + retval = input_register_device(rmi4_data->stylus_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register stylus device\n", + __func__); + goto err_register_stylus; + } + + return 0; + +err_register_stylus: + rmi4_data->stylus_dev = NULL; + +err_stylus_device: + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + +err_register_input: +err_query_device: + synaptics_rmi4_empty_fn_list(rmi4_data); + input_free_device(rmi4_data->input_dev); + +err_input_device: + return retval; +} + +static int synaptics_rmi4_set_gpio(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + retval = synaptics_rmi4_gpio_setup( + bdata->irq_gpio, + true, 0, 0); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure attention GPIO\n", + __func__); + goto err_gpio_irq; + } + + if (bdata->power_gpio >= 0) { + retval = synaptics_rmi4_gpio_setup( + bdata->power_gpio, + true, 1, !bdata->power_on_state); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure power GPIO\n", + __func__); + goto err_gpio_power; + } + } + + if (bdata->reset_gpio >= 0) { + retval = synaptics_rmi4_gpio_setup( + bdata->reset_gpio, + true, 1, !bdata->reset_on_state); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure reset GPIO\n", + __func__); + goto err_gpio_reset; + } + } + + if (bdata->power_gpio >= 0) { + gpio_set_value(bdata->power_gpio, bdata->power_on_state); + msleep(bdata->power_delay_ms); + } + + if (bdata->reset_gpio >= 0) { + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state); + msleep(bdata->reset_active_ms); + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state); + msleep(bdata->reset_delay_ms); + } + + return 0; + +err_gpio_reset: + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + +err_gpio_power: + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + +err_gpio_irq: + return retval; +} + +static int synaptics_rmi4_get_reg(struct synaptics_rmi4_data *rmi4_data, + bool get) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!get) { + retval = 0; + goto regulator_put; + } + + if ((bdata->pwr_reg_name != NULL) && (*bdata->pwr_reg_name != 0)) { + rmi4_data->pwr_reg = regulator_get(rmi4_data->pdev->dev.parent, + bdata->pwr_reg_name); + if (IS_ERR(rmi4_data->pwr_reg)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get power regulator\n", + __func__); + retval = PTR_ERR(rmi4_data->pwr_reg); + goto regulator_put; + } + } + + if ((bdata->bus_reg_name != NULL) && (*bdata->bus_reg_name != 0)) { + rmi4_data->bus_reg = regulator_get(rmi4_data->pdev->dev.parent, + bdata->bus_reg_name); + if (IS_ERR(rmi4_data->bus_reg)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get bus pullup regulator\n", + __func__); + retval = PTR_ERR(rmi4_data->bus_reg); + goto regulator_put; + } + } + + return 0; + +regulator_put: + if (rmi4_data->pwr_reg) { + regulator_put(rmi4_data->pwr_reg); + rmi4_data->pwr_reg = NULL; + } + + if (rmi4_data->bus_reg) { + regulator_put(rmi4_data->bus_reg); + rmi4_data->bus_reg = NULL; + } + + return retval; +} + +static int synaptics_rmi4_enable_reg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!enable) { + retval = 0; + goto disable_pwr_reg; + } + + if (rmi4_data->bus_reg) { + retval = regulator_enable(rmi4_data->bus_reg); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable bus pullup regulator\n", + __func__); + goto exit; + } + } + + if (rmi4_data->pwr_reg) { + retval = regulator_enable(rmi4_data->pwr_reg); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable power regulator\n", + __func__); + goto disable_bus_reg; + } + msleep(bdata->power_delay_ms); + } + + return 0; + +disable_pwr_reg: + if (rmi4_data->pwr_reg) + regulator_disable(rmi4_data->pwr_reg); + +disable_bus_reg: + if (rmi4_data->bus_reg) + regulator_disable(rmi4_data->bus_reg); + +exit: + return retval; +} + +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char ii; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + +#ifdef TYPE_B_PROTOCOL + for (ii = 0; ii < rmi4_data->num_of_fingers; ii++) { + input_mt_slot(rmi4_data->input_dev, ii); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 0); + } +#endif + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + input_sync(rmi4_data->input_dev); + + if (rmi4_data->stylus_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 0); + if (rmi4_data->eraser_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 0); + } + input_sync(rmi4_data->stylus_dev); + } + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + rmi4_data->fingers_on_2d = false; + + return 0; +} + +static int synaptics_rmi4_sw_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char command = 0x01; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + + if (rmi4_data->hw_if->ui_hw_init) { + retval = rmi4_data->hw_if->ui_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + return 0; +} + +static int synaptics_rmi4_do_rebuild(struct synaptics_rmi4_data *rmi4_data) +{ + struct synaptics_rmi4_input_settings *settings; + + settings = &(rmi4_data->input_settings); + + if (settings->num_of_fingers != rmi4_data->num_of_fingers) + return 1; + + if (settings->valid_button_count != rmi4_data->valid_button_count) + return 1; + + if (settings->max_touch_width != rmi4_data->max_touch_width) + return 1; + + if (settings->sensor_max_x != rmi4_data->sensor_max_x) + return 1; + + if (settings->sensor_max_y != rmi4_data->sensor_max_y) + return 1; + + if (settings->force_min != rmi4_data->force_min) + return 1; + + if (settings->force_max != rmi4_data->force_max) + return 1; + + if (settings->stylus_enable != rmi4_data->stylus_enable) + return 1; + + if (settings->eraser_enable != rmi4_data->eraser_enable) + return 1; + + return 0; +} + +static void synaptics_rmi4_rebuild_work(struct work_struct *work) +{ + int retval; + unsigned char attr_count; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct synaptics_rmi4_data *rmi4_data = + container_of(delayed_work, struct synaptics_rmi4_data, + rb_work); + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + mutex_lock(&exp_data.mutex); + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->remove != NULL) + exp_fhandler->exp_fn->remove(rmi4_data); + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + synaptics_rmi4_free_fingers(rmi4_data); + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + + retval = synaptics_rmi4_set_input_dev(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up input device\n", + __func__); + goto exit; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit; + } + } + + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->init != NULL) + exp_fhandler->exp_fn->init(rmi4_data); + } + + retval = 0; + +exit: + synaptics_rmi4_irq_enable(rmi4_data, true, false); + + mutex_unlock(&exp_data.mutex); + + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + + return; +} + +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + synaptics_rmi4_free_fingers(rmi4_data); + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) { + synaptics_rmi4_f12_set_enables(rmi4_data, 0); + break; + } + } + } + + retval = synaptics_rmi4_int_enable(rmi4_data, true); + if (retval < 0) + goto exit; + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->reinit != NULL) + exp_fhandler->exp_fn->reinit(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + synaptics_rmi4_set_configured(rmi4_data); + + retval = 0; + +exit: + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + return retval; +} + +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, + bool rebuild) +{ + int retval; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + + retval = synaptics_rmi4_sw_reset(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + goto exit; + } + + synaptics_rmi4_free_fingers(rmi4_data); + + synaptics_rmi4_empty_fn_list(rmi4_data); + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + goto exit; + } + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->reset != NULL) + exp_fhandler->exp_fn->reset(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + retval = 0; + +exit: + synaptics_rmi4_irq_enable(rmi4_data, true, false); + + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + + if (rebuild && synaptics_rmi4_do_rebuild(rmi4_data)) { + queue_delayed_work(rmi4_data->rb_workqueue, + &rmi4_data->rb_work, + msecs_to_jiffies(REBUILD_WORK_DELAY_MS)); + } + + return retval; +} + +#ifdef FB_READY_RESET +static void synaptics_rmi4_reset_work(struct work_struct *work) +{ + int retval; + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = + container_of(work, struct synaptics_rmi4_data, + reset_work); + + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return; +} +#endif + +static void synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char device_ctrl; + unsigned char no_sleep_setting = rmi4_data->no_sleep_setting; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device control\n", + __func__); + return; + } + + device_ctrl = device_ctrl & ~MASK_3BIT; + if (enable) + device_ctrl = device_ctrl | SENSOR_SLEEP; + else + device_ctrl = device_ctrl | no_sleep_setting | NORMAL_OPERATION; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write device control\n", + __func__); + return; + } + + rmi4_data->sensor_sleep = enable; + + return; +} + +static void synaptics_rmi4_exp_fn_work(struct work_struct *work) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler_temp; + struct synaptics_rmi4_data *rmi4_data = exp_data.rmi4_data; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + mutex_lock(&rmi4_data->rmi4_reset_mutex); + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry_safe(exp_fhandler, + exp_fhandler_temp, + &exp_data.list, + link) { + if ((exp_fhandler->exp_fn->init != NULL) && + exp_fhandler->insert) { + exp_fhandler->exp_fn->init(rmi4_data); + exp_fhandler->insert = false; + } else if ((exp_fhandler->exp_fn->remove != NULL) && + exp_fhandler->remove) { + exp_fhandler->exp_fn->remove(rmi4_data); + list_del(&exp_fhandler->link); + kfree(exp_fhandler); + } + } + } + mutex_unlock(&exp_data.mutex); + mutex_unlock(&rmi4_data->rmi4_reset_mutex); + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return; +} + +void synaptics_rmi4_new_function(struct synaptics_rmi4_exp_fn *exp_fn, + bool insert) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + + if (!exp_data.initialized) { + mutex_init(&exp_data.mutex); + INIT_LIST_HEAD(&exp_data.list); + exp_data.initialized = true; + } + + mutex_lock(&exp_data.mutex); + if (insert) { + exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL); + if (!exp_fhandler) { + pr_err("%s: Failed to alloc mem for expansion function\n", + __func__); + goto exit; + } + exp_fhandler->exp_fn = exp_fn; + exp_fhandler->insert = true; + exp_fhandler->remove = false; + list_add_tail(&exp_fhandler->link, &exp_data.list); + } else if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) { + if (exp_fhandler->exp_fn->fn_type == exp_fn->fn_type) { + exp_fhandler->insert = false; + exp_fhandler->remove = true; + goto exit; + } + } + } + +exit: + mutex_unlock(&exp_data.mutex); + + if (exp_data.queue_work) { + queue_delayed_work(exp_data.workqueue, + &exp_data.work, + msecs_to_jiffies(EXP_FN_WORK_DELAY_MS)); + } + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_new_function); + +#ifdef SYNAPTICS_ESD_CHECK +void synaptics_rmi4_esd_work(struct work_struct *work) +{ + unsigned char product_info[F01_STD_QUERY_LEN]; + int retval = 0; + + +struct delayed_work *esd_work = + container_of(work, struct delayed_work, work); +struct synaptics_rmi4_data *rmi4_data = + container_of(esd_work, struct synaptics_rmi4_data, + esd_work); + + +/* + struct synaptics_rmi4_data *rmi4_data = + container_of(work, struct synaptics_rmi4_data, + esd_work); + +*/ + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + printk("[synaptics]Enter %s\n", __func__); + + mutex_lock(&rmi4_data->rmi4_esd_mutex); + + pr_notice("%s: Start of esd check process\n", __func__); + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr, + product_info, + F01_STD_QUERY_LEN); + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s Failed to read product info, need to do HW RESET\n", + __func__); + + gpio_set_value(bdata->reset_gpio, 1); + mdelay(20); + gpio_set_value(bdata->reset_gpio, 0); + mdelay(20); + gpio_set_value(bdata->reset_gpio, 1); + mdelay(200); + + } + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + } + + pr_notice("%s: End of esd check process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_esd_mutex); + + queue_delayed_work(rmi4_data->esd_workqueue, &rmi4_data->esd_work, SYNAPTICS_ESD_CHECK_CIRCLE); + + return; + +} +#endif + + + + +static int synaptics_rmi4_probe(struct platform_device *pdev) +{ + int retval; + unsigned char attr_count; + + const struct synaptics_dsx_hw_interface *hw_if; + const struct synaptics_dsx_board_data *bdata; + + hw_if = pdev->dev.platform_data; + if (!hw_if) { + dev_err(&pdev->dev, + "%s: No hardware interface found\n", + __func__); + return -EINVAL; + } + + bdata = hw_if->board_data; + if (!bdata) { + dev_err(&pdev->dev, + "%s: No board data found\n", + __func__); + return -EINVAL; + } + + rmi4_data = kzalloc(sizeof(*rmi4_data), GFP_KERNEL); + if (!rmi4_data) { + dev_err(&pdev->dev, + "%s: Failed to alloc mem for rmi4_data\n", + __func__); + return -ENOMEM; + } + + rmi4_data->pdev = pdev; + rmi4_data->current_page = MASK_8BIT; + rmi4_data->hw_if = hw_if; + rmi4_data->suspend = false; + rmi4_data->irq_enabled = false; + rmi4_data->fingers_on_2d = false; + + rmi4_data->reset_device = synaptics_rmi4_reset_device; + rmi4_data->irq_enable = synaptics_rmi4_irq_enable; + rmi4_data->sleep_enable = synaptics_rmi4_sleep_enable; + rmi4_data->report_touch = synaptics_rmi4_report_touch; + + mutex_init(&(rmi4_data->rmi4_reset_mutex)); + mutex_init(&(rmi4_data->rmi4_report_mutex)); + mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); + mutex_init(&(rmi4_data->rmi4_exp_init_mutex)); + mutex_init(&(rmi4_data->rmi4_irq_enable_mutex)); + mutex_init(&(rmi4_data->rmi4_esd_mutex)); + + + platform_set_drvdata(pdev, rmi4_data); + + vir_button_map = bdata->vir_button_map; + + retval = synaptics_rmi4_get_reg(rmi4_data, true); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to get regulators\n", + __func__); + goto err_get_reg; + } + + retval = synaptics_rmi4_enable_reg(rmi4_data, true); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable regulators\n", + __func__); + goto err_enable_reg; + } + + retval = synaptics_rmi4_set_gpio(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to set up GPIO's\n", + __func__); + goto err_set_gpio; + } + + if (hw_if->ui_hw_init) { + retval = hw_if->ui_hw_init(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to initialize hardware interface\n", + __func__); + goto err_ui_hw_init; + } + } + + retval = synaptics_rmi4_set_input_dev(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to set up input device\n", + __func__); + goto err_set_input_dev; + } + +#ifdef CONFIG_FB + rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb; + retval = fb_register_client(&rmi4_data->fb_notifier); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to register fb notifier client\n", + __func__); + } +#endif + +#ifdef USE_EARLYSUSPEND + rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend; + rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume; + register_early_suspend(&rmi4_data->early_suspend); +#endif + + if (!exp_data.initialized) { + mutex_init(&exp_data.mutex); + INIT_LIST_HEAD(&exp_data.list); + exp_data.initialized = true; + } + + rmi4_data->irq = gpio_to_irq(bdata->irq_gpio); + + retval = synaptics_rmi4_irq_enable(rmi4_data, true, false); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable attention interrupt\n", + __func__); + goto err_enable_irq; + } + + if (vir_button_map->nbuttons) { + rmi4_data->board_prop_dir = kobject_create_and_add( + "board_properties", NULL); + if (!rmi4_data->board_prop_dir) { + dev_err(&pdev->dev, + "%s: Failed to create board_properties directory\n", + __func__); + goto err_virtual_buttons; + } else { + retval = sysfs_create_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to create virtual key map file\n", + __func__); + goto err_virtual_buttons; + } + } + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to create sysfs attributes\n", + __func__); + goto err_sysfs; + } + } + +#ifdef USE_DATA_SERVER + memset(&interrupt_signal, 0, sizeof(interrupt_signal)); + interrupt_signal.si_signo = SIGIO; + interrupt_signal.si_code = SI_USER; +#endif + + rmi4_data->rb_workqueue = + create_singlethread_workqueue("dsx_rebuild_workqueue"); + INIT_DELAYED_WORK(&rmi4_data->rb_work, synaptics_rmi4_rebuild_work); + + exp_data.workqueue = create_singlethread_workqueue("dsx_exp_workqueue"); + INIT_DELAYED_WORK(&exp_data.work, synaptics_rmi4_exp_fn_work); + exp_data.rmi4_data = rmi4_data; + exp_data.queue_work = true; + queue_delayed_work(exp_data.workqueue, + &exp_data.work, + 0); + +#ifdef FB_READY_RESET + rmi4_data->reset_workqueue = + create_singlethread_workqueue("dsx_reset_workqueue"); + INIT_WORK(&rmi4_data->reset_work, synaptics_rmi4_reset_work); + queue_work(rmi4_data->reset_workqueue, &rmi4_data->reset_work); +#endif + +#if WAKEUP_GESTURE + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP); + + rmi4_data->input_dev->event = synaptics_gesture_switch; +#endif + + +#ifdef SYNAPTICS_ESD_CHECK + rmi4_data->esd_workqueue = create_singlethread_workqueue("dsx_esd_workqueue"); + INIT_DELAYED_WORK(&(rmi4_data->esd_work), synaptics_rmi4_esd_work); + queue_delayed_work(rmi4_data->esd_workqueue, &rmi4_data->esd_work, SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + return retval; + +err_sysfs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + +err_virtual_buttons: + if (rmi4_data->board_prop_dir) { + sysfs_remove_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + kobject_put(rmi4_data->board_prop_dir); + } + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + +err_enable_irq: +#ifdef CONFIG_FB + fb_unregister_client(&rmi4_data->fb_notifier); +#endif + +#ifdef USE_EARLYSUSPEND + unregister_early_suspend(&rmi4_data->early_suspend); +#endif + + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + +err_set_input_dev: + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + + if (bdata->reset_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0); + + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + +err_ui_hw_init: +err_set_gpio: + synaptics_rmi4_enable_reg(rmi4_data, false); + +err_enable_reg: + synaptics_rmi4_get_reg(rmi4_data, false); + +err_get_reg: + kfree(rmi4_data); + + return retval; +} + +static int synaptics_rmi4_remove(struct platform_device *pdev) +{ + unsigned char attr_count; + struct synaptics_rmi4_data *rmi4_data = platform_get_drvdata(pdev); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + +#ifdef FB_READY_RESET + cancel_work_sync(&rmi4_data->reset_work); + flush_workqueue(rmi4_data->reset_workqueue); + destroy_workqueue(rmi4_data->reset_workqueue); +#endif +printk("Enter %s\n", __func__); +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); + flush_workqueue(rmi4_data->esd_workqueue); + destroy_workqueue(rmi4_data->esd_workqueue); +#endif + + cancel_delayed_work_sync(&exp_data.work); + flush_workqueue(exp_data.workqueue); + destroy_workqueue(exp_data.workqueue); + + cancel_delayed_work_sync(&rmi4_data->rb_work); + flush_workqueue(rmi4_data->rb_workqueue); + destroy_workqueue(rmi4_data->rb_workqueue); + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + if (rmi4_data->board_prop_dir) { + sysfs_remove_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + kobject_put(rmi4_data->board_prop_dir); + } + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + +#ifdef CONFIG_FB + fb_unregister_client(&rmi4_data->fb_notifier); +#endif + +#ifdef USE_EARLYSUSPEND + unregister_early_suspend(&rmi4_data->early_suspend); +#endif + + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + + if (bdata->reset_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0); + + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + + synaptics_rmi4_enable_reg(rmi4_data, false); + synaptics_rmi4_get_reg(rmi4_data, false); + + kfree(rmi4_data); + + return 0; +} + +#ifdef CONFIG_FB +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self, + unsigned long event, void *data) +{ + int *transition; + struct fb_event *evdata = data; + struct synaptics_rmi4_data *rmi4_data = + container_of(self, struct synaptics_rmi4_data, + fb_notifier); + + if (evdata && evdata->data && rmi4_data) { + if (event == FB_EVENT_BLANK) { + transition = evdata->data; + if (*transition == FB_BLANK_POWERDOWN) { + synaptics_rmi4_suspend(&rmi4_data->pdev->dev); + rmi4_data->fb_ready = false; + } else if (*transition == FB_BLANK_UNBLANK) { + synaptics_rmi4_resume(&rmi4_data->pdev->dev); + rmi4_data->fb_ready = true; + } + } + } + + return 0; +} +#endif + +#ifdef USE_EARLYSUSPEND +static void synaptics_rmi4_early_suspend(struct early_suspend *h) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = + container_of(h, struct synaptics_rmi4_data, + early_suspend); + unsigned char device_ctrl; + + if (rmi4_data->stay_awake) + return; + + + if (rmi4_data->enable_wakeup_gesture) { + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + enable_irq_wake(rmi4_data->irq); + goto exit; + } + +#ifdef SYNA_TDDI + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + udelay(TDDI_LPWG_WAIT_US); +#endif + synaptics_rmi4_irq_enable(rmi4_data, false, false); + synaptics_rmi4_sleep_enable(rmi4_data, true); + synaptics_rmi4_free_fingers(rmi4_data); + +exit: + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->early_suspend != NULL) + exp_fhandler->exp_fn->early_suspend(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = true; + + return; +} + +static void synaptics_rmi4_late_resume(struct early_suspend *h) +{ +#ifdef FB_READY_RESET + int retval; +#endif + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = + container_of(h, struct synaptics_rmi4_data, + early_suspend); + + if (rmi4_data->stay_awake) + return; + + if (rmi4_data->enable_wakeup_gesture) { + disable_irq_wake(rmi4_data->irq); + goto exit; + } + + rmi4_data->current_page = MASK_8BIT; + + if (rmi4_data->suspend) { + synaptics_rmi4_sleep_enable(rmi4_data, false); + synaptics_rmi4_irq_enable(rmi4_data, true, false); + } + +exit: +#ifdef FB_READY_RESET + if (rmi4_data->suspend) { + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } + } +#endif + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->late_resume != NULL) + exp_fhandler->exp_fn->late_resume(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = false; + + return; +} +#endif + + + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static int synaptics_rmi4_pm_suspend(struct device *dev){ + dev_info(rmi4_data->pdev->dev.parent, "Enter %s\n", __func__); + if (lcm_ffbm_mode){ + synaptics_rmi4_suspend(dev); + } + else{ + dev_err(rmi4_data->pdev->dev.parent, "We are not in ffbm mode\n"); + } + + return 0; +} + +static int synaptics_rmi4_pm_resume(struct device *dev){ + dev_info(rmi4_data->pdev->dev.parent, "Enter %s\n", __func__); + if (lcm_ffbm_mode){ + synaptics_rmi4_resume(dev); + } + else{ + dev_err(rmi4_data->pdev->dev.parent, "We are not in ffbm mode\n"); + } + + return 0; +} +#endif + + +static int synaptics_rmi4_suspend(struct device *dev) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned char device_ctrl; + + if (rmi4_data->stay_awake) + return 0; + dev_info(rmi4_data->pdev->dev.parent, "Enter %s\n", __func__); +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + + if (rmi4_data->enable_wakeup_gesture) { + dev_err(rmi4_data->pdev->dev.parent, "enable_wakeup_gesture is on\n"); + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + enable_irq_wake(rmi4_data->irq); + goto exit; + } + + if (!rmi4_data->suspend) { +#ifdef SYNA_TDDI + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + udelay(TDDI_LPWG_WAIT_US); +#endif + synaptics_rmi4_irq_enable(rmi4_data, false, false); + synaptics_rmi4_sleep_enable(rmi4_data, true); + synaptics_rmi4_free_fingers(rmi4_data); + } + +exit: + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->suspend != NULL) + exp_fhandler->exp_fn->suspend(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = true; + + dev_info(rmi4_data->pdev->dev.parent, "Exit %s\n", __func__); + + return 0; +} + +static int synaptics_rmi4_resume(struct device *dev) +{ +#ifdef FB_READY_RESET + int retval; +#endif + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + dev_info(rmi4_data->pdev->dev.parent, "TP-time TP resume begin\n"); + if (rmi4_data->stay_awake) + return 0; + + if (rmi4_data->enable_wakeup_gesture) { + disable_irq_wake(rmi4_data->irq); + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + goto exit; + } + + rmi4_data->current_page = MASK_8BIT; + + synaptics_rmi4_sleep_enable(rmi4_data, false); + synaptics_rmi4_irq_enable(rmi4_data, true, false); + +#ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + + +exit: +#ifdef FB_READY_RESET + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } +#endif + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->resume != NULL) + exp_fhandler->exp_fn->resume(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = false; + + dev_info(rmi4_data->pdev->dev.parent, "TP-time TP resume finish\n"); + return 0; +} + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = { + + .suspend = synaptics_rmi4_pm_suspend, + .resume = synaptics_rmi4_pm_resume, + +}; +#endif + +static struct platform_driver synaptics_rmi4_driver = { + .driver = { + .name = PLATFORM_DRIVER_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &synaptics_rmi4_dev_pm_ops, +#endif + }, + .probe = synaptics_rmi4_probe, + .remove = synaptics_rmi4_remove, +}; + +static int __init synaptics_rmi4_init(void) +{ + int retval; + + retval = synaptics_rmi4_bus_init(); + if (retval) + return retval; + + return platform_driver_register(&synaptics_rmi4_driver); +} + +static void __exit synaptics_rmi4_exit(void) +{ + platform_driver_unregister(&synaptics_rmi4_driver); + + synaptics_rmi4_bus_exit(); + + return; +} + +module_init(synaptics_rmi4_init); +module_exit(synaptics_rmi4_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Touch Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_core.h b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_core.h new file mode 100755 index 0000000000000..c7cdc6577620e --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_core.h @@ -0,0 +1,539 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#ifndef _SYNAPTICS_DSX_RMI4_H_ +#define _SYNAPTICS_DSX_RMI4_H_ + +#define SYNAPTICS_DS4 (1 << 0) +#define SYNAPTICS_DS5 (1 << 1) +#define SYNAPTICS_DSX_DRIVER_PRODUCT (SYNAPTICS_DS4 | SYNAPTICS_DS5) +#define SYNAPTICS_DSX_DRIVER_VERSION 0x2070 + +#include +#ifdef CONFIG_FB +#include +#include +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)) +#define KERNEL_ABOVE_2_6_38 +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +#define KERNEL_ABOVE_3_6 +#endif + +#ifdef KERNEL_ABOVE_2_6_38 +#define sstrtoul(...) kstrtoul(__VA_ARGS__) +#else +#define sstrtoul(...) strict_strtoul(__VA_ARGS__) +#endif + + +#ifdef SYNAPTICS_ESD_CHECK +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +#endif + + +/* +#define F51_DISCRETE_FORCE +#ifdef F51_DISCRETE_FORCE +#define FORCE_LEVEL_ADDR 0x0419 +#define FORCE_LEVEL_MAX 255 +#define CAL_DATA_SIZE 144 +#endif +#define SYNA_TDDI +*/ +#define SYNA_TDDI +#define PDT_PROPS (0X00EF) +#define PDT_START (0x00E9) +#define PDT_END (0x00D0) +#define PDT_ENTRY_SIZE (0x0006) +#define PAGES_TO_SERVICE (10) +#define PAGE_SELECT_LEN (2) +#define ADDRESS_LEN (2) + +#define SYNAPTICS_RMI4_F01 (0x01) +#define SYNAPTICS_RMI4_F11 (0x11) +#define SYNAPTICS_RMI4_F12 (0x12) +#define SYNAPTICS_RMI4_F1A (0x1A) +#define SYNAPTICS_RMI4_F21 (0x21) +#define SYNAPTICS_RMI4_F34 (0x34) +#define SYNAPTICS_RMI4_F35 (0x35) +#define SYNAPTICS_RMI4_F38 (0x38) +#define SYNAPTICS_RMI4_F51 (0x51) +#define SYNAPTICS_RMI4_F54 (0x54) +#define SYNAPTICS_RMI4_F55 (0x55) +#define SYNAPTICS_RMI4_FDB (0xDB) + +#define PRODUCT_INFO_SIZE 2 +#define PRODUCT_ID_SIZE 10 +#define BUILD_ID_SIZE 3 + +#define F12_FINGERS_TO_SUPPORT 10 +#define F12_NO_OBJECT_STATUS 0x00 +#define F12_FINGER_STATUS 0x01 +#define F12_ACTIVE_STYLUS_STATUS 0x02 +#define F12_PALM_STATUS 0x03 +#define F12_HOVERING_FINGER_STATUS 0x05 +#define F12_GLOVED_FINGER_STATUS 0x06 +#define F12_NARROW_OBJECT_STATUS 0x07 +#define F12_HAND_EDGE_STATUS 0x08 +#define F12_COVER_STATUS 0x0A +#define F12_STYLUS_STATUS 0x0B +#define F12_ERASER_STATUS 0x0C +#define F12_SMALL_OBJECT_STATUS 0x0D + +#define F12_GESTURE_DETECTION_LEN 5 + +#define MAX_NUMBER_OF_BUTTONS 4 +#define MAX_INTR_REGISTERS 4 + +#define MASK_16BIT 0xFFFF +#define MASK_8BIT 0xFF +#define MASK_7BIT 0x7F +#define MASK_6BIT 0x3F +#define MASK_5BIT 0x1F +#define MASK_4BIT 0x0F +#define MASK_3BIT 0x07 +#define MASK_2BIT 0x03 +#define MASK_1BIT 0x01 + +enum exp_fn { + RMI_DEV = 0, + RMI_FW_UPDATER, + RMI_TEST_REPORTING, + RMI_PROXIMITY, + RMI_ACTIVE_PEN, + RMI_GESTURE, + RMI_VIDEO, + RMI_DEBUG, + RMI_LAST, +}; + +/* + * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT entry + * @query_base_addr: base address for query registers + * @cmd_base_addr: base address for command registers + * @ctrl_base_addr: base address for control registers + * @data_base_addr: base address for data registers + * @intr_src_count: number of interrupt sources + * @fn_version: version of function + * @fn_number: function number + */ +struct synaptics_rmi4_fn_desc { + union { + struct { + unsigned char query_base_addr; + unsigned char cmd_base_addr; + unsigned char ctrl_base_addr; + unsigned char data_base_addr; + unsigned char intr_src_count:3; + unsigned char reserved_1:2; + unsigned char fn_version:2; + unsigned char reserved_2:1; + unsigned char fn_number; + } __packed; + unsigned char data[6]; + }; +}; + +/* + * synaptics_rmi4_fn_full_addr - full 16-bit base addresses + * @query_base: 16-bit base address for query registers + * @cmd_base: 16-bit base address for command registers + * @ctrl_base: 16-bit base address for control registers + * @data_base: 16-bit base address for data registers + */ +struct synaptics_rmi4_fn_full_addr { + unsigned short query_base; + unsigned short cmd_base; + unsigned short ctrl_base; + unsigned short data_base; +}; + +/* + * struct synaptics_rmi4_f11_extra_data - extra data of F$11 + * @data38_offset: offset to F11_2D_DATA38 register + */ +struct synaptics_rmi4_f11_extra_data { + unsigned char data38_offset; +}; + +/* + * struct synaptics_rmi4_f12_extra_data - extra data of F$12 + * @data1_offset: offset to F12_2D_DATA01 register + * @data4_offset: offset to F12_2D_DATA04 register + * @data15_offset: offset to F12_2D_DATA15 register + * @data15_size: size of F12_2D_DATA15 register + * @data15_data: buffer for reading F12_2D_DATA15 register + * @data29_offset: offset to F12_2D_DATA29 register + * @data29_size: size of F12_2D_DATA29 register + * @data29_data: buffer for reading F12_2D_DATA29 register + * @ctrl20_offset: offset to F12_2D_CTRL20 register + */ +struct synaptics_rmi4_f12_extra_data { + unsigned char data1_offset; + unsigned char data4_offset; + unsigned char data15_offset; + unsigned char data15_size; + unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8]; + unsigned char data29_offset; + unsigned char data29_size; + unsigned char data29_data[F12_FINGERS_TO_SUPPORT * 2]; + unsigned char ctrl20_offset; +}; + +/* + * struct synaptics_rmi4_fn - RMI function handler + * @fn_number: function number + * @num_of_data_sources: number of data sources + * @num_of_data_points: maximum number of fingers supported + * @intr_reg_num: index to associated interrupt register + * @intr_mask: interrupt mask + * @full_addr: full 16-bit base addresses of function registers + * @link: linked list for function handlers + * @data_size: size of private data + * @data: pointer to private data + * @extra: pointer to extra data + */ +struct synaptics_rmi4_fn { + unsigned char fn_number; + unsigned char num_of_data_sources; + unsigned char num_of_data_points; + unsigned char intr_reg_num; + unsigned char intr_mask; + struct synaptics_rmi4_fn_full_addr full_addr; + struct list_head link; + int data_size; + void *data; + void *extra; +}; + +/* + * struct synaptics_rmi4_input_settings - current input settings + * @num_of_fingers: maximum number of fingers for 2D touch + * @valid_button_count: number of valid 0D buttons + * @max_touch_width: maximum touch width + * @sensor_max_x: maximum x coordinate for 2D touch + * @sensor_max_y: maximum y coordinate for 2D touch + * @force_min: minimum force value + * @force_max: maximum force value + * @stylus_enable: flag to indicate reporting of stylus data + * @eraser_enable: flag to indicate reporting of eraser data + */ +struct synaptics_rmi4_input_settings { + unsigned char num_of_fingers; + unsigned char valid_button_count; + unsigned char max_touch_width; + int sensor_max_x; + int sensor_max_y; + int force_min; + int force_max; + bool stylus_enable; + bool eraser_enable; +}; + +/* + * struct synaptics_rmi4_device_info - device information + * @version_major: RMI protocol major version number + * @version_minor: RMI protocol minor version number + * @manufacturer_id: manufacturer ID + * @product_props: product properties + * @product_info: product information + * @product_id_string: product ID + * @build_id: firmware build ID + * @support_fn_list: linked list for function handlers + */ +struct synaptics_rmi4_device_info { + unsigned int version_major; + unsigned int version_minor; + unsigned char manufacturer_id; + unsigned char product_props; + unsigned char product_info[PRODUCT_INFO_SIZE]; + unsigned char product_id_string[PRODUCT_ID_SIZE + 1]; + unsigned char build_id[BUILD_ID_SIZE]; + struct list_head support_fn_list; +}; + +/* + * struct synaptics_rmi4_data - RMI4 device instance data + * @pdev: pointer to platform device + * @input_dev: pointer to associated input device + * @stylus_dev: pointer to associated stylus device + * @hw_if: pointer to hardware interface data + * @rmi4_mod_info: device information + * @board_prop_dir: /sys/board_properties directory for virtual key map file + * @pwr_reg: pointer to regulator for power control + * @bus_reg: pointer to regulator for bus pullup control + * @rmi4_reset_mutex: mutex for software reset + * @rmi4_report_mutex: mutex for input event reporting + * @rmi4_io_ctrl_mutex: mutex for communication interface I/O + * @rmi4_exp_init_mutex: mutex for expansion function module initialization + * @rmi4_irq_enable_mutex: mutex for enabling/disabling interrupt + * @rb_work: work for rebuilding input device + * @rb_workqueue: workqueue for rebuilding input device + * @fb_notifier: framebuffer notifier client + * @reset_work: work for issuing reset after display framebuffer ready + * @reset_workqueue: workqueue for issuing reset after display framebuffer ready + * @early_suspend: early suspend power management + * @current_page: current RMI page for register access + * @button_0d_enabled: switch for enabling 0d button support + * @num_of_tx: number of Tx channels for 2D touch + * @num_of_rx: number of Rx channels for 2D touch + * @num_of_fingers: maximum number of fingers for 2D touch + * @max_touch_width: maximum touch width + * @valid_button_count: number of valid 0D buttons + * @report_enable: input data to report for F$12 + * @no_sleep_setting: default setting of NoSleep in F01_RMI_CTRL00 register + * @gesture_detection: detected gesture type and properties + * @intr_mask: interrupt enable mask + * @button_txrx_mapping: Tx Rx mapping of 0D buttons + * @num_of_intr_regs: number of interrupt registers + * @f01_query_base_addr: query base address for f$01 + * @f01_cmd_base_addr: command base address for f$01 + * @f01_ctrl_base_addr: control base address for f$01 + * @f01_data_base_addr: data base address for f$01 + * @f51_query_base_addr: query base address for f$51 + * @firmware_id: firmware build ID + * @irq: attention interrupt + * @sensor_max_x: maximum x coordinate for 2D touch + * @sensor_max_y: maximum y coordinate for 2D touch + * @force_min: minimum force value + * @force_max: maximum force value + * @flash_prog_mode: flag to indicate flash programming mode status + * @irq_enabled: flag to indicate attention interrupt enable status + * @fingers_on_2d: flag to indicate presence of fingers in 2D area + * @suspend: flag to indicate whether in suspend state + * @sensor_sleep: flag to indicate sleep state of sensor + * @stay_awake: flag to indicate whether to stay awake during suspend + * @fb_ready: flag to indicate whether display framebuffer in ready state + * @f11_wakeup_gesture: flag to indicate support for wakeup gestures in F$11 + * @f12_wakeup_gesture: flag to indicate support for wakeup gestures in F$12 + * @enable_wakeup_gesture: flag to indicate usage of wakeup gestures + * @wedge_sensor: flag to indicate use of wedge sensor + * @report_pressure: flag to indicate reporting of pressure data + * @stylus_enable: flag to indicate reporting of stylus data + * @eraser_enable: flag to indicate reporting of eraser data + * @external_afe_buttons: flag to indicate presence of external AFE buttons + * @reset_device: pointer to device reset function + * @irq_enable: pointer to interrupt enable function + * @sleep_enable: pointer to sleep enable function + * @report_touch: pointer to touch reporting function + */ +struct synaptics_rmi4_data { + struct platform_device *pdev; + struct input_dev *input_dev; + struct input_dev *stylus_dev; + const struct synaptics_dsx_hw_interface *hw_if; + struct synaptics_rmi4_device_info rmi4_mod_info; + struct synaptics_rmi4_input_settings input_settings; + struct kobject *board_prop_dir; + struct regulator *pwr_reg; + struct regulator *bus_reg; + struct mutex rmi4_reset_mutex; + struct mutex rmi4_report_mutex; + struct mutex rmi4_io_ctrl_mutex; + struct mutex rmi4_exp_init_mutex; + struct mutex rmi4_irq_enable_mutex; + struct mutex rmi4_esd_mutex; + struct delayed_work rb_work; + struct workqueue_struct *rb_workqueue; +#ifdef CONFIG_FB + struct notifier_block fb_notifier; + struct work_struct reset_work; + struct workqueue_struct *reset_workqueue; +#endif +#ifdef SYNAPTICS_ESD_CHECK + struct delayed_work esd_work; + struct workqueue_struct *esd_workqueue; +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif + unsigned char current_page; + unsigned char button_0d_enabled; + unsigned char num_of_tx; + unsigned char num_of_rx; + unsigned char num_of_fingers; + unsigned char max_touch_width; + unsigned char valid_button_count; + unsigned char report_enable; + unsigned char no_sleep_setting; + unsigned char gesture_detection[F12_GESTURE_DETECTION_LEN]; + unsigned char intr_mask[MAX_INTR_REGISTERS]; + unsigned char *button_txrx_mapping; + unsigned short num_of_intr_regs; + unsigned short f01_query_base_addr; + unsigned short f01_cmd_base_addr; + unsigned short f01_ctrl_base_addr; + unsigned short f01_data_base_addr; +#ifdef F51_DISCRETE_FORCE + unsigned short f51_query_base_addr; +#endif + unsigned int firmware_id; + int irq; + int sensor_max_x; + int sensor_max_y; + int force_min; + int force_max; + bool flash_prog_mode; + bool irq_enabled; + bool fingers_on_2d; + bool suspend; + bool sensor_sleep; + bool stay_awake; + bool fb_ready; + bool f11_wakeup_gesture; + bool f12_wakeup_gesture; + bool enable_wakeup_gesture; + bool wedge_sensor; + bool report_pressure; + bool stylus_enable; + bool eraser_enable; + bool external_afe_buttons; + int (*reset_device)(struct synaptics_rmi4_data *rmi4_data, + bool rebuild); + int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable, + bool attn_only); + void (*sleep_enable)(struct synaptics_rmi4_data *rmi4_data, + bool enable); + void (*report_touch)(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler); +}; + +struct synaptics_dsx_bus_access { + unsigned char type; + int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, + unsigned char *data, unsigned int length); + int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, + unsigned char *data, unsigned int length); +}; + +struct synaptics_dsx_hw_interface { + struct synaptics_dsx_board_data *board_data; + const struct synaptics_dsx_bus_access *bus_access; + int (*bl_hw_init)(struct synaptics_rmi4_data *rmi4_data); + int (*ui_hw_init)(struct synaptics_rmi4_data *rmi4_data); +}; + +struct synaptics_rmi4_exp_fn { + enum exp_fn fn_type; + int (*init)(struct synaptics_rmi4_data *rmi4_data); + void (*remove)(struct synaptics_rmi4_data *rmi4_data); + void (*reset)(struct synaptics_rmi4_data *rmi4_data); + void (*reinit)(struct synaptics_rmi4_data *rmi4_data); + void (*early_suspend)(struct synaptics_rmi4_data *rmi4_data); + void (*suspend)(struct synaptics_rmi4_data *rmi4_data); + void (*resume)(struct synaptics_rmi4_data *rmi4_data); + void (*late_resume)(struct synaptics_rmi4_data *rmi4_data); + void (*attn)(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask); +}; + +int synaptics_rmi4_bus_init(void); + +void synaptics_rmi4_bus_exit(void); + +void synaptics_rmi4_new_function(struct synaptics_rmi4_exp_fn *exp_fn_module, + bool insert); + +int synaptics_fw_updater(const unsigned char *fw_data); + +static inline int synaptics_rmi4_reg_read( + struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, + unsigned char *data, + unsigned int len) +{ + return rmi4_data->hw_if->bus_access->read(rmi4_data, addr, data, len); +} + +static inline int synaptics_rmi4_reg_write( + struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, + unsigned char *data, + unsigned int len) +{ + return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len); +} + +static inline ssize_t synaptics_rmi4_show_error(struct device *dev, + struct device_attribute *attr, char *buf) +{ + dev_warn(dev, "%s Attempted to read from write-only attribute %s\n", + __func__, attr->attr.name); + return -EPERM; +} + +static inline ssize_t synaptics_rmi4_store_error(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + dev_warn(dev, "%s Attempted to write to read-only attribute %s\n", + __func__, attr->attr.name); + return -EPERM; +} + +static inline int secure_memcpy(unsigned char *dest, unsigned int dest_size, + const unsigned char *src, unsigned int src_size, + unsigned int count) +{ + if (dest == NULL || src == NULL) + return -EINVAL; + + if (count > dest_size || count > src_size) + return -EINVAL; + + memcpy((void *)dest, (const void *)src, count); + + return 0; +} + +static inline void batohs(unsigned short *dest, unsigned char *src) +{ + *dest = src[1] * 0x100 + src[0]; +} + +static inline void hstoba(unsigned char *dest, unsigned short src) +{ + dest[0] = src % 0x100; + dest[1] = src / 0x100; +} + +extern int get_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng); + +#endif diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_fw_update.c new file mode 100644 index 0000000000000..d41ab9ab0e319 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_fw_update.c @@ -0,0 +1,6042 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" +#include +#include + + +#define FW_IHEX_NAME "synaptics/startup_fw_update.bin" +#define FW_IMAGE_NAME "synaptics/startup_fw_update.img" + +#define DO_STARTUP_FW_UPDATE + +#define SYNAPTICS_LOCK_DOWN_INFO + +#ifdef DO_STARTUP_FW_UPDATE +#ifdef CONFIG_FB +#define WAIT_FOR_FB_READY +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +#endif +#endif + + +#define MAX_WRITE_SIZE 4096 + + +#define ENABLE_SYS_REFLASH true +#define FORCE_UPDATE false +#define DO_LOCKDOWN false + +#define MAX_IMAGE_NAME_LEN 256 +#define MAX_FIRMWARE_ID_LEN 10 + +#define IMAGE_HEADER_VERSION_05 0x05 +#define IMAGE_HEADER_VERSION_06 0x06 +#define IMAGE_HEADER_VERSION_10 0x10 + +#define IMAGE_AREA_OFFSET 0x100 +#define LOCKDOWN_SIZE 0x50 + +#define MAX_UTILITY_PARAMS 20 + +#define V5V6_BOOTLOADER_ID_OFFSET 0 +#define V5V6_CONFIG_ID_SIZE 4 + +#define V5_PROPERTIES_OFFSET 2 +#define V5_BLOCK_SIZE_OFFSET 3 +#define V5_BLOCK_COUNT_OFFSET 5 +#define V5_BLOCK_NUMBER_OFFSET 0 +#define V5_BLOCK_DATA_OFFSET 2 + +#define V6_PROPERTIES_OFFSET 1 +#define V6_BLOCK_SIZE_OFFSET 2 +#define V6_BLOCK_COUNT_OFFSET 3 +#define V6_PROPERTIES_2_OFFSET 4 +#define V6_GUEST_CODE_BLOCK_COUNT_OFFSET 5 +#define V6_BLOCK_NUMBER_OFFSET 0 +#define V6_BLOCK_DATA_OFFSET 1 +#define V6_FLASH_COMMAND_OFFSET 2 +#define V6_FLASH_STATUS_OFFSET 3 + +#define V7_CONFIG_ID_SIZE 32 + +#define V7_FLASH_STATUS_OFFSET 0 +#define V7_PARTITION_ID_OFFSET 1 +#define V7_BLOCK_NUMBER_OFFSET 2 +#define V7_TRANSFER_LENGTH_OFFSET 3 +#define V7_COMMAND_OFFSET 4 +#define V7_PAYLOAD_OFFSET 5 + +#define V7_PARTITION_SUPPORT_BYTES 4 + +#define F35_ERROR_CODE_OFFSET 0 +#define F35_FLASH_STATUS_OFFSET 5 +#define F35_CHUNK_NUM_LSB_OFFSET 0 +#define F35_CHUNK_NUM_MSB_OFFSET 1 +#define F35_CHUNK_DATA_OFFSET 2 +#define F35_CHUNK_COMMAND_OFFSET 18 + +#define F35_CHUNK_SIZE 16 +#define F35_ERASE_ALL_WAIT_MS 5000 +#define F35_RESET_WAIT_MS 250 + +#define SLEEP_MODE_NORMAL (0x00) +#define SLEEP_MODE_SENSOR_SLEEP (0x01) +#define SLEEP_MODE_RESERVED0 (0x02) +#define SLEEP_MODE_RESERVED1 (0x03) + +#define ENABLE_WAIT_MS (1 * 1000) +#define WRITE_WAIT_MS (3 * 1000) +#define ERASE_WAIT_MS (5 * 1000) + +#define MIN_SLEEP_TIME_US 50 +#define MAX_SLEEP_TIME_US 100 + +#define INT_DISABLE_WAIT_MS 20 +#define ENTER_FLASH_PROG_WAIT_MS 20 +#define READ_CONFIG_WAIT_MS 20 + +static int fwu_do_reflash(void); + +static int fwu_recovery_check_status(void); + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_read_panel_color_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#endif + +enum f34_version { + F34_V0 = 0, + F34_V1, + F34_V2, +}; + +enum bl_version { + BL_V5 = 5, + BL_V6 = 6, + BL_V7 = 7, + BL_V8 = 8, +}; + +enum flash_area { + NONE = 0, + UI_FIRMWARE, + UI_CONFIG, +}; + +enum update_mode { + NORMAL = 1, + FORCE = 2, + LOCKDOWN = 8, +}; + +enum config_area { + UI_CONFIG_AREA = 0, + PM_CONFIG_AREA, + BL_CONFIG_AREA, + DP_CONFIG_AREA, + FLASH_CONFIG_AREA, +#ifdef SYNA_TDDI + TDDI_FORCE_CONFIG_AREA, + TDDI_LCM_DATA_AREA, + TDDI_OEM_DATA_AREA, +#endif + UPP_AREA, +}; + +enum v7_status { + SUCCESS = 0x00, + DEVICE_NOT_IN_BOOTLOADER_MODE, + INVALID_PARTITION, + INVALID_COMMAND, + INVALID_BLOCK_OFFSET, + INVALID_TRANSFER, + NOT_ERASED, + FLASH_PROGRAMMING_KEY_INCORRECT, + BAD_PARTITION_TABLE, + CHECKSUM_FAILED, + FLASH_HARDWARE_FAILURE = 0x1f, +}; + +enum v7_partition_id { + BOOTLOADER_PARTITION = 0x01, + DEVICE_CONFIG_PARTITION, + FLASH_CONFIG_PARTITION, + MANUFACTURING_BLOCK_PARTITION, + GUEST_SERIALIZATION_PARTITION, + GLOBAL_PARAMETERS_PARTITION, + CORE_CODE_PARTITION, + CORE_CONFIG_PARTITION, + GUEST_CODE_PARTITION, + DISPLAY_CONFIG_PARTITION, + EXTERNAL_TOUCH_AFE_CONFIG_PARTITION, + UTILITY_PARAMETER_PARTITION, +}; + +enum v7_flash_command { + CMD_V7_IDLE = 0x00, + CMD_V7_ENTER_BL, + CMD_V7_READ, + CMD_V7_WRITE, + CMD_V7_ERASE, + CMD_V7_ERASE_AP, + CMD_V7_SENSOR_ID, +}; + +enum v5v6_flash_command { + CMD_V5V6_IDLE = 0x0, + CMD_V5V6_WRITE_FW = 0x2, + CMD_V5V6_ERASE_ALL = 0x3, + CMD_V5V6_WRITE_LOCKDOWN = 0x4, + CMD_V5V6_READ_CONFIG = 0x5, + CMD_V5V6_WRITE_CONFIG = 0x6, + CMD_V5V6_ERASE_UI_CONFIG = 0x7, + CMD_V5V6_ERASE_BL_CONFIG = 0x9, + CMD_V5V6_ERASE_DISP_CONFIG = 0xa, + CMD_V5V6_ERASE_GUEST_CODE = 0xb, + CMD_V5V6_WRITE_GUEST_CODE = 0xc, + CMD_V5V6_ERASE_CHIP = 0x0d, + CMD_V5V6_ENABLE_FLASH_PROG = 0xf, +#ifdef SYNA_TDDI + CMD_V5V6_ERASE_FORCE_CONFIG = 0x11, + CMD_V5V6_READ_FORCE_CONFIG = 0x12, + CMD_V5V6_WRITE_FORCE_CONFIG = 0x13, + CMD_V5V6_ERASE_LOCKDOWN_DATA = 0x1a, + CMD_V5V6_READ_LOCKDOWN_DATA = 0x1b, + CMD_V5V6_WRITE_LOCKDOWN_DATA = 0x1c, + CMD_V5V6_ERASE_LCM_DATA = 0x1d, + CMD_V5V6_ERASE_OEM_DATA = 0x1e, +#endif +}; + +enum flash_command { + CMD_IDLE = 0, + CMD_WRITE_FW, + CMD_WRITE_CONFIG, + CMD_WRITE_LOCKDOWN, + CMD_WRITE_GUEST_CODE, + CMD_WRITE_BOOTLOADER, + CMD_WRITE_UTILITY_PARAM, + CMD_READ_CONFIG, + CMD_ERASE_ALL, + CMD_ERASE_UI_FIRMWARE, + CMD_ERASE_UI_CONFIG, + CMD_ERASE_BL_CONFIG, + CMD_ERASE_DISP_CONFIG, + CMD_ERASE_FLASH_CONFIG, + CMD_ERASE_GUEST_CODE, + CMD_ERASE_BOOTLOADER, + CMD_ERASE_UTILITY_PARAMETER, + CMD_ENABLE_FLASH_PROG, +#ifdef SYNA_TDDI + CMD_ERASE_CHIP, + CMD_ERASE_FORCE_CONFIG, + CMD_READ_FORCE_CONFIG, + CMD_WRITE_FORCE_CONFIG, + CMD_ERASE_LOCKDOWN_DATA, + CMD_READ_LOCKDOWN_DATA, + CMD_WRITE_LOCKDOWN_DATA, + CMD_ERASE_LCM_DATA, + CMD_READ_LCM_DATA, + CMD_WRITE_LCM_DATA, + CMD_ERASE_OEM_DATA, + CMD_READ_OEM_DATA, + CMD_WRITE_OEM_DATA, +#endif +}; + +enum f35_flash_command { + CMD_F35_IDLE = 0x0, + CMD_F35_RESERVED = 0x1, + CMD_F35_WRITE_CHUNK = 0x2, + CMD_F35_ERASE_ALL = 0x3, + CMD_F35_RESET = 0x10, +}; + +enum container_id { + TOP_LEVEL_CONTAINER = 0, + UI_CONTAINER, + UI_CONFIG_CONTAINER, + BL_CONTAINER, + BL_IMAGE_CONTAINER, + BL_CONFIG_CONTAINER, + BL_LOCKDOWN_INFO_CONTAINER, + PERMANENT_CONFIG_CONTAINER, + GUEST_CODE_CONTAINER, + BL_PROTOCOL_DESCRIPTOR_CONTAINER, + UI_PROTOCOL_DESCRIPTOR_CONTAINER, + RMI_SELF_DISCOVERY_CONTAINER, + RMI_PAGE_CONTENT_CONTAINER, + GENERAL_INFORMATION_CONTAINER, + DEVICE_CONFIG_CONTAINER, + FLASH_CONFIG_CONTAINER, + GUEST_SERIALIZATION_CONTAINER, + GLOBAL_PARAMETERS_CONTAINER, + CORE_CODE_CONTAINER, + CORE_CONFIG_CONTAINER, + DISPLAY_CONFIG_CONTAINER, + EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER, + UTILITY_CONTAINER, + UTILITY_PARAMETER_CONTAINER, +}; + +enum utility_parameter_id { + UNUSED = 0, + FORCE_PARAMETER, + ANTI_BENDING_PARAMETER, +}; + +struct pdt_properties { + union { + struct { + unsigned char reserved_1:6; + unsigned char has_bsr:1; + unsigned char reserved_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct partition_table { + unsigned char partition_id:5; + unsigned char byte_0_reserved:3; + unsigned char byte_1_reserved; + unsigned char partition_length_7_0; + unsigned char partition_length_15_8; + unsigned char start_physical_address_7_0; + unsigned char start_physical_address_15_8; + unsigned char partition_properties_7_0; + unsigned char partition_properties_15_8; +} __packed; + +struct f01_device_control { + union { + struct { + unsigned char sleep_mode:2; + unsigned char nosleep:1; + unsigned char reserved:2; + unsigned char charger_connected:1; + unsigned char report_rate:1; + unsigned char configured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_0 { + union { + struct { + unsigned char subpacket_1_size:3; + unsigned char has_config_id:1; + unsigned char f34_query0_b4:1; + unsigned char has_thqa:1; + unsigned char f34_query0_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_1_7 { + union { + struct { + /* query 1 */ + unsigned char bl_minor_revision; + unsigned char bl_major_revision; + + /* query 2 */ + unsigned char bl_fw_id_7_0; + unsigned char bl_fw_id_15_8; + unsigned char bl_fw_id_23_16; + unsigned char bl_fw_id_31_24; + + /* query 3 */ + unsigned char minimum_write_size; + unsigned char block_size_7_0; + unsigned char block_size_15_8; + unsigned char flash_page_size_7_0; + unsigned char flash_page_size_15_8; + + /* query 4 */ + unsigned char adjustable_partition_area_size_7_0; + unsigned char adjustable_partition_area_size_15_8; + + /* query 5 */ + unsigned char flash_config_length_7_0; + unsigned char flash_config_length_15_8; + + /* query 6 */ + unsigned char payload_length_7_0; + unsigned char payload_length_15_8; + + /* query 7 */ + unsigned char f34_query7_b0:1; + unsigned char has_bootloader:1; + unsigned char has_device_config:1; + unsigned char has_flash_config:1; + unsigned char has_manufacturing_block:1; + unsigned char has_guest_serialization:1; + unsigned char has_global_parameters:1; + unsigned char has_core_code:1; + unsigned char has_core_config:1; + unsigned char has_guest_code:1; + unsigned char has_display_config:1; + unsigned char f34_query7_b11__15:5; + unsigned char f34_query7_b16__23; + unsigned char f34_query7_b24__31; + } __packed; + unsigned char data[21]; + }; +}; + +struct f34_v7_data0 { + union { + struct { + unsigned char operation_status:5; + unsigned char device_cfg_status:2; + unsigned char bl_mode:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_data_1_5 { + union { + struct { + unsigned char partition_id:5; + unsigned char f34_data1_b5__7:3; + unsigned char block_offset_7_0; + unsigned char block_offset_15_8; + unsigned char transfer_length_7_0; + unsigned char transfer_length_15_8; + unsigned char command; + unsigned char payload_0; + unsigned char payload_1; + } __packed; + unsigned char data[8]; + }; +}; + +struct f34_v5v6_flash_properties { + union { + struct { + unsigned char reg_map:1; + unsigned char unlocked:1; + unsigned char has_config_id:1; + unsigned char has_pm_config:1; + unsigned char has_bl_config:1; + unsigned char has_disp_config:1; + unsigned char has_ctrl1:1; + unsigned char has_query4:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v5v6_flash_properties_2 { + union { + struct { + unsigned char has_guest_code:1; + unsigned char f34_query4_b1:1; + unsigned char has_gesture_config:1; + unsigned char has_force_config:1; + unsigned char has_lockdown_data:1; + unsigned char has_lcm_data:1; + unsigned char has_oem_data:1; + unsigned char f34_query4_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct register_offset { + unsigned char properties; + unsigned char properties_2; + unsigned char block_size; + unsigned char block_count; + unsigned char gc_block_count; + unsigned char flash_status; + unsigned char partition_id; + unsigned char block_number; + unsigned char transfer_length; + unsigned char flash_cmd; + unsigned char payload; +}; + +struct block_count { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +#ifdef SYNA_TDDI + unsigned short tddi_force_config; + unsigned short tddi_lockdown_data; + unsigned short tddi_lcm_data; + unsigned short tddi_oem_data; +#endif + unsigned short total_count; +}; + +struct physical_address { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +}; + +struct container_descriptor { + unsigned char content_checksum[4]; + unsigned char container_id[2]; + unsigned char minor_version; + unsigned char major_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char container_option_flags[4]; + unsigned char content_options_length[4]; + unsigned char content_options_address[4]; + unsigned char content_length[4]; + unsigned char content_address[4]; +}; + +struct image_header_10 { + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char minor_header_version; + unsigned char major_header_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char top_level_container_start_addr[4]; +}; + +struct image_header_05_06 { + /* 0x00 - 0x0f */ + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char options_firmware_id:1; + unsigned char options_bootloader:1; + unsigned char options_guest_code:1; + unsigned char options_tddi:1; + unsigned char options_reserved:4; + unsigned char header_version; + unsigned char firmware_size[4]; + unsigned char config_size[4]; + /* 0x10 - 0x1f */ + unsigned char product_id[PRODUCT_ID_SIZE]; + unsigned char package_id[2]; + unsigned char package_id_revision[2]; + unsigned char product_info[PRODUCT_INFO_SIZE]; + /* 0x20 - 0x2f */ + unsigned char bootloader_addr[4]; + unsigned char bootloader_size[4]; + unsigned char ui_addr[4]; + unsigned char ui_size[4]; + /* 0x30 - 0x3f */ + unsigned char ds_id[16]; + /* 0x40 - 0x4f */ + union { + struct { + unsigned char cstmr_product_id[PRODUCT_ID_SIZE]; + unsigned char reserved_4a_4f[6]; + }; + struct { + unsigned char dsp_cfg_addr[4]; + unsigned char dsp_cfg_size[4]; + unsigned char reserved_48_4f[8]; + }; + }; + /* 0x50 - 0x53 */ + unsigned char firmware_id[4]; +}; + +struct block_data { + unsigned int size; + const unsigned char *data; +}; + +struct image_metadata { + bool contains_firmware_id; + bool contains_bootloader; + bool contains_guest_code; + bool contains_disp_config; + bool contains_perm_config; + bool contains_flash_config; + bool contains_utility_param; + unsigned int firmware_id; + unsigned int checksum; + unsigned int bootloader_size; + unsigned int disp_config_offset; + unsigned char bl_version; + unsigned char product_id[PRODUCT_ID_SIZE + 1]; + unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1]; + unsigned char utility_param_id[MAX_UTILITY_PARAMS]; + struct block_data bootloader; + struct block_data utility; + struct block_data ui_firmware; + struct block_data ui_config; + struct block_data dp_config; + struct block_data pm_config; + struct block_data fl_config; + struct block_data bl_image; + struct block_data bl_config; + struct block_data utility_param[MAX_UTILITY_PARAMS]; + struct block_data lockdown; + struct block_data guest_code; + struct block_count blkcount; + struct physical_address phyaddr; +}; + +struct synaptics_rmi4_fwu_handle { + enum bl_version bl_version; + bool initialized; + bool in_bl_mode; + bool in_ub_mode; + bool bl_mode_device; + bool force_update; + bool do_lockdown; + bool has_guest_code; +#ifdef SYNA_TDDI + bool has_force_config; + bool has_lockdown_data; + bool has_lcm_data; + bool has_oem_data; +#endif + bool has_utility_param; + bool new_partition_table; + bool incompatible_partition_tables; + bool write_bootloader; + unsigned int data_pos; + unsigned char *ext_data_source; + unsigned char *read_config_buf; + unsigned char intr_mask; + unsigned char command; + unsigned char bootloader_id[2]; + unsigned char config_id[32]; + unsigned char flash_status; + unsigned char partitions; +#ifdef F51_DISCRETE_FORCE + unsigned char *cal_data; + unsigned short cal_data_off; + unsigned short cal_data_size; + unsigned short cal_data_buf_size; + unsigned short cal_packet_data_size; +#endif + unsigned short block_size; + unsigned short config_size; + unsigned short config_area; + unsigned short config_block_count; + unsigned short flash_config_length; + unsigned short payload_length; + unsigned short partition_table_bytes; + unsigned short read_config_buf_size; + const unsigned char *config_data; + const unsigned char *image; + unsigned char *image_name; + unsigned int image_size; + struct image_metadata img; + struct register_offset off; + struct block_count blkcount; + struct physical_address phyaddr; + struct f34_v5v6_flash_properties flash_properties; + struct synaptics_rmi4_fn_desc f34_fd; + struct synaptics_rmi4_fn_desc f35_fd; + struct synaptics_rmi4_data *rmi4_data; + struct workqueue_struct *fwu_workqueue; + struct work_struct fwu_work; +}; + +static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = fwu_sysfs_show_image, + .write = fwu_sysfs_store_image, +}; + +static struct device_attribute attrs[] = { + __ATTR(dorecovery, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_recovery_store), + __ATTR(doreflash, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_reflash_store), + __ATTR(writeconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_config_store), + __ATTR(readconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_read_config_store), + __ATTR(configarea, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_config_area_store), + __ATTR(imagename, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_name_store), + __ATTR(imagesize, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_size_store), + __ATTR(blocksize, S_IRUGO, + fwu_sysfs_block_size_show, + synaptics_rmi4_store_error), + __ATTR(fwblockcount, S_IRUGO, + fwu_sysfs_firmware_block_count_show, + synaptics_rmi4_store_error), + __ATTR(configblockcount, S_IRUGO, + fwu_sysfs_configuration_block_count_show, + synaptics_rmi4_store_error), + __ATTR(dispconfigblockcount, S_IRUGO, + fwu_sysfs_disp_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(permconfigblockcount, S_IRUGO, + fwu_sysfs_perm_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(blconfigblockcount, S_IRUGO, + fwu_sysfs_bl_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(uppblockcount, S_IRUGO, + fwu_sysfs_utility_parameter_block_count_show, + synaptics_rmi4_store_error), + __ATTR(guestcodeblockcount, S_IRUGO, + fwu_sysfs_guest_code_block_count_show, + synaptics_rmi4_store_error), + __ATTR(writeguestcode, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + __ATTR(guestserialization, S_IRUGO, + fwu_sysfs_read_guest_serialization_show, + synaptics_rmi4_store_error), + __ATTR(panelcolor, S_IRUGO, + fwu_sysfs_read_panel_color_show, + NULL), + +#ifdef SYNA_TDDI + __ATTR(lockdowncode, (S_IWUSR | S_IWGRP | S_IRUGO), + fwu_sysfs_read_lockdown_code_show, + fwu_sysfs_write_lockdown_code_store), +#endif +}; + +static struct synaptics_rmi4_fwu_handle *fwu; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +DEFINE_MUTEX(fwu_sysfs_mutex); +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int fwu_do_read_customer_serialization_data(void); + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + fwu_do_read_customer_serialization_data(); + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; + + +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = +{ + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; +#endif +DECLARE_COMPLETION(fwu_remove_complete); + + + +static void calculate_checksum(unsigned short *data, unsigned long len, + unsigned long *result) +{ + unsigned long temp; + unsigned long sum1 = 0xffff; + unsigned long sum2 = 0xffff; + + *result = 0xffffffff; + + while (len--) { + temp = *data; + sum1 += temp; + sum2 += sum1; + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + data++; + } + + *result = sum2 << 16 | sum1; + + return; +} + +static void convert_to_little_endian(unsigned char *dest, unsigned long src) +{ + dest[0] = (unsigned char)(src & 0xff); + dest[1] = (unsigned char)((src >> 8) & 0xff); + dest[2] = (unsigned char)((src >> 16) & 0xff); + dest[3] = (unsigned char)((src >> 24) & 0xff); + + return; +} + +static unsigned int le_to_uint(const unsigned char *ptr) +{ + return (unsigned int)ptr[0] + + (unsigned int)ptr[1] * 0x100 + + (unsigned int)ptr[2] * 0x10000 + + (unsigned int)ptr[3] * 0x1000000; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_f51_force_data_init(void) +{ + int retval; + unsigned char query_count; + unsigned char packet_info; + unsigned char offset[2]; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 7, + offset, + sizeof(offset)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read force data offset\n", + __func__); + return retval; + } + + fwu->cal_data_off = offset[0] | offset[1] << 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr, + &query_count, + sizeof(query_count)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read number of F51 query registers\n", + __func__); + return retval; + } + + if (query_count >= 10) { + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 9, + &packet_info, + sizeof(packet_info)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F51 packet register info\n", + __func__); + return retval; + } + + if (packet_info & MASK_1BIT) { + fwu->cal_packet_data_size = packet_info >> 1; + fwu->cal_packet_data_size *= 2; + } else { + fwu->cal_packet_data_size = 0; + } + } else { + fwu->cal_packet_data_size = 0; + } + + fwu->cal_data_size = CAL_DATA_SIZE + fwu->cal_packet_data_size; + if (fwu->cal_data_size > fwu->cal_data_buf_size) { + kfree(fwu->cal_data); + fwu->cal_data_buf_size = fwu->cal_data_size; + fwu->cal_data = kmalloc(fwu->cal_data_buf_size, GFP_KERNEL); + if (!fwu->cal_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->cal_data\n", + __func__); + fwu->cal_data_buf_size = 0; + return -ENOMEM; + } + } + + return 0; +} +#endif + +static int fwu_allocate_read_config_buf(unsigned int count) +{ + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (count > fwu->read_config_buf_size) { + kfree(fwu->read_config_buf); + fwu->read_config_buf = kzalloc(count, GFP_KERNEL); + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + return -ENOMEM; + } + fwu->read_config_buf_size = count; + } + + return 0; +} + +static void fwu_compare_partition_tables(void) +{ + fwu->incompatible_partition_tables = false; + + if (fwu->phyaddr.bl_image != fwu->img.phyaddr.bl_image) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.lockdown != fwu->img.phyaddr.lockdown) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.bl_config != fwu->img.phyaddr.bl_config) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.utility_param != fwu->img.phyaddr.utility_param) + fwu->incompatible_partition_tables = true; + + if (fwu->bl_version == BL_V7) { + if (fwu->phyaddr.fl_config != fwu->img.phyaddr.fl_config) + fwu->incompatible_partition_tables = true; + } + + fwu->new_partition_table = false; + + if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware) + fwu->new_partition_table = true; + else if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config) + fwu->new_partition_table = true; + + if (fwu->flash_properties.has_disp_config) { + if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config) + fwu->new_partition_table = true; + } + + if (fwu->has_guest_code) { + if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code) + fwu->new_partition_table = true; + } + + return; +} + +static void fwu_parse_partition_table(const unsigned char *partition_table, + struct block_count *blkcount, struct physical_address *phyaddr) +{ + unsigned char ii; + unsigned char index; + unsigned char offset; + unsigned short partition_length; + unsigned short physical_address; + struct partition_table *ptable; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + for (ii = 0; ii < fwu->partitions; ii++) { + index = ii * 8 + 2; + ptable = (struct partition_table *)&partition_table[index]; + partition_length = ptable->partition_length_15_8 << 8 | + ptable->partition_length_7_0; + physical_address = ptable->start_physical_address_15_8 << 8 | + ptable->start_physical_address_7_0; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Partition entry %d:\n", + __func__, ii); + for (offset = 0; offset < 8; offset++) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: 0x%02x\n", + __func__, + partition_table[index + offset]); + } + switch (ptable->partition_id) { + case CORE_CODE_PARTITION: + blkcount->ui_firmware = partition_length; + phyaddr->ui_firmware = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core code block count: %d\n", + __func__, blkcount->ui_firmware); + blkcount->total_count += partition_length; + break; + case CORE_CONFIG_PARTITION: + blkcount->ui_config = partition_length; + phyaddr->ui_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core config block count: %d\n", + __func__, blkcount->ui_config); + blkcount->total_count += partition_length; + break; + case BOOTLOADER_PARTITION: + blkcount->bl_image = partition_length; + phyaddr->bl_image = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Bootloader block count: %d\n", + __func__, blkcount->bl_image); + blkcount->total_count += partition_length; + break; + case UTILITY_PARAMETER_PARTITION: + blkcount->utility_param = partition_length; + phyaddr->utility_param = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Utility parameter block count: %d\n", + __func__, blkcount->utility_param); + blkcount->total_count += partition_length; + break; + case DISPLAY_CONFIG_PARTITION: + blkcount->dp_config = partition_length; + phyaddr->dp_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Display config block count: %d\n", + __func__, blkcount->dp_config); + blkcount->total_count += partition_length; + break; + case FLASH_CONFIG_PARTITION: + blkcount->fl_config = partition_length; + phyaddr->fl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Flash config block count: %d\n", + __func__, blkcount->fl_config); + blkcount->total_count += partition_length; + break; + case GUEST_CODE_PARTITION: + blkcount->guest_code = partition_length; + phyaddr->guest_code = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest code block count: %d\n", + __func__, blkcount->guest_code); + blkcount->total_count += partition_length; + break; + case GUEST_SERIALIZATION_PARTITION: + blkcount->pm_config = partition_length; + phyaddr->pm_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest serialization block count: %d\n", + __func__, blkcount->pm_config); + blkcount->total_count += partition_length; + break; + case GLOBAL_PARAMETERS_PARTITION: + blkcount->bl_config = partition_length; + phyaddr->bl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Global parameters block count: %d\n", + __func__, blkcount->bl_config); + blkcount->total_count += partition_length; + break; + case DEVICE_CONFIG_PARTITION: + blkcount->lockdown = partition_length; + phyaddr->lockdown = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Device config block count: %d\n", + __func__, blkcount->lockdown); + blkcount->total_count += partition_length; + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_utility(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = fwu->img.utility.size / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + if (ii >= MAX_UTILITY_PARAMS) + continue; + addr = le_to_uint(fwu->img.utility.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UTILITY_PARAMETER_CONTAINER: + fwu->img.utility_param[ii].data = content; + fwu->img.utility_param[ii].size = length; + fwu->img.utility_param_id[ii] = content[0]; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_bootloader(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = (fwu->img.bootloader.size - 4) / 4; + + for (ii = 1; ii <= num_of_containers; ii++) { + addr = le_to_uint(fwu->img.bootloader.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case BL_IMAGE_CONTAINER: + fwu->img.bl_image.data = content; + fwu->img.bl_image.size = length; + break; + case BL_CONFIG_CONTAINER: + case GLOBAL_PARAMETERS_CONTAINER: + fwu->img.bl_config.data = content; + fwu->img.bl_config.size = length; + break; + case BL_LOCKDOWN_INFO_CONTAINER: + case DEVICE_CONFIG_CONTAINER: + fwu->img.lockdown.data = content; + fwu->img.lockdown.size = length; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10(void) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int offset; + unsigned int container_id; + unsigned int length; + const unsigned char *image; + const unsigned char *content; + struct container_descriptor *descriptor; + struct image_header_10 *header; + + image = fwu->image; + header = (struct image_header_10 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + /* address of top level container */ + offset = le_to_uint(header->top_level_container_start_addr); + descriptor = (struct container_descriptor *)(image + offset); + + /* address of top level container content */ + offset = le_to_uint(descriptor->content_address); + num_of_containers = le_to_uint(descriptor->content_length) / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + addr = le_to_uint(image + offset); + offset += 4; + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UI_CONTAINER: + case CORE_CODE_CONTAINER: + fwu->img.ui_firmware.data = content; + fwu->img.ui_firmware.size = length; + break; + case UI_CONFIG_CONTAINER: + case CORE_CONFIG_CONTAINER: + fwu->img.ui_config.data = content; + fwu->img.ui_config.size = length; + break; + case BL_CONTAINER: + fwu->img.bl_version = *content; + fwu->img.bootloader.data = content; + fwu->img.bootloader.size = length; + fwu_parse_image_header_10_bootloader(image); + break; + case UTILITY_CONTAINER: + fwu->img.utility.data = content; + fwu->img.utility.size = length; + fwu_parse_image_header_10_utility(image); + break; + case GUEST_CODE_CONTAINER: + fwu->img.contains_guest_code = true; + fwu->img.guest_code.data = content; + fwu->img.guest_code.size = length; + break; + case DISPLAY_CONFIG_CONTAINER: + fwu->img.contains_disp_config = true; + fwu->img.dp_config.data = content; + fwu->img.dp_config.size = length; + break; + case PERMANENT_CONFIG_CONTAINER: + case GUEST_SERIALIZATION_CONTAINER: + fwu->img.contains_perm_config = true; + fwu->img.pm_config.data = content; + fwu->img.pm_config.size = length; + break; + case FLASH_CONFIG_CONTAINER: + fwu->img.contains_flash_config = true; + fwu->img.fl_config.data = content; + fwu->img.fl_config.size = length; + break; + case GENERAL_INFORMATION_CONTAINER: + fwu->img.contains_firmware_id = true; + fwu->img.firmware_id = le_to_uint(content + 4); + break; + default: + break; + } + } + + return; +} + +static void fwu_parse_image_header_05_06(void) +{ + int retval; + const unsigned char *image; + struct image_header_05_06 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + image = fwu->image; + header = (struct image_header_05_06 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + fwu->img.bl_version = header->header_version; + + fwu->img.contains_bootloader = header->options_bootloader; + if (fwu->img.contains_bootloader) + fwu->img.bootloader_size = le_to_uint(header->bootloader_size); + + fwu->img.ui_firmware.size = le_to_uint(header->firmware_size); + if (fwu->img.ui_firmware.size) { + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + if (fwu->img.contains_bootloader) + fwu->img.ui_firmware.data += fwu->img.bootloader_size; + } + + if ((fwu->img.bl_version == BL_V6) && header->options_tddi) + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + + fwu->img.ui_config.size = le_to_uint(header->config_size); + if (fwu->img.ui_config.size) { + fwu->img.ui_config.data = fwu->img.ui_firmware.data + + fwu->img.ui_firmware.size; + } + + if (fwu->img.contains_bootloader || header->options_tddi) + fwu->img.contains_disp_config = true; + else + fwu->img.contains_disp_config = false; + + if (fwu->img.contains_disp_config) { + fwu->img.disp_config_offset = le_to_uint(header->dsp_cfg_addr); + fwu->img.dp_config.size = le_to_uint(header->dsp_cfg_size); + fwu->img.dp_config.data = image + fwu->img.disp_config_offset; + } else { + retval = secure_memcpy(fwu->img.cstmr_product_id, + sizeof(fwu->img.cstmr_product_id), + header->cstmr_product_id, + sizeof(header->cstmr_product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy custom product ID string\n", + __func__); + } + fwu->img.cstmr_product_id[PRODUCT_ID_SIZE] = 0; + } + + fwu->img.contains_firmware_id = header->options_firmware_id; + if (fwu->img.contains_firmware_id) + fwu->img.firmware_id = le_to_uint(header->firmware_id); + + retval = secure_memcpy(fwu->img.product_id, + sizeof(fwu->img.product_id), + header->product_id, + sizeof(header->product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + fwu->img.product_id[PRODUCT_ID_SIZE] = 0; + + fwu->img.lockdown.size = LOCKDOWN_SIZE; + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE; + + return; +} + +static int fwu_parse_image_info(void) +{ + struct image_header_10 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + header = (struct image_header_10 *)fwu->image; + + memset(&fwu->img, 0x00, sizeof(fwu->img)); + + switch (header->major_header_version) { + case IMAGE_HEADER_VERSION_10: + fwu_parse_image_header_10(); + break; + case IMAGE_HEADER_VERSION_05: + case IMAGE_HEADER_VERSION_06: + fwu_parse_image_header_05_06(); + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unsupported image file format (0x%02x)\n", + __func__, header->major_header_version); + return -EINVAL; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (!fwu->img.contains_flash_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No flash config found in firmware image\n", + __func__); + return -EINVAL; + } + + fwu_parse_partition_table(fwu->img.fl_config.data, + &fwu->img.blkcount, &fwu->img.phyaddr); + + if (fwu->img.blkcount.utility_param) + fwu->img.contains_utility_param = true; + + fwu_compare_partition_tables(); + } else { + fwu->new_partition_table = false; + fwu->incompatible_partition_tables = false; + } + + return 0; +} + +static int fwu_read_flash_status(void) +{ + int retval; + unsigned char status; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + fwu->in_bl_mode = status >> 7; + + if (fwu->bl_version == BL_V5) + fwu->flash_status = (status >> 4) & MASK_3BIT; + else if (fwu->bl_version == BL_V6) + fwu->flash_status = status & MASK_3BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->flash_status = status & MASK_5BIT; + + if (fwu->write_bootloader) + fwu->flash_status = 0x00; + + if (fwu->flash_status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash status = %d, command = 0x%02x\n", + __func__, fwu->flash_status, fwu->command); + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (fwu->flash_status == 0x08) + fwu->flash_status = 0x00; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash command\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) + fwu->command = command & MASK_4BIT; + else if (fwu->bl_version == BL_V6) + fwu->command = command & MASK_6BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->command = command; + + if (fwu->write_bootloader) + fwu->command = 0x00; + + return 0; +} + +static int fwu_wait_for_idle(int timeout_ms, bool poll) +{ + int count = 0; + int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + do { + usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US); + + count++; + if (poll || (count == timeout_count)) + fwu_read_flash_status(); + + if ((fwu->command == CMD_IDLE) && (fwu->flash_status == 0x00)) + return 0; + } while (count < timeout_count); + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for idle status\n", + __func__); + + return -ETIMEDOUT; +} + +static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd) +{ + int retval; + unsigned char data_base; + struct f34_v7_data_1_5 data_1_5; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + memset(data_1_5.data, 0x00, sizeof(data_1_5.data)); + + switch (cmd) { + case CMD_ERASE_ALL: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BL_CONFIG: + data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UI_CONFIG: + data_1_5.partition_id = CORE_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_DISP_CONFIG: + data_1_5.partition_id = DISPLAY_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_FLASH_CONFIG: + data_1_5.partition_id = FLASH_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_GUEST_CODE: + data_1_5.partition_id = GUEST_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BOOTLOADER: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UTILITY_PARAMETER: + data_1_5.partition_id = UTILITY_PARAMETER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ENTER_BL; + break; + }; + + data_1_5.payload_0 = fwu->bootloader_id[0]; + data_1_5.payload_1 = fwu->bootloader_id[1]; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + data_1_5.data, + sizeof(data_1_5.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write single transaction command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v7_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + case CMD_WRITE_CONFIG: + case CMD_WRITE_LOCKDOWN: + case CMD_WRITE_GUEST_CODE: + case CMD_WRITE_BOOTLOADER: + case CMD_WRITE_UTILITY_PARAM: + command = CMD_V7_WRITE; + break; + case CMD_READ_CONFIG: + command = CMD_V7_READ; + break; + case CMD_ERASE_ALL: + command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V7_ENTER_BL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + fwu->command = command; + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + case CMD_ENABLE_FLASH_PROG: + retval = fwu_write_f34_v7_command_single_transaction(cmd); + if (retval < 0) + return retval; + else + return 0; + default: + break; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write flash command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v5v6_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_IDLE: + command = CMD_V5V6_IDLE; + break; + case CMD_WRITE_FW: + command = CMD_V5V6_WRITE_FW; + break; + case CMD_WRITE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_WRITE_LOCKDOWN: + command = CMD_V5V6_WRITE_LOCKDOWN; + break; + case CMD_WRITE_GUEST_CODE: + command = CMD_V5V6_WRITE_GUEST_CODE; + break; + case CMD_READ_CONFIG: + command = CMD_V5V6_READ_CONFIG; + break; + case CMD_ERASE_ALL: + command = CMD_V5V6_ERASE_ALL; + break; + case CMD_ERASE_UI_CONFIG: + command = CMD_V5V6_ERASE_UI_CONFIG; + break; + case CMD_ERASE_DISP_CONFIG: + command = CMD_V5V6_ERASE_DISP_CONFIG; + break; + case CMD_ERASE_GUEST_CODE: + command = CMD_V5V6_ERASE_GUEST_CODE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V5V6_ENABLE_FLASH_PROG; + break; +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + command = CMD_V5V6_ERASE_CHIP; + break; + case CMD_ERASE_FORCE_CONFIG: + command = CMD_V5V6_ERASE_FORCE_CONFIG; + break; + case CMD_READ_FORCE_CONFIG: + command = CMD_V5V6_READ_FORCE_CONFIG; + break; + case CMD_WRITE_FORCE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_ERASE_LOCKDOWN_DATA: + command = CMD_V5V6_ERASE_LOCKDOWN_DATA; + break; + case CMD_READ_LOCKDOWN_DATA: + command = CMD_V5V6_READ_LOCKDOWN_DATA; + break; + case CMD_WRITE_LOCKDOWN_DATA: + command = CMD_V5V6_WRITE_LOCKDOWN_DATA; + break; + case CMD_ERASE_LCM_DATA: + command = CMD_V5V6_ERASE_LCM_DATA; + break; + case CMD_ERASE_OEM_DATA: + command = CMD_V5V6_ERASE_OEM_DATA; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + } + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_GUEST_CODE: +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + case CMD_ERASE_FORCE_CONFIG: + case CMD_ERASE_LOCKDOWN_DATA: + case CMD_ERASE_LCM_DATA: + case CMD_ERASE_OEM_DATA: +#endif + case CMD_ENABLE_FLASH_PROG: + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write bootloader ID\n", + __func__); + return retval; + } + break; + default: + break; + }; + + fwu->command = command; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command 0x%02x\n", + __func__, command); + return retval; + } + + return 0; +} + +static int fwu_write_f34_command(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_command(cmd); + else + retval = fwu_write_f34_v5v6_command(cmd); + + return retval; +} + +static int fwu_write_f34_v7_partition_id(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char partition; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + partition = CORE_CODE_PARTITION; + break; + case CMD_WRITE_CONFIG: + case CMD_READ_CONFIG: + if (fwu->config_area == UI_CONFIG_AREA) + partition = CORE_CONFIG_PARTITION; + else if (fwu->config_area == DP_CONFIG_AREA) + partition = DISPLAY_CONFIG_PARTITION; + else if (fwu->config_area == PM_CONFIG_AREA) + partition = GUEST_SERIALIZATION_PARTITION; + else if (fwu->config_area == BL_CONFIG_AREA) + partition = GLOBAL_PARAMETERS_PARTITION; + else if (fwu->config_area == FLASH_CONFIG_AREA) + partition = FLASH_CONFIG_PARTITION; + else if (fwu->config_area == UPP_AREA) + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_WRITE_LOCKDOWN: + partition = DEVICE_CONFIG_PARTITION; + break; + case CMD_WRITE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_WRITE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_WRITE_UTILITY_PARAM: + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_ERASE_ALL: + partition = CORE_CODE_PARTITION; + break; + case CMD_ERASE_BL_CONFIG: + partition = GLOBAL_PARAMETERS_PARTITION; + break; + case CMD_ERASE_UI_CONFIG: + partition = CORE_CONFIG_PARTITION; + break; + case CMD_ERASE_DISP_CONFIG: + partition = DISPLAY_CONFIG_PARTITION; + break; + case CMD_ERASE_FLASH_CONFIG: + partition = FLASH_CONFIG_PARTITION; + break; + case CMD_ERASE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_ERASE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_ENABLE_FLASH_PROG: + partition = BOOTLOADER_PARTITION; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + &partition, + sizeof(partition)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write partition ID\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_partition_id(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_partition_id(cmd); + else + retval = 0; + + return retval; +} + +static int fwu_read_f34_v7_partition_table(unsigned char *partition_table) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short block_number = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + fwu->config_area = FLASH_CONFIG_AREA; + + retval = fwu_write_f34_partition_id(CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + length[0] = (unsigned char)(fwu->flash_config_length & MASK_8BIT); + length[1] = (unsigned char)(fwu->flash_config_length >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length\n", + __func__); + return retval; + } + + retval = fwu_write_f34_command(CMD_READ_CONFIG); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + msleep(READ_CONFIG_WAIT_MS); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + partition_table, + fwu->partition_table_bytes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_read_f34_v7_queries(void) +{ + int retval; + unsigned char ii; + unsigned char query_base; + unsigned char index; + unsigned char offset; + unsigned char *ptable; + struct f34_v7_query_0 query_0; + struct f34_v7_query_1_7 query_1_7; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + query_base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base, + query_0.data, + sizeof(query_0.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query 0\n", + __func__); + return retval; + } + + offset = query_0.subpacket_1_size + 1; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base + offset, + query_1_7.data, + sizeof(query_1_7.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read queries 1 to 7\n", + __func__); + return retval; + } + + fwu->bootloader_id[0] = query_1_7.bl_minor_revision; + fwu->bootloader_id[1] = query_1_7.bl_major_revision; + + if (fwu->bootloader_id[1] == BL_V8) + fwu->bl_version = BL_V8; + + fwu->block_size = query_1_7.block_size_15_8 << 8 | + query_1_7.block_size_7_0; + + fwu->flash_config_length = query_1_7.flash_config_length_15_8 << 8 | + query_1_7.flash_config_length_7_0; + + fwu->payload_length = query_1_7.payload_length_15_8 << 8 | + query_1_7.payload_length_7_0; + + fwu->off.flash_status = V7_FLASH_STATUS_OFFSET; + fwu->off.partition_id = V7_PARTITION_ID_OFFSET; + fwu->off.block_number = V7_BLOCK_NUMBER_OFFSET; + fwu->off.transfer_length = V7_TRANSFER_LENGTH_OFFSET; + fwu->off.flash_cmd = V7_COMMAND_OFFSET; + fwu->off.payload = V7_PAYLOAD_OFFSET; + + index = sizeof(query_1_7.data) - V7_PARTITION_SUPPORT_BYTES; + + fwu->partitions = 0; + for (offset = 0; offset < V7_PARTITION_SUPPORT_BYTES; offset++) { + for (ii = 0; ii < 8; ii++) { + if (query_1_7.data[index + offset] & (1 << ii)) + fwu->partitions++; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Supported partitions: 0x%02x\n", + __func__, query_1_7.data[index + offset]); + } + + fwu->partition_table_bytes = fwu->partitions * 8 + 2; + + ptable = kzalloc(fwu->partition_table_bytes, GFP_KERNEL); + if (!ptable) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for partition table\n", + __func__); + return -ENOMEM; + } + + retval = fwu_read_f34_v7_partition_table(ptable); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read partition table\n", + __func__); + kfree(ptable); + return retval; + } + + fwu_parse_partition_table(ptable, &fwu->blkcount, &fwu->phyaddr); + + if (fwu->blkcount.dp_config) + fwu->flash_properties.has_disp_config = 1; + else + fwu->flash_properties.has_disp_config = 0; + + if (fwu->blkcount.pm_config) + fwu->flash_properties.has_pm_config = 1; + else + fwu->flash_properties.has_pm_config = 0; + + if (fwu->blkcount.bl_config) + fwu->flash_properties.has_bl_config = 1; + else + fwu->flash_properties.has_bl_config = 0; + + if (fwu->blkcount.guest_code) + fwu->has_guest_code = 1; + else + fwu->has_guest_code = 0; + + if (fwu->blkcount.utility_param) + fwu->has_utility_param = 1; + else + fwu->has_utility_param = 0; + + kfree(ptable); + + return 0; +} + +static int fwu_read_f34_v5v6_queries(void) +{ + int retval; + unsigned char count; + unsigned char base; + unsigned char offset; + unsigned char buf[10]; + struct f34_v5v6_flash_properties_2 properties_2; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + V5V6_BOOTLOADER_ID_OFFSET, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read bootloader ID\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) { + fwu->off.properties = V5_PROPERTIES_OFFSET; + fwu->off.block_size = V5_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V5_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V5_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V5_BLOCK_DATA_OFFSET; + } else if (fwu->bl_version == BL_V6) { + fwu->off.properties = V6_PROPERTIES_OFFSET; + fwu->off.properties_2 = V6_PROPERTIES_2_OFFSET; + fwu->off.block_size = V6_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V6_BLOCK_COUNT_OFFSET; + fwu->off.gc_block_count = V6_GUEST_CODE_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V6_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V6_BLOCK_DATA_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_size, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block size info\n", + __func__); + return retval; + } + + batohs(&fwu->block_size, &(buf[0])); + + if (fwu->bl_version == BL_V5) { + fwu->off.flash_cmd = fwu->off.payload + fwu->block_size; + fwu->off.flash_status = fwu->off.flash_cmd; + } else if (fwu->bl_version == BL_V6) { + fwu->off.flash_cmd = V6_FLASH_COMMAND_OFFSET; + fwu->off.flash_status = V6_FLASH_STATUS_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + count = 4; + + if (fwu->flash_properties.has_pm_config) + count += 2; + + if (fwu->flash_properties.has_bl_config) + count += 2; + + if (fwu->flash_properties.has_disp_config) + count += 2; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_count, + buf, + count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block count info\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.ui_firmware, &(buf[0])); + batohs(&fwu->blkcount.ui_config, &(buf[2])); + + count = 4; + + if (fwu->flash_properties.has_pm_config) { + batohs(&fwu->blkcount.pm_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_bl_config) { + batohs(&fwu->blkcount.bl_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_disp_config) + batohs(&fwu->blkcount.dp_config, &(buf[count])); + + fwu->has_guest_code = false; +#ifdef SYNA_TDDI + fwu->has_force_config = false; + fwu->has_lockdown_data = false; + fwu->has_lcm_data = false; + fwu->has_oem_data = false; +#endif + + if (fwu->flash_properties.has_query4) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties_2, + properties_2.data, + sizeof(properties_2.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties 2\n", + __func__); + return retval; + } + offset = fwu->off.properties_2 + 1; + count = 0; + if (properties_2.has_guest_code) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read guest code block count\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.guest_code, &(buf[0])); + count++; + fwu->has_guest_code = true; + } +#ifdef SYNA_TDDI + if (properties_2.has_force_config) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi force block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_force_config, &(buf[0])); + count++; + fwu->has_force_config = true; + } + if (properties_2.has_lockdown_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lockdown block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lockdown_data, &(buf[0])); + count++; + fwu->has_lockdown_data = true; + } + if (properties_2.has_lcm_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lcm block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lcm_data, &(buf[0])); + count++; + fwu->has_lcm_data = true; + } + if (properties_2.has_oem_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi oem block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_oem_data, &(buf[0])); + fwu->has_oem_data = true; + } +#endif + } + + fwu->has_utility_param = false; + + return 0; +} + +static int fwu_read_f34_queries(void) +{ + int retval; + + memset(&fwu->blkcount, 0x00, sizeof(fwu->blkcount)); + memset(&fwu->phyaddr, 0x00, sizeof(fwu->phyaddr)); + + if (fwu->bl_version == BL_V7) + retval = fwu_read_f34_v7_queries(); + else + retval = fwu_read_f34_v5v6_queries(); + + return retval; +} + +static int fwu_write_f34_v7_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short left_bytes; + unsigned short write_size; + unsigned short max_write_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + +#ifdef MAX_WRITE_SIZE + max_write_size = MAX_WRITE_SIZE; + if (max_write_size >= transfer * fwu->block_size) + max_write_size = transfer * fwu->block_size; + else if (max_write_size > fwu->block_size) + max_write_size -= max_write_size % fwu->block_size; + else + max_write_size = fwu->block_size; +#else + max_write_size = transfer * fwu->block_size; +#endif + left_bytes = transfer * fwu->block_size; + + do { + if (left_bytes / max_write_size) + write_size = max_write_size; + else + write_size = left_bytes; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + write_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + block_ptr += write_size; + left_bytes -= write_size; + } while (left_bytes); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (block %d)\n", + __func__, blk); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command for block %d\n", + __func__, blk); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (block %d)\n", + __func__, blk); + return retval; + } + + block_ptr += fwu->block_size; + } + + return 0; +} + +static int fwu_write_f34_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_blocks(block_ptr, block_cnt, cmd); + else + retval = fwu_write_f34_v5v6_blocks(block_ptr, block_cnt, cmd); + + return retval; +} + +static int fwu_read_f34_v7_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + transfer * fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + index += (transfer * fwu->block_size); + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write read config command\n", + __func__); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (block %d)\n", + __func__, blk); + return retval; + } + + index += fwu->block_size; + } + + return 0; +} + +static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_read_f34_v7_blocks(block_cnt, cmd); + else + retval = fwu_read_f34_v5v6_blocks(block_cnt, cmd); + + return retval; +} + +static int fwu_get_image_firmware_id(unsigned int *fw_id) +{ + int retval; + unsigned char index = 0; + char *strptr; + char *firmware_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->img.contains_firmware_id) { + *fw_id = fwu->img.firmware_id; + } else { + strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); + if (!strptr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n", + __func__, fwu->image_name); + return -EINVAL; + } + + strptr += 2; + firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL); + if (!firmware_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for firmware_id\n", + __func__); + return -ENOMEM; + } + while (strptr[index] >= '0' && strptr[index] <= '9') { + firmware_id[index] = strptr[index]; + index++; + if (index == MAX_FIRMWARE_ID_LEN - 1) + break; + } + + retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id); + kfree(firmware_id); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to obtain image firmware ID\n", + __func__); + return -EINVAL; + } + } + + return 0; +} + +static int fwu_get_device_config_id(void) +{ + int retval; + unsigned char config_id_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.ctrl_base_addr, + fwu->config_id, + config_id_size); + if (retval < 0) + return retval; + + return 0; +} + +static enum flash_area fwu_go_nogo(void) +{ + int retval; + enum flash_area flash_area = NONE; + unsigned char ii; + unsigned char config_id_size; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->force_update) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Update both UI and config if device is in bootloader mode */ + if (fwu->bl_mode_device) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Get device firmware ID */ + device_fw_id = rmi4_data->firmware_id; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device firmware ID = %d\n", + __func__, device_fw_id); + + /* Get image firmware ID */ + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) { + flash_area = NONE; + goto exit; + } + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID = %d\n", + __func__, image_fw_id); + + if (image_fw_id > device_fw_id) { + flash_area = UI_FIRMWARE; + goto exit; + } else if (image_fw_id < device_fw_id) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID older than device firmware ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + /* Get device config ID */ + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + for (ii = 0; ii < config_id_size; ii++) { + if (fwu->img.ui_config.data[ii] > fwu->config_id[ii]) { + flash_area = UI_CONFIG; + goto exit; + } else if (fwu->img.ui_config.data[ii] < fwu->config_id[ii]) { + flash_area = NONE; + goto exit; + } + } + + flash_area = NONE; + +exit: + if (flash_area == NONE) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: No need to do reflash\n", + __func__); + } else { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Updating %s\n", + __func__, + flash_area == UI_FIRMWARE ? + "UI firmware and config" : + "UI config only"); + } + + return flash_area; +} + +static int fwu_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + bool f01found = false; + bool f34found = false; + bool f35found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->in_ub_mode = false; + + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + if (rmi_fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, rmi_fd.fn_number); + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + f01found = true; + + rmi4_data->f01_query_base_addr = + rmi_fd.query_base_addr; + rmi4_data->f01_ctrl_base_addr = + rmi_fd.ctrl_base_addr; + rmi4_data->f01_data_base_addr = + rmi_fd.data_base_addr; + rmi4_data->f01_cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + case SYNAPTICS_RMI4_F34: + f34found = true; + fwu->f34_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f34_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f34_fd.data_base_addr = + rmi_fd.data_base_addr; + + switch (rmi_fd.fn_version) { + case F34_V0: + fwu->bl_version = BL_V5; + break; + case F34_V1: + fwu->bl_version = BL_V6; + break; + case F34_V2: + fwu->bl_version = BL_V7; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unrecognized F34 version\n", + __func__); + return -EINVAL; + } + + fwu->intr_mask = 0; + intr_src = rmi_fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + fwu->intr_mask |= 1 << ii; + } + break; + case SYNAPTICS_RMI4_F35: + f35found = true; + fwu->f35_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f35_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f35_fd.data_base_addr = + rmi_fd.data_base_addr; + fwu->f35_fd.cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + } + } else { + break; + } + + intr_count += rmi_fd.intr_src_count; + } + + if (!f01found || !f34found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find both F01 and F34\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + fwu->in_ub_mode = true; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + fwu_recovery_check_status(); + return 0; + } + } + + rmi4_data->intr_mask[0] |= fwu->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_enter_flash_prog(void) +{ + int retval; + struct f01_device_control f01_device_control; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_read_flash_status(); + if (retval < 0) + return retval; + + if (fwu->in_bl_mode) + return 0; + + retval = rmi4_data->irq_enable(rmi4_data, false, true); + if (retval < 0) + return retval; + + msleep(INT_DISABLE_WAIT_MS); + + retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG); + if (retval < 0) + return retval; + + retval = fwu_wait_for_idle(ENABLE_WAIT_MS, false); + if (retval < 0) + return retval; + + if (!fwu->in_bl_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: BL mode not entered\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->hw_if->bl_hw_init) { + retval = rmi4_data->hw_if->bl_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return retval; + + retval = fwu_read_f34_queries(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F01 device control\n", + __func__); + return retval; + } + + f01_device_control.nosleep = true; + f01_device_control.sleep_mode = SLEEP_MODE_NORMAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write F01 device control\n", + __func__); + return retval; + } + + msleep(ENTER_FLASH_PROG_WAIT_MS); + + return retval; +} + +static int fwu_check_ui_firmware_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_firmware.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_firmware) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI firmware size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_ui_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_dp_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.dp_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.dp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_pm_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.pm_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_bl_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.bl_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_guest_code_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.guest_code.size / fwu->block_size; + if (block_count != fwu->blkcount.guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_erase_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UI_CONFIG); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG); + if (retval < 0) + return retval; + break; + case BL_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG); + if (retval < 0) + return retval; + break; + case FLASH_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG); + if (retval < 0) + return retval; + break; + case UPP_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UTILITY_PARAMETER); + if (retval < 0) + return retval; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return retval; +} + +static int fwu_erase_bootloader(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_BOOTLOADER); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#ifdef SYNA_TDDI +static int fwu_erase_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + msleep(100); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#endif + +static int fwu_erase_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_GUEST_CODE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +static int fwu_erase_all(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7) { + retval = fwu_write_f34_command(CMD_ERASE_UI_FIRMWARE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } else { + retval = fwu_write_f34_command(CMD_ERASE_ALL); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase all command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (!(fwu->bl_version == BL_V8 && + fwu->flash_status == BAD_PARTITION_TABLE)) { + if (retval < 0) + return retval; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + if (fwu->bl_version == BL_V8) + return 0; + } + + if (fwu->flash_properties.has_disp_config) { + fwu->config_area = DP_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code) { + retval = fwu_erase_guest_code(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_write_firmware(void) +{ + unsigned short firmware_block_count; + + firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data, + firmware_block_count, CMD_WRITE_FW); +} + +static int fwu_write_bootloader(void) +{ + int retval; + unsigned short bootloader_block_count; + + bootloader_block_count = fwu->img.bl_image.size / fwu->block_size; + + fwu->write_bootloader = true; + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.bl_image.data, + bootloader_block_count, CMD_WRITE_BOOTLOADER); + fwu->write_bootloader = false; + + return retval; +} + +static int fwu_write_utility_parameter(void) +{ + int retval; + unsigned char ii; + unsigned char checksum_array[4]; + unsigned char *pbuf; + unsigned short remaining_size; + unsigned short utility_param_size; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + utility_param_size = fwu->blkcount.utility_param * fwu->block_size; + retval = fwu_allocate_read_config_buf(utility_param_size); + if (retval < 0) + return retval; + memset(fwu->read_config_buf, 0x00, utility_param_size); + + pbuf = fwu->read_config_buf; + remaining_size = utility_param_size - 4; + + for (ii = 0; ii < MAX_UTILITY_PARAMS; ii++) { + if (fwu->img.utility_param_id[ii] == UNUSED) + continue; + +#ifdef F51_DISCRETE_FORCE + if (fwu->img.utility_param_id[ii] == FORCE_PARAMETER) { + if (fwu->bl_mode_device) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + goto image_param; + } + retval = secure_memcpy(&(pbuf[4]), + remaining_size - 4, + fwu->cal_data, + fwu->cal_data_buf_size, + fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy force calibration data\n", + __func__); + return retval; + } + pbuf[0] = FORCE_PARAMETER; + pbuf[1] = 0x00; + pbuf[2] = (4 + fwu->cal_data_size) / 2; + pbuf += (fwu->cal_data_size + 4); + remaining_size -= (fwu->cal_data_size + 4); + continue; + } +image_param: +#endif + + retval = secure_memcpy(pbuf, + remaining_size, + fwu->img.utility_param[ii].data, + fwu->img.utility_param[ii].size, + fwu->img.utility_param[ii].size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy utility parameter data\n", + __func__); + return retval; + } + pbuf += fwu->img.utility_param[ii].size; + remaining_size -= fwu->img.utility_param[ii].size; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((utility_param_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[utility_param_size - 4] = checksum_array[0]; + fwu->read_config_buf[utility_param_size - 3] = checksum_array[1]; + fwu->read_config_buf[utility_param_size - 2] = checksum_array[2]; + fwu->read_config_buf[utility_param_size - 1] = checksum_array[3]; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->read_config_buf, + fwu->blkcount.utility_param, CMD_WRITE_UTILITY_PARAM); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_configuration(void) +{ + return fwu_write_f34_blocks((unsigned char *)fwu->config_data, + fwu->config_block_count, CMD_WRITE_CONFIG); +} + +static int fwu_write_ui_configuration(void) +{ + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->img.ui_config.data; + fwu->config_size = fwu->img.ui_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_dp_configuration(void) +{ + fwu->config_area = DP_CONFIG_AREA; + fwu->config_data = fwu->img.dp_config.data; + fwu->config_size = fwu->img.dp_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_pm_configuration(void) +{ + fwu->config_area = PM_CONFIG_AREA; + fwu->config_data = fwu->img.pm_config.data; + fwu->config_size = fwu->img.pm_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +#ifdef SYNA_TDDI +static int fwu_write_tddi_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_blocks(fwu->read_config_buf, + fwu->blkcount.tddi_lockdown_data, + CMD_WRITE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + return 0; +} +#endif + +static int fwu_write_flash_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_guest_code(void) +{ + int retval; + unsigned short guest_code_block_count; + + guest_code_block_count = fwu->img.guest_code.size / fwu->block_size; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.guest_code.data, + guest_code_block_count, CMD_WRITE_GUEST_CODE); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_lockdown(void) +{ + unsigned short lockdown_block_count; + + lockdown_block_count = fwu->img.lockdown.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.lockdown.data, + lockdown_block_count, CMD_WRITE_LOCKDOWN); +} + +static int fwu_write_partition_table_v8(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_partition_table_v7(void) +{ + int retval; + unsigned short block_count; + + block_count = fwu->blkcount.bl_config; + fwu->config_area = BL_CONFIG_AREA; + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_flash_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_bl_area_v7(void) +{ + int retval; + bool has_utility_param; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + has_utility_param = fwu->has_utility_param; + + if (fwu->has_utility_param) { + fwu->config_area = UPP_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + fwu->config_area = BL_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = FLASH_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_erase_bootloader(); + if (retval < 0) + return retval; + + retval = fwu_write_bootloader(); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->img.bl_config.data; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + if (fwu->img.contains_utility_param) { + retval = fwu_write_utility_parameter(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_do_reflash(void) +{ + int retval; + bool do_bl_update = false; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!fwu->new_partition_table) { + retval = fwu_check_ui_firmware_size(); + if (retval < 0) + return retval; + + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_check_guest_code_size(); + if (retval < 0) + return retval; + } + } else if (fwu->bl_version == BL_V7) { + retval = fwu_check_bl_configuration_size(); + if (retval < 0) + return retval; + } + + if (!fwu->has_utility_param && fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (fwu->has_utility_param && !fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (!do_bl_update && fwu->incompatible_partition_tables) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Incompatible partition tables\n", + __func__); + return -EINVAL; + } else if (!do_bl_update && fwu->new_partition_table) { + if (!fwu->force_update) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Partition table mismatch\n", + __func__); + return -EINVAL; + } + } + + retval = fwu_erase_all(); + if (retval < 0) + return retval; + + if (do_bl_update) { + retval = fwu_write_bl_area_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Bootloader area programmed\n", __func__); + } else if (fwu->bl_version == BL_V7 && fwu->new_partition_table) { + retval = fwu_write_partition_table_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } else if (fwu->bl_version == BL_V8) { + retval = fwu_write_partition_table_v8(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } + + fwu->config_area = UI_CONFIG_AREA; + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_write_dp_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Display configuration programmed\n", __func__); + } + + retval = fwu_write_ui_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Configuration programmed\n", __func__); + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_write_guest_code(); + if (retval < 0) + return retval; + pr_notice("%s: Guest code programmed\n", __func__); + } + + retval = fwu_write_firmware(); + if (retval < 0) + return retval; + pr_notice("%s: Firmware programmed\n", __func__); + + return retval; +} + +static int fwu_do_read_config(void) +{ + int retval; + unsigned short block_count; + unsigned short config_area; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + block_count = fwu->blkcount.ui_config; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.dp_config; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.pm_config; + break; + case BL_CONFIG_AREA: + if (!fwu->flash_properties.has_bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.bl_config; + break; + case UPP_AREA: + if (!fwu->has_utility_param) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Utility parameter not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.utility_param; + break; +#ifdef SYNA_TDDI + case TDDI_FORCE_CONFIG_AREA: + if (!fwu->has_force_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: force configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_force_config; + break; + case TDDI_OEM_DATA_AREA: + if (!fwu->has_oem_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: oem data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_oem_data; + break; + case TDDI_LCM_DATA_AREA: + if (!fwu->has_lcm_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: lcm data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_lcm_data; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + return -EINVAL; + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) { + config_area = fwu->config_area; + retval = fwu_enter_flash_prog(); + fwu->config_area = config_area; + if (retval < 0) + goto exit; + } + + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + +exit: + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) + rmi4_data->reset_device(rmi4_data, false); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return retval; +} + +static int fwu_do_read_customer_serialization_data(void) +{ + int ii; + int retval = 0; + int block_count = 0; + char temp[40] = {0}; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of customer serialization aquirement process\n", __func__); + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; +/* + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; +*/ + fwu->config_area = PM_CONFIG_AREA; + block_count = fwu->blkcount.pm_config; + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + goto exit; + } + fwu->config_size = fwu->block_size * block_count; + pr_notice("%s: Block size = %d\n", __func__, fwu->block_size); + pr_notice("%s: Permanent config block count = %d\n", __func__, block_count); + pr_notice("%s: Permanent config size = %d\n", __func__, fwu->config_size); + dev_info(rmi4_data->pdev->dev.parent, + "%s: permanent config size = %d\n", + __func__, fwu->config_size); + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + + goto exit; + } + + retval = fwu_read_f34_blocks(block_count, + CMD_READ_CONFIG); + if (retval < 0) { + + goto exit; + } + + for (ii = 0; ii < 10; ii++) + pr_notice("%s: Permanent config data[%d] = 0x%02x\n", __func__, ii, fwu->read_config_buf[ii]); + + sprintf(temp, "%02x%02x%02x%02x%02x%02x%02x%02x", fwu->read_config_buf[0], fwu->read_config_buf[1], fwu->read_config_buf[2], fwu->read_config_buf[3], fwu->read_config_buf[4], fwu->read_config_buf[5], fwu->read_config_buf[6], fwu->read_config_buf[7]); +printk("tp_lockdown info : %s\n", temp); +strcpy(tp_lockdown_info, temp); + + + +exit: + + pr_notice("%s: End of customer serialization acquirement process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + + + +#ifdef SYNA_TDDI +static int fwu_do_read_tddi_lockdown_data(void) +{ + int retval = -EINVAL; + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.tddi_lockdown_data; + fwu->config_size = fwu->block_size * block_count; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + kfree(fwu->read_config_buf); + + fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL); + + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + retval = -ENOMEM; + goto exit; + } + fwu->read_config_buf_size = fwu->config_size; + retval = fwu_read_f34_blocks(block_count, CMD_READ_LOCKDOWN_DATA); +exit: + return retval; +} + +int get_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng) +{ + int retval; + + retval = fwu_do_read_tddi_lockdown_data(); + if (retval < 0) + return retval; + memcpy(lockdown_data, fwu->read_config_buf, leng); + return retval; +} + +int set_tddi_lockdown_data(unsigned char *lockdown_data, unsigned short leng) +{ + int retval = -EINVAL; + unsigned long checksum; + unsigned char checksum_array[4]; + unsigned short blk_cnt; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_erase_lockdown_data(); + if (retval < 0) + goto exit; + + fwu->config_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + memset(fwu->read_config_buf, 0x00, fwu->config_size); + retval = secure_memcpy(fwu->read_config_buf, fwu->config_size, + lockdown_data, leng, leng); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy tddi lockdwon data\n", + __func__); + goto exit; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[blk_cnt * fwu->block_size - 4] = checksum_array[0]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 3] = checksum_array[1]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 2] = checksum_array[2]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 1] = checksum_array[3]; + retval = fwu_write_tddi_lockdown_data(); +exit: + return retval; +} +#endif + +static int fwu_do_lockdown_v7(void) +{ + int retval; + struct f34_v7_data0 status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if (status.device_cfg_status == 2) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +static int fwu_do_lockdown_v5v6(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#ifdef SYNA_TDDI + unsigned char *img_ld; + + img_ld = (unsigned char *)fwu->img.lockdown.data; + if (fwu->has_lockdown_data) { + retval = set_tddi_lockdown_data(img_ld, + LOCKDOWN_SIZE); + if (retval < 0) + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write lockdown data\n", + __func__); + return retval; + } +#endif + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.query_base_addr + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + if (fwu->flash_properties.unlocked == 0) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_do_restore_f51_cal_data(void) +{ + int retval; + unsigned char checksum_array[4]; + unsigned short block_count; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.ui_config; + fwu->config_size = fwu->block_size * block_count; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = secure_memcpy(&fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data, + fwu->cal_data_buf_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore calibration data\n", + __func__); + return retval; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[fwu->config_size - 4] = checksum_array[0]; + fwu->read_config_buf[fwu->config_size - 3] = checksum_array[1]; + fwu->read_config_buf[fwu->config_size - 2] = checksum_array[2]; + fwu->read_config_buf[fwu->config_size - 1] = checksum_array[3]; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} +#endif + +static int fwu_start_write_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + if (!fwu->has_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code not supported\n", + __func__); + return -EINVAL; + } + + if (!fwu->img.contains_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No guest code in firmware image\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write guest code process\n", __func__); + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_check_guest_code_size(); + if (retval < 0) + goto exit; + + retval = fwu_erase_guest_code(); + if (retval < 0) + goto exit; + + retval = fwu_write_guest_code(); + if (retval < 0) + goto exit; + + pr_notice("%s: Guest code programmed\n", __func__); + +exit: + rmi4_data->reset_device(rmi4_data, false); + + pr_notice("%s: End of write guest code process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_start_write_config(void) +{ + int retval; + unsigned short config_area; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + device_fw_id = rmi4_data->firmware_id; + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) + return retval; + if (device_fw_id != image_fw_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Device and image firmware IDs don't match\n", + __func__); + return -EINVAL; + } + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No display configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_perm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No permanent configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_pm_configuration_size(); + if (retval < 0) + return retval; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Configuration not supported\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write config process\n", __func__); + + config_area = fwu->config_area; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + fwu->config_area = config_area; + + if (fwu->config_area != PM_CONFIG_AREA) { + retval = fwu_erase_configuration(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to erase config\n", + __func__); + goto exit; + } + } + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_ui_configuration(); + if (retval < 0) + goto exit; + break; + case DP_CONFIG_AREA: + retval = fwu_write_dp_configuration(); + if (retval < 0) + goto exit; + break; + case PM_CONFIG_AREA: + retval = fwu_write_pm_configuration(); + if (retval < 0) + goto exit; + break; + } + + pr_notice("%s: Config written\n", __func__); + +exit: + switch (fwu->config_area) { + case UI_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, true); + break; + case DP_CONFIG_AREA: + case PM_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, false); + break; + } + + pr_notice("%s: End of write config process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} +static char tp_info_summary[80] = ""; + +static int fwu_start_reflash(void) +{ + int retval = 0; + enum flash_area flash_area; + bool do_rebuild = false; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + unsigned char config_ver[20] = {0}; + + char tp_temp_info[80]; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of reflash process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IMAGE_NAME, sizeof(FW_IMAGE_NAME), + sizeof(FW_IMAGE_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware image %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware image %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + } + + retval = fwu_parse_image_info(); + if (retval < 0) + goto exit; + + if (fwu->blkcount.total_count != fwu->img.blkcount.total_count) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash size mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (fwu->bl_version != fwu->img.bl_version) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader version mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; + + if (fwu->in_bl_mode) { + fwu->bl_mode_device = true; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode\n", + __func__); + } else { + fwu->bl_mode_device = false; + } + + flash_area = fwu_go_nogo(); + + if (flash_area != NONE) { + retval = fwu_enter_flash_prog(); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } + +#ifdef F51_DISCRETE_FORCE + if (flash_area != NONE && !fwu->bl_mode_device) { + fwu->config_size = fwu->block_size * fwu->blkcount.ui_config; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = fwu_read_f34_blocks(fwu->blkcount.ui_config, + CMD_READ_CONFIG); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = secure_memcpy(fwu->cal_data, fwu->cal_data_buf_size, + &fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to save calibration data\n", + __func__); + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } +#endif + + switch (flash_area) { + case UI_FIRMWARE: + do_rebuild = true; + retval = fwu_do_reflash(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param || fwu->img.contains_utility_param) + break; + + rmi4_data->reset_device(rmi4_data, false); + + if (fwu->bl_mode_device || fwu->in_bl_mode) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + break; + } + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case UI_CONFIG: + do_rebuild = true; + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + break; + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + break; + retval = fwu_write_ui_configuration(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param) + break; + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case NONE: + default: + break; + } + + if (retval < 0) { + do_rebuild = false; + rmi4_data->reset_device(rmi4_data, false); + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + goto exit; + } + + if (fwu->do_lockdown && (fwu->img.lockdown.data != NULL)) { + switch (fwu->bl_version) { + case BL_V5: + case BL_V6: + retval = fwu_do_lockdown_v5v6(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + case BL_V7: + case BL_V8: + retval = fwu_do_lockdown_v7(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + default: + break; + } + } + +exit: + if (fw_entry) + release_firmware(fw_entry); + + if (do_rebuild) + rmi4_data->reset_device(rmi4_data, true); + + pr_notice("%s: End of reflash process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + synaptics_rmi4_reg_read(rmi4_data, + 0x000c, + config_ver, + 1); + printk("config_ver info =%02x\n", config_ver[0]); + + + if ((tp_lockdown_info[6] == '0') && (tp_lockdown_info[7] == '1')) + strcpy(tp_info_summary, "[Vendor]Tianma(G6.0), [IC]TD4310(synaptics), [FW]Ver"); + else if ((tp_lockdown_info[6] == '0') && (tp_lockdown_info[7] == '2')) + strcpy(tp_info_summary, "[Vendor]Tianma(G5.5), [IC]TD4310(synaptics), [FW]Ver"); + sprintf(tp_temp_info, "%02x", config_ver[0]); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + hq_regiser_hw_info(HWID_CTP, tp_info_summary); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_recovery_check_status(void) +{ + int retval; + unsigned char data_base; + unsigned char status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_ERROR_CODE_OFFSET, + &status, + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read status\n", + __func__); + return retval; + } + + status = status & MASK_5BIT; + + if (status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Recovery mode status = %d\n", + __func__, status); + return -EINVAL; + } + + return 0; +} + +static int fwu_recovery_erase_completion(void) +{ + int retval; + unsigned char data_base; + unsigned char command; + unsigned char status; + unsigned int timeout = F35_ERASE_ALL_WAIT_MS / 20; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + do { + command = 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue command\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command status\n", + __func__); + return retval; + } + + if ((command & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + + if (timeout == 0) + goto exit; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_FLASH_STATUS_OFFSET, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if ((status & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + +exit: + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for flash erase completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int fwu_recovery_erase_all(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_ERASE_ALL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue erase all command\n", + __func__); + return retval; + } + + if (fwu->f35_fd.cmd_base_addr) { + retval = fwu_recovery_erase_completion(); + if (retval < 0) + return retval; + } else { + msleep(F35_ERASE_ALL_WAIT_MS); + } + + retval = fwu_recovery_check_status(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_recovery_write_chunk(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char chunk_number[] = {0, 0}; + unsigned char chunk_spare; + unsigned char chunk_size; + unsigned char buf[F35_CHUNK_SIZE + 1]; + unsigned short chunk; + unsigned short chunk_total; + unsigned short bytes_written = 0; + unsigned char *chunk_ptr = (unsigned char *)fwu->image; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_NUM_LSB_OFFSET, + chunk_number, + sizeof(chunk_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk number\n", + __func__); + return retval; + } + + buf[sizeof(buf) - 1] = CMD_F35_WRITE_CHUNK; + + chunk_total = fwu->image_size / F35_CHUNK_SIZE; + chunk_spare = fwu->image_size % F35_CHUNK_SIZE; + if (chunk_spare) + chunk_total++; + + for (chunk = 0; chunk < chunk_total; chunk++) { + if (chunk_spare && chunk == chunk_total - 1) + chunk_size = chunk_spare; + else + chunk_size = F35_CHUNK_SIZE; + + memset(buf, 0x00, F35_CHUNK_SIZE); + secure_memcpy(buf, sizeof(buf), chunk_ptr, + fwu->image_size - bytes_written, + chunk_size); + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_DATA_OFFSET, + buf, + sizeof(buf)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data (chunk %d)\n", + __func__, chunk); + return retval; + } + chunk_ptr += chunk_size; + bytes_written += chunk_size; + } + + retval = fwu_recovery_check_status(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_recovery_reset(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_RESET; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + return retval; + } + + msleep(F35_RESET_WAIT_MS); + + return 0; +} + +static int fwu_start_recovery(void) +{ + int retval; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of recovery process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IHEX_NAME, sizeof(FW_IHEX_NAME), + sizeof(FW_IHEX_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy ihex file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware ihex %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware ihex %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + fwu->image_size = fw_entry->size; + } + + retval = rmi4_data->irq_enable(rmi4_data, false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable interrupt\n", + __func__); + goto exit; + } + + retval = fwu_recovery_erase_all(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do erase all in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: External flash erased\n", __func__); + + retval = fwu_recovery_write_chunk(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Chunk data programmed\n", __func__); + + retval = fwu_recovery_reset(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reset device in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Recovery mode reset issued\n", __func__); + + rmi4_data->reset_device(rmi4_data, true); + + retval = 0; + +exit: + if (fw_entry) + release_firmware(fw_entry); + + pr_notice("%s: End of recovery process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +int synaptics_fw_updater(const unsigned char *fw_data) +{ + int retval; + + if (!fwu) + return -ENODEV; + + if (!fwu->initialized) + return -ENODEV; + + if (fwu->in_ub_mode) { + fwu->image = NULL; + retval = fwu_start_recovery(); + if (retval < 0) + return retval; + } + + fwu->image = fw_data; + + retval = fwu_start_reflash(); + + fwu->image = NULL; + + return retval; +} +EXPORT_SYMBOL(synaptics_fw_updater); + +#ifdef DO_STARTUP_FW_UPDATE +static void fwu_startup_fw_update_work(struct work_struct *work) +{ + static unsigned char do_once = 1; +#ifdef WAIT_FOR_FB_READY + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#endif + + + if (!do_once) + return; + do_once = 0; + +#ifdef WAIT_FOR_FB_READY + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } +#endif + + synaptics_fw_updater(NULL); + + + + return; +} +#endif + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (count < fwu->config_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + retval = -EINVAL; + goto exit; + } + + retval = secure_memcpy(buf, count, fwu->read_config_buf, + fwu->read_config_buf_size, fwu->config_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy config data\n", + __func__); + goto exit; + } else { + retval = fwu->config_size; + } + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = secure_memcpy(&fwu->ext_data_source[fwu->data_pos], + fwu->image_size - fwu->data_pos, buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image data\n", + __func__); + goto exit; + } else { + retval = count; + } + + fwu->data_pos += count; + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (!fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not in microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_recovery(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do recovery\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + if (input & LOCKDOWN) { + fwu->do_lockdown = true; + input &= ~LOCKDOWN; + } + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; + + } + + if (input == FORCE) + fwu->force_update = true; + + retval = synaptics_fw_updater(fwu->image); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_do_read_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long config_area; + + retval = sstrtoul(buf, 10, &config_area); + if (retval) + return retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + fwu->config_area = config_area; + + mutex_unlock(&fwu_sysfs_mutex); + + return count; +} + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + } else { + retval = count; + } + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = sstrtoul(buf, 10, &size); + if (retval) + return retval; + +/* if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; +*/ + fwu->image_size = size; + fwu->data_pos = 0; + + kfree(fwu->ext_data_source); + fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL); + if (!fwu->ext_data_source) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image data\n", + __func__); + retval = -ENOMEM; + } else { + retval = count; + } + + + + return retval; +} + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_firmware); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.dp_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.pm_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.bl_config); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.utility_param); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.guest_code); + + mutex_unlock(&fwu_sysfs_mutex); + + return retval; +} + + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + fwu_do_read_customer_serialization_data(); + + retval = snprintf(buf, PAGE_SIZE, "%s\n", fwu->read_config_buf); + + return retval; +} + + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_guest_code(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write guest code\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex); + return retval; +} + +static ssize_t fwu_sysfs_read_panel_color_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + + if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '1')) + ret = scnprintf(buf, PAGE_SIZE, "0x31 WHITE\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '2')) + ret = scnprintf(buf, PAGE_SIZE, "0x32 BLACK\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '3')) + ret = scnprintf(buf, PAGE_SIZE, "0x33 RED\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '4')) + ret = scnprintf(buf, PAGE_SIZE, "0x34 YELLOW\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '5')) + ret = scnprintf(buf, PAGE_SIZE, "0x35 GREEN\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '6')) + ret = scnprintf(buf, PAGE_SIZE, "0x36 PINK\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '7')) + ret = scnprintf(buf, PAGE_SIZE, "0x37 PURPLE\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '8')) + ret = scnprintf(buf, PAGE_SIZE, "0x38 GOLDEN\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '9')) + ret = scnprintf(buf, PAGE_SIZE, "0x39 SLIVER\n"); + else if ((tp_lockdown_info[4] == '4') && (tp_lockdown_info[5] == '0')) + ret = scnprintf(buf, PAGE_SIZE, "0x40 GRAY\n"); + else if ((tp_lockdown_info[4] == '4') && (tp_lockdown_info[5] == '1')) + ret = scnprintf(buf, PAGE_SIZE, "0x41 SLIVER BLUE\n"); + else if ((tp_lockdown_info[4] == '4') && (tp_lockdown_info[5] == '2')) + ret = scnprintf(buf, PAGE_SIZE, "0x42 CORAL BLUE\n"); + + return ret; +} + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned short lockdown_data_size; + unsigned char *lockdown_data; + char ld_val[2]; + int retval = 0; + int i = 0; + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + lockdown_data_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) { + mutex_unlock(&fwu_sysfs_mutex); + return -ENOMEM; + } + + if (get_tddi_lockdown_data(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return -EINVAL; + } + + for (i = 0; i < lockdown_data_size; i++) { + retval += snprintf(ld_val, PAGE_SIZE, "%02x", + *(lockdown_data + i)); + strlcat(buf, ld_val, lockdown_data_size); + } + *(buf + retval) = '\n'; + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return retval + 1; +} + +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned short lockdown_data_size = (count - 1) / 2; + unsigned char *lockdown_data; + unsigned char temp[2]; + int ld_val; + int i = 0; + + for (i = 0; i < (count - 1); i++) { + if (((*buf >= '0') && (*buf <= '9')) || + (('a' < *buf) && (*buf > 'f')) || + (('A' < *buf) && (*buf > 'F'))) + continue; + else + return -EINVAL; + } + + if (count % 2 != 1) + return -EINVAL; + + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) + return -ENOMEM; + + for (i = 0; i < lockdown_data_size; i++) { + memcpy(temp, (buf + 2 * i), sizeof(temp)); + if (sscanf(temp, "%02x", &ld_val) == 1) + *(lockdown_data + i) = ld_val & 0xff; + } + + if (!mutex_trylock(&fwu_sysfs_mutex)) + return -EBUSY; + + if (set_tddi_lockdown_data(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return -EINVAL; + } + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex); + return count; +} +#endif +static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!fwu) + return; + + if (fwu->intr_mask & intr_mask) + fwu_read_flash_status(); + + return; +} + +static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + struct pdt_properties pdt_props; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) + unsigned char lockdown[20] = {0}; +#endif + if (fwu) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + fwu = kzalloc(sizeof(*fwu), GFP_KERNEL); + if (!fwu) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + fwu->image_name = kzalloc(MAX_IMAGE_NAME_LEN, GFP_KERNEL); + if (!fwu->image_name) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image name\n", + __func__); + retval = -ENOMEM; + goto exit_free_fwu; + } + + fwu->rmi4_data = rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + PDT_PROPS, + pdt_props.data, + sizeof(pdt_props.data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read PDT properties, assuming 0x00\n", + __func__); + } else if (pdt_props.has_bsr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Reflash for LTS not currently supported\n", + __func__); + retval = -ENODEV; + goto exit_free_mem; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + if (!fwu->in_ub_mode) { + retval = fwu_read_f34_queries(); + if (retval < 0) + goto exit_free_mem; + + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + goto exit_free_mem; + } + } + + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + fwu->initialized = true; + +#ifdef DO_STARTUP_FW_UPDATE + +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); + INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work); + queue_work(fwu->fwu_workqueue, + &fwu->fwu_work); + + #ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif +#endif + +printk("before get_tddi_lockdown_data"); + + if (get_tddi_lockdown_data(lockdown, 20) < 0){ + printk("read lockdown fail\n"); + } + printk("lockdown info =%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + sprintf(tp_lockdown_info, "%02x%02x%02x%02x%02x%02x%02x%02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) + { + printk("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); + } + + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) { + retval = fwu_f51_force_data_init(); + if (retval < 0) + goto exit_free_mem; + } +#endif + + if (ENABLE_SYS_REFLASH == false) + return 0; + + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_free_mem; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + + return 0; + +exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit_free_mem: + kfree(fwu->image_name); + +exit_free_fwu: + kfree(fwu); + fwu = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!fwu) + goto exit; + +#ifdef DO_STARTUP_FW_UPDATE + cancel_work_sync(&fwu->fwu_work); + flush_workqueue(fwu->fwu_workqueue); + destroy_workqueue(fwu->fwu_workqueue); +#endif + +#ifdef F51_DISCRETE_FORCE + kfree(fwu->cal_data); +#endif + kfree(fwu->read_config_buf); + kfree(fwu->image_name); + kfree(fwu); + fwu = NULL; + + if (ENABLE_SYS_REFLASH == false) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit: + complete(&fwu_remove_complete); + + return; +} + +static void synaptics_rmi4_fwu_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!fwu) { + synaptics_rmi4_fwu_init(rmi4_data); + return; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return; + + if (!fwu->in_ub_mode) + fwu_read_f34_queries(); + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) + fwu_f51_force_data_init(); +#endif + + return; +} + +static struct synaptics_rmi4_exp_fn fwu_module = { + .fn_type = RMI_FW_UPDATER, + .init = synaptics_rmi4_fwu_init, + .remove = synaptics_rmi4_fwu_remove, + .reset = synaptics_rmi4_fwu_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_fwu_attn, +}; + +static int __init rmi4_fw_update_module_init(void) +{ + synaptics_rmi4_new_function(&fwu_module, true); + + return 0; +} + +static void __exit rmi4_fw_update_module_exit(void) +{ + synaptics_rmi4_new_function(&fwu_module, false); + + wait_for_completion(&fwu_remove_complete); + + return; +} + +module_init(rmi4_fw_update_module_init); +module_exit(rmi4_fw_update_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX FW Update Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_gesture.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_gesture.c new file mode 100755 index 0000000000000..c91eb26b88bb5 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_gesture.c @@ -0,0 +1,2308 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define GESTURE_PHYS_NAME "synaptics_dsx/gesture" + +#define TUNING_SYSFS_DIR_NAME "tuning" + +#define STORE_GESTURES +#ifdef STORE_GESTURES +#define GESTURES_TO_STORE 10 +#endif + +#define CTRL23_FINGER_REPORT_ENABLE_BIT 0 +#define CTRL27_UDG_ENABLE_BIT 4 +#define WAKEUP_GESTURE_MODE 0x02 + +static ssize_t udg_sysfs_engine_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_detection_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_detection_score_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_detection_index_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_registration_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_registration_begin_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_registration_status_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_max_index_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_detection_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_index_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_template_valid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_valid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_template_clear_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_trace_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t udg_sysfs_template_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t udg_sysfs_trace_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t udg_sysfs_template_displacement_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_template_displacement_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_rotation_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_rotation_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_scale_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_scale_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_threshold_factor_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_threshold_factor_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_match_metric_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_match_metric_threshold_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t udg_sysfs_max_inter_stroke_time_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t udg_sysfs_max_inter_stroke_time_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static int udg_read_tuning_params(void); + +static int udg_write_tuning_params(void); + +static int udg_detection_enable(bool enable); + +static int udg_engine_enable(bool enable); + +static int udg_set_index(unsigned char index); + +#ifdef STORE_GESTURES +static int udg_read_valid_data(void); +static int udg_write_valid_data(void); +static int udg_read_template_data(unsigned char index); +static int udg_write_template_data(void); +#endif + +enum gesture_type { + DETECTION = 0x0f, + REGISTRATION = 0x10, +}; + +struct udg_tuning { + union { + struct { + unsigned char maximum_number_of_templates; + unsigned char template_size; + unsigned char template_disp_lsb; + unsigned char template_disp_msb; + unsigned char rotation_inv_lsb; + unsigned char rotation_inv_msb; + unsigned char scale_inv_lsb; + unsigned char scale_inv_msb; + unsigned char thres_factor_lsb; + unsigned char thres_factor_msb; + unsigned char metric_thres_lsb; + unsigned char metric_thres_msb; + unsigned char inter_stroke_lsb; + unsigned char inter_stroke_msb; + } __packed; + unsigned char data[14]; + }; +}; + +struct udg_addr { + unsigned short data_4; + unsigned short ctrl_18; + unsigned short ctrl_20; + unsigned short ctrl_23; + unsigned short ctrl_27; + unsigned short ctrl_41; + unsigned short trace_x; + unsigned short trace_y; + unsigned short trace_segment; + unsigned short template_helper; + unsigned short template_data; + unsigned short template_flags; +}; + +struct synaptics_rmi4_f12_query_0 { + union { + struct { + struct { + unsigned char has_register_descriptors:1; + unsigned char has_closed_cover:1; + unsigned char has_fast_glove_detect:1; + unsigned char has_dribble:1; + unsigned char has_4p4_jitter_filter_strength:1; + unsigned char f12_query0_s0_b5__7:3; + } __packed; + struct { + unsigned char max_num_templates:4; + unsigned char f12_query0_s1_b4__7:4; + unsigned char template_size_lsb; + unsigned char template_size_msb; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + struct { + unsigned char ctrl24_is_present:1; + unsigned char ctrl25_is_present:1; + unsigned char ctrl26_is_present:1; + unsigned char ctrl27_is_present:1; + unsigned char ctrl28_is_present:1; + unsigned char ctrl29_is_present:1; + unsigned char ctrl30_is_present:1; + unsigned char ctrl31_is_present:1; + } __packed; + struct { + unsigned char ctrl32_is_present:1; + unsigned char ctrl33_is_present:1; + unsigned char ctrl34_is_present:1; + unsigned char ctrl35_is_present:1; + unsigned char ctrl36_is_present:1; + unsigned char ctrl37_is_present:1; + unsigned char ctrl38_is_present:1; + unsigned char ctrl39_is_present:1; + } __packed; + struct { + unsigned char ctrl40_is_present:1; + unsigned char ctrl41_is_present:1; + unsigned char ctrl42_is_present:1; + unsigned char ctrl43_is_present:1; + unsigned char ctrl44_is_present:1; + unsigned char ctrl45_is_present:1; + unsigned char ctrl46_is_present:1; + unsigned char ctrl47_is_present:1; + } __packed; + }; + unsigned char data[7]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + struct { + unsigned char data8_is_present:1; + unsigned char data9_is_present:1; + unsigned char data10_is_present:1; + unsigned char data11_is_present:1; + unsigned char data12_is_present:1; + unsigned char data13_is_present:1; + unsigned char data14_is_present:1; + unsigned char data15_is_present:1; + } __packed; + struct { + unsigned char data16_is_present:1; + unsigned char data17_is_present:1; + unsigned char data18_is_present:1; + unsigned char data19_is_present:1; + unsigned char data20_is_present:1; + unsigned char data21_is_present:1; + unsigned char data22_is_present:1; + unsigned char data23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f12_control_41 { + union { + struct { + unsigned char enable_registration:1; + unsigned char template_index:4; + unsigned char begin:1; + unsigned char f12_ctrl41_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_udg_handle { + atomic_t attn_event; + unsigned char intr_mask; + unsigned char report_flags; + unsigned char object_type_enable1; + unsigned char object_type_enable2; + unsigned char trace_size; + unsigned char template_index; + unsigned char max_num_templates; + unsigned char detection_score; + unsigned char detection_index; + unsigned char detection_status; + unsigned char registration_status; + unsigned char *ctrl_buf; + unsigned char *trace_data_buf; + unsigned char *template_data_buf; +#ifdef STORE_GESTURES + unsigned char gestures_to_store; + unsigned char *storage_buf; + unsigned char valid_buf[2]; +#endif + unsigned short trace_data_buf_size; + unsigned short template_size; + unsigned short template_data_size; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short ctrl_18_sub10_off; + unsigned short ctrl_20_sub1_off; + unsigned short ctrl_23_sub3_off; + unsigned short ctrl_27_sub5_off; + struct input_dev *udg_dev; + struct kobject *tuning_dir; + struct udg_addr addr; + struct udg_tuning tuning; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct device_attribute attrs[] = { + __ATTR(engine_enable, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_engine_enable_store), + __ATTR(detection_enable, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_detection_enable_store), + __ATTR(detection_score, S_IRUGO, + udg_sysfs_detection_score_show, + synaptics_rmi4_store_error), + __ATTR(detection_index, S_IRUGO, + udg_sysfs_detection_index_show, + synaptics_rmi4_store_error), + __ATTR(registration_enable, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_registration_enable_store), + __ATTR(registration_begin, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_registration_begin_store), + __ATTR(registration_status, S_IRUGO, + udg_sysfs_registration_status_show, + synaptics_rmi4_store_error), + __ATTR(template_size, S_IRUGO, + udg_sysfs_template_size_show, + synaptics_rmi4_store_error), + __ATTR(template_max_index, S_IRUGO, + udg_sysfs_template_max_index_show, + synaptics_rmi4_store_error), + __ATTR(template_detection, S_IRUGO, + udg_sysfs_template_detection_show, + synaptics_rmi4_store_error), + __ATTR(template_index, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_template_index_store), + __ATTR(template_valid, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_template_valid_show, + udg_sysfs_template_valid_store), + __ATTR(template_clear, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + udg_sysfs_template_clear_store), + __ATTR(trace_size, S_IRUGO, + udg_sysfs_trace_size_show, + synaptics_rmi4_store_error), +}; + +static struct bin_attribute template_data = { + .attr = { + .name = "template_data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = udg_sysfs_template_data_show, + .write = udg_sysfs_template_data_store, +}; + +static struct bin_attribute trace_data = { + .attr = { + .name = "trace_data", + .mode = S_IRUGO, + }, + .size = 0, + .read = udg_sysfs_trace_data_show, + .write = NULL, +}; + +static struct device_attribute params[] = { + __ATTR(template_displacement, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_template_displacement_show, + udg_sysfs_template_displacement_store), + __ATTR(rotation_invariance, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_rotation_invariance_show, + udg_sysfs_rotation_invariance_store), + __ATTR(scale_invariance, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_scale_invariance_show, + udg_sysfs_scale_invariance_store), + __ATTR(threshold_factor, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_threshold_factor_show, + udg_sysfs_threshold_factor_store), + __ATTR(match_metric_threshold, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_match_metric_threshold_show, + udg_sysfs_match_metric_threshold_store), + __ATTR(max_inter_stroke_time, (S_IRUGO | S_IWUSR | S_IWGRP), + udg_sysfs_max_inter_stroke_time_show, + udg_sysfs_max_inter_stroke_time_store), +}; + +static struct synaptics_rmi4_udg_handle *udg; + +static unsigned char ctrl_18_sub_size[] = {10, 10, 10, 2, 3, 4, 3, 3, 1, 1}; +static unsigned char ctrl_20_sub_size[] = {2}; +static unsigned char ctrl_23_sub_size[] = {1, 1, 1}; +static unsigned char ctrl_27_sub_size[] = {1, 5, 2, 1, 7}; + +DECLARE_COMPLETION(udg_remove_complete); + +static ssize_t udg_sysfs_engine_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool enable; + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + enable = true; + else if (input == 0) + enable = false; + else + return -EINVAL; + + retval = udg_engine_enable(enable); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_detection_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool enable; + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + enable = true; + else if (input == 0) + enable = false; + else + return -EINVAL; + + udg->detection_status = 0; + + retval = udg_detection_enable(enable); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_detection_score_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->detection_score); +} + +static ssize_t udg_sysfs_detection_index_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->detection_index); +} + +static ssize_t udg_sysfs_registration_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool enable; + unsigned int input; + struct synaptics_rmi4_f12_control_41 control_41; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + enable = true; + else if (input == 0) + enable = false; + else + return -EINVAL; + + if (enable) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[0] = 0; + udg->ctrl_buf[0] |= (1 << CTRL23_FINGER_REPORT_ENABLE_BIT); + if (udg->ctrl_23_sub3_off) + udg->ctrl_buf[udg->ctrl_23_sub3_off] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[0] = udg->object_type_enable1; + if (udg->ctrl_23_sub3_off) { + udg->ctrl_buf[udg->ctrl_23_sub3_off] = + udg->object_type_enable2; + } + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + control_41.enable_registration = enable ? 1 : 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_registration_begin_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + bool begin; + unsigned int input; + struct synaptics_rmi4_f12_control_41 control_41; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + begin = true; + else if (input == 0) + begin = false; + else + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + control_41.begin = begin ? 1 : 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_registration_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%02x\n", udg->registration_status); +} + +static ssize_t udg_sysfs_template_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->template_size); +} + +static ssize_t udg_sysfs_template_max_index_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->max_num_templates - 1); +} + +static ssize_t udg_sysfs_template_detection_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + int attn_event; + unsigned char detection_status; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + attn_event = atomic_read(&udg->attn_event); + atomic_set(&udg->attn_event, 0); + + if (attn_event == 0) + return snprintf(buf, PAGE_SIZE, "0\n"); + + if (udg->detection_status == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.data_4, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) + return retval; + + udg->detection_status = rmi4_data->gesture_detection[0]; + } + + detection_status = udg->detection_status; + udg->detection_status = 0; + + switch (detection_status) { + case DETECTION: + udg->detection_score = rmi4_data->gesture_detection[1]; + udg->detection_index = rmi4_data->gesture_detection[4]; + udg->trace_size = rmi4_data->gesture_detection[3]; + break; + case REGISTRATION: + udg->registration_status = rmi4_data->gesture_detection[1]; + udg->trace_size = rmi4_data->gesture_detection[3]; + break; + default: + return snprintf(buf, PAGE_SIZE, "0\n"); + } + + return snprintf(buf, PAGE_SIZE, "0x%02x\n", detection_status); +} + +static ssize_t udg_sysfs_template_index_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long index; + + retval = sstrtoul(buf, 10, &index); + if (retval) + return retval; + + retval = udg_set_index((unsigned char)index); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_template_valid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned char valid; + unsigned char offset; + unsigned char byte_num; + unsigned char template_flags[2]; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + byte_num = udg->template_index / 8; + offset = udg->template_index % 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_flags, + template_flags, + sizeof(template_flags)); + if (retval < 0) + return retval; + + valid = (template_flags[byte_num] & (1 << offset)) >> offset; + + return snprintf(buf, PAGE_SIZE, "%u\n", valid); +} + +static ssize_t udg_sysfs_template_valid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long valid; + unsigned char offset; + unsigned char byte_num; + unsigned char template_flags[2]; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = sstrtoul(buf, 10, &valid); + if (retval) + return retval; + + if (valid > 0) + valid = 1; + + byte_num = udg->template_index / 8; + offset = udg->template_index % 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_flags, + template_flags, + sizeof(template_flags)); + if (retval < 0) + return retval; + + if (valid) + template_flags[byte_num] |= (1 << offset); + else + template_flags[byte_num] &= ~(1 << offset); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_flags, + template_flags, + sizeof(template_flags)); + if (retval < 0) + return retval; + +#ifdef STORE_GESTURES + udg_read_valid_data(); +#endif + + return count; +} + +static ssize_t udg_sysfs_template_clear_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + const char cmd[] = {'0', 0}; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + memset(udg->template_data_buf, 0x00, udg->template_data_size); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_data, + udg->template_data_buf, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to clear template data\n", + __func__); + return retval; + } + + retval = udg_sysfs_template_valid_store(dev, attr, cmd, 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to clear valid bit\n", + __func__); + return retval; + } + +#ifdef STORE_GESTURES + udg_read_template_data(udg->template_index); + udg_read_valid_data(); +#endif + + return count; +} + +static ssize_t udg_sysfs_trace_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", udg->trace_size); +} + +static ssize_t udg_sysfs_trace_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned short index = 0; + unsigned short trace_data_size; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + trace_data_size = udg->trace_size * 5; + + if (trace_data_size == 0) + return -EINVAL; + + if (count < trace_data_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + return -EINVAL; + } + + if (udg->trace_data_buf_size < trace_data_size) { + if (udg->trace_data_buf_size) + kfree(udg->trace_data_buf); + udg->trace_data_buf = kzalloc(trace_data_size, GFP_KERNEL); + if (!udg->trace_data_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for trace data buffer\n", + __func__); + udg->trace_data_buf_size = 0; + return -ENOMEM; + } + udg->trace_data_buf_size = trace_data_size; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.trace_x, + &udg->trace_data_buf[index], + udg->trace_size * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read trace X data\n", + __func__); + return retval; + } else { + index += udg->trace_size * 2; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.trace_y, + &udg->trace_data_buf[index], + udg->trace_size * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read trace Y data\n", + __func__); + return retval; + } else { + index += udg->trace_size * 2; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.trace_segment, + &udg->trace_data_buf[index], + udg->trace_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read trace segment data\n", + __func__); + return retval; + } + + retval = secure_memcpy(buf, count, udg->trace_data_buf, + udg->trace_data_buf_size, trace_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy trace data\n", + __func__); + return retval; + } + + return trace_data_size; +} + +static ssize_t udg_sysfs_template_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (count < udg->template_data_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + return -EINVAL; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_data, + udg->template_data_buf, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read template data\n", + __func__); + return retval; + } + + retval = secure_memcpy(buf, count, udg->template_data_buf, + udg->template_data_size, udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy template data\n", + __func__); + return retval; + } + +#ifdef STORE_GESTURES + udg_read_template_data(udg->template_index); + udg_read_valid_data(); +#endif + + return udg->template_data_size; +} + +static ssize_t udg_sysfs_template_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = secure_memcpy(udg->template_data_buf, udg->template_data_size, + buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy template data\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_data, + udg->template_data_buf, + count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write template data\n", + __func__); + return retval; + } + +#ifdef STORE_GESTURES + udg_read_template_data(udg->template_index); + udg_read_valid_data(); +#endif + + return count; +} + +static ssize_t udg_sysfs_template_displacement_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short template_displacement; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + template_displacement = + ((unsigned short)udg->tuning.template_disp_lsb << 0) | + ((unsigned short)udg->tuning.template_disp_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", template_displacement); +} + +static ssize_t udg_sysfs_template_displacement_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.template_disp_lsb = (unsigned char)(input >> 0); + udg->tuning.template_disp_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_rotation_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short rotation_invariance; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + rotation_invariance = + ((unsigned short)udg->tuning.rotation_inv_lsb << 0) | + ((unsigned short)udg->tuning.rotation_inv_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", rotation_invariance); +} + +static ssize_t udg_sysfs_rotation_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.rotation_inv_lsb = (unsigned char)(input >> 0); + udg->tuning.rotation_inv_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_scale_invariance_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short scale_invariance; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + scale_invariance = + ((unsigned short)udg->tuning.scale_inv_lsb << 0) | + ((unsigned short)udg->tuning.scale_inv_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", scale_invariance); +} + +static ssize_t udg_sysfs_scale_invariance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.scale_inv_lsb = (unsigned char)(input >> 0); + udg->tuning.scale_inv_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_threshold_factor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short threshold_factor; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + threshold_factor = + ((unsigned short)udg->tuning.thres_factor_lsb << 0) | + ((unsigned short)udg->tuning.thres_factor_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", threshold_factor); +} + +static ssize_t udg_sysfs_threshold_factor_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.thres_factor_lsb = (unsigned char)(input >> 0); + udg->tuning.thres_factor_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_match_metric_threshold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short match_metric_threshold; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + match_metric_threshold = + ((unsigned short)udg->tuning.metric_thres_lsb << 0) | + ((unsigned short)udg->tuning.metric_thres_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", match_metric_threshold); +} + +static ssize_t udg_sysfs_match_metric_threshold_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.metric_thres_lsb = (unsigned char)(input >> 0); + udg->tuning.metric_thres_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t udg_sysfs_max_inter_stroke_time_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned short max_inter_stroke_time; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + max_inter_stroke_time = + ((unsigned short)udg->tuning.inter_stroke_lsb << 0) | + ((unsigned short)udg->tuning.inter_stroke_msb << 8); + + return snprintf(buf, PAGE_SIZE, "%u\n", max_inter_stroke_time); +} + +static ssize_t udg_sysfs_max_inter_stroke_time_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long input; + + retval = sstrtoul(buf, 10, &input); + if (retval) + return retval; + + retval = udg_read_tuning_params(); + if (retval < 0) + return retval; + + udg->tuning.inter_stroke_lsb = (unsigned char)(input >> 0); + udg->tuning.inter_stroke_msb = (unsigned char)(input >> 8); + + retval = udg_write_tuning_params(); + if (retval < 0) + return retval; + + return count; +} + +static int udg_ctrl_subpacket(unsigned char ctrlreg, + unsigned char subpacket, + struct synaptics_rmi4_f12_query_5 *query_5) +{ + int retval; + unsigned char cnt; + unsigned char regnum; + unsigned char bitnum; + unsigned char q5_index; + unsigned char q6_index; + unsigned char offset; + unsigned char max_ctrlreg; + unsigned char *query_6; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + max_ctrlreg = (sizeof(query_5->data) - 1) * 8 - 1; + + if (ctrlreg > max_ctrlreg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Control register number (%d) over limit\n", + __func__, ctrlreg); + return -EINVAL; + } + + q5_index = ctrlreg / 8 + 1; + bitnum = ctrlreg % 8; + if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Control %d is not present\n", + __func__, ctrlreg); + return -EINVAL; + } + + query_6 = kmalloc(query_5->size_of_query6, GFP_KERNEL); + if (!query_6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query 6\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 6, + query_6, + query_5->size_of_query6); + if (retval < 0) + goto exit; + + q6_index = 0; + + for (regnum = 0; regnum < ctrlreg; regnum++) { + q5_index = regnum / 8 + 1; + bitnum = regnum % 8; + if ((query_5->data[q5_index] & (1 << bitnum)) == 0x00) + continue; + + if (query_6[q6_index] == 0x00) + q6_index += 3; + else + q6_index++; + + while (query_6[q6_index] & ~MASK_7BIT) + q6_index++; + + q6_index++; + } + + cnt = 0; + q6_index++; + offset = subpacket / 7; + bitnum = subpacket % 7; + + do { + if (cnt == offset) { + if (query_6[q6_index + cnt] & (1 << bitnum)) + retval = 1; + else + retval = 0; + goto exit; + } + cnt++; + } while (query_6[q6_index + cnt - 1] & ~MASK_7BIT); + + retval = 0; + +exit: + kfree(query_6); + + return retval; +} + +static int udg_read_tuning_params(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_18, + udg->ctrl_buf, + udg->ctrl_18_sub10_off + sizeof(struct udg_tuning)); + if (retval < 0) + return retval; + + secure_memcpy(udg->tuning.data, + sizeof(udg->tuning.data), + (unsigned char *)&udg->ctrl_buf[udg->ctrl_18_sub10_off], + sizeof(struct udg_tuning), + sizeof(struct udg_tuning)); + + return 0; +} + +static int udg_write_tuning_params(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + secure_memcpy((unsigned char *)&udg->ctrl_buf[udg->ctrl_18_sub10_off], + sizeof(struct udg_tuning), + udg->tuning.data, + sizeof(udg->tuning.data), + sizeof(struct udg_tuning)); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_18, + udg->ctrl_buf, + udg->ctrl_18_sub10_off + sizeof(struct udg_tuning)); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_detection_enable(bool enable) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_20, + udg->ctrl_buf, + udg->ctrl_20_sub1_off + 1); + if (retval < 0) + return retval; + + if (enable) + udg->ctrl_buf[udg->ctrl_20_sub1_off] = WAKEUP_GESTURE_MODE; + else + udg->ctrl_buf[udg->ctrl_20_sub1_off] = udg->report_flags; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_20, + udg->ctrl_buf, + udg->ctrl_20_sub1_off + 1); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_engine_enable(bool enable) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (enable) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[udg->ctrl_27_sub5_off] |= + (1 << CTRL27_UDG_ENABLE_BIT); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + + udg->ctrl_buf[udg->ctrl_27_sub5_off] &= + ~(1 << CTRL27_UDG_ENABLE_BIT); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_27, + udg->ctrl_buf, + udg->ctrl_27_sub5_off + 1); + if (retval < 0) + return retval; + } + + return 0; +} + +static void udg_report(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + atomic_set(&udg->attn_event, 1); + + if (rmi4_data->suspend) { + if (rmi4_data->gesture_detection[0] == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.data_4, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read gesture detection\n", + __func__); + return; + } + } + + udg->detection_status = rmi4_data->gesture_detection[0]; + rmi4_data->gesture_detection[0] = 0; + + if (udg->detection_status == DETECTION) { + input_report_key(udg->udg_dev, KEY_WAKEUP, 1); + input_sync(udg->udg_dev); + input_report_key(udg->udg_dev, KEY_WAKEUP, 0); + input_sync(udg->udg_dev); + rmi4_data->suspend = false; + } + } + + return; +} + +static int udg_set_index(unsigned char index) +{ + int retval; + struct synaptics_rmi4_f12_control_41 control_41; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + if (index >= udg->max_num_templates) + return -EINVAL; + + udg->template_index = index; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + control_41.template_index = udg->template_index; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.ctrl_41, + control_41.data, + sizeof(control_41.data)); + if (retval < 0) + return retval; + + return 0; +} + +#ifdef STORE_GESTURES +static int udg_read_valid_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_flags, + udg->valid_buf, + sizeof(udg->valid_buf)); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_write_valid_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_flags, + udg->valid_buf, + sizeof(udg->valid_buf)); + if (retval < 0) + return retval; + + return 0; +} + +static int udg_read_template_data(unsigned char index) +{ + int retval; + unsigned char *storage; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + udg_set_index(index); + storage = &(udg->storage_buf[index * udg->template_data_size]); + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.template_data, + storage, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read template data\n", + __func__); + return retval; + } + + return 0; +} + +static int udg_write_template_data(void) +{ + int retval; + unsigned char ii; + unsigned char *storage; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + for (ii = 0; ii < udg->gestures_to_store; ii++) { + udg_set_index(ii); + storage = &(udg->storage_buf[ii * udg->template_data_size]); + + retval = synaptics_rmi4_reg_write(rmi4_data, + udg->addr.template_data, + storage, + udg->template_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write template data\n", + __func__); + return retval; + } + } + + return 0; +} +#endif + +static int udg_reg_init(void) +{ + int retval; + unsigned char ii; + unsigned char data_offset; + unsigned char size_of_query; + unsigned char ctrl_18_offset; + unsigned char ctrl_20_offset; + unsigned char ctrl_23_offset; + unsigned char ctrl_27_offset; + unsigned char ctrl_41_offset; + struct synaptics_rmi4_f12_query_0 query_0; + struct synaptics_rmi4_f12_query_5 query_5; + struct synaptics_rmi4_f12_query_8 query_8; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 7, + &size_of_query, + sizeof(size_of_query)); + if (retval < 0) + return retval; + + if (size_of_query < 4) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: User defined gesture support unavailable (missing data registers)\n", + __func__); + retval = -ENODEV; + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 8, + query_8.data, + sizeof(query_8.data)); + if (retval < 0) + return retval; + + if ((query_8.data16_is_present) && + (query_8.data17_is_present) && + (query_8.data18_is_present) && + (query_8.data19_is_present) && + (query_8.data20_is_present) && + (query_8.data21_is_present)) { + data_offset = query_8.data0_is_present + + query_8.data1_is_present + + query_8.data2_is_present + + query_8.data3_is_present; + udg->addr.data_4 = udg->data_base_addr + data_offset; + data_offset = data_offset + + query_8.data4_is_present + + query_8.data5_is_present + + query_8.data6_is_present + + query_8.data7_is_present + + query_8.data8_is_present + + query_8.data9_is_present + + query_8.data10_is_present + + query_8.data11_is_present + + query_8.data12_is_present + + query_8.data13_is_present + + query_8.data14_is_present + + query_8.data15_is_present; + udg->addr.trace_x = udg->data_base_addr + data_offset; + udg->addr.trace_y = udg->addr.trace_x + 1; + udg->addr.trace_segment = udg->addr.trace_y + 1; + udg->addr.template_helper = udg->addr.trace_segment + 1; + udg->addr.template_data = udg->addr.template_helper + 1; + udg->addr.template_flags = udg->addr.template_data + 1; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: User defined gesture support unavailable (missing data registers)\n", + __func__); + retval = -ENODEV; + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 4, + &size_of_query, + sizeof(size_of_query)); + if (retval < 0) + return retval; + + if (size_of_query < 7) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: User defined gesture support unavailable (missing control registers)\n", + __func__); + retval = -ENODEV; + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 5, + query_5.data, + sizeof(query_5.data)); + if (retval < 0) + return retval; + + ctrl_18_offset = query_5.ctrl0_is_present + + query_5.ctrl1_is_present + + query_5.ctrl2_is_present + + query_5.ctrl3_is_present + + query_5.ctrl4_is_present + + query_5.ctrl5_is_present + + query_5.ctrl6_is_present + + query_5.ctrl7_is_present + + query_5.ctrl8_is_present + + query_5.ctrl9_is_present + + query_5.ctrl10_is_present + + query_5.ctrl11_is_present + + query_5.ctrl12_is_present + + query_5.ctrl13_is_present + + query_5.ctrl14_is_present + + query_5.ctrl15_is_present + + query_5.ctrl16_is_present + + query_5.ctrl17_is_present; + + ctrl_20_offset = ctrl_18_offset + + query_5.ctrl18_is_present + + query_5.ctrl19_is_present; + + ctrl_23_offset = ctrl_20_offset + + query_5.ctrl20_is_present + + query_5.ctrl21_is_present + + query_5.ctrl22_is_present; + + ctrl_27_offset = ctrl_23_offset+ + query_5.ctrl23_is_present + + query_5.ctrl24_is_present + + query_5.ctrl25_is_present + + query_5.ctrl26_is_present; + + ctrl_41_offset = ctrl_27_offset+ + query_5.ctrl27_is_present + + query_5.ctrl28_is_present + + query_5.ctrl29_is_present + + query_5.ctrl30_is_present + + query_5.ctrl31_is_present + + query_5.ctrl32_is_present + + query_5.ctrl33_is_present + + query_5.ctrl34_is_present + + query_5.ctrl35_is_present + + query_5.ctrl36_is_present + + query_5.ctrl37_is_present + + query_5.ctrl38_is_present + + query_5.ctrl39_is_present + + query_5.ctrl40_is_present; + + udg->addr.ctrl_18 = udg->control_base_addr + ctrl_18_offset; + udg->addr.ctrl_20 = udg->control_base_addr + ctrl_20_offset; + udg->addr.ctrl_23 = udg->control_base_addr + ctrl_23_offset; + udg->addr.ctrl_27 = udg->control_base_addr + ctrl_27_offset; + udg->addr.ctrl_41 = udg->control_base_addr + ctrl_41_offset; + + udg->ctrl_18_sub10_off = 0; + for (ii = 0; ii < 10; ii++) { + retval = udg_ctrl_subpacket(18, ii, &query_5); + if (retval == 1) + udg->ctrl_18_sub10_off += ctrl_18_sub_size[ii]; + else if (retval < 0) + return retval; + } + + udg->ctrl_20_sub1_off = 0; + for (ii = 0; ii < 1; ii++) { + retval = udg_ctrl_subpacket(20, ii, &query_5); + if (retval == 1) + udg->ctrl_20_sub1_off += ctrl_20_sub_size[ii]; + else if (retval < 0) + return retval; + } + + udg->ctrl_23_sub3_off = 0; + for (ii = 0; ii < 3; ii++) { + retval = udg_ctrl_subpacket(23, ii, &query_5); + if (retval == 1) + udg->ctrl_23_sub3_off += ctrl_23_sub_size[ii]; + else if (retval < 0) + return retval; + } + + retval = udg_ctrl_subpacket(23, 3, &query_5); + if (retval == 0) + udg->ctrl_23_sub3_off = 0; + else if (retval < 0) + return retval; + + udg->ctrl_27_sub5_off = 0; + for (ii = 0; ii < 5; ii++) { + retval = udg_ctrl_subpacket(27, ii, &query_5); + if (retval == 1) + udg->ctrl_27_sub5_off += ctrl_27_sub_size[ii]; + else if (retval < 0) + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->query_base_addr + 0, + query_0.data, + sizeof(query_0.data)); + if (retval < 0) + return retval; + + udg->max_num_templates = query_0.max_num_templates; + udg->template_size = + ((unsigned short)query_0.template_size_lsb << 0) | + ((unsigned short)query_0.template_size_msb << 8); + udg->template_data_size = udg->template_size * 4 * 2 + 4 + 1; + +#ifdef STORE_GESTURES + udg->gestures_to_store = udg->max_num_templates; + if (GESTURES_TO_STORE < udg->gestures_to_store) + udg->gestures_to_store = GESTURES_TO_STORE; +#endif + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_20, + udg->ctrl_buf, + udg->ctrl_20_sub1_off + 1); + if (retval < 0) + return retval; + + udg->report_flags = udg->ctrl_buf[udg->ctrl_20_sub1_off]; + + retval = synaptics_rmi4_reg_read(rmi4_data, + udg->addr.ctrl_23, + udg->ctrl_buf, + udg->ctrl_23_sub3_off + 1); + if (retval < 0) + return retval; + + udg->object_type_enable1 = udg->ctrl_buf[0]; + if (udg->ctrl_23_sub3_off) + udg->object_type_enable2 = udg->ctrl_buf[udg->ctrl_23_sub3_off]; + + return retval; +} + +static int udg_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char page; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + struct synaptics_rmi4_fn_desc fd; + struct synaptics_rmi4_data *rmi4_data = udg->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&fd, + sizeof(fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, fd.fn_number); + switch (fd.fn_number) { + case SYNAPTICS_RMI4_F12: + goto f12_found; + break; + } + } else { + break; + } + + intr_count += fd.intr_src_count; + } + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F12\n", + __func__); + return -EINVAL; + +f12_found: + udg->query_base_addr = fd.query_base_addr | (page << 8); + udg->control_base_addr = fd.ctrl_base_addr | (page << 8); + udg->data_base_addr = fd.data_base_addr | (page << 8); + udg->command_base_addr = fd.cmd_base_addr | (page << 8); + + retval = udg_reg_init(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize user defined gesture registers\n", + __func__); + return retval; + } + + udg->intr_mask = 0; + intr_src = fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + udg->intr_mask |= 1 << ii; + } + + rmi4_data->intr_mask[0] |= udg->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &rmi4_data->intr_mask[0], + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static void synaptics_rmi4_udg_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!udg) + return; + + if (udg->intr_mask & intr_mask) + udg_report(); + + return; +} + +static int synaptics_rmi4_udg_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char size; + unsigned char attr_count; + unsigned char param_count; + + if (udg) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + udg = kzalloc(sizeof(*udg), GFP_KERNEL); + if (!udg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for udg\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + size = 0; + for (ii = 0; ii < sizeof(ctrl_18_sub_size); ii++) + size += ctrl_18_sub_size[ii]; + size += sizeof(struct udg_tuning); + udg->ctrl_buf = kzalloc(size, GFP_KERNEL); + if (!udg->ctrl_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_buf\n", + __func__); + retval = -ENOMEM; + goto exit_free_udg; + } + + udg->rmi4_data = rmi4_data; + + retval = udg_scan_pdt(); + if (retval < 0) + goto exit_free_ctrl_buf; + + udg->template_data_buf = kzalloc(udg->template_data_size, GFP_KERNEL); + if (!udg->template_data_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for template_data_buf\n", + __func__); + retval = -ENOMEM; + goto exit_free_ctrl_buf; + } + +#ifdef STORE_GESTURES + udg->storage_buf = kzalloc( + udg->template_data_size * udg->gestures_to_store, + GFP_KERNEL); + if (!udg->storage_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for storage_buf\n", + __func__); + kfree(udg->template_data_buf); + retval = -ENOMEM; + goto exit_free_ctrl_buf; + } +#endif + + udg->udg_dev = input_allocate_device(); + if (udg->udg_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate gesture device\n", + __func__); + retval = -ENOMEM; + goto exit_free_template_data_buf; + } + + udg->udg_dev->name = GESTURE_DRIVER_NAME; + udg->udg_dev->phys = GESTURE_PHYS_NAME; + udg->udg_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + udg->udg_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + udg->udg_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(udg->udg_dev, rmi4_data); + + set_bit(EV_KEY, udg->udg_dev->evbit); + set_bit(KEY_WAKEUP, udg->udg_dev->keybit); + input_set_capability(udg->udg_dev, EV_KEY, KEY_WAKEUP); + + retval = input_register_device(udg->udg_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register gesture device\n", + __func__); + input_free_device(udg->udg_dev); + goto exit_free_template_data_buf; + } + + udg->tuning_dir = kobject_create_and_add(TUNING_SYSFS_DIR_NAME, + &udg->udg_dev->dev.kobj); + if (!udg->tuning_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create tuning sysfs directory\n", + __func__); + goto exit_unregister_input_device; + } + + retval = sysfs_create_bin_file(&udg->udg_dev->dev.kobj, &template_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create template data bin file\n", + __func__); + goto exit_remove_sysfs_directory; + } + + retval = sysfs_create_bin_file(&udg->udg_dev->dev.kobj, &trace_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create trace data bin file\n", + __func__); + goto exit_remove_bin_file; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&udg->udg_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + + for (param_count = 0; param_count < ARRAY_SIZE(params); param_count++) { + retval = sysfs_create_file(udg->tuning_dir, + ¶ms[param_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create tuning parameters\n", + __func__); + retval = -ENODEV; + goto exit_remove_params; + } + } + + retval = udg_engine_enable(true); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable gesture engine\n", + __func__); + goto exit_remove_params; + } + + return 0; + +exit_remove_params: + for (param_count--; param_count >= 0; param_count--) { + sysfs_remove_file(udg->tuning_dir, + ¶ms[param_count].attr); + } + +exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&udg->udg_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &trace_data); + +exit_remove_bin_file: + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &template_data); + +exit_remove_sysfs_directory: + kobject_put(udg->tuning_dir); + +exit_unregister_input_device: + input_unregister_device(udg->udg_dev); + +exit_free_template_data_buf: +#ifdef STORE_GESTURES + kfree(udg->storage_buf); +#endif + kfree(udg->template_data_buf); + +exit_free_ctrl_buf: + kfree(udg->ctrl_buf); + +exit_free_udg: + kfree(udg); + udg = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_udg_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char count; + + if (!udg) + goto exit; + + for (count = 0; count < ARRAY_SIZE(params); count++) { + sysfs_remove_file(udg->tuning_dir, + ¶ms[count].attr); + } + + for (count = 0; count < ARRAY_SIZE(attrs); count++) { + sysfs_remove_file(&udg->udg_dev->dev.kobj, + &attrs[count].attr); + } + + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &trace_data); + sysfs_remove_bin_file(&udg->udg_dev->dev.kobj, &template_data); + kobject_put(udg->tuning_dir); + + input_unregister_device(udg->udg_dev); +#ifdef STORE_GESTURES + kfree(udg->storage_buf); +#endif + kfree(udg->template_data_buf); + kfree(udg->trace_data_buf); + kfree(udg->ctrl_buf); + kfree(udg); + udg = NULL; + +exit: + complete(&udg_remove_complete); + + return; +} + +static void synaptics_rmi4_udg_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) { + synaptics_rmi4_udg_init(rmi4_data); + return; + } + + udg_scan_pdt(); + udg_engine_enable(true); +#ifdef STORE_GESTURES + udg_write_template_data(); + udg_write_valid_data(); +#endif + + return; +} + +static void synaptics_rmi4_udg_reinit(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + udg_engine_enable(true); +#ifdef STORE_GESTURES + udg_write_template_data(); + udg_write_valid_data(); +#endif + + return; +} + +static void synaptics_rmi4_udg_e_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + rmi4_data->sleep_enable(rmi4_data, false); + rmi4_data->irq_enable(rmi4_data, true, false); + enable_irq_wake(rmi4_data->irq); + + udg_engine_enable(true); + udg_detection_enable(true); + + return; +} + +static void synaptics_rmi4_udg_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + rmi4_data->sleep_enable(rmi4_data, false); + rmi4_data->irq_enable(rmi4_data, true, false); + enable_irq_wake(rmi4_data->irq); + + udg_engine_enable(true); + udg_detection_enable(true); + + return; +} + +static void synaptics_rmi4_udg_resume(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + disable_irq_wake(rmi4_data->irq); + udg_detection_enable(false); + + return; +} + +static void synaptics_rmi4_udg_l_resume(struct synaptics_rmi4_data *rmi4_data) +{ + if (!udg) + return; + + disable_irq_wake(rmi4_data->irq); + udg_detection_enable(false); + + return; +} + +static struct synaptics_rmi4_exp_fn gesture_module = { + .fn_type = RMI_GESTURE, + .init = synaptics_rmi4_udg_init, + .remove = synaptics_rmi4_udg_remove, + .reset = synaptics_rmi4_udg_reset, + .reinit = synaptics_rmi4_udg_reinit, + .early_suspend = synaptics_rmi4_udg_e_suspend, + .suspend = synaptics_rmi4_udg_suspend, + .resume = synaptics_rmi4_udg_resume, + .late_resume = synaptics_rmi4_udg_l_resume, + .attn = synaptics_rmi4_udg_attn, +}; + +static int __init rmi4_gesture_module_init(void) +{ + synaptics_rmi4_new_function(&gesture_module, true); + + return 0; +} + +static void __exit rmi4_gesture_module_exit(void) +{ + synaptics_rmi4_new_function(&gesture_module, false); + + wait_for_completion(&udg_remove_complete); + + return; +} + +module_init(rmi4_gesture_module_init); +module_exit(rmi4_gesture_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX User Defined Gesture Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_i2c.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_i2c.c new file mode 100755 index 0000000000000..993fb61603412 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_i2c.c @@ -0,0 +1,649 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYN_I2C_RETRY_TIMES 10 + +/* +#define I2C_BURST_LIMIT 255 +*/ +/* +#define XFER_MSGS_LIMIT 8 +*/ + +static unsigned char *wr_buf; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_i2c_device; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,rst-gpio", 0, + NULL); +printk("reset gpio : %d\n", bdata->reset_gpio); + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int synaptics_rmi4_i2c_alloc_buf(struct synaptics_rmi4_data *rmi4_data, + unsigned int count) +{ + static unsigned int buf_size; + + if (count > buf_size) { + if (buf_size) + kfree(wr_buf); + wr_buf = kzalloc(count, GFP_KERNEL); + if (!wr_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buffer\n", + __func__); + buf_size = 0; + return -ENOMEM; + } + buf_size = count; + } + + return 0; +} + +static void synaptics_rmi4_i2c_check_addr(struct synaptics_rmi4_data *rmi4_data, + struct i2c_client *i2c) +{ + if (hw_if.board_data->ub_i2c_addr == -1) + return; + + if (hw_if.board_data->i2c_addr == i2c->addr) + hw_if.board_data->i2c_addr = hw_if.board_data->ub_i2c_addr; + else + hw_if.board_data->i2c_addr = i2c->addr; + + return; +} + +static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr) +{ + int retval; + unsigned char retry; + unsigned char buf[PAGE_SELECT_LEN]; + unsigned char page; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = PAGE_SELECT_LEN; + msg[0].buf = buf; + + page = ((addr >> 8) & MASK_8BIT); + buf[0] = MASK_8BIT; + buf[1] = page; + + if (page != rmi4_data->current_page) { + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(i2c->adapter, msg, 1) == 1) { + rmi4_data->current_page = page; + retval = PAGE_SELECT_LEN; + break; + } + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + msg[0].addr = hw_if.board_data->i2c_addr; + } + } + } else { + retval = PAGE_SELECT_LEN; + } + + return retval; +} + +static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + unsigned char buf; +#ifdef I2C_BURST_LIMIT + unsigned int ii; + unsigned int rd_msgs = ((length - 1) / I2C_BURST_LIMIT) + 1; +#else + unsigned int rd_msgs = 1; +#endif + unsigned char index = 0; + unsigned char xfer_msgs; + unsigned char remaining_msgs; + unsigned short i2c_addr; + unsigned short data_offset = 0; + unsigned int remaining_length = length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_adapter *adap = i2c->adapter; + struct i2c_msg msg[rd_msgs + 1]; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + retval = -EIO; + goto exit; + } + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &buf; + +#ifdef I2C_BURST_LIMIT + for (ii = 0; ii < (rd_msgs - 1); ii++) { + msg[ii + 1].addr = hw_if.board_data->i2c_addr; + msg[ii + 1].flags = I2C_M_RD; + msg[ii + 1].len = I2C_BURST_LIMIT; + msg[ii + 1].buf = &data[data_offset]; + data_offset += I2C_BURST_LIMIT; + remaining_length -= I2C_BURST_LIMIT; + } +#endif + + msg[rd_msgs].addr = hw_if.board_data->i2c_addr; + msg[rd_msgs].flags = I2C_M_RD; + msg[rd_msgs].len = (unsigned short)remaining_length; + msg[rd_msgs].buf = &data[data_offset]; + + buf = addr & MASK_8BIT; + + remaining_msgs = rd_msgs + 1; + + while (remaining_msgs) { +#ifdef XFER_MSGS_LIMIT + if (remaining_msgs > XFER_MSGS_LIMIT) + xfer_msgs = XFER_MSGS_LIMIT; + else + xfer_msgs = remaining_msgs; +#else + xfer_msgs = remaining_msgs; +#endif + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + retval = i2c_transfer(adap, &msg[index], xfer_msgs); + if (retval == xfer_msgs) + break; + + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + i2c_addr = hw_if.board_data->i2c_addr; + msg[0].addr = i2c_addr; +#ifdef I2C_BURST_LIMIT + for (ii = 0; ii < (rd_msgs - 1); ii++) + msg[ii + 1].addr = i2c_addr; +#endif + msg[rd_msgs].addr = i2c_addr; + } + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C read over retry limit\n", + __func__); + retval = -EIO; + goto exit; + } + + remaining_msgs -= xfer_msgs; + index += xfer_msgs; + } + + retval = length; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + + retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1); + if (retval < 0) + return retval; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + retval = -EIO; + goto exit; + } + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = (unsigned short)(length + 1); + msg[0].buf = wr_buf; + + wr_buf[0] = addr & MASK_8BIT; + retval = secure_memcpy(&wr_buf[1], length, &data[0], length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + goto exit; + } + + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(i2c->adapter, msg, 1) == 1) { + retval = length; + break; + } + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + msg[0].addr = hw_if.board_data->i2c_addr; + } + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C write over retry limit\n", + __func__); + retval = -EIO; + } + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_I2C, + .read = synaptics_rmi4_i2c_read, + .write = synaptics_rmi4_i2c_write, +}; + +static void synaptics_rmi4_i2c_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_i2c_device); + + return; +} + +static int synaptics_rmi4_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int retval; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "%s: SMBus byte data commands not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_i2c_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_i2c_device) { + dev_err(&client->dev, + "%s: Failed to allocate memory for synaptics_dsx_i2c_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (client->dev.of_node) { + hw_if.board_data = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&client->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&client->dev, hw_if.board_data); + } +#else + hw_if.board_data = client->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + hw_if.board_data->i2c_addr = client->addr; + + synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_i2c_device->id = 0; + synaptics_dsx_i2c_device->num_resources = 0; + synaptics_dsx_i2c_device->dev.parent = &client->dev; + synaptics_dsx_i2c_device->dev.platform_data = &hw_if; + synaptics_dsx_i2c_device->dev.release = synaptics_rmi4_i2c_dev_release; + + retval = platform_device_register(synaptics_dsx_i2c_device); + if (retval) { + dev_err(&client->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_i2c_remove(struct i2c_client *client) +{ + platform_device_unregister(synaptics_dsx_i2c_device); + + return 0; +} + +static const struct i2c_device_id synaptics_rmi4_id_table[] = { + {I2C_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics,dsx-i2c", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct i2c_driver synaptics_rmi4_i2c_driver = { + .driver = { + .name = I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_i2c_probe, + .remove = synaptics_rmi4_i2c_remove, + .id_table = synaptics_rmi4_id_table, +}; + +int synaptics_rmi4_bus_init(void) +{ + return i2c_add_driver(&synaptics_rmi4_i2c_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init); + +void synaptics_rmi4_bus_exit(void) +{ + kfree(wr_buf); + + i2c_del_driver(&synaptics_rmi4_i2c_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_proximity.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_proximity.c new file mode 100755 index 0000000000000..67d9e0a094551 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_proximity.c @@ -0,0 +1,692 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define PROX_PHYS_NAME "synaptics_dsx/proximity" + +#define HOVER_Z_MAX (255) + +#define HOVERING_FINGER_EN (1 << 4) + +static ssize_t synaptics_rmi4_hover_finger_en_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_hover_finger_en_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static struct device_attribute attrs[] = { + __ATTR(hover_finger_en, (S_IRUGO | S_IWUGO), + synaptics_rmi4_hover_finger_en_show, + synaptics_rmi4_hover_finger_en_store), +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + }; + unsigned char data[2]; + }; +}; + +struct prox_finger_data { + union { + struct { + unsigned char object_type_and_status; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; + unsigned char z; + } __packed; + unsigned char proximity_data[6]; + }; +}; + +struct synaptics_rmi4_prox_handle { + bool hover_finger_present; + bool hover_finger_en; + unsigned char intr_mask; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short hover_finger_en_addr; + unsigned short hover_finger_data_addr; + struct input_dev *prox_dev; + struct prox_finger_data *finger_data; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_prox_handle *prox; + +DECLARE_COMPLETION(prox_remove_complete); + +static void prox_hover_finger_lift(void) +{ + input_report_key(prox->prox_dev, BTN_TOUCH, 0); + input_report_key(prox->prox_dev, BTN_TOOL_FINGER, 0); + input_sync(prox->prox_dev); + prox->hover_finger_present = false; + + return; +} + +static void prox_hover_finger_report(void) +{ + int retval; + int x; + int y; + int z; + struct prox_finger_data *data; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + data = prox->finger_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->hover_finger_data_addr, + data->proximity_data, + sizeof(data->proximity_data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read hovering finger data\n", + __func__); + return; + } + + if (data->object_type_and_status != F12_HOVERING_FINGER_STATUS) { + if (prox->hover_finger_present) + prox_hover_finger_lift(); + + return; + } + + x = (data->x_msb << 8) | (data->x_lsb); + y = (data->y_msb << 8) | (data->y_lsb); + z = HOVER_Z_MAX - data->z; + + input_report_key(prox->prox_dev, BTN_TOUCH, 0); + input_report_key(prox->prox_dev, BTN_TOOL_FINGER, 1); + input_report_abs(prox->prox_dev, ABS_X, x); + input_report_abs(prox->prox_dev, ABS_Y, y); + input_report_abs(prox->prox_dev, ABS_DISTANCE, z); + + input_sync(prox->prox_dev); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: x = %d y = %d z = %d\n", + __func__, x, y, z); + + prox->hover_finger_present = true; + + return; +} + +static int prox_set_hover_finger_en(void) +{ + int retval; + unsigned char object_report_enable; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->hover_finger_en_addr, + &object_report_enable, + sizeof(object_report_enable)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read from object report enable register\n", + __func__); + return retval; + } + + if (prox->hover_finger_en) + object_report_enable |= HOVERING_FINGER_EN; + else + object_report_enable &= ~HOVERING_FINGER_EN; + + retval = synaptics_rmi4_reg_write(rmi4_data, + prox->hover_finger_en_addr, + &object_report_enable, + sizeof(object_report_enable)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write to object report enable register\n", + __func__); + return retval; + } + + return 0; +} + +static void prox_set_params(void) +{ + input_set_abs_params(prox->prox_dev, ABS_X, 0, + prox->rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(prox->prox_dev, ABS_Y, 0, + prox->rmi4_data->sensor_max_y, 0, 0); + input_set_abs_params(prox->prox_dev, ABS_DISTANCE, 0, + HOVER_Z_MAX, 0, 0); + + return; +} + +static int prox_reg_init(void) +{ + int retval; + unsigned char ctrl_23_offset; + unsigned char data_1_offset; + struct synaptics_rmi4_f12_query_5 query_5; + struct synaptics_rmi4_f12_query_8 query_8; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->query_base_addr + 5, + query_5.data, + sizeof(query_5.data)); + if (retval < 0) + return retval; + + ctrl_23_offset = query_5.ctrl0_is_present + + query_5.ctrl1_is_present + + query_5.ctrl2_is_present + + query_5.ctrl3_is_present + + query_5.ctrl4_is_present + + query_5.ctrl5_is_present + + query_5.ctrl6_is_present + + query_5.ctrl7_is_present + + query_5.ctrl8_is_present + + query_5.ctrl9_is_present + + query_5.ctrl10_is_present + + query_5.ctrl11_is_present + + query_5.ctrl12_is_present + + query_5.ctrl13_is_present + + query_5.ctrl14_is_present + + query_5.ctrl15_is_present + + query_5.ctrl16_is_present + + query_5.ctrl17_is_present + + query_5.ctrl18_is_present + + query_5.ctrl19_is_present + + query_5.ctrl20_is_present + + query_5.ctrl21_is_present + + query_5.ctrl22_is_present; + + prox->hover_finger_en_addr = prox->control_base_addr + ctrl_23_offset; + + retval = synaptics_rmi4_reg_read(rmi4_data, + prox->query_base_addr + 8, + query_8.data, + sizeof(query_8.data)); + if (retval < 0) + return retval; + + data_1_offset = query_8.data0_is_present; + prox->hover_finger_data_addr = prox->data_base_addr + data_1_offset; + + return retval; +} + +static int prox_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char page; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + struct synaptics_rmi4_fn_desc fd; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&fd, + sizeof(fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, fd.fn_number); + switch (fd.fn_number) { + case SYNAPTICS_RMI4_F12: + goto f12_found; + break; + } + } else { + break; + } + + intr_count += fd.intr_src_count; + } + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F12\n", + __func__); + return -EINVAL; + +f12_found: + prox->query_base_addr = fd.query_base_addr | (page << 8); + prox->control_base_addr = fd.ctrl_base_addr | (page << 8); + prox->data_base_addr = fd.data_base_addr | (page << 8); + prox->command_base_addr = fd.cmd_base_addr | (page << 8); + + retval = prox_reg_init(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize proximity registers\n", + __func__); + return retval; + } + + prox->intr_mask = 0; + intr_src = fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + prox->intr_mask |= 1 << ii; + } + + rmi4_data->intr_mask[0] |= prox->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static ssize_t synaptics_rmi4_hover_finger_en_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (!prox) + return -ENODEV; + + return snprintf(buf, PAGE_SIZE, "%u\n", + prox->hover_finger_en); +} + +static ssize_t synaptics_rmi4_hover_finger_en_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; + + if (!prox) + return -ENODEV; + + if (sscanf(buf, "%x", &input) != 1) + return -EINVAL; + + if (input == 1) + prox->hover_finger_en = true; + else if (input == 0) + prox->hover_finger_en = false; + else + return -EINVAL; + + retval = prox_set_hover_finger_en(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change hovering finger enable setting\n", + __func__); + return retval; + } + + return count; +} + +int synaptics_rmi4_prox_hover_finger_en(bool enable) +{ + int retval; + + if (!prox) + return -ENODEV; + + prox->hover_finger_en = enable; + + retval = prox_set_hover_finger_en(); + if (retval < 0) + return retval; + + return 0; +} +EXPORT_SYMBOL(synaptics_rmi4_prox_hover_finger_en); + +static void synaptics_rmi4_prox_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!prox) + return; + + if (prox->intr_mask & intr_mask) + prox_hover_finger_report(); + + return; +} + +static int synaptics_rmi4_prox_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + + if (prox) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + prox = kzalloc(sizeof(*prox), GFP_KERNEL); + if (!prox) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for prox\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + prox->finger_data = kzalloc(sizeof(*(prox->finger_data)), GFP_KERNEL); + if (!prox->finger_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for finger_data\n", + __func__); + retval = -ENOMEM; + goto exit_free_prox; + } + + prox->rmi4_data = rmi4_data; + + retval = prox_scan_pdt(); + if (retval < 0) + goto exit_free_finger_data; + + prox->hover_finger_en = true; + + retval = prox_set_hover_finger_en(); + if (retval < 0) + return retval; + + prox->prox_dev = input_allocate_device(); + if (prox->prox_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate proximity device\n", + __func__); + retval = -ENOMEM; + goto exit_free_finger_data; + } + + prox->prox_dev->name = PROXIMITY_DRIVER_NAME; + prox->prox_dev->phys = PROX_PHYS_NAME; + prox->prox_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + prox->prox_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + prox->prox_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(prox->prox_dev, rmi4_data); + + set_bit(EV_KEY, prox->prox_dev->evbit); + set_bit(EV_ABS, prox->prox_dev->evbit); + set_bit(BTN_TOUCH, prox->prox_dev->keybit); + set_bit(BTN_TOOL_FINGER, prox->prox_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, prox->prox_dev->propbit); +#endif + + prox_set_params(); + + retval = input_register_device(prox->prox_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register proximity device\n", + __func__); + goto exit_free_input_device; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit_free_sysfs; + } + } + + return 0; + +exit_free_sysfs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + input_unregister_device(prox->prox_dev); + prox->prox_dev = NULL; + +exit_free_input_device: + if (prox->prox_dev) + input_free_device(prox->prox_dev); + +exit_free_finger_data: + kfree(prox->finger_data); + +exit_free_prox: + kfree(prox); + prox = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_prox_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!prox) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + input_unregister_device(prox->prox_dev); + kfree(prox->finger_data); + kfree(prox); + prox = NULL; + +exit: + complete(&prox_remove_complete); + + return; +} + +static void synaptics_rmi4_prox_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) { + synaptics_rmi4_prox_init(rmi4_data); + return; + } + + prox_hover_finger_lift(); + + prox_scan_pdt(); + + prox_set_hover_finger_en(); + + return; +} + +static void synaptics_rmi4_prox_reinit(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) + return; + + prox_hover_finger_lift(); + + prox_set_hover_finger_en(); + + return; +} + +static void synaptics_rmi4_prox_e_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) + return; + + prox_hover_finger_lift(); + + return; +} + +static void synaptics_rmi4_prox_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + if (!prox) + return; + + prox_hover_finger_lift(); + + return; +} + +static struct synaptics_rmi4_exp_fn proximity_module = { + .fn_type = RMI_PROXIMITY, + .init = synaptics_rmi4_prox_init, + .remove = synaptics_rmi4_prox_remove, + .reset = synaptics_rmi4_prox_reset, + .reinit = synaptics_rmi4_prox_reinit, + .early_suspend = synaptics_rmi4_prox_e_suspend, + .suspend = synaptics_rmi4_prox_suspend, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_prox_attn, +}; + +static int __init rmi4_proximity_module_init(void) +{ + synaptics_rmi4_new_function(&proximity_module, true); + + return 0; +} + +static void __exit rmi4_proximity_module_exit(void) +{ + synaptics_rmi4_new_function(&proximity_module, false); + + wait_for_completion(&prox_remove_complete); + + return; +} + +module_init(rmi4_proximity_module_init); +module_exit(rmi4_proximity_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Proximity Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_rmi_dev.c new file mode 100755 index 0000000000000..b85ba1d94e52b --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_rmi_dev.c @@ -0,0 +1,1064 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define CHAR_DEVICE_NAME "rmi" +#define DEVICE_CLASS_NAME "rmidev" +#define SYSFS_FOLDER_NAME "rmidev" +#define DEV_NUMBER 1 +#define REG_ADDR_LIMIT 0xFFFF + +#define RMIDEV_MAJOR_NUM 0 + +static ssize_t rmidev_sysfs_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t rmidev_sysfs_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t rmidev_sysfs_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_attn_state_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_pid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_term_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_concurrent_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_concurrent_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +struct rmidev_handle { + dev_t dev_no; + pid_t pid; + unsigned char intr_mask; + unsigned char *tmpbuf; + unsigned int tmpbuf_size; + struct device dev; + struct synaptics_rmi4_data *rmi4_data; + struct kobject *sysfs_dir; + struct siginfo interrupt_signal; + struct siginfo terminate_signal; + struct task_struct *task; + void *data; + bool concurrent; +}; + +struct rmidev_data { + int ref_count; + struct cdev main_dev; + struct class *device_class; + struct mutex file_mutex; + struct rmidev_handle *rmi_dev; +}; + +static struct bin_attribute attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = rmidev_sysfs_data_show, + .write = rmidev_sysfs_data_store, +}; + +static struct device_attribute attrs[] = { + __ATTR(open, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_open_store), + __ATTR(release, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_release_store), + __ATTR(attn_state, S_IRUGO, + rmidev_sysfs_attn_state_show, + synaptics_rmi4_store_error), + __ATTR(pid, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_pid_show, + rmidev_sysfs_pid_store), + __ATTR(term, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_term_store), + __ATTR(intr_mask, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_intr_mask_show, + rmidev_sysfs_intr_mask_store), + __ATTR(concurrent, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_concurrent_show, + rmidev_sysfs_concurrent_store), +}; + +static int rmidev_major_num = RMIDEV_MAJOR_NUM; + +static struct class *rmidev_device_class; + +static struct rmidev_handle *rmidev; + +DECLARE_COMPLETION(rmidev_remove_complete); + +static irqreturn_t rmidev_sysfs_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *rmi4_data = data; + + sysfs_notify(&rmi4_data->input_dev->dev.kobj, + SYSFS_FOLDER_NAME, "attn_state"); + + return IRQ_HANDLED; +} + +static int rmidev_sysfs_irq_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval = 0; + unsigned char intr_status[MAX_INTR_REGISTERS]; + unsigned long irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT; + + mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex)); + + if (enable) { + if (rmi4_data->irq_enabled) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Interrupt already enabled\n", + __func__); + goto exit; + } + + /* Clear interrupts first */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr + 1, + intr_status, + rmi4_data->num_of_intr_regs); + if (retval < 0) + goto exit; + + retval = request_threaded_irq(rmi4_data->irq, NULL, + rmidev_sysfs_irq, irq_flags, + PLATFORM_DRIVER_NAME, rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create irq thread\n", + __func__); + goto exit; + } + + rmi4_data->irq_enabled = true; + } else { + if (rmi4_data->irq_enabled) { + disable_irq(rmi4_data->irq); + free_irq(rmi4_data->irq, rmi4_data); + rmi4_data->irq_enabled = false; + } + } + +exit: + mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex)); + + return retval; +} + +static ssize_t rmidev_sysfs_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned char intr_status = 0; + unsigned int length = (unsigned int)count; + unsigned short address = (unsigned short)pos; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (length > (REG_ADDR_LIMIT - address)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Out of register map limit\n", + __func__); + return -EINVAL; + } + + if (length) { + retval = synaptics_rmi4_reg_read(rmi4_data, + address, + (unsigned char *)buf, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data\n", + __func__); + return retval; + } + } else { + return -EINVAL; + } + + if (!rmidev->concurrent) + goto exit; + + if (address != rmi4_data->f01_data_base_addr) + goto exit; + + if (length <= 1) + goto exit; + + intr_status = buf[1]; + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & intr_status) { + rmi4_data->report_touch(rmi4_data, + fhandler); + } + } + } + } + +exit: + return length; +} + +static ssize_t rmidev_sysfs_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned int length = (unsigned int)count; + unsigned short address = (unsigned short)pos; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (length > (REG_ADDR_LIMIT - address)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Out of register map limit\n", + __func__); + return -EINVAL; + } + + if (length) { + retval = synaptics_rmi4_reg_write(rmi4_data, + address, + (unsigned char *)buf, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write data\n", + __func__); + return retval; + } + } else { + return -EINVAL; + } + + return length; +} + +static ssize_t rmidev_sysfs_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + rmi4_data->irq_enable(rmi4_data, false, false); + rmidev_sysfs_irq_enable(rmi4_data, true); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Attention interrupt disabled\n", + __func__); + + return count; +} + +static ssize_t rmidev_sysfs_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + rmidev_sysfs_irq_enable(rmi4_data, false); + + rmi4_data->reset_device(rmi4_data, false); + + rmi4_data->stay_awake = false; + + return count; +} + +static ssize_t rmidev_sysfs_attn_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int attn_state; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + attn_state = gpio_get_value(bdata->irq_gpio); + + return snprintf(buf, PAGE_SIZE, "%u\n", attn_state); +} + +static ssize_t rmidev_sysfs_pid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", rmidev->pid); +} + +static ssize_t rmidev_sysfs_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->pid = input; + + if (rmidev->pid) { + rmidev->task = pid_task(find_vpid(rmidev->pid), PIDTYPE_PID); + if (!rmidev->task) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to locate PID of data logging tool\n", + __func__); + return -EINVAL; + } + } + + return count; +} + +static ssize_t rmidev_sysfs_term_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (rmidev->pid) + send_sig_info(SIGTERM, &rmidev->terminate_signal, rmidev->task); + + return count; +} + +static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%02x\n", rmidev->intr_mask); +} + +static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->intr_mask = (unsigned char)input; + + return count; +} + +static ssize_t rmidev_sysfs_concurrent_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", rmidev->concurrent); +} + +static ssize_t rmidev_sysfs_concurrent_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->concurrent = input > 0 ? true : false; + + return count; +} + +static int rmidev_allocate_buffer(int count) +{ + if (count + 1 > rmidev->tmpbuf_size) { + if (rmidev->tmpbuf_size) + kfree(rmidev->tmpbuf); + rmidev->tmpbuf = kzalloc(count + 1, GFP_KERNEL); + if (!rmidev->tmpbuf) { + dev_err(rmidev->rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buffer\n", + __func__); + rmidev->tmpbuf_size = 0; + return -ENOMEM; + } + rmidev->tmpbuf_size = count + 1; + } + + return 0; +} + +/* + * rmidev_llseek - set register address to access for RMI device + * + * @filp: pointer to file structure + * @off: + * if whence == SEEK_SET, + * off: 16-bit RMI register address + * if whence == SEEK_CUR, + * off: offset from current position + * if whence == SEEK_END, + * off: offset from end position (0xFFFF) + * @whence: SEEK_SET, SEEK_CUR, or SEEK_END + */ +static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence) +{ + loff_t newpos; + struct rmidev_data *dev_data = filp->private_data; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + mutex_lock(&(dev_data->file_mutex)); + + switch (whence) { + case SEEK_SET: + newpos = off; + break; + case SEEK_CUR: + newpos = filp->f_pos + off; + break; + case SEEK_END: + newpos = REG_ADDR_LIMIT + off; + break; + default: + newpos = -EINVAL; + goto clean_up; + } + + if (newpos < 0 || newpos > REG_ADDR_LIMIT) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: New position 0x%04x is invalid\n", + __func__, (unsigned int)newpos); + newpos = -EINVAL; + goto clean_up; + } + + filp->f_pos = newpos; + +clean_up: + mutex_unlock(&(dev_data->file_mutex)); + + return newpos; +} + +/* + * rmidev_read: read register data from RMI device + * + * @filp: pointer to file structure + * @buf: pointer to user space buffer + * @count: number of bytes to read + * @f_pos: starting RMI register address + */ +static ssize_t rmidev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t retval; + unsigned char intr_status = 0; + unsigned short address; + struct rmidev_data *dev_data = filp->private_data; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + if (count == 0) + return 0; + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + + address = (unsigned short)(*f_pos); + + mutex_lock(&(dev_data->file_mutex)); + + rmidev_allocate_buffer(count); + + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, + count); + if (retval < 0) + goto clean_up; + + if (copy_to_user(buf, rmidev->tmpbuf, count)) + retval = -EFAULT; + else + *f_pos += retval; + + if (!rmidev->concurrent) + goto clean_up; + + if (address != rmi4_data->f01_data_base_addr) + goto clean_up; + + if (count <= 1) + goto clean_up; + + intr_status = rmidev->tmpbuf[1]; + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & intr_status) { + rmi4_data->report_touch(rmi4_data, + fhandler); + } + } + } + } + +clean_up: + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +/* + * rmidev_write: write register data to RMI device + * + * @filp: pointer to file structure + * @buf: pointer to user space buffer + * @count: number of bytes to write + * @f_pos: starting RMI register address + */ +static ssize_t rmidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t retval; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + if (count == 0) + return 0; + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + + mutex_lock(&(dev_data->file_mutex)); + + rmidev_allocate_buffer(count); + + if (copy_from_user(rmidev->tmpbuf, buf, count)) + return -EFAULT; + + retval = synaptics_rmi4_reg_write(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, + count); + if (retval >= 0) + *f_pos += retval; + + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +static int rmidev_open(struct inode *inp, struct file *filp) +{ + int retval = 0; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + struct rmidev_data *dev_data = + container_of(inp->i_cdev, struct rmidev_data, main_dev); + + if (!dev_data) + return -EACCES; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + filp->private_data = dev_data; + + mutex_lock(&(dev_data->file_mutex)); + + rmi4_data->irq_enable(rmi4_data, false, false); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Attention interrupt disabled\n", + __func__); + + if (dev_data->ref_count < 1) + dev_data->ref_count++; + else + retval = -EACCES; + + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +static int rmidev_release(struct inode *inp, struct file *filp) +{ + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + struct rmidev_data *dev_data = + container_of(inp->i_cdev, struct rmidev_data, main_dev); + + if (!dev_data) + return -EACCES; + + mutex_lock(&(dev_data->file_mutex)); + + dev_data->ref_count--; + if (dev_data->ref_count < 0) + dev_data->ref_count = 0; + + rmi4_data->reset_device(rmi4_data, false); + + rmi4_data->stay_awake = false; + + mutex_unlock(&(dev_data->file_mutex)); + + return 0; +} + +static const struct file_operations rmidev_fops = { + .owner = THIS_MODULE, + .llseek = rmidev_llseek, + .read = rmidev_read, + .write = rmidev_write, + .open = rmidev_open, + .release = rmidev_release, +}; + +static void rmidev_device_cleanup(struct rmidev_data *dev_data) +{ + dev_t devno; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (dev_data) { + devno = dev_data->main_dev.dev; + + if (dev_data->device_class) + device_destroy(dev_data->device_class, devno); + + cdev_del(&dev_data->main_dev); + + unregister_chrdev_region(devno, 1); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: rmidev device removed\n", + __func__); + } + + return; +} + +static char *rmi_char_devnode(struct device *dev, umode_t *mode) +{ + if (!mode) + return NULL; + + *mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + + return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev)); +} + +static int rmidev_create_device_class(void) +{ + if (rmidev_device_class != NULL) + return 0; + + rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME); + + if (IS_ERR(rmidev_device_class)) { + pr_err("%s: Failed to create /dev/%s\n", + __func__, CHAR_DEVICE_NAME); + return -ENODEV; + } + + rmidev_device_class->devnode = rmi_char_devnode; + + return 0; +} + +static void rmidev_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!rmidev) + return; + + if (rmidev->pid && (rmidev->intr_mask & intr_mask)) + send_sig_info(SIGIO, &rmidev->interrupt_signal, rmidev->task); + + return; +} + +static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + dev_t dev_no; + unsigned char attr_count; + struct rmidev_data *dev_data; + struct device *device_ptr; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (rmidev) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + rmidev = kzalloc(sizeof(*rmidev), GFP_KERNEL); + if (!rmidev) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for rmidev\n", + __func__); + retval = -ENOMEM; + goto err_rmidev; + } + + rmidev->rmi4_data = rmi4_data; + + memset(&rmidev->interrupt_signal, 0, sizeof(rmidev->interrupt_signal)); + rmidev->interrupt_signal.si_signo = SIGIO; + rmidev->interrupt_signal.si_code = SI_USER; + + memset(&rmidev->terminate_signal, 0, sizeof(rmidev->terminate_signal)); + rmidev->terminate_signal.si_signo = SIGTERM; + rmidev->terminate_signal.si_code = SI_USER; + + retval = rmidev_create_device_class(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create device class\n", + __func__); + goto err_device_class; + } + + if (rmidev_major_num) { + dev_no = MKDEV(rmidev_major_num, DEV_NUMBER); + retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); + } else { + retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate char device region\n", + __func__); + goto err_device_region; + } + + rmidev_major_num = MAJOR(dev_no); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Major number of rmidev = %d\n", + __func__, rmidev_major_num); + } + + dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); + if (!dev_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for dev_data\n", + __func__); + retval = -ENOMEM; + goto err_dev_data; + } + + mutex_init(&dev_data->file_mutex); + dev_data->rmi_dev = rmidev; + rmidev->data = dev_data; + + cdev_init(&dev_data->main_dev, &rmidev_fops); + + retval = cdev_add(&dev_data->main_dev, dev_no, 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to add rmi char device\n", + __func__); + goto err_char_device; + } + + dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no)); + dev_data->device_class = rmidev_device_class; + + device_ptr = device_create(dev_data->device_class, NULL, dev_no, + NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); + if (IS_ERR(device_ptr)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create rmi char device\n", + __func__); + retval = -ENODEV; + goto err_char_device; + } + + retval = gpio_export(bdata->irq_gpio, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to export attention gpio\n", + __func__); + } else { + retval = gpio_export_link(&(rmi4_data->input_dev->dev), + "attn", bdata->irq_gpio); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s Failed to create gpio symlink\n", + __func__); + } else { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Exported attention gpio %d\n", + __func__, bdata->irq_gpio); + } + } + + rmidev->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!rmidev->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + retval = -ENODEV; + goto err_sysfs_dir; + } + + retval = sysfs_create_bin_file(rmidev->sysfs_dir, + &attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto err_sysfs_bin; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(rmidev->sysfs_dir, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto err_sysfs_attrs; + } + } + + return 0; + +err_sysfs_attrs: + for (attr_count--; attr_count >= 0; attr_count--) + sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); + + sysfs_remove_bin_file(rmidev->sysfs_dir, &attr_data); + +err_sysfs_bin: + kobject_put(rmidev->sysfs_dir); + +err_sysfs_dir: + sysfs_remove_link(&(rmi4_data->input_dev->dev.kobj), "attn"); + gpio_unexport(bdata->irq_gpio); + +err_char_device: + rmidev_device_cleanup(dev_data); + kfree(dev_data); + +err_dev_data: + unregister_chrdev_region(dev_no, 1); + +err_device_region: + if (rmidev_device_class != NULL) { + class_destroy(rmidev_device_class); + rmidev_device_class = NULL; + } + +err_device_class: + kfree(rmidev); + rmidev = NULL; + +err_rmidev: + return retval; +} + +static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + struct rmidev_data *dev_data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!rmidev) + goto exit; + + rmidev_major_num = RMIDEV_MAJOR_NUM; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) + sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); + + sysfs_remove_bin_file(rmidev->sysfs_dir, &attr_data); + + kobject_put(rmidev->sysfs_dir); + + sysfs_remove_link(&(rmi4_data->input_dev->dev.kobj), "attn"); + gpio_unexport(bdata->irq_gpio); + + dev_data = rmidev->data; + if (dev_data) { + rmidev_device_cleanup(dev_data); + kfree(dev_data); + } + + unregister_chrdev_region(rmidev->dev_no, 1); + + if (rmidev_device_class != NULL) { + class_destroy(rmidev_device_class); + rmidev_device_class = NULL; + } + + kfree(rmidev->tmpbuf); + + kfree(rmidev); + rmidev = NULL; + +exit: + complete(&rmidev_remove_complete); + + return; +} + +static struct synaptics_rmi4_exp_fn rmidev_module = { + .fn_type = RMI_DEV, + .init = rmidev_init_device, + .remove = rmidev_remove_device, + .reset = NULL, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = rmidev_attn, +}; + +static int __init rmidev_module_init(void) +{ + synaptics_rmi4_new_function(&rmidev_module, true); + + return 0; +} + +static void __exit rmidev_module_exit(void) +{ + synaptics_rmi4_new_function(&rmidev_module, false); + + wait_for_completion(&rmidev_remove_complete); + + return; +} + +module_init(rmidev_module_init); +module_exit(rmidev_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX RMI Dev Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_rmi_hid_i2c.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_rmi_hid_i2c.c new file mode 100755 index 0000000000000..244e97e3aa508 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_rmi_hid_i2c.c @@ -0,0 +1,1006 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYN_I2C_RETRY_TIMES 10 + +#define REPORT_ID_GET_BLOB 0x07 +#define REPORT_ID_WRITE 0x09 +#define REPORT_ID_READ_ADDRESS 0x0a +#define REPORT_ID_READ_DATA 0x0b +#define REPORT_ID_SET_RMI_MODE 0x0f + +#define PREFIX_USAGE_PAGE_1BYTE 0x05 +#define PREFIX_USAGE_PAGE_2BYTES 0x06 +#define PREFIX_USAGE 0x09 +#define PREFIX_REPORT_ID 0x85 +#define PREFIX_REPORT_COUNT_1BYTE 0x95 +#define PREFIX_REPORT_COUNT_2BYTES 0x96 + +#define USAGE_GET_BLOB 0xc5 +#define USAGE_WRITE 0x02 +#define USAGE_READ_ADDRESS 0x03 +#define USAGE_READ_DATA 0x04 +#define USAGE_SET_MODE 0x06 + +#define FEATURE_REPORT_TYPE 0x03 + +#define VENDOR_DEFINED_PAGE 0xff00 + +#define BLOB_REPORT_SIZE 256 + +#define RESET_COMMAND 0x01 +#define GET_REPORT_COMMAND 0x02 +#define SET_REPORT_COMMAND 0x03 +#define SET_POWER_COMMAND 0x08 + +#define FINGER_MODE 0x00 +#define RMI_MODE 0x02 + +struct hid_report_info { + unsigned char get_blob_id; + unsigned char write_id; + unsigned char read_addr_id; + unsigned char read_data_id; + unsigned char set_mode_id; + unsigned int blob_size; +}; + +static struct hid_report_info hid_report; + +struct hid_device_descriptor { + unsigned short device_descriptor_length; + unsigned short format_version; + unsigned short report_descriptor_length; + unsigned short report_descriptor_index; + unsigned short input_register_index; + unsigned short input_report_max_length; + unsigned short output_register_index; + unsigned short output_report_max_length; + unsigned short command_register_index; + unsigned short data_register_index; + unsigned short vendor_id; + unsigned short product_id; + unsigned short version_id; + unsigned int reserved; +}; + +static struct hid_device_descriptor hid_dd; + +struct i2c_rw_buffer { + unsigned char *read; + unsigned char *write; + unsigned int read_size; + unsigned int write_size; +}; + +static struct i2c_rw_buffer buffer; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,dev-dscrptr-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,dev-dscrptr-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,dev-dscrptr-addr property\n", + __func__); + return retval; + } else { + bdata->device_descriptor_addr = (unsigned short)value; + } + } else { + bdata->device_descriptor_addr = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int do_i2c_transfer(struct i2c_client *client, struct i2c_msg *msg) +{ + unsigned char retry; + + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + dev_err(&client->dev, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(&client->dev, + "%s: I2C transfer over retry limit\n", + __func__); + return -EIO; + } + + return 0; +} + +static int check_buffer(unsigned char **buffer, unsigned int *buffer_size, + unsigned int length) +{ + if (*buffer_size < length) { + if (*buffer_size) + kfree(*buffer); + *buffer = kzalloc(length, GFP_KERNEL); + if (!(*buffer)) + return -ENOMEM; + *buffer_size = length; + } + + return 0; +} + +static int generic_read(struct i2c_client *client, unsigned short length) +{ + int retval; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + } + }; + + check_buffer(&buffer.read, &buffer.read_size, length); + msg[0].buf = buffer.read; + + retval = do_i2c_transfer(client, msg); + + return retval; +} + +static int generic_write(struct i2c_client *client, unsigned short length) +{ + int retval; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length, + .buf = buffer.write, + } + }; + + retval = do_i2c_transfer(client, msg); + + return retval; +} + +static void traverse_report_descriptor(unsigned int *index) +{ + unsigned char size; + unsigned char *buf = buffer.read; + + size = buf[*index] & MASK_2BIT; + switch (size) { + case 0: /* 0 bytes */ + *index += 1; + break; + case 1: /* 1 byte */ + *index += 2; + break; + case 2: /* 2 bytes */ + *index += 3; + break; + case 3: /* 4 bytes */ + *index += 5; + break; + default: + break; + } + + return; +} + +static void find_blob_size(unsigned int index) +{ + unsigned int ii = index; + unsigned char *buf = buffer.read; + + while (ii < hid_dd.report_descriptor_length) { + if (buf[ii] == PREFIX_REPORT_COUNT_1BYTE) { + hid_report.blob_size = buf[ii + 1]; + return; + } else if (buf[ii] == PREFIX_REPORT_COUNT_2BYTES) { + hid_report.blob_size = buf[ii + 1] | (buf[ii + 2] << 8); + return; + } + traverse_report_descriptor(&ii); + } + + return; +} + +static void find_reports(unsigned int index) +{ + unsigned int ii = index; + unsigned char *buf = buffer.read; + static unsigned int report_id_index; + static unsigned char report_id; + static unsigned short usage_page; + + if (buf[ii] == PREFIX_REPORT_ID) { + report_id = buf[ii + 1]; + report_id_index = ii; + return; + } + + if (buf[ii] == PREFIX_USAGE_PAGE_1BYTE) { + usage_page = buf[ii + 1]; + return; + } else if (buf[ii] == PREFIX_USAGE_PAGE_2BYTES) { + usage_page = buf[ii + 1] | (buf[ii + 2] << 8); + return; + } + + if ((usage_page == VENDOR_DEFINED_PAGE) && (buf[ii] == PREFIX_USAGE)) { + switch (buf[ii + 1]) { + case USAGE_GET_BLOB: + hid_report.get_blob_id = report_id; + find_blob_size(report_id_index); + break; + case USAGE_WRITE: + hid_report.write_id = report_id; + break; + case USAGE_READ_ADDRESS: + hid_report.read_addr_id = report_id; + break; + case USAGE_READ_DATA: + hid_report.read_data_id = report_id; + break; + case USAGE_SET_MODE: + hid_report.set_mode_id = report_id; + break; + default: + break; + } + } + + return; +} + +static int parse_report_descriptor(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned int ii = 0; + unsigned char *buf; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + buffer.write[0] = hid_dd.report_descriptor_index & MASK_8BIT; + buffer.write[1] = hid_dd.report_descriptor_index >> 8; + retval = generic_write(i2c, 2); + if (retval < 0) + return retval; + retval = generic_read(i2c, hid_dd.report_descriptor_length); + if (retval < 0) + return retval; + + buf = buffer.read; + + hid_report.get_blob_id = REPORT_ID_GET_BLOB; + hid_report.write_id = REPORT_ID_WRITE; + hid_report.read_addr_id = REPORT_ID_READ_ADDRESS; + hid_report.read_data_id = REPORT_ID_READ_DATA; + hid_report.set_mode_id = REPORT_ID_SET_RMI_MODE; + hid_report.blob_size = BLOB_REPORT_SIZE; + + while (ii < hid_dd.report_descriptor_length) { + find_reports(ii); + traverse_report_descriptor(&ii); + } + + return 0; +} + +static int switch_to_rmi(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, 11); + + /* set rmi mode */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = (FEATURE_REPORT_TYPE << 4) | hid_report.set_mode_id; + buffer.write[3] = SET_REPORT_COMMAND; + buffer.write[4] = hid_report.set_mode_id; + buffer.write[5] = hid_dd.data_register_index & MASK_8BIT; + buffer.write[6] = hid_dd.data_register_index >> 8; + buffer.write[7] = 0x04; + buffer.write[8] = 0x00; + buffer.write[9] = hid_report.set_mode_id; + buffer.write[10] = RMI_MODE; + + retval = generic_write(i2c, 11); + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int check_report_mode(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned short report_size; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, 7); + + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = (FEATURE_REPORT_TYPE << 4) | hid_report.set_mode_id; + buffer.write[3] = GET_REPORT_COMMAND; + buffer.write[4] = hid_report.set_mode_id; + buffer.write[5] = hid_dd.data_register_index & MASK_8BIT; + buffer.write[6] = hid_dd.data_register_index >> 8; + + retval = generic_write(i2c, 7); + if (retval < 0) + goto exit; + + retval = generic_read(i2c, 2); + if (retval < 0) + goto exit; + + report_size = (buffer.read[1] << 8) | buffer.read[0]; + + retval = generic_write(i2c, 7); + if (retval < 0) + goto exit; + + retval = generic_read(i2c, report_size); + if (retval < 0) + goto exit; + + retval = buffer.read[3]; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Report mode = %d\n", + __func__, retval); + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int hid_i2c_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, 6); + + /* read device descriptor */ + buffer.write[0] = bdata->device_descriptor_addr & MASK_8BIT; + buffer.write[1] = bdata->device_descriptor_addr >> 8; + retval = generic_write(i2c, 2); + if (retval < 0) + goto exit; + retval = generic_read(i2c, sizeof(hid_dd)); + if (retval < 0) + goto exit; + retval = secure_memcpy((unsigned char *)&hid_dd, + sizeof(struct hid_device_descriptor), + buffer.read, + buffer.read_size, + sizeof(hid_dd)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy device descriptor data\n", + __func__); + goto exit; + } + + retval = parse_report_descriptor(rmi4_data); + if (retval < 0) + goto exit; + + /* set power */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = 0x00; + buffer.write[3] = SET_POWER_COMMAND; + retval = generic_write(i2c, 4); + if (retval < 0) + goto exit; + + /* reset */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = 0x00; + buffer.write[3] = RESET_COMMAND; + retval = generic_write(i2c, 4); + if (retval < 0) + goto exit; + + while (gpio_get_value(bdata->irq_gpio)) + msleep(20); + + retval = generic_read(i2c, hid_dd.input_report_max_length); + if (retval < 0) + goto exit; + + /* get blob */ + buffer.write[0] = hid_dd.command_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.command_register_index >> 8; + buffer.write[2] = (FEATURE_REPORT_TYPE << 4) | hid_report.get_blob_id; + buffer.write[3] = 0x02; + buffer.write[4] = hid_dd.data_register_index & MASK_8BIT; + buffer.write[5] = hid_dd.data_register_index >> 8; + + retval = generic_write(i2c, 6); + if (retval < 0) + goto exit; + + msleep(20); + + retval = generic_read(i2c, hid_report.blob_size + 3); + if (retval < 0) + goto exit; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to initialize HID/I2C interface\n", + __func__); + return retval; + } + + retval = switch_to_rmi(rmi4_data); + + return retval; +} + +static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + unsigned char recover = 1; + unsigned short report_length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[] = { + { + .addr = i2c->addr, + .flags = 0, + .len = hid_dd.output_report_max_length + 2, + }, + { + .addr = i2c->addr, + .flags = I2C_M_RD, + .len = (unsigned short)(length + 4), + }, + }; + +recover: + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, + hid_dd.output_report_max_length + 2); + msg[0].buf = buffer.write; + buffer.write[0] = hid_dd.output_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.output_register_index >> 8; + buffer.write[2] = hid_dd.output_report_max_length & MASK_8BIT; + buffer.write[3] = hid_dd.output_report_max_length >> 8; + buffer.write[4] = hid_report.read_addr_id; + buffer.write[5] = 0x00; + buffer.write[6] = addr & MASK_8BIT; + buffer.write[7] = addr >> 8; + buffer.write[8] = (unsigned char)length; + buffer.write[9] = (unsigned char)(length >> 8); + + check_buffer(&buffer.read, &buffer.read_size, length + 4); + msg[1].buf = buffer.read; + + retval = do_i2c_transfer(i2c, &msg[0]); + if (retval != 0) + goto exit; + + retry = 0; + do { + retval = do_i2c_transfer(i2c, &msg[1]); + if (retval == 0) + retval = length; + else + goto exit; + + report_length = (buffer.read[1] << 8) | buffer.read[0]; + if (report_length == hid_dd.input_report_max_length) { + retval = secure_memcpy(&data[0], length, + &buffer.read[4], buffer.read_size - 4, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + } else { + retval = length; + } + goto exit; + } + + msleep(20); + retry++; + } while (retry < SYN_I2C_RETRY_TIMES); + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to receive read report\n", + __func__); + retval = -EIO; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + if ((retval != length) && (recover == 1)) { + recover = 0; + if (check_report_mode(rmi4_data) != RMI_MODE) { + retval = hid_i2c_init(rmi4_data); + if (retval == 0) + goto recover; + } + } + + return retval; +} + +static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char recover = 1; + unsigned int msg_length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[] = { + { + .addr = i2c->addr, + .flags = 0, + } + }; + + if ((length + 10) < (hid_dd.output_report_max_length + 2)) + msg_length = hid_dd.output_report_max_length + 2; + else + msg_length = length + 10; + +recover: + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + check_buffer(&buffer.write, &buffer.write_size, msg_length); + msg[0].len = (unsigned short)msg_length; + msg[0].buf = buffer.write; + buffer.write[0] = hid_dd.output_register_index & MASK_8BIT; + buffer.write[1] = hid_dd.output_register_index >> 8; + buffer.write[2] = hid_dd.output_report_max_length & MASK_8BIT; + buffer.write[3] = hid_dd.output_report_max_length >> 8; + buffer.write[4] = hid_report.write_id; + buffer.write[5] = 0x00; + buffer.write[6] = addr & MASK_8BIT; + buffer.write[7] = addr >> 8; + buffer.write[8] = (unsigned char)length; + buffer.write[9] = (unsigned char)(length >> 8); + retval = secure_memcpy(&buffer.write[10], buffer.write_size - 10, + &data[0], length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + } else { + retval = do_i2c_transfer(i2c, msg); + if (retval == 0) + retval = length; + } + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + if ((retval != length) && (recover == 1)) { + recover = 0; + if (check_report_mode(rmi4_data) != RMI_MODE) { + retval = hid_i2c_init(rmi4_data); + if (retval == 0) + goto recover; + } + } + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_I2C, + .read = synaptics_rmi4_i2c_read, + .write = synaptics_rmi4_i2c_write, +}; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_i2c_device; + +static void synaptics_rmi4_i2c_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_i2c_device); + + return; +} + +static int synaptics_rmi4_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int retval; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "%s: SMBus byte data commands not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_i2c_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_i2c_device) { + dev_err(&client->dev, + "%s: Failed to allocate memory for synaptics_dsx_i2c_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (client->dev.of_node) { + hw_if.board_data = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&client->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&client->dev, hw_if.board_data); + } +#else + hw_if.board_data = client->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + hw_if.bl_hw_init = switch_to_rmi; + hw_if.ui_hw_init = hid_i2c_init; + + synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_i2c_device->id = 0; + synaptics_dsx_i2c_device->num_resources = 0; + synaptics_dsx_i2c_device->dev.parent = &client->dev; + synaptics_dsx_i2c_device->dev.platform_data = &hw_if; + synaptics_dsx_i2c_device->dev.release = synaptics_rmi4_i2c_dev_release; + + retval = platform_device_register(synaptics_dsx_i2c_device); + if (retval) { + dev_err(&client->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_i2c_remove(struct i2c_client *client) +{ + if (buffer.read_size) + kfree(buffer.read); + + if (buffer.write_size) + kfree(buffer.write); + + platform_device_unregister(synaptics_dsx_i2c_device); + + return 0; +} + +static const struct i2c_device_id synaptics_rmi4_id_table[] = { + {I2C_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics,dsx-rmi-hid-i2c", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct i2c_driver synaptics_rmi4_i2c_driver = { + .driver = { + .name = I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_i2c_probe, + .remove = synaptics_rmi4_i2c_remove, + .id_table = synaptics_rmi4_id_table, +}; + +int synaptics_rmi4_bus_init(void) +{ + return i2c_add_driver(&synaptics_rmi4_i2c_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init); + +void synaptics_rmi4_bus_exit(void) +{ + i2c_del_driver(&synaptics_rmi4_i2c_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_spi.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_spi.c new file mode 100755 index 0000000000000..e2dafbb5b45c6 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_spi.c @@ -0,0 +1,712 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SPI_READ 0x80 +#define SPI_WRITE 0x00 + +static unsigned char *buf; + +static struct spi_transfer *xfer; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,byte-delay-us", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,byte-delay-us", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,byte-delay-us property\n", + __func__); + return retval; + } else { + bdata->byte_delay_us = value; + } + } else { + bdata->byte_delay_us = 0; + } + + prop = of_find_property(np, "synaptics,block-delay-us", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,block-delay-us", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,block-delay-us property\n", + __func__); + return retval; + } else { + bdata->block_delay_us = value; + } + } else { + bdata->block_delay_us = 0; + } + + prop = of_find_property(np, "synaptics,address-delay-us", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,address-delay-us", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,address-delay-us property\n", + __func__); + return retval; + } else { + bdata->addr_delay_us = value; + } + } else { + bdata->addr_delay_us = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int synaptics_rmi4_spi_alloc_buf(struct synaptics_rmi4_data *rmi4_data, + unsigned int size, unsigned int count) +{ + static unsigned int buf_size; + static unsigned int xfer_count; + + if (size > buf_size) { + if (buf_size) + kfree(buf); + buf = kmalloc(size, GFP_KERNEL); + if (!buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buf\n", + __func__); + buf_size = 0; + return -ENOMEM; + } + buf_size = size; + } + + if (count > xfer_count) { + if (xfer_count) + kfree(xfer); + xfer = kcalloc(count, sizeof(struct spi_transfer), GFP_KERNEL); + if (!xfer) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for xfer\n", + __func__); + xfer_count = 0; + return -ENOMEM; + } + xfer_count = count; + } else { + memset(xfer, 0, count * sizeof(struct spi_transfer)); + } + + return 0; +} + +static int synaptics_rmi4_spi_set_page(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr) +{ + int retval; + unsigned int index; + unsigned int byte_count = PAGE_SELECT_LEN + 1; + unsigned char page; + struct spi_message msg; + struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + page = ((addr >> 8) & MASK_8BIT); + if ((page >> 7) == (rmi4_data->current_page >> 7)) + return PAGE_SELECT_LEN; + + spi_message_init(&msg); + + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count, + byte_count); + if (retval < 0) + return retval; + + buf[0] = SPI_WRITE; + buf[1] = MASK_8BIT; + buf[2] = page; + + if (bdata->byte_delay_us == 0) { + xfer[0].len = byte_count; + xfer[0].tx_buf = &buf[0]; + if (bdata->block_delay_us) + xfer[0].delay_usecs = bdata->block_delay_us; + spi_message_add_tail(&xfer[0], &msg); + } else { + for (index = 0; index < byte_count; index++) { + xfer[index].len = 1; + xfer[index].tx_buf = &buf[index]; + if (index == 1) + xfer[index].delay_usecs = bdata->addr_delay_us; + else + xfer[index].delay_usecs = bdata->byte_delay_us; + spi_message_add_tail(&xfer[index], &msg); + } + if (bdata->block_delay_us) + xfer[index - 1].delay_usecs = bdata->block_delay_us; + } + + retval = spi_sync(spi, &msg); + if (retval == 0) { + rmi4_data->current_page = page; + retval = PAGE_SELECT_LEN; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete SPI transfer, error = %d\n", + __func__, retval); + } + + return retval; +} + +static int synaptics_rmi4_spi_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned int index; + unsigned int byte_count = length + ADDRESS_LEN; + unsigned char txbuf[ADDRESS_LEN]; + struct spi_message msg; + struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + spi_message_init(&msg); + + txbuf[0] = (addr >> 8) | SPI_READ; + txbuf[1] = addr & MASK_8BIT; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_spi_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return -EIO; + } + + if (bdata->byte_delay_us == 0) { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, length, + 2); + } else { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, length, + byte_count); + } + if (retval < 0) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return retval; + } + + if (bdata->byte_delay_us == 0) { + xfer[0].len = ADDRESS_LEN; + xfer[0].tx_buf = &txbuf[0]; + spi_message_add_tail(&xfer[0], &msg); + xfer[1].len = length; + xfer[1].rx_buf = &buf[0]; + if (bdata->block_delay_us) + xfer[1].delay_usecs = bdata->block_delay_us; + spi_message_add_tail(&xfer[1], &msg); + } else { + for (index = 0; index < byte_count; index++) { + xfer[index].len = 1; + if (index < ADDRESS_LEN) + xfer[index].tx_buf = &txbuf[index]; + else + xfer[index].rx_buf = &buf[index - ADDRESS_LEN]; + if (index == 1) + xfer[index].delay_usecs = bdata->addr_delay_us; + else + xfer[index].delay_usecs = bdata->byte_delay_us; + spi_message_add_tail(&xfer[index], &msg); + } + if (bdata->block_delay_us) + xfer[index - 1].delay_usecs = bdata->block_delay_us; + } + + retval = spi_sync(spi, &msg); + if (retval == 0) { + retval = secure_memcpy(data, length, buf, length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + } else { + retval = length; + } + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete SPI transfer, error = %d\n", + __func__, retval); + } + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int synaptics_rmi4_spi_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned int index; + unsigned int byte_count = length + ADDRESS_LEN; + struct spi_message msg; + struct spi_device *spi = to_spi_device(rmi4_data->pdev->dev.parent); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + spi_message_init(&msg); + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_spi_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return -EIO; + } + + if (bdata->byte_delay_us == 0) { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count, + 1); + } else { + retval = synaptics_rmi4_spi_alloc_buf(rmi4_data, byte_count, + byte_count); + } + if (retval < 0) { + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return retval; + } + + buf[0] = (addr >> 8) & ~SPI_READ; + buf[1] = addr & MASK_8BIT; + retval = secure_memcpy(&buf[ADDRESS_LEN], + byte_count - ADDRESS_LEN, data, length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + return retval; + } + + if (bdata->byte_delay_us == 0) { + xfer[0].len = byte_count; + xfer[0].tx_buf = &buf[0]; + if (bdata->block_delay_us) + xfer[0].delay_usecs = bdata->block_delay_us; + spi_message_add_tail(xfer, &msg); + } else { + for (index = 0; index < byte_count; index++) { + xfer[index].len = 1; + xfer[index].tx_buf = &buf[index]; + if (index == 1) + xfer[index].delay_usecs = bdata->addr_delay_us; + else + xfer[index].delay_usecs = bdata->byte_delay_us; + spi_message_add_tail(&xfer[index], &msg); + } + if (bdata->block_delay_us) + xfer[index - 1].delay_usecs = bdata->block_delay_us; + } + + retval = spi_sync(spi, &msg); + if (retval == 0) { + retval = length; + } else { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete SPI transfer, error = %d\n", + __func__, retval); + } + + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_SPI, + .read = synaptics_rmi4_spi_read, + .write = synaptics_rmi4_spi_write, +}; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_spi_device; + +static void synaptics_rmi4_spi_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_spi_device); + + return; +} + +static int synaptics_rmi4_spi_probe(struct spi_device *spi) +{ + int retval; + + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { + dev_err(&spi->dev, + "%s: Full duplex not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_spi_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_spi_device) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for synaptics_dsx_spi_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (spi->dev.of_node) { + hw_if.board_data = devm_kzalloc(&spi->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&spi->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&spi->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&spi->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&spi->dev, hw_if.board_data); + } +#else + hw_if.board_data = spi->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + + spi->bits_per_word = 8; + spi->mode = SPI_MODE_3; + + retval = spi_setup(spi); + if (retval < 0) { + dev_err(&spi->dev, + "%s: Failed to perform SPI setup\n", + __func__); + return retval; + } + + synaptics_dsx_spi_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_spi_device->id = 0; + synaptics_dsx_spi_device->num_resources = 0; + synaptics_dsx_spi_device->dev.parent = &spi->dev; + synaptics_dsx_spi_device->dev.platform_data = &hw_if; + synaptics_dsx_spi_device->dev.release = synaptics_rmi4_spi_dev_release; + + retval = platform_device_register(synaptics_dsx_spi_device); + if (retval) { + dev_err(&spi->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_spi_remove(struct spi_device *spi) +{ + platform_device_unregister(synaptics_dsx_spi_device); + + return 0; +} + +static const struct spi_device_id synaptics_rmi4_id_table[] = { + {SPI_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(spi, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics,dsx-spi", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct spi_driver synaptics_rmi4_spi_driver = { + .driver = { + .name = SPI_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_spi_probe, + .remove = synaptics_rmi4_spi_remove, + .id_table = synaptics_rmi4_id_table, +}; + + +int synaptics_rmi4_bus_init(void) +{ + return spi_register_driver(&synaptics_rmi4_spi_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init); + +void synaptics_rmi4_bus_exit(void) +{ + kfree(buf); + + kfree(xfer); + + spi_unregister_driver(&synaptics_rmi4_spi_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX SPI Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_test_reporting.c new file mode 100755 index 0000000000000..248cb06a2e647 --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_test_reporting.c @@ -0,0 +1,7698 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#include +#include + +#define SYSFS_FOLDER_NAME "f54" + +#define GET_REPORT_TIMEOUT_S 1 +#define CALIBRATION_TIMEOUT_S 10 +#define COMMAND_TIMEOUT_100MS 20 + +#define NO_SLEEP_OFF (0 << 2) +#define NO_SLEEP_ON (1 << 2) + +#define STATUS_IDLE 0 +#define STATUS_BUSY 1 +#define STATUS_ERROR 2 + +#define REPORT_INDEX_OFFSET 1 +#define REPORT_DATA_OFFSET 3 + +#define SENSOR_RX_MAPPING_OFFSET 1 +#define SENSOR_TX_MAPPING_OFFSET 2 + +#define COMMAND_GET_REPORT 1 +#define COMMAND_FORCE_CAL 2 +#define COMMAND_FORCE_UPDATE 4 + +#define CONTROL_NO_AUTO_CAL 1 + +#define CONTROL_0_SIZE 1 +#define CONTROL_1_SIZE 1 +#define CONTROL_2_SIZE 2 +#define CONTROL_3_SIZE 1 +#define CONTROL_4_6_SIZE 3 +#define CONTROL_7_SIZE 1 +#define CONTROL_8_9_SIZE 3 +#define CONTROL_10_SIZE 1 +#define CONTROL_11_SIZE 2 +#define CONTROL_12_13_SIZE 2 +#define CONTROL_14_SIZE 1 +#define CONTROL_15_SIZE 1 +#define CONTROL_16_SIZE 1 +#define CONTROL_17_SIZE 1 +#define CONTROL_18_SIZE 1 +#define CONTROL_19_SIZE 1 +#define CONTROL_20_SIZE 1 +#define CONTROL_21_SIZE 2 +#define CONTROL_22_26_SIZE 7 +#define CONTROL_27_SIZE 1 +#define CONTROL_28_SIZE 2 +#define CONTROL_29_SIZE 1 +#define CONTROL_30_SIZE 1 +#define CONTROL_31_SIZE 1 +#define CONTROL_32_35_SIZE 8 +#define CONTROL_36_SIZE 1 +#define CONTROL_37_SIZE 1 +#define CONTROL_38_SIZE 1 +#define CONTROL_39_SIZE 1 +#define CONTROL_40_SIZE 1 +#define CONTROL_41_SIZE 1 +#define CONTROL_42_SIZE 2 +#define CONTROL_43_54_SIZE 13 +#define CONTROL_55_56_SIZE 2 +#define CONTROL_57_SIZE 1 +#define CONTROL_58_SIZE 1 +#define CONTROL_59_SIZE 2 +#define CONTROL_60_62_SIZE 3 +#define CONTROL_63_SIZE 1 +#define CONTROL_64_67_SIZE 4 +#define CONTROL_68_73_SIZE 8 +#define CONTROL_74_SIZE 2 +#define CONTROL_75_SIZE 1 +#define CONTROL_76_SIZE 1 +#define CONTROL_77_78_SIZE 2 +#define CONTROL_79_83_SIZE 5 +#define CONTROL_84_85_SIZE 2 +#define CONTROL_86_SIZE 1 +#define CONTROL_87_SIZE 1 +#define CONTROL_88_SIZE 1 +#define CONTROL_89_SIZE 1 +#define CONTROL_90_SIZE 1 +#define CONTROL_91_SIZE 1 +#define CONTROL_92_SIZE 1 +#define CONTROL_93_SIZE 1 +#define CONTROL_94_SIZE 1 +#define CONTROL_95_SIZE 1 +#define CONTROL_96_SIZE 1 +#define CONTROL_97_SIZE 1 +#define CONTROL_98_SIZE 1 +#define CONTROL_99_SIZE 1 +#define CONTROL_100_SIZE 1 +#define CONTROL_101_SIZE 1 +#define CONTROL_102_SIZE 1 +#define CONTROL_103_SIZE 1 +#define CONTROL_104_SIZE 1 +#define CONTROL_105_SIZE 1 +#define CONTROL_106_SIZE 1 +#define CONTROL_107_SIZE 1 +#define CONTROL_108_SIZE 1 +#define CONTROL_109_SIZE 1 +#define CONTROL_110_SIZE 1 +#define CONTROL_111_SIZE 1 +#define CONTROL_112_SIZE 1 +#define CONTROL_113_SIZE 1 +#define CONTROL_114_SIZE 1 +#define CONTROL_115_SIZE 1 +#define CONTROL_116_SIZE 1 +#define CONTROL_117_SIZE 1 +#define CONTROL_118_SIZE 1 +#define CONTROL_119_SIZE 1 +#define CONTROL_120_SIZE 1 +#define CONTROL_121_SIZE 1 +#define CONTROL_122_SIZE 1 +#define CONTROL_123_SIZE 1 +#define CONTROL_124_SIZE 1 +#define CONTROL_125_SIZE 1 +#define CONTROL_126_SIZE 1 +#define CONTROL_127_SIZE 1 +#define CONTROL_128_SIZE 1 +#define CONTROL_129_SIZE 1 +#define CONTROL_130_SIZE 1 +#define CONTROL_131_SIZE 1 +#define CONTROL_132_SIZE 1 +#define CONTROL_133_SIZE 1 +#define CONTROL_134_SIZE 1 +#define CONTROL_135_SIZE 1 +#define CONTROL_136_SIZE 1 +#define CONTROL_137_SIZE 1 +#define CONTROL_138_SIZE 1 +#define CONTROL_139_SIZE 1 +#define CONTROL_140_SIZE 1 +#define CONTROL_141_SIZE 1 +#define CONTROL_142_SIZE 1 +#define CONTROL_143_SIZE 1 +#define CONTROL_144_SIZE 1 +#define CONTROL_145_SIZE 1 +#define CONTROL_146_SIZE 1 +#define CONTROL_147_SIZE 1 +#define CONTROL_148_SIZE 1 +#define CONTROL_149_SIZE 1 +#define CONTROL_150_SIZE 1 +#define CONTROL_151_SIZE 1 +#define CONTROL_152_SIZE 1 +#define CONTROL_153_SIZE 1 +#define CONTROL_154_SIZE 1 +#define CONTROL_155_SIZE 1 +#define CONTROL_156_SIZE 1 +#define CONTROL_157_158_SIZE 2 +#define CONTROL_163_SIZE 1 +#define CONTROL_165_SIZE 1 +#define CONTROL_166_SIZE 1 +#define CONTROL_167_SIZE 1 +#define CONTROL_168_SIZE 1 +#define CONTROL_169_SIZE 1 +#define CONTROL_171_SIZE 1 +#define CONTROL_172_SIZE 1 +#define CONTROL_173_SIZE 1 +#define CONTROL_174_SIZE 1 +#define CONTROL_175_SIZE 1 +#define CONTROL_176_SIZE 1 +#define CONTROL_177_178_SIZE 2 +#define CONTROL_179_SIZE 1 +#define CONTROL_182_SIZE 1 +#define CONTROL_183_SIZE 1 +#define CONTROL_185_SIZE 1 +#define CONTROL_186_SIZE 1 +#define CONTROL_187_SIZE 1 +#define CONTROL_188_SIZE 1 +#define CONTROL_196_SIZE 1 +#define CONTROL_218_SIZE 1 +#define CONTROL_223_SIZE 1 + +#define HIGH_RESISTANCE_DATA_SIZE 6 +#define FULL_RAW_CAP_MIN_MAX_DATA_SIZE 4 +#define TRX_OPEN_SHORT_DATA_SIZE 7 + +/* tddi f54 test reporting + */ + + +#define F54_POLLING_GET_REPORT + +/* +#define F54_SHOW_MAX_MIN +*/ + +/* test limit config */ + +#define TX_NUM_DEFAULT 18 +#define RX_NUM_DEFAULT 32 + +/*add by HQ-zmc 20171016*/ +static short *tddi_full_raw_limit_lower; +static short *tddi_full_raw_limit_upper; +/*G6.0 raw data limit*/ +static short tddi_full_raw_limit_lower_G60[TX_NUM_DEFAULT * RX_NUM_DEFAULT] = {1717 , 1634 , 1639 , 1657 , 1647 , 1632 , 1665 , 1641 , 1639 , 1664 , 1655 , 1660 , 1697 , 1662 , 1682 , 1719 , 1693 , 1711 , 1725 , 1698 , 1693 , 1719 , 1698 , 1697 , 1728 , 1704 , 1706 , 1720 , 1680 , 1688 , 1728 , 1782 , +1637 , 1542 , 1547 , 1570 , 1557 , 1539 , 1575 , 1544 , 1542 , 1563 , 1557 , 1560 , 1599 , 1557 , 1567 , 1597 , 1573 , 1589 , 1607 , 1580 , 1567 , 1609 , 1572 , 1565 , 1598 , 1570 , 1568 , 1593 , 1552 , 1555 , 1593 , 1595 , +1642 , 1548 , 1554 , 1579 , 1568 , 1549 , 1585 , 1555 , 1552 , 1574 , 1567 , 1568 , 1609 , 1565 , 1573 , 1604 , 1578 , 1594 , 1612 , 1579 , 1572 , 1604 , 1575 , 1569 , 1596 , 1574 , 1572 , 1602 , 1556 , 1558 , 1589 , 1586 , +1658 , 1567 , 1559 , 1594 , 1579 , 1558 , 1596 , 1568 , 1558 , 1587 , 1576 , 1576 , 1615 , 1572 , 1576 , 1613 , 1580 , 1593 , 1616 , 1580 , 1572 , 1603 , 1578 , 1570 , 1600 , 1577 , 1574 , 1605 , 1559 , 1559 , 1587 , 1582 , +1660 , 1569 , 1562 , 1599 , 1585 , 1563 , 1604 , 1576 , 1562 , 1590 , 1583 , 1580 , 1619 , 1578 , 1578 , 1619 , 1579 , 1589 , 1611 , 1581 , 1570 , 1600 , 1583 , 1569 , 1598 , 1581 , 1573 , 1605 , 1564 , 1555 , 1593 , 1587 , +1659 , 1571 , 1563 , 1601 , 1587 , 1565 , 1608 , 1579 , 1565 , 1594 , 1586 , 1580 , 1619 , 1578 , 1574 , 1615 , 1576 , 1585 , 1607 , 1578 , 1567 , 1604 , 1580 , 1567 , 1601 , 1580 , 1570 , 1604 , 1563 , 1553 , 1589 , 1587 , +1667 , 1576 , 1567 , 1606 , 1591 , 1567 , 1609 , 1580 , 1564 , 1591 , 1583 , 1577 , 1615 , 1574 , 1571 , 1610 , 1572 , 1581 , 1604 , 1576 , 1565 , 1601 , 1579 , 1565 , 1600 , 1579 , 1570 , 1602 , 1561 , 1552 , 1588 , 1588 , +1643 , 1568 , 1568 , 1618 , 1593 , 1565 , 1607 , 1578 , 1563 , 1592 , 1583 , 1576 , 1613 , 1574 , 1570 , 1608 , 1570 , 1580 , 1602 , 1575 , 1563 , 1599 , 1578 , 1564 , 1599 , 1579 , 1570 , 1601 , 1561 , 1552 , 1587 , 1595 , +1661 , 1564 , 1571 , 1599 , 1583 , 1568 , 1605 , 1574 , 1567 , 1592 , 1580 , 1578 , 1616 , 1570 , 1572 , 1605 , 1566 , 1581 , 1602 , 1569 , 1566 , 1595 , 1574 , 1565 , 1600 , 1576 , 1572 , 1596 , 1547 , 1552 , 1558 , 1601 , +1607 , 1559 , 1572 , 1555 , 1563 , 1580 , 1565 , 1565 , 1602 , 1578 , 1568 , 1602 , 1566 , 1574 , 1590 , 1573 , 1561 , 1598 , 1568 , 1568 , 1592 , 1563 , 1554 , 1596 , 1568 , 1576 , 1594 , 1565 , 1542 , 1587 , 1542 , 1599 , +1615 , 1556 , 1600 , 1567 , 1561 , 1582 , 1570 , 1563 , 1602 , 1583 , 1566 , 1600 , 1571 , 1571 , 1591 , 1578 , 1559 , 1599 , 1572 , 1565 , 1589 , 1567 , 1551 , 1596 , 1569 , 1572 , 1600 , 1578 , 1537 , 1605 , 1553 , 1568 , +1606 , 1550 , 1595 , 1563 , 1559 , 1583 , 1570 , 1564 , 1604 , 1584 , 1567 , 1602 , 1572 , 1572 , 1592 , 1580 , 1561 , 1602 , 1575 , 1568 , 1591 , 1569 , 1552 , 1598 , 1570 , 1574 , 1599 , 1576 , 1537 , 1594 , 1558 , 1563 , +1596 , 1544 , 1589 , 1557 , 1554 , 1577 , 1566 , 1561 , 1602 , 1583 , 1568 , 1606 , 1574 , 1576 , 1596 , 1582 , 1565 , 1606 , 1578 , 1571 , 1593 , 1571 , 1555 , 1601 , 1571 , 1575 , 1600 , 1577 , 1539 , 1596 , 1559 , 1564 , +1591 , 1539 , 1583 , 1553 , 1550 , 1570 , 1562 , 1557 , 1591 , 1581 , 1566 , 1602 , 1574 , 1578 , 1599 , 1586 , 1570 , 1611 , 1582 , 1576 , 1597 , 1574 , 1558 , 1604 , 1574 , 1578 , 1603 , 1578 , 1541 , 1599 , 1561 , 1564 , +1581 , 1535 , 1575 , 1541 , 1545 , 1561 , 1551 , 1551 , 1587 , 1570 , 1561 , 1598 , 1567 , 1574 , 1597 , 1582 , 1574 , 1612 , 1581 , 1578 , 1599 , 1571 , 1559 , 1604 , 1572 , 1578 , 1602 , 1575 , 1542 , 1603 , 1560 , 1563 , +1576 , 1529 , 1568 , 1534 , 1537 , 1553 , 1541 , 1543 , 1576 , 1561 , 1555 , 1589 , 1560 , 1570 , 1589 , 1578 , 1575 , 1611 , 1581 , 1580 , 1598 , 1570 , 1559 , 1598 , 1567 , 1578 , 1598 , 1570 , 1542 , 1598 , 1552 , 1568 , +1572 , 1524 , 1557 , 1524 , 1528 , 1541 , 1531 , 1533 , 1570 , 1554 , 1546 , 1591 , 1559 , 1562 , 1582 , 1572 , 1571 , 1606 , 1576 , 1574 , 1593 , 1565 , 1554 , 1594 , 1564 , 1574 , 1594 , 1565 , 1539 , 1596 , 1552 , 1579 , +1684 , 1646 , 1672 , 1636 , 1637 , 1650 , 1638 , 1643 , 1678 , 1663 , 1657 , 1688 , 1665 , 1678 , 1698 , 1691 , 1693 , 1723 , 1685 , 1685 , 1699 , 1674 , 1666 , 1710 , 1676 , 1688 , 1706 , 1674 , 1648 , 1706 , 1665 , 1711 }; + +static short tddi_full_raw_limit_upper_G60[TX_NUM_DEFAULT * RX_NUM_DEFAULT] = {3565 , 3394 , 3403 , 3441 , 3421 , 3389 , 3459 , 3407 , 3403 , 3456 , 3437 , 3448 , 3524 , 3452 , 3492 , 3569 , 3517 , 3553 , 3583 , 3526 , 3515 , 3571 , 3526 , 3524 , 3590 , 3540 , 3542 , 3572 , 3488 , 3506 , 3588 , 3700 , +3401 , 3202 , 3213 , 3260 , 3235 , 3195 , 3271 , 3208 , 3204 , 3247 , 3235 , 3240 , 3321 , 3233 , 3255 , 3317 , 3267 , 3299 , 3337 , 3282 , 3255 , 3343 , 3264 , 3249 , 3318 , 3260 , 3258 , 3308 , 3222 , 3231 , 3309 , 3313 , +3410 , 3216 , 3228 , 3279 , 3256 , 3217 , 3293 , 3231 , 3222 , 3268 , 3254 , 3258 , 3341 , 3249 , 3267 , 3332 , 3278 , 3310 , 3348 , 3279 , 3266 , 3330 , 3271 , 3259 , 3316 , 3268 , 3264 , 3326 , 3232 , 3236 , 3301 , 3294 , +3443 , 3255 , 3237 , 3310 , 3279 , 3236 , 3316 , 3256 , 3236 , 3295 , 3272 , 3274 , 3355 , 3264 , 3274 , 3349 , 3281 , 3309 , 3356 , 3282 , 3266 , 3329 , 3278 , 3260 , 3322 , 3275 , 3268 , 3333 , 3237 , 3237 , 3295 , 3286 , +3448 , 3259 , 3244 , 3321 , 3291 , 3245 , 3332 , 3272 , 3244 , 3302 , 3289 , 3281 , 3362 , 3278 , 3276 , 3362 , 3279 , 3301 , 3347 , 3285 , 3260 , 3322 , 3287 , 3259 , 3320 , 3285 , 3267 , 3333 , 3248 , 3229 , 3308 , 3297 , +3447 , 3263 , 3247 , 3325 , 3297 , 3251 , 3340 , 3279 , 3249 , 3310 , 3294 , 3282 , 3362 , 3276 , 3270 , 3353 , 3272 , 3291 , 3339 , 3278 , 3255 , 3330 , 3281 , 3254 , 3325 , 3281 , 3262 , 3330 , 3245 , 3225 , 3299 , 3297 , +3463 , 3272 , 3254 , 3335 , 3305 , 3255 , 3341 , 3281 , 3248 , 3303 , 3287 , 3275 , 3355 , 3270 , 3263 , 3344 , 3264 , 3285 , 3332 , 3274 , 3251 , 3325 , 3279 , 3251 , 3324 , 3279 , 3262 , 3328 , 3243 , 3224 , 3298 , 3298 , +3411 , 3256 , 3258 , 3360 , 3309 , 3251 , 3339 , 3278 , 3247 , 3306 , 3287 , 3272 , 3351 , 3268 , 3262 , 3340 , 3260 , 3281 , 3326 , 3271 , 3247 , 3321 , 3276 , 3248 , 3321 , 3279 , 3262 , 3325 , 3241 , 3222 , 3297 , 3313 , +3451 , 3248 , 3263 , 3321 , 3289 , 3256 , 3333 , 3268 , 3254 , 3306 , 3282 , 3276 , 3356 , 3262 , 3266 , 3333 , 3252 , 3285 , 3328 , 3259 , 3252 , 3313 , 3270 , 3251 , 3324 , 3272 , 3266 , 3316 , 3213 , 3222 , 3236 , 3325 , +3337 , 3237 , 3266 , 3231 , 3245 , 3282 , 3249 , 3249 , 3326 , 3278 , 3256 , 3326 , 3252 , 3268 , 3302 , 3267 , 3243 , 3318 , 3258 , 3256 , 3306 , 3245 , 3228 , 3314 , 3258 , 3274 , 3312 , 3249 , 3202 , 3295 , 3202 , 3321 , +3355 , 3232 , 3324 , 3255 , 3241 , 3286 , 3260 , 3245 , 3328 , 3289 , 3252 , 3324 , 3263 , 3263 , 3303 , 3276 , 3237 , 3321 , 3266 , 3251 , 3299 , 3255 , 3221 , 3316 , 3259 , 3266 , 3322 , 3278 , 3193 , 3333 , 3225 , 3258 , +3336 , 3220 , 3313 , 3245 , 3239 , 3287 , 3262 , 3248 , 3332 , 3290 , 3254 , 3328 , 3266 , 3266 , 3306 , 3281 , 3241 , 3328 , 3271 , 3256 , 3303 , 3259 , 3224 , 3320 , 3262 , 3268 , 3321 , 3272 , 3193 , 3312 , 3236 , 3245 , +3316 , 3206 , 3301 , 3235 , 3228 , 3275 , 3252 , 3243 , 3326 , 3289 , 3256 , 3335 , 3270 , 3272 , 3314 , 3286 , 3249 , 3336 , 3276 , 3263 , 3309 , 3263 , 3229 , 3325 , 3263 , 3271 , 3324 , 3275 , 3195 , 3316 , 3239 , 3248 , +3305 , 3197 , 3289 , 3225 , 3220 , 3260 , 3244 , 3233 , 3303 , 3285 , 3252 , 3326 , 3270 , 3276 , 3321 , 3294 , 3260 , 3347 , 3286 , 3272 , 3317 , 3270 , 3236 , 3332 , 3268 , 3276 , 3329 , 3276 , 3201 , 3321 , 3243 , 3248 , +3285 , 3187 , 3271 , 3201 , 3209 , 3243 , 3221 , 3221 , 3295 , 3262 , 3243 , 3318 , 3255 , 3270 , 3317 , 3286 , 3270 , 3348 , 3283 , 3278 , 3321 , 3263 , 3237 , 3330 , 3266 , 3278 , 3328 , 3271 , 3202 , 3329 , 3240 , 3247 , +3272 , 3177 , 3256 , 3186 , 3191 , 3225 , 3201 , 3205 , 3274 , 3243 , 3231 , 3301 , 3240 , 3260 , 3301 , 3278 , 3271 , 3345 , 3285 , 3281 , 3318 , 3260 , 3237 , 3318 , 3255 , 3276 , 3320 , 3262 , 3202 , 3320 , 3224 , 3258 , +3264 , 3164 , 3235 , 3166 , 3173 , 3201 , 3179 , 3183 , 3262 , 3227 , 3212 , 3305 , 3237 , 3244 , 3286 , 3264 , 3263 , 3335 , 3272 , 3268 , 3308 , 3251 , 3228 , 3312 , 3248 , 3270 , 3312 , 3251 , 3197 , 3316 , 3224 , 3279 , +3498 , 3420 , 3472 , 3398 , 3401 , 3426 , 3402 , 3413 , 3486 , 3455 , 3441 , 3506 , 3457 , 3486 , 3528 , 3511 , 3515 , 3579 , 3501 , 3501 , 3529 , 3478 , 3460 , 3552 , 3482 , 3506 , 3542 , 3476 , 3422 , 3542 , 3457 , 3553 }; + +/*add by HQ-zmc 20171016*/ +static short tddi_full_raw_limit_lower_G55[TX_NUM_DEFAULT * RX_NUM_DEFAULT] = {1687 , 1602 , 1599 , 1642 , 1596 , 1601 , 1633 , 1619 , 1625 , 1633 , 1614 , 1623 , 1653 , 1629 , 1623 , 1679 , 1661 , 1653 , 1692 , 1653 , 1647 , 1680 , 1649 , 1652 , 1697 , 1662 , 1670 , 1666 , 1646 , 1641 , 1685 , 1730, +1609 , 1511 , 1509 , 1556 , 1508 , 1510 , 1546 , 1527 , 1532 , 1537 , 1521 , 1527 , 1561 , 1530 , 1522 , 1572 , 1556 , 1547 , 1587 , 1550 , 1536 , 1584 , 1538 , 1535 , 1582 , 1543 , 1549 , 1554 , 1534 , 1526 , 1567 , 1567, +1613 , 1517 , 1515 , 1565 , 1518 , 1520 , 1557 , 1537 , 1541 , 1548 , 1530 , 1536 , 1571 , 1540 , 1530 , 1580 , 1563 , 1554 , 1593 , 1550 , 1543 , 1579 , 1541 , 1539 , 1582 , 1548 , 1552 , 1563 , 1538 , 1528 , 1564 , 1560, +1628 , 1537 , 1521 , 1579 , 1530 , 1529 , 1568 , 1550 , 1549 , 1562 , 1540 , 1545 , 1578 , 1548 , 1536 , 1591 , 1566 , 1555 , 1600 , 1553 , 1545 , 1580 , 1546 , 1541 , 1585 , 1552 , 1554 , 1566 , 1541 , 1530 , 1563 , 1558, +1633 , 1541 , 1526 , 1586 , 1538 , 1535 , 1578 , 1560 , 1556 , 1568 , 1550 , 1550 , 1584 , 1558 , 1539 , 1599 , 1568 , 1554 , 1598 , 1558 , 1545 , 1580 , 1553 , 1543 , 1587 , 1559 , 1556 , 1569 , 1548 , 1529 , 1570 , 1565, +1634 , 1544 , 1529 , 1590 , 1543 , 1540 , 1584 , 1565 , 1560 , 1574 , 1555 , 1554 , 1586 , 1560 , 1538 , 1597 , 1566 , 1552 , 1597 , 1557 , 1545 , 1586 , 1552 , 1543 , 1591 , 1559 , 1556 , 1569 , 1548 , 1528 , 1568 , 1566, +1642 , 1550 , 1533 , 1596 , 1548 , 1543 , 1587 , 1568 , 1562 , 1573 , 1554 , 1552 , 1585 , 1558 , 1536 , 1595 , 1565 , 1550 , 1595 , 1557 , 1545 , 1585 , 1553 , 1544 , 1592 , 1560 , 1558 , 1570 , 1549 , 1529 , 1569 , 1568, +1619 , 1542 , 1535 , 1608 , 1550 , 1542 , 1586 , 1567 , 1562 , 1575 , 1554 , 1552 , 1584 , 1557 , 1536 , 1593 , 1564 , 1549 , 1594 , 1556 , 1544 , 1585 , 1553 , 1544 , 1592 , 1561 , 1558 , 1569 , 1549 , 1529 , 1569 , 1573, +1637 , 1538 , 1538 , 1590 , 1540 , 1545 , 1583 , 1563 , 1565 , 1574 , 1552 , 1554 , 1587 , 1554 , 1538 , 1590 , 1560 , 1551 , 1595 , 1551 , 1547 , 1582 , 1550 , 1547 , 1593 , 1558 , 1561 , 1566 , 1537 , 1530 , 1540 , 1576, +1587 , 1523 , 1538 , 1550 , 1523 , 1584 , 1556 , 1546 , 1570 , 1562 , 1530 , 1574 , 1542 , 1546 , 1578 , 1556 , 1538 , 1581 , 1545 , 1545 , 1578 , 1553 , 1523 , 1580 , 1545 , 1547 , 1577 , 1533 , 1512 , 1553 , 1523 , 1566, +1595 , 1520 , 1565 , 1561 , 1520 , 1585 , 1560 , 1543 , 1570 , 1567 , 1527 , 1571 , 1546 , 1543 , 1578 , 1560 , 1535 , 1583 , 1548 , 1541 , 1574 , 1557 , 1520 , 1581 , 1546 , 1543 , 1581 , 1547 , 1508 , 1572 , 1535 , 1542, +1584 , 1513 , 1559 , 1555 , 1517 , 1584 , 1560 , 1544 , 1571 , 1567 , 1527 , 1573 , 1547 , 1544 , 1580 , 1561 , 1537 , 1584 , 1550 , 1543 , 1575 , 1557 , 1521 , 1581 , 1547 , 1543 , 1580 , 1545 , 1508 , 1562 , 1540 , 1538, +1572 , 1505 , 1551 , 1548 , 1511 , 1577 , 1553 , 1540 , 1567 , 1565 , 1527 , 1573 , 1548 , 1546 , 1582 , 1562 , 1538 , 1586 , 1551 , 1543 , 1576 , 1558 , 1521 , 1581 , 1546 , 1543 , 1579 , 1544 , 1508 , 1562 , 1540 , 1539, +1567 , 1500 , 1545 , 1543 , 1506 , 1569 , 1549 , 1534 , 1555 , 1561 , 1524 , 1569 , 1546 , 1546 , 1583 , 1565 , 1542 , 1590 , 1553 , 1546 , 1578 , 1559 , 1522 , 1583 , 1547 , 1544 , 1580 , 1544 , 1510 , 1564 , 1542 , 1539, +1556 , 1495 , 1535 , 1530 , 1499 , 1560 , 1536 , 1527 , 1550 , 1549 , 1518 , 1564 , 1537 , 1541 , 1579 , 1558 , 1544 , 1588 , 1550 , 1546 , 1577 , 1554 , 1521 , 1581 , 1543 , 1542 , 1578 , 1539 , 1508 , 1565 , 1538 , 1536, +1548 , 1489 , 1527 , 1523 , 1491 , 1551 , 1526 , 1518 , 1539 , 1539 , 1511 , 1555 , 1529 , 1535 , 1570 , 1552 , 1542 , 1584 , 1548 , 1545 , 1575 , 1552 , 1520 , 1574 , 1538 , 1541 , 1573 , 1533 , 1506 , 1558 , 1529 , 1538, +1545 , 1483 , 1517 , 1514 , 1482 , 1541 , 1516 , 1508 , 1533 , 1531 , 1502 , 1556 , 1526 , 1526 , 1561 , 1545 , 1537 , 1578 , 1541 , 1539 , 1570 , 1547 , 1516 , 1571 , 1534 , 1537 , 1569 , 1528 , 1502 , 1555 , 1526 , 1547, +1641 , 1594 , 1620 , 1615 , 1581 , 1638 , 1611 , 1607 , 1630 , 1629 , 1600 , 1640 , 1618 , 1627 , 1662 , 1646 , 1641 , 1681 , 1644 , 1645 , 1671 , 1650 , 1621 , 1680 , 1640 , 1645 , 1672 , 1629 , 1604 , 1655 , 1630 , 1666 +}; + +static short tddi_full_raw_limit_upper_G55[TX_NUM_DEFAULT * RX_NUM_DEFAULT] = {3504 , 3328 , 3322 , 3411 , 3315 , 3326 , 3393 , 3364 , 3375 , 3393 , 3352 , 3371 , 3434 , 3384 , 3372 , 3489 , 3451 , 3434 , 3514 , 3433 , 3421 , 3491 , 3426 , 3431 , 3525 , 3452 , 3470 , 3460 , 3419 , 3410 , 3500 , 3593, +3341 , 3139 , 3134 , 3232 , 3133 , 3137 , 3211 , 3171 , 3183 , 3192 , 3159 , 3172 , 3242 , 3179 , 3162 , 3266 , 3232 , 3213 , 3297 , 3220 , 3192 , 3290 , 3194 , 3189 , 3287 , 3206 , 3217 , 3227 , 3186 , 3169 , 3256 , 3255, +3350 , 3151 , 3148 , 3250 , 3153 , 3157 , 3234 , 3193 , 3202 , 3215 , 3179 , 3191 , 3263 , 3198 , 3178 , 3283 , 3246 , 3227 , 3310 , 3220 , 3205 , 3280 , 3202 , 3197 , 3285 , 3215 , 3223 , 3246 , 3195 , 3175 , 3249 , 3241, +3383 , 3192 , 3159 , 3281 , 3178 , 3175 , 3258 , 3220 , 3219 , 3245 , 3199 , 3209 , 3279 , 3217 , 3191 , 3305 , 3253 , 3231 , 3323 , 3227 , 3208 , 3282 , 3211 , 3202 , 3293 , 3223 , 3229 , 3254 , 3201 , 3177 , 3247 , 3236, +3392 , 3200 , 3169 , 3295 , 3196 , 3189 , 3279 , 3241 , 3232 , 3257 , 3220 , 3221 , 3291 , 3237 , 3197 , 3321 , 3257 , 3229 , 3320 , 3236 , 3209 , 3282 , 3226 , 3206 , 3296 , 3239 , 3233 , 3259 , 3216 , 3175 , 3261 , 3251, +3394 , 3207 , 3176 , 3303 , 3205 , 3199 , 3291 , 3252 , 3241 , 3270 , 3230 , 3227 , 3295 , 3241 , 3195 , 3318 , 3254 , 3225 , 3317 , 3235 , 3209 , 3294 , 3224 , 3206 , 3306 , 3238 , 3232 , 3259 , 3215 , 3174 , 3257 , 3254, +3412 , 3219 , 3185 , 3314 , 3216 , 3206 , 3296 , 3257 , 3244 , 3268 , 3229 , 3225 , 3292 , 3237 , 3192 , 3313 , 3251 , 3220 , 3314 , 3235 , 3208 , 3293 , 3226 , 3208 , 3307 , 3241 , 3236 , 3261 , 3217 , 3176 , 3258 , 3257, +3364 , 3204 , 3188 , 3340 , 3220 , 3203 , 3294 , 3255 , 3244 , 3272 , 3229 , 3223 , 3291 , 3235 , 3190 , 3310 , 3248 , 3217 , 3311 , 3232 , 3207 , 3292 , 3226 , 3207 , 3306 , 3242 , 3237 , 3259 , 3218 , 3176 , 3258 , 3269, +3401 , 3194 , 3194 , 3303 , 3199 , 3209 , 3288 , 3247 , 3250 , 3269 , 3225 , 3228 , 3296 , 3229 , 3194 , 3303 , 3242 , 3221 , 3314 , 3222 , 3213 , 3286 , 3220 , 3213 , 3310 , 3236 , 3242 , 3252 , 3193 , 3179 , 3200 , 3274, +3297 , 3164 , 3195 , 3221 , 3163 , 3290 , 3231 , 3211 , 3261 , 3245 , 3178 , 3269 , 3203 , 3212 , 3279 , 3233 , 3195 , 3285 , 3209 , 3209 , 3278 , 3226 , 3164 , 3282 , 3210 , 3213 , 3275 , 3185 , 3141 , 3227 , 3164 , 3252, +3313 , 3156 , 3250 , 3242 , 3157 , 3293 , 3241 , 3206 , 3262 , 3254 , 3173 , 3264 , 3212 , 3206 , 3279 , 3241 , 3189 , 3287 , 3216 , 3201 , 3270 , 3233 , 3157 , 3283 , 3212 , 3205 , 3285 , 3213 , 3132 , 3265 , 3188 , 3203, +3290 , 3143 , 3237 , 3230 , 3152 , 3291 , 3240 , 3207 , 3264 , 3255 , 3172 , 3267 , 3214 , 3208 , 3281 , 3243 , 3193 , 3291 , 3219 , 3204 , 3272 , 3235 , 3159 , 3285 , 3213 , 3205 , 3282 , 3208 , 3133 , 3244 , 3199 , 3196, +3266 , 3127 , 3222 , 3216 , 3140 , 3277 , 3227 , 3198 , 3256 , 3251 , 3173 , 3268 , 3215 , 3211 , 3286 , 3245 , 3196 , 3294 , 3222 , 3206 , 3274 , 3236 , 3159 , 3285 , 3211 , 3205 , 3280 , 3207 , 3133 , 3245 , 3199 , 3196, +3255 , 3117 , 3209 , 3205 , 3129 , 3259 , 3217 , 3187 , 3231 , 3244 , 3166 , 3260 , 3212 , 3211 , 3289 , 3250 , 3204 , 3303 , 3227 , 3211 , 3278 , 3239 , 3162 , 3289 , 3214 , 3207 , 3282 , 3207 , 3136 , 3249 , 3203 , 3196, +3231 , 3105 , 3188 , 3179 , 3114 , 3240 , 3191 , 3171 , 3220 , 3217 , 3153 , 3249 , 3193 , 3201 , 3280 , 3236 , 3207 , 3298 , 3219 , 3211 , 3277 , 3229 , 3160 , 3283 , 3206 , 3204 , 3277 , 3197 , 3133 , 3251 , 3195 , 3191, +3217 , 3092 , 3173 , 3163 , 3097 , 3222 , 3171 , 3154 , 3197 , 3197 , 3139 , 3230 , 3175 , 3189 , 3261 , 3225 , 3204 , 3291 , 3216 , 3210 , 3272 , 3223 , 3158 , 3270 , 3194 , 3201 , 3267 , 3185 , 3129 , 3237 , 3175 , 3196, +3209 , 3082 , 3152 , 3146 , 3078 , 3200 , 3150 , 3133 , 3185 , 3181 , 3121 , 3233 , 3170 , 3171 , 3243 , 3209 , 3192 , 3277 , 3201 , 3198 , 3262 , 3213 , 3150 , 3263 , 3187 , 3193 , 3259 , 3173 , 3121 , 3230 , 3170 , 3214, +3409 , 3311 , 3366 , 3354 , 3283 , 3402 , 3347 , 3338 , 3386 , 3383 , 3323 , 3408 , 3361 , 3380 , 3451 , 3420 , 3409 , 3493 , 3414 , 3417 , 3470 , 3428 , 3368 , 3490 , 3406 , 3416 , 3474 , 3384 , 3331 , 3438 , 3386 , 3462, +}; + +#define FULL_RAW_CAP_TEST_LIMIT_LOWER 300 +#define FULL_RAW_CAP_TEST_LIMIT_UPPER 60000 + +#define NOISE_TEST_LIMIT 35 +#define NOISE_TEST_NUM_OF_FRAMES 10 + +#define EE_SHORT_TEST_LIMIT_PART1 230 +#define EE_SHORT_TEST_LIMIT_PART2 70 + +#define AMP_OPEN_INT_DUR_ONE 145 +#define AMP_OPEN_INT_DUR_TWO 10 +#define AMP_OPEN_TEST_LIMIT_PHASE1_LOWER 500 +#define AMP_OPEN_TEST_LIMIT_PHASE1_UPPER 3000 +#define AMP_OPEN_TEST_LIMIT_PHASE2_LOWER 70 +#define AMP_OPEN_TEST_LIMIT_PHASE2_UPPER 130 + +#define NUM_BUTTON 3 +#define ABS_0D_OPEN_FACTOR 15 +#define ABS_0D_OPEN_TEST_LIMIT 30 + +#define ELEC_OPEN_TEST_TX_ON_COUNT 2 +#define ELEC_OPEN_TEST_RX_ON_COUNT 2 +#define ELEC_OPEN_INT_DUR_ONE 15 +#define ELEC_OPEN_INT_DUR_TWO 25 +/*para add by HQ-zmc 20170919*/ +#define ELEC_OPEN_TEST_LIMIT_ONE_LOWER 5 +#define ELEC_OPEN_TEST_LIMIT_ONE_UPPER 8000 +#define ELEC_OPEN_TEST_LIMIT_TWO_LOWER 40 +#define ELEC_OPEN_TEST_LIMIT_TWO_UPPER 240 + +/* tddi f54 test reporting - */ + +#define _TEST_FAIL 1 +#define _TEST_PASS 0 + + +#define concat(a, b) a##b + +#define attrify(propname) (&dev_attr_##propname.attr) + +#define show_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_show)(\ + struct device *dev,\ + struct device_attribute *attr,\ + char *buf);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, S_IRUGO,\ + concat(test_sysfs, _##propname##_show),\ + synaptics_rmi4_store_error); + +#define store_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_store)(\ + struct device *dev,\ + struct device_attribute *attr,\ + const char *buf, size_t count);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, (S_IWUSR | S_IWGRP),\ + synaptics_rmi4_show_error,\ + concat(test_sysfs, _##propname##_store)); + +#define show_store_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_show)(\ + struct device *dev,\ + struct device_attribute *attr,\ + char *buf);\ +\ +static ssize_t concat(test_sysfs, _##propname##_store)(\ + struct device *dev,\ + struct device_attribute *attr,\ + const char *buf, size_t count);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, (S_IRUGO | S_IWUSR | S_IWGRP),\ + concat(test_sysfs, _##propname##_show),\ + concat(test_sysfs, _##propname##_store)); + +#define disable_cbc(ctrl_num)\ +do {\ + retval = synaptics_rmi4_reg_read(rmi4_data,\ + f54->control.ctrl_num->address,\ + f54->control.ctrl_num->data,\ + sizeof(f54->control.ctrl_num->data));\ + if (retval < 0) {\ + dev_err(rmi4_data->pdev->dev.parent,\ + "%s: Failed to disable CBC (" #ctrl_num ")\n",\ + __func__);\ + return retval;\ + } \ + f54->control.ctrl_num->cbc_tx_carrier_selection = 0;\ + retval = synaptics_rmi4_reg_write(rmi4_data,\ + f54->control.ctrl_num->address,\ + f54->control.ctrl_num->data,\ + sizeof(f54->control.ctrl_num->data));\ + if (retval < 0) {\ + dev_err(rmi4_data->pdev->dev.parent,\ + "%s: Failed to disable CBC (" #ctrl_num ")\n",\ + __func__);\ + return retval;\ + } \ +} while (0) + +enum f54_report_types { + F54_8BIT_IMAGE = 1, + F54_16BIT_IMAGE = 2, + F54_RAW_16BIT_IMAGE = 3, + F54_HIGH_RESISTANCE = 4, + F54_TX_TO_TX_SHORTS = 5, + F54_RX_TO_RX_SHORTS_1 = 7, + F54_TRUE_BASELINE = 9, + F54_FULL_RAW_CAP_MIN_MAX = 13, + F54_RX_OPENS_1 = 14, + F54_TX_OPENS = 15, + F54_TX_TO_GND_SHORTS = 16, + F54_RX_TO_RX_SHORTS_2 = 17, + F54_RX_OPENS_2 = 18, + F54_FULL_RAW_CAP = 19, + F54_FULL_RAW_CAP_NO_RX_COUPLING = 20, + F54_SENSOR_SPEED = 22, + F54_ADC_RANGE = 23, + F54_TRX_OPENS = 24, + F54_TRX_TO_GND_SHORTS = 25, + F54_TRX_SHORTS = 26, + F54_ABS_RAW_CAP = 38, + F54_ABS_DELTA_CAP = 40, + F54_ABS_HYBRID_DELTA_CAP = 59, + F54_ABS_HYBRID_RAW_CAP = 63, + F54_AMP_FULL_RAW_CAP = 78, + F54_AMP_RAW_ADC = 83, + /* tddi f54 test reporting + */ + F54_FULL_RAW_CAP_TDDI = 92, + F54_NOISE_TDDI = 94, + F54_EE_SHORT_TDDI = 95, + /* tddi f54 test reporting - */ + + INVALID_REPORT_TYPE = -1, +}; + +enum f54_afe_cal { + F54_AFE_CAL, + F54_AFE_IS_CAL, +}; + +struct f54_query { + union { + struct { + /* query 0 */ + unsigned char num_of_rx_electrodes; + + /* query 1 */ + unsigned char num_of_tx_electrodes; + + /* query 2 */ + unsigned char f54_query2_b0__1:2; + unsigned char has_baseline:1; + unsigned char has_image8:1; + unsigned char f54_query2_b4__5:2; + unsigned char has_image16:1; + unsigned char f54_query2_b7:1; + + /* queries 3.0 and 3.1 */ + unsigned short clock_rate; + + /* query 4 */ + unsigned char touch_controller_family; + + /* query 5 */ + unsigned char has_pixel_touch_threshold_adjustment:1; + unsigned char f54_query5_b1__7:7; + + /* query 6 */ + unsigned char has_sensor_assignment:1; + unsigned char has_interference_metric:1; + unsigned char has_sense_frequency_control:1; + unsigned char has_firmware_noise_mitigation:1; + unsigned char has_ctrl11:1; + unsigned char has_two_byte_report_rate:1; + unsigned char has_one_byte_report_rate:1; + unsigned char has_relaxation_control:1; + + /* query 7 */ + unsigned char curve_compensation_mode:2; + unsigned char f54_query7_b2__7:6; + + /* query 8 */ + unsigned char f54_query8_b0:1; + unsigned char has_iir_filter:1; + unsigned char has_cmn_removal:1; + unsigned char has_cmn_maximum:1; + unsigned char has_touch_hysteresis:1; + unsigned char has_edge_compensation:1; + unsigned char has_per_frequency_noise_control:1; + unsigned char has_enhanced_stretch:1; + + /* query 9 */ + unsigned char has_force_fast_relaxation:1; + unsigned char has_multi_metric_state_machine:1; + unsigned char has_signal_clarity:1; + unsigned char has_variance_metric:1; + unsigned char has_0d_relaxation_control:1; + unsigned char has_0d_acquisition_control:1; + unsigned char has_status:1; + unsigned char has_slew_metric:1; + + /* query 10 */ + unsigned char has_h_blank:1; + unsigned char has_v_blank:1; + unsigned char has_long_h_blank:1; + unsigned char has_startup_fast_relaxation:1; + unsigned char has_esd_control:1; + unsigned char has_noise_mitigation2:1; + unsigned char has_noise_state:1; + unsigned char has_energy_ratio_relaxation:1; + + /* query 11 */ + unsigned char has_excessive_noise_reporting:1; + unsigned char has_slew_option:1; + unsigned char has_two_overhead_bursts:1; + unsigned char has_query13:1; + unsigned char has_one_overhead_burst:1; + unsigned char f54_query11_b5:1; + unsigned char has_ctrl88:1; + unsigned char has_query15:1; + + /* query 12 */ + unsigned char number_of_sensing_frequencies:4; + unsigned char f54_query12_b4__7:4; + } __packed; + unsigned char data[14]; + }; +}; + +struct f54_query_13 { + union { + struct { + unsigned char has_ctrl86:1; + unsigned char has_ctrl87:1; + unsigned char has_ctrl87_sub0:1; + unsigned char has_ctrl87_sub1:1; + unsigned char has_ctrl87_sub2:1; + unsigned char has_cidim:1; + unsigned char has_noise_mitigation_enhancement:1; + unsigned char has_rail_im:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_15 { + union { + struct { + unsigned char has_ctrl90:1; + unsigned char has_transmit_strength:1; + unsigned char has_ctrl87_sub3:1; + unsigned char has_query16:1; + unsigned char has_query20:1; + unsigned char has_query21:1; + unsigned char has_query22:1; + unsigned char has_query25:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_16 { + union { + struct { + unsigned char has_query17:1; + unsigned char has_data17:1; + unsigned char has_ctrl92:1; + unsigned char has_ctrl93:1; + unsigned char has_ctrl94_query18:1; + unsigned char has_ctrl95_query19:1; + unsigned char has_ctrl99:1; + unsigned char has_ctrl100:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_21 { + union { + struct { + unsigned char has_abs_rx:1; + unsigned char has_abs_tx:1; + unsigned char has_ctrl91:1; + unsigned char has_ctrl96:1; + unsigned char has_ctrl97:1; + unsigned char has_ctrl98:1; + unsigned char has_data19:1; + unsigned char has_query24_data18:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_22 { + union { + struct { + unsigned char has_packed_image:1; + unsigned char has_ctrl101:1; + unsigned char has_dynamic_sense_display_ratio:1; + unsigned char has_query23:1; + unsigned char has_ctrl103_query26:1; + unsigned char has_ctrl104:1; + unsigned char has_ctrl105:1; + unsigned char has_query28:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_23 { + union { + struct { + unsigned char has_ctrl102:1; + unsigned char has_ctrl102_sub1:1; + unsigned char has_ctrl102_sub2:1; + unsigned char has_ctrl102_sub4:1; + unsigned char has_ctrl102_sub5:1; + unsigned char has_ctrl102_sub9:1; + unsigned char has_ctrl102_sub10:1; + unsigned char has_ctrl102_sub11:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_25 { + union { + struct { + unsigned char has_ctrl106:1; + unsigned char has_ctrl102_sub12:1; + unsigned char has_ctrl107:1; + unsigned char has_ctrl108:1; + unsigned char has_ctrl109:1; + unsigned char has_data20:1; + unsigned char f54_query25_b6:1; + unsigned char has_query27:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_27 { + union { + struct { + unsigned char has_ctrl110:1; + unsigned char has_data21:1; + unsigned char has_ctrl111:1; + unsigned char has_ctrl112:1; + unsigned char has_ctrl113:1; + unsigned char has_data22:1; + unsigned char has_ctrl114:1; + unsigned char has_query29:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_29 { + union { + struct { + unsigned char has_ctrl115:1; + unsigned char has_ground_ring_options:1; + unsigned char has_lost_bursts_tuning:1; + unsigned char has_aux_exvcom2_select:1; + unsigned char has_ctrl116:1; + unsigned char has_data23:1; + unsigned char has_ctrl117:1; + unsigned char has_query30:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_30 { + union { + struct { + unsigned char has_ctrl118:1; + unsigned char has_ctrl119:1; + unsigned char has_ctrl120:1; + unsigned char has_ctrl121:1; + unsigned char has_ctrl122_query31:1; + unsigned char has_ctrl123:1; + unsigned char has_ctrl124:1; + unsigned char has_query32:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_32 { + union { + struct { + unsigned char has_ctrl125:1; + unsigned char has_ctrl126:1; + unsigned char has_ctrl127:1; + unsigned char has_abs_charge_pump_disable:1; + unsigned char has_query33:1; + unsigned char has_data24:1; + unsigned char has_query34:1; + unsigned char has_query35:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_33 { + union { + struct { + unsigned char has_ctrl128:1; + unsigned char has_ctrl129:1; + unsigned char has_ctrl130:1; + unsigned char has_ctrl131:1; + unsigned char has_ctrl132:1; + unsigned char has_ctrl133:1; + unsigned char has_ctrl134:1; + unsigned char has_query36:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_35 { + union { + struct { + unsigned char has_data25:1; + unsigned char has_ctrl135:1; + unsigned char has_ctrl136:1; + unsigned char has_ctrl137:1; + unsigned char has_ctrl138:1; + unsigned char has_ctrl139:1; + unsigned char has_data26:1; + unsigned char has_ctrl140:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_36 { + union { + struct { + unsigned char has_ctrl141:1; + unsigned char has_ctrl142:1; + unsigned char has_query37:1; + unsigned char has_ctrl143:1; + unsigned char has_ctrl144:1; + unsigned char has_ctrl145:1; + unsigned char has_ctrl146:1; + unsigned char has_query38:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_38 { + union { + struct { + unsigned char has_ctrl147:1; + unsigned char has_ctrl148:1; + unsigned char has_ctrl149:1; + unsigned char has_ctrl150:1; + unsigned char has_ctrl151:1; + unsigned char has_ctrl152:1; + unsigned char has_ctrl153:1; + unsigned char has_query39:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_39 { + union { + struct { + unsigned char has_ctrl154:1; + unsigned char has_ctrl155:1; + unsigned char has_ctrl156:1; + unsigned char has_ctrl160:1; + unsigned char has_ctrl157_ctrl158:1; + unsigned char f54_query39_b5__6:2; + unsigned char has_query40:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_40 { + union { + struct { + unsigned char has_ctrl169:1; + unsigned char has_ctrl163_query41:1; + unsigned char f54_query40_b2:1; + unsigned char has_ctrl165_query42:1; + unsigned char has_ctrl166:1; + unsigned char has_ctrl167:1; + unsigned char has_ctrl168:1; + unsigned char has_query43:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_43 { + union { + struct { + unsigned char f54_query43_b0__1:2; + unsigned char has_ctrl171:1; + unsigned char has_ctrl172_query44_query45:1; + unsigned char has_ctrl173:1; + unsigned char has_ctrl174:1; + unsigned char has_ctrl175:1; + unsigned char has_query46:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_46 { + union { + struct { + unsigned char has_ctrl176:1; + unsigned char has_ctrl177_ctrl178:1; + unsigned char has_ctrl179:1; + unsigned char f54_query46_b3:1; + unsigned char has_data27:1; + unsigned char has_data28:1; + unsigned char f54_query46_b6:1; + unsigned char has_query47:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_47 { + union { + struct { + unsigned char f54_query47_b0:1; + unsigned char has_ctrl182:1; + unsigned char has_ctrl183:1; + unsigned char f54_query47_b3:1; + unsigned char has_ctrl185:1; + unsigned char has_ctrl186:1; + unsigned char has_ctrl187:1; + unsigned char has_query49:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_49 { + union { + struct { + unsigned char f54_query49_b0__1:2; + unsigned char has_ctrl188:1; + unsigned char has_data31:1; + unsigned char f54_query49_b4__6:3; + unsigned char has_query50:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_50 { + union { + struct { + unsigned char f54_query50_b0__6:7; + unsigned char has_query51:1; + } __packed; + unsigned char data[1]; + }; +}; + +/* tddi f54 test reporting + */ +struct f54_query_51 { + union { + struct { + unsigned char f54_query51_b0:1; + unsigned char has_ctrl196:1; + unsigned char f54_query51_b2:1; + unsigned char f54_query51_b3:1; + unsigned char f54_query51_b4:1; + unsigned char has_query53_query54_ctrl198:1; + unsigned char has_ctrl199:1; + unsigned char has_query55:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_55 { + union { + struct { + unsigned char has_query56:1; + unsigned char has_data33_data34:1; + unsigned char has_alternate_report_rate:1; + unsigned char has_ctrl200:1; + unsigned char has_ctrl201_ctrl202:1; + unsigned char has_ctrl203:1; + unsigned char has_ctrl204:1; + unsigned char has_query57:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_57 { + union { + struct { + unsigned char has_ctrl205:1; + unsigned char has_ctrl206:1; + unsigned char has_usb_bulk_read:1; + unsigned char has_ctrl207:1; + unsigned char has_ctrl208:1; + unsigned char has_ctrl209:1; + unsigned char has_ctrl210:1; + unsigned char has_query58:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_58 { + union { + struct { + unsigned char has_query59:1; + unsigned char has_query60:1; + unsigned char has_ctrl211:1; + unsigned char has_ctrl212:1; + unsigned char has_hybrid_abs_tx_axis_filtering:1; + unsigned char f54_query58_b5:1; + unsigned char has_ctrl213:1; + unsigned char has_query61:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_61 { + union { + struct { + unsigned char has_ctrl214:1; + unsigned char has_ctrl215_query62_query63:1; + unsigned char f54_query61_b2__4:3; + unsigned char has_ctrl218:1; + unsigned char has_hybrid_abs_buttons:1; + unsigned char has_query64:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_64 { + union { + struct { + unsigned char f54_query64_b0:1; + unsigned char has_ctrl220:1; + unsigned char f54_query64_b2__3:2; + unsigned char has_ctrl219_sub1:1; + unsigned char has_ctrl103_sub3:1; + unsigned char has_ctrl224_ctrl226_ctrl227:1; + unsigned char has_query65:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_65 { + union { + struct { + unsigned char f54_query65_b0__4:5; + unsigned char has_query66_ctrl231:1; + unsigned char has_ctrl232:1; + unsigned char has_query67:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_67 { + union { + struct { + unsigned char has_abs_doze_spatial_filter_enable:1; + unsigned char has_abs_doze_average_filter_enable:1; + unsigned char has_single_display_pulse:1; + unsigned char f54_query67_b3__6:4; + unsigned char has_query68:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_68 { + union { + struct { + unsigned char f54_query68_b0__4:5; + unsigned char has_freq_filter_bw_ext:1; + unsigned char f54_query68_b6:1; + unsigned char has_query69:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_69 { + union { + struct { + unsigned char has_ctrl240_sub0:1; + unsigned char has_ctrl240_sub1_sub2:1; + unsigned char has_ctrl240_sub3:1; + unsigned char has_ctrl240_sub4:1; + unsigned char burst_mode_report_type_enabled:1; + unsigned char f54_query69_b5__7:3; + } __packed; + unsigned char data[1]; + }; +}; +/* tddi f54 test reporting - */ + +struct f54_data_31 { + union { + struct { + unsigned char is_calibration_crc:1; + unsigned char calibration_crc:1; + unsigned char short_test_row_number:5; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_7 { + union { + struct { + unsigned char cbc_cap:3; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char f54_ctrl7_b5__7:3; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_41 { + union { + struct { + unsigned char no_signal_clarity:1; + unsigned char f54_ctrl41_b1__7:7; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_57 { + union { + struct { + unsigned char cbc_cap:3; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char f54_ctrl57_b5__7:3; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_86 { + union { + struct { + unsigned char enable_high_noise_state:1; + unsigned char dynamic_sense_display_ratio:2; + unsigned char f54_ctrl86_b3__7:5; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_88 { + union { + struct { + unsigned char tx_low_reference_polarity:1; + unsigned char tx_high_reference_polarity:1; + unsigned char abs_low_reference_polarity:1; + unsigned char abs_polarity:1; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char charge_pump_enable:1; + unsigned char cbc_abs_auto_servo:1; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +/* tddi f54 test reporting + */ +struct f54_control_91 { + union { + struct { + unsigned char reflo_transcap_capacitance; + unsigned char refhi_transcap_capacitance; + unsigned char receiver_feedback_capacitance; + unsigned char reference_receiver_feedback_capacitance; + unsigned char gain_ctrl; + } __packed; + struct { + unsigned char data[5]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_96 { + union { + struct { + unsigned char cbc_transcap[64]; + } __packed; + struct { + unsigned char data[64]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_99 { + union { + struct { + unsigned char integration_duration_lsb; + unsigned char integration_duration_msb; + unsigned char reset_duration; + } __packed; + struct { + unsigned char data[3]; + unsigned short address; + } __packed; + }; +}; +/* tddi f54 test reporting - */ + +struct f54_control_110 { + union { + struct { + unsigned char active_stylus_rx_feedback_cap; + unsigned char active_stylus_rx_feedback_cap_reference; + unsigned char active_stylus_low_reference; + unsigned char active_stylus_high_reference; + unsigned char active_stylus_gain_control; + unsigned char active_stylus_gain_control_reference; + unsigned char active_stylus_timing_mode; + unsigned char active_stylus_discovery_bursts; + unsigned char active_stylus_detection_bursts; + unsigned char active_stylus_discovery_noise_multiplier; + unsigned char active_stylus_detection_envelope_min; + unsigned char active_stylus_detection_envelope_max; + unsigned char active_stylus_lose_count; + } __packed; + struct { + unsigned char data[13]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_149 { + union { + struct { + unsigned char trans_cbc_global_cap_enable:1; + unsigned char f54_ctrl149_b1__7:7; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_182 { + union { + struct { + unsigned char cbc_timing_ctrl_tx_lsb; + unsigned char cbc_timing_ctrl_tx_msb; + unsigned char cbc_timing_ctrl_rx_lsb; + unsigned char cbc_timing_ctrl_rx_msb; + } __packed; + struct { + unsigned char data[4]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_188 { + union { + struct { + unsigned char start_calibration:1; + unsigned char start_is_calibration:1; + unsigned char frequency:2; + unsigned char start_production_test:1; + unsigned char short_test_calibration:1; + unsigned char f54_ctrl188_b7:1; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_223 { + union { + struct { + unsigned char voltages_for_0d:8; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control { + struct f54_control_7 *reg_7; + struct f54_control_41 *reg_41; + struct f54_control_57 *reg_57; + struct f54_control_86 *reg_86; + struct f54_control_88 *reg_88; + struct f54_control_91 *reg_91; + struct f54_control_96 *reg_96; + struct f54_control_99 *reg_99; + struct f54_control_110 *reg_110; + struct f54_control_149 *reg_149; + struct f54_control_182 *reg_182; + struct f54_control_188 *reg_188; + struct f54_control_223 *reg_223; +}; + +struct synaptics_rmi4_f54_handle { + bool is_burst; + bool no_auto_cal; + bool skip_preparation; + bool burst_read; + unsigned char status; + unsigned char intr_mask; + unsigned char intr_reg_num; + unsigned char tx_assigned; + unsigned char rx_assigned; + /* tddi f54 test reporting + */ + unsigned char swap_sensor_side; + unsigned char left_mux_size; + unsigned char right_mux_size; + /*tddi f54 test reporting - */ + unsigned char *report_data; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short fifoindex; + unsigned int report_size; + unsigned int data_buffer_size; + unsigned int data_pos; + enum f54_report_types report_type; + struct f54_query query; + struct f54_query_13 query_13; + struct f54_query_15 query_15; + struct f54_query_16 query_16; + struct f54_query_21 query_21; + struct f54_query_22 query_22; + struct f54_query_23 query_23; + struct f54_query_25 query_25; + struct f54_query_27 query_27; + struct f54_query_29 query_29; + struct f54_query_30 query_30; + struct f54_query_32 query_32; + struct f54_query_33 query_33; + struct f54_query_35 query_35; + struct f54_query_36 query_36; + struct f54_query_38 query_38; + struct f54_query_39 query_39; + struct f54_query_40 query_40; + struct f54_query_43 query_43; + struct f54_query_46 query_46; + struct f54_query_47 query_47; + struct f54_query_49 query_49; + struct f54_query_50 query_50; + struct f54_query_51 query_51; + /* tddi f54 test reporting + */ + struct f54_query_55 query_55; + struct f54_query_57 query_57; + struct f54_query_58 query_58; + struct f54_query_61 query_61; + struct f54_query_64 query_64; + struct f54_query_65 query_65; + struct f54_query_67 query_67; + struct f54_query_68 query_68; + struct f54_query_69 query_69; + /* tddi f54 test reporting - */ + struct f54_data_31 data_31; + struct f54_control control; + struct mutex status_mutex; + struct kobject *sysfs_dir; + struct hrtimer watchdog; + struct work_struct timeout_work; + struct work_struct test_report_work; + struct workqueue_struct *test_report_workqueue; + struct synaptics_rmi4_data *rmi4_data; +}; + +struct f55_query { + union { + struct { + /* query 0 */ + unsigned char num_of_rx_electrodes; + + /* query 1 */ + unsigned char num_of_tx_electrodes; + + /* query 2 */ + unsigned char has_sensor_assignment:1; + unsigned char has_edge_compensation:1; + unsigned char curve_compensation_mode:2; + unsigned char has_ctrl6:1; + unsigned char has_alternate_transmitter_assignment:1; + unsigned char has_single_layer_multi_touch:1; + unsigned char has_query5:1; + } __packed; + unsigned char data[3]; + }; +}; + +struct f55_query_3 { + union { + struct { + unsigned char has_ctrl8:1; + unsigned char has_ctrl9:1; + unsigned char has_oncell_pattern_support:1; + unsigned char has_data0:1; + unsigned char has_single_wide_pattern_support:1; + unsigned char has_mirrored_tx_pattern_support:1; + unsigned char has_discrete_pattern_support:1; + unsigned char has_query9:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_5 { + union { + struct { + unsigned char has_corner_compensation:1; + unsigned char has_ctrl12:1; + unsigned char has_trx_configuration:1; + unsigned char has_ctrl13:1; + unsigned char f55_query5_b4:1; + unsigned char has_ctrl14:1; + unsigned char has_basis_function:1; + unsigned char has_query17:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_17 { + union { + struct { + unsigned char f55_query17_b0:1; + unsigned char has_ctrl16:1; + unsigned char has_ctrl18_ctrl19:1; + unsigned char has_ctrl17:1; + unsigned char has_ctrl20:1; + unsigned char has_ctrl21:1; + unsigned char has_ctrl22:1; + unsigned char has_query18:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_18 { + union { + struct { + unsigned char has_ctrl23:1; + unsigned char has_ctrl24:1; + unsigned char has_query19:1; + unsigned char has_ctrl25:1; + unsigned char has_ctrl26:1; + unsigned char has_ctrl27_query20:1; + unsigned char has_ctrl28_query21:1; + unsigned char has_query22:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_22 { + union { + struct { + unsigned char has_ctrl29:1; + unsigned char has_query23:1; + unsigned char has_guard_disable:1; + unsigned char has_ctrl30:1; + unsigned char has_ctrl31:1; + unsigned char has_ctrl32:1; + unsigned char has_query24_through_query27:1; + unsigned char has_query28:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_23 { + union { + struct { + unsigned char amp_sensor_enabled:1; + unsigned char image_transposed:1; + unsigned char first_column_at_left_side:1; + unsigned char size_of_column2mux:5; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_28 { + union { + struct { + unsigned char f55_query28_b0__4:5; + unsigned char has_ctrl37:1; + unsigned char has_query29:1; + unsigned char has_query30:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_30 { + union { + struct { + unsigned char has_ctrl38:1; + unsigned char has_query31_query32:1; + unsigned char has_ctrl39:1; + unsigned char has_ctrl40:1; + unsigned char has_ctrl41:1; + unsigned char has_ctrl42:1; + unsigned char has_ctrl43_ctrl44:1; + unsigned char has_query33:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_33 { + union { + struct { + unsigned char has_extended_amp_pad:1; + unsigned char has_extended_amp_btn:1; + unsigned char has_ctrl45_ctrl46:1; + unsigned char f55_query33_b3:1; + unsigned char has_ctrl47_sub0_sub1:1; + unsigned char f55_query33_b5__7:3; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_control_43 { + union { + struct { + unsigned char swap_sensor_side:1; + unsigned char f55_ctrl43_b1__7:7; + unsigned char afe_l_mux_size:4; + unsigned char afe_r_mux_size:4; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f55_handle { + bool amp_sensor; + bool extended_amp; + bool extended_amp_btn; + bool has_force; + unsigned char size_of_column2mux; + unsigned char afe_mux_offset; + unsigned char force_tx_offset; + unsigned char force_rx_offset; + unsigned char *tx_assignment; + unsigned char *rx_assignment; + unsigned char *force_tx_assignment; + unsigned char *force_rx_assignment; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + struct f55_query query; + struct f55_query_3 query_3; + struct f55_query_5 query_5; + struct f55_query_17 query_17; + struct f55_query_18 query_18; + struct f55_query_22 query_22; + struct f55_query_23 query_23; + struct f55_query_28 query_28; + struct f55_query_30 query_30; + struct f55_query_33 query_33; +}; + +struct f21_query_2 { + union { + struct { + unsigned char size_of_query3; + struct { + unsigned char query0_is_present:1; + unsigned char query1_is_present:1; + unsigned char query2_is_present:1; + unsigned char query3_is_present:1; + unsigned char query4_is_present:1; + unsigned char query5_is_present:1; + unsigned char query6_is_present:1; + unsigned char query7_is_present:1; + } __packed; + struct { + unsigned char query8_is_present:1; + unsigned char query9_is_present:1; + unsigned char query10_is_present:1; + unsigned char query11_is_present:1; + unsigned char query12_is_present:1; + unsigned char query13_is_present:1; + unsigned char query14_is_present:1; + unsigned char query15_is_present:1; + } __packed; + }; + unsigned char data[3]; + }; +}; + +struct f21_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct f21_query_11 { + union { + struct { + unsigned char has_high_resolution_force:1; + unsigned char has_force_sensing_txrx_mapping:1; + unsigned char f21_query11_00_b2__7:6; + unsigned char f21_query11_00_reserved; + unsigned char max_number_of_force_sensors; + unsigned char max_number_of_force_txs; + unsigned char max_number_of_force_rxs; + unsigned char f21_query11_01_reserved; + } __packed; + unsigned char data[6]; + }; +}; + +struct synaptics_rmi4_f21_handle { + bool has_force; + unsigned char tx_assigned; + unsigned char rx_assigned; + unsigned char max_num_of_tx; + unsigned char max_num_of_rx; + unsigned char max_num_of_txrx; + unsigned char *force_txrx_assignment; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; +}; + +show_prototype(num_of_mapped_tx) +show_prototype(num_of_mapped_rx) +show_prototype(tx_mapping) +show_prototype(rx_mapping) +show_prototype(num_of_mapped_force_tx) +show_prototype(num_of_mapped_force_rx) +show_prototype(force_tx_mapping) +show_prototype(force_rx_mapping) +show_prototype(report_size) +show_prototype(status) +show_prototype(ito_test_result) +store_prototype(do_preparation) +store_prototype(force_cal) +store_prototype(get_report) +store_prototype(resume_touch) +store_prototype(do_afe_calibration) +show_store_prototype(report_type) +show_store_prototype(fifoindex) +show_store_prototype(no_auto_cal) +show_store_prototype(read_report) +/* tddi f54 test reporting + */ +show_store_prototype(tddi_full_raw) +show_store_prototype(tddi_noise) +show_store_prototype(tddi_ee_short) +show_store_prototype(tddi_amp_open) +show_store_prototype(tddi_amp_electrode_open) +show_store_prototype(burst) +/* tddi f54 test reporting - */ + +static struct attribute *attrs[] = { + attrify(num_of_mapped_tx), + attrify(num_of_mapped_rx), + attrify(tx_mapping), + attrify(rx_mapping), + attrify(num_of_mapped_force_tx), + attrify(num_of_mapped_force_rx), + attrify(force_tx_mapping), + attrify(force_rx_mapping), + attrify(report_size), + attrify(status), + attrify(ito_test_result), + attrify(do_preparation), + attrify(force_cal), + attrify(get_report), + attrify(resume_touch), + attrify(do_afe_calibration), + attrify(report_type), + attrify(fifoindex), + attrify(no_auto_cal), + attrify(read_report), + /* tddi f54 test reporting + */ + attrify(tddi_full_raw), + attrify(tddi_noise), + attrify(tddi_ee_short), + attrify(tddi_amp_open), + attrify(tddi_amp_electrode_open), + attrify(burst), + /* tddi f54 test reporting - */ + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = attrs, +}; + +static ssize_t test_sysfs_data_read(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static struct bin_attribute test_report_data = { + .attr = { + .name = "report_data", + .mode = S_IRUGO, + }, + .size = 0, + .read = test_sysfs_data_read, +}; + +static struct synaptics_rmi4_f54_handle *f54; +static struct synaptics_rmi4_f55_handle *f55; +static struct synaptics_rmi4_f21_handle *f21; + + +/* tddi f54 test reporting + */ + + + +static unsigned char *g_tddi_full_raw_data_output; + + + +static signed short *g_tddi_noise_data_output; + + + +static unsigned char *g_tddi_ee_short_data_output; + + + +static unsigned char *g_tddi_amp_open_data_output; + + + + + + + +static bool g_flag_readrt_err; + +/* tddi f54 test reporting - */ + +DECLARE_COMPLETION(test_remove_complete); + +static bool test_report_type_valid(enum f54_report_types report_type) +{ + switch (report_type) { + case F54_8BIT_IMAGE: + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_HIGH_RESISTANCE: + case F54_TX_TO_TX_SHORTS: + case F54_RX_TO_RX_SHORTS_1: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP_MIN_MAX: + case F54_RX_OPENS_1: + case F54_TX_OPENS: + case F54_TX_TO_GND_SHORTS: + case F54_RX_TO_RX_SHORTS_2: + case F54_RX_OPENS_2: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_TRX_OPENS: + case F54_TRX_TO_GND_SHORTS: + case F54_TRX_SHORTS: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_AMP_FULL_RAW_CAP: + case F54_AMP_RAW_ADC: + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + case F54_NOISE_TDDI: + case F54_EE_SHORT_TDDI: + /* tddi f54 test reporting - */ + return true; + break; + default: + f54->report_type = INVALID_REPORT_TYPE; + f54->report_size = 0; + return false; + } +} + +static void test_set_report_size(void) +{ + int retval; + unsigned char tx = f54->tx_assigned; + unsigned char rx = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + switch (f54->report_type) { + case F54_8BIT_IMAGE: + f54->report_size = tx * rx; + break; + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_AMP_FULL_RAW_CAP: + case F54_AMP_RAW_ADC: + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + if (f55->extended_amp_btn) { + tx += 1; + } + f54->report_size = 2 * tx * rx; + break; + case F54_NOISE_TDDI: + /* tddi f54 test reporting - */ + f54->report_size = 2 * tx * rx; + break; + /* tddi f54 test reporting + */ + case F54_EE_SHORT_TDDI: + f54->report_size = 2 * 2 * tx * rx; + break; + /* tddi f54 test reporting - */ + case F54_HIGH_RESISTANCE: + f54->report_size = HIGH_RESISTANCE_DATA_SIZE; + break; + case F54_TX_TO_TX_SHORTS: + case F54_TX_OPENS: + case F54_TX_TO_GND_SHORTS: + f54->report_size = (tx + 7) / 8; + break; + case F54_RX_TO_RX_SHORTS_1: + case F54_RX_OPENS_1: + if (rx < tx) + f54->report_size = 2 * rx * rx; + else + f54->report_size = 2 * tx * rx; + break; + case F54_FULL_RAW_CAP_MIN_MAX: + f54->report_size = FULL_RAW_CAP_MIN_MAX_DATA_SIZE; + break; + case F54_RX_TO_RX_SHORTS_2: + case F54_RX_OPENS_2: + if (rx <= tx) + f54->report_size = 0; + else + f54->report_size = 2 * rx * (rx - tx); + break; + case F54_ADC_RANGE: + if (f54->query.has_signal_clarity) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_41->address, + f54->control.reg_41->data, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read control reg_41\n", + __func__); + f54->report_size = 0; + break; + } + if (!f54->control.reg_41->no_signal_clarity) { + if (tx % 4) + tx += 4 - (tx % 4); + } + } + f54->report_size = 2 * tx * rx; + break; + case F54_TRX_OPENS: + case F54_TRX_TO_GND_SHORTS: + case F54_TRX_SHORTS: + f54->report_size = TRX_OPEN_SHORT_DATA_SIZE; + break; + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + tx += f21->tx_assigned; + rx += f21->rx_assigned; + f54->report_size = 4 * (tx + rx); + break; + default: + f54->report_size = 0; + } + + return; +} + +static int test_set_interrupt(bool set) +{ + int retval; + unsigned char ii; + unsigned char zero = 0x00; + unsigned char *intr_mask; + unsigned short f01_ctrl_reg; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + intr_mask = rmi4_data->intr_mask; + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + f54->intr_reg_num; + + if (!set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } + + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { + if (intr_mask[ii] != 0x00) { + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + ii; + if (set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &(intr_mask[ii]), + sizeof(intr_mask[ii])); + if (retval < 0) + return retval; + } + } + } + + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + f54->intr_reg_num; + + if (set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &f54->intr_mask, + 1); + if (retval < 0) + return retval; + } + + return 0; +} + +static int test_wait_for_command_completion(void) +{ + int retval; + unsigned char value; + unsigned char timeout_count; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + timeout_count = 0; + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->command_base_addr, + &value, + sizeof(value)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command register\n", + __func__); + return retval; + } + + if (value == 0x00) + break; + + msleep(100); + timeout_count++; + } while (timeout_count < COMMAND_TIMEOUT_100MS); + + if (timeout_count == COMMAND_TIMEOUT_100MS) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for command completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int test_do_command(unsigned char command) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + retval = test_wait_for_command_completion(); + if (retval < 0) + return retval; + + return 0; +} + +static int test_do_preparation(void) +{ + int retval; + unsigned char value; + unsigned char zero = 0x00; + unsigned char device_ctrl; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set no sleep\n", + __func__); + return retval; + } + + device_ctrl |= NO_SLEEP_ON; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set no sleep\n", + __func__); + return retval; + } + + if (f54->skip_preparation) + return 0; + + switch (f54->report_type) { + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + case F54_NOISE_TDDI: + case F54_EE_SHORT_TDDI: + /* tddi f54 test reporting - */ + break; + case F54_AMP_RAW_ADC: + if (f54->query_49.has_ctrl188) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + f54->control.reg_188->start_production_test = 1; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + } + break; + default: + if (f54->query.touch_controller_family == 1) + disable_cbc(reg_7); + else if (f54->query.has_ctrl88) + disable_cbc(reg_88); + + if (f54->query.has_0d_acquisition_control) + disable_cbc(reg_57); + + if ((f54->query.has_query15) && + (f54->query_15.has_query25) && + (f54->query_25.has_query27) && + (f54->query_27.has_query29) && + (f54->query_29.has_query30) && + (f54->query_30.has_query32) && + (f54->query_32.has_query33) && + (f54->query_33.has_query36) && + (f54->query_36.has_query38) && + (f54->query_38.has_ctrl149)) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_149->address, + &zero, + sizeof(f54->control.reg_149->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable global CBC\n", + __func__); + return retval; + } + } + + if (f54->query.has_signal_clarity) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_41->address, + &value, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable signal clarity\n", + __func__); + return retval; + } + value |= 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_41->address, + &value, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable signal clarity\n", + __func__); + return retval; + } + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update\n", + __func__); + return retval; + } + + retval = test_do_command(COMMAND_FORCE_CAL); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force cal\n", + __func__); + return retval; + } + } + + return 0; +} + +static int test_do_afe_calibration(enum f54_afe_cal mode) +{ + int retval; + unsigned char timeout = CALIBRATION_TIMEOUT_S; + unsigned char timeout_count = 0; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to start calibration\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) + f54->control.reg_188->start_calibration = 1; + else if (mode == F54_AFE_IS_CAL) + f54->control.reg_188->start_is_calibration = 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to start calibration\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete calibration\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) { + if (!f54->control.reg_188->start_calibration) + break; + } else if (mode == F54_AFE_IS_CAL) { + if (!f54->control.reg_188->start_is_calibration) + break; + } + + if (timeout_count == timeout) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for calibration completion\n", + __func__); + return -EBUSY; + } + + timeout_count++; + msleep(1000); + } while (true); + + /* check CRC */ + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_31.address, + f54->data_31.data, + sizeof(f54->data_31.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read calibration CRC\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) { + if (f54->data_31.calibration_crc == 0) + return 0; + } else if (mode == F54_AFE_IS_CAL) { + if (f54->data_31.is_calibration_crc == 0) + return 0; + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read calibration CRC\n", + __func__); + + return -EINVAL; +} + +static int test_check_for_idle_status(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + switch (f54->status) { + case STATUS_IDLE: + retval = 0; + break; + case STATUS_BUSY: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Status busy\n", + __func__); + retval = -EINVAL; + break; + case STATUS_ERROR: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Status error\n", + __func__); + retval = -EINVAL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid status (%d)\n", + __func__, f54->status); + retval = -EINVAL; + } + + return retval; +} + +static void test_timeout_work(struct work_struct *work) +{ + int retval; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + if (f54->status == STATUS_BUSY) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command register\n", + __func__); + } else if (command & COMMAND_GET_REPORT) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type not supported by FW\n", + __func__); + } else { + queue_work(f54->test_report_workqueue, + &f54->test_report_work); + goto exit; + } + f54->status = STATUS_ERROR; + f54->report_size = 0; + } + +exit: + mutex_unlock(&f54->status_mutex); + + return; +} + +static enum hrtimer_restart test_get_report_timeout(struct hrtimer *timer) +{ + schedule_work(&(f54->timeout_work)); + + return HRTIMER_NORESTART; +} + +static ssize_t test_sysfs_num_of_mapped_tx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->tx_assigned); +} + +static ssize_t test_sysfs_num_of_mapped_rx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->rx_assigned); +} + +static ssize_t test_sysfs_tx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char tx_num; + unsigned char tx_electrodes; + + if (!f55) + return -EINVAL; + + tx_electrodes = f55->query.num_of_tx_electrodes; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f55->tx_assignment[ii]; + if (tx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", tx_num); + buf += cnt; + count += cnt; + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_rx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char rx_num; + unsigned char rx_electrodes; + + if (!f55) + return -EINVAL; + + rx_electrodes = f55->query.num_of_rx_electrodes; + + for (ii = 0; ii < rx_electrodes; ii++) { + rx_num = f55->rx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", rx_num); + buf += cnt; + count += cnt; + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_num_of_mapped_force_tx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f21->tx_assigned); +} + +static ssize_t test_sysfs_num_of_mapped_force_rx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f21->rx_assigned); +} + +static ssize_t test_sysfs_force_tx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char tx_num; + unsigned char tx_electrodes; + + if ((!f55 || !f55->has_force) && (!f21 || !f21->has_force)) + return -EINVAL; + + if (f55->has_force) { + tx_electrodes = f55->query.num_of_tx_electrodes; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f55->force_tx_assignment[ii]; + if (tx_num == 0xff) { + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + tx_num); + } + buf += cnt; + count += cnt; + } + } else if (f21->has_force) { + tx_electrodes = f21->max_num_of_tx; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f21->force_txrx_assignment[ii]; + if (tx_num == 0xff) { + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + tx_num); + } + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_force_rx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char offset; + unsigned char rx_num; + unsigned char rx_electrodes; + + if ((!f55 || !f55->has_force) && (!f21 || !f21->has_force)) + return -EINVAL; + + if (f55->has_force) { + rx_electrodes = f55->query.num_of_rx_electrodes; + + for (ii = 0; ii < rx_electrodes; ii++) { + rx_num = f55->force_rx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + rx_num); + buf += cnt; + count += cnt; + } + } else if (f21->has_force) { + offset = f21->max_num_of_tx; + rx_electrodes = f21->max_num_of_rx; + + for (ii = offset; ii < (rx_electrodes + offset); ii++) { + rx_num = f21->force_txrx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + rx_num); + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_report_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->report_size); +} + +static ssize_t test_sysfs_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + mutex_lock(&f54->status_mutex); + + retval = snprintf(buf, PAGE_SIZE, "%u\n", f54->status); + + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_do_preparation_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + retval = test_do_preparation(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do preparation\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_force_cal_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + retval = test_do_command(COMMAND_FORCE_CAL); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force cal\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +/* tddi f54 test reporting + */ +#ifdef F54_POLLING_GET_REPORT +static ssize_t test_sysfs_get_report_polling(void) +{ + int retval = 0; + unsigned char report_index[2]; + unsigned int byte_delay_us; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_wait_for_command_completion(); + if (retval < 0) { + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + test_set_report_size(); + if (f54->report_size == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report data size = 0\n", __func__); + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + if (f54->data_buffer_size < f54->report_size) { + if (f54->data_buffer_size) + kfree(f54->report_data); + f54->report_data = kzalloc(f54->report_size, GFP_KERNEL); + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", __func__); + f54->data_buffer_size = 0; + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + f54->data_buffer_size = f54->report_size; + } + + report_index[0] = 0; + report_index[1] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + report_index, + sizeof(report_index)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report data index\n", __func__); + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) { + byte_delay_us = rmi4_data->hw_if->board_data->byte_delay_us; + rmi4_data->hw_if->board_data->byte_delay_us = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_DATA_OFFSET, + f54->report_data, + f54->report_size); + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) + rmi4_data->hw_if->board_data->byte_delay_us = byte_delay_us; + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report data\n", + __func__); + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + f54->status = STATUS_IDLE; + return retval; +} +#endif +/* tddi f54 test reporting - */ + +static ssize_t test_sysfs_get_report_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char command; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!test_report_type_valid(f54->report_type)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid report type\n", + __func__); + retval = -EINVAL; + goto exit; + } + + test_set_interrupt(true); + + command = (unsigned char)COMMAND_GET_REPORT; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write get report command\n", + __func__); + goto exit; + } + +/* tddi f54 test reporting + */ +#ifdef F54_POLLING_GET_REPORT + + retval = test_sysfs_get_report_polling(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get report image\n", + __func__); + goto exit; + } + +#else +/* tddi f54 test reporting - */ + + f54->status = STATUS_BUSY; + f54->report_size = 0; + f54->data_pos = 0; + + hrtimer_start(&f54->watchdog, + ktime_set(GET_REPORT_TIMEOUT_S, 0), + HRTIMER_MODE_REL); + + retval = count; + +#endif + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_resume_touch_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char device_ctrl; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore no sleep setting\n", + __func__); + return retval; + } + + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + device_ctrl |= rmi4_data->no_sleep_setting; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore no sleep setting\n", + __func__); + return retval; + } + + test_set_interrupt(false); + + if (f54->skip_preparation) + return count; + + switch (f54->report_type) { + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_FULL_RAW_CAP_TDDI: + /* tddi f54 test reporting + */ + case F54_NOISE_TDDI: + case F54_EE_SHORT_TDDI: + /* tddi f54 test reporting - */ + break; + case F54_AMP_RAW_ADC: + if (f54->query_49.has_ctrl188) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + f54->control.reg_188->start_production_test = 0; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + } + break; + default: + rmi4_data->reset_device(rmi4_data, false); + } + + return count; +} + +static ssize_t test_sysfs_do_afe_calibration_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (!f54->query_49.has_ctrl188) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: F54_ANALOG_Ctrl188 not found\n", + __func__); + return -EINVAL; + } + + if (setting == 0 || setting == 1) + retval = test_do_afe_calibration((enum f54_afe_cal)setting); + else + return -EINVAL; + + if (retval) + return retval; + else + return count; +} + +static ssize_t test_sysfs_report_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->report_type); +} + +static ssize_t test_sysfs_report_type_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!test_report_type_valid((enum f54_report_types)setting)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type not supported by driver\n", + __func__); + retval = -EINVAL; + goto exit; + } + + f54->report_type = (enum f54_report_types)setting; + data = (unsigned char)setting; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report type\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_fifoindex_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned char data[2]; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report index\n", + __func__); + return retval; + } + + batohs(&f54->fifoindex, data); + + return snprintf(buf, PAGE_SIZE, "%u\n", f54->fifoindex); +} + +static ssize_t test_sysfs_fifoindex_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data[2]; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + f54->fifoindex = setting; + + hstoba(data, (unsigned short)setting); + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report index\n", + __func__); + return retval; + } + + return count; +} + +static ssize_t test_sysfs_no_auto_cal_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->no_auto_cal); +} + +static ssize_t test_sysfs_no_auto_cal_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting > 1) + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read no auto cal setting\n", + __func__); + return retval; + } + + if (setting) + data |= CONTROL_NO_AUTO_CAL; + else + data &= ~CONTROL_NO_AUTO_CAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write no auto cal setting\n", + __func__); + return retval; + } + + f54->no_auto_cal = (setting == 1); + + return count; +} + +static int check_ito_test_flag = 2; +#ifdef SYNAPTICS_ESD_CHECK +extern void synaptics_rmi4_esd_work(struct work_struct *work); +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +extern struct synaptics_rmi4_data *rmi4_data; +#endif +static ssize_t test_sysfs_read_report_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int ii; + unsigned int jj; + int cnt; + int count = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + char *report_data_8; + short *report_data_16; + int *report_data_32; + unsigned short *report_data_u16; + unsigned int *report_data_u32; + +#ifdef SYNAPTICS_ESD_CHECK + printk("%s SYNAPTICS_ESD_CHECK is off\n", __func__); + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + switch (f54->report_type) { + case F54_8BIT_IMAGE: + printk("F54_8BIT_IMAGE\n"); + report_data_8 = (char *)f54->report_data; + for (ii = 0; ii < f54->report_size; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: %d\n", + ii, *report_data_8); + report_data_8++; + buf += cnt; + count += cnt; + } + break; + case F54_AMP_RAW_ADC: + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + break; + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_AMP_FULL_RAW_CAP: + /* tddi f54 test reporting + */ + case F54_NOISE_TDDI: + /* tddi f54 test reporting - */ + printk("start F54_NOISE_TDDI\n"); + report_data_16 = (short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", + *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d\n", + *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + break; + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + printk("start F54_FULL_RAW_CAP_TDDI\n"); + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", + *report_data_u16); + if (*report_data_16 <= 1700 || *report_data_16 >= 2300){ + if ((jj == 24) && (ii != 1) && (ii != 6) && (ii != 12)){ + check_ito_test_flag = 1; + } else{ + check_ito_test_flag = 0; + } + }else{ + check_ito_test_flag = 0; + } + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + if (1 == check_ito_test_flag){ + cnt = snprintf(buf, PAGE_SIZE - count, "fail\n"); + buf += cnt; + count += cnt; + printk("[synaptics]ITO test fail\n"); + }else{ + cnt = snprintf(buf, PAGE_SIZE - count, "pass\n"); + buf += cnt; + count += cnt; + printk("[synaptics]ITO test pass\n"); + } + break; + case F54_EE_SHORT_TDDI: + printk("start F54_EE_SHORT_TDDI\n"); + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + break; + /* tddi f54 test reporting - */ + case F54_HIGH_RESISTANCE: + case F54_FULL_RAW_CAP_MIN_MAX: + report_data_16 = (short *)f54->report_data; + for (ii = 0; ii < f54->report_size; ii += 2) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: %d\n", + ii / 2, *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + break; + case F54_ABS_RAW_CAP: + case F54_ABS_HYBRID_RAW_CAP: + tx_num += f21->tx_assigned; + rx_num += f21->rx_assigned; + report_data_u32 = (unsigned int *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "rx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5u", + *report_data_u32); + report_data_u32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, "tx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5u", + *report_data_u32); + report_data_u32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + break; + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + tx_num += f21->tx_assigned; + rx_num += f21->rx_assigned; + report_data_32 = (int *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "rx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5d", + *report_data_32); + report_data_32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, "tx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5d", + *report_data_32); + report_data_32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + break; + default: + for (ii = 0; ii < f54->report_size; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: 0x%02x\n", + ii, f54->report_data[ii]); + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + +#ifdef SYNAPTICS_ESD_CHECK + printk("%s SYNAPTICS_ESD_CHECK is on\n", __func__); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + return count; +} + +static ssize_t test_sysfs_read_report_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char timeout = GET_REPORT_TIMEOUT_S * 10; + unsigned char timeout_count; + const char cmd[] = {'1', 0}; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_sysfs_report_type_store(dev, attr, buf, count); + if (retval < 0) + goto exit; + + retval = test_sysfs_do_preparation_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + retval = test_sysfs_get_report_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + timeout_count = 0; + do { + if (f54->status != STATUS_BUSY) + break; + msleep(100); + timeout_count++; + } while (timeout_count < timeout); + + if ((f54->status != STATUS_IDLE) || (f54->report_size == 0)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = test_sysfs_resume_touch_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + return count; + +exit: + rmi4_data->reset_device(rmi4_data, false); + + return retval; +} + +static ssize_t test_sysfs_ito_test_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + printk("synaptics check_ito_test_flag = %d\n", check_ito_test_flag); + if (4 == check_ito_test_flag){ + return snprintf(buf, PAGE_SIZE, "%s\n", "pass"); + }else{ + return snprintf(buf, PAGE_SIZE, "%s\n", "fail"); + } +} + +/* tddi f54 test reporting + */ +static ssize_t test_sysfs_read_report(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count, + bool do_preparation, bool do_reset) +{ + int retval = count; + unsigned char timeout = GET_REPORT_TIMEOUT_S * 10; + unsigned char timeout_count; + const char cmd[] = {'1', 0}; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_sysfs_report_type_store(dev, attr, buf, count); + if (retval < 0) + goto exit; + + if (do_preparation){ + retval = test_sysfs_do_preparation_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + } + retval = test_sysfs_get_report_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + timeout_count = 0; + do { + if (f54->status != STATUS_BUSY) + break; + msleep(100); + timeout_count++; + } while (timeout_count < timeout); + + if ((f54->status != STATUS_IDLE) || (f54->report_size == 0)) { + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report\n", + __func__); + retval = -EINVAL; + goto exit; + } + +exit: + if (do_reset) + rmi4_data->reset_device(rmi4_data, false); + + return retval; +} + +static short find_median(short *pdata, int num) +{ + int i, j; + short temp; + short *value; + short median; + + value = (short *)kzalloc(num * sizeof(short), GFP_KERNEL); + + for (i = 0; i < num; i++) + *(value+i) = *(pdata+i); + + + for (i = 1; i < = num-1; i++) + { + for (j = 1; j < = num-i; j++) + { + if (*(value+j-1) <= *(value+j)) + { + temp = *(value+j-1); + *(value+j-1) = *(value+j); + *(value+j) = temp; + } + else + continue ; + } + } + + + if (num % 2 == 0) + median = (*(value+(num/2 -1)) + *(value+(num/2)))/2; + else + median = *(value+(num/2)); + + if (value) + kfree(value); + + return median; +} + +static int tddi_ratio_calculation(signed short *p_image) +{ + int retval = 0; + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + unsigned char left_size = f54->left_mux_size; + unsigned char right_size = f54->right_mux_size; + signed short *p_data_16; + signed short *p_left_median = NULL; + signed short *p_right_median = NULL; + signed short *p_left_column_buf = NULL; + signed short *p_right_column_buf = NULL; + signed int temp; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + if (!p_image) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Fail. p_image is null\n", __func__); + retval = -EINVAL; + goto exit; + } + + + p_right_median = (signed short *) kzalloc(rx_num * sizeof(short), GFP_KERNEL); + if (!p_right_median) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_right_median\n", __func__); + retval = -ENOMEM; + goto exit; + } + + p_left_median = (signed short *) kzalloc(rx_num * sizeof(short), GFP_KERNEL); + if (!p_left_median) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_left_median\n", __func__); + retval = -ENOMEM; + goto exit; + } + + p_right_column_buf = (signed short *) kzalloc(right_size * rx_num * sizeof(short), GFP_KERNEL); + if (!p_right_column_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_right_column_buf\n", __func__); + retval = -ENOMEM; + goto exit; + } + + p_left_column_buf = (signed short *) kzalloc(left_size * rx_num * sizeof(short), GFP_KERNEL); + if (!p_left_column_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_left_column_buf\n", __func__); + retval = -ENOMEM; + goto exit; + } + + + if (f54->swap_sensor_side) { + + + p_data_16 = p_image; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < left_size; j++) { + p_left_column_buf[i * left_size + j] = p_data_16[j * rx_num + i]; + } + } + + p_data_16 = p_image + left_size * rx_num; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < right_size; j++) { + p_right_column_buf[i * right_size + j] = p_data_16[j * rx_num + i]; + } + } + } + else { + + + p_data_16 = p_image; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < right_size; j++) { + p_right_column_buf[i * right_size + j] = p_data_16[j * rx_num + i]; + } + } + + p_data_16 = p_image + right_size * rx_num; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < left_size; j++) { + p_left_column_buf[i * left_size + j] = p_data_16[j * rx_num + i]; + } + } + } + + + for (i = 0; i < rx_num; i++) { + p_left_median[i] = find_median(p_left_column_buf + i * left_size, left_size); + p_right_median[i] = find_median(p_right_column_buf + i * right_size, right_size); + } + + + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + + + if (f54->swap_sensor_side) { + + if (i < left_size) { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_left_median[j]; + } else { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_right_median[j]; + } + } + else { + + if (i < right_size) { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_right_median[j]; + } else { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_left_median[j]; + } + } + + + p_image[i * rx_num + j] = temp; + } + } + +exit: + kfree(p_right_median); + kfree(p_left_median); + kfree(p_right_column_buf); + kfree(p_left_column_buf); + return retval; +} + +static ssize_t test_sysfs_tddi_ee_short_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + int i, j, offset; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + signed short *tddi_rt95_part_one = NULL; + signed short *tddi_rt95_part_two = NULL; + unsigned int buffer_size = tx_num * rx_num * 2; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + /* allocate the g_tddi_ee_short_data_output */ + if (g_tddi_ee_short_data_output) + kfree(g_tddi_ee_short_data_output); + + g_tddi_ee_short_data_output = kzalloc(tx_num * rx_num, GFP_KERNEL); + if (!g_tddi_ee_short_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_ee_short_data_output\n", + __func__); + return -ENOMEM; + } + + + tddi_rt95_part_one = kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_rt95_part_one) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_rt95_part_one\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + tddi_rt95_part_two = kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_rt95_part_two) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for td43xx_rt95_part_two\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + g_flag_readrt_err = false; + + /* step 1 */ + /* get report image 95 */ + retval = test_sysfs_read_report(dev, attr, "95", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 95. exit\n", __func__); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + + /* step 2 */ + /* use the upper half as part 1 image */ + /* the data should be lower than TEST_LIMIT_PART1 ( fail, if > TEST_LIMIT_PART1 ) */ + for (i = 0, offset = 0; i < tx_num * rx_num; i++) { + tddi_rt95_part_one[i] = (signed short)(f54->report_data[offset]) | + ((signed short)(f54->report_data[offset + 1]) << 8); + offset += 2; + } + +#ifdef F54_SHOW_MAX_MIN + min = max = tddi_rt95_part_one[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, tddi_rt95_part_one[i*rx_num + j], min); + max = max_t(signed short, tddi_rt95_part_one[i*rx_num + j], max); +#endif + if (tddi_rt95_part_one[i*rx_num + j] > EE_SHORT_TEST_LIMIT_PART1) { + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d in part 1 image (limit = %d)\n", + __func__, i, j, tddi_rt95_part_one[i*rx_num + j], EE_SHORT_TEST_LIMIT_PART1); + + tddi_rt95_part_one[i*rx_num + j] = _TEST_FAIL; + } + else { + tddi_rt95_part_one[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : image part 1 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + /* step 3 */ + /* use the lower half as part 2 image */ + /* and perform the calculation */ + /* the calculated data should be over than TEST_LIMIT_PART2 ( fail, if < TEST_LIMIT_PART2 ) */ + for (i = 0, offset = buffer_size; i < tx_num * rx_num; i++) { + tddi_rt95_part_two[i] = (signed short)(f54->report_data[offset]) | + ((signed short)(f54->report_data[offset + 1]) << 8); + offset += 2; + } + + + tddi_ratio_calculation(tddi_rt95_part_two); + +#ifdef F54_SHOW_MAX_MIN + min = max = tddi_rt95_part_two[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, tddi_rt95_part_two[i*rx_num + j], min); + max = max_t(signed short, tddi_rt95_part_two[i*rx_num + j], max); +#endif + if (tddi_rt95_part_two[i*rx_num + j] < EE_SHORT_TEST_LIMIT_PART2) { + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d in part 2 image (limit = %d)\n", + __func__, i, j, tddi_rt95_part_two[i*rx_num + j], EE_SHORT_TEST_LIMIT_PART2); + + tddi_rt95_part_two[i*rx_num + j] = _TEST_FAIL; + } + else { + tddi_rt95_part_two[i*rx_num + j] = _TEST_PASS; + } + } + } + +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : image part 2 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + /* step 4 */ + /* filling out the g_tddi_ee_short_data_output */ + /* 1: fail / 0 : pass */ + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_ee_short_data_output[i * rx_num + j] = + (unsigned char)(tddi_rt95_part_one[i * rx_num + j]) || tddi_rt95_part_two[i * rx_num + j]; + } + } + + retval = count; + +exit: + kfree(tddi_rt95_part_one); + kfree(tddi_rt95_part_two); + + return retval; +} + +static ssize_t test_sysfs_tddi_ee_short_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + if (!g_tddi_ee_short_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_ee_short_data_output); + g_tddi_ee_short_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_ee_short_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_ee_short_data_output); + g_tddi_ee_short_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +static ssize_t test_sysfs_tddi_noise_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int i, j, offset; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int repeat; + + signed short report_data_16; + signed short *tddi_noise_max = NULL; + signed short *tddi_noise_min = NULL; + unsigned char *tddi_noise_data = NULL; + unsigned int buffer_size = tx_num * rx_num * 2; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + /* allocate the g_tddi_noise_data_output */ + if (g_tddi_noise_data_output) + kfree(g_tddi_noise_data_output); + + g_tddi_noise_data_output = (signed short *)kzalloc(tx_num * rx_num *sizeof(short), GFP_KERNEL); + if (!g_tddi_noise_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_noise_data_output\n", + __func__); + return -ENOMEM; + } + + tddi_noise_data = kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_noise_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_noise_data\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + tddi_noise_max = (unsigned short *)kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_noise_max) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_noise_max\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + tddi_noise_min = (unsigned short *) kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_noise_min) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_noise_min\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + g_flag_readrt_err = false; + + /* get report image 94 repeatedly */ + /* and calculate the minimum and maximun value as well */ + for (repeat = 0 ; repeat < NOISE_TEST_NUM_OF_FRAMES; repeat++){ + + retval = test_sysfs_read_report(dev, attr, "94", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 94 at %d round. exit\n", + __func__, repeat); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + memset(tddi_noise_data, 0x00, buffer_size); + + secure_memcpy(tddi_noise_data, buffer_size, + f54->report_data, f54->report_size, f54->report_size); + + for (i = 0, offset = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + + report_data_16 = + (signed short)tddi_noise_data[offset] + + ((signed short)tddi_noise_data[offset+1] << 8); + offset += 2; + + tddi_noise_max[i*rx_num + j] = + max_t(signed short, tddi_noise_max[i*rx_num + j], report_data_16); + tddi_noise_min[i*rx_num + j] = + min_t(signed short, tddi_noise_min[i*rx_num + j], report_data_16); + } + } + + } + + + + + +#ifdef F54_SHOW_MAX_MIN + min = tddi_noise_max[0]; + max = tddi_noise_min[0]; +#endif + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_noise_data_output[i*rx_num + j] = + tddi_noise_max[i*rx_num + j] - tddi_noise_min[i*rx_num + j]; + +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, g_tddi_noise_data_output[i*rx_num + j], min); + max = max_t(signed short, g_tddi_noise_data_output[i*rx_num + j], max); +#endif + + if (g_tddi_noise_data_output[i*rx_num + j] > NOISE_TEST_LIMIT) { + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d (limit = %d)\n", + __func__, i, j, g_tddi_noise_data_output[i*rx_num + j], NOISE_TEST_LIMIT); + + g_tddi_noise_data_output[i*rx_num + j] = _TEST_FAIL; + } + else { + g_tddi_noise_data_output[i*rx_num + j] = _TEST_PASS; + } + + } + } + +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + retval = count; + +exit: + kfree(tddi_noise_max); + kfree(tddi_noise_min); + kfree(tddi_noise_data); + + return retval; +} + +static ssize_t test_sysfs_tddi_noise_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + if (!g_tddi_noise_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_noise_data_output); + g_tddi_noise_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_noise_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_noise_data_output); + g_tddi_noise_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +static ssize_t test_sysfs_tddi_full_raw_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + unsigned int full_raw_report_size; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + + if (f55->extended_amp_btn) { + tx_num += 1; + } + full_raw_report_size = tx_num * rx_num * 2; + + g_flag_readrt_err = false; + + /* allocate the g_tddi_full_raw_data_output */ + if (g_tddi_full_raw_data_output) + kfree(g_tddi_full_raw_data_output); + + g_tddi_full_raw_data_output = kzalloc(full_raw_report_size, GFP_KERNEL); + if (!g_tddi_full_raw_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_full_raw_data_output\n", + __func__); + return -ENOMEM; + } + + /* get the report image 92 */ + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92. exit\n", __func__); + g_flag_readrt_err = true ; + return -EIO; + } + + secure_memcpy(g_tddi_full_raw_data_output, full_raw_report_size, + f54->report_data, f54->report_size, f54->report_size); + + retval = count; + + return retval; +} + +static ssize_t test_sysfs_tddi_full_raw_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int i; + unsigned int j; + unsigned int k; + int cnt; + int count = 0; + int fail_count = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + unsigned short *report_data_16; + + unsigned short min = 0, max = 0; + + if (!g_tddi_full_raw_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_full_raw_data_output); + g_tddi_full_raw_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + + + + + + report_data_16 = (unsigned short *)g_tddi_full_raw_data_output; + + min = max = *report_data_16; + + for (i = 0, k = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", *report_data_16); + + min = (min < *report_data_16)? min : *report_data_16; + max = (max > *report_data_16)? max : *report_data_16; + + /*if (((*report_data_16) < (tddi_full_raw_limit_lower[k]))|| ((*report_data_16) > (tddi_full_raw_limit_upper[k]))) { + fail_count ++; + }*/ + /*changed by HQ-zmc 20171025*/ + if (!tddi_full_raw_limit_lower || !tddi_full_raw_limit_upper) + return snprintf(buf, PAGE_SIZE, "%s\n", "fail: tddi_full_raw_limit == NULL"); + if (((*report_data_16) < (*(tddi_full_raw_limit_lower+k))) || ((*report_data_16) > (*(tddi_full_raw_limit_upper+k)))) { + fail_count ++; + } + k++; + report_data_16++; + + + } + + + + + } + + + + + + + + + if (f55->extended_amp_btn) { + cnt = snprintf(buf, PAGE_SIZE - count, "\namp button count = %d.\n", NUM_BUTTON); + buf += cnt; + count += cnt; + + for (i = 0; i < NUM_BUTTON; i++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", *report_data_16); + + report_data_16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + } + + + + + + kfree(g_tddi_full_raw_data_output); + g_tddi_full_raw_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); + +} + +static ssize_t test_sysfs_tddi_amp_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int i, j, k; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + unsigned long setting; + unsigned char original_data_f54_ctrl99[3] = {0x00, 0x00, 0x00}; + struct f54_control control = f54->control; + unsigned char *p_report_data_8 = NULL; + signed short *p_rt92_delta_image = NULL; + signed short *p_rt92_image_1 = NULL; + signed short *p_rt92_image_2 = NULL; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + + if (g_tddi_amp_open_data_output) + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = kzalloc(tx_num * rx_num, GFP_KERNEL); + if (!g_tddi_amp_open_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_amp_open_data_output\n", + __func__); + return -ENOMEM; + } + + g_flag_readrt_err = false; + + + p_report_data_8 = kzalloc(tx_num * rx_num * 2, GFP_KERNEL); + if (!p_report_data_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_report_data_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_delta_image = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_delta_image) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_delta_image\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_1 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_1\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_2 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_2\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + + + if (f54->query.touch_controller_family != 2) { + + dev_err(rmi4_data->pdev->dev.parent, + "%s: not support touch controller family = 0 or 1 \n", + __func__); + retval = -EINVAL; + goto exit; + } + + + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + original_data_f54_ctrl99, + sizeof(original_data_f54_ctrl99)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read integration duration\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 1 */ + /* set the in_iter_duration_1 setting */ + /* and read the first rt92 image */ + control.reg_99->integration_duration_lsb = AMP_OPEN_INT_DUR_ONE; + control.reg_99->integration_duration_msb = (AMP_OPEN_INT_DUR_ONE >> 8) & 0xff; + control.reg_99->reset_duration = original_data_f54_ctrl99[2]; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write the integration duration to f54_ctrl_99 in step 1\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 1\n", + __func__); + retval = -EIO; + goto exit; + } + + + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 1. exit\n", + __func__); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_1[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + + memset(p_report_data_8, 0x00, tx_num * rx_num * 2); + + /* step 2 */ + /* set the in_iter_duration_2 setting */ + /* and read the second rt92 image */ + control.reg_99->integration_duration_lsb = AMP_OPEN_INT_DUR_TWO; + control.reg_99->integration_duration_msb = (AMP_OPEN_INT_DUR_TWO >> 8) & 0xff; + control.reg_99->reset_duration = original_data_f54_ctrl99[2]; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write the integration duration to f54_ctrl_99 in step 2\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 2\n", + __func__); + retval = -EIO; + goto exit; + } + + + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 2. exit\n", + __func__); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_2[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + + /* restore the original settings */ + control.reg_99->integration_duration_lsb = original_data_f54_ctrl99[0]; + control.reg_99->integration_duration_msb = original_data_f54_ctrl99[1]; + control.reg_99->reset_duration = original_data_f54_ctrl99[2]; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write the integration duration to f54_ctrl_99 in restore phase\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in restore phase\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 3 */ + /* generate the delta image, td43xx_rt92_delta_image */ + /* unit is femtofarad (fF) */ + for (i = 0; i < tx_num * rx_num; i++) { + p_rt92_delta_image[i] = p_rt92_image_1[i] - p_rt92_image_2[i]; + } + + memset(p_rt92_image_1, 0x00, tx_num * rx_num * 2); + + /* step 4 */ + /* phase 1, the delta value form the above two rt92 images */ + /* should be within the phase 1 test limit*/ + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < AMP_OPEN_TEST_LIMIT_PHASE1_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > AMP_OPEN_TEST_LIMIT_PHASE1_UPPER)) { + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 1 (limit = %d, %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + AMP_OPEN_TEST_LIMIT_PHASE1_LOWER, AMP_OPEN_TEST_LIMIT_PHASE1_UPPER); + + p_rt92_image_1[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_1[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.1 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + memset(p_rt92_image_2, 0x00, tx_num * rx_num * 2); + + /* step 5 */ + /* data calculation and verification */ + /* phase 2, the calculated ratio should be within the phase 2 test limit*/ + + + tddi_ratio_calculation(p_rt92_delta_image); + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < AMP_OPEN_TEST_LIMIT_PHASE2_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > AMP_OPEN_TEST_LIMIT_PHASE2_UPPER)) { + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 2 (limit = %d, %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + AMP_OPEN_TEST_LIMIT_PHASE2_LOWER, AMP_OPEN_TEST_LIMIT_PHASE2_UPPER); + + p_rt92_image_2[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_2[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.2 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + + /* step 6 */ + /* filling out the g_tddi_amp_open_data_output */ + /* 1: fail / 0 : pass */ + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_amp_open_data_output[i * rx_num + j] = + (unsigned char)(p_rt92_image_1[i * rx_num + j]) || p_rt92_image_2[i * rx_num + j]; + } + } + + retval = count; + +exit: + + kfree(p_rt92_image_1); + kfree(p_rt92_image_2); + kfree(p_rt92_delta_image); + kfree(p_report_data_8); + + return count; +} + +static ssize_t test_sysfs_tddi_amp_open_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + if (!g_tddi_amp_open_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_amp_open_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +static ssize_t test_sysfs_burst_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + unsigned long setting; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting == 1) + f54->is_burst = 1; + else + f54->is_burst = 0; + + return count; +} + +static ssize_t test_sysfs_burst_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", (f54->is_burst == 1) ? "BURST" : "BYTE"); +} + + +static ssize_t test_sysfs_tddi_amp_electrode_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int i, j, k; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + struct f54_control control = f54->control; + unsigned long setting; + + struct f54_control_91 original_f54_ctrl91; + struct f54_control_99 original_f54_ctrl99; + struct f54_control_182 original_f54_ctrl182; + + unsigned char *p_report_data_8 = NULL; + signed short *p_rt92_image_1 = NULL; + signed short *p_rt92_image_2 = NULL; + signed short *p_rt92_delta_image = NULL; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + + if (g_tddi_amp_open_data_output) + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = kzalloc(tx_num * rx_num, GFP_KERNEL); + if (!g_tddi_amp_open_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_amp_open_data_output\n", + __func__); + return -ENOMEM; + } + + g_flag_readrt_err = false; + + + p_report_data_8 = kzalloc(tx_num * rx_num * 2, GFP_KERNEL); + if (!p_report_data_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_report_data_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_delta_image = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_delta_image) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_delta_image\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_1 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_1\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_2 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_2\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + + /* keep the original reference high/low capacitance */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_91->address, + original_f54_ctrl91.data, + sizeof(original_f54_ctrl91.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read original data from f54_ctrl91\n", + __func__); + retval = -EIO; + goto exit; + } + /* keep the original integration and reset duration */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + original_f54_ctrl99.data, + sizeof(original_f54_ctrl99.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read original data from f54_ctrl99\n", + __func__); + retval = -EIO; + goto exit; + } + /* keep the original timing control */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_182->address, + original_f54_ctrl182.data, + sizeof(original_f54_ctrl182.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read original data from f54_ctrl182\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 1 */ + /* Wide refcap hi/ lo and feedback, Write 0x0F to F54_ANALOG_CTRL91 */ + control.reg_91->reflo_transcap_capacitance = 0x0f; + control.reg_91->refhi_transcap_capacitance = 0x0f; + control.reg_91->receiver_feedback_capacitance = 0x0f; + control.reg_91->reference_receiver_feedback_capacitance = original_f54_ctrl91.reference_receiver_feedback_capacitance; + control.reg_91->gain_ctrl = original_f54_ctrl91.gain_ctrl; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_91->address, + control.reg_91->data, + sizeof(control.reg_91->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set f54_ctrl91 in step 1\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 2 */ + /* Increase RST_DUR to 1.53us, Write 0x5c to F54_ANALOG_CTRL99 */ + control.reg_99->integration_duration_lsb = original_f54_ctrl99.integration_duration_lsb; + control.reg_99->integration_duration_msb = original_f54_ctrl99.integration_duration_msb; + control.reg_99->reset_duration = 0x5c; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set f54_ctrl99 in step 2\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 3 */ + /* Write 0x02 to F54_ANALOG_CTRL182 (00)/00 and (00)/02 */ + control.reg_182->cbc_timing_ctrl_tx_lsb = ELEC_OPEN_TEST_TX_ON_COUNT & 0xff; + control.reg_182->cbc_timing_ctrl_tx_msb = (ELEC_OPEN_TEST_TX_ON_COUNT >> 8) & 0xff; + control.reg_182->cbc_timing_ctrl_rx_lsb = ELEC_OPEN_TEST_RX_ON_COUNT & 0xff; + control.reg_182->cbc_timing_ctrl_rx_msb = (ELEC_OPEN_TEST_RX_ON_COUNT >> 8) & 0xff; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_182->address, + control.reg_182->data, + sizeof(control.reg_182->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set f54_reg_182 in step 3\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 4 */ + /* Change the INT_DUR as ELEC_OPEN_INT_DUR_ONE */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data from f54_ctrl99 in step 4\n", + __func__); + retval = -EIO; + goto exit; + } + control.reg_99->integration_duration_lsb = ELEC_OPEN_INT_DUR_ONE; + control.reg_99->integration_duration_msb = (ELEC_OPEN_INT_DUR_ONE >> 8) & 0xff; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to seet ELEC_OPEN_INT_DUR_ONE(%d) in step 4\n", + __func__, ELEC_OPEN_INT_DUR_ONE); + retval = -EIO; + goto exit; + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 4\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 5 */ + /* Capture raw capacitance (rt92) image 1 */ + /* Run Report Type 92 */ + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 5. exit\n", + __func__); + retval = -EIO; + g_flag_readrt_err = false; + goto exit; + } + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_1[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + memset(p_report_data_8, 0x00, tx_num * rx_num * 2); + + /* step 6 */ + /* Change the INT_DUR into ELEC_OPEN_INT_DUR_TWO */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data from f54_ctrl99 in step 6\n", + __func__); + retval = -EIO; + goto exit; + } + control.reg_99->integration_duration_lsb = ELEC_OPEN_INT_DUR_TWO; + control.reg_99->integration_duration_msb = (ELEC_OPEN_INT_DUR_TWO >> 8) & 0xff; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to seet ELEC_OPEN_INT_DUR_TWO(%d) in step 6\n", + __func__, ELEC_OPEN_INT_DUR_TWO); + retval = -EIO; + goto exit; + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 6\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 7 */ + /* Capture raw capacitance (rt92) image 2 */ + /* Run Report Type 92 */ + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 7. exit\n", + __func__); + retval = -EIO; + goto exit; + } + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_2[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + + /* step 8 */ + /* generate the delta image, which is equeal to image2 - image1 */ + /* unit is femtofarad (fF) */ + for (i = 0; i < tx_num * rx_num; i++) { + p_rt92_delta_image[i] = p_rt92_image_2[i] - p_rt92_image_1[i]; + } + + /* step 9 */ + /* restore the original configuration */ + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_91->address, + original_f54_ctrl91.data, + sizeof(original_f54_ctrl91.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore f54_ctrl91 data\n", + __func__); + retval = -EIO; + goto exit; + } + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + original_f54_ctrl99.data, + sizeof(original_f54_ctrl99.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore f54_ctrl99 data\n", + __func__); + retval = -EIO; + goto exit; + } + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_182->address, + original_f54_ctrl182.data, + sizeof(original_f54_ctrl182.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore f54_ctrl182 data\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 9\n", + __func__); + retval = -EIO; + goto exit; + } + + memset(p_rt92_image_1, 0x00, tx_num * rx_num * 2); + + /* step 10 */ + /* phase 1, data verification */ + /* the delta value should be lower than the test limit */ + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < ELEC_OPEN_TEST_LIMIT_ONE_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > ELEC_OPEN_TEST_LIMIT_ONE_UPPER)){ + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 1 (limit: %d - %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + ELEC_OPEN_TEST_LIMIT_ONE_LOWER, ELEC_OPEN_TEST_LIMIT_ONE_UPPER); + + p_rt92_image_1[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_1[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.1 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + memset(p_rt92_image_2, 0x00, tx_num * rx_num * 2); + + /* step 11 */ + /* phase 2, data calculation and verification */ + /* the calculated ratio should be lower than the test limit */ + + + tddi_ratio_calculation(p_rt92_delta_image); + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < ELEC_OPEN_TEST_LIMIT_TWO_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > ELEC_OPEN_TEST_LIMIT_TWO_UPPER)){ + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 2 (limit: %d - %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + ELEC_OPEN_TEST_LIMIT_TWO_LOWER, ELEC_OPEN_TEST_LIMIT_TWO_UPPER); + + p_rt92_image_2[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_2[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.2 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + /* step 12 */ + /* filling out the g_tddi_amp_open_data_output */ + /* 1: fail / 0 : pass */ + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_amp_open_data_output[i * rx_num + j] = + (unsigned char)(p_rt92_image_1[i * rx_num + j]) || p_rt92_image_2[i * rx_num + j]; + } + } + + retval = count; + +exit: + + kfree(p_report_data_8); + kfree(p_rt92_image_1); + kfree(p_rt92_image_2); + kfree(p_rt92_delta_image); + + return count; +} + +static ssize_t test_sysfs_tddi_amp_electrode_open_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + check_ito_test_flag = 0; + + if (!g_tddi_amp_open_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_amp_open_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +/* tddi f54 test reporting - */ + + +static ssize_t test_sysfs_data_read(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned int read_size; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type %d data not available\n", + __func__, f54->report_type); + retval = -EINVAL; + goto exit; + } + + if ((f54->data_pos + count) > f54->report_size) + read_size = f54->report_size - f54->data_pos; + else + read_size = min_t(unsigned int, count, f54->report_size); + + retval = secure_memcpy(buf, count, f54->report_data + f54->data_pos, + f54->data_buffer_size - f54->data_pos, read_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy report data\n", + __func__); + goto exit; + } + f54->data_pos += read_size; + retval = read_size; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static void test_report_work(struct work_struct *work) +{ + int retval; + unsigned char report_index[2]; + unsigned int byte_delay_us; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + if (f54->status != STATUS_BUSY) { + retval = f54->status; + goto exit; + } + + retval = test_wait_for_command_completion(); + if (retval < 0) { + retval = STATUS_ERROR; + goto exit; + } + + test_set_report_size(); + if (f54->report_size == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report data size = 0\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + if (f54->data_buffer_size < f54->report_size) { + if (f54->data_buffer_size) + kfree(f54->report_data); + f54->report_data = kzalloc(f54->report_size, GFP_KERNEL); + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", + __func__); + f54->data_buffer_size = 0; + retval = STATUS_ERROR; + goto exit; + } + f54->data_buffer_size = f54->report_size; + } + + report_index[0] = 0; + report_index[1] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + report_index, + sizeof(report_index)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report data index\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) { + byte_delay_us = rmi4_data->hw_if->board_data->byte_delay_us; + rmi4_data->hw_if->board_data->byte_delay_us = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_DATA_OFFSET, + f54->report_data, + f54->report_size); + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) + rmi4_data->hw_if->board_data->byte_delay_us = byte_delay_us; + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report data\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + retval = STATUS_IDLE; + +exit: + mutex_unlock(&f54->status_mutex); + + if (retval == STATUS_ERROR) + f54->report_size = 0; + + f54->status = retval; + return; +} + +static void test_remove_sysfs(void) +{ + sysfs_remove_group(f54->sysfs_dir, &attr_group); + sysfs_remove_bin_file(f54->sysfs_dir, &test_report_data); + kobject_put(f54->sysfs_dir); + + return; +} + + +static int tp_data_dump_proc_show(struct seq_file *m, void *v) { + int retval = 0; + int i, j, k; + unsigned short numberOfRows = f54->tx_assigned; + unsigned short numberOfColums = f54->rx_assigned; + short temp; + short *p_data = NULL; + + + seq_printf(m, "tx:%d\n", numberOfColums); + seq_printf(m, "rx:%d\n", numberOfRows); + retval = test_sysfs_read_report(NULL, NULL, "2", 2, true, false); + p_data = (unsigned short*)kzalloc(numberOfRows * numberOfColums * 2, GFP_KERNEL); + for (i = 0, k = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + temp = f54->report_data[k] | (f54->report_data[k+1] << 8); + p_data[i*numberOfColums+j] = temp; + k = k + 2; + } + } + + for (i = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + seq_printf(m, "%-5d ", p_data[i * numberOfColums + j]); + } + seq_printf(m, "\n"); + } + seq_printf(m, "tx:%d\n", numberOfColums); + seq_printf(m, "rx:%d\n", numberOfRows); + retval = test_sysfs_read_report(NULL, NULL, "92", 2, true, false); + p_data = (unsigned short*)kzalloc(numberOfRows * numberOfColums * 2, GFP_KERNEL); + for (i = 0, k = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + temp = f54->report_data[k] | (f54->report_data[k+1] << 8); + p_data[i*numberOfColums+j] = temp; + k = k + 2; + } + } + + for (i = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + seq_printf(m, "%-5d ", p_data[i * numberOfColums + j]); + } + seq_printf(m, "\n"); + } + if (p_data) + kfree(p_data); + return 0; +} + +static int tp_data_dump_proc_open(struct inode *inode, struct file *file) { + return single_open(file, tp_data_dump_proc_show, NULL); +} + +static const struct file_operations tp_data_dump_proc_fops = { + .owner = THIS_MODULE, + .open = tp_data_dump_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int test_set_sysfs(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + + proc_create("tp_data_dump", 0, NULL, &tp_data_dump_proc_fops); + + f54->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!f54->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + goto exit_directory; + } + + retval = sysfs_create_bin_file(f54->sysfs_dir, &test_report_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_bin_file; + } + + retval = sysfs_create_group(f54->sysfs_dir, &attr_group); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit_attributes; + } + + return 0; + +exit_attributes: + sysfs_remove_group(f54->sysfs_dir, &attr_group); + sysfs_remove_bin_file(f54->sysfs_dir, &test_report_data); + +exit_bin_file: + kobject_put(f54->sysfs_dir); + +exit_directory: + return -ENODEV; +} + +static void test_free_control_mem(void) +{ + struct f54_control control = f54->control; + + kfree(control.reg_7); + kfree(control.reg_41); + kfree(control.reg_57); + kfree(control.reg_86); + kfree(control.reg_88); + kfree(control.reg_91); + kfree(control.reg_96); + kfree(control.reg_99); + kfree(control.reg_110); + kfree(control.reg_149); + kfree(control.reg_182); + kfree(control.reg_188); + kfree(control.reg_223); + + return; +} + +static void test_set_data(void) +{ + unsigned short reg_addr; + + reg_addr = f54->data_base_addr + REPORT_DATA_OFFSET + 1; + + /* data 4 */ + if (f54->query.has_sense_frequency_control) + reg_addr++; + + /* data 5 reserved */ + + /* data 6 */ + if (f54->query.has_interference_metric) + reg_addr += 2; + + /* data 7 */ + if (f54->query.has_one_byte_report_rate | + f54->query.has_two_byte_report_rate) + reg_addr++; + if (f54->query.has_two_byte_report_rate) + reg_addr++; + + /* data 8 */ + if (f54->query.has_variance_metric) + reg_addr += 2; + + /* data 9 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += 2; + + /* data 10 */ + if (f54->query.has_multi_metric_state_machine | + f54->query.has_noise_state) + reg_addr++; + + /* data 11 */ + if (f54->query.has_status) + reg_addr++; + + /* data 12 */ + if (f54->query.has_slew_metric) + reg_addr += 2; + + /* data 13 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += 2; + + /* data 14 */ + if (f54->query_13.has_cidim) + reg_addr++; + + /* data 15 */ + if (f54->query_13.has_rail_im) + reg_addr++; + + /* data 16 */ + if (f54->query_13.has_noise_mitigation_enhancement) + reg_addr++; + + /* data 17 */ + if (f54->query_16.has_data17) + reg_addr++; + + /* data 18 */ + if (f54->query_21.has_query24_data18) + reg_addr++; + + /* data 19 */ + if (f54->query_21.has_data19) + reg_addr++; + + /* data_20 */ + if (f54->query_25.has_ctrl109) + reg_addr++; + + /* data 21 */ + if (f54->query_27.has_data21) + reg_addr++; + + /* data 22 */ + if (f54->query_27.has_data22) + reg_addr++; + + /* data 23 */ + if (f54->query_29.has_data23) + reg_addr++; + + /* data 24 */ + if (f54->query_32.has_data24) + reg_addr++; + + /* data 25 */ + if (f54->query_35.has_data25) + reg_addr++; + + /* data 26 */ + if (f54->query_35.has_data26) + reg_addr++; + + /* data 27 */ + if (f54->query_46.has_data27) + reg_addr++; + + /* data 28 */ + if (f54->query_46.has_data28) + reg_addr++; + + /* data 29 30 reserved */ + + /* data 31 */ + if (f54->query_49.has_data31) { + f54->data_31.address = reg_addr; + reg_addr++; + } + + return; +} + +static int test_set_controls(void) +{ + int retval; + unsigned char length; + unsigned char num_of_sensing_freqs; + unsigned short reg_addr = f54->control_base_addr; + struct f54_control *control = &f54->control; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + num_of_sensing_freqs = f54->query.number_of_sensing_frequencies; + + /* control 0 */ + reg_addr += CONTROL_0_SIZE; + + /* control 1 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_1_SIZE; + + /* control 2 */ + reg_addr += CONTROL_2_SIZE; + + /* control 3 */ + if (f54->query.has_pixel_touch_threshold_adjustment) + reg_addr += CONTROL_3_SIZE; + + /* controls 4 5 6 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_4_6_SIZE; + + /* control 7 */ + if (f54->query.touch_controller_family == 1) { + control->reg_7 = kzalloc(sizeof(*(control->reg_7)), + GFP_KERNEL); + if (!control->reg_7) + goto exit_no_mem; + control->reg_7->address = reg_addr; + reg_addr += CONTROL_7_SIZE; + } + + /* controls 8 9 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_8_9_SIZE; + + /* control 10 */ + if (f54->query.has_interference_metric) + reg_addr += CONTROL_10_SIZE; + + /* control 11 */ + if (f54->query.has_ctrl11) + reg_addr += CONTROL_11_SIZE; + + /* controls 12 13 */ + if (f54->query.has_relaxation_control) + reg_addr += CONTROL_12_13_SIZE; + + /* controls 14 15 16 */ + if (f54->query.has_sensor_assignment) { + reg_addr += CONTROL_14_SIZE; + reg_addr += CONTROL_15_SIZE * f54->query.num_of_rx_electrodes; + reg_addr += CONTROL_16_SIZE * f54->query.num_of_tx_electrodes; + } + + /* controls 17 18 19 */ + if (f54->query.has_sense_frequency_control) { + reg_addr += CONTROL_17_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_18_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_19_SIZE * num_of_sensing_freqs; + } + + /* control 20 */ + reg_addr += CONTROL_20_SIZE; + + /* control 21 */ + if (f54->query.has_sense_frequency_control) + reg_addr += CONTROL_21_SIZE; + + /* controls 22 23 24 25 26 */ + if (f54->query.has_firmware_noise_mitigation) + reg_addr += CONTROL_22_26_SIZE; + + /* control 27 */ + if (f54->query.has_iir_filter) + reg_addr += CONTROL_27_SIZE; + + /* control 28 */ + if (f54->query.has_firmware_noise_mitigation) + reg_addr += CONTROL_28_SIZE; + + /* control 29 */ + if (f54->query.has_cmn_removal) + reg_addr += CONTROL_29_SIZE; + + /* control 30 */ + if (f54->query.has_cmn_maximum) + reg_addr += CONTROL_30_SIZE; + + /* control 31 */ + if (f54->query.has_touch_hysteresis) + reg_addr += CONTROL_31_SIZE; + + /* controls 32 33 34 35 */ + if (f54->query.has_edge_compensation) + reg_addr += CONTROL_32_35_SIZE; + + /* control 36 */ + if ((f54->query.curve_compensation_mode == 1) || + (f54->query.curve_compensation_mode == 2)) { + if (f54->query.curve_compensation_mode == 1) { + length = max(f54->query.num_of_rx_electrodes, + f54->query.num_of_tx_electrodes); + } else if (f54->query.curve_compensation_mode == 2) { + length = f54->query.num_of_rx_electrodes; + } + reg_addr += CONTROL_36_SIZE * length; + } + + /* control 37 */ + if (f54->query.curve_compensation_mode == 2) + reg_addr += CONTROL_37_SIZE * f54->query.num_of_tx_electrodes; + + /* controls 38 39 40 */ + if (f54->query.has_per_frequency_noise_control) { + reg_addr += CONTROL_38_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_39_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_40_SIZE * num_of_sensing_freqs; + } + + /* control 41 */ + if (f54->query.has_signal_clarity) { + control->reg_41 = kzalloc(sizeof(*(control->reg_41)), + GFP_KERNEL); + if (!control->reg_41) + goto exit_no_mem; + control->reg_41->address = reg_addr; + reg_addr += CONTROL_41_SIZE; + } + + /* control 42 */ + if (f54->query.has_variance_metric) + reg_addr += CONTROL_42_SIZE; + + /* controls 43 44 45 46 47 48 49 50 51 52 53 54 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += CONTROL_43_54_SIZE; + + /* controls 55 56 */ + if (f54->query.has_0d_relaxation_control) + reg_addr += CONTROL_55_56_SIZE; + + /* control 57 */ + if (f54->query.has_0d_acquisition_control) { + control->reg_57 = kzalloc(sizeof(*(control->reg_57)), + GFP_KERNEL); + if (!control->reg_57) + goto exit_no_mem; + control->reg_57->address = reg_addr; + reg_addr += CONTROL_57_SIZE; + } + + /* control 58 */ + if (f54->query.has_0d_acquisition_control) + reg_addr += CONTROL_58_SIZE; + + /* control 59 */ + if (f54->query.has_h_blank) + reg_addr += CONTROL_59_SIZE; + + /* controls 60 61 62 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_60_62_SIZE; + + /* control 63 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank) || + (f54->query.has_slew_metric) || + (f54->query.has_slew_option) || + (f54->query.has_noise_mitigation2)) + reg_addr += CONTROL_63_SIZE; + + /* controls 64 65 66 67 */ + if (f54->query.has_h_blank) + reg_addr += CONTROL_64_67_SIZE * 7; + else if ((f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_64_67_SIZE; + + /* controls 68 69 70 71 72 73 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_68_73_SIZE; + + /* control 74 */ + if (f54->query.has_slew_metric) + reg_addr += CONTROL_74_SIZE; + + /* control 75 */ + if (f54->query.has_enhanced_stretch) + reg_addr += CONTROL_75_SIZE * num_of_sensing_freqs; + + /* control 76 */ + if (f54->query.has_startup_fast_relaxation) + reg_addr += CONTROL_76_SIZE; + + /* controls 77 78 */ + if (f54->query.has_esd_control) + reg_addr += CONTROL_77_78_SIZE; + + /* controls 79 80 81 82 83 */ + if (f54->query.has_noise_mitigation2) + reg_addr += CONTROL_79_83_SIZE; + + /* controls 84 85 */ + if (f54->query.has_energy_ratio_relaxation) + reg_addr += CONTROL_84_85_SIZE; + + /* control 86 */ + if (f54->query_13.has_ctrl86) { + control->reg_86 = kzalloc(sizeof(*(control->reg_86)), + GFP_KERNEL); + if (!control->reg_86) + goto exit_no_mem; + control->reg_86->address = reg_addr; + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_86->address, + f54->control.reg_86->data, + sizeof(f54->control.reg_86->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read sense display ratio\n", + __func__); + return retval; + } + reg_addr += CONTROL_86_SIZE; + } + + /* control 87 */ + if (f54->query_13.has_ctrl87) + reg_addr += CONTROL_87_SIZE; + + /* control 88 */ + if (f54->query.has_ctrl88) { + control->reg_88 = kzalloc(sizeof(*(control->reg_88)), + GFP_KERNEL); + if (!control->reg_88) + goto exit_no_mem; + control->reg_88->address = reg_addr; + reg_addr += CONTROL_88_SIZE; + } + + /* control 89 */ + if (f54->query_13.has_cidim || + f54->query_13.has_noise_mitigation_enhancement || + f54->query_13.has_rail_im) + reg_addr += CONTROL_89_SIZE; + + /* control 90 */ + if (f54->query_15.has_ctrl90) + reg_addr += CONTROL_90_SIZE; + + /* control 91 */ + if (f54->query_21.has_ctrl91) { + /* tddi f54 test reporting + */ + control->reg_91 = kzalloc(sizeof(*(control->reg_91)), + GFP_KERNEL); + if (!control->reg_91) + goto exit_no_mem; + control->reg_91->address = reg_addr; + /* tddi f54 test reporting - */ + reg_addr += CONTROL_91_SIZE; + } + + /* control 92 */ + if (f54->query_16.has_ctrl92) + reg_addr += CONTROL_92_SIZE; + + /* control 93 */ + if (f54->query_16.has_ctrl93) + reg_addr += CONTROL_93_SIZE; + + /* control 94 */ + if (f54->query_16.has_ctrl94_query18) + reg_addr += CONTROL_94_SIZE; + + /* control 95 */ + if (f54->query_16.has_ctrl95_query19) + reg_addr += CONTROL_95_SIZE; + + /* control 96 */ + if (f54->query_21.has_ctrl96) { + /* tddi f54 test reporting + */ + control->reg_96 = kzalloc(sizeof(*(control->reg_96)), + GFP_KERNEL); + if (!control->reg_96) + goto exit_no_mem; + control->reg_96->address = reg_addr; + /* tddi f54 test reporting - */ + reg_addr += CONTROL_96_SIZE; + } + + /* control 97 */ + if (f54->query_21.has_ctrl97) + reg_addr += CONTROL_97_SIZE; + + /* control 98 */ + if (f54->query_21.has_ctrl98) + reg_addr += CONTROL_98_SIZE; + + /* control 99 */ + if (f54->query.touch_controller_family == 2) { + /* tddi f54 test reporting + */ + control->reg_99 = kzalloc(sizeof(*(control->reg_99)), + GFP_KERNEL); + if (!control->reg_99) + goto exit_no_mem; + control->reg_99->address = reg_addr; + /* tddi f54 test reporting - */ + reg_addr += CONTROL_99_SIZE; + } + + /* control 100 */ + if (f54->query_16.has_ctrl100) + reg_addr += CONTROL_100_SIZE; + + /* control 101 */ + if (f54->query_22.has_ctrl101) + reg_addr += CONTROL_101_SIZE; + + + /* control 102 */ + if (f54->query_23.has_ctrl102) + reg_addr += CONTROL_102_SIZE; + + /* control 103 */ + if (f54->query_22.has_ctrl103_query26) { + f54->skip_preparation = true; + reg_addr += CONTROL_103_SIZE; + } + + /* control 104 */ + if (f54->query_22.has_ctrl104) + reg_addr += CONTROL_104_SIZE; + + /* control 105 */ + if (f54->query_22.has_ctrl105) + reg_addr += CONTROL_105_SIZE; + + /* control 106 */ + if (f54->query_25.has_ctrl106) + reg_addr += CONTROL_106_SIZE; + + /* control 107 */ + if (f54->query_25.has_ctrl107) + reg_addr += CONTROL_107_SIZE; + + /* control 108 */ + if (f54->query_25.has_ctrl108) + reg_addr += CONTROL_108_SIZE; + + /* control 109 */ + if (f54->query_25.has_ctrl109) + reg_addr += CONTROL_109_SIZE; + + /* control 110 */ + if (f54->query_27.has_ctrl110) { + control->reg_110 = kzalloc(sizeof(*(control->reg_110)), + GFP_KERNEL); + if (!control->reg_110) + goto exit_no_mem; + control->reg_110->address = reg_addr; + reg_addr += CONTROL_110_SIZE; + } + + /* control 111 */ + if (f54->query_27.has_ctrl111) + reg_addr += CONTROL_111_SIZE; + + /* control 112 */ + if (f54->query_27.has_ctrl112) + reg_addr += CONTROL_112_SIZE; + + /* control 113 */ + if (f54->query_27.has_ctrl113) + reg_addr += CONTROL_113_SIZE; + + /* control 114 */ + if (f54->query_27.has_ctrl114) + reg_addr += CONTROL_114_SIZE; + + /* control 115 */ + if (f54->query_29.has_ctrl115) + reg_addr += CONTROL_115_SIZE; + + /* control 116 */ + if (f54->query_29.has_ctrl116) + reg_addr += CONTROL_116_SIZE; + + /* control 117 */ + if (f54->query_29.has_ctrl117) + reg_addr += CONTROL_117_SIZE; + + /* control 118 */ + if (f54->query_30.has_ctrl118) + reg_addr += CONTROL_118_SIZE; + + /* control 119 */ + if (f54->query_30.has_ctrl119) + reg_addr += CONTROL_119_SIZE; + + /* control 120 */ + if (f54->query_30.has_ctrl120) + reg_addr += CONTROL_120_SIZE; + + /* control 121 */ + if (f54->query_30.has_ctrl121) + reg_addr += CONTROL_121_SIZE; + + /* control 122 */ + if (f54->query_30.has_ctrl122_query31) + reg_addr += CONTROL_122_SIZE; + + /* control 123 */ + if (f54->query_30.has_ctrl123) + reg_addr += CONTROL_123_SIZE; + + /* control 124 */ + if (f54->query_30.has_ctrl124) + reg_addr += CONTROL_124_SIZE; + + /* control 125 */ + if (f54->query_32.has_ctrl125) + reg_addr += CONTROL_125_SIZE; + + /* control 126 */ + if (f54->query_32.has_ctrl126) + reg_addr += CONTROL_126_SIZE; + + /* control 127 */ + if (f54->query_32.has_ctrl127) + reg_addr += CONTROL_127_SIZE; + + /* control 128 */ + if (f54->query_33.has_ctrl128) + reg_addr += CONTROL_128_SIZE; + + /* control 129 */ + if (f54->query_33.has_ctrl129) + reg_addr += CONTROL_129_SIZE; + + /* control 130 */ + if (f54->query_33.has_ctrl130) + reg_addr += CONTROL_130_SIZE; + + /* control 131 */ + if (f54->query_33.has_ctrl131) + reg_addr += CONTROL_131_SIZE; + + /* control 132 */ + if (f54->query_33.has_ctrl132) + reg_addr += CONTROL_132_SIZE; + + /* control 133 */ + if (f54->query_33.has_ctrl133) + reg_addr += CONTROL_133_SIZE; + + /* control 134 */ + if (f54->query_33.has_ctrl134) + reg_addr += CONTROL_134_SIZE; + + /* control 135 */ + if (f54->query_35.has_ctrl135) + reg_addr += CONTROL_135_SIZE; + + /* control 136 */ + if (f54->query_35.has_ctrl136) + reg_addr += CONTROL_136_SIZE; + + /* control 137 */ + if (f54->query_35.has_ctrl137) + reg_addr += CONTROL_137_SIZE; + + /* control 138 */ + if (f54->query_35.has_ctrl138) + reg_addr += CONTROL_138_SIZE; + + /* control 139 */ + if (f54->query_35.has_ctrl139) + reg_addr += CONTROL_139_SIZE; + + /* control 140 */ + if (f54->query_35.has_ctrl140) + reg_addr += CONTROL_140_SIZE; + + /* control 141 */ + if (f54->query_36.has_ctrl141) + reg_addr += CONTROL_141_SIZE; + + /* control 142 */ + if (f54->query_36.has_ctrl142) + reg_addr += CONTROL_142_SIZE; + + /* control 143 */ + if (f54->query_36.has_ctrl143) + reg_addr += CONTROL_143_SIZE; + + /* control 144 */ + if (f54->query_36.has_ctrl144) + reg_addr += CONTROL_144_SIZE; + + /* control 145 */ + if (f54->query_36.has_ctrl145) + reg_addr += CONTROL_145_SIZE; + + /* control 146 */ + if (f54->query_36.has_ctrl146) + reg_addr += CONTROL_146_SIZE; + + /* control 147 */ + if (f54->query_38.has_ctrl147) + reg_addr += CONTROL_147_SIZE; + + /* control 148 */ + if (f54->query_38.has_ctrl148) + reg_addr += CONTROL_148_SIZE; + + /* control 149 */ + if (f54->query_38.has_ctrl149) { + control->reg_149 = kzalloc(sizeof(*(control->reg_149)), + GFP_KERNEL); + if (!control->reg_149) + goto exit_no_mem; + control->reg_149->address = reg_addr; + reg_addr += CONTROL_149_SIZE; + } + + /* control 150 */ + if (f54->query_38.has_ctrl150) + reg_addr += CONTROL_150_SIZE; + + /* control 151 */ + if (f54->query_38.has_ctrl151) + reg_addr += CONTROL_151_SIZE; + + /* control 152 */ + if (f54->query_38.has_ctrl152) + reg_addr += CONTROL_152_SIZE; + + /* control 153 */ + if (f54->query_38.has_ctrl153) + reg_addr += CONTROL_153_SIZE; + + /* control 154 */ + if (f54->query_39.has_ctrl154) + reg_addr += CONTROL_154_SIZE; + + /* control 155 */ + if (f54->query_39.has_ctrl155) + reg_addr += CONTROL_155_SIZE; + + /* control 156 */ + if (f54->query_39.has_ctrl156) + reg_addr += CONTROL_156_SIZE; + + /* controls 157 158 */ + if (f54->query_39.has_ctrl157_ctrl158) + reg_addr += CONTROL_157_158_SIZE; + + /* controls 159 to 162 reserved */ + + /* control 163 */ + if (f54->query_40.has_ctrl163_query41) + reg_addr += CONTROL_163_SIZE; + + /* control 164 reserved */ + + /* control 165 */ + if (f54->query_40.has_ctrl165_query42) + reg_addr += CONTROL_165_SIZE; + + /* control 166 */ + if (f54->query_40.has_ctrl166) + reg_addr += CONTROL_166_SIZE; + + /* control 167 */ + if (f54->query_40.has_ctrl167) + reg_addr += CONTROL_167_SIZE; + + /* control 168 */ + if (f54->query_40.has_ctrl168) + reg_addr += CONTROL_168_SIZE; + + /* control 169 */ + if (f54->query_40.has_ctrl169) + reg_addr += CONTROL_169_SIZE; + + /* control 170 reserved */ + + /* control 171 */ + if (f54->query_43.has_ctrl171) + reg_addr += CONTROL_171_SIZE; + + /* control 172 */ + if (f54->query_43.has_ctrl172_query44_query45) + reg_addr += CONTROL_172_SIZE; + + /* control 173 */ + if (f54->query_43.has_ctrl173) + reg_addr += CONTROL_173_SIZE; + + /* control 174 */ + if (f54->query_43.has_ctrl174) + reg_addr += CONTROL_174_SIZE; + + /* control 175 */ + if (f54->query_43.has_ctrl175) + reg_addr += CONTROL_175_SIZE; + + /* control 176 */ + if (f54->query_46.has_ctrl176) + reg_addr += CONTROL_176_SIZE; + + /* controls 177 178 */ + if (f54->query_46.has_ctrl177_ctrl178) + reg_addr += CONTROL_177_178_SIZE; + + /* control 179 */ + if (f54->query_46.has_ctrl179) + reg_addr += CONTROL_179_SIZE; + + /* controls 180 to 181 reserved */ + + /* control 182 */ + if (f54->query_47.has_ctrl182) { + control->reg_182 = kzalloc(sizeof(*(control->reg_182)), + GFP_KERNEL); + if (!control->reg_182) + goto exit_no_mem; + control->reg_182->address = reg_addr; + reg_addr += CONTROL_182_SIZE; + } + + /* control 183 */ + if (f54->query_47.has_ctrl183) + reg_addr += CONTROL_183_SIZE; + + /* control 184 reserved */ + + /* control 185 */ + if (f54->query_47.has_ctrl185) + reg_addr += CONTROL_185_SIZE; + + /* control 186 */ + if (f54->query_47.has_ctrl186) + reg_addr += CONTROL_186_SIZE; + + /* control 187 */ + if (f54->query_47.has_ctrl187) + reg_addr += CONTROL_187_SIZE; + + /* control 188 */ + if (f54->query_49.has_ctrl188) { + control->reg_188 = kzalloc(sizeof(*(control->reg_188)), + GFP_KERNEL); + if (!control->reg_188) + goto exit_no_mem; + control->reg_188->address = reg_addr; + reg_addr += CONTROL_188_SIZE; + } + + /* control 189 - 195 reserved */ + + /* control 196 */ + if (f54->query_51.has_ctrl196) + reg_addr += CONTROL_196_SIZE; + + /* control 197 - 217 reserved */ + + /* control 218 reserved */ + if (f54->query_61.has_ctrl218) + reg_addr += CONTROL_218_SIZE; + + /* control 219 - 222 reserved */ + + /* control 223 reserved */ + if (f54->query_64.has_ctrl103_sub3) { + control->reg_223 = kzalloc(sizeof(*(control->reg_223)), + GFP_KERNEL); + if (!control->reg_223) + goto exit_no_mem; + control->reg_223->address = reg_addr; + reg_addr += CONTROL_223_SIZE; + } + + return 0; + +exit_no_mem: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for control registers\n", + __func__); + return -ENOMEM; +} + +static int test_set_queries(void) +{ + int retval; + unsigned char offset; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr, + f54->query.data, + sizeof(f54->query.data)); + if (retval < 0) + return retval; + + offset = sizeof(f54->query.data); + + /* query 12 */ + if (f54->query.has_sense_frequency_control == 0) + offset -= 1; + + /* query 13 */ + if (f54->query.has_query13) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_13.data, + sizeof(f54->query_13.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 14 */ + if (f54->query_13.has_ctrl87) + offset += 1; + + /* query 15 */ + if (f54->query.has_query15) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_15.data, + sizeof(f54->query_15.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 16 */ + if (f54->query_15.has_query16) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_16.data, + sizeof(f54->query_16.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 17 */ + if (f54->query_16.has_query17) + offset += 1; + + /* query 18 */ + if (f54->query_16.has_ctrl94_query18) + offset += 1; + + /* query 19 */ + if (f54->query_16.has_ctrl95_query19) + offset += 1; + + /* query 20 */ + if (f54->query_15.has_query20) + offset += 1; + + /* query 21 */ + if (f54->query_15.has_query21) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_21.data, + sizeof(f54->query_21.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 22 */ + if (f54->query_15.has_query22) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_22.data, + sizeof(f54->query_22.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 23 */ + if (f54->query_22.has_query23) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_23.data, + sizeof(f54->query_23.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 24 */ + if (f54->query_21.has_query24_data18) + offset += 1; + + /* query 25 */ + if (f54->query_15.has_query25) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_25.data, + sizeof(f54->query_25.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 26 */ + if (f54->query_22.has_ctrl103_query26) + offset += 1; + + /* query 27 */ + if (f54->query_25.has_query27) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_27.data, + sizeof(f54->query_27.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 28 */ + if (f54->query_22.has_query28) + offset += 1; + + /* query 29 */ + if (f54->query_27.has_query29) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_29.data, + sizeof(f54->query_29.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 30 */ + if (f54->query_29.has_query30) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_30.data, + sizeof(f54->query_30.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 31 */ + if (f54->query_30.has_ctrl122_query31) + offset += 1; + + /* query 32 */ + if (f54->query_30.has_query32) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_32.data, + sizeof(f54->query_32.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 33 */ + if (f54->query_32.has_query33) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_33.data, + sizeof(f54->query_33.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 34 */ + if (f54->query_32.has_query34) + offset += 1; + + /* query 35 */ + if (f54->query_32.has_query35) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_35.data, + sizeof(f54->query_35.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 36 */ + if (f54->query_33.has_query36) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_36.data, + sizeof(f54->query_36.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 37 */ + if (f54->query_36.has_query37) + offset += 1; + + /* query 38 */ + if (f54->query_36.has_query38) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_38.data, + sizeof(f54->query_38.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 39 */ + if (f54->query_38.has_query39) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_39.data, + sizeof(f54->query_39.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 40 */ + if (f54->query_39.has_query40) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_40.data, + sizeof(f54->query_40.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 41 */ + if (f54->query_40.has_ctrl163_query41) + offset += 1; + + /* query 42 */ + if (f54->query_40.has_ctrl165_query42) + offset += 1; + + /* query 43 */ + if (f54->query_40.has_query43) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_43.data, + sizeof(f54->query_43.data)); + if (retval < 0) + return retval; + offset += 1; + } + + if (f54->query_43.has_ctrl172_query44_query45) + offset += 2; + + /* query 46 */ + if (f54->query_43.has_query46) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_46.data, + sizeof(f54->query_46.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 47 */ + if (f54->query_46.has_query47) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_47.data, + sizeof(f54->query_47.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 48 reserved */ + + /* query 49 */ + if (f54->query_47.has_query49) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_49.data, + sizeof(f54->query_49.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 50 */ + if (f54->query_49.has_query50) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_50.data, + sizeof(f54->query_50.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 51 */ + if (f54->query_50.has_query51) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_51.data, + sizeof(f54->query_51.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* tddi f54 test reporting + */ + + /* query 52 reserved */ + + /* queries 53 54 */ + if (f54->query_51.has_query53_query54_ctrl198) + offset += 2; + + /* query 55 */ + if (f54->query_51.has_query55) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_55.data, + sizeof(f54->query_55.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 56 */ + if (f54->query_55.has_query56) + offset += 1; + + /* query 57 */ + if (f54->query_55.has_query57) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_57.data, + sizeof(f54->query_57.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 58 */ + if (f54->query_57.has_query58) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_58.data, + sizeof(f54->query_58.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 59 */ + if (f54->query_58.has_query59) + offset += 1; + + /* queries 60 */ + if (f54->query_58.has_query60) + offset += 1; + + /* queries 61 */ + if (f54->query_58.has_query61) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_61.data, + sizeof(f54->query_61.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 62 63 */ + if (f54->query_61.has_ctrl215_query62_query63) + offset += 2; + + /* queries 64 */ + if (f54->query_61.has_query64) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_64.data, + sizeof(f54->query_64.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 65 */ + if (f54->query_64.has_query65) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_65.data, + sizeof(f54->query_65.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 66 */ + if (f54->query_65.has_query66_ctrl231) + offset += 1; + + /* queries 67 */ + if (f54->query_65.has_query67) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_67.data, + sizeof(f54->query_67.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 68 */ + if (f54->query_67.has_query68) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_68.data, + sizeof(f54->query_68.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 69 */ + if (f54->query_68.has_query69) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_69.data, + sizeof(f54->query_69.data)); + if (retval < 0) + return retval; + offset += 1; + } + + f54->burst_read = f54->query_69.burst_mode_report_type_enabled; + /* tddi f54 test reporting - */ + + return 0; +} + +static void test_f54_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count, + unsigned char page) +{ + unsigned char ii; + unsigned char intr_offset; + + f54->query_base_addr = fd->query_base_addr | (page << 8); + f54->control_base_addr = fd->ctrl_base_addr | (page << 8); + f54->data_base_addr = fd->data_base_addr | (page << 8); + f54->command_base_addr = fd->cmd_base_addr | (page << 8); + + f54->intr_reg_num = (intr_count + 7) / 8; + if (f54->intr_reg_num != 0) + f54->intr_reg_num -= 1; + + f54->intr_mask = 0; + intr_offset = intr_count % 8; + for (ii = intr_offset; + ii < (fd->intr_src_count + intr_offset); + ii++) { + f54->intr_mask |= 1 << ii; + } + + return; +} + +static int test_f55_set_controls(void) +{ + unsigned char offset = 0; + + /* controls 0 1 2 */ + if (f55->query.has_sensor_assignment) + offset += 3; + + /* control 3 */ + if (f55->query.has_edge_compensation) + offset++; + + /* control 4 */ + if (f55->query.curve_compensation_mode == 0x1 || + f55->query.curve_compensation_mode == 0x2) + offset++; + + /* control 5 */ + if (f55->query.curve_compensation_mode == 0x2) + offset++; + + /* control 6 */ + if (f55->query.has_ctrl6) + offset++; + + /* control 7 */ + if (f55->query.has_alternate_transmitter_assignment) + offset++; + + /* control 8 */ + if (f55->query_3.has_ctrl8) + offset++; + + /* control 9 */ + if (f55->query_3.has_ctrl9) + offset++; + + /* control 10 */ + if (f55->query_5.has_corner_compensation) + offset++; + + /* control 11 */ + if (f55->query.curve_compensation_mode == 0x3) + offset++; + + /* control 12 */ + if (f55->query_5.has_ctrl12) + offset++; + + /* control 13 */ + if (f55->query_5.has_ctrl13) + offset++; + + /* control 14 */ + if (f55->query_5.has_ctrl14) + offset++; + + /* control 15 */ + if (f55->query_5.has_basis_function) + offset++; + + /* control 16 */ + if (f55->query_17.has_ctrl16) + offset++; + + /* control 17 */ + if (f55->query_17.has_ctrl17) + offset++; + + /* controls 18 19 */ + if (f55->query_17.has_ctrl18_ctrl19) + offset += 2; + + /* control 20 */ + if (f55->query_17.has_ctrl20) + offset++; + + /* control 21 */ + if (f55->query_17.has_ctrl21) + offset++; + + /* control 22 */ + if (f55->query_17.has_ctrl22) + offset++; + + /* control 23 */ + if (f55->query_18.has_ctrl23) + offset++; + + /* control 24 */ + if (f55->query_18.has_ctrl24) + offset++; + + /* control 25 */ + if (f55->query_18.has_ctrl25) + offset++; + + /* control 26 */ + if (f55->query_18.has_ctrl26) + offset++; + + /* control 27 */ + if (f55->query_18.has_ctrl27_query20) + offset++; + + /* control 28 */ + if (f55->query_18.has_ctrl28_query21) + offset++; + + /* control 29 */ + if (f55->query_22.has_ctrl29) + offset++; + + /* control 30 */ + if (f55->query_22.has_ctrl30) + offset++; + + /* control 31 */ + if (f55->query_22.has_ctrl31) + offset++; + + /* control 32 */ + if (f55->query_22.has_ctrl32) + offset++; + + /* controls 33 34 35 36 reserved */ + + /* control 37 */ + if (f55->query_28.has_ctrl37) + offset++; + + /* control 38 */ + if (f55->query_30.has_ctrl38) + offset++; + + /* control 39 */ + if (f55->query_30.has_ctrl39) + offset++; + + /* control 40 */ + if (f55->query_30.has_ctrl40) + offset++; + + /* control 41 */ + if (f55->query_30.has_ctrl41) + offset++; + + /* control 42 */ + if (f55->query_30.has_ctrl42) + offset++; + + /* controls 43 44 */ + if (f55->query_30.has_ctrl43_ctrl44) { + f55->afe_mux_offset = offset; + offset += 2; + } + + /* controls 45 46 */ + if (f55->query_33.has_ctrl45_ctrl46) { + f55->has_force = true; + f55->force_tx_offset = offset; + f55->force_rx_offset = offset + 1; + offset += 2; + } + + return 0; +} + +static int test_f55_set_queries(void) +{ + int retval; + unsigned char offset; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr, + f55->query.data, + sizeof(f55->query.data)); + if (retval < 0) + return retval; + + offset = sizeof(f55->query.data); + + /* query 3 */ + if (f55->query.has_single_layer_multi_touch) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_3.data, + sizeof(f55->query_3.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 4 */ + if (f55->query_3.has_ctrl9) + offset += 1; + + /* query 5 */ + if (f55->query.has_query5) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_5.data, + sizeof(f55->query_5.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 6 7 */ + if (f55->query.curve_compensation_mode == 0x3) + offset += 2; + + /* query 8 */ + if (f55->query_3.has_ctrl8) + offset += 1; + + /* query 9 */ + if (f55->query_3.has_query9) + offset += 1; + + /* queries 10 11 12 13 14 15 16 */ + if (f55->query_5.has_basis_function) + offset += 7; + + /* query 17 */ + if (f55->query_5.has_query17) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_17.data, + sizeof(f55->query_17.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 18 */ + if (f55->query_17.has_query18) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_18.data, + sizeof(f55->query_18.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 19 */ + if (f55->query_18.has_query19) + offset += 1; + + /* query 20 */ + if (f55->query_18.has_ctrl27_query20) + offset += 1; + + /* query 21 */ + if (f55->query_18.has_ctrl28_query21) + offset += 1; + + /* query 22 */ + if (f55->query_18.has_query22) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_22.data, + sizeof(f55->query_22.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 23 */ + if (f55->query_22.has_query23) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_23.data, + sizeof(f55->query_23.data)); + if (retval < 0) + return retval; + offset += 1; + + f55->amp_sensor = f55->query_23.amp_sensor_enabled; + f55->size_of_column2mux = f55->query_23.size_of_column2mux; + } + + /* queries 24 25 26 27 reserved */ + + /* query 28 */ + if (f55->query_22.has_query28) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_28.data, + sizeof(f55->query_28.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 29 */ + if (f55->query_28.has_query29) + offset += 1; + + /* query 30 */ + if (f55->query_28.has_query30) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_30.data, + sizeof(f55->query_30.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 31 32 */ + if (f55->query_30.has_query31_query32) + offset += 2; + + /* query 33 */ + if (f55->query_30.has_query33) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_33.data, + sizeof(f55->query_33.data)); + if (retval < 0) + return retval; + offset += 1; + + f55->extended_amp = f55->query_33.has_extended_amp_pad; + f55->extended_amp_btn = f55->query_33.has_extended_amp_btn; + } + + return 0; +} + +static void test_f55_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char rx_electrodes; + unsigned char tx_electrodes; + struct f55_control_43 ctrl_43; + + retval = test_f55_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 query registers\n", + __func__); + return; + } + + if (!f55->query.has_sensor_assignment) + return; + + retval = test_f55_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F55 control registers\n", + __func__); + return; + } + + tx_electrodes = f55->query.num_of_tx_electrodes; + rx_electrodes = f55->query.num_of_rx_electrodes; + + f55->tx_assignment = kzalloc(tx_electrodes, GFP_KERNEL); + f55->rx_assignment = kzalloc(rx_electrodes, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + SENSOR_TX_MAPPING_OFFSET, + f55->tx_assignment, + tx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 tx assignment\n", + __func__); + return; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + SENSOR_RX_MAPPING_OFFSET, + f55->rx_assignment, + rx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 rx assignment\n", + __func__); + return; + } + + f54->tx_assigned = 0; + for (ii = 0; ii < tx_electrodes; ii++) { + if (f55->tx_assignment[ii] != 0xff) + f54->tx_assigned++; + } + + f54->rx_assigned = 0; + for (ii = 0; ii < rx_electrodes; ii++) { + if (f55->rx_assignment[ii] != 0xff) + f54->rx_assigned++; + } + + if (f55->amp_sensor) { + f54->tx_assigned = f55->size_of_column2mux; + f54->rx_assigned /= 2; + } + + if (f55->extended_amp) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->afe_mux_offset, + ctrl_43.data, + sizeof(ctrl_43.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 AFE mux sizes\n", + __func__); + return; + } + + f54->tx_assigned = ctrl_43.afe_l_mux_size + + ctrl_43.afe_r_mux_size; + /* tddi f54 test reporting + */ + f54->swap_sensor_side = ctrl_43.swap_sensor_side; + f54->left_mux_size = ctrl_43.afe_l_mux_size; + f54->right_mux_size = ctrl_43.afe_r_mux_size; + /* tddi f54 test reporting - */ + } + + /* force mapping */ + if (f55->has_force) { + f55->force_tx_assignment = kzalloc(tx_electrodes, GFP_KERNEL); + f55->force_rx_assignment = kzalloc(rx_electrodes, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->force_tx_offset, + f55->force_tx_assignment, + tx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 force tx assignment\n", + __func__); + return; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->force_rx_offset, + f55->force_rx_assignment, + rx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 force rx assignment\n", + __func__); + return; + } + + for (ii = 0; ii < tx_electrodes; ii++) { + if (f55->force_tx_assignment[ii] != 0xff) + f54->tx_assigned++; + } + + for (ii = 0; ii < rx_electrodes; ii++) { + if (f55->force_rx_assignment[ii] != 0xff) + f54->rx_assigned++; + } + } + + return; +} + +static void test_f55_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned char page) +{ + f55 = kzalloc(sizeof(*f55), GFP_KERNEL); + if (!f55) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F55\n", + __func__); + return; + } + + f55->query_base_addr = fd->query_base_addr | (page << 8); + f55->control_base_addr = fd->ctrl_base_addr | (page << 8); + f55->data_base_addr = fd->data_base_addr | (page << 8); + f55->command_base_addr = fd->cmd_base_addr | (page << 8); + + return; +} + +static void test_f21_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char size_of_query2; + unsigned char size_of_query5; + unsigned char query_11_offset; + unsigned char ctrl_4_offset; + struct f21_query_2 *query_2 = NULL; + struct f21_query_5 *query_5 = NULL; + struct f21_query_11 *query_11 = NULL; + + query_2 = kzalloc(sizeof(*query_2), GFP_KERNEL); + if (!query_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_2\n", + __func__); + goto exit; + } + + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL); + if (!query_5) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_5\n", + __func__); + goto exit; + } + + query_11 = kzalloc(sizeof(*query_11), GFP_KERNEL); + if (!query_11) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_11\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 1, + &size_of_query2, + sizeof(size_of_query2)); + if (retval < 0) + goto exit; + + if (size_of_query2 > sizeof(query_2->data)) + size_of_query2 = sizeof(query_2->data); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 2, + query_2->data, + size_of_query2); + if (retval < 0) + goto exit; + + if (!query_2->query11_is_present) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No F21 force capabilities\n", + __func__); + goto exit; + } + + query_11_offset = query_2->query0_is_present + + query_2->query1_is_present + + query_2->query2_is_present + + query_2->query3_is_present + + query_2->query4_is_present + + query_2->query5_is_present + + query_2->query6_is_present + + query_2->query7_is_present + + query_2->query8_is_present + + query_2->query9_is_present + + query_2->query10_is_present; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 11, + query_11->data, + sizeof(query_11->data)); + if (retval < 0) + goto exit; + + if (!query_11->has_force_sensing_txrx_mapping) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No F21 force mapping\n", + __func__); + goto exit; + } + + f21->max_num_of_tx = query_11->max_number_of_force_txs; + f21->max_num_of_rx = query_11->max_number_of_force_rxs; + f21->max_num_of_txrx = f21->max_num_of_tx + f21->max_num_of_rx; + + f21->force_txrx_assignment = kzalloc(f21->max_num_of_txrx, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 4, + &size_of_query5, + sizeof(size_of_query5)); + if (retval < 0) + goto exit; + + if (size_of_query5 > sizeof(query_5->data)) + size_of_query5 = sizeof(query_5->data); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 5, + query_5->data, + size_of_query5); + if (retval < 0) + goto exit; + + ctrl_4_offset = query_5->ctrl0_is_present + + query_5->ctrl1_is_present + + query_5->ctrl2_is_present + + query_5->ctrl3_is_present; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->control_base_addr + ctrl_4_offset, + f21->force_txrx_assignment, + f21->max_num_of_txrx); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F21 force txrx assignment\n", + __func__); + goto exit; + } + + f21->has_force = true; + + for (ii = 0; ii < f21->max_num_of_tx; ii++) { + if (f21->force_txrx_assignment[ii] != 0xff) + f21->tx_assigned++; + } + + for (ii = f21->max_num_of_tx; ii < f21->max_num_of_txrx; ii++) { + if (f21->force_txrx_assignment[ii] != 0xff) + f21->rx_assigned++; + } + +exit: + kfree(query_2); + kfree(query_5); + kfree(query_11); + + return; +} + +static void test_f21_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned char page) +{ + f21 = kzalloc(sizeof(*f21), GFP_KERNEL); + if (!f21) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F21\n", + __func__); + return; + } + + f21->query_base_addr = fd->query_base_addr | (page << 8); + f21->control_base_addr = fd->ctrl_base_addr | (page << 8); + f21->data_base_addr = fd->data_base_addr | (page << 8); + f21->command_base_addr = fd->cmd_base_addr | (page << 8); + + return; +} + +static int test_scan_pdt(void) +{ + int retval; + unsigned char intr_count = 0; + unsigned char page; + unsigned short addr; + bool f54found = false; + bool f55found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (!rmi_fd.fn_number) + break; + + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F54: + test_f54_set_regs(rmi4_data, + &rmi_fd, intr_count, page); + f54found = true; + break; + case SYNAPTICS_RMI4_F55: + test_f55_set_regs(rmi4_data, + &rmi_fd, page); + f55found = true; + break; + case SYNAPTICS_RMI4_F21: + test_f21_set_regs(rmi4_data, + &rmi_fd, page); + break; + default: + break; + } + + if (f54found && f55found) + goto pdt_done; + + intr_count += rmi_fd.intr_src_count; + } + } + + if (!f54found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F54\n", + __func__); + return -EINVAL; + } + +pdt_done: + return 0; +} + +static void synaptics_rmi4_test_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!f54) + return; + + if (f54->intr_mask & intr_mask) + queue_work(f54->test_report_workqueue, &f54->test_report_work); + + return; +} + +static int synaptics_rmi4_test_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char lockdown[20] = {0}; + + if (f54) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + f54 = kzalloc(sizeof(*f54), GFP_KERNEL); + if (!f54) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F54\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + f54->rmi4_data = rmi4_data; + + f55 = NULL; + + f21 = NULL; + + retval = test_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + retval = test_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F54 query registers\n", + __func__); + goto exit_free_mem; + } + + f54->tx_assigned = f54->query.num_of_tx_electrodes; + f54->rx_assigned = f54->query.num_of_rx_electrodes; + + retval = test_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F54 control registers\n", + __func__); + goto exit_free_control; + } + + test_set_data(); + + if (f55) + test_f55_init(rmi4_data); + + if (f21) + test_f21_init(rmi4_data); + + if (rmi4_data->external_afe_buttons) + f54->tx_assigned++; + + retval = test_set_sysfs(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs entries\n", + __func__); + goto exit_sysfs; + } + + f54->test_report_workqueue = + create_singlethread_workqueue("test_report_workqueue"); + INIT_WORK(&f54->test_report_work, test_report_work); + + hrtimer_init(&f54->watchdog, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + f54->watchdog.function = test_get_report_timeout; + INIT_WORK(&f54->timeout_work, test_timeout_work); + + mutex_init(&f54->status_mutex); + f54->status = STATUS_IDLE; + + /*add by zmc 20171011*/ + if (get_tddi_lockdown_data(lockdown, 20) < 0){ + printk("%s:read lockdown fail\n", __func__); + } + printk("lockdown[7]: %d\n", lockdown[7]); + if (lockdown[7] == 1){ + printk("%s:HQ-zmc: tianma 6.0\n", __func__); + tddi_full_raw_limit_lower = tddi_full_raw_limit_lower_G60; + tddi_full_raw_limit_upper = tddi_full_raw_limit_upper_G60; + } + else if (lockdown[7] == 2){ + printk("%s:HQ-zmc: tianma 5.5\n", __func__); + tddi_full_raw_limit_lower = tddi_full_raw_limit_lower_G55; + tddi_full_raw_limit_upper = tddi_full_raw_limit_upper_G55; + } + + return 0; + +exit_sysfs: + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + +exit_free_control: + test_free_control_mem(); + +exit_free_mem: + kfree(f21); + f21 = NULL; + kfree(f55); + f55 = NULL; + kfree(f54); + f54 = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_test_remove(struct synaptics_rmi4_data *rmi4_data) +{ + if (!f54) + goto exit; + + hrtimer_cancel(&f54->watchdog); + + cancel_work_sync(&f54->test_report_work); + flush_workqueue(f54->test_report_workqueue); + destroy_workqueue(f54->test_report_workqueue); + + test_remove_sysfs(); + + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + + test_free_control_mem(); + + if (f54->data_buffer_size) + kfree(f54->report_data); + + kfree(f21); + f21 = NULL; + + kfree(f55); + f55 = NULL; + + kfree(f54); + f54 = NULL; + +exit: + complete(&test_remove_complete); + + return; +} + +static void synaptics_rmi4_test_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!f54) { + synaptics_rmi4_test_init(rmi4_data); + return; + } + + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + + test_free_control_mem(); + + kfree(f55); + f55 = NULL; + + kfree(f21); + f21 = NULL; + + retval = test_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + retval = test_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F54 query registers\n", + __func__); + goto exit_free_mem; + } + + f54->tx_assigned = f54->query.num_of_tx_electrodes; + f54->rx_assigned = f54->query.num_of_rx_electrodes; + + retval = test_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F54 control registers\n", + __func__); + goto exit_free_control; + } + + test_set_data(); + + if (f55) + test_f55_init(rmi4_data); + + if (f21) + test_f21_init(rmi4_data); + + if (rmi4_data->external_afe_buttons) + f54->tx_assigned++; + + f54->status = STATUS_IDLE; + + return; + +exit_free_control: + test_free_control_mem(); + +exit_free_mem: + hrtimer_cancel(&f54->watchdog); + + cancel_work_sync(&f54->test_report_work); + flush_workqueue(f54->test_report_workqueue); + destroy_workqueue(f54->test_report_workqueue); + + test_remove_sysfs(); + + if (f54->data_buffer_size) + kfree(f54->report_data); + + kfree(f21); + f21 = NULL; + + kfree(f55); + f55 = NULL; + + kfree(f54); + f54 = NULL; + + return; +} + +static struct synaptics_rmi4_exp_fn test_module = { + .fn_type = RMI_TEST_REPORTING, + .init = synaptics_rmi4_test_init, + .remove = synaptics_rmi4_test_remove, + .reset = synaptics_rmi4_test_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_test_attn, +}; + +static int __init rmi4_test_module_init(void) +{ + synaptics_rmi4_new_function(&test_module, true); + + return 0; +} + +static void __exit rmi4_test_module_exit(void) +{ + synaptics_rmi4_new_function(&test_module, false); + + wait_for_completion(&test_remove_complete); + + + remove_proc_entry("tp_data_dump", NULL); + + return; +} + +module_init(rmi4_test_module_init); +module_exit(rmi4_test_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Test Reporting Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_e7/synaptics_dsx_video.c b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_video.c new file mode 100755 index 0000000000000..59ef780d423cf --- /dev/null +++ b/drivers/input/touchscreen/td4310_e7/synaptics_dsx_video.c @@ -0,0 +1,416 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#define SYSFS_FOLDER_NAME "video" + +/* +#define RMI_DCS_SUSPEND_RESUME +*/ + +static ssize_t video_sysfs_dcs_write_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t video_sysfs_param_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static int video_send_dcs_command(unsigned char command_opcode); + +struct f38_command { + union { + struct { + unsigned char command_opcode; + unsigned char register_access:1; + unsigned char gamma_page:1; + unsigned char f38_control1_b2__7:6; + unsigned char parameter_field_1; + unsigned char parameter_field_2; + unsigned char parameter_field_3; + unsigned char parameter_field_4; + unsigned char send_to_dcs:1; + unsigned char f38_command6_b1__7:7; + } __packed; + unsigned char data[7]; + }; +}; + +struct synaptics_rmi4_video_handle { + unsigned char param; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + struct synaptics_rmi4_data *rmi4_data; + struct kobject *sysfs_dir; +}; + +#ifdef RMI_DCS_SUSPEND_RESUME +struct dcs_command { + unsigned char command; + unsigned int wait_time; +}; + +static struct dcs_command suspend_sequence[] = { + { + .command = 0x28, + .wait_time = 200, + }, + { + .command = 0x10, + .wait_time = 200, + }, +}; + +static struct dcs_command resume_sequence[] = { + { + .command = 0x11, + .wait_time = 200, + }, + { + .command = 0x29, + .wait_time = 200, + }, +}; +#endif + +static struct device_attribute attrs[] = { + __ATTR(dcs_write, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + video_sysfs_dcs_write_store), + __ATTR(param, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + video_sysfs_param_store), +}; + +static struct synaptics_rmi4_video_handle *video; + +DECLARE_COMPLETION(video_remove_complete); + +static ssize_t video_sysfs_dcs_write_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + + if (sscanf(buf, "%x", &input) != 1) + return -EINVAL; + + retval = video_send_dcs_command((unsigned char)input); + if (retval < 0) + return retval; + + return count; +} + +static ssize_t video_sysfs_param_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%x", &input) != 1) + return -EINVAL; + + video->param = (unsigned char)input; + + return count; +} + +static int video_send_dcs_command(unsigned char command_opcode) +{ + int retval; + struct f38_command command; + struct synaptics_rmi4_data *rmi4_data = video->rmi4_data; + + memset(&command, 0x00, sizeof(command)); + + command.command_opcode = command_opcode; + command.parameter_field_1 = video->param; + command.send_to_dcs = 1; + + video->param = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + video->command_base_addr, + command.data, + sizeof(command.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to send DCS command\n", + __func__); + return retval; + } + + return 0; +} + +static int video_scan_pdt(void) +{ + int retval; + unsigned char page; + unsigned short addr; + bool f38_found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = video->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (!rmi_fd.fn_number) + break; + + if (rmi_fd.fn_number == SYNAPTICS_RMI4_F38) { + f38_found = true; + goto f38_found; + } + } + } + + if (!f38_found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F38\n", + __func__); + return -EINVAL; + } + +f38_found: + video->query_base_addr = rmi_fd.query_base_addr | (page << 8); + video->control_base_addr = rmi_fd.ctrl_base_addr | (page << 8); + video->data_base_addr = rmi_fd.data_base_addr | (page << 8); + video->command_base_addr = rmi_fd.cmd_base_addr | (page << 8); + + return 0; +} + +static int synaptics_rmi4_video_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + + if (video) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + video = kzalloc(sizeof(*video), GFP_KERNEL); + if (!video) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for video\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + video->rmi4_data = rmi4_data; + + retval = video_scan_pdt(); + if (retval < 0) { + retval = 0; + goto exit_scan_pdt; + } + + video->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!video->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + retval = -ENODEV; + goto exit_sysfs_dir; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(video->sysfs_dir, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_sysfs_attrs; + } + } + + return 0; + +exit_sysfs_attrs: + for (attr_count--; attr_count >= 0; attr_count--) + sysfs_remove_file(video->sysfs_dir, &attrs[attr_count].attr); + + kobject_put(video->sysfs_dir); + +exit_sysfs_dir: +exit_scan_pdt: + kfree(video); + video = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_video_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!video) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) + sysfs_remove_file(video->sysfs_dir, &attrs[attr_count].attr); + + kobject_put(video->sysfs_dir); + + kfree(video); + video = NULL; + +exit: + complete(&video_remove_complete); + + return; +} + +static void synaptics_rmi4_video_reset(struct synaptics_rmi4_data *rmi4_data) +{ + if (!video) + synaptics_rmi4_video_init(rmi4_data); + + return; +} + +#ifdef RMI_DCS_SUSPEND_RESUME +static void synaptics_rmi4_video_suspend(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char command; + unsigned char num_of_cmds; + + if (!video) + return; + + num_of_cmds = ARRAY_SIZE(suspend_sequence); + + for (ii = 0; ii < num_of_cmds; ii++) { + command = suspend_sequence[ii].command; + retval = video_send_dcs_command(command); + if (retval < 0) + return; + msleep(suspend_sequence[ii].wait_time); + } + + return; +} + +static void synaptics_rmi4_video_resume(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char command; + unsigned char num_of_cmds; + + if (!video) + return; + + num_of_cmds = ARRAY_SIZE(resume_sequence); + + for (ii = 0; ii < num_of_cmds; ii++) { + command = resume_sequence[ii].command; + retval = video_send_dcs_command(command); + if (retval < 0) + return; + msleep(resume_sequence[ii].wait_time); + } + + return; +} +#endif + +static struct synaptics_rmi4_exp_fn video_module = { + .fn_type = RMI_VIDEO, + .init = synaptics_rmi4_video_init, + .remove = synaptics_rmi4_video_remove, + .reset = synaptics_rmi4_video_reset, + .reinit = NULL, + .early_suspend = NULL, +#ifdef RMI_DCS_SUSPEND_RESUME + .suspend = synaptics_rmi4_video_suspend, + .resume = synaptics_rmi4_video_resume, +#else + .suspend = NULL, + .resume = NULL, +#endif + .late_resume = NULL, + .attn = NULL, +}; + +static int __init rmi4_video_module_init(void) +{ + synaptics_rmi4_new_function(&video_module, true); + + return 0; +} + +static void __exit rmi4_video_module_exit(void) +{ + synaptics_rmi4_new_function(&video_module, false); + + wait_for_completion(&video_remove_complete); + + return; +} + +module_init(rmi4_video_module_init); +module_exit(rmi4_video_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Video Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_lansi_e7/Kconfig b/drivers/input/touchscreen/td4310_lansi_e7/Kconfig new file mode 100755 index 0000000000000..b2fa11501269d --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/Kconfig @@ -0,0 +1,128 @@ +# +# Synaptics DSX touchscreen driver configuration +# +menuconfig TOUCHSCREEN_SYNAPTICS_DSX + bool "Synaptics DSX touchscreen" + default y + help + Say Y here if you have a Synaptics DSX touchscreen connected + to your system. + + If unsure, say N. + +if TOUCHSCREEN_SYNAPTICS_DSX + +choice + default TOUCHSCREEN_SYNAPTICS_DSX_I2C + prompt "Synaptics DSX bus interface" +config TOUCHSCREEN_SYNAPTICS_DSX_I2C + bool "RMI over I2C" + depends on I2C +config TOUCHSCREEN_SYNAPTICS_DSX_SPI + bool "RMI over SPI" + depends on SPI_MASTER +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C + bool "HID over I2C" + depends on I2C +endchoice + +config TOUCHSCREEN_SYNAPTICS_DSX_CORE + tristate "Synaptics DSX core driver module" + depends on I2C || SPI_MASTER + help + Say Y here to enable basic touch reporting functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_core. + +config TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV + tristate "Synaptics DSX RMI device module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for direct RMI register access. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_rmi_dev. + +config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE + tristate "Synaptics DSX firmware update module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for doing firmware update. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_fw_update. + +config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING + tristate "Synaptics DSX test reporting module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for retrieving production test reports. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_test_reporting. + +config TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY + tristate "Synaptics DSX proximity module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for proximity functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_proximity. + +config TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN + tristate "Synaptics DSX active pen module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for active pen functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_active_pen. + +config TOUCHSCREEN_SYNAPTICS_DSX_GESTURE + tristate "Synaptics DSX user defined gesture module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for user defined gesture functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_gesture. + +config TOUCHSCREEN_SYNAPTICS_DSX_VIDEO + tristate "Synaptics DSX video module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for video communication functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_video. + +config TOUCHSCREEN_SYNAPTICS_DSX_DEBUG + tristate "Synaptics DSX debug module" + depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE + help + Say Y here to enable support for firmware debug functionality. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called synaptics_dsx_debug. + +endif diff --git a/drivers/input/touchscreen/td4310_lansi_e7/Makefile b/drivers/input/touchscreen/td4310_lansi_e7/Makefile new file mode 100755 index 0000000000000..a8cb3865719c0 --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the Synaptics DSX touchscreen driver. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics_dsx_i2c.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_SPI) += synaptics_dsx_spi.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_HID_I2C) += synaptics_dsx_rmi_hid_i2c.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics_dsx_core.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics_dsx_rmi_dev.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics_dsx_fw_update.o +obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics_dsx_test_reporting.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_PROXIMITY) += synaptics_dsx_proximity.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_ACTIVE_PEN) += synaptics_dsx_active_pen.o +#obj-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics_dsx_gesture.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_VIDEO) += synaptics_dsx_video.o +#obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_DEBUG) += synaptics_dsx_debug.o diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx.h b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx.h new file mode 100644 index 0000000000000..300330f0d6ecc --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx.h @@ -0,0 +1,115 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#ifndef _SYNAPTICS_DSX_H_ +#define _SYNAPTICS_DSX_H_ + +#define PLATFORM_DRIVER_NAME "lansi_dsx_v21" +#define STYLUS_DRIVER_NAME "synaptics_dsx_stylus_lansi" +#define ACTIVE_PEN_DRIVER_NAME "synaptics_dsx_active_pen" +#define PROXIMITY_DRIVER_NAME "synaptics_dsx_proximity" +#define GESTURE_DRIVER_NAME "synaptics_dsx_gesture" +#define I2C_DRIVER_NAME "lansi_dsx_i2c" +#define SPI_DRIVER_NAME "lansi_dsx_spi" + +/* + * struct synaptics_dsx_button_map - button map + * @nbuttons: number of buttons + * @map: pointer to array of button codes + */ +struct synaptics_dsx_button_map { + unsigned char nbuttons; + unsigned int *map; +}; + +/* + * struct synaptics_dsx_board_data - DSX board data + * @x_flip: x flip flag + * @y_flip: y flip flag + * @swap_axes: swap axes flag + * @irq_gpio: attention interrupt GPIO + * @irq_on_state: attention interrupt active state + * @power_gpio: power switch GPIO + * @power_on_state: power switch active state + * @reset_gpio: reset GPIO + * @reset_on_state: reset active state + * @max_y_for_2d: maximum y value for 2D area when virtual buttons are present + * @irq_flags: IRQ flags + * @i2c_addr: I2C slave address + * @ub_i2c_addr: microbootloader mode I2C slave address + * @device_descriptor_addr: HID device descriptor address + * @panel_x: x-axis resolution of display panel + * @panel_y: y-axis resolution of display panel + * @power_delay_ms: delay time to wait after powering up device + * @reset_delay_ms: delay time to wait after resetting device + * @reset_active_ms: reset active time + * @byte_delay_us: delay time between two bytes of SPI data + * @block_delay_us: delay time between two SPI transfers + * @addr_delay_us: delay time after sending address word + * @pwr_reg_name: pointer to name of regulator for power control + * @bus_reg_name: pointer to name of regulator for bus pullup control + * @cap_button_map: pointer to 0D button map + * @vir_button_map: pointer to virtual button map + */ +struct synaptics_dsx_board_data { + bool x_flip; + bool y_flip; + bool swap_axes; + int irq; + int irq_gpio; + int irq_on_state; + int power_gpio; + int power_on_state; + int reset_gpio; + int reset_on_state; + int display_reset_gpio; + int max_y_for_2d; + unsigned long irq_flags; + unsigned short i2c_addr; + unsigned short ub_i2c_addr; + unsigned short device_descriptor_addr; + unsigned int panel_x; + unsigned int panel_y; + unsigned int power_delay_ms; + unsigned int reset_delay_ms; + unsigned int reset_active_ms; + unsigned int byte_delay_us; + unsigned int block_delay_us; + unsigned int addr_delay_us; + const char *pwr_reg_name; + const char *bus_reg_name; + struct synaptics_dsx_button_map *cap_button_map; + struct synaptics_dsx_button_map *vir_button_map; +}; + +#endif diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_core.c b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_core.c new file mode 100755 index 0000000000000..80465caac4b36 --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_core.c @@ -0,0 +1,4932 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "synaptics_dsx_core.h" +#include +#include +#include + +#ifdef KERNEL_ABOVE_2_6_38 +#include +#endif + +#define INPUT_PHYS_NAME "synaptics_dsx/touch_input" +#define STYLUS_PHYS_NAME "synaptics_dsx/stylus" + +#define VIRTUAL_KEY_MAP_FILE_NAME "virtualkeys." PLATFORM_DRIVER_NAME + +#ifdef KERNEL_ABOVE_2_6_38 +#define TYPE_B_PROTOCOL +#endif + +/* +#define USE_DATA_SERVER +*/ + +#define WAKEUP_GESTURE 1 + +#define NO_0D_WHILE_2D +#define REPORT_2D_Z +#define REPORT_2D_W +/* +#define REPORT_2D_PRESSURE +*/ + +#define F12_DATA_15_WORKAROUND + +#define IGNORE_FN_INIT_FAILURE +/* +#define FB_READY_RESET +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +*/ +#ifdef SYNA_TDDI +#define TDDI_LPWG_WAIT_US 100 +#endif +#define RPT_TYPE (1 << 0) +#define RPT_X_LSB (1 << 1) +#define RPT_X_MSB (1 << 2) +#define RPT_Y_LSB (1 << 3) +#define RPT_Y_MSB (1 << 4) +#define RPT_Z (1 << 5) +#define RPT_WX (1 << 6) +#define RPT_WY (1 << 7) +#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB) + +#define REBUILD_WORK_DELAY_MS 500 /* ms */ + +#define EXP_FN_WORK_DELAY_MS 500 /* ms */ +#define MAX_F11_TOUCH_WIDTH 15 +#define MAX_F12_TOUCH_WIDTH 255 + +#define CHECK_STATUS_TIMEOUT_MS 100 + +#define F01_STD_QUERY_LEN 21 +#define F01_BUID_ID_OFFSET 18 + +#define STATUS_NO_ERROR 0x00 +#define STATUS_RESET_OCCURRED 0x01 +#define STATUS_INVALID_CONFIG 0x02 +#define STATUS_DEVICE_FAILURE 0x03 +#define STATUS_CONFIG_CRC_FAILURE 0x04 +#define STATUS_FIRMWARE_CRC_FAILURE 0x05 +#define STATUS_CRC_IN_PROGRESS 0x06 + +#define NORMAL_OPERATION (0 << 0) +#define SENSOR_SLEEP (1 << 0) +#define NO_SLEEP_OFF (0 << 2) +#define NO_SLEEP_ON (1 << 2) +#define CONFIGURED (1 << 7) + +#define F11_CONTINUOUS_MODE 0x00 +#define F11_WAKEUP_GESTURE_MODE 0x04 +#define F12_CONTINUOUS_MODE 0x00 +#define F12_WAKEUP_GESTURE_MODE 0x02 +#define F12_UDG_DETECT 0x0f + + +static struct synaptics_rmi4_data *rmi4_data; + +bool synaptics_gesture_func_on_lansi = 1; +#if WAKEUP_GESTURE +#define WAKEUP_OFF 4 +#define WAKEUP_ON 5 + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +extern bool lcm_ffbm_mode; +#endif + +int synaptics_gesture_switch_lansi(struct input_dev *dev, unsigned int type, unsigned int code, int value) +{ + + unsigned int input ; + if (type == EV_SYN && code == SYN_CONFIG) + { + if (value == WAKEUP_OFF){ + synaptics_gesture_func_on_lansi = false; + input = 0; + }else if (value == WAKEUP_ON){ + synaptics_gesture_func_on_lansi = true; + input = 1; + } + } + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) + rmi4_data->enable_wakeup_gesture = input; + + return 0; +} +#endif + + +extern int get_tddi_lockdown_data_lansi(unsigned char *lockdown_data, unsigned short leng); + +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, + bool *was_in_bl_mode); +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data); +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data); +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, + bool rebuild); + +#ifdef SYNAPTICS_ESD_CHECK +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +void synaptics_rmi4_esd_work(struct work_struct *work); +#if 1 +#define SYNAPTICS_ESD_CHECK_RETRY_TIME 5 +int touch_event_flag; +int fw_update_flag; + + + + +#endif +#endif + + +#ifdef CONFIG_FB +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self, + unsigned long event, void *data); +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +#ifndef CONFIG_FB +#define USE_EARLYSUSPEND +#endif +#endif + +#ifdef USE_EARLYSUSPEND +static void synaptics_rmi4_early_suspend(struct early_suspend *h); + +static void synaptics_rmi4_late_resume(struct early_suspend *h); +#endif + +static int synaptics_rmi4_suspend(struct device *dev); + +static int synaptics_rmi4_resume(struct device *dev); + +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_suspend_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +#ifdef USE_DATA_SERVER +static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); +#endif + +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf); + +struct synaptics_rmi4_f01_device_status { + union { + struct { + unsigned char status_code:4; + unsigned char reserved:2; + unsigned char flash_prog:1; + unsigned char unconfigured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_0_5 { + union { + struct { + /* query 0 */ + unsigned char f11_query0_b0__2:3; + unsigned char has_query_9:1; + unsigned char has_query_11:1; + unsigned char has_query_12:1; + unsigned char has_query_27:1; + unsigned char has_query_28:1; + + /* query 1 */ + unsigned char num_of_fingers:3; + unsigned char has_rel:1; + unsigned char has_abs:1; + unsigned char has_gestures:1; + unsigned char has_sensitibity_adjust:1; + unsigned char f11_query1_b7:1; + + /* query 2 */ + unsigned char num_of_x_electrodes; + + /* query 3 */ + unsigned char num_of_y_electrodes; + + /* query 4 */ + unsigned char max_electrodes:7; + unsigned char f11_query4_b7:1; + + /* query 5 */ + unsigned char abs_data_size:2; + unsigned char has_anchored_finger:1; + unsigned char has_adj_hyst:1; + unsigned char has_dribble:1; + unsigned char has_bending_correction:1; + unsigned char has_large_object_suppression:1; + unsigned char has_jitter_filter:1; + } __packed; + unsigned char data[6]; + }; +}; + +struct synaptics_rmi4_f11_query_7_8 { + union { + struct { + /* query 7 */ + unsigned char has_single_tap:1; + unsigned char has_tap_and_hold:1; + unsigned char has_double_tap:1; + unsigned char has_early_tap:1; + unsigned char has_flick:1; + unsigned char has_press:1; + unsigned char has_pinch:1; + unsigned char has_chiral_scroll:1; + + /* query 8 */ + unsigned char has_palm_detect:1; + unsigned char has_rotate:1; + unsigned char has_touch_shapes:1; + unsigned char has_scroll_zones:1; + unsigned char individual_scroll_zones:1; + unsigned char has_multi_finger_scroll:1; + unsigned char has_multi_finger_scroll_edge_motion:1; + unsigned char has_multi_finger_scroll_inertia:1; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f11_query_9 { + union { + struct { + unsigned char has_pen:1; + unsigned char has_proximity:1; + unsigned char has_large_object_sensitivity:1; + unsigned char has_suppress_on_large_object_detect:1; + unsigned char has_two_pen_thresholds:1; + unsigned char has_contact_geometry:1; + unsigned char has_pen_hover_discrimination:1; + unsigned char has_pen_hover_and_edge_filters:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_12 { + union { + struct { + unsigned char has_small_object_detection:1; + unsigned char has_small_object_detection_tuning:1; + unsigned char has_8bit_w:1; + unsigned char has_2d_adjustable_mapping:1; + unsigned char has_general_information_2:1; + unsigned char has_physical_properties:1; + unsigned char has_finger_limit:1; + unsigned char has_linear_cofficient_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_query_27 { + union { + struct { + unsigned char f11_query27_b0:1; + unsigned char has_pen_position_correction:1; + unsigned char has_pen_jitter_filter_coefficient:1; + unsigned char has_group_decomposition:1; + unsigned char has_wakeup_gesture:1; + unsigned char has_small_finger_correction:1; + unsigned char has_data_37:1; + unsigned char f11_query27_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f11_ctrl_6_9 { + union { + struct { + unsigned char sensor_max_x_pos_7_0; + unsigned char sensor_max_x_pos_11_8:4; + unsigned char f11_ctrl7_b4__7:4; + unsigned char sensor_max_y_pos_7_0; + unsigned char sensor_max_y_pos_11_8:4; + unsigned char f11_ctrl9_b4__7:4; + } __packed; + unsigned char data[4]; + }; +}; + +struct synaptics_rmi4_f11_data_1_5 { + union { + struct { + unsigned char x_position_11_4; + unsigned char y_position_11_4; + unsigned char x_position_3_0:4; + unsigned char y_position_3_0:4; + unsigned char wx:4; + unsigned char wy:4; + unsigned char z; + } __packed; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + struct { + unsigned char ctrl24_is_present:1; + unsigned char ctrl25_is_present:1; + unsigned char ctrl26_is_present:1; + unsigned char ctrl27_is_present:1; + unsigned char ctrl28_is_present:1; + unsigned char ctrl29_is_present:1; + unsigned char ctrl30_is_present:1; + unsigned char ctrl31_is_present:1; + } __packed; + struct { + unsigned char ctrl32_is_present:1; + unsigned char ctrl33_is_present:1; + unsigned char ctrl34_is_present:1; + unsigned char ctrl35_is_present:1; + unsigned char ctrl36_is_present:1; + unsigned char ctrl37_is_present:1; + unsigned char ctrl38_is_present:1; + unsigned char ctrl39_is_present:1; + } __packed; + struct { + unsigned char ctrl40_is_present:1; + unsigned char ctrl41_is_present:1; + unsigned char ctrl42_is_present:1; + unsigned char ctrl43_is_present:1; + unsigned char ctrl44_is_present:1; + unsigned char ctrl45_is_present:1; + unsigned char ctrl46_is_present:1; + unsigned char ctrl47_is_present:1; + } __packed; + struct { + unsigned char ctrl48_is_present:1; + unsigned char ctrl49_is_present:1; + unsigned char ctrl50_is_present:1; + unsigned char ctrl51_is_present:1; + unsigned char ctrl52_is_present:1; + unsigned char ctrl53_is_present:1; + unsigned char ctrl54_is_present:1; + unsigned char ctrl55_is_present:1; + } __packed; + struct { + unsigned char ctrl56_is_present:1; + unsigned char ctrl57_is_present:1; + unsigned char ctrl58_is_present:1; + unsigned char ctrl59_is_present:1; + unsigned char ctrl60_is_present:1; + unsigned char ctrl61_is_present:1; + unsigned char ctrl62_is_present:1; + unsigned char ctrl63_is_present:1; + } __packed; + }; + unsigned char data[9]; + }; +}; + +struct synaptics_rmi4_f12_query_8 { + union { + struct { + unsigned char size_of_query9; + struct { + unsigned char data0_is_present:1; + unsigned char data1_is_present:1; + unsigned char data2_is_present:1; + unsigned char data3_is_present:1; + unsigned char data4_is_present:1; + unsigned char data5_is_present:1; + unsigned char data6_is_present:1; + unsigned char data7_is_present:1; + } __packed; + struct { + unsigned char data8_is_present:1; + unsigned char data9_is_present:1; + unsigned char data10_is_present:1; + unsigned char data11_is_present:1; + unsigned char data12_is_present:1; + unsigned char data13_is_present:1; + unsigned char data14_is_present:1; + unsigned char data15_is_present:1; + } __packed; + struct { + unsigned char data16_is_present:1; + unsigned char data17_is_present:1; + unsigned char data18_is_present:1; + unsigned char data19_is_present:1; + unsigned char data20_is_present:1; + unsigned char data21_is_present:1; + unsigned char data22_is_present:1; + unsigned char data23_is_present:1; + } __packed; + struct { + unsigned char data24_is_present:1; + unsigned char data25_is_present:1; + unsigned char data26_is_present:1; + unsigned char data27_is_present:1; + unsigned char data28_is_present:1; + unsigned char data29_is_present:1; + unsigned char data30_is_present:1; + unsigned char data31_is_present:1; + } __packed; + }; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_8 { + union { + struct { + unsigned char max_x_coord_lsb; + unsigned char max_x_coord_msb; + unsigned char max_y_coord_lsb; + unsigned char max_y_coord_msb; + unsigned char rx_pitch_lsb; + unsigned char rx_pitch_msb; + unsigned char tx_pitch_lsb; + unsigned char tx_pitch_msb; + unsigned char low_rx_clip; + unsigned char high_rx_clip; + unsigned char low_tx_clip; + unsigned char high_tx_clip; + unsigned char num_of_rx; + unsigned char num_of_tx; + }; + unsigned char data[14]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_23 { + union { + struct { + unsigned char finger_enable:1; + unsigned char active_stylus_enable:1; + unsigned char palm_enable:1; + unsigned char unclassified_object_enable:1; + unsigned char hovering_finger_enable:1; + unsigned char gloved_finger_enable:1; + unsigned char f12_ctr23_00_b6__7:2; + unsigned char max_reported_objects; + unsigned char f12_ctr23_02_b0:1; + unsigned char report_active_stylus_as_finger:1; + unsigned char report_palm_as_finger:1; + unsigned char report_unclassified_object_as_finger:1; + unsigned char report_hovering_finger_as_finger:1; + unsigned char report_gloved_finger_as_finger:1; + unsigned char report_narrow_object_swipe_as_finger:1; + unsigned char report_handedge_as_finger:1; + unsigned char cover_enable:1; + unsigned char stylus_enable:1; + unsigned char eraser_enable:1; + unsigned char small_object_enable:1; + unsigned char f12_ctr23_03_b4__7:4; + unsigned char report_cover_as_finger:1; + unsigned char report_stylus_as_finger:1; + unsigned char report_eraser_as_finger:1; + unsigned char report_small_object_as_finger:1; + unsigned char f12_ctr23_04_b4__7:4; + }; + unsigned char data[5]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_31 { + union { + struct { + unsigned char max_x_coord_lsb; + unsigned char max_x_coord_msb; + unsigned char max_y_coord_lsb; + unsigned char max_y_coord_msb; + unsigned char rx_pitch_lsb; + unsigned char rx_pitch_msb; + unsigned char rx_clip_low; + unsigned char rx_clip_high; + unsigned char wedge_clip_low; + unsigned char wedge_clip_high; + unsigned char num_of_p; + unsigned char num_of_q; + }; + unsigned char data[12]; + }; +}; + +struct synaptics_rmi4_f12_ctrl_58 { + union { + struct { + unsigned char reporting_format; + unsigned char f12_ctr58_00_reserved; + unsigned char min_force_lsb; + unsigned char min_force_msb; + unsigned char max_force_lsb; + unsigned char max_force_msb; + unsigned char light_press_threshold_lsb; + unsigned char light_press_threshold_msb; + unsigned char light_press_hysteresis_lsb; + unsigned char light_press_hysteresis_msb; + unsigned char hard_press_threshold_lsb; + unsigned char hard_press_threshold_msb; + unsigned char hard_press_hysteresis_lsb; + unsigned char hard_press_hysteresis_msb; + }; + unsigned char data[14]; + }; +}; + +struct synaptics_rmi4_f12_finger_data { + unsigned char object_type_and_status; + unsigned char x_lsb; + unsigned char x_msb; + unsigned char y_lsb; + unsigned char y_msb; +#ifdef REPORT_2D_Z + unsigned char z; +#endif +#ifdef REPORT_2D_W + unsigned char wx; + unsigned char wy; +#endif +}; + +struct synaptics_rmi4_f1a_query { + union { + struct { + unsigned char max_button_count:3; + unsigned char f1a_query0_b3__4:2; + unsigned char has_query4:1; + unsigned char has_query3:1; + unsigned char has_query2:1; + unsigned char has_general_control:1; + unsigned char has_interrupt_enable:1; + unsigned char has_multibutton_select:1; + unsigned char has_tx_rx_map:1; + unsigned char has_perbutton_threshold:1; + unsigned char has_release_threshold:1; + unsigned char has_strongestbtn_hysteresis:1; + unsigned char has_filter_strength:1; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f1a_query_4 { + union { + struct { + unsigned char has_ctrl19:1; + unsigned char f1a_query4_b1__4:4; + unsigned char has_ctrl24:1; + unsigned char f1a_query4_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f1a_control_0 { + union { + struct { + unsigned char multibutton_report:2; + unsigned char filter_mode:2; + unsigned char reserved:4; + } __packed; + unsigned char data[1]; + }; +}; + +struct synaptics_rmi4_f1a_control { + struct synaptics_rmi4_f1a_control_0 general_control; + unsigned char button_int_enable; + unsigned char multi_button; + unsigned char *txrx_map; + unsigned char *button_threshold; + unsigned char button_release_threshold; + unsigned char strongest_button_hysteresis; + unsigned char filter_strength; +}; + +struct synaptics_rmi4_f1a_handle { + int button_bitmask_size; + unsigned char max_count; + unsigned char valid_button_count; + unsigned char *button_data_buffer; + unsigned char *button_map; + struct synaptics_rmi4_f1a_query button_query; + struct synaptics_rmi4_f1a_control button_control; +}; + +struct synaptics_rmi4_exp_fhandler { + struct synaptics_rmi4_exp_fn *exp_fn; + bool insert; + bool remove; + struct list_head link; +}; + +struct synaptics_rmi4_exp_fn_data { + bool initialized; + bool queue_work; + struct mutex mutex; + struct list_head list; + struct delayed_work work; + struct workqueue_struct *workqueue; + struct synaptics_rmi4_data *rmi4_data; +}; + +static struct synaptics_rmi4_exp_fn_data exp_data; + +static struct synaptics_dsx_button_map *vir_button_map; + +#ifdef USE_DATA_SERVER +static pid_t synad_pid; +static struct task_struct *synad_task; +static struct siginfo interrupt_signal; +#endif + +static struct device_attribute attrs[] = { + __ATTR(reset, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_f01_reset_store), + __ATTR(productinfo, S_IRUGO, + synaptics_rmi4_f01_productinfo_show, + synaptics_rmi4_store_error), + __ATTR(buildid, S_IRUGO, + synaptics_rmi4_f01_buildid_show, + synaptics_rmi4_store_error), + __ATTR(flashprog, S_IRUGO, + synaptics_rmi4_f01_flashprog_show, + synaptics_rmi4_store_error), + __ATTR(0dbutton, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_0dbutton_show, + synaptics_rmi4_0dbutton_store), + __ATTR(suspend, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_suspend_store), + __ATTR(wake_gesture, (S_IRUGO | S_IWUSR | S_IWGRP), + synaptics_rmi4_wake_gesture_show, + synaptics_rmi4_wake_gesture_store), +#ifdef USE_DATA_SERVER + __ATTR(synad_pid, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + synaptics_rmi4_synad_pid_store), +#endif +}; + +static struct kobj_attribute virtual_key_map_attr = { + .attr = { + .name = VIRTUAL_KEY_MAP_FILE_NAME, + .mode = S_IRUGO, + }, + .show = synaptics_rmi4_virtual_key_map_show, +}; + +static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int reset; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + if (sscanf(buf, "%u", &reset) != 1) + return -EINVAL; + + if (reset != 1) + return -EINVAL; + + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command, error = %d\n", + __func__, retval); + return retval; + } + + return count; +} + +static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n", + (rmi4_data->rmi4_mod_info.product_info[0]), + (rmi4_data->rmi4_mod_info.product_info[1])); +} + +static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->firmware_id); +} + +static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + struct synaptics_rmi4_f01_device_status device_status; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + device_status.data, + sizeof(device_status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device status, error = %d\n", + __func__, retval); + return retval; + } + + return snprintf(buf, PAGE_SIZE, "%u\n", + device_status.flash_prog); +} + +static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->button_0d_enabled); +} + +static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + unsigned char ii; + unsigned char intr_enable; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + input = input > 0 ? 1 : 0; + + if (rmi4_data->button_0d_enabled == input) + return count; + + if (list_empty(&rmi->support_fn_list)) + return -ENODEV; + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { + ii = fhandler->intr_reg_num; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr + 1 + ii, + &intr_enable, + sizeof(intr_enable)); + if (retval < 0) + return retval; + + if (input == 1) + intr_enable |= fhandler->intr_mask; + else + intr_enable &= ~fhandler->intr_mask; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr + 1 + ii, + &intr_enable, + sizeof(intr_enable)); + if (retval < 0) + return retval; + } + } + + rmi4_data->button_0d_enabled = input; + + return count; +} + +static ssize_t synaptics_rmi4_suspend_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input == 1) + synaptics_rmi4_suspend(dev); + else if (input == 0) + synaptics_rmi4_resume(dev); + else + return -EINVAL; + + return count; +} + +static ssize_t synaptics_rmi4_wake_gesture_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + return snprintf(buf, PAGE_SIZE, "%u\n", + rmi4_data->enable_wakeup_gesture); +} + + +static ssize_t synaptics_rmi4_wake_gesture_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned int input ; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input) + input = 1; + else + input = 0; + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture){ + rmi4_data->enable_wakeup_gesture = input; + synaptics_gesture_func_on_lansi = input; + } + + return count; +} + +#ifdef USE_DATA_SERVER +static ssize_t synaptics_rmi4_synad_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + synad_pid = input; + + if (synad_pid) { + synad_task = pid_task(find_vpid(synad_pid), PIDTYPE_PID); + if (!synad_task) + return -EINVAL; + } + + return count; +} +#endif + +static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int ii; + int cnt; + int count = 0; + + for (ii = 0; ii < vir_button_map->nbuttons; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "0x01:%d:%d:%d:%d:%d\n", + vir_button_map->map[ii * 5 + 0], + vir_button_map->map[ii * 5 + 1], + vir_button_map->map[ii * 5 + 2], + vir_button_map->map[ii * 5 + 3], + vir_button_map->map[ii * 5 + 4]); + buf += cnt; + count += cnt; + } + + return count; +} + +static void synaptics_rmi4_f11_wg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char reporting_control; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F11) + break; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base, + &reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + reporting_control = (reporting_control & ~MASK_3BIT); + if (enable) + reporting_control |= F11_WAKEUP_GESTURE_MODE; + else + reporting_control |= F11_CONTINUOUS_MODE; + + retval = synaptics_rmi4_reg_write(rmi4_data, + fhandler->full_addr.ctrl_base, + &reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + return; +} + +static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char offset; + unsigned char reporting_control[3]; + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) + break; + } + + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + offset = extra_data->ctrl20_offset; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + if (enable) + reporting_control[2] = F12_WAKEUP_GESTURE_MODE; + else + reporting_control[2] = F12_CONTINUOUS_MODE; + + retval = synaptics_rmi4_reg_write(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + reporting_control, + sizeof(reporting_control)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to change reporting mode\n", + __func__); + return; + } + + return; +} + +static void synaptics_rmi4_wakeup_gesture(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + if (rmi4_data->f11_wakeup_gesture) + synaptics_rmi4_f11_wg(rmi4_data, enable); + else if (rmi4_data->f12_wakeup_gesture) + synaptics_rmi4_f12_wg(rmi4_data, enable); + + return; +} + +static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; /* number of touch points */ + unsigned char reg_index; + unsigned char finger; + unsigned char fingers_supported; + unsigned char num_of_finger_status_regs; + unsigned char finger_shift; + unsigned char finger_status; + unsigned char finger_status_reg[3]; + unsigned char detected_gestures; + unsigned short data_addr; + unsigned short data_offset; + int x; + int y; + int wx; + int wy; + int temp; + struct synaptics_rmi4_f11_data_1_5 data; + struct synaptics_rmi4_f11_extra_data *extra_data; + + /* + * The number of finger status registers is determined by the + * maximum number of fingers supported - 2 bits per finger. So + * the number of finger status registers to read is: + * register_count = ceil(max_num_of_fingers / 4) + */ + fingers_supported = fhandler->num_of_data_points; + num_of_finger_status_regs = (fingers_supported + 3) / 4; + data_addr = fhandler->full_addr.data_base; + + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra; + + if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data38_offset, + &detected_gestures, + sizeof(detected_gestures)); + if (retval < 0) + return 0; + + if (detected_gestures) { + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1); + input_sync(rmi4_data->input_dev); + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0); + input_sync(rmi4_data->input_dev); + rmi4_data->suspend = false; + } + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + return 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr, + finger_status_reg, + num_of_finger_status_regs); + if (retval < 0) + return 0; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (finger = 0; finger < fingers_supported; finger++) { + reg_index = finger / 4; + finger_shift = (finger % 4) * 2; + finger_status = (finger_status_reg[reg_index] >> finger_shift) + & MASK_2BIT; + + /* + * Each 2-bit finger status field represents the following: + * 00 = finger not present + * 01 = finger present and data accurate + * 10 = finger present but data may be inaccurate + * 11 = reserved + */ +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, finger_status); +#endif + + if (finger_status) { + data_offset = data_addr + + num_of_finger_status_regs + + (finger * sizeof(data.data)); + retval = synaptics_rmi4_reg_read(rmi4_data, + data_offset, + data.data, + sizeof(data.data)); + if (retval < 0) { + touch_count = 0; + goto exit; + } + + x = (data.x_position_11_4 << 4) | data.x_position_3_0; + y = (data.y_position_11_4 << 4) | data.y_position_3_0; + wx = data.wx; + wy = data.wy; + + if (rmi4_data->hw_if->board_data->swap_axes) { + temp = x; + x = y; + y = temp; + temp = wx; + wx = wy; + wy = temp; + } + + if (rmi4_data->hw_if->board_data->x_flip) + x = rmi4_data->sensor_max_x - x; + if (rmi4_data->hw_if->board_data->y_flip) + y = rmi4_data->sensor_max_y - y; + + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 1); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_Y, y); +#ifdef REPORT_2D_W + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, max(wx, wy)); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, min(wx, wy)); +#endif +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: status = 0x%02x, x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + finger_status, + x, y, wx, wy); + + touch_count++; + } + } + + if (touch_count == 0) { + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + } + + input_sync(rmi4_data->input_dev); + +exit: + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return touch_count; +} + +static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; /* number of touch points */ + unsigned char index; + unsigned char finger; + unsigned char fingers_to_process; + unsigned char finger_status; + unsigned char size_of_2d_data; + unsigned char gesture_type; + unsigned short data_addr; + int x; + int y; + int wx; + int wy; + int temp; +#if defined(REPORT_2D_PRESSURE) || defined(F51_DISCRETE_FORCE) + int pressure; +#endif +#ifdef REPORT_2D_PRESSURE + unsigned char f_fingers; + unsigned char f_lsb; + unsigned char f_msb; + unsigned char *f_data; +#endif +#ifdef F51_DISCRETE_FORCE + unsigned char force_level; +#endif + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_f12_finger_data *data; + struct synaptics_rmi4_f12_finger_data *finger_data; + static unsigned char finger_presence; + static unsigned char stylus_presence; +#ifdef F12_DATA_15_WORKAROUND + static unsigned char objects_already_present; +#endif + + fingers_to_process = fhandler->num_of_data_points; + data_addr = fhandler->full_addr.data_base; + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data); + + if (rmi4_data->suspend && rmi4_data->enable_wakeup_gesture) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data4_offset, + rmi4_data->gesture_detection, + sizeof(rmi4_data->gesture_detection)); + if (retval < 0) + return 0; + + gesture_type = rmi4_data->gesture_detection[0]; + + if (gesture_type && gesture_type != F12_UDG_DETECT) { + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 1); + input_sync(rmi4_data->input_dev); + input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0); + input_sync(rmi4_data->input_dev); + + rmi4_data->suspend = false; + } + + return 0; + } + + /* Determine the total number of fingers to process */ + if (extra_data->data15_size) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data15_offset, + extra_data->data15_data, + extra_data->data15_size); + if (retval < 0) + return 0; + + /* Start checking from the highest bit */ + index = extra_data->data15_size - 1; /* Highest byte */ + finger = (fingers_to_process - 1) % 8; /* Highest bit */ + do { + if (extra_data->data15_data[index] & (1 << finger)) + break; + + if (finger) { + finger--; + } else if (index > 0) { + index--; /* Move to the next lower byte */ + finger = 7; + } + + fingers_to_process--; + } while (fingers_to_process); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of fingers to process = %d\n", + __func__, fingers_to_process); + } + +#ifdef F12_DATA_15_WORKAROUND + fingers_to_process = max(fingers_to_process, objects_already_present); +#endif + + if (!fingers_to_process) { + synaptics_rmi4_free_fingers(rmi4_data); + finger_presence = 0; + stylus_presence = 0; + return 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data1_offset, + (unsigned char *)fhandler->data, + fingers_to_process * size_of_2d_data); + if (retval < 0) + return 0; + + data = (struct synaptics_rmi4_f12_finger_data *)fhandler->data; + +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr + extra_data->data29_offset, + extra_data->data29_data, + extra_data->data29_size); + if (retval < 0) + return 0; + } +#endif + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (finger = 0; finger < fingers_to_process; finger++) { + finger_data = data + finger; + finger_status = finger_data->object_type_and_status; + +#ifdef F12_DATA_15_WORKAROUND + objects_already_present = finger + 1; +#endif + + x = (finger_data->x_msb << 8) | (finger_data->x_lsb); + y = (finger_data->y_msb << 8) | (finger_data->y_lsb); +#ifdef REPORT_2D_W + wx = finger_data->wx; + wy = finger_data->wy; +#endif + + if (rmi4_data->hw_if->board_data->swap_axes) { + temp = x; + x = y; + y = temp; + temp = wx; + wx = wy; + wy = temp; + } + + if (rmi4_data->hw_if->board_data->x_flip) + x = rmi4_data->sensor_max_x - x; + if (rmi4_data->hw_if->board_data->y_flip) + y = rmi4_data->sensor_max_y - y; + + switch (finger_status) { + case F12_FINGER_STATUS: + case F12_GLOVED_FINGER_STATUS: + /* Stylus has priority over fingers */ + if (stylus_presence) + break; +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 1); +#endif + + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 1); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 1); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(rmi4_data->input_dev, + ABS_MT_POSITION_Y, y); +#ifdef REPORT_2D_W + if (rmi4_data->wedge_sensor) { + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, wx); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, wx); + } else { + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, + max(wx, wy)); + input_report_abs(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, + min(wx, wy)); + } +#endif +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + f_fingers = extra_data->data29_size / 2; + f_data = extra_data->data29_data; + if (finger + 1 > f_fingers) { + pressure = 1; + } else { + f_lsb = finger * 2; + f_msb = finger * 2 + 1; + pressure = (int)f_data[f_lsb] << 0 | + (int)f_data[f_msb] << 8; + } + pressure = pressure > 0 ? pressure : 1; + if (pressure > rmi4_data->force_max) + pressure = rmi4_data->force_max; + input_report_abs(rmi4_data->input_dev, + ABS_MT_PRESSURE, pressure); + } +#elif defined(F51_DISCRETE_FORCE) + if (finger == 0) { + retval = synaptics_rmi4_reg_read(rmi4_data, + FORCE_LEVEL_ADDR, + &force_level, + sizeof(force_level)); + if (retval < 0) + return 0; + pressure = force_level > 0 ? force_level : 1; + } else { + pressure = 1; + } + input_report_abs(rmi4_data->input_dev, + ABS_MT_PRESSURE, pressure); +#endif +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: status = 0x%02x, x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + finger_status, + x, y, wx, wy); + + finger_presence = 1; + touch_count++; + break; + case F12_PALM_STATUS: + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Finger %d: x = %d, y = %d, wx = %d, wy = %d\n", + __func__, finger, + x, y, wx, wy); + break; + case F12_STYLUS_STATUS: + case F12_ERASER_STATUS: + if (!rmi4_data->stylus_enable) + break; + /* Stylus has priority over fingers */ + if (finger_presence) { + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + synaptics_rmi4_free_fingers(rmi4_data); + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + finger_presence = 0; + } + if (stylus_presence) {/* Allow one stylus at a timee */ + if (finger + 1 != stylus_presence) + break; + } + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 1); + if (finger_status == F12_STYLUS_STATUS) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 1); + } else { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 1); + } + input_report_abs(rmi4_data->stylus_dev, + ABS_X, x); + input_report_abs(rmi4_data->stylus_dev, + ABS_Y, y); + input_sync(rmi4_data->stylus_dev); + + stylus_presence = finger + 1; + touch_count++; + break; + default: +#ifdef TYPE_B_PROTOCOL + input_mt_slot(rmi4_data->input_dev, finger); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 0); +#endif + break; + } + } + + if (touch_count == 0) { + finger_presence = 0; +#ifdef F12_DATA_15_WORKAROUND + objects_already_present = 0; +#endif + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + + if (rmi4_data->stylus_enable) { + stylus_presence = 0; + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 0); + if (rmi4_data->eraser_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 0); + } + input_sync(rmi4_data->stylus_dev); + } + } + + input_sync(rmi4_data->input_dev); + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return touch_count; +} + +static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char touch_count = 0; + unsigned char button; + unsigned char index; + unsigned char shift; + unsigned char status; + unsigned char *data; + unsigned short data_addr = fhandler->full_addr.data_base; + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + static unsigned char do_once = 1; + static bool current_status[MAX_NUMBER_OF_BUTTONS]; +#ifdef NO_0D_WHILE_2D + static bool before_2d_status[MAX_NUMBER_OF_BUTTONS]; + static bool while_2d_status[MAX_NUMBER_OF_BUTTONS]; +#endif + + if (do_once) { + memset(current_status, 0, sizeof(current_status)); +#ifdef NO_0D_WHILE_2D + memset(before_2d_status, 0, sizeof(before_2d_status)); + memset(while_2d_status, 0, sizeof(while_2d_status)); +#endif + do_once = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_addr, + f1a->button_data_buffer, + f1a->button_bitmask_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read button data registers\n", + __func__); + return; + } + + data = f1a->button_data_buffer; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + + for (button = 0; button < f1a->valid_button_count; button++) { + index = button / 8; + shift = button % 8; + status = ((data[index] >> shift) & MASK_1BIT); + + if (current_status[button] == status) + continue; + else + current_status[button] = status; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Button %d (code %d) ->%d\n", + __func__, button, + f1a->button_map[button], + status); +#ifdef NO_0D_WHILE_2D + if (rmi4_data->fingers_on_2d == false) { + if (status == 1) { + before_2d_status[button] = 1; + } else { + if (while_2d_status[button] == 1) { + while_2d_status[button] = 0; + continue; + } else { + before_2d_status[button] = 0; + } + } + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); + } else { + if (before_2d_status[button] == 1) { + before_2d_status[button] = 0; + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); + } else { + if (status == 1) + while_2d_status[button] = 1; + else + while_2d_status[button] = 0; + } + } +#else + touch_count++; + input_report_key(rmi4_data->input_dev, + f1a->button_map[button], + status); +#endif + } + + if (touch_count) + input_sync(rmi4_data->input_dev); + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + return; +} + +static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + unsigned char touch_count_2d; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x reporting\n", + __func__, fhandler->fn_number); + + switch (fhandler->fn_number) { + case SYNAPTICS_RMI4_F11: + touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data, + fhandler); + + if (touch_count_2d) + rmi4_data->fingers_on_2d = true; + else + rmi4_data->fingers_on_2d = false; + break; + case SYNAPTICS_RMI4_F12: + touch_count_2d = synaptics_rmi4_f12_abs_report(rmi4_data, + fhandler); + + if (touch_count_2d) + rmi4_data->fingers_on_2d = true; + else + rmi4_data->fingers_on_2d = false; + break; + case SYNAPTICS_RMI4_F1A: + synaptics_rmi4_f1a_report(rmi4_data, fhandler); + break; +#ifdef USE_DATA_SERVER + case SYNAPTICS_RMI4_F21: + if (synad_pid) + send_sig_info(SIGIO, &interrupt_signal, synad_task); + break; +#endif + default: + break; + } + + return; +} + +static void synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data, + bool report) +{ + int retval; + unsigned char data[MAX_INTR_REGISTERS + 1]; + unsigned char *intr = &data[1]; + bool was_in_bl_mode; + struct synaptics_rmi4_f01_device_status status; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + /* + * Get interrupt status information from F01 Data1 register to + * determine the source(s) that are flagging the interrupt. + */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + data, + rmi4_data->num_of_intr_regs + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read interrupt status\n", + __func__); + return; + } + + status.data[0] = data[0]; + if (status.status_code == STATUS_CRC_IN_PROGRESS) { + retval = synaptics_rmi4_check_status(rmi4_data, + &was_in_bl_mode); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to check status\n", + __func__); + return; + } + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device status\n", + __func__); + return; + } + } + if (status.unconfigured && !status.flash_prog) { + pr_notice("%s: spontaneous reset detected\n", __func__); + retval = synaptics_rmi4_reinit_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reinit device\n", + __func__); + } + } + + if (!report) + return; + + /* + * Traverse the function handler list and service the source(s) + * of the interrupt accordingly. + */ + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & + intr[fhandler->intr_reg_num]) { + + synaptics_rmi4_report_touch(rmi4_data, + fhandler); + + } + } + } + } + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) { + if (!exp_fhandler->insert && + !exp_fhandler->remove && + (exp_fhandler->exp_fn->attn != NULL)) + exp_fhandler->exp_fn->attn(rmi4_data, intr[0]); + } + } + mutex_unlock(&exp_data.mutex); + + return; +} + +static irqreturn_t synaptics_rmi4_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *rmi4_data = data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (gpio_get_value(bdata->irq_gpio) != bdata->irq_on_state) + goto exit; + + synaptics_rmi4_sensor_report(rmi4_data, true); + +exit: + return IRQ_HANDLED; +} + +static int synaptics_rmi4_int_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval = 0; + unsigned char ii; + unsigned char zero = 0x00; + unsigned char *intr_mask; + unsigned short intr_addr; + + intr_mask = rmi4_data->intr_mask; + + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { + if (intr_mask[ii] != 0x00) { + intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii; + if (enable) { + retval = synaptics_rmi4_reg_write(rmi4_data, + intr_addr, + &(intr_mask[ii]), + sizeof(intr_mask[ii])); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_write(rmi4_data, + intr_addr, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } + } + } + + return retval; +} + +static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable, bool attn_only) +{ + int retval = 0; + unsigned char data[MAX_INTR_REGISTERS]; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex)); + + if (attn_only) { + retval = synaptics_rmi4_int_enable(rmi4_data, enable); + goto exit; + } + + if (enable) { + if (rmi4_data->irq_enabled) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Interrupt already enabled\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_int_enable(rmi4_data, false); + if (retval < 0) + goto exit; + + /* Clear interrupts */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr + 1, + data, + rmi4_data->num_of_intr_regs); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read interrupt status\n", + __func__); + goto exit; + } + + retval = request_threaded_irq(rmi4_data->irq, NULL, + synaptics_rmi4_irq, bdata->irq_flags, + PLATFORM_DRIVER_NAME, rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create irq thread\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_int_enable(rmi4_data, true); + if (retval < 0) + goto exit; + + rmi4_data->irq_enabled = true; + } else { + if (rmi4_data->irq_enabled) { + disable_irq(rmi4_data->irq); + free_irq(rmi4_data->irq, rmi4_data); + rmi4_data->irq_enabled = false; + } + } + +exit: + mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex)); + + return retval; +} + +static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + unsigned char ii; + unsigned char intr_offset; + + fhandler->intr_reg_num = (intr_count + 7) / 8; + if (fhandler->intr_reg_num != 0) + fhandler->intr_reg_num -= 1; + + /* Set an enable bit for each data source */ + intr_offset = intr_count % 8; + fhandler->intr_mask = 0; + for (ii = intr_offset; + ii < (fd->intr_src_count + intr_offset); + ii++) + fhandler->intr_mask |= 1 << ii; + + return; +} + +static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->data = NULL; + fhandler->extra = NULL; + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + rmi4_data->f01_query_base_addr = fd->query_base_addr; + rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr; + rmi4_data->f01_data_base_addr = fd->data_base_addr; + rmi4_data->f01_cmd_base_addr = fd->cmd_base_addr; + + return 0; +} + +static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval; + int temp; + unsigned char offset; + unsigned char fingers_supported; + struct synaptics_rmi4_f11_extra_data *extra_data; + struct synaptics_rmi4_f11_query_0_5 query_0_5; + struct synaptics_rmi4_f11_query_7_8 query_7_8; + struct synaptics_rmi4_f11_query_9 query_9; + struct synaptics_rmi4_f11_query_12 query_12; + struct synaptics_rmi4_f11_query_27 query_27; + struct synaptics_rmi4_f11_ctrl_6_9 control_6_9; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL); + if (!fhandler->extra) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->extra\n", + __func__); + return -ENOMEM; + } + extra_data = (struct synaptics_rmi4_f11_extra_data *)fhandler->extra; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base, + query_0_5.data, + sizeof(query_0_5.data)); + if (retval < 0) + return retval; + + /* Maximum number of fingers supported */ + if (query_0_5.num_of_fingers <= 4) + fhandler->num_of_data_points = query_0_5.num_of_fingers + 1; + else if (query_0_5.num_of_fingers == 5) + fhandler->num_of_data_points = 10; + + rmi4_data->num_of_fingers = fhandler->num_of_data_points; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + 6, + control_6_9.data, + sizeof(control_6_9.data)); + if (retval < 0) + return retval; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = control_6_9.sensor_max_x_pos_7_0 | + (control_6_9.sensor_max_x_pos_11_8 << 8); + rmi4_data->sensor_max_y = control_6_9.sensor_max_y_pos_7_0 | + (control_6_9.sensor_max_y_pos_11_8 << 8); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x max x = %d max y = %d\n", + __func__, fhandler->fn_number, + rmi4_data->sensor_max_x, + rmi4_data->sensor_max_y); + + rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH; + + if (bdata->swap_axes) { + temp = rmi4_data->sensor_max_x; + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y; + rmi4_data->sensor_max_y = temp; + } + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + fhandler->data = NULL; + + offset = sizeof(query_0_5.data); + + /* query 6 */ + if (query_0_5.has_rel) + offset += 1; + + /* queries 7 8 */ + if (query_0_5.has_gestures) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_7_8.data, + sizeof(query_7_8.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_7_8.data); + } + + /* query 9 */ + if (query_0_5.has_query_9) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_9.data, + sizeof(query_9.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_9.data); + } + + /* query 10 */ + if (query_0_5.has_gestures && query_7_8.has_touch_shapes) + offset += 1; + + /* query 11 */ + if (query_0_5.has_query_11) + offset += 1; + + /* query 12 */ + if (query_0_5.has_query_12) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_12.data, + sizeof(query_12.data)); + if (retval < 0) + return retval; + + offset += sizeof(query_12.data); + } + + /* query 13 */ + if (query_0_5.has_jitter_filter) + offset += 1; + + /* query 14 */ + if (query_0_5.has_query_12 && query_12.has_general_information_2) + offset += 1; + + /* queries 15 16 17 18 19 20 21 22 23 24 25 26*/ + if (query_0_5.has_query_12 && query_12.has_physical_properties) + offset += 12; + + /* query 27 */ + if (query_0_5.has_query_27) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_27.data, + sizeof(query_27.data)); + if (retval < 0) + return retval; + + rmi4_data->f11_wakeup_gesture = query_27.has_wakeup_gesture; + } + + if (!rmi4_data->f11_wakeup_gesture) + return retval; + + /* data 0 */ + fingers_supported = fhandler->num_of_data_points; + offset = (fingers_supported + 3) / 4; + + /* data 1 2 3 4 5 */ + offset += 5 * fingers_supported; + + /* data 6 7 */ + if (query_0_5.has_rel) + offset += 2 * fingers_supported; + + /* data 8 */ + if (query_0_5.has_gestures && query_7_8.data[0]) + offset += 1; + + /* data 9 */ + if (query_0_5.has_gestures && (query_7_8.data[0] || query_7_8.data[1])) + offset += 1; + + /* data 10 */ + if (query_0_5.has_gestures && + (query_7_8.has_pinch || query_7_8.has_flick)) + offset += 1; + + /* data 11 12 */ + if (query_0_5.has_gestures && + (query_7_8.has_flick || query_7_8.has_rotate)) + offset += 2; + + /* data 13 */ + if (query_0_5.has_gestures && query_7_8.has_touch_shapes) + offset += (fingers_supported + 3) / 4; + + /* data 14 15 */ + if (query_0_5.has_gestures && + (query_7_8.has_scroll_zones || + query_7_8.has_multi_finger_scroll || + query_7_8.has_chiral_scroll)) + offset += 2; + + /* data 16 17 */ + if (query_0_5.has_gestures && + (query_7_8.has_scroll_zones && + query_7_8.individual_scroll_zones)) + offset += 2; + + /* data 18 19 20 21 22 23 24 25 26 27 */ + if (query_0_5.has_query_9 && query_9.has_contact_geometry) + offset += 10 * fingers_supported; + + /* data 28 */ + if (query_0_5.has_bending_correction || + query_0_5.has_large_object_suppression) + offset += 1; + + /* data 29 30 31 */ + if (query_0_5.has_query_9 && query_9.has_pen_hover_discrimination) + offset += 3; + + /* data 32 */ + if (query_0_5.has_query_12 && + query_12.has_small_object_detection_tuning) + offset += 1; + + /* data 33 34 */ + if (query_0_5.has_query_27 && query_27.f11_query27_b0) + offset += 2; + + /* data 35 */ + if (query_0_5.has_query_12 && query_12.has_8bit_w) + offset += fingers_supported; + + /* data 36 */ + if (query_0_5.has_bending_correction) + offset += 1; + + /* data 37 */ + if (query_0_5.has_query_27 && query_27.has_data_37) + offset += 1; + + /* data 38 */ + if (query_0_5.has_query_27 && query_27.has_wakeup_gesture) + extra_data->data38_offset = offset; + + return retval; +} + +static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data, + unsigned short ctrl28) +{ + int retval; + static unsigned short ctrl_28_address; + + if (ctrl28) + ctrl_28_address = ctrl28; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_28_address, + &rmi4_data->report_enable, + sizeof(rmi4_data->report_enable)); + if (retval < 0) + return retval; + + return retval; +} + +static int synaptics_rmi4_f12_find_sub(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + unsigned char *presence, unsigned char presence_size, + unsigned char structure_offset, unsigned char reg, + unsigned char sub) +{ + int retval; + unsigned char cnt; + unsigned char regnum; + unsigned char bitnum; + unsigned char p_index; + unsigned char s_index; + unsigned char offset; + unsigned char max_reg; + unsigned char *structure; + + max_reg = (presence_size - 1) * 8 - 1; + + if (reg > max_reg) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Register number (%d) over limit\n", + __func__, reg); + return -EINVAL; + } + + p_index = reg / 8 + 1; + bitnum = reg % 8; + if ((presence[p_index] & (1 << bitnum)) == 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Register %d is not present\n", + __func__, reg); + return -EINVAL; + } + + structure = kmalloc(presence[0], GFP_KERNEL); + if (!structure) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for structure register\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + structure_offset, + structure, + presence[0]); + if (retval < 0) + goto exit; + + s_index = 0; + + for (regnum = 0; regnum < reg; regnum++) { + p_index = regnum / 8 + 1; + bitnum = regnum % 8; + if ((presence[p_index] & (1 << bitnum)) == 0x00) + continue; + + if (structure[s_index] == 0x00) + s_index += 3; + else + s_index++; + + while (structure[s_index] & ~MASK_7BIT) + s_index++; + + s_index++; + } + + cnt = 0; + s_index++; + offset = sub / 7; + bitnum = sub % 7; + + do { + if (cnt == offset) { + if (structure[s_index + cnt] & (1 << bitnum)) + retval = 1; + else + retval = 0; + goto exit; + } + cnt++; + } while (structure[s_index + cnt - 1] & ~MASK_7BIT); + + retval = 0; + +exit: + kfree(structure); + + return retval; +} + +static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval = 0; + int temp; + unsigned char subpacket; + unsigned char ctrl_23_size; + unsigned char size_of_2d_data; + unsigned char size_of_query5; + unsigned char size_of_query8; + unsigned char ctrl_8_offset; + unsigned char ctrl_20_offset; + unsigned char ctrl_23_offset; + unsigned char ctrl_28_offset; + unsigned char ctrl_31_offset; + unsigned char ctrl_58_offset; + unsigned char num_of_fingers; + struct synaptics_rmi4_f12_extra_data *extra_data; + struct synaptics_rmi4_f12_query_5 *query_5 = NULL; + struct synaptics_rmi4_f12_query_8 *query_8 = NULL; + struct synaptics_rmi4_f12_ctrl_8 *ctrl_8 = NULL; + struct synaptics_rmi4_f12_ctrl_23 *ctrl_23 = NULL; + struct synaptics_rmi4_f12_ctrl_31 *ctrl_31 = NULL; + struct synaptics_rmi4_f12_ctrl_58 *ctrl_58 = NULL; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL); + if (!fhandler->extra) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->extra\n", + __func__); + return -ENOMEM; + } + extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra; + size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data); + + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL); + if (!query_5) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_5\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + query_8 = kzalloc(sizeof(*query_8), GFP_KERNEL); + if (!query_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_8 = kzalloc(sizeof(*ctrl_8), GFP_KERNEL); + if (!ctrl_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_23 = kzalloc(sizeof(*ctrl_23), GFP_KERNEL); + if (!ctrl_23) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_23\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_31 = kzalloc(sizeof(*ctrl_31), GFP_KERNEL); + if (!ctrl_31) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_31\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + ctrl_58 = kzalloc(sizeof(*ctrl_58), GFP_KERNEL); + if (!ctrl_58) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for ctrl_58\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 4, + &size_of_query5, + sizeof(size_of_query5)); + if (retval < 0) + goto exit; + + if (size_of_query5 > sizeof(query_5->data)) + size_of_query5 = sizeof(query_5->data); + memset(query_5->data, 0x00, sizeof(query_5->data)); + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 5, + query_5->data, + size_of_query5); + if (retval < 0) + goto exit; + + ctrl_8_offset = query_5->ctrl0_is_present + + query_5->ctrl1_is_present + + query_5->ctrl2_is_present + + query_5->ctrl3_is_present + + query_5->ctrl4_is_present + + query_5->ctrl5_is_present + + query_5->ctrl6_is_present + + query_5->ctrl7_is_present; + + ctrl_20_offset = ctrl_8_offset + + query_5->ctrl8_is_present + + query_5->ctrl9_is_present + + query_5->ctrl10_is_present + + query_5->ctrl11_is_present + + query_5->ctrl12_is_present + + query_5->ctrl13_is_present + + query_5->ctrl14_is_present + + query_5->ctrl15_is_present + + query_5->ctrl16_is_present + + query_5->ctrl17_is_present + + query_5->ctrl18_is_present + + query_5->ctrl19_is_present; + + ctrl_23_offset = ctrl_20_offset + + query_5->ctrl20_is_present + + query_5->ctrl21_is_present + + query_5->ctrl22_is_present; + + ctrl_28_offset = ctrl_23_offset + + query_5->ctrl23_is_present + + query_5->ctrl24_is_present + + query_5->ctrl25_is_present + + query_5->ctrl26_is_present + + query_5->ctrl27_is_present; + + ctrl_31_offset = ctrl_28_offset + + query_5->ctrl28_is_present + + query_5->ctrl29_is_present + + query_5->ctrl30_is_present; + + ctrl_58_offset = ctrl_31_offset + + query_5->ctrl31_is_present + + query_5->ctrl32_is_present + + query_5->ctrl33_is_present + + query_5->ctrl34_is_present + + query_5->ctrl35_is_present + + query_5->ctrl36_is_present + + query_5->ctrl37_is_present + + query_5->ctrl38_is_present + + query_5->ctrl39_is_present + + query_5->ctrl40_is_present + + query_5->ctrl41_is_present + + query_5->ctrl42_is_present + + query_5->ctrl43_is_present + + query_5->ctrl44_is_present + + query_5->ctrl45_is_present + + query_5->ctrl46_is_present + + query_5->ctrl47_is_present + + query_5->ctrl48_is_present + + query_5->ctrl49_is_present + + query_5->ctrl50_is_present + + query_5->ctrl51_is_present + + query_5->ctrl52_is_present + + query_5->ctrl53_is_present + + query_5->ctrl54_is_present + + query_5->ctrl55_is_present + + query_5->ctrl56_is_present + + query_5->ctrl57_is_present; + + ctrl_23_size = 2; + for (subpacket = 2; subpacket <= 4; subpacket++) { + retval = synaptics_rmi4_f12_find_sub(rmi4_data, + fhandler, query_5->data, sizeof(query_5->data), + 6, 23, subpacket); + if (retval == 1) + ctrl_23_size++; + else if (retval < 0) + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_23_offset, + ctrl_23->data, + ctrl_23_size); + if (retval < 0) + goto exit; + + /* Maximum number of fingers supported */ + fhandler->num_of_data_points = min_t(unsigned char, + ctrl_23->max_reported_objects, + (unsigned char)F12_FINGERS_TO_SUPPORT); + + num_of_fingers = fhandler->num_of_data_points; + rmi4_data->num_of_fingers = num_of_fingers; + + rmi4_data->stylus_enable = ctrl_23->stylus_enable; + rmi4_data->eraser_enable = ctrl_23->eraser_enable; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 7, + &size_of_query8, + sizeof(size_of_query8)); + if (retval < 0) + goto exit; + + if (size_of_query8 > sizeof(query_8->data)) + size_of_query8 = sizeof(query_8->data); + memset(query_8->data, 0x00, sizeof(query_8->data)); + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + 8, + query_8->data, + size_of_query8); + if (retval < 0) + goto exit; + + /* Determine the presence of the Data0 register */ + extra_data->data1_offset = query_8->data0_is_present; + + if ((size_of_query8 >= 3) && (query_8->data15_is_present)) { + extra_data->data15_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present + + query_8->data4_is_present + + query_8->data5_is_present + + query_8->data6_is_present + + query_8->data7_is_present + + query_8->data8_is_present + + query_8->data9_is_present + + query_8->data10_is_present + + query_8->data11_is_present + + query_8->data12_is_present + + query_8->data13_is_present + + query_8->data14_is_present; + extra_data->data15_size = (num_of_fingers + 7) / 8; + } else { + extra_data->data15_size = 0; + } + +#ifdef REPORT_2D_PRESSURE + if ((size_of_query8 >= 5) && (query_8->data29_is_present)) { + extra_data->data29_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present + + query_8->data4_is_present + + query_8->data5_is_present + + query_8->data6_is_present + + query_8->data7_is_present + + query_8->data8_is_present + + query_8->data9_is_present + + query_8->data10_is_present + + query_8->data11_is_present + + query_8->data12_is_present + + query_8->data13_is_present + + query_8->data14_is_present + + query_8->data15_is_present + + query_8->data16_is_present + + query_8->data17_is_present + + query_8->data18_is_present + + query_8->data19_is_present + + query_8->data20_is_present + + query_8->data21_is_present + + query_8->data22_is_present + + query_8->data23_is_present + + query_8->data24_is_present + + query_8->data25_is_present + + query_8->data26_is_present + + query_8->data27_is_present + + query_8->data28_is_present; + extra_data->data29_size = 0; + for (subpacket = 0; subpacket <= num_of_fingers; subpacket++) { + retval = synaptics_rmi4_f12_find_sub(rmi4_data, + fhandler, query_8->data, + sizeof(query_8->data), + 9, 29, subpacket); + if (retval == 1) + extra_data->data29_size += 2; + else if (retval < 0) + goto exit; + } + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_58_offset, + ctrl_58->data, + sizeof(ctrl_58->data)); + if (retval < 0) + goto exit; + rmi4_data->force_min = + (int)(ctrl_58->min_force_lsb << 0) | + (int)(ctrl_58->min_force_msb << 8); + rmi4_data->force_max = + (int)(ctrl_58->max_force_lsb << 0) | + (int)(ctrl_58->max_force_msb << 8); + rmi4_data->report_pressure = true; + } else { + extra_data->data29_size = 0; + rmi4_data->report_pressure = false; + } +#endif + + rmi4_data->report_enable = RPT_DEFAULT; +#ifdef REPORT_2D_Z + rmi4_data->report_enable |= RPT_Z; +#endif +#ifdef REPORT_2D_W + rmi4_data->report_enable |= (RPT_WX | RPT_WY); +#endif + + retval = synaptics_rmi4_f12_set_enables(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_28_offset); + if (retval < 0) + goto exit; + + if (query_5->ctrl8_is_present) { + rmi4_data->wedge_sensor = false; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_8_offset, + ctrl_8->data, + sizeof(ctrl_8->data)); + if (retval < 0) + goto exit; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = + ((unsigned int)ctrl_8->max_x_coord_lsb << 0) | + ((unsigned int)ctrl_8->max_x_coord_msb << 8); + rmi4_data->sensor_max_y = + ((unsigned int)ctrl_8->max_y_coord_lsb << 0) | + ((unsigned int)ctrl_8->max_y_coord_msb << 8); + + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH; + } else { + rmi4_data->wedge_sensor = true; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + ctrl_31_offset, + ctrl_31->data, + sizeof(ctrl_31->data)); + if (retval < 0) + goto exit; + + /* Maximum x and y */ + rmi4_data->sensor_max_x = + ((unsigned int)ctrl_31->max_x_coord_lsb << 0) | + ((unsigned int)ctrl_31->max_x_coord_msb << 8); + rmi4_data->sensor_max_y = + ((unsigned int)ctrl_31->max_y_coord_lsb << 0) | + ((unsigned int)ctrl_31->max_y_coord_msb << 8); + + rmi4_data->max_touch_width = MAX_F12_TOUCH_WIDTH; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Function %02x max x = %d max y = %d\n", + __func__, fhandler->fn_number, + rmi4_data->sensor_max_x, + rmi4_data->sensor_max_y); + + if (bdata->swap_axes) { + temp = rmi4_data->sensor_max_x; + rmi4_data->sensor_max_x = rmi4_data->sensor_max_y; + rmi4_data->sensor_max_y = temp; + } + + rmi4_data->f12_wakeup_gesture = query_5->ctrl27_is_present; + if (rmi4_data->f12_wakeup_gesture) { + extra_data->ctrl20_offset = ctrl_20_offset; + extra_data->data4_offset = query_8->data0_is_present + + query_8->data1_is_present + + query_8->data2_is_present + + query_8->data3_is_present; + } + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + /* Allocate memory for finger data storage space */ + fhandler->data_size = num_of_fingers * size_of_2d_data; + fhandler->data = kmalloc(fhandler->data_size, GFP_KERNEL); + if (!fhandler->data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fhandler->data\n", + __func__); + retval = -ENOMEM; + goto exit; + } + +exit: + kfree(query_5); + kfree(query_8); + kfree(ctrl_8); + kfree(ctrl_23); + kfree(ctrl_31); + kfree(ctrl_58); + + return retval; +} + +static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + struct synaptics_rmi4_f1a_handle *f1a; + + f1a = kzalloc(sizeof(*f1a), GFP_KERNEL); + if (!f1a) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for function handle\n", + __func__); + return -ENOMEM; + } + + fhandler->data = (void *)f1a; + fhandler->extra = NULL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base, + f1a->button_query.data, + sizeof(f1a->button_query.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query registers\n", + __func__); + return retval; + } + + f1a->max_count = f1a->button_query.max_button_count + 1; + + f1a->button_control.txrx_map = kzalloc(f1a->max_count * 2, GFP_KERNEL); + if (!f1a->button_control.txrx_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tx rx mapping\n", + __func__); + return -ENOMEM; + } + + f1a->button_bitmask_size = (f1a->max_count + 7) / 8; + + f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size, + sizeof(*(f1a->button_data_buffer)), GFP_KERNEL); + if (!f1a->button_data_buffer) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", + __func__); + return -ENOMEM; + } + + f1a->button_map = kcalloc(f1a->max_count, + sizeof(*(f1a->button_map)), GFP_KERNEL); + if (!f1a->button_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for button map\n", + __func__); + return -ENOMEM; + } + + return 0; +} + +static int synaptics_rmi4_f1a_button_map(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler) +{ + int retval; + unsigned char ii; + unsigned char offset = 0; + struct synaptics_rmi4_f1a_query_4 query_4; + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + rmi4_data->valid_button_count = f1a->valid_button_count; + + offset = f1a->button_query.has_general_control + + f1a->button_query.has_interrupt_enable + + f1a->button_query.has_multibutton_select; + + if (f1a->button_query.has_tx_rx_map) { + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.ctrl_base + offset, + f1a->button_control.txrx_map, + f1a->max_count * 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tx rx mapping\n", + __func__); + return retval; + } + + rmi4_data->button_txrx_mapping = f1a->button_control.txrx_map; + } + + if (f1a->button_query.has_query4) { + offset = 2 + f1a->button_query.has_query2 + + f1a->button_query.has_query3; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fhandler->full_addr.query_base + offset, + query_4.data, + sizeof(query_4.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read button features 4\n", + __func__); + return retval; + } + + if (query_4.has_ctrl24) + rmi4_data->external_afe_buttons = true; + else + rmi4_data->external_afe_buttons = false; + } + + if (!bdata->cap_button_map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: cap_button_map is NULL in board file\n", + __func__); + return -ENODEV; + } else if (!bdata->cap_button_map->map) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Button map is missing in board file\n", + __func__); + return -ENODEV; + } else { + if (bdata->cap_button_map->nbuttons != f1a->max_count) { + f1a->valid_button_count = min(f1a->max_count, + bdata->cap_button_map->nbuttons); + } else { + f1a->valid_button_count = f1a->max_count; + } + + for (ii = 0; ii < f1a->valid_button_count; ii++) + f1a->button_map[ii] = bdata->cap_button_map->map[ii]; + + rmi4_data->valid_button_count = f1a->valid_button_count; + } + + return 0; +} + +static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler) +{ + struct synaptics_rmi4_f1a_handle *f1a = fhandler->data; + + if (f1a) { + kfree(f1a->button_control.txrx_map); + kfree(f1a->button_data_buffer); + kfree(f1a->button_map); + kfree(f1a); + fhandler->data = NULL; + } + + return; +} + +static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) +{ + int retval; + + fhandler->fn_number = fd->fn_number; + fhandler->num_of_data_sources = fd->intr_src_count; + + synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + + retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler); + if (retval < 0) + goto error_exit; + + retval = synaptics_rmi4_f1a_button_map(rmi4_data, fhandler); + if (retval < 0) + goto error_exit; + + rmi4_data->button_0d_enabled = 1; + + return 0; + +error_exit: + synaptics_rmi4_f1a_kfree(fhandler); + + return retval; +} + +static void synaptics_rmi4_empty_fn_list(struct synaptics_rmi4_data *rmi4_data) +{ + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_fn *fhandler_temp; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry_safe(fhandler, + fhandler_temp, + &rmi->support_fn_list, + link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) { + synaptics_rmi4_f1a_kfree(fhandler); + } else { + kfree(fhandler->extra); + kfree(fhandler->data); + } + list_del(&fhandler->link); + kfree(fhandler); + } + } + INIT_LIST_HEAD(&rmi->support_fn_list); + + return; +} + +static int synaptics_rmi4_check_status(struct synaptics_rmi4_data *rmi4_data, + bool *was_in_bl_mode) +{ + int retval; + int timeout = CHECK_STATUS_TIMEOUT_MS; + struct synaptics_rmi4_f01_device_status status; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) + return retval; + + while (status.status_code == STATUS_CRC_IN_PROGRESS) { + if (timeout > 0) + msleep(20); + else + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr, + status.data, + sizeof(status.data)); + if (retval < 0) + return retval; + + timeout -= 20; + } + + if (timeout != CHECK_STATUS_TIMEOUT_MS) + *was_in_bl_mode = true; + + if (status.flash_prog == 1) { + rmi4_data->flash_prog_mode = true; + pr_notice("%s: In flash prog mode, status = 0x%02x\n", + __func__, + status.status_code); + } else { + rmi4_data->flash_prog_mode = false; + } + + return 0; +} + +static void synaptics_rmi4_set_configured(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char device_ctrl; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set configured\n", + __func__); + return; + } + + rmi4_data->no_sleep_setting = device_ctrl & NO_SLEEP_ON; + device_ctrl |= CONFIGURED; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set configured\n", + __func__); + } + + return; +} + +static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler, + struct synaptics_rmi4_fn_desc *rmi_fd, int page_number) +{ + *fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL); + if (!(*fhandler)) + return -ENOMEM; + + (*fhandler)->full_addr.data_base = + (rmi_fd->data_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.ctrl_base = + (rmi_fd->ctrl_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.cmd_base = + (rmi_fd->cmd_base_addr | + (page_number << 8)); + (*fhandler)->full_addr.query_base = + (rmi_fd->query_base_addr | + (page_number << 8)); + + return 0; +} + +static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char page_number; + unsigned char intr_count; + unsigned char *f01_query; + unsigned short pdt_entry_addr; + bool f01found; + bool f35found; + bool was_in_bl_mode; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + +rescan_pdt: + f01found = false; + f35found = false; + was_in_bl_mode = false; + intr_count = 0; + INIT_LIST_HEAD(&rmi->support_fn_list); + + /* Scan the page description tables of the pages to service */ + for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) { + for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END; + pdt_entry_addr -= PDT_ENTRY_SIZE) { + pdt_entry_addr |= (page_number << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + pdt_entry_addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + pdt_entry_addr &= ~(MASK_8BIT << 8); + + fhandler = NULL; + + if (rmi_fd.fn_number == 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Reached end of PDT\n", + __func__); + break; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: F%02x found (page %d)\n", + __func__, rmi_fd.fn_number, + page_number); + + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + if (rmi_fd.intr_src_count == 0) + break; + + f01found = true; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f01_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_check_status(rmi4_data, + &was_in_bl_mode); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to check status\n", + __func__); + return retval; + } + + if (was_in_bl_mode) { + kfree(fhandler); + fhandler = NULL; + goto rescan_pdt; + } + + if (rmi4_data->flash_prog_mode) + goto flash_prog_mode; + + break; + case SYNAPTICS_RMI4_F11: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f11_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + break; + case SYNAPTICS_RMI4_F12: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f12_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; + break; + case SYNAPTICS_RMI4_F1A: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + retval = synaptics_rmi4_f1a_init(rmi4_data, + fhandler, &rmi_fd, intr_count); + if (retval < 0) { +#ifdef IGNORE_FN_INIT_FAILURE + kfree(fhandler); + fhandler = NULL; +#else + return retval; +#endif + } + break; +#ifdef USE_DATA_SERVER + case SYNAPTICS_RMI4_F21: + if (rmi_fd.intr_src_count == 0) + break; + + retval = synaptics_rmi4_alloc_fh(&fhandler, + &rmi_fd, page_number); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc for F%d\n", + __func__, + rmi_fd.fn_number); + return retval; + } + + fhandler->fn_number = rmi_fd.fn_number; + fhandler->num_of_data_sources = + rmi_fd.intr_src_count; + + synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd, + intr_count); + break; +#endif + case SYNAPTICS_RMI4_F35: + f35found = true; + break; +#ifdef F51_DISCRETE_FORCE + case SYNAPTICS_RMI4_F51: + rmi4_data->f51_query_base_addr = + rmi_fd.query_base_addr | + (page_number << 8); + break; +#endif + } + + /* Accumulate the interrupt count */ + intr_count += rmi_fd.intr_src_count; + + if (fhandler && rmi_fd.intr_src_count) { + list_add_tail(&fhandler->link, + &rmi->support_fn_list); + } + } + } + + if (!f01found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F01\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + pr_notice("%s: In microbootloader mode\n", + __func__); + return 0; + } + } + +flash_prog_mode: + rmi4_data->num_of_intr_regs = (intr_count + 7) / 8; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Number of interrupt registers = %d\n", + __func__, rmi4_data->num_of_intr_regs); + + f01_query = kmalloc(F01_STD_QUERY_LEN, GFP_KERNEL); + if (!f01_query) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for f01_query\n", + __func__); + return -ENOMEM; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr, + f01_query, + F01_STD_QUERY_LEN); + if (retval < 0) { + kfree(f01_query); + return retval; + } + + /* RMI Version 4.0 currently supported */ + rmi->version_major = 4; + rmi->version_minor = 0; + + rmi->manufacturer_id = f01_query[0]; + rmi->product_props = f01_query[1]; + rmi->product_info[0] = f01_query[2]; + rmi->product_info[1] = f01_query[3]; + retval = secure_memcpy(rmi->product_id_string, + sizeof(rmi->product_id_string), + &f01_query[11], + F01_STD_QUERY_LEN - 11, + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + + kfree(f01_query); + + if (rmi->manufacturer_id != 1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Non-Synaptics device found, manufacturer ID = %d\n", + __func__, rmi->manufacturer_id); + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET, + rmi->build_id, + sizeof(rmi->build_id)); + if (retval < 0) + return retval; + + rmi4_data->firmware_id = (unsigned int)rmi->build_id[0] + + (unsigned int)rmi->build_id[1] * 0x100 + + (unsigned int)rmi->build_id[2] * 0x10000; + + memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask)); + + /* + * Map out the interrupt bit masks for the interrupt sources + * from the registered function handlers. + */ + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + rmi4_data->intr_mask[fhandler->intr_reg_num] |= + fhandler->intr_mask; + } + } + } + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture){ + rmi4_data->enable_wakeup_gesture = false; + synaptics_gesture_func_on_lansi = false; + } + + synaptics_rmi4_set_configured(rmi4_data); + + return 0; +} + +static int synaptics_rmi4_gpio_setup(int gpio, bool config, int dir, int state) +{ + int retval = 0; + unsigned char buf[16]; + + if (config) { + snprintf(buf, PAGE_SIZE, "dsx_gpio_%u\n", gpio); + + retval = gpio_request(gpio, buf); + if (retval) { + pr_err("%s: Failed to get gpio %d (code: %d)", + __func__, gpio, retval); + return retval; + } + + if (dir == 0) + retval = gpio_direction_input(gpio); + else + retval = gpio_direction_output(gpio, state); + if (retval) { + pr_err("%s: Failed to set gpio %d direction", + __func__, gpio); + return retval; + } + } else { + gpio_free(gpio); + } + + return retval; +} + +static void synaptics_rmi4_set_params(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char ii; + struct synaptics_rmi4_f1a_handle *f1a; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_POSITION_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_POSITION_Y, 0, + rmi4_data->sensor_max_y, 0, 0); +#ifdef REPORT_2D_W + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_TOUCH_MAJOR, 0, + rmi4_data->max_touch_width, 0, 0); + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_TOUCH_MINOR, 0, + rmi4_data->max_touch_width, 0, 0); +#endif + + rmi4_data->input_settings.sensor_max_x = rmi4_data->sensor_max_x; + rmi4_data->input_settings.sensor_max_y = rmi4_data->sensor_max_y; + rmi4_data->input_settings.max_touch_width = rmi4_data->max_touch_width; + +#ifdef REPORT_2D_PRESSURE + if (rmi4_data->report_pressure) { + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_PRESSURE, rmi4_data->force_min, + rmi4_data->force_max, 0, 0); + + rmi4_data->input_settings.force_min = rmi4_data->force_min; + rmi4_data->input_settings.force_max = rmi4_data->force_max; + } +#elif defined(F51_DISCRETE_FORCE) + input_set_abs_params(rmi4_data->input_dev, + ABS_MT_PRESSURE, 0, + FORCE_LEVEL_MAX, 0, 0); +#endif + +#ifdef TYPE_B_PROTOCOL +#ifdef KERNEL_ABOVE_3_6 + input_mt_init_slots(rmi4_data->input_dev, + rmi4_data->num_of_fingers, INPUT_MT_DIRECT); +#else + input_mt_init_slots(rmi4_data->input_dev, + rmi4_data->num_of_fingers); +#endif +#endif + + rmi4_data->input_settings.num_of_fingers = rmi4_data->num_of_fingers; + + f1a = NULL; + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) + f1a = fhandler->data; + } + } + + if (f1a) { + for (ii = 0; ii < f1a->valid_button_count; ii++) { + set_bit(f1a->button_map[ii], + rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, + EV_KEY, f1a->button_map[ii]); + } + + rmi4_data->input_settings.valid_button_count = + f1a->valid_button_count; + } + + if (vir_button_map->nbuttons) { + for (ii = 0; ii < vir_button_map->nbuttons; ii++) { + set_bit(vir_button_map->map[ii * 5], + rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, + EV_KEY, vir_button_map->map[ii * 5]); + } + } + + if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) { + set_bit(KEY_WAKEUP, rmi4_data->input_dev->keybit); + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP); + } + + return; +} + +static int synaptics_rmi4_set_input_dev(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + rmi4_data->input_dev = input_allocate_device(); + if (rmi4_data->input_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate input device\n", + __func__); + retval = -ENOMEM; + goto err_input_device; + } + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + goto err_query_device; + } + + rmi4_data->input_dev->name = PLATFORM_DRIVER_NAME; + rmi4_data->input_dev->phys = INPUT_PHYS_NAME; + rmi4_data->input_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + rmi4_data->input_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + rmi4_data->input_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(rmi4_data->input_dev, rmi4_data); + + set_bit(EV_SYN, rmi4_data->input_dev->evbit); + set_bit(EV_KEY, rmi4_data->input_dev->evbit); + set_bit(EV_ABS, rmi4_data->input_dev->evbit); + set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit); + set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit); +#endif + + if (bdata->max_y_for_2d >= 0) + rmi4_data->sensor_max_y = bdata->max_y_for_2d; + + synaptics_rmi4_set_params(rmi4_data); + + retval = input_register_device(rmi4_data->input_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register input device\n", + __func__); + goto err_register_input; + } + + rmi4_data->input_settings.stylus_enable = rmi4_data->stylus_enable; + rmi4_data->input_settings.eraser_enable = rmi4_data->eraser_enable; + + if (!rmi4_data->stylus_enable) + return 0; + + rmi4_data->stylus_dev = input_allocate_device(); + if (rmi4_data->stylus_dev == NULL) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate stylus device\n", + __func__); + retval = -ENOMEM; + goto err_stylus_device; + } + + rmi4_data->stylus_dev->name = STYLUS_DRIVER_NAME; + rmi4_data->stylus_dev->phys = STYLUS_PHYS_NAME; + rmi4_data->stylus_dev->id.product = SYNAPTICS_DSX_DRIVER_PRODUCT; + rmi4_data->stylus_dev->id.version = SYNAPTICS_DSX_DRIVER_VERSION; + rmi4_data->stylus_dev->dev.parent = rmi4_data->pdev->dev.parent; + input_set_drvdata(rmi4_data->stylus_dev, rmi4_data); + + set_bit(EV_KEY, rmi4_data->stylus_dev->evbit); + set_bit(EV_ABS, rmi4_data->stylus_dev->evbit); + set_bit(BTN_TOUCH, rmi4_data->stylus_dev->keybit); + set_bit(BTN_TOOL_PEN, rmi4_data->stylus_dev->keybit); + if (rmi4_data->eraser_enable) + set_bit(BTN_TOOL_RUBBER, rmi4_data->stylus_dev->keybit); +#ifdef INPUT_PROP_DIRECT + set_bit(INPUT_PROP_DIRECT, rmi4_data->stylus_dev->propbit); +#endif + + input_set_abs_params(rmi4_data->stylus_dev, ABS_X, 0, + rmi4_data->sensor_max_x, 0, 0); + input_set_abs_params(rmi4_data->stylus_dev, ABS_Y, 0, + rmi4_data->sensor_max_y, 0, 0); + + retval = input_register_device(rmi4_data->stylus_dev); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to register stylus device\n", + __func__); + goto err_register_stylus; + } + + return 0; + +err_register_stylus: + rmi4_data->stylus_dev = NULL; + +err_stylus_device: + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + +err_register_input: +err_query_device: + synaptics_rmi4_empty_fn_list(rmi4_data); + input_free_device(rmi4_data->input_dev); + +err_input_device: + return retval; +} + +static int synaptics_rmi4_set_gpio(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + retval = synaptics_rmi4_gpio_setup( + bdata->irq_gpio, + true, 0, 0); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure attention GPIO\n", + __func__); + goto err_gpio_irq; + } + + if (bdata->power_gpio >= 0) { + retval = synaptics_rmi4_gpio_setup( + bdata->power_gpio, + true, 1, !bdata->power_on_state); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure power GPIO\n", + __func__); + goto err_gpio_power; + } + } + + if (bdata->reset_gpio >= 0) { + retval = synaptics_rmi4_gpio_setup( + bdata->reset_gpio, + true, 1, !bdata->reset_on_state); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to configure reset GPIO\n", + __func__); + goto err_gpio_reset; + } + } + + if (bdata->power_gpio >= 0) { + gpio_set_value(bdata->power_gpio, bdata->power_on_state); + msleep(bdata->power_delay_ms); + } + + if (bdata->reset_gpio >= 0) { + gpio_set_value(bdata->reset_gpio, bdata->reset_on_state); + msleep(bdata->reset_active_ms); + gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state); + msleep(bdata->reset_delay_ms); + } + + return 0; + +err_gpio_reset: + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + +err_gpio_power: + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + +err_gpio_irq: + return retval; +} + +static int synaptics_rmi4_get_reg(struct synaptics_rmi4_data *rmi4_data, + bool get) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!get) { + retval = 0; + goto regulator_put; + } + + if ((bdata->pwr_reg_name != NULL) && (*bdata->pwr_reg_name != 0)) { + rmi4_data->pwr_reg = regulator_get(rmi4_data->pdev->dev.parent, + bdata->pwr_reg_name); + if (IS_ERR(rmi4_data->pwr_reg)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get power regulator\n", + __func__); + retval = PTR_ERR(rmi4_data->pwr_reg); + goto regulator_put; + } + } + + if ((bdata->bus_reg_name != NULL) && (*bdata->bus_reg_name != 0)) { + rmi4_data->bus_reg = regulator_get(rmi4_data->pdev->dev.parent, + bdata->bus_reg_name); + if (IS_ERR(rmi4_data->bus_reg)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get bus pullup regulator\n", + __func__); + retval = PTR_ERR(rmi4_data->bus_reg); + goto regulator_put; + } + } + + return 0; + +regulator_put: + if (rmi4_data->pwr_reg) { + regulator_put(rmi4_data->pwr_reg); + rmi4_data->pwr_reg = NULL; + } + + if (rmi4_data->bus_reg) { + regulator_put(rmi4_data->bus_reg); + rmi4_data->bus_reg = NULL; + } + + return retval; +} + +static int synaptics_rmi4_enable_reg(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!enable) { + retval = 0; + goto disable_pwr_reg; + } + + if (rmi4_data->bus_reg) { + retval = regulator_enable(rmi4_data->bus_reg); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable bus pullup regulator\n", + __func__); + goto exit; + } + } + + if (rmi4_data->pwr_reg) { + retval = regulator_enable(rmi4_data->pwr_reg); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to enable power regulator\n", + __func__); + goto disable_bus_reg; + } + msleep(bdata->power_delay_ms); + } + + return 0; + +disable_pwr_reg: + if (rmi4_data->pwr_reg) + regulator_disable(rmi4_data->pwr_reg); + +disable_bus_reg: + if (rmi4_data->bus_reg) + regulator_disable(rmi4_data->bus_reg); + +exit: + return retval; +} + +static int synaptics_rmi4_free_fingers(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char ii; + + mutex_lock(&(rmi4_data->rmi4_report_mutex)); + +#ifdef TYPE_B_PROTOCOL + for (ii = 0; ii < rmi4_data->num_of_fingers; ii++) { + input_mt_slot(rmi4_data->input_dev, ii); + input_mt_report_slot_state(rmi4_data->input_dev, + MT_TOOL_FINGER, 0); + } +#endif + input_report_key(rmi4_data->input_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->input_dev, + BTN_TOOL_FINGER, 0); +#ifndef TYPE_B_PROTOCOL + input_mt_sync(rmi4_data->input_dev); +#endif + input_sync(rmi4_data->input_dev); + + if (rmi4_data->stylus_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOUCH, 0); + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_PEN, 0); + if (rmi4_data->eraser_enable) { + input_report_key(rmi4_data->stylus_dev, + BTN_TOOL_RUBBER, 0); + } + input_sync(rmi4_data->stylus_dev); + } + + mutex_unlock(&(rmi4_data->rmi4_report_mutex)); + + rmi4_data->fingers_on_2d = false; + + return 0; +} + +static int synaptics_rmi4_sw_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char command = 0x01; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + + if (rmi4_data->hw_if->ui_hw_init) { + retval = rmi4_data->hw_if->ui_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + return 0; +} + +static int synaptics_rmi4_do_rebuild(struct synaptics_rmi4_data *rmi4_data) +{ + struct synaptics_rmi4_input_settings *settings; + + settings = &(rmi4_data->input_settings); + + if (settings->num_of_fingers != rmi4_data->num_of_fingers) + return 1; + + if (settings->valid_button_count != rmi4_data->valid_button_count) + return 1; + + if (settings->max_touch_width != rmi4_data->max_touch_width) + return 1; + + if (settings->sensor_max_x != rmi4_data->sensor_max_x) + return 1; + + if (settings->sensor_max_y != rmi4_data->sensor_max_y) + return 1; + + if (settings->force_min != rmi4_data->force_min) + return 1; + + if (settings->force_max != rmi4_data->force_max) + return 1; + + if (settings->stylus_enable != rmi4_data->stylus_enable) + return 1; + + if (settings->eraser_enable != rmi4_data->eraser_enable) + return 1; + + return 0; +} + +static void synaptics_rmi4_rebuild_work(struct work_struct *work) +{ + int retval; + unsigned char attr_count; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + struct synaptics_rmi4_data *rmi4_data = + container_of(delayed_work, struct synaptics_rmi4_data, + rb_work); + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + mutex_lock(&exp_data.mutex); + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->remove != NULL) + exp_fhandler->exp_fn->remove(rmi4_data); + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + synaptics_rmi4_free_fingers(rmi4_data); + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + + retval = synaptics_rmi4_set_input_dev(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up input device\n", + __func__); + goto exit; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit; + } + } + + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->init != NULL) + exp_fhandler->exp_fn->init(rmi4_data); + } + + retval = 0; + +exit: + synaptics_rmi4_irq_enable(rmi4_data, true, false); + + mutex_unlock(&exp_data.mutex); + + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + + return; +} + +static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_device_info *rmi; + + rmi = &(rmi4_data->rmi4_mod_info); + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + synaptics_rmi4_free_fingers(rmi4_data); + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->fn_number == SYNAPTICS_RMI4_F12) { + synaptics_rmi4_f12_set_enables(rmi4_data, 0); + break; + } + } + } + + retval = synaptics_rmi4_int_enable(rmi4_data, true); + if (retval < 0) + goto exit; + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->reinit != NULL) + exp_fhandler->exp_fn->reinit(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + synaptics_rmi4_set_configured(rmi4_data); + + retval = 0; + +exit: + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + return retval; +} + +static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data, + bool rebuild) +{ + int retval; + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + + mutex_lock(&(rmi4_data->rmi4_reset_mutex)); + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + + retval = synaptics_rmi4_sw_reset(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + goto exit; + } + + synaptics_rmi4_free_fingers(rmi4_data); + + synaptics_rmi4_empty_fn_list(rmi4_data); + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + goto exit; + } + + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->reset != NULL) + exp_fhandler->exp_fn->reset(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + retval = 0; + +exit: + synaptics_rmi4_irq_enable(rmi4_data, true, false); + + mutex_unlock(&(rmi4_data->rmi4_reset_mutex)); + + if (rebuild && synaptics_rmi4_do_rebuild(rmi4_data)) { + queue_delayed_work(rmi4_data->rb_workqueue, + &rmi4_data->rb_work, + msecs_to_jiffies(REBUILD_WORK_DELAY_MS)); + } + + return retval; +} + +#ifdef FB_READY_RESET +static void synaptics_rmi4_reset_work(struct work_struct *work) +{ + int retval; + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = + container_of(work, struct synaptics_rmi4_data, + reset_work); + + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return; +} +#endif + +static void synaptics_rmi4_sleep_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval; + unsigned char device_ctrl; + unsigned char no_sleep_setting = rmi4_data->no_sleep_setting; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device control\n", + __func__); + return; + } + + device_ctrl = device_ctrl & ~MASK_3BIT; + if (enable) + device_ctrl = device_ctrl | SENSOR_SLEEP; + else + device_ctrl = device_ctrl | no_sleep_setting | NORMAL_OPERATION; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write device control\n", + __func__); + return; + } + + rmi4_data->sensor_sleep = enable; + + return; +} + +static void synaptics_rmi4_exp_fn_work(struct work_struct *work) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_exp_fhandler *exp_fhandler_temp; + struct synaptics_rmi4_data *rmi4_data = exp_data.rmi4_data; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + mutex_lock(&rmi4_data->rmi4_reset_mutex); + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry_safe(exp_fhandler, + exp_fhandler_temp, + &exp_data.list, + link) { + if ((exp_fhandler->exp_fn->init != NULL) && + exp_fhandler->insert) { + exp_fhandler->exp_fn->init(rmi4_data); + exp_fhandler->insert = false; + } else if ((exp_fhandler->exp_fn->remove != NULL) && + exp_fhandler->remove) { + exp_fhandler->exp_fn->remove(rmi4_data); + list_del(&exp_fhandler->link); + kfree(exp_fhandler); + } + } + } + mutex_unlock(&exp_data.mutex); + mutex_unlock(&rmi4_data->rmi4_reset_mutex); + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return; +} + +void synaptics_rmi4_new_function_lansi(struct synaptics_rmi4_exp_fn *exp_fn, + bool insert) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + + if (!exp_data.initialized) { + mutex_init(&exp_data.mutex); + INIT_LIST_HEAD(&exp_data.list); + exp_data.initialized = true; + } + + mutex_lock(&exp_data.mutex); + if (insert) { + exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL); + if (!exp_fhandler) { + pr_err("%s: Failed to alloc mem for expansion function\n", + __func__); + goto exit; + } + exp_fhandler->exp_fn = exp_fn; + exp_fhandler->insert = true; + exp_fhandler->remove = false; + list_add_tail(&exp_fhandler->link, &exp_data.list); + } else if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) { + if (exp_fhandler->exp_fn->fn_type == exp_fn->fn_type) { + exp_fhandler->insert = false; + exp_fhandler->remove = true; + goto exit; + } + } + } + +exit: + mutex_unlock(&exp_data.mutex); + + if (exp_data.queue_work) { + queue_delayed_work(exp_data.workqueue, + &exp_data.work, + msecs_to_jiffies(EXP_FN_WORK_DELAY_MS)); + } + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_new_function_lansi); + +#ifdef SYNAPTICS_ESD_CHECK +void synaptics_rmi4_esd_work(struct work_struct *work) +{ + unsigned char product_info[F01_STD_QUERY_LEN]; + int retval = 0; + + +struct delayed_work *esd_work = + container_of(work, struct delayed_work, work); +struct synaptics_rmi4_data *rmi4_data = + container_of(esd_work, struct synaptics_rmi4_data, + esd_work); + + +/* + struct synaptics_rmi4_data *rmi4_data = + container_of(work, struct synaptics_rmi4_data, + esd_work); + +*/ + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + printk("[synaptics]Enter %s\n", __func__); + + mutex_lock(&rmi4_data->rmi4_esd_mutex); + + pr_notice("%s: Start of esd check process\n", __func__); + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_query_base_addr, + product_info, + F01_STD_QUERY_LEN); + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s Failed to read product info, need to do HW RESET\n", + __func__); + + gpio_set_value(bdata->reset_gpio, 1); + mdelay(20); + gpio_set_value(bdata->reset_gpio, 0); + mdelay(20); + gpio_set_value(bdata->reset_gpio, 1); + mdelay(200); + + } + + retval = synaptics_rmi4_query_device(rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to query device\n", + __func__); + } + + pr_notice("%s: End of esd check process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_esd_mutex); + + queue_delayed_work(rmi4_data->esd_workqueue, &rmi4_data->esd_work, SYNAPTICS_ESD_CHECK_CIRCLE); + + return; + +} +#endif + + + + +static int synaptics_rmi4_probe(struct platform_device *pdev) +{ + int retval; + unsigned char attr_count; + + const struct synaptics_dsx_hw_interface *hw_if; + const struct synaptics_dsx_board_data *bdata; + + hw_if = pdev->dev.platform_data; + if (!hw_if) { + dev_err(&pdev->dev, + "%s: No hardware interface found\n", + __func__); + return -EINVAL; + } + + bdata = hw_if->board_data; + if (!bdata) { + dev_err(&pdev->dev, + "%s: No board data found\n", + __func__); + return -EINVAL; + } + + rmi4_data = kzalloc(sizeof(*rmi4_data), GFP_KERNEL); + if (!rmi4_data) { + dev_err(&pdev->dev, + "%s: Failed to alloc mem for rmi4_data\n", + __func__); + return -ENOMEM; + } + + rmi4_data->pdev = pdev; + rmi4_data->current_page = MASK_8BIT; + rmi4_data->hw_if = hw_if; + rmi4_data->suspend = false; + rmi4_data->irq_enabled = false; + rmi4_data->fingers_on_2d = false; + + rmi4_data->reset_device = synaptics_rmi4_reset_device; + rmi4_data->irq_enable = synaptics_rmi4_irq_enable; + rmi4_data->sleep_enable = synaptics_rmi4_sleep_enable; + rmi4_data->report_touch = synaptics_rmi4_report_touch; + + mutex_init(&(rmi4_data->rmi4_reset_mutex)); + mutex_init(&(rmi4_data->rmi4_report_mutex)); + mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex)); + mutex_init(&(rmi4_data->rmi4_exp_init_mutex)); + mutex_init(&(rmi4_data->rmi4_irq_enable_mutex)); + mutex_init(&(rmi4_data->rmi4_esd_mutex)); + + + platform_set_drvdata(pdev, rmi4_data); + + vir_button_map = bdata->vir_button_map; + + retval = synaptics_rmi4_get_reg(rmi4_data, true); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to get regulators\n", + __func__); + goto err_get_reg; + } + + retval = synaptics_rmi4_enable_reg(rmi4_data, true); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable regulators\n", + __func__); + goto err_enable_reg; + } + + retval = synaptics_rmi4_set_gpio(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to set up GPIO's\n", + __func__); + goto err_set_gpio; + } + + if (hw_if->ui_hw_init) { + retval = hw_if->ui_hw_init(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to initialize hardware interface\n", + __func__); + goto err_ui_hw_init; + } + } + + retval = synaptics_rmi4_set_input_dev(rmi4_data); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to set up input device\n", + __func__); + goto err_set_input_dev; + } + +#ifdef CONFIG_FB + rmi4_data->fb_notifier.notifier_call = synaptics_rmi4_fb_notifier_cb; + retval = fb_register_client(&rmi4_data->fb_notifier); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to register fb notifier client\n", + __func__); + } +#endif + +#ifdef USE_EARLYSUSPEND + rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend; + rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume; + register_early_suspend(&rmi4_data->early_suspend); +#endif + + if (!exp_data.initialized) { + mutex_init(&exp_data.mutex); + INIT_LIST_HEAD(&exp_data.list); + exp_data.initialized = true; + } + + rmi4_data->irq = gpio_to_irq(bdata->irq_gpio); + + retval = synaptics_rmi4_irq_enable(rmi4_data, true, false); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to enable attention interrupt\n", + __func__); + goto err_enable_irq; + } + + if (vir_button_map->nbuttons) { + rmi4_data->board_prop_dir = kobject_create_and_add( + "board_properties", NULL); + if (!rmi4_data->board_prop_dir) { + dev_err(&pdev->dev, + "%s: Failed to create board_properties directory\n", + __func__); + goto err_virtual_buttons; + } else { + retval = sysfs_create_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to create virtual key map file\n", + __func__); + goto err_virtual_buttons; + } + } + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(&pdev->dev, + "%s: Failed to create sysfs attributes\n", + __func__); + goto err_sysfs; + } + } + +#ifdef USE_DATA_SERVER + memset(&interrupt_signal, 0, sizeof(interrupt_signal)); + interrupt_signal.si_signo = SIGIO; + interrupt_signal.si_code = SI_USER; +#endif + + rmi4_data->rb_workqueue = + create_singlethread_workqueue("dsx_rebuild_workqueue"); + INIT_DELAYED_WORK(&rmi4_data->rb_work, synaptics_rmi4_rebuild_work); + + exp_data.workqueue = create_singlethread_workqueue("dsx_exp_workqueue"); + INIT_DELAYED_WORK(&exp_data.work, synaptics_rmi4_exp_fn_work); + exp_data.rmi4_data = rmi4_data; + exp_data.queue_work = true; + queue_delayed_work(exp_data.workqueue, + &exp_data.work, + 0); + +#ifdef FB_READY_RESET + rmi4_data->reset_workqueue = + create_singlethread_workqueue("dsx_reset_workqueue"); + INIT_WORK(&rmi4_data->reset_work, synaptics_rmi4_reset_work); + queue_work(rmi4_data->reset_workqueue, &rmi4_data->reset_work); +#endif + +#if WAKEUP_GESTURE + input_set_capability(rmi4_data->input_dev, EV_KEY, KEY_WAKEUP); + + rmi4_data->input_dev->event = synaptics_gesture_switch_lansi; +#endif + + +#ifdef SYNAPTICS_ESD_CHECK + rmi4_data->esd_workqueue = create_singlethread_workqueue("dsx_esd_workqueue"); + INIT_DELAYED_WORK(&(rmi4_data->esd_work), synaptics_rmi4_esd_work); + queue_delayed_work(rmi4_data->esd_workqueue, &rmi4_data->esd_work, SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + return retval; + +err_sysfs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + +err_virtual_buttons: + if (rmi4_data->board_prop_dir) { + sysfs_remove_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + kobject_put(rmi4_data->board_prop_dir); + } + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + +err_enable_irq: +#ifdef CONFIG_FB + fb_unregister_client(&rmi4_data->fb_notifier); +#endif + +#ifdef USE_EARLYSUSPEND + unregister_early_suspend(&rmi4_data->early_suspend); +#endif + + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + +err_set_input_dev: + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + + if (bdata->reset_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0); + + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + +err_ui_hw_init: +err_set_gpio: + synaptics_rmi4_enable_reg(rmi4_data, false); + +err_enable_reg: + synaptics_rmi4_get_reg(rmi4_data, false); + +err_get_reg: + kfree(rmi4_data); + + return retval; +} + +static int synaptics_rmi4_remove(struct platform_device *pdev) +{ + unsigned char attr_count; + struct synaptics_rmi4_data *rmi4_data = platform_get_drvdata(pdev); + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + +#ifdef FB_READY_RESET + cancel_work_sync(&rmi4_data->reset_work); + flush_workqueue(rmi4_data->reset_workqueue); + destroy_workqueue(rmi4_data->reset_workqueue); +#endif +printk("Enter %s\n", __func__); +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); + flush_workqueue(rmi4_data->esd_workqueue); + destroy_workqueue(rmi4_data->esd_workqueue); +#endif + + cancel_delayed_work_sync(&exp_data.work); + flush_workqueue(exp_data.workqueue); + destroy_workqueue(exp_data.workqueue); + + cancel_delayed_work_sync(&rmi4_data->rb_work); + flush_workqueue(rmi4_data->rb_workqueue); + destroy_workqueue(rmi4_data->rb_workqueue); + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + if (rmi4_data->board_prop_dir) { + sysfs_remove_file(rmi4_data->board_prop_dir, + &virtual_key_map_attr.attr); + kobject_put(rmi4_data->board_prop_dir); + } + + synaptics_rmi4_irq_enable(rmi4_data, false, false); + +#ifdef CONFIG_FB + fb_unregister_client(&rmi4_data->fb_notifier); +#endif + +#ifdef USE_EARLYSUSPEND + unregister_early_suspend(&rmi4_data->early_suspend); +#endif + + synaptics_rmi4_empty_fn_list(rmi4_data); + input_unregister_device(rmi4_data->input_dev); + rmi4_data->input_dev = NULL; + if (rmi4_data->stylus_enable) { + input_unregister_device(rmi4_data->stylus_dev); + rmi4_data->stylus_dev = NULL; + } + + synaptics_rmi4_gpio_setup(bdata->irq_gpio, false, 0, 0); + + if (bdata->reset_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->reset_gpio, false, 0, 0); + + if (bdata->power_gpio >= 0) + synaptics_rmi4_gpio_setup(bdata->power_gpio, false, 0, 0); + + synaptics_rmi4_enable_reg(rmi4_data, false); + synaptics_rmi4_get_reg(rmi4_data, false); + + kfree(rmi4_data); + + return 0; +} + +#ifdef CONFIG_FB +static int synaptics_rmi4_fb_notifier_cb(struct notifier_block *self, + unsigned long event, void *data) +{ + int *transition; + struct fb_event *evdata = data; + struct synaptics_rmi4_data *rmi4_data = + container_of(self, struct synaptics_rmi4_data, + fb_notifier); + + if (evdata && evdata->data && rmi4_data) { + if (event == FB_EVENT_BLANK) { + transition = evdata->data; + if (*transition == FB_BLANK_POWERDOWN) { + synaptics_rmi4_suspend(&rmi4_data->pdev->dev); + rmi4_data->fb_ready = false; + } else if (*transition == FB_BLANK_UNBLANK) { + synaptics_rmi4_resume(&rmi4_data->pdev->dev); + rmi4_data->fb_ready = true; + } + } + } + + return 0; +} +#endif + +#ifdef USE_EARLYSUSPEND +static void synaptics_rmi4_early_suspend(struct early_suspend *h) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = + container_of(h, struct synaptics_rmi4_data, + early_suspend); + unsigned char device_ctrl; + + if (rmi4_data->stay_awake) + return; + + + if (rmi4_data->enable_wakeup_gesture) { + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + enable_irq_wake(rmi4_data->irq); + goto exit; + } + +#ifdef SYNA_TDDI + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + udelay(TDDI_LPWG_WAIT_US); +#endif + synaptics_rmi4_irq_enable(rmi4_data, false, false); + synaptics_rmi4_sleep_enable(rmi4_data, true); + synaptics_rmi4_free_fingers(rmi4_data); + +exit: + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->early_suspend != NULL) + exp_fhandler->exp_fn->early_suspend(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = true; + + return; +} + +static void synaptics_rmi4_late_resume(struct early_suspend *h) +{ +#ifdef FB_READY_RESET + int retval; +#endif + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = + container_of(h, struct synaptics_rmi4_data, + early_suspend); + + if (rmi4_data->stay_awake) + return; + + if (rmi4_data->enable_wakeup_gesture) { + disable_irq_wake(rmi4_data->irq); + goto exit; + } + + rmi4_data->current_page = MASK_8BIT; + + if (rmi4_data->suspend) { + synaptics_rmi4_sleep_enable(rmi4_data, false); + synaptics_rmi4_irq_enable(rmi4_data, true, false); + } + +exit: +#ifdef FB_READY_RESET + if (rmi4_data->suspend) { + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } + } +#endif + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->late_resume != NULL) + exp_fhandler->exp_fn->late_resume(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = false; + + return; +} +#endif + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static int synaptics_rmi4_pm_suspend(struct device *dev){ + dev_info(rmi4_data->pdev->dev.parent, "Enter %s\n", __func__); + if (lcm_ffbm_mode){ + synaptics_rmi4_suspend(dev); + } + else{ + dev_err(rmi4_data->pdev->dev.parent, "We are not in ffbm mode\n"); + } + + return 0; +} + +static int synaptics_rmi4_pm_resume(struct device *dev){ + dev_info(rmi4_data->pdev->dev.parent, "Enter %s\n", __func__); + if (lcm_ffbm_mode){ + synaptics_rmi4_resume(dev); + } + else{ + dev_err(rmi4_data->pdev->dev.parent, "We are not in ffbm mode\n"); + } + + return 0; +} +#endif + +static int synaptics_rmi4_suspend(struct device *dev) +{ + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + unsigned char device_ctrl; + + if (rmi4_data->stay_awake) + return 0; + printk("[zmc] Enter %s\n", __func__); + +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + + if (rmi4_data->enable_wakeup_gesture) { + printk("[zmc] enable_wakeup_gesture is on\n"); + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + enable_irq_wake(rmi4_data->irq); + goto exit; + } + + if (!rmi4_data->suspend) { +#ifdef SYNA_TDDI + if (rmi4_data->no_sleep_setting) { + synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + } + synaptics_rmi4_wakeup_gesture(rmi4_data, true); + udelay(TDDI_LPWG_WAIT_US); +#endif + synaptics_rmi4_irq_enable(rmi4_data, false, false); + synaptics_rmi4_sleep_enable(rmi4_data, true); + synaptics_rmi4_free_fingers(rmi4_data); + } + +exit: + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->suspend != NULL) + exp_fhandler->exp_fn->suspend(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = true; + + return 0; +} + +static int synaptics_rmi4_resume(struct device *dev) +{ +#ifdef FB_READY_RESET + int retval; +#endif + struct synaptics_rmi4_exp_fhandler *exp_fhandler; + struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); + + printk("TP-time TP resume begin\n"); + + if (rmi4_data->stay_awake) + return 0; + + if (rmi4_data->enable_wakeup_gesture) { + disable_irq_wake(rmi4_data->irq); + synaptics_rmi4_wakeup_gesture(rmi4_data, false); + goto exit; + } + + rmi4_data->current_page = MASK_8BIT; + + synaptics_rmi4_sleep_enable(rmi4_data, false); + synaptics_rmi4_irq_enable(rmi4_data, true, false); + +#ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + + +exit: +#ifdef FB_READY_RESET + retval = synaptics_rmi4_reset_device(rmi4_data, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + } +#endif + mutex_lock(&exp_data.mutex); + if (!list_empty(&exp_data.list)) { + list_for_each_entry(exp_fhandler, &exp_data.list, link) + if (exp_fhandler->exp_fn->resume != NULL) + exp_fhandler->exp_fn->resume(rmi4_data); + } + mutex_unlock(&exp_data.mutex); + + rmi4_data->suspend = false; + + printk("TP-time TP resume finish\n"); + return 0; +} + +#if ((defined CONFIG_PM) && (defined CONFIG_ENABLE_PM_TP_SUSPEND_RESUME)) +static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = { + + .suspend = synaptics_rmi4_pm_suspend, + .resume = synaptics_rmi4_pm_resume, + +}; +#endif + +static struct platform_driver synaptics_rmi4_driver = { + .driver = { + .name = PLATFORM_DRIVER_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &synaptics_rmi4_dev_pm_ops, +#endif + }, + .probe = synaptics_rmi4_probe, + .remove = synaptics_rmi4_remove, +}; + +static int __init synaptics_rmi4_init(void) +{ + int retval; + + retval = synaptics_rmi4_bus_init_lansi(); + if (retval) + return retval; + + return platform_driver_register(&synaptics_rmi4_driver); +} + +static void __exit synaptics_rmi4_exit(void) +{ + platform_driver_unregister(&synaptics_rmi4_driver); + + synaptics_rmi4_bus_exit_lansi(); + + return; +} + +module_init(synaptics_rmi4_init); +module_exit(synaptics_rmi4_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Touch Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_core.h b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_core.h new file mode 100755 index 0000000000000..6bb0e0890ea3d --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_core.h @@ -0,0 +1,537 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#ifndef _SYNAPTICS_DSX_RMI4_H_ +#define _SYNAPTICS_DSX_RMI4_H_ + +#define SYNAPTICS_DS4 (1 << 0) +#define SYNAPTICS_DS5 (1 << 1) +#define SYNAPTICS_DSX_DRIVER_PRODUCT (SYNAPTICS_DS4 | SYNAPTICS_DS5) +#define SYNAPTICS_DSX_DRIVER_VERSION 0x2070 + +#include +#ifdef CONFIG_FB +#include +#include +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)) +#define KERNEL_ABOVE_2_6_38 +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) +#define KERNEL_ABOVE_3_6 +#endif + +#ifdef KERNEL_ABOVE_2_6_38 +#define sstrtoul(...) kstrtoul(__VA_ARGS__) +#else +#define sstrtoul(...) strict_strtoul(__VA_ARGS__) +#endif + + +#ifdef SYNAPTICS_ESD_CHECK +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +#endif + + +/* +#define F51_DISCRETE_FORCE +#ifdef F51_DISCRETE_FORCE +#define FORCE_LEVEL_ADDR 0x0419 +#define FORCE_LEVEL_MAX 255 +#define CAL_DATA_SIZE 144 +#endif +#define SYNA_TDDI +*/ +#define SYNA_TDDI +#define PDT_PROPS (0X00EF) +#define PDT_START (0x00E9) +#define PDT_END (0x00D0) +#define PDT_ENTRY_SIZE (0x0006) +#define PAGES_TO_SERVICE (10) +#define PAGE_SELECT_LEN (2) +#define ADDRESS_LEN (2) + +#define SYNAPTICS_RMI4_F01 (0x01) +#define SYNAPTICS_RMI4_F11 (0x11) +#define SYNAPTICS_RMI4_F12 (0x12) +#define SYNAPTICS_RMI4_F1A (0x1A) +#define SYNAPTICS_RMI4_F21 (0x21) +#define SYNAPTICS_RMI4_F34 (0x34) +#define SYNAPTICS_RMI4_F35 (0x35) +#define SYNAPTICS_RMI4_F38 (0x38) +#define SYNAPTICS_RMI4_F51 (0x51) +#define SYNAPTICS_RMI4_F54 (0x54) +#define SYNAPTICS_RMI4_F55 (0x55) +#define SYNAPTICS_RMI4_FDB (0xDB) + +#define PRODUCT_INFO_SIZE 2 +#define PRODUCT_ID_SIZE 10 +#define BUILD_ID_SIZE 3 + +#define F12_FINGERS_TO_SUPPORT 10 +#define F12_NO_OBJECT_STATUS 0x00 +#define F12_FINGER_STATUS 0x01 +#define F12_ACTIVE_STYLUS_STATUS 0x02 +#define F12_PALM_STATUS 0x03 +#define F12_HOVERING_FINGER_STATUS 0x05 +#define F12_GLOVED_FINGER_STATUS 0x06 +#define F12_NARROW_OBJECT_STATUS 0x07 +#define F12_HAND_EDGE_STATUS 0x08 +#define F12_COVER_STATUS 0x0A +#define F12_STYLUS_STATUS 0x0B +#define F12_ERASER_STATUS 0x0C +#define F12_SMALL_OBJECT_STATUS 0x0D + +#define F12_GESTURE_DETECTION_LEN 5 + +#define MAX_NUMBER_OF_BUTTONS 4 +#define MAX_INTR_REGISTERS 4 + +#define MASK_16BIT 0xFFFF +#define MASK_8BIT 0xFF +#define MASK_7BIT 0x7F +#define MASK_6BIT 0x3F +#define MASK_5BIT 0x1F +#define MASK_4BIT 0x0F +#define MASK_3BIT 0x07 +#define MASK_2BIT 0x03 +#define MASK_1BIT 0x01 + +enum exp_fn { + RMI_DEV = 0, + RMI_FW_UPDATER, + RMI_TEST_REPORTING, + RMI_PROXIMITY, + RMI_ACTIVE_PEN, + RMI_GESTURE, + RMI_VIDEO, + RMI_DEBUG, + RMI_LAST, +}; + +/* + * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT entry + * @query_base_addr: base address for query registers + * @cmd_base_addr: base address for command registers + * @ctrl_base_addr: base address for control registers + * @data_base_addr: base address for data registers + * @intr_src_count: number of interrupt sources + * @fn_version: version of function + * @fn_number: function number + */ +struct synaptics_rmi4_fn_desc { + union { + struct { + unsigned char query_base_addr; + unsigned char cmd_base_addr; + unsigned char ctrl_base_addr; + unsigned char data_base_addr; + unsigned char intr_src_count:3; + unsigned char reserved_1:2; + unsigned char fn_version:2; + unsigned char reserved_2:1; + unsigned char fn_number; + } __packed; + unsigned char data[6]; + }; +}; + +/* + * synaptics_rmi4_fn_full_addr - full 16-bit base addresses + * @query_base: 16-bit base address for query registers + * @cmd_base: 16-bit base address for command registers + * @ctrl_base: 16-bit base address for control registers + * @data_base: 16-bit base address for data registers + */ +struct synaptics_rmi4_fn_full_addr { + unsigned short query_base; + unsigned short cmd_base; + unsigned short ctrl_base; + unsigned short data_base; +}; + +/* + * struct synaptics_rmi4_f11_extra_data - extra data of F$11 + * @data38_offset: offset to F11_2D_DATA38 register + */ +struct synaptics_rmi4_f11_extra_data { + unsigned char data38_offset; +}; + +/* + * struct synaptics_rmi4_f12_extra_data - extra data of F$12 + * @data1_offset: offset to F12_2D_DATA01 register + * @data4_offset: offset to F12_2D_DATA04 register + * @data15_offset: offset to F12_2D_DATA15 register + * @data15_size: size of F12_2D_DATA15 register + * @data15_data: buffer for reading F12_2D_DATA15 register + * @data29_offset: offset to F12_2D_DATA29 register + * @data29_size: size of F12_2D_DATA29 register + * @data29_data: buffer for reading F12_2D_DATA29 register + * @ctrl20_offset: offset to F12_2D_CTRL20 register + */ +struct synaptics_rmi4_f12_extra_data { + unsigned char data1_offset; + unsigned char data4_offset; + unsigned char data15_offset; + unsigned char data15_size; + unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8]; + unsigned char data29_offset; + unsigned char data29_size; + unsigned char data29_data[F12_FINGERS_TO_SUPPORT * 2]; + unsigned char ctrl20_offset; +}; + +/* + * struct synaptics_rmi4_fn - RMI function handler + * @fn_number: function number + * @num_of_data_sources: number of data sources + * @num_of_data_points: maximum number of fingers supported + * @intr_reg_num: index to associated interrupt register + * @intr_mask: interrupt mask + * @full_addr: full 16-bit base addresses of function registers + * @link: linked list for function handlers + * @data_size: size of private data + * @data: pointer to private data + * @extra: pointer to extra data + */ +struct synaptics_rmi4_fn { + unsigned char fn_number; + unsigned char num_of_data_sources; + unsigned char num_of_data_points; + unsigned char intr_reg_num; + unsigned char intr_mask; + struct synaptics_rmi4_fn_full_addr full_addr; + struct list_head link; + int data_size; + void *data; + void *extra; +}; + +/* + * struct synaptics_rmi4_input_settings - current input settings + * @num_of_fingers: maximum number of fingers for 2D touch + * @valid_button_count: number of valid 0D buttons + * @max_touch_width: maximum touch width + * @sensor_max_x: maximum x coordinate for 2D touch + * @sensor_max_y: maximum y coordinate for 2D touch + * @force_min: minimum force value + * @force_max: maximum force value + * @stylus_enable: flag to indicate reporting of stylus data + * @eraser_enable: flag to indicate reporting of eraser data + */ +struct synaptics_rmi4_input_settings { + unsigned char num_of_fingers; + unsigned char valid_button_count; + unsigned char max_touch_width; + int sensor_max_x; + int sensor_max_y; + int force_min; + int force_max; + bool stylus_enable; + bool eraser_enable; +}; + +/* + * struct synaptics_rmi4_device_info - device information + * @version_major: RMI protocol major version number + * @version_minor: RMI protocol minor version number + * @manufacturer_id: manufacturer ID + * @product_props: product properties + * @product_info: product information + * @product_id_string: product ID + * @build_id: firmware build ID + * @support_fn_list: linked list for function handlers + */ +struct synaptics_rmi4_device_info { + unsigned int version_major; + unsigned int version_minor; + unsigned char manufacturer_id; + unsigned char product_props; + unsigned char product_info[PRODUCT_INFO_SIZE]; + unsigned char product_id_string[PRODUCT_ID_SIZE + 1]; + unsigned char build_id[BUILD_ID_SIZE]; + struct list_head support_fn_list; +}; + +/* + * struct synaptics_rmi4_data - RMI4 device instance data + * @pdev: pointer to platform device + * @input_dev: pointer to associated input device + * @stylus_dev: pointer to associated stylus device + * @hw_if: pointer to hardware interface data + * @rmi4_mod_info: device information + * @board_prop_dir: /sys/board_properties directory for virtual key map file + * @pwr_reg: pointer to regulator for power control + * @bus_reg: pointer to regulator for bus pullup control + * @rmi4_reset_mutex: mutex for software reset + * @rmi4_report_mutex: mutex for input event reporting + * @rmi4_io_ctrl_mutex: mutex for communication interface I/O + * @rmi4_exp_init_mutex: mutex for expansion function module initialization + * @rmi4_irq_enable_mutex: mutex for enabling/disabling interrupt + * @rb_work: work for rebuilding input device + * @rb_workqueue: workqueue for rebuilding input device + * @fb_notifier: framebuffer notifier client + * @reset_work: work for issuing reset after display framebuffer ready + * @reset_workqueue: workqueue for issuing reset after display framebuffer ready + * @early_suspend: early suspend power management + * @current_page: current RMI page for register access + * @button_0d_enabled: switch for enabling 0d button support + * @num_of_tx: number of Tx channels for 2D touch + * @num_of_rx: number of Rx channels for 2D touch + * @num_of_fingers: maximum number of fingers for 2D touch + * @max_touch_width: maximum touch width + * @valid_button_count: number of valid 0D buttons + * @report_enable: input data to report for F$12 + * @no_sleep_setting: default setting of NoSleep in F01_RMI_CTRL00 register + * @gesture_detection: detected gesture type and properties + * @intr_mask: interrupt enable mask + * @button_txrx_mapping: Tx Rx mapping of 0D buttons + * @num_of_intr_regs: number of interrupt registers + * @f01_query_base_addr: query base address for f$01 + * @f01_cmd_base_addr: command base address for f$01 + * @f01_ctrl_base_addr: control base address for f$01 + * @f01_data_base_addr: data base address for f$01 + * @f51_query_base_addr: query base address for f$51 + * @firmware_id: firmware build ID + * @irq: attention interrupt + * @sensor_max_x: maximum x coordinate for 2D touch + * @sensor_max_y: maximum y coordinate for 2D touch + * @force_min: minimum force value + * @force_max: maximum force value + * @flash_prog_mode: flag to indicate flash programming mode status + * @irq_enabled: flag to indicate attention interrupt enable status + * @fingers_on_2d: flag to indicate presence of fingers in 2D area + * @suspend: flag to indicate whether in suspend state + * @sensor_sleep: flag to indicate sleep state of sensor + * @stay_awake: flag to indicate whether to stay awake during suspend + * @fb_ready: flag to indicate whether display framebuffer in ready state + * @f11_wakeup_gesture: flag to indicate support for wakeup gestures in F$11 + * @f12_wakeup_gesture: flag to indicate support for wakeup gestures in F$12 + * @enable_wakeup_gesture: flag to indicate usage of wakeup gestures + * @wedge_sensor: flag to indicate use of wedge sensor + * @report_pressure: flag to indicate reporting of pressure data + * @stylus_enable: flag to indicate reporting of stylus data + * @eraser_enable: flag to indicate reporting of eraser data + * @external_afe_buttons: flag to indicate presence of external AFE buttons + * @reset_device: pointer to device reset function + * @irq_enable: pointer to interrupt enable function + * @sleep_enable: pointer to sleep enable function + * @report_touch: pointer to touch reporting function + */ +struct synaptics_rmi4_data { + struct platform_device *pdev; + struct input_dev *input_dev; + struct input_dev *stylus_dev; + const struct synaptics_dsx_hw_interface *hw_if; + struct synaptics_rmi4_device_info rmi4_mod_info; + struct synaptics_rmi4_input_settings input_settings; + struct kobject *board_prop_dir; + struct regulator *pwr_reg; + struct regulator *bus_reg; + struct mutex rmi4_reset_mutex; + struct mutex rmi4_report_mutex; + struct mutex rmi4_io_ctrl_mutex; + struct mutex rmi4_exp_init_mutex; + struct mutex rmi4_irq_enable_mutex; + struct mutex rmi4_esd_mutex; + struct delayed_work rb_work; + struct workqueue_struct *rb_workqueue; +#ifdef CONFIG_FB + struct notifier_block fb_notifier; + struct work_struct reset_work; + struct workqueue_struct *reset_workqueue; +#endif +#ifdef SYNAPTICS_ESD_CHECK + struct delayed_work esd_work; + struct workqueue_struct *esd_workqueue; +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif + unsigned char current_page; + unsigned char button_0d_enabled; + unsigned char num_of_tx; + unsigned char num_of_rx; + unsigned char num_of_fingers; + unsigned char max_touch_width; + unsigned char valid_button_count; + unsigned char report_enable; + unsigned char no_sleep_setting; + unsigned char gesture_detection[F12_GESTURE_DETECTION_LEN]; + unsigned char intr_mask[MAX_INTR_REGISTERS]; + unsigned char *button_txrx_mapping; + unsigned short num_of_intr_regs; + unsigned short f01_query_base_addr; + unsigned short f01_cmd_base_addr; + unsigned short f01_ctrl_base_addr; + unsigned short f01_data_base_addr; +#ifdef F51_DISCRETE_FORCE + unsigned short f51_query_base_addr; +#endif + unsigned int firmware_id; + int irq; + int sensor_max_x; + int sensor_max_y; + int force_min; + int force_max; + bool flash_prog_mode; + bool irq_enabled; + bool fingers_on_2d; + bool suspend; + bool sensor_sleep; + bool stay_awake; + bool fb_ready; + bool f11_wakeup_gesture; + bool f12_wakeup_gesture; + bool enable_wakeup_gesture; + bool wedge_sensor; + bool report_pressure; + bool stylus_enable; + bool eraser_enable; + bool external_afe_buttons; + int (*reset_device)(struct synaptics_rmi4_data *rmi4_data, + bool rebuild); + int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable, + bool attn_only); + void (*sleep_enable)(struct synaptics_rmi4_data *rmi4_data, + bool enable); + void (*report_touch)(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn *fhandler); +}; + +struct synaptics_dsx_bus_access { + unsigned char type; + int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, + unsigned char *data, unsigned int length); + int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr, + unsigned char *data, unsigned int length); +}; + +struct synaptics_dsx_hw_interface { + struct synaptics_dsx_board_data *board_data; + const struct synaptics_dsx_bus_access *bus_access; + int (*bl_hw_init)(struct synaptics_rmi4_data *rmi4_data); + int (*ui_hw_init)(struct synaptics_rmi4_data *rmi4_data); +}; + +struct synaptics_rmi4_exp_fn { + enum exp_fn fn_type; + int (*init)(struct synaptics_rmi4_data *rmi4_data); + void (*remove)(struct synaptics_rmi4_data *rmi4_data); + void (*reset)(struct synaptics_rmi4_data *rmi4_data); + void (*reinit)(struct synaptics_rmi4_data *rmi4_data); + void (*early_suspend)(struct synaptics_rmi4_data *rmi4_data); + void (*suspend)(struct synaptics_rmi4_data *rmi4_data); + void (*resume)(struct synaptics_rmi4_data *rmi4_data); + void (*late_resume)(struct synaptics_rmi4_data *rmi4_data); + void (*attn)(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask); +}; + +int synaptics_rmi4_bus_init_lansi(void); + +void synaptics_rmi4_bus_exit_lansi(void); + +void synaptics_rmi4_new_function_lansi(struct synaptics_rmi4_exp_fn *exp_fn_module, + bool insert); + +int synaptics_fw_updater_lansi(const unsigned char *fw_data); + +static inline int synaptics_rmi4_reg_read( + struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, + unsigned char *data, + unsigned int len) +{ + return rmi4_data->hw_if->bus_access->read(rmi4_data, addr, data, len); +} + +static inline int synaptics_rmi4_reg_write( + struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, + unsigned char *data, + unsigned int len) +{ + return rmi4_data->hw_if->bus_access->write(rmi4_data, addr, data, len); +} + +static inline ssize_t synaptics_rmi4_show_error(struct device *dev, + struct device_attribute *attr, char *buf) +{ + dev_warn(dev, "%s Attempted to read from write-only attribute %s\n", + __func__, attr->attr.name); + return -EPERM; +} + +static inline ssize_t synaptics_rmi4_store_error(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + dev_warn(dev, "%s Attempted to write to read-only attribute %s\n", + __func__, attr->attr.name); + return -EPERM; +} + +static inline int secure_memcpy(unsigned char *dest, unsigned int dest_size, + const unsigned char *src, unsigned int src_size, + unsigned int count) +{ + if (dest == NULL || src == NULL) + return -EINVAL; + + if (count > dest_size || count > src_size) + return -EINVAL; + + memcpy((void *)dest, (const void *)src, count); + + return 0; +} + +static inline void batohs(unsigned short *dest, unsigned char *src) +{ + *dest = src[1] * 0x100 + src[0]; +} + +static inline void hstoba(unsigned char *dest, unsigned short src) +{ + dest[0] = src % 0x100; + dest[1] = src / 0x100; +} + +#endif diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_fw_update.c new file mode 100644 index 0000000000000..f760c025daff1 --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_fw_update.c @@ -0,0 +1,6040 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "synaptics_dsx_core.h" +#include +#include + + +#define FW_IHEX_NAME "synaptics/startup_fw_update_lansi.bin" +#define FW_IMAGE_NAME "synaptics/startup_fw_update_lansi.img" + +#define DO_STARTUP_FW_UPDATE + +#define SYNAPTICS_LOCK_DOWN_INFO + +#ifdef DO_STARTUP_FW_UPDATE +#ifdef CONFIG_FB +#define WAIT_FOR_FB_READY +#define FB_READY_WAIT_MS 100 +#define FB_READY_TIMEOUT_S 30 +#endif +#endif + + +#define MAX_WRITE_SIZE 4096 + + +#define ENABLE_SYS_REFLASH true +#define FORCE_UPDATE false +#define DO_LOCKDOWN false + +#define MAX_IMAGE_NAME_LEN 256 +#define MAX_FIRMWARE_ID_LEN 10 + +#define IMAGE_HEADER_VERSION_05 0x05 +#define IMAGE_HEADER_VERSION_06 0x06 +#define IMAGE_HEADER_VERSION_10 0x10 + +#define IMAGE_AREA_OFFSET 0x100 +#define LOCKDOWN_SIZE 0x50 + +#define MAX_UTILITY_PARAMS 20 + +#define V5V6_BOOTLOADER_ID_OFFSET 0 +#define V5V6_CONFIG_ID_SIZE 4 + +#define V5_PROPERTIES_OFFSET 2 +#define V5_BLOCK_SIZE_OFFSET 3 +#define V5_BLOCK_COUNT_OFFSET 5 +#define V5_BLOCK_NUMBER_OFFSET 0 +#define V5_BLOCK_DATA_OFFSET 2 + +#define V6_PROPERTIES_OFFSET 1 +#define V6_BLOCK_SIZE_OFFSET 2 +#define V6_BLOCK_COUNT_OFFSET 3 +#define V6_PROPERTIES_2_OFFSET 4 +#define V6_GUEST_CODE_BLOCK_COUNT_OFFSET 5 +#define V6_BLOCK_NUMBER_OFFSET 0 +#define V6_BLOCK_DATA_OFFSET 1 +#define V6_FLASH_COMMAND_OFFSET 2 +#define V6_FLASH_STATUS_OFFSET 3 + +#define V7_CONFIG_ID_SIZE 32 + +#define V7_FLASH_STATUS_OFFSET 0 +#define V7_PARTITION_ID_OFFSET 1 +#define V7_BLOCK_NUMBER_OFFSET 2 +#define V7_TRANSFER_LENGTH_OFFSET 3 +#define V7_COMMAND_OFFSET 4 +#define V7_PAYLOAD_OFFSET 5 + +#define V7_PARTITION_SUPPORT_BYTES 4 + +#define F35_ERROR_CODE_OFFSET 0 +#define F35_FLASH_STATUS_OFFSET 5 +#define F35_CHUNK_NUM_LSB_OFFSET 0 +#define F35_CHUNK_NUM_MSB_OFFSET 1 +#define F35_CHUNK_DATA_OFFSET 2 +#define F35_CHUNK_COMMAND_OFFSET 18 + +#define F35_CHUNK_SIZE 16 +#define F35_ERASE_ALL_WAIT_MS 5000 +#define F35_RESET_WAIT_MS 250 + +#define SLEEP_MODE_NORMAL (0x00) +#define SLEEP_MODE_SENSOR_SLEEP (0x01) +#define SLEEP_MODE_RESERVED0 (0x02) +#define SLEEP_MODE_RESERVED1 (0x03) + +#define ENABLE_WAIT_MS (1 * 1000) +#define WRITE_WAIT_MS (3 * 1000) +#define ERASE_WAIT_MS (5 * 1000) + +#define MIN_SLEEP_TIME_US 50 +#define MAX_SLEEP_TIME_US 100 + +#define INT_DISABLE_WAIT_MS 20 +#define ENTER_FLASH_PROG_WAIT_MS 20 +#define READ_CONFIG_WAIT_MS 20 + +static int fwu_do_reflash(void); + +static int fwu_recovery_check_status(void); + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t fwu_sysfs_read_panel_color_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf); + +#endif + +enum f34_version { + F34_V0 = 0, + F34_V1, + F34_V2, +}; + +enum bl_version { + BL_V5 = 5, + BL_V6 = 6, + BL_V7 = 7, + BL_V8 = 8, +}; + +enum flash_area { + NONE = 0, + UI_FIRMWARE, + UI_CONFIG, +}; + +enum update_mode { + NORMAL = 1, + FORCE = 2, + LOCKDOWN = 8, +}; + +enum config_area { + UI_CONFIG_AREA = 0, + PM_CONFIG_AREA, + BL_CONFIG_AREA, + DP_CONFIG_AREA, + FLASH_CONFIG_AREA, +#ifdef SYNA_TDDI + TDDI_FORCE_CONFIG_AREA, + TDDI_LCM_DATA_AREA, + TDDI_OEM_DATA_AREA, +#endif + UPP_AREA, +}; + +enum v7_status { + SUCCESS = 0x00, + DEVICE_NOT_IN_BOOTLOADER_MODE, + INVALID_PARTITION, + INVALID_COMMAND, + INVALID_BLOCK_OFFSET, + INVALID_TRANSFER, + NOT_ERASED, + FLASH_PROGRAMMING_KEY_INCORRECT, + BAD_PARTITION_TABLE, + CHECKSUM_FAILED, + FLASH_HARDWARE_FAILURE = 0x1f, +}; + +enum v7_partition_id { + BOOTLOADER_PARTITION = 0x01, + DEVICE_CONFIG_PARTITION, + FLASH_CONFIG_PARTITION, + MANUFACTURING_BLOCK_PARTITION, + GUEST_SERIALIZATION_PARTITION, + GLOBAL_PARAMETERS_PARTITION, + CORE_CODE_PARTITION, + CORE_CONFIG_PARTITION, + GUEST_CODE_PARTITION, + DISPLAY_CONFIG_PARTITION, + EXTERNAL_TOUCH_AFE_CONFIG_PARTITION, + UTILITY_PARAMETER_PARTITION, +}; + +enum v7_flash_command { + CMD_V7_IDLE = 0x00, + CMD_V7_ENTER_BL, + CMD_V7_READ, + CMD_V7_WRITE, + CMD_V7_ERASE, + CMD_V7_ERASE_AP, + CMD_V7_SENSOR_ID, +}; + +enum v5v6_flash_command { + CMD_V5V6_IDLE = 0x0, + CMD_V5V6_WRITE_FW = 0x2, + CMD_V5V6_ERASE_ALL = 0x3, + CMD_V5V6_WRITE_LOCKDOWN = 0x4, + CMD_V5V6_READ_CONFIG = 0x5, + CMD_V5V6_WRITE_CONFIG = 0x6, + CMD_V5V6_ERASE_UI_CONFIG = 0x7, + CMD_V5V6_ERASE_BL_CONFIG = 0x9, + CMD_V5V6_ERASE_DISP_CONFIG = 0xa, + CMD_V5V6_ERASE_GUEST_CODE = 0xb, + CMD_V5V6_WRITE_GUEST_CODE = 0xc, + CMD_V5V6_ERASE_CHIP = 0x0d, + CMD_V5V6_ENABLE_FLASH_PROG = 0xf, +#ifdef SYNA_TDDI + CMD_V5V6_ERASE_FORCE_CONFIG = 0x11, + CMD_V5V6_READ_FORCE_CONFIG = 0x12, + CMD_V5V6_WRITE_FORCE_CONFIG = 0x13, + CMD_V5V6_ERASE_LOCKDOWN_DATA = 0x1a, + CMD_V5V6_READ_LOCKDOWN_DATA = 0x1b, + CMD_V5V6_WRITE_LOCKDOWN_DATA = 0x1c, + CMD_V5V6_ERASE_LCM_DATA = 0x1d, + CMD_V5V6_ERASE_OEM_DATA = 0x1e, +#endif +}; + +enum flash_command { + CMD_IDLE = 0, + CMD_WRITE_FW, + CMD_WRITE_CONFIG, + CMD_WRITE_LOCKDOWN, + CMD_WRITE_GUEST_CODE, + CMD_WRITE_BOOTLOADER, + CMD_WRITE_UTILITY_PARAM, + CMD_READ_CONFIG, + CMD_ERASE_ALL, + CMD_ERASE_UI_FIRMWARE, + CMD_ERASE_UI_CONFIG, + CMD_ERASE_BL_CONFIG, + CMD_ERASE_DISP_CONFIG, + CMD_ERASE_FLASH_CONFIG, + CMD_ERASE_GUEST_CODE, + CMD_ERASE_BOOTLOADER, + CMD_ERASE_UTILITY_PARAMETER, + CMD_ENABLE_FLASH_PROG, +#ifdef SYNA_TDDI + CMD_ERASE_CHIP, + CMD_ERASE_FORCE_CONFIG, + CMD_READ_FORCE_CONFIG, + CMD_WRITE_FORCE_CONFIG, + CMD_ERASE_LOCKDOWN_DATA, + CMD_READ_LOCKDOWN_DATA, + CMD_WRITE_LOCKDOWN_DATA, + CMD_ERASE_LCM_DATA, + CMD_READ_LCM_DATA, + CMD_WRITE_LCM_DATA, + CMD_ERASE_OEM_DATA, + CMD_READ_OEM_DATA, + CMD_WRITE_OEM_DATA, +#endif +}; + +enum f35_flash_command { + CMD_F35_IDLE = 0x0, + CMD_F35_RESERVED = 0x1, + CMD_F35_WRITE_CHUNK = 0x2, + CMD_F35_ERASE_ALL = 0x3, + CMD_F35_RESET = 0x10, +}; + +enum container_id { + TOP_LEVEL_CONTAINER = 0, + UI_CONTAINER, + UI_CONFIG_CONTAINER, + BL_CONTAINER, + BL_IMAGE_CONTAINER, + BL_CONFIG_CONTAINER, + BL_LOCKDOWN_INFO_CONTAINER, + PERMANENT_CONFIG_CONTAINER, + GUEST_CODE_CONTAINER, + BL_PROTOCOL_DESCRIPTOR_CONTAINER, + UI_PROTOCOL_DESCRIPTOR_CONTAINER, + RMI_SELF_DISCOVERY_CONTAINER, + RMI_PAGE_CONTENT_CONTAINER, + GENERAL_INFORMATION_CONTAINER, + DEVICE_CONFIG_CONTAINER, + FLASH_CONFIG_CONTAINER, + GUEST_SERIALIZATION_CONTAINER, + GLOBAL_PARAMETERS_CONTAINER, + CORE_CODE_CONTAINER, + CORE_CONFIG_CONTAINER, + DISPLAY_CONFIG_CONTAINER, + EXTERNAL_TOUCH_AFE_CONFIG_CONTAINER, + UTILITY_CONTAINER, + UTILITY_PARAMETER_CONTAINER, +}; + +enum utility_parameter_id { + UNUSED = 0, + FORCE_PARAMETER, + ANTI_BENDING_PARAMETER, +}; + +struct pdt_properties { + union { + struct { + unsigned char reserved_1:6; + unsigned char has_bsr:1; + unsigned char reserved_2:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct partition_table { + unsigned char partition_id:5; + unsigned char byte_0_reserved:3; + unsigned char byte_1_reserved; + unsigned char partition_length_7_0; + unsigned char partition_length_15_8; + unsigned char start_physical_address_7_0; + unsigned char start_physical_address_15_8; + unsigned char partition_properties_7_0; + unsigned char partition_properties_15_8; +} __packed; + +struct f01_device_control { + union { + struct { + unsigned char sleep_mode:2; + unsigned char nosleep:1; + unsigned char reserved:2; + unsigned char charger_connected:1; + unsigned char report_rate:1; + unsigned char configured:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_0 { + union { + struct { + unsigned char subpacket_1_size:3; + unsigned char has_config_id:1; + unsigned char f34_query0_b4:1; + unsigned char has_thqa:1; + unsigned char f34_query0_b6__7:2; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_query_1_7 { + union { + struct { + /* query 1 */ + unsigned char bl_minor_revision; + unsigned char bl_major_revision; + + /* query 2 */ + unsigned char bl_fw_id_7_0; + unsigned char bl_fw_id_15_8; + unsigned char bl_fw_id_23_16; + unsigned char bl_fw_id_31_24; + + /* query 3 */ + unsigned char minimum_write_size; + unsigned char block_size_7_0; + unsigned char block_size_15_8; + unsigned char flash_page_size_7_0; + unsigned char flash_page_size_15_8; + + /* query 4 */ + unsigned char adjustable_partition_area_size_7_0; + unsigned char adjustable_partition_area_size_15_8; + + /* query 5 */ + unsigned char flash_config_length_7_0; + unsigned char flash_config_length_15_8; + + /* query 6 */ + unsigned char payload_length_7_0; + unsigned char payload_length_15_8; + + /* query 7 */ + unsigned char f34_query7_b0:1; + unsigned char has_bootloader:1; + unsigned char has_device_config:1; + unsigned char has_flash_config:1; + unsigned char has_manufacturing_block:1; + unsigned char has_guest_serialization:1; + unsigned char has_global_parameters:1; + unsigned char has_core_code:1; + unsigned char has_core_config:1; + unsigned char has_guest_code:1; + unsigned char has_display_config:1; + unsigned char f34_query7_b11__15:5; + unsigned char f34_query7_b16__23; + unsigned char f34_query7_b24__31; + } __packed; + unsigned char data[21]; + }; +}; + +struct f34_v7_data0 { + union { + struct { + unsigned char operation_status:5; + unsigned char device_cfg_status:2; + unsigned char bl_mode:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v7_data_1_5 { + union { + struct { + unsigned char partition_id:5; + unsigned char f34_data1_b5__7:3; + unsigned char block_offset_7_0; + unsigned char block_offset_15_8; + unsigned char transfer_length_7_0; + unsigned char transfer_length_15_8; + unsigned char command; + unsigned char payload_0; + unsigned char payload_1; + } __packed; + unsigned char data[8]; + }; +}; + +struct f34_v5v6_flash_properties { + union { + struct { + unsigned char reg_map:1; + unsigned char unlocked:1; + unsigned char has_config_id:1; + unsigned char has_pm_config:1; + unsigned char has_bl_config:1; + unsigned char has_disp_config:1; + unsigned char has_ctrl1:1; + unsigned char has_query4:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f34_v5v6_flash_properties_2 { + union { + struct { + unsigned char has_guest_code:1; + unsigned char f34_query4_b1:1; + unsigned char has_gesture_config:1; + unsigned char has_force_config:1; + unsigned char has_lockdown_data:1; + unsigned char has_lcm_data:1; + unsigned char has_oem_data:1; + unsigned char f34_query4_b7:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct register_offset { + unsigned char properties; + unsigned char properties_2; + unsigned char block_size; + unsigned char block_count; + unsigned char gc_block_count; + unsigned char flash_status; + unsigned char partition_id; + unsigned char block_number; + unsigned char transfer_length; + unsigned char flash_cmd; + unsigned char payload; +}; + +struct block_count { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +#ifdef SYNA_TDDI + unsigned short tddi_force_config; + unsigned short tddi_lockdown_data; + unsigned short tddi_lcm_data; + unsigned short tddi_oem_data; +#endif + unsigned short total_count; +}; + +struct physical_address { + unsigned short ui_firmware; + unsigned short ui_config; + unsigned short dp_config; + unsigned short pm_config; + unsigned short fl_config; + unsigned short bl_image; + unsigned short bl_config; + unsigned short utility_param; + unsigned short lockdown; + unsigned short guest_code; +}; + +struct container_descriptor { + unsigned char content_checksum[4]; + unsigned char container_id[2]; + unsigned char minor_version; + unsigned char major_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char container_option_flags[4]; + unsigned char content_options_length[4]; + unsigned char content_options_address[4]; + unsigned char content_length[4]; + unsigned char content_address[4]; +}; + +struct image_header_10 { + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char minor_header_version; + unsigned char major_header_version; + unsigned char reserved_08; + unsigned char reserved_09; + unsigned char reserved_0a; + unsigned char reserved_0b; + unsigned char top_level_container_start_addr[4]; +}; + +struct image_header_05_06 { + /* 0x00 - 0x0f */ + unsigned char checksum[4]; + unsigned char reserved_04; + unsigned char reserved_05; + unsigned char options_firmware_id:1; + unsigned char options_bootloader:1; + unsigned char options_guest_code:1; + unsigned char options_tddi:1; + unsigned char options_reserved:4; + unsigned char header_version; + unsigned char firmware_size[4]; + unsigned char config_size[4]; + /* 0x10 - 0x1f */ + unsigned char product_id[PRODUCT_ID_SIZE]; + unsigned char package_id[2]; + unsigned char package_id_revision[2]; + unsigned char product_info[PRODUCT_INFO_SIZE]; + /* 0x20 - 0x2f */ + unsigned char bootloader_addr[4]; + unsigned char bootloader_size[4]; + unsigned char ui_addr[4]; + unsigned char ui_size[4]; + /* 0x30 - 0x3f */ + unsigned char ds_id[16]; + /* 0x40 - 0x4f */ + union { + struct { + unsigned char cstmr_product_id[PRODUCT_ID_SIZE]; + unsigned char reserved_4a_4f[6]; + }; + struct { + unsigned char dsp_cfg_addr[4]; + unsigned char dsp_cfg_size[4]; + unsigned char reserved_48_4f[8]; + }; + }; + /* 0x50 - 0x53 */ + unsigned char firmware_id[4]; +}; + +struct block_data { + unsigned int size; + const unsigned char *data; +}; + +struct image_metadata { + bool contains_firmware_id; + bool contains_bootloader; + bool contains_guest_code; + bool contains_disp_config; + bool contains_perm_config; + bool contains_flash_config; + bool contains_utility_param; + unsigned int firmware_id; + unsigned int checksum; + unsigned int bootloader_size; + unsigned int disp_config_offset; + unsigned char bl_version; + unsigned char product_id[PRODUCT_ID_SIZE + 1]; + unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1]; + unsigned char utility_param_id[MAX_UTILITY_PARAMS]; + struct block_data bootloader; + struct block_data utility; + struct block_data ui_firmware; + struct block_data ui_config; + struct block_data dp_config; + struct block_data pm_config; + struct block_data fl_config; + struct block_data bl_image; + struct block_data bl_config; + struct block_data utility_param[MAX_UTILITY_PARAMS]; + struct block_data lockdown; + struct block_data guest_code; + struct block_count blkcount; + struct physical_address phyaddr; +}; + +struct synaptics_rmi4_fwu_handle { + enum bl_version bl_version; + bool initialized; + bool in_bl_mode; + bool in_ub_mode; + bool bl_mode_device; + bool force_update; + bool do_lockdown; + bool has_guest_code; +#ifdef SYNA_TDDI + bool has_force_config; + bool has_lockdown_data; + bool has_lcm_data; + bool has_oem_data; +#endif + bool has_utility_param; + bool new_partition_table; + bool incompatible_partition_tables; + bool write_bootloader; + unsigned int data_pos; + unsigned char *ext_data_source; + unsigned char *read_config_buf; + unsigned char intr_mask; + unsigned char command; + unsigned char bootloader_id[2]; + unsigned char config_id[32]; + unsigned char flash_status; + unsigned char partitions; +#ifdef F51_DISCRETE_FORCE + unsigned char *cal_data; + unsigned short cal_data_off; + unsigned short cal_data_size; + unsigned short cal_data_buf_size; + unsigned short cal_packet_data_size; +#endif + unsigned short block_size; + unsigned short config_size; + unsigned short config_area; + unsigned short config_block_count; + unsigned short flash_config_length; + unsigned short payload_length; + unsigned short partition_table_bytes; + unsigned short read_config_buf_size; + const unsigned char *config_data; + const unsigned char *image; + unsigned char *image_name; + unsigned int image_size; + struct image_metadata img; + struct register_offset off; + struct block_count blkcount; + struct physical_address phyaddr; + struct f34_v5v6_flash_properties flash_properties; + struct synaptics_rmi4_fn_desc f34_fd; + struct synaptics_rmi4_fn_desc f35_fd; + struct synaptics_rmi4_data *rmi4_data; + struct workqueue_struct *fwu_workqueue; + struct work_struct fwu_work; +}; + +static struct bin_attribute dev_attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = fwu_sysfs_show_image, + .write = fwu_sysfs_store_image, +}; + +static struct device_attribute attrs[] = { + __ATTR(dorecovery, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_recovery_store), + __ATTR(doreflash, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_do_reflash_store), + __ATTR(writeconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_config_store), + __ATTR(readconfig, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_read_config_store), + __ATTR(configarea, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_config_area_store), + __ATTR(imagename, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_name_store), + __ATTR(imagesize, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_image_size_store), + __ATTR(blocksize, S_IRUGO, + fwu_sysfs_block_size_show, + synaptics_rmi4_store_error), + __ATTR(fwblockcount, S_IRUGO, + fwu_sysfs_firmware_block_count_show, + synaptics_rmi4_store_error), + __ATTR(configblockcount, S_IRUGO, + fwu_sysfs_configuration_block_count_show, + synaptics_rmi4_store_error), + __ATTR(dispconfigblockcount, S_IRUGO, + fwu_sysfs_disp_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(permconfigblockcount, S_IRUGO, + fwu_sysfs_perm_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(blconfigblockcount, S_IRUGO, + fwu_sysfs_bl_config_block_count_show, + synaptics_rmi4_store_error), + __ATTR(uppblockcount, S_IRUGO, + fwu_sysfs_utility_parameter_block_count_show, + synaptics_rmi4_store_error), + __ATTR(guestcodeblockcount, S_IRUGO, + fwu_sysfs_guest_code_block_count_show, + synaptics_rmi4_store_error), + __ATTR(writeguestcode, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + fwu_sysfs_write_guest_code_store), + __ATTR(guestserialization, S_IRUGO, + fwu_sysfs_read_guest_serialization_show, + synaptics_rmi4_store_error), + __ATTR(panelcolor, S_IRUGO, + fwu_sysfs_read_panel_color_show, + NULL), + +#ifdef SYNA_TDDI + __ATTR(lockdowncode, (S_IWUSR | S_IWGRP | S_IRUGO), + fwu_sysfs_read_lockdown_code_show, + fwu_sysfs_write_lockdown_code_store), +#endif +}; + +static struct synaptics_rmi4_fwu_handle *fwu; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) +#define CTP_PROC_LOCKDOWN_FILE "tp_lockdown_info" +DEFINE_MUTEX(fwu_sysfs_mutex_lansi); +static struct proc_dir_entry *ctp_lockdown_status_proc; +static char tp_lockdown_info[128]; + +static int fwu_do_read_customer_serialization_data(void); + +static int ctp_lockdown_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + fwu_do_read_customer_serialization_data(); + + sprintf(temp, "%s\n", tp_lockdown_info); + seq_printf(file, "%s\n", temp); + + return 0; + + +} + +static int ctp_lockdown_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, ctp_lockdown_proc_show, inode->i_private); +} + +static const struct file_operations ctp_lockdown_proc_fops = +{ + .open = ctp_lockdown_proc_open, + .read = seq_read, +}; +#endif +DECLARE_COMPLETION(fwu_remove_complete_lansi); + + + +static void calculate_checksum(unsigned short *data, unsigned long len, + unsigned long *result) +{ + unsigned long temp; + unsigned long sum1 = 0xffff; + unsigned long sum2 = 0xffff; + + *result = 0xffffffff; + + while (len--) { + temp = *data; + sum1 += temp; + sum2 += sum1; + sum1 = (sum1 & 0xffff) + (sum1 >> 16); + sum2 = (sum2 & 0xffff) + (sum2 >> 16); + data++; + } + + *result = sum2 << 16 | sum1; + + return; +} + +static void convert_to_little_endian(unsigned char *dest, unsigned long src) +{ + dest[0] = (unsigned char)(src & 0xff); + dest[1] = (unsigned char)((src >> 8) & 0xff); + dest[2] = (unsigned char)((src >> 16) & 0xff); + dest[3] = (unsigned char)((src >> 24) & 0xff); + + return; +} + +static unsigned int le_to_uint(const unsigned char *ptr) +{ + return (unsigned int)ptr[0] + + (unsigned int)ptr[1] * 0x100 + + (unsigned int)ptr[2] * 0x10000 + + (unsigned int)ptr[3] * 0x1000000; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_f51_force_data_init(void) +{ + int retval; + unsigned char query_count; + unsigned char packet_info; + unsigned char offset[2]; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 7, + offset, + sizeof(offset)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read force data offset\n", + __func__); + return retval; + } + + fwu->cal_data_off = offset[0] | offset[1] << 8; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr, + &query_count, + sizeof(query_count)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read number of F51 query registers\n", + __func__); + return retval; + } + + if (query_count >= 10) { + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f51_query_base_addr + 9, + &packet_info, + sizeof(packet_info)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F51 packet register info\n", + __func__); + return retval; + } + + if (packet_info & MASK_1BIT) { + fwu->cal_packet_data_size = packet_info >> 1; + fwu->cal_packet_data_size *= 2; + } else { + fwu->cal_packet_data_size = 0; + } + } else { + fwu->cal_packet_data_size = 0; + } + + fwu->cal_data_size = CAL_DATA_SIZE + fwu->cal_packet_data_size; + if (fwu->cal_data_size > fwu->cal_data_buf_size) { + kfree(fwu->cal_data); + fwu->cal_data_buf_size = fwu->cal_data_size; + fwu->cal_data = kmalloc(fwu->cal_data_buf_size, GFP_KERNEL); + if (!fwu->cal_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->cal_data\n", + __func__); + fwu->cal_data_buf_size = 0; + return -ENOMEM; + } + } + + return 0; +} +#endif + +static int fwu_allocate_read_config_buf(unsigned int count) +{ + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (count > fwu->read_config_buf_size) { + kfree(fwu->read_config_buf); + fwu->read_config_buf = kzalloc(count, GFP_KERNEL); + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + return -ENOMEM; + } + fwu->read_config_buf_size = count; + } + + return 0; +} + +static void fwu_compare_partition_tables(void) +{ + fwu->incompatible_partition_tables = false; + + if (fwu->phyaddr.bl_image != fwu->img.phyaddr.bl_image) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.lockdown != fwu->img.phyaddr.lockdown) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.bl_config != fwu->img.phyaddr.bl_config) + fwu->incompatible_partition_tables = true; + else if (fwu->phyaddr.utility_param != fwu->img.phyaddr.utility_param) + fwu->incompatible_partition_tables = true; + + if (fwu->bl_version == BL_V7) { + if (fwu->phyaddr.fl_config != fwu->img.phyaddr.fl_config) + fwu->incompatible_partition_tables = true; + } + + fwu->new_partition_table = false; + + if (fwu->phyaddr.ui_firmware != fwu->img.phyaddr.ui_firmware) + fwu->new_partition_table = true; + else if (fwu->phyaddr.ui_config != fwu->img.phyaddr.ui_config) + fwu->new_partition_table = true; + + if (fwu->flash_properties.has_disp_config) { + if (fwu->phyaddr.dp_config != fwu->img.phyaddr.dp_config) + fwu->new_partition_table = true; + } + + if (fwu->has_guest_code) { + if (fwu->phyaddr.guest_code != fwu->img.phyaddr.guest_code) + fwu->new_partition_table = true; + } + + return; +} + +static void fwu_parse_partition_table(const unsigned char *partition_table, + struct block_count *blkcount, struct physical_address *phyaddr) +{ + unsigned char ii; + unsigned char index; + unsigned char offset; + unsigned short partition_length; + unsigned short physical_address; + struct partition_table *ptable; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + for (ii = 0; ii < fwu->partitions; ii++) { + index = ii * 8 + 2; + ptable = (struct partition_table *)&partition_table[index]; + partition_length = ptable->partition_length_15_8 << 8 | + ptable->partition_length_7_0; + physical_address = ptable->start_physical_address_15_8 << 8 | + ptable->start_physical_address_7_0; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Partition entry %d:\n", + __func__, ii); + for (offset = 0; offset < 8; offset++) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: 0x%02x\n", + __func__, + partition_table[index + offset]); + } + switch (ptable->partition_id) { + case CORE_CODE_PARTITION: + blkcount->ui_firmware = partition_length; + phyaddr->ui_firmware = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core code block count: %d\n", + __func__, blkcount->ui_firmware); + blkcount->total_count += partition_length; + break; + case CORE_CONFIG_PARTITION: + blkcount->ui_config = partition_length; + phyaddr->ui_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Core config block count: %d\n", + __func__, blkcount->ui_config); + blkcount->total_count += partition_length; + break; + case BOOTLOADER_PARTITION: + blkcount->bl_image = partition_length; + phyaddr->bl_image = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Bootloader block count: %d\n", + __func__, blkcount->bl_image); + blkcount->total_count += partition_length; + break; + case UTILITY_PARAMETER_PARTITION: + blkcount->utility_param = partition_length; + phyaddr->utility_param = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Utility parameter block count: %d\n", + __func__, blkcount->utility_param); + blkcount->total_count += partition_length; + break; + case DISPLAY_CONFIG_PARTITION: + blkcount->dp_config = partition_length; + phyaddr->dp_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Display config block count: %d\n", + __func__, blkcount->dp_config); + blkcount->total_count += partition_length; + break; + case FLASH_CONFIG_PARTITION: + blkcount->fl_config = partition_length; + phyaddr->fl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Flash config block count: %d\n", + __func__, blkcount->fl_config); + blkcount->total_count += partition_length; + break; + case GUEST_CODE_PARTITION: + blkcount->guest_code = partition_length; + phyaddr->guest_code = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest code block count: %d\n", + __func__, blkcount->guest_code); + blkcount->total_count += partition_length; + break; + case GUEST_SERIALIZATION_PARTITION: + blkcount->pm_config = partition_length; + phyaddr->pm_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Guest serialization block count: %d\n", + __func__, blkcount->pm_config); + blkcount->total_count += partition_length; + break; + case GLOBAL_PARAMETERS_PARTITION: + blkcount->bl_config = partition_length; + phyaddr->bl_config = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Global parameters block count: %d\n", + __func__, blkcount->bl_config); + blkcount->total_count += partition_length; + break; + case DEVICE_CONFIG_PARTITION: + blkcount->lockdown = partition_length; + phyaddr->lockdown = physical_address; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Device config block count: %d\n", + __func__, blkcount->lockdown); + blkcount->total_count += partition_length; + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_utility(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = fwu->img.utility.size / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + if (ii >= MAX_UTILITY_PARAMS) + continue; + addr = le_to_uint(fwu->img.utility.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UTILITY_PARAMETER_CONTAINER: + fwu->img.utility_param[ii].data = content; + fwu->img.utility_param[ii].size = length; + fwu->img.utility_param_id[ii] = content[0]; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10_bootloader(const unsigned char *image) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + + num_of_containers = (fwu->img.bootloader.size - 4) / 4; + + for (ii = 1; ii <= num_of_containers; ii++) { + addr = le_to_uint(fwu->img.bootloader.data + (ii * 4)); + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case BL_IMAGE_CONTAINER: + fwu->img.bl_image.data = content; + fwu->img.bl_image.size = length; + break; + case BL_CONFIG_CONTAINER: + case GLOBAL_PARAMETERS_CONTAINER: + fwu->img.bl_config.data = content; + fwu->img.bl_config.size = length; + break; + case BL_LOCKDOWN_INFO_CONTAINER: + case DEVICE_CONFIG_CONTAINER: + fwu->img.lockdown.data = content; + fwu->img.lockdown.size = length; + break; + default: + break; + }; + } + + return; +} + +static void fwu_parse_image_header_10(void) +{ + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int offset; + unsigned int container_id; + unsigned int length; + const unsigned char *image; + const unsigned char *content; + struct container_descriptor *descriptor; + struct image_header_10 *header; + + image = fwu->image; + header = (struct image_header_10 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + /* address of top level container */ + offset = le_to_uint(header->top_level_container_start_addr); + descriptor = (struct container_descriptor *)(image + offset); + + /* address of top level container content */ + offset = le_to_uint(descriptor->content_address); + num_of_containers = le_to_uint(descriptor->content_length) / 4; + + for (ii = 0; ii < num_of_containers; ii++) { + addr = le_to_uint(image + offset); + offset += 4; + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; + content = image + le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); + switch (container_id) { + case UI_CONTAINER: + case CORE_CODE_CONTAINER: + fwu->img.ui_firmware.data = content; + fwu->img.ui_firmware.size = length; + break; + case UI_CONFIG_CONTAINER: + case CORE_CONFIG_CONTAINER: + fwu->img.ui_config.data = content; + fwu->img.ui_config.size = length; + break; + case BL_CONTAINER: + fwu->img.bl_version = *content; + fwu->img.bootloader.data = content; + fwu->img.bootloader.size = length; + fwu_parse_image_header_10_bootloader(image); + break; + case UTILITY_CONTAINER: + fwu->img.utility.data = content; + fwu->img.utility.size = length; + fwu_parse_image_header_10_utility(image); + break; + case GUEST_CODE_CONTAINER: + fwu->img.contains_guest_code = true; + fwu->img.guest_code.data = content; + fwu->img.guest_code.size = length; + break; + case DISPLAY_CONFIG_CONTAINER: + fwu->img.contains_disp_config = true; + fwu->img.dp_config.data = content; + fwu->img.dp_config.size = length; + break; + case PERMANENT_CONFIG_CONTAINER: + case GUEST_SERIALIZATION_CONTAINER: + fwu->img.contains_perm_config = true; + fwu->img.pm_config.data = content; + fwu->img.pm_config.size = length; + break; + case FLASH_CONFIG_CONTAINER: + fwu->img.contains_flash_config = true; + fwu->img.fl_config.data = content; + fwu->img.fl_config.size = length; + break; + case GENERAL_INFORMATION_CONTAINER: + fwu->img.contains_firmware_id = true; + fwu->img.firmware_id = le_to_uint(content + 4); + break; + default: + break; + } + } + + return; +} + +static void fwu_parse_image_header_05_06(void) +{ + int retval; + const unsigned char *image; + struct image_header_05_06 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + image = fwu->image; + header = (struct image_header_05_06 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); + + fwu->img.bl_version = header->header_version; + + fwu->img.contains_bootloader = header->options_bootloader; + if (fwu->img.contains_bootloader) + fwu->img.bootloader_size = le_to_uint(header->bootloader_size); + + fwu->img.ui_firmware.size = le_to_uint(header->firmware_size); + if (fwu->img.ui_firmware.size) { + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + if (fwu->img.contains_bootloader) + fwu->img.ui_firmware.data += fwu->img.bootloader_size; + } + + if ((fwu->img.bl_version == BL_V6) && header->options_tddi) + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; + + fwu->img.ui_config.size = le_to_uint(header->config_size); + if (fwu->img.ui_config.size) { + fwu->img.ui_config.data = fwu->img.ui_firmware.data + + fwu->img.ui_firmware.size; + } + + if (fwu->img.contains_bootloader || header->options_tddi) + fwu->img.contains_disp_config = true; + else + fwu->img.contains_disp_config = false; + + if (fwu->img.contains_disp_config) { + fwu->img.disp_config_offset = le_to_uint(header->dsp_cfg_addr); + fwu->img.dp_config.size = le_to_uint(header->dsp_cfg_size); + fwu->img.dp_config.data = image + fwu->img.disp_config_offset; + } else { + retval = secure_memcpy(fwu->img.cstmr_product_id, + sizeof(fwu->img.cstmr_product_id), + header->cstmr_product_id, + sizeof(header->cstmr_product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy custom product ID string\n", + __func__); + } + fwu->img.cstmr_product_id[PRODUCT_ID_SIZE] = 0; + } + + fwu->img.contains_firmware_id = header->options_firmware_id; + if (fwu->img.contains_firmware_id) + fwu->img.firmware_id = le_to_uint(header->firmware_id); + + retval = secure_memcpy(fwu->img.product_id, + sizeof(fwu->img.product_id), + header->product_id, + sizeof(header->product_id), + PRODUCT_ID_SIZE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy product ID string\n", + __func__); + } + fwu->img.product_id[PRODUCT_ID_SIZE] = 0; + + fwu->img.lockdown.size = LOCKDOWN_SIZE; + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE; + + return; +} + +static int fwu_parse_image_info(void) +{ + struct image_header_10 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + header = (struct image_header_10 *)fwu->image; + + memset(&fwu->img, 0x00, sizeof(fwu->img)); + + switch (header->major_header_version) { + case IMAGE_HEADER_VERSION_10: + fwu_parse_image_header_10(); + break; + case IMAGE_HEADER_VERSION_05: + case IMAGE_HEADER_VERSION_06: + fwu_parse_image_header_05_06(); + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unsupported image file format (0x%02x)\n", + __func__, header->major_header_version); + return -EINVAL; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (!fwu->img.contains_flash_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No flash config found in firmware image\n", + __func__); + return -EINVAL; + } + + fwu_parse_partition_table(fwu->img.fl_config.data, + &fwu->img.blkcount, &fwu->img.phyaddr); + + if (fwu->img.blkcount.utility_param) + fwu->img.contains_utility_param = true; + + fwu_compare_partition_tables(); + } else { + fwu->new_partition_table = false; + fwu->incompatible_partition_tables = false; + } + + return 0; +} + +static int fwu_read_flash_status(void) +{ + int retval; + unsigned char status; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + fwu->in_bl_mode = status >> 7; + + if (fwu->bl_version == BL_V5) + fwu->flash_status = (status >> 4) & MASK_3BIT; + else if (fwu->bl_version == BL_V6) + fwu->flash_status = status & MASK_3BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->flash_status = status & MASK_5BIT; + + if (fwu->write_bootloader) + fwu->flash_status = 0x00; + + if (fwu->flash_status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash status = %d, command = 0x%02x\n", + __func__, fwu->flash_status, fwu->command); + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) { + if (fwu->flash_status == 0x08) + fwu->flash_status = 0x00; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash command\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) + fwu->command = command & MASK_4BIT; + else if (fwu->bl_version == BL_V6) + fwu->command = command & MASK_6BIT; + else if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + fwu->command = command; + + if (fwu->write_bootloader) + fwu->command = 0x00; + + return 0; +} + +static int fwu_wait_for_idle(int timeout_ms, bool poll) +{ + int count = 0; + int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + do { + usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US); + + count++; + if (poll || (count == timeout_count)) + fwu_read_flash_status(); + + if ((fwu->command == CMD_IDLE) && (fwu->flash_status == 0x00)) + return 0; + } while (count < timeout_count); + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for idle status\n", + __func__); + + return -ETIMEDOUT; +} + +static int fwu_write_f34_v7_command_single_transaction(unsigned char cmd) +{ + int retval; + unsigned char data_base; + struct f34_v7_data_1_5 data_1_5; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + memset(data_1_5.data, 0x00, sizeof(data_1_5.data)); + + switch (cmd) { + case CMD_ERASE_ALL: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + data_1_5.partition_id = CORE_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BL_CONFIG: + data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UI_CONFIG: + data_1_5.partition_id = CORE_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_DISP_CONFIG: + data_1_5.partition_id = DISPLAY_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_FLASH_CONFIG: + data_1_5.partition_id = FLASH_CONFIG_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_GUEST_CODE: + data_1_5.partition_id = GUEST_CODE_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_BOOTLOADER: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ERASE_UTILITY_PARAMETER: + data_1_5.partition_id = UTILITY_PARAMETER_PARTITION; + data_1_5.command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + data_1_5.partition_id = BOOTLOADER_PARTITION; + data_1_5.command = CMD_V7_ENTER_BL; + break; + }; + + data_1_5.payload_0 = fwu->bootloader_id[0]; + data_1_5.payload_1 = fwu->bootloader_id[1]; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + data_1_5.data, + sizeof(data_1_5.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write single transaction command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v7_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + case CMD_WRITE_CONFIG: + case CMD_WRITE_LOCKDOWN: + case CMD_WRITE_GUEST_CODE: + case CMD_WRITE_BOOTLOADER: + case CMD_WRITE_UTILITY_PARAM: + command = CMD_V7_WRITE; + break; + case CMD_READ_CONFIG: + command = CMD_V7_READ; + break; + case CMD_ERASE_ALL: + command = CMD_V7_ERASE_AP; + break; + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + command = CMD_V7_ERASE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V7_ENTER_BL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + fwu->command = command; + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_FIRMWARE: + case CMD_ERASE_BL_CONFIG: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_FLASH_CONFIG: + case CMD_ERASE_GUEST_CODE: + case CMD_ERASE_BOOTLOADER: + case CMD_ERASE_UTILITY_PARAMETER: + case CMD_ENABLE_FLASH_PROG: + retval = fwu_write_f34_v7_command_single_transaction(cmd); + if (retval < 0) + return retval; + else + return 0; + default: + break; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write flash command\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_v5v6_command(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_IDLE: + command = CMD_V5V6_IDLE; + break; + case CMD_WRITE_FW: + command = CMD_V5V6_WRITE_FW; + break; + case CMD_WRITE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_WRITE_LOCKDOWN: + command = CMD_V5V6_WRITE_LOCKDOWN; + break; + case CMD_WRITE_GUEST_CODE: + command = CMD_V5V6_WRITE_GUEST_CODE; + break; + case CMD_READ_CONFIG: + command = CMD_V5V6_READ_CONFIG; + break; + case CMD_ERASE_ALL: + command = CMD_V5V6_ERASE_ALL; + break; + case CMD_ERASE_UI_CONFIG: + command = CMD_V5V6_ERASE_UI_CONFIG; + break; + case CMD_ERASE_DISP_CONFIG: + command = CMD_V5V6_ERASE_DISP_CONFIG; + break; + case CMD_ERASE_GUEST_CODE: + command = CMD_V5V6_ERASE_GUEST_CODE; + break; + case CMD_ENABLE_FLASH_PROG: + command = CMD_V5V6_ENABLE_FLASH_PROG; + break; +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + command = CMD_V5V6_ERASE_CHIP; + break; + case CMD_ERASE_FORCE_CONFIG: + command = CMD_V5V6_ERASE_FORCE_CONFIG; + break; + case CMD_READ_FORCE_CONFIG: + command = CMD_V5V6_READ_FORCE_CONFIG; + break; + case CMD_WRITE_FORCE_CONFIG: + command = CMD_V5V6_WRITE_CONFIG; + break; + case CMD_ERASE_LOCKDOWN_DATA: + command = CMD_V5V6_ERASE_LOCKDOWN_DATA; + break; + case CMD_READ_LOCKDOWN_DATA: + command = CMD_V5V6_READ_LOCKDOWN_DATA; + break; + case CMD_WRITE_LOCKDOWN_DATA: + command = CMD_V5V6_WRITE_LOCKDOWN_DATA; + break; + case CMD_ERASE_LCM_DATA: + command = CMD_V5V6_ERASE_LCM_DATA; + break; + case CMD_ERASE_OEM_DATA: + command = CMD_V5V6_ERASE_OEM_DATA; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + } + + switch (cmd) { + case CMD_ERASE_ALL: + case CMD_ERASE_UI_CONFIG: + case CMD_ERASE_DISP_CONFIG: + case CMD_ERASE_GUEST_CODE: +#ifdef SYNA_TDDI + case CMD_ERASE_CHIP: + case CMD_ERASE_FORCE_CONFIG: + case CMD_ERASE_LOCKDOWN_DATA: + case CMD_ERASE_LCM_DATA: + case CMD_ERASE_OEM_DATA: +#endif + case CMD_ENABLE_FLASH_PROG: + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write bootloader ID\n", + __func__); + return retval; + } + break; + default: + break; + }; + + fwu->command = command; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.flash_cmd, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command 0x%02x\n", + __func__, command); + return retval; + } + + return 0; +} + +static int fwu_write_f34_command(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_command(cmd); + else + retval = fwu_write_f34_v5v6_command(cmd); + + return retval; +} + +static int fwu_write_f34_v7_partition_id(unsigned char cmd) +{ + int retval; + unsigned char data_base; + unsigned char partition; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + switch (cmd) { + case CMD_WRITE_FW: + partition = CORE_CODE_PARTITION; + break; + case CMD_WRITE_CONFIG: + case CMD_READ_CONFIG: + if (fwu->config_area == UI_CONFIG_AREA) + partition = CORE_CONFIG_PARTITION; + else if (fwu->config_area == DP_CONFIG_AREA) + partition = DISPLAY_CONFIG_PARTITION; + else if (fwu->config_area == PM_CONFIG_AREA) + partition = GUEST_SERIALIZATION_PARTITION; + else if (fwu->config_area == BL_CONFIG_AREA) + partition = GLOBAL_PARAMETERS_PARTITION; + else if (fwu->config_area == FLASH_CONFIG_AREA) + partition = FLASH_CONFIG_PARTITION; + else if (fwu->config_area == UPP_AREA) + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_WRITE_LOCKDOWN: + partition = DEVICE_CONFIG_PARTITION; + break; + case CMD_WRITE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_WRITE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_WRITE_UTILITY_PARAM: + partition = UTILITY_PARAMETER_PARTITION; + break; + case CMD_ERASE_ALL: + partition = CORE_CODE_PARTITION; + break; + case CMD_ERASE_BL_CONFIG: + partition = GLOBAL_PARAMETERS_PARTITION; + break; + case CMD_ERASE_UI_CONFIG: + partition = CORE_CONFIG_PARTITION; + break; + case CMD_ERASE_DISP_CONFIG: + partition = DISPLAY_CONFIG_PARTITION; + break; + case CMD_ERASE_FLASH_CONFIG: + partition = FLASH_CONFIG_PARTITION; + break; + case CMD_ERASE_GUEST_CODE: + partition = GUEST_CODE_PARTITION; + break; + case CMD_ERASE_BOOTLOADER: + partition = BOOTLOADER_PARTITION; + break; + case CMD_ENABLE_FLASH_PROG: + partition = BOOTLOADER_PARTITION; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid command 0x%02x\n", + __func__, cmd); + return -EINVAL; + }; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.partition_id, + &partition, + sizeof(partition)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write partition ID\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_write_f34_partition_id(unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_partition_id(cmd); + else + retval = 0; + + return retval; +} + +static int fwu_read_f34_v7_partition_table(unsigned char *partition_table) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short block_number = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + fwu->config_area = FLASH_CONFIG_AREA; + + retval = fwu_write_f34_partition_id(CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + length[0] = (unsigned char)(fwu->flash_config_length & MASK_8BIT); + length[1] = (unsigned char)(fwu->flash_config_length >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length\n", + __func__); + return retval; + } + + retval = fwu_write_f34_command(CMD_READ_CONFIG); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + msleep(READ_CONFIG_WAIT_MS); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, true); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + partition_table, + fwu->partition_table_bytes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_read_f34_v7_queries(void) +{ + int retval; + unsigned char ii; + unsigned char query_base; + unsigned char index; + unsigned char offset; + unsigned char *ptable; + struct f34_v7_query_0 query_0; + struct f34_v7_query_1_7 query_1_7; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + query_base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base, + query_0.data, + sizeof(query_0.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read query 0\n", + __func__); + return retval; + } + + offset = query_0.subpacket_1_size + 1; + + retval = synaptics_rmi4_reg_read(rmi4_data, + query_base + offset, + query_1_7.data, + sizeof(query_1_7.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read queries 1 to 7\n", + __func__); + return retval; + } + + fwu->bootloader_id[0] = query_1_7.bl_minor_revision; + fwu->bootloader_id[1] = query_1_7.bl_major_revision; + + if (fwu->bootloader_id[1] == BL_V8) + fwu->bl_version = BL_V8; + + fwu->block_size = query_1_7.block_size_15_8 << 8 | + query_1_7.block_size_7_0; + + fwu->flash_config_length = query_1_7.flash_config_length_15_8 << 8 | + query_1_7.flash_config_length_7_0; + + fwu->payload_length = query_1_7.payload_length_15_8 << 8 | + query_1_7.payload_length_7_0; + + fwu->off.flash_status = V7_FLASH_STATUS_OFFSET; + fwu->off.partition_id = V7_PARTITION_ID_OFFSET; + fwu->off.block_number = V7_BLOCK_NUMBER_OFFSET; + fwu->off.transfer_length = V7_TRANSFER_LENGTH_OFFSET; + fwu->off.flash_cmd = V7_COMMAND_OFFSET; + fwu->off.payload = V7_PAYLOAD_OFFSET; + + index = sizeof(query_1_7.data) - V7_PARTITION_SUPPORT_BYTES; + + fwu->partitions = 0; + for (offset = 0; offset < V7_PARTITION_SUPPORT_BYTES; offset++) { + for (ii = 0; ii < 8; ii++) { + if (query_1_7.data[index + offset] & (1 << ii)) + fwu->partitions++; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Supported partitions: 0x%02x\n", + __func__, query_1_7.data[index + offset]); + } + + fwu->partition_table_bytes = fwu->partitions * 8 + 2; + + ptable = kzalloc(fwu->partition_table_bytes, GFP_KERNEL); + if (!ptable) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for partition table\n", + __func__); + return -ENOMEM; + } + + retval = fwu_read_f34_v7_partition_table(ptable); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read partition table\n", + __func__); + kfree(ptable); + return retval; + } + + fwu_parse_partition_table(ptable, &fwu->blkcount, &fwu->phyaddr); + + if (fwu->blkcount.dp_config) + fwu->flash_properties.has_disp_config = 1; + else + fwu->flash_properties.has_disp_config = 0; + + if (fwu->blkcount.pm_config) + fwu->flash_properties.has_pm_config = 1; + else + fwu->flash_properties.has_pm_config = 0; + + if (fwu->blkcount.bl_config) + fwu->flash_properties.has_bl_config = 1; + else + fwu->flash_properties.has_bl_config = 0; + + if (fwu->blkcount.guest_code) + fwu->has_guest_code = 1; + else + fwu->has_guest_code = 0; + + if (fwu->blkcount.utility_param) + fwu->has_utility_param = 1; + else + fwu->has_utility_param = 0; + + kfree(ptable); + + return 0; +} + +static int fwu_read_f34_v5v6_queries(void) +{ + int retval; + unsigned char count; + unsigned char base; + unsigned char offset; + unsigned char buf[10]; + struct f34_v5v6_flash_properties_2 properties_2; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + base = fwu->f34_fd.query_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + V5V6_BOOTLOADER_ID_OFFSET, + fwu->bootloader_id, + sizeof(fwu->bootloader_id)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read bootloader ID\n", + __func__); + return retval; + } + + if (fwu->bl_version == BL_V5) { + fwu->off.properties = V5_PROPERTIES_OFFSET; + fwu->off.block_size = V5_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V5_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V5_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V5_BLOCK_DATA_OFFSET; + } else if (fwu->bl_version == BL_V6) { + fwu->off.properties = V6_PROPERTIES_OFFSET; + fwu->off.properties_2 = V6_PROPERTIES_2_OFFSET; + fwu->off.block_size = V6_BLOCK_SIZE_OFFSET; + fwu->off.block_count = V6_BLOCK_COUNT_OFFSET; + fwu->off.gc_block_count = V6_GUEST_CODE_BLOCK_COUNT_OFFSET; + fwu->off.block_number = V6_BLOCK_NUMBER_OFFSET; + fwu->off.payload = V6_BLOCK_DATA_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_size, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block size info\n", + __func__); + return retval; + } + + batohs(&fwu->block_size, &(buf[0])); + + if (fwu->bl_version == BL_V5) { + fwu->off.flash_cmd = fwu->off.payload + fwu->block_size; + fwu->off.flash_status = fwu->off.flash_cmd; + } else if (fwu->bl_version == BL_V6) { + fwu->off.flash_cmd = V6_FLASH_COMMAND_OFFSET; + fwu->off.flash_status = V6_FLASH_STATUS_OFFSET; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + count = 4; + + if (fwu->flash_properties.has_pm_config) + count += 2; + + if (fwu->flash_properties.has_bl_config) + count += 2; + + if (fwu->flash_properties.has_disp_config) + count += 2; + + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.block_count, + buf, + count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block count info\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.ui_firmware, &(buf[0])); + batohs(&fwu->blkcount.ui_config, &(buf[2])); + + count = 4; + + if (fwu->flash_properties.has_pm_config) { + batohs(&fwu->blkcount.pm_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_bl_config) { + batohs(&fwu->blkcount.bl_config, &(buf[count])); + count += 2; + } + + if (fwu->flash_properties.has_disp_config) + batohs(&fwu->blkcount.dp_config, &(buf[count])); + + fwu->has_guest_code = false; +#ifdef SYNA_TDDI + fwu->has_force_config = false; + fwu->has_lockdown_data = false; + fwu->has_lcm_data = false; + fwu->has_oem_data = false; +#endif + + if (fwu->flash_properties.has_query4) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + fwu->off.properties_2, + properties_2.data, + sizeof(properties_2.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties 2\n", + __func__); + return retval; + } + offset = fwu->off.properties_2 + 1; + count = 0; + if (properties_2.has_guest_code) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read guest code block count\n", + __func__); + return retval; + } + + batohs(&fwu->blkcount.guest_code, &(buf[0])); + count++; + fwu->has_guest_code = true; + } +#ifdef SYNA_TDDI + if (properties_2.has_force_config) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi force block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_force_config, &(buf[0])); + count++; + fwu->has_force_config = true; + } + if (properties_2.has_lockdown_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lockdown block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lockdown_data, &(buf[0])); + count++; + fwu->has_lockdown_data = true; + } + if (properties_2.has_lcm_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi lcm block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_lcm_data, &(buf[0])); + count++; + fwu->has_lcm_data = true; + } + if (properties_2.has_oem_data) { + retval = synaptics_rmi4_reg_read(rmi4_data, + base + offset + count, + buf, + 2); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read tddi oem block count\n", + __func__); + return retval; + } + batohs(&fwu->blkcount.tddi_oem_data, &(buf[0])); + fwu->has_oem_data = true; + } +#endif + } + + fwu->has_utility_param = false; + + return 0; +} + +static int fwu_read_f34_queries(void) +{ + int retval; + + memset(&fwu->blkcount, 0x00, sizeof(fwu->blkcount)); + memset(&fwu->phyaddr, 0x00, sizeof(fwu->phyaddr)); + + if (fwu->bl_version == BL_V7) + retval = fwu_read_f34_v7_queries(); + else + retval = fwu_read_f34_v5v6_queries(); + + return retval; +} + +static int fwu_write_f34_v7_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short left_bytes; + unsigned short write_size; + unsigned short max_write_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + +#ifdef MAX_WRITE_SIZE + max_write_size = MAX_WRITE_SIZE; + if (max_write_size >= transfer * fwu->block_size) + max_write_size = transfer * fwu->block_size; + else if (max_write_size > fwu->block_size) + max_write_size -= max_write_size % fwu->block_size; + else + max_write_size = fwu->block_size; +#else + max_write_size = transfer * fwu->block_size; +#endif + left_bytes = transfer * fwu->block_size; + + do { + if (left_bytes / max_write_size) + write_size = max_write_size; + else + write_size = left_bytes; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + write_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + block_ptr += write_size; + left_bytes -= write_size; + } while (left_bytes); + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_write_f34_v5v6_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.payload, + block_ptr, + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block data (block %d)\n", + __func__, blk); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command for block %d\n", + __func__, blk); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (block %d)\n", + __func__, blk); + return retval; + } + + block_ptr += fwu->block_size; + } + + return 0; +} + +static int fwu_write_f34_blocks(unsigned char *block_ptr, + unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_write_f34_v7_blocks(block_ptr, block_cnt, cmd); + else + retval = fwu_write_f34_v5v6_blocks(block_ptr, block_cnt, cmd); + + return retval; +} + +static int fwu_read_f34_v7_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char length[2]; + unsigned short transfer; + unsigned short remaining = block_cnt; + unsigned short block_number = 0; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + retval = fwu_write_f34_partition_id(command); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + (unsigned char *)&block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + do { + if (remaining / fwu->payload_length) + transfer = fwu->payload_length; + else + transfer = remaining; + + length[0] = (unsigned char)(transfer & MASK_8BIT); + length[1] = (unsigned char)(transfer >> 8); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.transfer_length, + length, + sizeof(length)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write transfer length (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status (remaining = %d)\n", + __func__, remaining); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + transfer * fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (remaining = %d)\n", + __func__, remaining); + return retval; + } + + index += (transfer * fwu->block_size); + remaining -= transfer; + } while (remaining); + + return 0; +} + +static int fwu_read_f34_v5v6_blocks(unsigned short block_cnt, + unsigned char command) +{ + int retval; + unsigned char data_base; + unsigned char block_number[] = {0, 0}; + unsigned short blk; + unsigned short index = 0; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f34_fd.data_base_addr; + + block_number[1] |= (fwu->config_area << 5); + + retval = synaptics_rmi4_reg_write(rmi4_data, + data_base + fwu->off.block_number, + block_number, + sizeof(block_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write block number\n", + __func__); + return retval; + } + + for (blk = 0; blk < block_cnt; blk++) { + retval = fwu_write_f34_command(command); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write read config command\n", + __func__); + return retval; + } + + retval = fwu_wait_for_idle(WRITE_WAIT_MS, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to wait for idle status\n", + __func__); + return retval; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + fwu->off.payload, + &fwu->read_config_buf[index], + fwu->block_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read block data (block %d)\n", + __func__, blk); + return retval; + } + + index += fwu->block_size; + } + + return 0; +} + +static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd) +{ + int retval; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + retval = fwu_read_f34_v7_blocks(block_cnt, cmd); + else + retval = fwu_read_f34_v5v6_blocks(block_cnt, cmd); + + return retval; +} + +static int fwu_get_image_firmware_id(unsigned int *fw_id) +{ + int retval; + unsigned char index = 0; + char *strptr; + char *firmware_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->img.contains_firmware_id) { + *fw_id = fwu->img.firmware_id; + } else { + strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN); + if (!strptr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n", + __func__, fwu->image_name); + return -EINVAL; + } + + strptr += 2; + firmware_id = kzalloc(MAX_FIRMWARE_ID_LEN, GFP_KERNEL); + if (!firmware_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for firmware_id\n", + __func__); + return -ENOMEM; + } + while (strptr[index] >= '0' && strptr[index] <= '9') { + firmware_id[index] = strptr[index]; + index++; + if (index == MAX_FIRMWARE_ID_LEN - 1) + break; + } + + retval = sstrtoul(firmware_id, 10, (unsigned long *)fw_id); + kfree(firmware_id); + if (retval) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to obtain image firmware ID\n", + __func__); + return -EINVAL; + } + } + + return 0; +} + +static int fwu_get_device_config_id(void) +{ + int retval; + unsigned char config_id_size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.ctrl_base_addr, + fwu->config_id, + config_id_size); + if (retval < 0) + return retval; + + return 0; +} + +static enum flash_area fwu_go_nogo(void) +{ + int retval; + enum flash_area flash_area = NONE; + unsigned char ii; + unsigned char config_id_size; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->force_update) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Update both UI and config if device is in bootloader mode */ + if (fwu->bl_mode_device) { + flash_area = UI_FIRMWARE; + goto exit; + } + + /* Get device firmware ID */ + device_fw_id = rmi4_data->firmware_id; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device firmware ID = %d\n", + __func__, device_fw_id); + + /* Get image firmware ID */ + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) { + flash_area = NONE; + goto exit; + } + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID = %d\n", + __func__, image_fw_id); + + if (image_fw_id > device_fw_id) { + flash_area = UI_FIRMWARE; + goto exit; + } else if (image_fw_id < device_fw_id) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Image firmware ID older than device firmware ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + /* Get device config ID */ + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + flash_area = NONE; + goto exit; + } + + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + config_id_size = V7_CONFIG_ID_SIZE; + else + config_id_size = V5V6_CONFIG_ID_SIZE; + + for (ii = 0; ii < config_id_size; ii++) { + if (fwu->img.ui_config.data[ii] > fwu->config_id[ii]) { + flash_area = UI_CONFIG; + goto exit; + } else if (fwu->img.ui_config.data[ii] < fwu->config_id[ii]) { + flash_area = NONE; + goto exit; + } + } + + flash_area = NONE; + +exit: + if (flash_area == NONE) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: No need to do reflash\n", + __func__); + } else { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Updating %s\n", + __func__, + flash_area == UI_FIRMWARE ? + "UI firmware and config" : + "UI config only"); + } + + return flash_area; +} + +static int fwu_scan_pdt(void) +{ + int retval; + unsigned char ii; + unsigned char intr_count = 0; + unsigned char intr_off; + unsigned char intr_src; + unsigned short addr; + bool f01found = false; + bool f34found = false; + bool f35found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->in_ub_mode = false; + + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + if (rmi_fd.fn_number) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Found F%02x\n", + __func__, rmi_fd.fn_number); + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F01: + f01found = true; + + rmi4_data->f01_query_base_addr = + rmi_fd.query_base_addr; + rmi4_data->f01_ctrl_base_addr = + rmi_fd.ctrl_base_addr; + rmi4_data->f01_data_base_addr = + rmi_fd.data_base_addr; + rmi4_data->f01_cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + case SYNAPTICS_RMI4_F34: + f34found = true; + fwu->f34_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f34_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f34_fd.data_base_addr = + rmi_fd.data_base_addr; + + switch (rmi_fd.fn_version) { + case F34_V0: + fwu->bl_version = BL_V5; + break; + case F34_V1: + fwu->bl_version = BL_V6; + break; + case F34_V2: + fwu->bl_version = BL_V7; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Unrecognized F34 version\n", + __func__); + return -EINVAL; + } + + fwu->intr_mask = 0; + intr_src = rmi_fd.intr_src_count; + intr_off = intr_count % 8; + for (ii = intr_off; + ii < (intr_src + intr_off); + ii++) { + fwu->intr_mask |= 1 << ii; + } + break; + case SYNAPTICS_RMI4_F35: + f35found = true; + fwu->f35_fd.query_base_addr = + rmi_fd.query_base_addr; + fwu->f35_fd.ctrl_base_addr = + rmi_fd.ctrl_base_addr; + fwu->f35_fd.data_base_addr = + rmi_fd.data_base_addr; + fwu->f35_fd.cmd_base_addr = + rmi_fd.cmd_base_addr; + break; + } + } else { + break; + } + + intr_count += rmi_fd.intr_src_count; + } + + if (!f01found || !f34found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find both F01 and F34\n", + __func__); + if (!f35found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F35\n", + __func__); + return -EINVAL; + } else { + fwu->in_ub_mode = true; + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + fwu_recovery_check_status(); + return 0; + } + } + + rmi4_data->intr_mask[0] |= fwu->intr_mask; + + addr = rmi4_data->f01_ctrl_base_addr + 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + addr, + &(rmi4_data->intr_mask[0]), + sizeof(rmi4_data->intr_mask[0])); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set interrupt enable bit\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_enter_flash_prog(void) +{ + int retval; + struct f01_device_control f01_device_control; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_read_flash_status(); + if (retval < 0) + return retval; + + if (fwu->in_bl_mode) + return 0; + + retval = rmi4_data->irq_enable(rmi4_data, false, true); + if (retval < 0) + return retval; + + msleep(INT_DISABLE_WAIT_MS); + + retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG); + if (retval < 0) + return retval; + + retval = fwu_wait_for_idle(ENABLE_WAIT_MS, false); + if (retval < 0) + return retval; + + if (!fwu->in_bl_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: BL mode not entered\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->hw_if->bl_hw_init) { + retval = rmi4_data->hw_if->bl_hw_init(rmi4_data); + if (retval < 0) + return retval; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return retval; + + retval = fwu_read_f34_queries(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F01 device control\n", + __func__); + return retval; + } + + f01_device_control.nosleep = true; + f01_device_control.sleep_mode = SLEEP_MODE_NORMAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + f01_device_control.data, + sizeof(f01_device_control.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write F01 device control\n", + __func__); + return retval; + } + + msleep(ENTER_FLASH_PROG_WAIT_MS); + + return retval; +} + +static int fwu_check_ui_firmware_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_firmware.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_firmware) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI firmware size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_ui_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.ui_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.ui_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: UI configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_dp_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.dp_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.dp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_pm_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.pm_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_bl_configuration_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.bl_config.size / fwu->block_size; + + if (block_count != fwu->blkcount.bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_check_guest_code_size(void) +{ + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->img.guest_code.size / fwu->block_size; + if (block_count != fwu->blkcount.guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code size mismatch\n", + __func__); + return -EINVAL; + } + + return 0; +} + +static int fwu_erase_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UI_CONFIG); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG); + if (retval < 0) + return retval; + break; + case BL_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG); + if (retval < 0) + return retval; + break; + case FLASH_CONFIG_AREA: + retval = fwu_write_f34_command(CMD_ERASE_FLASH_CONFIG); + if (retval < 0) + return retval; + break; + case UPP_AREA: + retval = fwu_write_f34_command(CMD_ERASE_UTILITY_PARAMETER); + if (retval < 0) + return retval; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return retval; +} + +static int fwu_erase_bootloader(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_BOOTLOADER); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#ifdef SYNA_TDDI +static int fwu_erase_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + msleep(100); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +#endif + +static int fwu_erase_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_command(CMD_ERASE_GUEST_CODE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + return 0; +} + +static int fwu_erase_all(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version == BL_V7) { + retval = fwu_write_f34_command(CMD_ERASE_UI_FIRMWARE); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } else { + retval = fwu_write_f34_command(CMD_ERASE_ALL); + if (retval < 0) + return retval; + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Erase all command written\n", + __func__); + + retval = fwu_wait_for_idle(ERASE_WAIT_MS, false); + if (!(fwu->bl_version == BL_V8 && + fwu->flash_status == BAD_PARTITION_TABLE)) { + if (retval < 0) + return retval; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Idle status detected\n", + __func__); + + if (fwu->bl_version == BL_V8) + return 0; + } + + if (fwu->flash_properties.has_disp_config) { + fwu->config_area = DP_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code) { + retval = fwu_erase_guest_code(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_write_firmware(void) +{ + unsigned short firmware_block_count; + + firmware_block_count = fwu->img.ui_firmware.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.ui_firmware.data, + firmware_block_count, CMD_WRITE_FW); +} + +static int fwu_write_bootloader(void) +{ + int retval; + unsigned short bootloader_block_count; + + bootloader_block_count = fwu->img.bl_image.size / fwu->block_size; + + fwu->write_bootloader = true; + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.bl_image.data, + bootloader_block_count, CMD_WRITE_BOOTLOADER); + fwu->write_bootloader = false; + + return retval; +} + +static int fwu_write_utility_parameter(void) +{ + int retval; + unsigned char ii; + unsigned char checksum_array[4]; + unsigned char *pbuf; + unsigned short remaining_size; + unsigned short utility_param_size; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + utility_param_size = fwu->blkcount.utility_param * fwu->block_size; + retval = fwu_allocate_read_config_buf(utility_param_size); + if (retval < 0) + return retval; + memset(fwu->read_config_buf, 0x00, utility_param_size); + + pbuf = fwu->read_config_buf; + remaining_size = utility_param_size - 4; + + for (ii = 0; ii < MAX_UTILITY_PARAMS; ii++) { + if (fwu->img.utility_param_id[ii] == UNUSED) + continue; + +#ifdef F51_DISCRETE_FORCE + if (fwu->img.utility_param_id[ii] == FORCE_PARAMETER) { + if (fwu->bl_mode_device) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + goto image_param; + } + retval = secure_memcpy(&(pbuf[4]), + remaining_size - 4, + fwu->cal_data, + fwu->cal_data_buf_size, + fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy force calibration data\n", + __func__); + return retval; + } + pbuf[0] = FORCE_PARAMETER; + pbuf[1] = 0x00; + pbuf[2] = (4 + fwu->cal_data_size) / 2; + pbuf += (fwu->cal_data_size + 4); + remaining_size -= (fwu->cal_data_size + 4); + continue; + } +image_param: +#endif + + retval = secure_memcpy(pbuf, + remaining_size, + fwu->img.utility_param[ii].data, + fwu->img.utility_param[ii].size, + fwu->img.utility_param[ii].size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy utility parameter data\n", + __func__); + return retval; + } + pbuf += fwu->img.utility_param[ii].size; + remaining_size -= fwu->img.utility_param[ii].size; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((utility_param_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[utility_param_size - 4] = checksum_array[0]; + fwu->read_config_buf[utility_param_size - 3] = checksum_array[1]; + fwu->read_config_buf[utility_param_size - 2] = checksum_array[2]; + fwu->read_config_buf[utility_param_size - 1] = checksum_array[3]; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->read_config_buf, + fwu->blkcount.utility_param, CMD_WRITE_UTILITY_PARAM); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_configuration(void) +{ + return fwu_write_f34_blocks((unsigned char *)fwu->config_data, + fwu->config_block_count, CMD_WRITE_CONFIG); +} + +static int fwu_write_ui_configuration(void) +{ + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->img.ui_config.data; + fwu->config_size = fwu->img.ui_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_dp_configuration(void) +{ + fwu->config_area = DP_CONFIG_AREA; + fwu->config_data = fwu->img.dp_config.data; + fwu->config_size = fwu->img.dp_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +static int fwu_write_pm_configuration(void) +{ + fwu->config_area = PM_CONFIG_AREA; + fwu->config_data = fwu->img.pm_config.data; + fwu->config_size = fwu->img.pm_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + return fwu_write_configuration(); +} + +#ifdef SYNA_TDDI +static int fwu_write_tddi_lockdown_data(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_write_f34_blocks(fwu->read_config_buf, + fwu->blkcount.tddi_lockdown_data, + CMD_WRITE_LOCKDOWN_DATA); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + return 0; +} +#endif + +static int fwu_write_flash_configuration(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_guest_code(void) +{ + int retval; + unsigned short guest_code_block_count; + + guest_code_block_count = fwu->img.guest_code.size / fwu->block_size; + + retval = fwu_write_f34_blocks((unsigned char *)fwu->img.guest_code.data, + guest_code_block_count, CMD_WRITE_GUEST_CODE); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_lockdown(void) +{ + unsigned short lockdown_block_count; + + lockdown_block_count = fwu->img.lockdown.size / fwu->block_size; + + return fwu_write_f34_blocks((unsigned char *)fwu->img.lockdown.data, + lockdown_block_count, CMD_WRITE_LOCKDOWN); +} + +static int fwu_write_partition_table_v8(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + if (fwu->config_block_count != fwu->blkcount.fl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash configuration size mismatch\n", + __func__); + return -EINVAL; + } + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + rmi4_data->reset_device(rmi4_data, false); + + return 0; +} + +static int fwu_write_partition_table_v7(void) +{ + int retval; + unsigned short block_count; + + block_count = fwu->blkcount.bl_config; + fwu->config_area = BL_CONFIG_AREA; + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_flash_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_write_bl_area_v7(void) +{ + int retval; + bool has_utility_param; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + has_utility_param = fwu->has_utility_param; + + if (fwu->has_utility_param) { + fwu->config_area = UPP_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + } + + fwu->config_area = BL_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + fwu->config_area = FLASH_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_erase_bootloader(); + if (retval < 0) + return retval; + + retval = fwu_write_bootloader(); + if (retval < 0) + return retval; + + msleep(rmi4_data->hw_if->board_data->reset_delay_ms); + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = FLASH_CONFIG_AREA; + fwu->config_data = fwu->img.fl_config.data; + fwu->config_size = fwu->img.fl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + rmi4_data->reset_device(rmi4_data, false); + + fwu->config_area = BL_CONFIG_AREA; + fwu->config_data = fwu->img.bl_config.data; + fwu->config_size = fwu->img.bl_config.size; + fwu->config_block_count = fwu->config_size / fwu->block_size; + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + if (fwu->img.contains_utility_param) { + retval = fwu_write_utility_parameter(); + if (retval < 0) + return retval; + } + + return 0; +} + +static int fwu_do_reflash(void) +{ + int retval; + bool do_bl_update = false; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!fwu->new_partition_table) { + retval = fwu_check_ui_firmware_size(); + if (retval < 0) + return retval; + + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + } + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_check_guest_code_size(); + if (retval < 0) + return retval; + } + } else if (fwu->bl_version == BL_V7) { + retval = fwu_check_bl_configuration_size(); + if (retval < 0) + return retval; + } + + if (!fwu->has_utility_param && fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (fwu->has_utility_param && !fwu->img.contains_utility_param) { + if (fwu->bl_version == BL_V7 || fwu->bl_version == BL_V8) + do_bl_update = true; + } + + if (!do_bl_update && fwu->incompatible_partition_tables) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Incompatible partition tables\n", + __func__); + return -EINVAL; + } else if (!do_bl_update && fwu->new_partition_table) { + if (!fwu->force_update) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Partition table mismatch\n", + __func__); + return -EINVAL; + } + } + + retval = fwu_erase_all(); + if (retval < 0) + return retval; + + if (do_bl_update) { + retval = fwu_write_bl_area_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Bootloader area programmed\n", __func__); + } else if (fwu->bl_version == BL_V7 && fwu->new_partition_table) { + retval = fwu_write_partition_table_v7(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } else if (fwu->bl_version == BL_V8) { + retval = fwu_write_partition_table_v8(); + if (retval < 0) + return retval; + pr_notice("%s: Partition table programmed\n", __func__); + } + + fwu->config_area = UI_CONFIG_AREA; + if (fwu->flash_properties.has_disp_config && + fwu->img.contains_disp_config) { + retval = fwu_write_dp_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Display configuration programmed\n", __func__); + } + + retval = fwu_write_ui_configuration(); + if (retval < 0) + return retval; + pr_notice("%s: Configuration programmed\n", __func__); + + if (fwu->has_guest_code && fwu->img.contains_guest_code) { + retval = fwu_write_guest_code(); + if (retval < 0) + return retval; + pr_notice("%s: Guest code programmed\n", __func__); + } + + retval = fwu_write_firmware(); + if (retval < 0) + return retval; + pr_notice("%s: Firmware programmed\n", __func__); + + return retval; +} + +static int fwu_do_read_config(void) +{ + int retval; + unsigned short block_count; + unsigned short config_area; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + block_count = fwu->blkcount.ui_config; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.dp_config; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.pm_config; + break; + case BL_CONFIG_AREA: + if (!fwu->flash_properties.has_bl_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.bl_config; + break; + case UPP_AREA: + if (!fwu->has_utility_param) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Utility parameter not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.utility_param; + break; +#ifdef SYNA_TDDI + case TDDI_FORCE_CONFIG_AREA: + if (!fwu->has_force_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: force configuration not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_force_config; + break; + case TDDI_OEM_DATA_AREA: + if (!fwu->has_oem_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: oem data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_oem_data; + break; + case TDDI_LCM_DATA_AREA: + if (!fwu->has_lcm_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: lcm data not supported\n", + __func__); + return -EINVAL; + } + block_count = fwu->blkcount.tddi_lcm_data; + break; +#endif + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid config area\n", + __func__); + return -EINVAL; + } + + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + return -EINVAL; + } + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) { + config_area = fwu->config_area; + retval = fwu_enter_flash_prog(); + fwu->config_area = config_area; + if (retval < 0) + goto exit; + } + + fwu->config_size = fwu->block_size * block_count; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + +exit: + if (fwu->bl_version == BL_V5 || fwu->bl_version == BL_V6) + rmi4_data->reset_device(rmi4_data, false); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + return retval; +} + +static int fwu_do_read_customer_serialization_data(void) +{ + int ii; + int retval = 0; + int block_count = 0; + char temp[40] = {0}; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of customer serialization aquirement process\n", __func__); + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; +/* + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; +*/ + fwu->config_area = PM_CONFIG_AREA; + block_count = fwu->blkcount.pm_config; + if (block_count == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid block count\n", + __func__); + goto exit; + } + fwu->config_size = fwu->block_size * block_count; + pr_notice("%s: Block size = %d\n", __func__, fwu->block_size); + pr_notice("%s: Permanent config block count = %d\n", __func__, block_count); + pr_notice("%s: Permanent config size = %d\n", __func__, fwu->config_size); + dev_info(rmi4_data->pdev->dev.parent, + "%s: permanent config size = %d\n", + __func__, fwu->config_size); + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + + goto exit; + } + + retval = fwu_read_f34_blocks(block_count, + CMD_READ_CONFIG); + if (retval < 0) { + + goto exit; + } + + for (ii = 0; ii < 10; ii++) + pr_notice("%s: Permanent config data[%d] = 0x%02x\n", __func__, ii, fwu->read_config_buf[ii]); + + sprintf(temp, "%02x%02x%02x%02x%02x%02x%02x%02x", fwu->read_config_buf[0], fwu->read_config_buf[1], fwu->read_config_buf[2], fwu->read_config_buf[3], fwu->read_config_buf[4], fwu->read_config_buf[5], fwu->read_config_buf[6], fwu->read_config_buf[7]); +printk("tp_lockdown info : %s\n", temp); +strcpy(tp_lockdown_info, temp); + + + +exit: + + pr_notice("%s: End of customer serialization acquirement process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + + + +#ifdef SYNA_TDDI +static int fwu_do_read_tddi_lockdown_data(void) +{ + int retval = -EINVAL; + unsigned short block_count; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.tddi_lockdown_data; + fwu->config_size = fwu->block_size * block_count; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + kfree(fwu->read_config_buf); + + fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL); + + if (!fwu->read_config_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu->read_config_buf\n", + __func__); + fwu->read_config_buf_size = 0; + retval = -ENOMEM; + goto exit; + } + fwu->read_config_buf_size = fwu->config_size; + retval = fwu_read_f34_blocks(block_count, CMD_READ_LOCKDOWN_DATA); +exit: + return retval; +} + +int get_tddi_lockdown_data_lansi(unsigned char *lockdown_data, unsigned short leng) +{ + int retval; + + retval = fwu_do_read_tddi_lockdown_data(); + if (retval < 0) + return retval; + memcpy(lockdown_data, fwu->read_config_buf, leng); + return retval; +} + +int set_tddi_lockdown_data_lansi(unsigned char *lockdown_data, unsigned short leng) +{ + int retval = -EINVAL; + unsigned long checksum; + unsigned char checksum_array[4]; + unsigned short blk_cnt; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (fwu->bl_version != BL_V6) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data in bl v.%d\n", + __func__, + fwu->bl_version); + goto exit; + } else if (!fwu->has_lockdown_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not support lockdown data\n", __func__); + goto exit; + } + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_erase_lockdown_data(); + if (retval < 0) + goto exit; + + fwu->config_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + goto exit; + memset(fwu->read_config_buf, 0x00, fwu->config_size); + retval = secure_memcpy(fwu->read_config_buf, fwu->config_size, + lockdown_data, leng, leng); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy tddi lockdwon data\n", + __func__); + goto exit; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[blk_cnt * fwu->block_size - 4] = checksum_array[0]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 3] = checksum_array[1]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 2] = checksum_array[2]; + fwu->read_config_buf[blk_cnt * fwu->block_size - 1] = checksum_array[3]; + retval = fwu_write_tddi_lockdown_data(); +exit: + return retval; +} +#endif + +static int fwu_do_lockdown_v7(void) +{ + int retval; + struct f34_v7_data0 status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.data_base_addr + fwu->off.flash_status, + status.data, + sizeof(status.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if (status.device_cfg_status == 2) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +static int fwu_do_lockdown_v5v6(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#ifdef SYNA_TDDI + unsigned char *img_ld; + + img_ld = (unsigned char *)fwu->img.lockdown.data; + if (fwu->has_lockdown_data) { + retval = set_tddi_lockdown_data_lansi(img_ld, + LOCKDOWN_SIZE); + if (retval < 0) + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write lockdown data\n", + __func__); + return retval; + } +#endif + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f34_fd.query_base_addr + fwu->off.properties, + fwu->flash_properties.data, + sizeof(fwu->flash_properties.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash properties\n", + __func__); + return retval; + } + + if (fwu->flash_properties.unlocked == 0) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device already locked down\n", + __func__); + return 0; + } + + retval = fwu_write_lockdown(); + if (retval < 0) + return retval; + + pr_notice("%s: Lockdown programmed\n", __func__); + + return retval; +} + +#ifdef F51_DISCRETE_FORCE +static int fwu_do_restore_f51_cal_data(void) +{ + int retval; + unsigned char checksum_array[4]; + unsigned short block_count; + unsigned long checksum; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + block_count = fwu->blkcount.ui_config; + fwu->config_size = fwu->block_size * block_count; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) + return retval; + + retval = fwu_read_f34_blocks(block_count, CMD_READ_CONFIG); + if (retval < 0) + return retval; + + retval = secure_memcpy(&fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data, + fwu->cal_data_buf_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore calibration data\n", + __func__); + return retval; + } + + calculate_checksum((unsigned short *)fwu->read_config_buf, + ((fwu->config_size - 4) / 2), + &checksum); + + convert_to_little_endian(checksum_array, checksum); + + fwu->read_config_buf[fwu->config_size - 4] = checksum_array[0]; + fwu->read_config_buf[fwu->config_size - 3] = checksum_array[1]; + fwu->read_config_buf[fwu->config_size - 2] = checksum_array[2]; + fwu->read_config_buf[fwu->config_size - 1] = checksum_array[3]; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + return retval; + + fwu->config_area = UI_CONFIG_AREA; + fwu->config_data = fwu->read_config_buf; + fwu->config_block_count = fwu->config_size / fwu->block_size; + + retval = fwu_erase_configuration(); + if (retval < 0) + return retval; + + retval = fwu_write_configuration(); + if (retval < 0) + return retval; + + return 0; +} +#endif + +static int fwu_start_write_guest_code(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + if (!fwu->has_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Guest code not supported\n", + __func__); + return -EINVAL; + } + + if (!fwu->img.contains_guest_code) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No guest code in firmware image\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write guest code process\n", __func__); + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + retval = fwu_check_guest_code_size(); + if (retval < 0) + goto exit; + + retval = fwu_erase_guest_code(); + if (retval < 0) + goto exit; + + retval = fwu_write_guest_code(); + if (retval < 0) + goto exit; + + pr_notice("%s: Guest code programmed\n", __func__); + +exit: + rmi4_data->reset_device(rmi4_data, false); + + pr_notice("%s: End of write guest code process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_start_write_config(void) +{ + int retval; + unsigned short config_area; + unsigned int device_fw_id; + unsigned int image_fw_id; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = fwu_parse_image_info(); + if (retval < 0) + return -EINVAL; + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + device_fw_id = rmi4_data->firmware_id; + retval = fwu_get_image_firmware_id(&image_fw_id); + if (retval < 0) + return retval; + if (device_fw_id != image_fw_id) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Device and image firmware IDs don't match\n", + __func__); + return -EINVAL; + } + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + return retval; + break; + case DP_CONFIG_AREA: + if (!fwu->flash_properties.has_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Display configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_disp_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No display configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_dp_configuration_size(); + if (retval < 0) + return retval; + break; + case PM_CONFIG_AREA: + if (!fwu->flash_properties.has_pm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Permanent configuration not supported\n", + __func__); + return -EINVAL; + } + if (!fwu->img.contains_perm_config) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No permanent configuration in firmware image\n", + __func__); + return -EINVAL; + } + retval = fwu_check_pm_configuration_size(); + if (retval < 0) + return retval; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Configuration not supported\n", + __func__); + return -EINVAL; + } + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of write config process\n", __func__); + + config_area = fwu->config_area; + + retval = fwu_enter_flash_prog(); + if (retval < 0) + goto exit; + + fwu->config_area = config_area; + + if (fwu->config_area != PM_CONFIG_AREA) { + retval = fwu_erase_configuration(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to erase config\n", + __func__); + goto exit; + } + } + + switch (fwu->config_area) { + case UI_CONFIG_AREA: + retval = fwu_write_ui_configuration(); + if (retval < 0) + goto exit; + break; + case DP_CONFIG_AREA: + retval = fwu_write_dp_configuration(); + if (retval < 0) + goto exit; + break; + case PM_CONFIG_AREA: + retval = fwu_write_pm_configuration(); + if (retval < 0) + goto exit; + break; + } + + pr_notice("%s: Config written\n", __func__); + +exit: + switch (fwu->config_area) { + case UI_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, true); + break; + case DP_CONFIG_AREA: + case PM_CONFIG_AREA: + rmi4_data->reset_device(rmi4_data, false); + break; + } + + pr_notice("%s: End of write config process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} +static char tp_info_summary[80] = ""; + +static int fwu_start_reflash(void) +{ + int retval = 0; + enum flash_area flash_area; + bool do_rebuild = false; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + unsigned char config_ver[20] = {0}; + + char tp_temp_info[80]; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of reflash process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IMAGE_NAME, sizeof(FW_IMAGE_NAME), + sizeof(FW_IMAGE_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware image %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware image %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + } + + retval = fwu_parse_image_info(); + if (retval < 0) + goto exit; + + if (fwu->blkcount.total_count != fwu->img.blkcount.total_count) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Flash size mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (fwu->bl_version != fwu->img.bl_version) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Bootloader version mismatch\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_read_flash_status(); + if (retval < 0) + goto exit; + + if (fwu->in_bl_mode) { + fwu->bl_mode_device = true; + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode\n", + __func__); + } else { + fwu->bl_mode_device = false; + } + + flash_area = fwu_go_nogo(); + + if (flash_area != NONE) { + retval = fwu_enter_flash_prog(); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } + +#ifdef F51_DISCRETE_FORCE + if (flash_area != NONE && !fwu->bl_mode_device) { + fwu->config_size = fwu->block_size * fwu->blkcount.ui_config; + fwu->config_area = UI_CONFIG_AREA; + + retval = fwu_allocate_read_config_buf(fwu->config_size); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = fwu_read_f34_blocks(fwu->blkcount.ui_config, + CMD_READ_CONFIG); + if (retval < 0) { + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + + retval = secure_memcpy(fwu->cal_data, fwu->cal_data_buf_size, + &fwu->read_config_buf[fwu->cal_data_off], + fwu->cal_data_size, fwu->cal_data_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to save calibration data\n", + __func__); + rmi4_data->reset_device(rmi4_data, false); + goto exit; + } + } +#endif + + switch (flash_area) { + case UI_FIRMWARE: + do_rebuild = true; + retval = fwu_do_reflash(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param || fwu->img.contains_utility_param) + break; + + rmi4_data->reset_device(rmi4_data, false); + + if (fwu->bl_mode_device || fwu->in_bl_mode) { + dev_info(rmi4_data->pdev->dev.parent, + "%s: Device in bootloader mode, skipping calibration data restoration\n", + __func__); + break; + } + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case UI_CONFIG: + do_rebuild = true; + retval = fwu_check_ui_configuration_size(); + if (retval < 0) + break; + fwu->config_area = UI_CONFIG_AREA; + retval = fwu_erase_configuration(); + if (retval < 0) + break; + retval = fwu_write_ui_configuration(); +#ifdef F51_DISCRETE_FORCE + if (retval < 0) + break; + + if (fwu->has_utility_param) + break; + + retval = fwu_do_restore_f51_cal_data(); +#endif + break; + case NONE: + default: + break; + } + + if (retval < 0) { + do_rebuild = false; + rmi4_data->reset_device(rmi4_data, false); + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + goto exit; + } + + if (fwu->do_lockdown && (fwu->img.lockdown.data != NULL)) { + switch (fwu->bl_version) { + case BL_V5: + case BL_V6: + retval = fwu_do_lockdown_v5v6(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + case BL_V7: + case BL_V8: + retval = fwu_do_lockdown_v7(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do lockdown\n", + __func__); + } + rmi4_data->reset_device(rmi4_data, false); + break; + default: + break; + } + } + +exit: + if (fw_entry) + release_firmware(fw_entry); + + if (do_rebuild) + rmi4_data->reset_device(rmi4_data, true); + + pr_notice("%s: End of reflash process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + synaptics_rmi4_reg_read(rmi4_data, + 0x000c, + config_ver, + 1); + printk("config_ver info =%02x\n", config_ver[0]); + + + strcpy(tp_info_summary, "[Vendor]Lansi, [IC]TD4310(synaptics), [FW]Ver"); + sprintf(tp_temp_info, "%02x", config_ver[0]); + strcat(tp_info_summary, tp_temp_info); + strcat(tp_info_summary, "\0"); + hq_regiser_hw_info(HWID_CTP, tp_info_summary); + + rmi4_data->stay_awake = false; + + return retval; +} + +static int fwu_recovery_check_status(void) +{ + int retval; + unsigned char data_base; + unsigned char status; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_ERROR_CODE_OFFSET, + &status, + 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read status\n", + __func__); + return retval; + } + + status = status & MASK_5BIT; + + if (status != 0x00) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Recovery mode status = %d\n", + __func__, status); + return -EINVAL; + } + + return 0; +} + +static int fwu_recovery_erase_completion(void) +{ + int retval; + unsigned char data_base; + unsigned char command; + unsigned char status; + unsigned int timeout = F35_ERASE_ALL_WAIT_MS / 20; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + data_base = fwu->f35_fd.data_base_addr; + + do { + command = 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue command\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + fwu->f35_fd.cmd_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command status\n", + __func__); + return retval; + } + + if ((command & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + + if (timeout == 0) + goto exit; + + retval = synaptics_rmi4_reg_read(rmi4_data, + data_base + F35_FLASH_STATUS_OFFSET, + &status, + sizeof(status)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read flash status\n", + __func__); + return retval; + } + + if ((status & 0x01) == 0x00) + break; + + msleep(20); + timeout--; + } while (timeout > 0); + +exit: + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for flash erase completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int fwu_recovery_erase_all(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_ERASE_ALL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue erase all command\n", + __func__); + return retval; + } + + if (fwu->f35_fd.cmd_base_addr) { + retval = fwu_recovery_erase_completion(); + if (retval < 0) + return retval; + } else { + msleep(F35_ERASE_ALL_WAIT_MS); + } + + retval = fwu_recovery_check_status(); + if (retval < 0) + return retval; + + return 0; +} + +static int fwu_recovery_write_chunk(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char chunk_number[] = {0, 0}; + unsigned char chunk_spare; + unsigned char chunk_size; + unsigned char buf[F35_CHUNK_SIZE + 1]; + unsigned short chunk; + unsigned short chunk_total; + unsigned short bytes_written = 0; + unsigned char *chunk_ptr = (unsigned char *)fwu->image; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_NUM_LSB_OFFSET, + chunk_number, + sizeof(chunk_number)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk number\n", + __func__); + return retval; + } + + buf[sizeof(buf) - 1] = CMD_F35_WRITE_CHUNK; + + chunk_total = fwu->image_size / F35_CHUNK_SIZE; + chunk_spare = fwu->image_size % F35_CHUNK_SIZE; + if (chunk_spare) + chunk_total++; + + for (chunk = 0; chunk < chunk_total; chunk++) { + if (chunk_spare && chunk == chunk_total - 1) + chunk_size = chunk_spare; + else + chunk_size = F35_CHUNK_SIZE; + + memset(buf, 0x00, F35_CHUNK_SIZE); + secure_memcpy(buf, sizeof(buf), chunk_ptr, + fwu->image_size - bytes_written, + chunk_size); + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_DATA_OFFSET, + buf, + sizeof(buf)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data (chunk %d)\n", + __func__, chunk); + return retval; + } + chunk_ptr += chunk_size; + bytes_written += chunk_size; + } + + retval = fwu_recovery_check_status(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data\n", + __func__); + return retval; + } + + return 0; +} + +static int fwu_recovery_reset(void) +{ + int retval; + unsigned char ctrl_base; + unsigned char command = CMD_F35_RESET; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + ctrl_base = fwu->f35_fd.ctrl_base_addr; + + retval = synaptics_rmi4_reg_write(rmi4_data, + ctrl_base + F35_CHUNK_COMMAND_OFFSET, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to issue reset command\n", + __func__); + return retval; + } + + msleep(F35_RESET_WAIT_MS); + + return 0; +} + +static int fwu_start_recovery(void) +{ + int retval; + const struct firmware *fw_entry = NULL; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + mutex_lock(&rmi4_data->rmi4_exp_init_mutex); + + pr_notice("%s: Start of recovery process\n", __func__); + + if (fwu->image == NULL) { + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + FW_IHEX_NAME, sizeof(FW_IHEX_NAME), + sizeof(FW_IHEX_NAME)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy ihex file name\n", + __func__); + goto exit; + } + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Requesting firmware ihex %s\n", + __func__, fwu->image_name); + + retval = request_firmware(&fw_entry, fwu->image_name, + rmi4_data->pdev->dev.parent); + if (retval != 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Firmware ihex %s not available\n", + __func__, fwu->image_name); + retval = -EINVAL; + goto exit; + } + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Firmware image size = %d\n", + __func__, (unsigned int)fw_entry->size); + + fwu->image = fw_entry->data; + fwu->image_size = fw_entry->size; + } + + retval = rmi4_data->irq_enable(rmi4_data, false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable interrupt\n", + __func__); + goto exit; + } + + retval = fwu_recovery_erase_all(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do erase all in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: External flash erased\n", __func__); + + retval = fwu_recovery_write_chunk(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write chunk data in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Chunk data programmed\n", __func__); + + retval = fwu_recovery_reset(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to reset device in recovery mode\n", + __func__); + goto exit; + } + + pr_notice("%s: Recovery mode reset issued\n", __func__); + + rmi4_data->reset_device(rmi4_data, true); + + retval = 0; + +exit: + if (fw_entry) + release_firmware(fw_entry); + + pr_notice("%s: End of recovery process\n", __func__); + + mutex_unlock(&rmi4_data->rmi4_exp_init_mutex); + + rmi4_data->stay_awake = false; + + return retval; +} + +int synaptics_fw_updater_lansi(const unsigned char *fw_data) +{ + int retval; + + if (!fwu) + return -ENODEV; + + if (!fwu->initialized) + return -ENODEV; + + if (fwu->in_ub_mode) { + fwu->image = NULL; + retval = fwu_start_recovery(); + if (retval < 0) + return retval; + } + + fwu->image = fw_data; + + retval = fwu_start_reflash(); + + fwu->image = NULL; + + return retval; +} +EXPORT_SYMBOL(synaptics_fw_updater_lansi); + +#ifdef DO_STARTUP_FW_UPDATE +static void fwu_startup_fw_update_work(struct work_struct *work) +{ + static unsigned char do_once = 1; +#ifdef WAIT_FOR_FB_READY + unsigned int timeout; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; +#endif + + + if (!do_once) + return; + do_once = 0; + +#ifdef WAIT_FOR_FB_READY + timeout = FB_READY_TIMEOUT_S * 1000 / FB_READY_WAIT_MS + 1; + + while (!rmi4_data->fb_ready) { + msleep(FB_READY_WAIT_MS); + timeout--; + if (timeout == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for FB ready\n", + __func__); + return; + } + } +#endif + + synaptics_fw_updater_lansi(NULL); + + + + return; +} +#endif + +static ssize_t fwu_sysfs_show_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + if (count < fwu->config_size) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not enough space (%d bytes) in buffer\n", + __func__, (unsigned int)count); + retval = -EINVAL; + goto exit; + } + + retval = secure_memcpy(buf, count, fwu->read_config_buf, + fwu->read_config_buf_size, fwu->config_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy config data\n", + __func__); + goto exit; + } else { + retval = fwu->config_size; + } + +exit: + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_store_image(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = secure_memcpy(&fwu->ext_data_source[fwu->data_pos], + fwu->image_size - fwu->data_pos, buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image data\n", + __func__); + goto exit; + } else { + retval = count; + } + + fwu->data_pos += count; + +exit: + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_do_recovery_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (!fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Not in microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_recovery(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do recovery\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_do_reflash_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + + } else { + fwu->image = fwu->ext_data_source; + } + + if (input & LOCKDOWN) { + fwu->do_lockdown = true; + input &= ~LOCKDOWN; + } + + if ((input != NORMAL) && (input != FORCE)) { + retval = -EINVAL; + + } + + if (input == FORCE) + fwu->force_update = true; + + retval = synaptics_fw_updater_lansi(fwu->image); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do reflash\n", + __func__); + + } + + retval = count; + + + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_write_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_read_config_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = fwu_do_read_config(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read config\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_config_area_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long config_area; + + retval = sstrtoul(buf, 10, &config_area); + if (retval) + return retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + fwu->config_area = config_area; + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return count; +} + +static ssize_t fwu_sysfs_image_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = secure_memcpy(fwu->image_name, MAX_IMAGE_NAME_LEN, + buf, count, count); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy image file name\n", + __func__); + } else { + retval = count; + } + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_image_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long size; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + retval = sstrtoul(buf, 10, &size); + if (retval) + return retval; + +/* if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; +*/ + fwu->image_size = size; + fwu->data_pos = 0; + + kfree(fwu->ext_data_source); + fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL); + if (!fwu->ext_data_source) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image data\n", + __func__); + retval = -ENOMEM; + } else { + retval = count; + } + + + + return retval; +} + +static ssize_t fwu_sysfs_block_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_firmware); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.ui_config); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.dp_config); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.pm_config); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.bl_config); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_utility_parameter_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.utility_param); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + +static ssize_t fwu_sysfs_guest_code_block_count_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + retval = snprintf(buf, PAGE_SIZE, "%u\n", fwu->blkcount.guest_code); + + mutex_unlock(&fwu_sysfs_mutex_lansi); + + return retval; +} + + +static ssize_t fwu_sysfs_read_guest_serialization_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + fwu_do_read_customer_serialization_data(); + + retval = snprintf(buf, PAGE_SIZE, "%s\n", fwu->read_config_buf); + + return retval; +} + + +static ssize_t fwu_sysfs_write_guest_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + if (sscanf(buf, "%u", &input) != 1) { + retval = -EINVAL; + goto exit; + } + + if (input != 1) { + retval = -EINVAL; + goto exit; + } + + if (fwu->in_ub_mode) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: In microbootloader mode\n", + __func__); + retval = -EINVAL; + goto exit; + } + + if (!fwu->ext_data_source) { + retval = -EINVAL; + goto exit; + } else { + fwu->image = fwu->ext_data_source; + } + + retval = fwu_start_write_guest_code(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write guest code\n", + __func__); + goto exit; + } + + retval = count; + +exit: + kfree(fwu->ext_data_source); + fwu->ext_data_source = NULL; + fwu->image = NULL; + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval; +} + +static ssize_t fwu_sysfs_read_panel_color_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + + if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '1')) + ret = scnprintf(buf, PAGE_SIZE, "0x31 WHITE\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '2')) + ret = scnprintf(buf, PAGE_SIZE, "0x32 BLACK\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '3')) + ret = scnprintf(buf, PAGE_SIZE, "0x33 RED\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '4')) + ret = scnprintf(buf, PAGE_SIZE, "0x34 YELLOW\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '5')) + ret = scnprintf(buf, PAGE_SIZE, "0x35 GREEN\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '6')) + ret = scnprintf(buf, PAGE_SIZE, "0x36 PINK\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '7')) + ret = scnprintf(buf, PAGE_SIZE, "0x37 PURPLE\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '8')) + ret = scnprintf(buf, PAGE_SIZE, "0x38 GOLDEN\n"); + else if ((tp_lockdown_info[4] == '3') && (tp_lockdown_info[5] == '9')) + ret = scnprintf(buf, PAGE_SIZE, "0x39 SLIVER\n"); + else if ((tp_lockdown_info[4] == '4') && (tp_lockdown_info[5] == '0')) + ret = scnprintf(buf, PAGE_SIZE, "0x40 GRAY\n"); + else if ((tp_lockdown_info[4] == '4') && (tp_lockdown_info[5] == '1')) + ret = scnprintf(buf, PAGE_SIZE, "0x41 SLIVER BLUE\n"); + else if ((tp_lockdown_info[4] == '4') && (tp_lockdown_info[5] == '2')) + ret = scnprintf(buf, PAGE_SIZE, "0x42 CORAL BLUE\n"); + + return ret; +} + +#ifdef SYNA_TDDI +static ssize_t fwu_sysfs_read_lockdown_code_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned short lockdown_data_size; + unsigned char *lockdown_data; + char ld_val[2]; + int retval = 0; + int i = 0; + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + lockdown_data_size = fwu->blkcount.tddi_lockdown_data * fwu->block_size; + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) { + mutex_unlock(&fwu_sysfs_mutex_lansi); + return -ENOMEM; + } + + if (get_tddi_lockdown_data_lansi(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex_lansi); + return -EINVAL; + } + + for (i = 0; i < lockdown_data_size; i++) { + retval += snprintf(ld_val, PAGE_SIZE, "%02x", + *(lockdown_data + i)); + strlcat(buf, ld_val, lockdown_data_size); + } + *(buf + retval) = '\n'; + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex_lansi); + return retval + 1; +} + +static ssize_t fwu_sysfs_write_lockdown_code_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned short lockdown_data_size = (count - 1) / 2; + unsigned char *lockdown_data; + unsigned char temp[2]; + int ld_val; + int i = 0; + + for (i = 0; i < (count - 1); i++) { + if (((*buf >= '0') && (*buf <= '9')) || + (('a' < *buf) && (*buf > 'f')) || + (('A' < *buf) && (*buf > 'F'))) + continue; + else + return -EINVAL; + } + + if (count % 2 != 1) + return -EINVAL; + + lockdown_data = kzalloc(lockdown_data_size, GFP_KERNEL); + if (!lockdown_data) + return -ENOMEM; + + for (i = 0; i < lockdown_data_size; i++) { + memcpy(temp, (buf + 2 * i), sizeof(temp)); + if (sscanf(temp, "%02x", &ld_val) == 1) + *(lockdown_data + i) = ld_val & 0xff; + } + + if (!mutex_trylock(&fwu_sysfs_mutex_lansi)) + return -EBUSY; + + if (set_tddi_lockdown_data_lansi(lockdown_data, lockdown_data_size) < 0) { + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex_lansi); + return -EINVAL; + } + kfree(lockdown_data); + mutex_unlock(&fwu_sysfs_mutex_lansi); + return count; +} +#endif +static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!fwu) + return; + + if (fwu->intr_mask & intr_mask) + fwu_read_flash_status(); + + return; +} + +static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char attr_count; + struct pdt_properties pdt_props; + +#if defined(SYNAPTICS_LOCK_DOWN_INFO) + unsigned char lockdown[20] = {0}; +#endif + if (fwu) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + fwu = kzalloc(sizeof(*fwu), GFP_KERNEL); + if (!fwu) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for fwu\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + fwu->image_name = kzalloc(MAX_IMAGE_NAME_LEN, GFP_KERNEL); + if (!fwu->image_name) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for image name\n", + __func__); + retval = -ENOMEM; + goto exit_free_fwu; + } + + fwu->rmi4_data = rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + PDT_PROPS, + pdt_props.data, + sizeof(pdt_props.data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read PDT properties, assuming 0x00\n", + __func__); + } else if (pdt_props.has_bsr) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Reflash for LTS not currently supported\n", + __func__); + retval = -ENODEV; + goto exit_free_mem; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + if (!fwu->in_ub_mode) { + retval = fwu_read_f34_queries(); + if (retval < 0) + goto exit_free_mem; + + retval = fwu_get_device_config_id(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read device config ID\n", + __func__); + goto exit_free_mem; + } + } + + fwu->force_update = FORCE_UPDATE; + fwu->do_lockdown = DO_LOCKDOWN; + fwu->initialized = true; + +#ifdef DO_STARTUP_FW_UPDATE + +#ifdef SYNAPTICS_ESD_CHECK + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue"); + INIT_WORK(&fwu->fwu_work, fwu_startup_fw_update_work); + queue_work(fwu->fwu_workqueue, + &fwu->fwu_work); + + #ifdef SYNAPTICS_ESD_CHECK + printk("SYNAPTICS_ESD_CHECK is on\n"); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif +#endif + +printk("before get_tddi_lockdown_data_lansi"); + + if (get_tddi_lockdown_data_lansi(lockdown, 20) < 0){ + printk("read lockdown fail\n"); + } + printk("lockdown info =%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + sprintf(tp_lockdown_info, "%02x%02x%02x%02x%02x%02x%02x%02x\n", lockdown[4], lockdown[5], lockdown[6], lockdown[7], lockdown[8], lockdown[9], lockdown[10], lockdown[11]); + + ctp_lockdown_status_proc = proc_create(CTP_PROC_LOCKDOWN_FILE, 0644, NULL, &ctp_lockdown_proc_fops); + if (ctp_lockdown_status_proc == NULL) + { + printk("tpd, create_proc_entry ctp_lockdown_status_proc failed\n"); + } + + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) { + retval = fwu_f51_force_data_init(); + if (retval < 0) + goto exit_free_mem; + } +#endif + + if (ENABLE_SYS_REFLASH == false) + return 0; + + retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, + &dev_attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_free_mem; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto exit_remove_attrs; + } + } + + return 0; + +exit_remove_attrs: + for (attr_count--; attr_count >= 0; attr_count--) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit_free_mem: + kfree(fwu->image_name); + +exit_free_fwu: + kfree(fwu); + fwu = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + + if (!fwu) + goto exit; + +#ifdef DO_STARTUP_FW_UPDATE + cancel_work_sync(&fwu->fwu_work); + flush_workqueue(fwu->fwu_workqueue); + destroy_workqueue(fwu->fwu_workqueue); +#endif + +#ifdef F51_DISCRETE_FORCE + kfree(fwu->cal_data); +#endif + kfree(fwu->read_config_buf); + kfree(fwu->image_name); + kfree(fwu); + fwu = NULL; + + if (ENABLE_SYS_REFLASH == false) + goto exit; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + sysfs_remove_file(&rmi4_data->input_dev->dev.kobj, + &attrs[attr_count].attr); + } + + sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data); + +exit: + complete(&fwu_remove_complete_lansi); + + return; +} + +static void synaptics_rmi4_fwu_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!fwu) { + synaptics_rmi4_fwu_init(rmi4_data); + return; + } + + retval = fwu_scan_pdt(); + if (retval < 0) + return; + + if (!fwu->in_ub_mode) + fwu_read_f34_queries(); + +#ifdef F51_DISCRETE_FORCE + fwu_read_flash_status(); + if (!fwu->in_bl_mode) + fwu_f51_force_data_init(); +#endif + + return; +} + +static struct synaptics_rmi4_exp_fn fwu_module = { + .fn_type = RMI_FW_UPDATER, + .init = synaptics_rmi4_fwu_init, + .remove = synaptics_rmi4_fwu_remove, + .reset = synaptics_rmi4_fwu_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_fwu_attn, +}; + +static int __init rmi4_fw_update_module_init(void) +{ + synaptics_rmi4_new_function_lansi(&fwu_module, true); + + return 0; +} + +static void __exit rmi4_fw_update_module_exit(void) +{ + synaptics_rmi4_new_function_lansi(&fwu_module, false); + + wait_for_completion(&fwu_remove_complete_lansi); + + return; +} + +module_init(rmi4_fw_update_module_init); +module_exit(rmi4_fw_update_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX FW Update Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_i2c.c b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_i2c.c new file mode 100755 index 0000000000000..e66529f5dcfdb --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_i2c.c @@ -0,0 +1,651 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "synaptics_dsx_core.h" + +#define SYN_I2C_RETRY_TIMES 10 + +/* +#define I2C_BURST_LIMIT 255 +*/ +/* +#define XFER_MSGS_LIMIT 8 +*/ + +static unsigned char *wr_buf; + +static struct synaptics_dsx_hw_interface hw_if; + +static struct platform_device *synaptics_dsx_i2c_device; + +#ifdef CONFIG_OF +static int parse_dt(struct device *dev, struct synaptics_dsx_board_data *bdata) +{ + int retval; + u32 value; + const char *name; + struct property *prop; + struct device_node *np = dev->of_node; + + bdata->irq_gpio = of_get_named_gpio_flags(np, + "synaptics,irq-gpio", 0, + (enum of_gpio_flags *)&bdata->irq_flags); + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,rst-gpio", 0, + NULL); +printk("reset gpio : %d\n", bdata->reset_gpio); + retval = of_property_read_u32(np, "synaptics,irq-on-state", + &value); + if (retval < 0) + bdata->irq_on_state = 0; + else + bdata->irq_on_state = value; + + retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name); + if (retval < 0) + bdata->pwr_reg_name = NULL; + else + bdata->pwr_reg_name = name; + + retval = of_property_read_string(np, "synaptics,bus-reg-name", &name); + if (retval < 0) + bdata->bus_reg_name = NULL; + else + bdata->bus_reg_name = name; + + prop = of_find_property(np, "synaptics,power-gpio", NULL); + if (prop && prop->length) { + bdata->power_gpio = of_get_named_gpio_flags(np, + "synaptics,power-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,power-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-on-state property\n", + __func__); + return retval; + } else { + bdata->power_on_state = value; + } + } else { + bdata->power_gpio = -1; + } + + prop = of_find_property(np, "synaptics,power-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,power-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,power-delay-ms property\n", + __func__); + return retval; + } else { + bdata->power_delay_ms = value; + } + } else { + bdata->power_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,reset-gpio", NULL); + if (prop && prop->length) { + bdata->reset_gpio = of_get_named_gpio_flags(np, + "synaptics,reset-gpio", 0, NULL); + retval = of_property_read_u32(np, "synaptics,reset-on-state", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-on-state property\n", + __func__); + return retval; + } else { + bdata->reset_on_state = value; + } + retval = of_property_read_u32(np, "synaptics,reset-active-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-active-ms property\n", + __func__); + return retval; + } else { + bdata->reset_active_ms = value; + } + } else { + bdata->reset_gpio = -1; + } + + prop = of_find_property(np, "synaptics,reset-delay-ms", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,reset-delay-ms", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,reset-delay-ms property\n", + __func__); + return retval; + } else { + bdata->reset_delay_ms = value; + } + } else { + bdata->reset_delay_ms = 0; + } + + prop = of_find_property(np, "synaptics,max-y-for-2d", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,max-y-for-2d", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,max-y-for-2d property\n", + __func__); + return retval; + } else { + bdata->max_y_for_2d = value; + } + } else { + bdata->max_y_for_2d = -1; + } + + prop = of_find_property(np, "synaptics,swap-axes", NULL); + bdata->swap_axes = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,x-flip", NULL); + bdata->x_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,y-flip", NULL); + bdata->y_flip = prop > 0 ? true : false; + + prop = of_find_property(np, "synaptics,ub-i2c-addr", NULL); + if (prop && prop->length) { + retval = of_property_read_u32(np, "synaptics,ub-i2c-addr", + &value); + if (retval < 0) { + dev_err(dev, "%s: Unable to read synaptics,ub-i2c-addr property\n", + __func__); + return retval; + } else { + bdata->ub_i2c_addr = (unsigned short)value; + } + } else { + bdata->ub_i2c_addr = -1; + } + + prop = of_find_property(np, "synaptics,cap-button-codes", NULL); + if (prop && prop->length) { + bdata->cap_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->cap_button_map->map) + return -ENOMEM; + bdata->cap_button_map->nbuttons = prop->length / sizeof(u32); + retval = of_property_read_u32_array(np, + "synaptics,cap-button-codes", + bdata->cap_button_map->map, + bdata->cap_button_map->nbuttons); + if (retval < 0) { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + } else { + bdata->cap_button_map->nbuttons = 0; + bdata->cap_button_map->map = NULL; + } + + prop = of_find_property(np, "synaptics,vir-button-codes", NULL); + if (prop && prop->length) { + bdata->vir_button_map->map = devm_kzalloc(dev, + prop->length, + GFP_KERNEL); + if (!bdata->vir_button_map->map) + return -ENOMEM; + bdata->vir_button_map->nbuttons = prop->length / sizeof(u32); + bdata->vir_button_map->nbuttons /= 5; + retval = of_property_read_u32_array(np, + "synaptics,vir-button-codes", + bdata->vir_button_map->map, + bdata->vir_button_map->nbuttons * 5); + if (retval < 0) { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + } else { + bdata->vir_button_map->nbuttons = 0; + bdata->vir_button_map->map = NULL; + } + + return 0; +} +#endif + +static int synaptics_rmi4_i2c_alloc_buf(struct synaptics_rmi4_data *rmi4_data, + unsigned int count) +{ + static unsigned int buf_size; + + if (count > buf_size) { + if (buf_size) + kfree(wr_buf); + wr_buf = kzalloc(count, GFP_KERNEL); + if (!wr_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buffer\n", + __func__); + buf_size = 0; + return -ENOMEM; + } + buf_size = count; + } + + return 0; +} + +static void synaptics_rmi4_i2c_check_addr(struct synaptics_rmi4_data *rmi4_data, + struct i2c_client *i2c) +{ + if (hw_if.board_data->ub_i2c_addr == -1) + return; + + if (hw_if.board_data->i2c_addr == i2c->addr) + hw_if.board_data->i2c_addr = hw_if.board_data->ub_i2c_addr; + else + hw_if.board_data->i2c_addr = i2c->addr; + + return; +} + +static int synaptics_rmi4_i2c_set_page(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr) +{ + int retval; + unsigned char retry; + unsigned char buf[PAGE_SELECT_LEN]; + unsigned char page; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = PAGE_SELECT_LEN; + msg[0].buf = buf; + + page = ((addr >> 8) & MASK_8BIT); + buf[0] = MASK_8BIT; + buf[1] = page; + + if (page != rmi4_data->current_page) { + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(i2c->adapter, msg, 1) == 1) { + rmi4_data->current_page = page; + retval = PAGE_SELECT_LEN; + break; + } + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + msg[0].addr = hw_if.board_data->i2c_addr; + } + } + } else { + retval = PAGE_SELECT_LEN; + } + + return retval; +} + +static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + unsigned char buf; +#ifdef I2C_BURST_LIMIT + unsigned int ii; + unsigned int rd_msgs = ((length - 1) / I2C_BURST_LIMIT) + 1; +#else + unsigned int rd_msgs = 1; +#endif + unsigned char index = 0; + unsigned char xfer_msgs; + unsigned char remaining_msgs; + unsigned short i2c_addr; + unsigned short data_offset = 0; + unsigned int remaining_length = length; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_adapter *adap = i2c->adapter; + struct i2c_msg msg[rd_msgs + 1]; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + retval = -EIO; + goto exit; + } + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &buf; + +#ifdef I2C_BURST_LIMIT + for (ii = 0; ii < (rd_msgs - 1); ii++) { + msg[ii + 1].addr = hw_if.board_data->i2c_addr; + msg[ii + 1].flags = I2C_M_RD; + msg[ii + 1].len = I2C_BURST_LIMIT; + msg[ii + 1].buf = &data[data_offset]; + data_offset += I2C_BURST_LIMIT; + remaining_length -= I2C_BURST_LIMIT; + } +#endif + + msg[rd_msgs].addr = hw_if.board_data->i2c_addr; + msg[rd_msgs].flags = I2C_M_RD; + msg[rd_msgs].len = (unsigned short)remaining_length; + msg[rd_msgs].buf = &data[data_offset]; + + buf = addr & MASK_8BIT; + + remaining_msgs = rd_msgs + 1; + + while (remaining_msgs) { +#ifdef XFER_MSGS_LIMIT + if (remaining_msgs > XFER_MSGS_LIMIT) + xfer_msgs = XFER_MSGS_LIMIT; + else + xfer_msgs = remaining_msgs; +#else + xfer_msgs = remaining_msgs; +#endif + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + retval = i2c_transfer(adap, &msg[index], xfer_msgs); + if (retval == xfer_msgs) + break; + + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + i2c_addr = hw_if.board_data->i2c_addr; + msg[0].addr = i2c_addr; +#ifdef I2C_BURST_LIMIT + for (ii = 0; ii < (rd_msgs - 1); ii++) + msg[ii + 1].addr = i2c_addr; +#endif + msg[rd_msgs].addr = i2c_addr; + } + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C read over retry limit\n", + __func__); + retval = -EIO; + goto exit; + } + + remaining_msgs -= xfer_msgs; + index += xfer_msgs; + } + + retval = length; + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, + unsigned short addr, unsigned char *data, unsigned int length) +{ + int retval; + unsigned char retry; + struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); + struct i2c_msg msg[1]; + + retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1); + if (retval < 0) + return retval; + + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + + retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); + if (retval != PAGE_SELECT_LEN) { + retval = -EIO; + goto exit; + } + + msg[0].addr = hw_if.board_data->i2c_addr; + msg[0].flags = 0; + msg[0].len = (unsigned short)(length + 1); + msg[0].buf = wr_buf; + + wr_buf[0] = addr & MASK_8BIT; + retval = secure_memcpy(&wr_buf[1], length, &data[0], length, length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy data\n", + __func__); + goto exit; + } + + for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) { + if (i2c_transfer(i2c->adapter, msg, 1) == 1) { + retval = length; + break; + } + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C retry %d\n", + __func__, retry + 1); + msleep(20); + + if (retry == SYN_I2C_RETRY_TIMES / 2) { + synaptics_rmi4_i2c_check_addr(rmi4_data, i2c); + msg[0].addr = hw_if.board_data->i2c_addr; + } + } + + if (retry == SYN_I2C_RETRY_TIMES) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: I2C write over retry limit\n", + __func__); + retval = -EIO; + } + +exit: + mutex_unlock(&rmi4_data->rmi4_io_ctrl_mutex); + + return retval; +} + +static struct synaptics_dsx_bus_access bus_access = { + .type = BUS_I2C, + .read = synaptics_rmi4_i2c_read, + .write = synaptics_rmi4_i2c_write, +}; + +static void synaptics_rmi4_i2c_dev_release(struct device *dev) +{ + kfree(synaptics_dsx_i2c_device); + + return; +} + +static int synaptics_rmi4_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int retval; + + pr_err("yinchenyang in lansi td4310 i2c probe\n"); + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "%s: SMBus byte data commands not supported by host\n", + __func__); + return -EIO; + } + + synaptics_dsx_i2c_device = kzalloc( + sizeof(struct platform_device), + GFP_KERNEL); + if (!synaptics_dsx_i2c_device) { + dev_err(&client->dev, + "%s: Failed to allocate memory for synaptics_dsx_i2c_device\n", + __func__); + return -ENOMEM; + } + +#ifdef CONFIG_OF + if (client->dev.of_node) { + hw_if.board_data = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_board_data), + GFP_KERNEL); + if (!hw_if.board_data) { + dev_err(&client->dev, + "%s: Failed to allocate memory for board data\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->cap_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->cap_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for 0D button map\n", + __func__); + return -ENOMEM; + } + hw_if.board_data->vir_button_map = devm_kzalloc(&client->dev, + sizeof(struct synaptics_dsx_button_map), + GFP_KERNEL); + if (!hw_if.board_data->vir_button_map) { + dev_err(&client->dev, + "%s: Failed to allocate memory for virtual button map\n", + __func__); + return -ENOMEM; + } + parse_dt(&client->dev, hw_if.board_data); + } +#else + hw_if.board_data = client->dev.platform_data; +#endif + + hw_if.bus_access = &bus_access; + hw_if.board_data->i2c_addr = client->addr; + + synaptics_dsx_i2c_device->name = PLATFORM_DRIVER_NAME; + synaptics_dsx_i2c_device->id = 0; + synaptics_dsx_i2c_device->num_resources = 0; + synaptics_dsx_i2c_device->dev.parent = &client->dev; + synaptics_dsx_i2c_device->dev.platform_data = &hw_if; + synaptics_dsx_i2c_device->dev.release = synaptics_rmi4_i2c_dev_release; + + retval = platform_device_register(synaptics_dsx_i2c_device); + if (retval) { + dev_err(&client->dev, + "%s: Failed to register platform device\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int synaptics_rmi4_i2c_remove(struct i2c_client *client) +{ + platform_device_unregister(synaptics_dsx_i2c_device); + + return 0; +} + +static const struct i2c_device_id synaptics_rmi4_id_table[] = { + {I2C_DRIVER_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table); + +#ifdef CONFIG_OF +static struct of_device_id synaptics_rmi4_of_match_table[] = { + { + .compatible = "synaptics_lansi,dsx-i2c", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, synaptics_rmi4_of_match_table); +#else +#define synaptics_rmi4_of_match_table NULL +#endif + +static struct i2c_driver synaptics_rmi4_i2c_driver = { + .driver = { + .name = I2C_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = synaptics_rmi4_of_match_table, + }, + .probe = synaptics_rmi4_i2c_probe, + .remove = synaptics_rmi4_i2c_remove, + .id_table = synaptics_rmi4_id_table, +}; + +int synaptics_rmi4_bus_init_lansi(void) +{ + return i2c_add_driver(&synaptics_rmi4_i2c_driver); +} +EXPORT_SYMBOL(synaptics_rmi4_bus_init_lansi); + +void synaptics_rmi4_bus_exit_lansi(void) +{ + kfree(wr_buf); + + i2c_del_driver(&synaptics_rmi4_i2c_driver); + + return; +} +EXPORT_SYMBOL(synaptics_rmi4_bus_exit_lansi); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX I2C Bus Support Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_rmi_dev.c new file mode 100755 index 0000000000000..d692667104017 --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_rmi_dev.c @@ -0,0 +1,1065 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "synaptics_dsx_core.h" + +#define CHAR_DEVICE_NAME "rmi" +#define DEVICE_CLASS_NAME "rmidev" +#define SYSFS_FOLDER_NAME "rmidev" +#define DEV_NUMBER 1 +#define REG_ADDR_LIMIT 0xFFFF + +#define RMIDEV_MAJOR_NUM 0 + +static ssize_t rmidev_sysfs_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t rmidev_sysfs_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static ssize_t rmidev_sysfs_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_attn_state_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_pid_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_term_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +static ssize_t rmidev_sysfs_concurrent_show(struct device *dev, + struct device_attribute *attr, char *buf); + +static ssize_t rmidev_sysfs_concurrent_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); + +struct rmidev_handle { + dev_t dev_no; + pid_t pid; + unsigned char intr_mask; + unsigned char *tmpbuf; + unsigned int tmpbuf_size; + struct device dev; + struct synaptics_rmi4_data *rmi4_data; + struct kobject *sysfs_dir; + struct siginfo interrupt_signal; + struct siginfo terminate_signal; + struct task_struct *task; + void *data; + bool concurrent; +}; + +struct rmidev_data { + int ref_count; + struct cdev main_dev; + struct class *device_class; + struct mutex file_mutex; + struct rmidev_handle *rmi_dev; +}; + +static struct bin_attribute attr_data = { + .attr = { + .name = "data", + .mode = (S_IRUGO | S_IWUSR | S_IWGRP), + }, + .size = 0, + .read = rmidev_sysfs_data_show, + .write = rmidev_sysfs_data_store, +}; + +static struct device_attribute attrs[] = { + __ATTR(open, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_open_store), + __ATTR(release, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_release_store), + __ATTR(attn_state, S_IRUGO, + rmidev_sysfs_attn_state_show, + synaptics_rmi4_store_error), + __ATTR(pid, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_pid_show, + rmidev_sysfs_pid_store), + __ATTR(term, (S_IWUSR | S_IWGRP), + synaptics_rmi4_show_error, + rmidev_sysfs_term_store), + __ATTR(intr_mask, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_intr_mask_show, + rmidev_sysfs_intr_mask_store), + __ATTR(concurrent, (S_IRUGO | S_IWUSR | S_IWGRP), + rmidev_sysfs_concurrent_show, + rmidev_sysfs_concurrent_store), +}; + +static int rmidev_major_num = RMIDEV_MAJOR_NUM; + +static struct class *rmidev_device_class; + +static struct rmidev_handle *rmidev; + +DECLARE_COMPLETION(rmidev_remove_complete_lansi); + +static irqreturn_t rmidev_sysfs_irq(int irq, void *data) +{ + struct synaptics_rmi4_data *rmi4_data = data; + + sysfs_notify(&rmi4_data->input_dev->dev.kobj, + SYSFS_FOLDER_NAME, "attn_state"); + + return IRQ_HANDLED; +} + +static int rmidev_sysfs_irq_enable(struct synaptics_rmi4_data *rmi4_data, + bool enable) +{ + int retval = 0; + unsigned char intr_status[MAX_INTR_REGISTERS]; + unsigned long irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT; + + mutex_lock(&(rmi4_data->rmi4_irq_enable_mutex)); + + if (enable) { + if (rmi4_data->irq_enabled) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Interrupt already enabled\n", + __func__); + goto exit; + } + + /* Clear interrupts first */ + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_data_base_addr + 1, + intr_status, + rmi4_data->num_of_intr_regs); + if (retval < 0) + goto exit; + + retval = request_threaded_irq(rmi4_data->irq, NULL, + rmidev_sysfs_irq, irq_flags, + PLATFORM_DRIVER_NAME, rmi4_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create irq thread\n", + __func__); + goto exit; + } + + rmi4_data->irq_enabled = true; + } else { + if (rmi4_data->irq_enabled) { + disable_irq(rmi4_data->irq); + free_irq(rmi4_data->irq, rmi4_data); + rmi4_data->irq_enabled = false; + } + } + +exit: + mutex_unlock(&(rmi4_data->rmi4_irq_enable_mutex)); + + return retval; +} + +static ssize_t rmidev_sysfs_data_show(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned char intr_status = 0; + unsigned int length = (unsigned int)count; + unsigned short address = (unsigned short)pos; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (length > (REG_ADDR_LIMIT - address)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Out of register map limit\n", + __func__); + return -EINVAL; + } + + if (length) { + retval = synaptics_rmi4_reg_read(rmi4_data, + address, + (unsigned char *)buf, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data\n", + __func__); + return retval; + } + } else { + return -EINVAL; + } + + if (!rmidev->concurrent) + goto exit; + + if (address != rmi4_data->f01_data_base_addr) + goto exit; + + if (length <= 1) + goto exit; + + intr_status = buf[1]; + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & intr_status) { + rmi4_data->report_touch(rmi4_data, + fhandler); + } + } + } + } + +exit: + return length; +} + +static ssize_t rmidev_sysfs_data_store(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned int length = (unsigned int)count; + unsigned short address = (unsigned short)pos; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (length > (REG_ADDR_LIMIT - address)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Out of register map limit\n", + __func__); + return -EINVAL; + } + + if (length) { + retval = synaptics_rmi4_reg_write(rmi4_data, + address, + (unsigned char *)buf, + length); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write data\n", + __func__); + return retval; + } + } else { + return -EINVAL; + } + + return length; +} + +static ssize_t rmidev_sysfs_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + rmi4_data->irq_enable(rmi4_data, false, false); + rmidev_sysfs_irq_enable(rmi4_data, true); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Attention interrupt disabled\n", + __func__); + + return count; +} + +static ssize_t rmidev_sysfs_release_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + rmidev_sysfs_irq_enable(rmi4_data, false); + + rmi4_data->reset_device(rmi4_data, false); + + rmi4_data->stay_awake = false; + + return count; +} + +static ssize_t rmidev_sysfs_attn_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int attn_state; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + attn_state = gpio_get_value(bdata->irq_gpio); + + return snprintf(buf, PAGE_SIZE, "%u\n", attn_state); +} + +static ssize_t rmidev_sysfs_pid_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", rmidev->pid); +} + +static ssize_t rmidev_sysfs_pid_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->pid = input; + + if (rmidev->pid) { + rmidev->task = pid_task(find_vpid(rmidev->pid), PIDTYPE_PID); + if (!rmidev->task) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to locate PID of data logging tool\n", + __func__); + return -EINVAL; + } + } + + return count; +} + +static ssize_t rmidev_sysfs_term_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + if (input != 1) + return -EINVAL; + + if (rmidev->pid) + send_sig_info(SIGTERM, &rmidev->terminate_signal, rmidev->task); + + return count; +} + +static ssize_t rmidev_sysfs_intr_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%02x\n", rmidev->intr_mask); +} + +static ssize_t rmidev_sysfs_intr_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->intr_mask = (unsigned char)input; + + return count; +} + +static ssize_t rmidev_sysfs_concurrent_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", rmidev->concurrent); +} + +static ssize_t rmidev_sysfs_concurrent_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + + if (sscanf(buf, "%u", &input) != 1) + return -EINVAL; + + rmidev->concurrent = input > 0 ? true : false; + + return count; +} + +static int rmidev_allocate_buffer(int count) +{ + if (count + 1 > rmidev->tmpbuf_size) { + if (rmidev->tmpbuf_size) + kfree(rmidev->tmpbuf); + rmidev->tmpbuf = kzalloc(count + 1, GFP_KERNEL); + if (!rmidev->tmpbuf) { + dev_err(rmidev->rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for buffer\n", + __func__); + rmidev->tmpbuf_size = 0; + return -ENOMEM; + } + rmidev->tmpbuf_size = count + 1; + } + + return 0; +} + +/* + * rmidev_llseek - set register address to access for RMI device + * + * @filp: pointer to file structure + * @off: + * if whence == SEEK_SET, + * off: 16-bit RMI register address + * if whence == SEEK_CUR, + * off: offset from current position + * if whence == SEEK_END, + * off: offset from end position (0xFFFF) + * @whence: SEEK_SET, SEEK_CUR, or SEEK_END + */ +static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence) +{ + loff_t newpos; + struct rmidev_data *dev_data = filp->private_data; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + mutex_lock(&(dev_data->file_mutex)); + + switch (whence) { + case SEEK_SET: + newpos = off; + break; + case SEEK_CUR: + newpos = filp->f_pos + off; + break; + case SEEK_END: + newpos = REG_ADDR_LIMIT + off; + break; + default: + newpos = -EINVAL; + goto clean_up; + } + + if (newpos < 0 || newpos > REG_ADDR_LIMIT) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: New position 0x%04x is invalid\n", + __func__, (unsigned int)newpos); + newpos = -EINVAL; + goto clean_up; + } + + filp->f_pos = newpos; + +clean_up: + mutex_unlock(&(dev_data->file_mutex)); + + return newpos; +} + +/* + * rmidev_read: read register data from RMI device + * + * @filp: pointer to file structure + * @buf: pointer to user space buffer + * @count: number of bytes to read + * @f_pos: starting RMI register address + */ +static ssize_t rmidev_read(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t retval; + unsigned char intr_status = 0; + unsigned short address; + struct rmidev_data *dev_data = filp->private_data; + struct synaptics_rmi4_fn *fhandler; + struct synaptics_rmi4_device_info *rmi; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + rmi = &(rmi4_data->rmi4_mod_info); + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + if (count == 0) + return 0; + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + + address = (unsigned short)(*f_pos); + + mutex_lock(&(dev_data->file_mutex)); + + rmidev_allocate_buffer(count); + + retval = synaptics_rmi4_reg_read(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, + count); + if (retval < 0) + goto clean_up; + + if (copy_to_user(buf, rmidev->tmpbuf, count)) + retval = -EFAULT; + else + *f_pos += retval; + + if (!rmidev->concurrent) + goto clean_up; + + if (address != rmi4_data->f01_data_base_addr) + goto clean_up; + + if (count <= 1) + goto clean_up; + + intr_status = rmidev->tmpbuf[1]; + + if (!list_empty(&rmi->support_fn_list)) { + list_for_each_entry(fhandler, &rmi->support_fn_list, link) { + if (fhandler->num_of_data_sources) { + if (fhandler->intr_mask & intr_status) { + rmi4_data->report_touch(rmi4_data, + fhandler); + } + } + } + } + +clean_up: + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +/* + * rmidev_write: write register data to RMI device + * + * @filp: pointer to file structure + * @buf: pointer to user space buffer + * @count: number of bytes to write + * @f_pos: starting RMI register address + */ +static ssize_t rmidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + ssize_t retval; + struct rmidev_data *dev_data = filp->private_data; + + if (IS_ERR(dev_data)) { + pr_err("%s: Pointer of char device data is invalid", __func__); + return -EBADF; + } + + if (count == 0) + return 0; + + if (count > (REG_ADDR_LIMIT - *f_pos)) + count = REG_ADDR_LIMIT - *f_pos; + + mutex_lock(&(dev_data->file_mutex)); + + rmidev_allocate_buffer(count); + + if (copy_from_user(rmidev->tmpbuf, buf, count)) + return -EFAULT; + + retval = synaptics_rmi4_reg_write(rmidev->rmi4_data, + *f_pos, + rmidev->tmpbuf, + count); + if (retval >= 0) + *f_pos += retval; + + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +static int rmidev_open(struct inode *inp, struct file *filp) +{ + int retval = 0; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + struct rmidev_data *dev_data = + container_of(inp->i_cdev, struct rmidev_data, main_dev); + + if (!dev_data) + return -EACCES; + + if (rmi4_data->sensor_sleep) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Sensor sleeping\n", + __func__); + return -ENODEV; + } + + rmi4_data->stay_awake = true; + + filp->private_data = dev_data; + + mutex_lock(&(dev_data->file_mutex)); + + rmi4_data->irq_enable(rmi4_data, false, false); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Attention interrupt disabled\n", + __func__); + + if (dev_data->ref_count < 1) + dev_data->ref_count++; + else + retval = -EACCES; + + mutex_unlock(&(dev_data->file_mutex)); + + return retval; +} + +static int rmidev_release(struct inode *inp, struct file *filp) +{ + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + struct rmidev_data *dev_data = + container_of(inp->i_cdev, struct rmidev_data, main_dev); + + if (!dev_data) + return -EACCES; + + mutex_lock(&(dev_data->file_mutex)); + + dev_data->ref_count--; + if (dev_data->ref_count < 0) + dev_data->ref_count = 0; + + rmi4_data->reset_device(rmi4_data, false); + + rmi4_data->stay_awake = false; + + mutex_unlock(&(dev_data->file_mutex)); + + return 0; +} + +static const struct file_operations rmidev_fops = { + .owner = THIS_MODULE, + .llseek = rmidev_llseek, + .read = rmidev_read, + .write = rmidev_write, + .open = rmidev_open, + .release = rmidev_release, +}; + +static void rmidev_device_cleanup(struct rmidev_data *dev_data) +{ + dev_t devno; + struct synaptics_rmi4_data *rmi4_data = rmidev->rmi4_data; + + if (dev_data) { + devno = dev_data->main_dev.dev; + + if (dev_data->device_class) + device_destroy(dev_data->device_class, devno); + + cdev_del(&dev_data->main_dev); + + unregister_chrdev_region(devno, 1); + + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: rmidev device removed\n", + __func__); + } + + return; +} + +static char *rmi_char_devnode(struct device *dev, umode_t *mode) +{ + if (!mode) + return NULL; + + *mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + + return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev)); +} + +static int rmidev_create_device_class(void) +{ + if (rmidev_device_class != NULL) + return 0; + + rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME); + + if (IS_ERR(rmidev_device_class)) { + pr_err("%s: Failed to create /dev/%s\n", + __func__, CHAR_DEVICE_NAME); + return -ENODEV; + } + + rmidev_device_class->devnode = rmi_char_devnode; + + return 0; +} + +static void rmidev_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!rmidev) + return; + + if (rmidev->pid && (rmidev->intr_mask & intr_mask)) + send_sig_info(SIGIO, &rmidev->interrupt_signal, rmidev->task); + + return; +} + +static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + dev_t dev_no; + unsigned char attr_count; + struct rmidev_data *dev_data; + struct device *device_ptr; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (rmidev) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + rmidev = kzalloc(sizeof(*rmidev), GFP_KERNEL); + if (!rmidev) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for rmidev\n", + __func__); + retval = -ENOMEM; + goto err_rmidev; + } + + rmidev->rmi4_data = rmi4_data; + + memset(&rmidev->interrupt_signal, 0, sizeof(rmidev->interrupt_signal)); + rmidev->interrupt_signal.si_signo = SIGIO; + rmidev->interrupt_signal.si_code = SI_USER; + + memset(&rmidev->terminate_signal, 0, sizeof(rmidev->terminate_signal)); + rmidev->terminate_signal.si_signo = SIGTERM; + rmidev->terminate_signal.si_code = SI_USER; + + retval = rmidev_create_device_class(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create device class\n", + __func__); + goto err_device_class; + } + + if (rmidev_major_num) { + dev_no = MKDEV(rmidev_major_num, DEV_NUMBER); + retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME); + } else { + retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to allocate char device region\n", + __func__); + goto err_device_region; + } + + rmidev_major_num = MAJOR(dev_no); + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Major number of rmidev = %d\n", + __func__, rmidev_major_num); + } + + dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); + if (!dev_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for dev_data\n", + __func__); + retval = -ENOMEM; + goto err_dev_data; + } + + mutex_init(&dev_data->file_mutex); + dev_data->rmi_dev = rmidev; + rmidev->data = dev_data; + + cdev_init(&dev_data->main_dev, &rmidev_fops); + + retval = cdev_add(&dev_data->main_dev, dev_no, 1); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to add rmi char device\n", + __func__); + goto err_char_device; + } + + dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no)); + dev_data->device_class = rmidev_device_class; + + device_ptr = device_create(dev_data->device_class, NULL, dev_no, + NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no)); + if (IS_ERR(device_ptr)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create rmi char device\n", + __func__); + retval = -ENODEV; + goto err_char_device; + } + + retval = gpio_export(bdata->irq_gpio, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to export attention gpio\n", + __func__); + } else { + retval = gpio_export_link(&(rmi4_data->input_dev->dev), + "attn", bdata->irq_gpio); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s Failed to create gpio symlink\n", + __func__); + } else { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Exported attention gpio %d\n", + __func__, bdata->irq_gpio); + } + } + + rmidev->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!rmidev->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + retval = -ENODEV; + goto err_sysfs_dir; + } + + retval = sysfs_create_bin_file(rmidev->sysfs_dir, + &attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto err_sysfs_bin; + } + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) { + retval = sysfs_create_file(rmidev->sysfs_dir, + &attrs[attr_count].attr); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + retval = -ENODEV; + goto err_sysfs_attrs; + } + } + + return 0; + +err_sysfs_attrs: + for (attr_count--; attr_count >= 0; attr_count--) + sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); + + sysfs_remove_bin_file(rmidev->sysfs_dir, &attr_data); + +err_sysfs_bin: + kobject_put(rmidev->sysfs_dir); + +err_sysfs_dir: + sysfs_remove_link(&(rmi4_data->input_dev->dev.kobj), "attn"); + gpio_unexport(bdata->irq_gpio); + +err_char_device: + rmidev_device_cleanup(dev_data); + kfree(dev_data); + +err_dev_data: + unregister_chrdev_region(dev_no, 1); + +err_device_region: + if (rmidev_device_class != NULL) { + class_destroy(rmidev_device_class); + rmidev_device_class = NULL; + } + +err_device_class: + kfree(rmidev); + rmidev = NULL; + +err_rmidev: + return retval; +} + +static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data) +{ + unsigned char attr_count; + struct rmidev_data *dev_data; + const struct synaptics_dsx_board_data *bdata = + rmi4_data->hw_if->board_data; + + if (!rmidev) + goto exit; + + rmidev_major_num = RMIDEV_MAJOR_NUM; + + for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) + sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr); + + sysfs_remove_bin_file(rmidev->sysfs_dir, &attr_data); + + kobject_put(rmidev->sysfs_dir); + + sysfs_remove_link(&(rmi4_data->input_dev->dev.kobj), "attn"); + gpio_unexport(bdata->irq_gpio); + + dev_data = rmidev->data; + if (dev_data) { + rmidev_device_cleanup(dev_data); + kfree(dev_data); + } + + unregister_chrdev_region(rmidev->dev_no, 1); + + if (rmidev_device_class != NULL) { + class_destroy(rmidev_device_class); + rmidev_device_class = NULL; + } + + kfree(rmidev->tmpbuf); + + kfree(rmidev); + rmidev = NULL; + +exit: + complete(&rmidev_remove_complete_lansi); + + return; +} + +static struct synaptics_rmi4_exp_fn rmidev_module = { + .fn_type = RMI_DEV, + .init = rmidev_init_device, + .remove = rmidev_remove_device, + .reset = NULL, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = rmidev_attn, +}; + +static int __init rmidev_module_init(void) +{ + synaptics_rmi4_new_function_lansi(&rmidev_module, true); + + return 0; +} + +static void __exit rmidev_module_exit(void) +{ + synaptics_rmi4_new_function_lansi(&rmidev_module, false); + + wait_for_completion(&rmidev_remove_complete_lansi); + + return; +} + +module_init(rmidev_module_init); +module_exit(rmidev_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX RMI Dev Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_test_reporting.c new file mode 100755 index 0000000000000..b9b1d7a16e698 --- /dev/null +++ b/drivers/input/touchscreen/td4310_lansi_e7/synaptics_dsx_test_reporting.c @@ -0,0 +1,7638 @@ +/* + * Synaptics DSX touchscreen driver + * + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. + * + * Copyright (C) 2012 Alexandra Chin + * Copyright (C) 2012 Scott Lin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "synaptics_dsx_core.h" + +#include +#include + +#define SYSFS_FOLDER_NAME "f54" + +#define GET_REPORT_TIMEOUT_S 1 +#define CALIBRATION_TIMEOUT_S 10 +#define COMMAND_TIMEOUT_100MS 20 + +#define NO_SLEEP_OFF (0 << 2) +#define NO_SLEEP_ON (1 << 2) + +#define STATUS_IDLE 0 +#define STATUS_BUSY 1 +#define STATUS_ERROR 2 + +#define REPORT_INDEX_OFFSET 1 +#define REPORT_DATA_OFFSET 3 + +#define SENSOR_RX_MAPPING_OFFSET 1 +#define SENSOR_TX_MAPPING_OFFSET 2 + +#define COMMAND_GET_REPORT 1 +#define COMMAND_FORCE_CAL 2 +#define COMMAND_FORCE_UPDATE 4 + +#define CONTROL_NO_AUTO_CAL 1 + +#define CONTROL_0_SIZE 1 +#define CONTROL_1_SIZE 1 +#define CONTROL_2_SIZE 2 +#define CONTROL_3_SIZE 1 +#define CONTROL_4_6_SIZE 3 +#define CONTROL_7_SIZE 1 +#define CONTROL_8_9_SIZE 3 +#define CONTROL_10_SIZE 1 +#define CONTROL_11_SIZE 2 +#define CONTROL_12_13_SIZE 2 +#define CONTROL_14_SIZE 1 +#define CONTROL_15_SIZE 1 +#define CONTROL_16_SIZE 1 +#define CONTROL_17_SIZE 1 +#define CONTROL_18_SIZE 1 +#define CONTROL_19_SIZE 1 +#define CONTROL_20_SIZE 1 +#define CONTROL_21_SIZE 2 +#define CONTROL_22_26_SIZE 7 +#define CONTROL_27_SIZE 1 +#define CONTROL_28_SIZE 2 +#define CONTROL_29_SIZE 1 +#define CONTROL_30_SIZE 1 +#define CONTROL_31_SIZE 1 +#define CONTROL_32_35_SIZE 8 +#define CONTROL_36_SIZE 1 +#define CONTROL_37_SIZE 1 +#define CONTROL_38_SIZE 1 +#define CONTROL_39_SIZE 1 +#define CONTROL_40_SIZE 1 +#define CONTROL_41_SIZE 1 +#define CONTROL_42_SIZE 2 +#define CONTROL_43_54_SIZE 13 +#define CONTROL_55_56_SIZE 2 +#define CONTROL_57_SIZE 1 +#define CONTROL_58_SIZE 1 +#define CONTROL_59_SIZE 2 +#define CONTROL_60_62_SIZE 3 +#define CONTROL_63_SIZE 1 +#define CONTROL_64_67_SIZE 4 +#define CONTROL_68_73_SIZE 8 +#define CONTROL_74_SIZE 2 +#define CONTROL_75_SIZE 1 +#define CONTROL_76_SIZE 1 +#define CONTROL_77_78_SIZE 2 +#define CONTROL_79_83_SIZE 5 +#define CONTROL_84_85_SIZE 2 +#define CONTROL_86_SIZE 1 +#define CONTROL_87_SIZE 1 +#define CONTROL_88_SIZE 1 +#define CONTROL_89_SIZE 1 +#define CONTROL_90_SIZE 1 +#define CONTROL_91_SIZE 1 +#define CONTROL_92_SIZE 1 +#define CONTROL_93_SIZE 1 +#define CONTROL_94_SIZE 1 +#define CONTROL_95_SIZE 1 +#define CONTROL_96_SIZE 1 +#define CONTROL_97_SIZE 1 +#define CONTROL_98_SIZE 1 +#define CONTROL_99_SIZE 1 +#define CONTROL_100_SIZE 1 +#define CONTROL_101_SIZE 1 +#define CONTROL_102_SIZE 1 +#define CONTROL_103_SIZE 1 +#define CONTROL_104_SIZE 1 +#define CONTROL_105_SIZE 1 +#define CONTROL_106_SIZE 1 +#define CONTROL_107_SIZE 1 +#define CONTROL_108_SIZE 1 +#define CONTROL_109_SIZE 1 +#define CONTROL_110_SIZE 1 +#define CONTROL_111_SIZE 1 +#define CONTROL_112_SIZE 1 +#define CONTROL_113_SIZE 1 +#define CONTROL_114_SIZE 1 +#define CONTROL_115_SIZE 1 +#define CONTROL_116_SIZE 1 +#define CONTROL_117_SIZE 1 +#define CONTROL_118_SIZE 1 +#define CONTROL_119_SIZE 1 +#define CONTROL_120_SIZE 1 +#define CONTROL_121_SIZE 1 +#define CONTROL_122_SIZE 1 +#define CONTROL_123_SIZE 1 +#define CONTROL_124_SIZE 1 +#define CONTROL_125_SIZE 1 +#define CONTROL_126_SIZE 1 +#define CONTROL_127_SIZE 1 +#define CONTROL_128_SIZE 1 +#define CONTROL_129_SIZE 1 +#define CONTROL_130_SIZE 1 +#define CONTROL_131_SIZE 1 +#define CONTROL_132_SIZE 1 +#define CONTROL_133_SIZE 1 +#define CONTROL_134_SIZE 1 +#define CONTROL_135_SIZE 1 +#define CONTROL_136_SIZE 1 +#define CONTROL_137_SIZE 1 +#define CONTROL_138_SIZE 1 +#define CONTROL_139_SIZE 1 +#define CONTROL_140_SIZE 1 +#define CONTROL_141_SIZE 1 +#define CONTROL_142_SIZE 1 +#define CONTROL_143_SIZE 1 +#define CONTROL_144_SIZE 1 +#define CONTROL_145_SIZE 1 +#define CONTROL_146_SIZE 1 +#define CONTROL_147_SIZE 1 +#define CONTROL_148_SIZE 1 +#define CONTROL_149_SIZE 1 +#define CONTROL_150_SIZE 1 +#define CONTROL_151_SIZE 1 +#define CONTROL_152_SIZE 1 +#define CONTROL_153_SIZE 1 +#define CONTROL_154_SIZE 1 +#define CONTROL_155_SIZE 1 +#define CONTROL_156_SIZE 1 +#define CONTROL_157_158_SIZE 2 +#define CONTROL_163_SIZE 1 +#define CONTROL_165_SIZE 1 +#define CONTROL_166_SIZE 1 +#define CONTROL_167_SIZE 1 +#define CONTROL_168_SIZE 1 +#define CONTROL_169_SIZE 1 +#define CONTROL_171_SIZE 1 +#define CONTROL_172_SIZE 1 +#define CONTROL_173_SIZE 1 +#define CONTROL_174_SIZE 1 +#define CONTROL_175_SIZE 1 +#define CONTROL_176_SIZE 1 +#define CONTROL_177_178_SIZE 2 +#define CONTROL_179_SIZE 1 +#define CONTROL_182_SIZE 1 +#define CONTROL_183_SIZE 1 +#define CONTROL_185_SIZE 1 +#define CONTROL_186_SIZE 1 +#define CONTROL_187_SIZE 1 +#define CONTROL_188_SIZE 1 +#define CONTROL_196_SIZE 1 +#define CONTROL_218_SIZE 1 +#define CONTROL_223_SIZE 1 + +#define HIGH_RESISTANCE_DATA_SIZE 6 +#define FULL_RAW_CAP_MIN_MAX_DATA_SIZE 4 +#define TRX_OPEN_SHORT_DATA_SIZE 7 + +/* tddi f54 test reporting + */ + + +#define F54_POLLING_GET_REPORT + +/* +#define F54_SHOW_MAX_MIN +*/ + +/* test limit config */ + +#define TX_NUM_DEFAULT 18 +#define RX_NUM_DEFAULT 32 + +static short tddi_full_raw_limit_lower[TX_NUM_DEFAULT * RX_NUM_DEFAULT] = {2015, 1942, 1894, 1875, 1944, 1888, 1899, 1907, 1880, 1878, 1924, 1877, 1862, 1898, 1812, 1841, 1834, 1798, 1800, 1829, 1785, 1803, 1816, 1782, 1803, 1827, 1761, 1758, 1811, 1776, 1758, 1905, +1721, 1717, 1682, 1669, 1741, 1688, 1703, 1714, 1686, 1687, 1754, 1689, 1686, 1734, 1674, 1719, 1712, 1679, 1683, 1719, 1671, 1691, 1698, 1668, 1690, 1717, 1647, 1649, 1705, 1665, 1648, 1790, +1691, 1702, 1671, 1662, 1739, 1681, 1698, 1705, 1684, 1687, 1744, 1693, 1683, 1739, 1679, 1727, 1721, 1689, 1695, 1732, 1684, 1705, 1714, 1681, 1705, 1734, 1662, 1665, 1718, 1677, 1661, 1805, +1685, 1695, 1667, 1658, 1735, 1677, 1695, 1703, 1681, 1686, 1740, 1689, 1681, 1741, 1676, 1727, 1731, 1693, 1701, 1738, 1690, 1715, 1728, 1688, 1717, 1743, 1668, 1676, 1731, 1679, 1681, 1820, +1690, 1701, 1664, 1664, 1734, 1676, 1701, 1703, 1681, 1692, 1738, 1688, 1686, 1739, 1675, 1729, 1742, 1700, 1716, 1749, 1700, 1731, 1740, 1699, 1735, 1760, 1682, 1692, 1745, 1691, 1692, 1834, +1690, 1696, 1661, 1662, 1733, 1676, 1700, 1707, 1680, 1691, 1745, 1688, 1685, 1736, 1671, 1726, 1738, 1696, 1716, 1750, 1702, 1736, 1745, 1703, 1739, 1765, 1684, 1695, 1746, 1689, 1692, 1831, +1691, 1696, 1661, 1662, 1733, 1675, 1699, 1707, 1680, 1691, 1744, 1687, 1684, 1734, 1670, 1723, 1737, 1695, 1715, 1748, 1701, 1735, 1744, 1707, 1744, 1772, 1692, 1707, 1757, 1699, 1703, 1845, +1689, 1693, 1660, 1662, 1731, 1675, 1698, 1705, 1678, 1691, 1743, 1687, 1683, 1733, 1669, 1721, 1735, 1695, 1714, 1746, 1698, 1732, 1745, 1705, 1741, 1768, 1689, 1705, 1770, 1701, 1693, 1814, +1676, 1657, 1661, 1646, 1728, 1675, 1694, 1706, 1681, 1688, 1743, 1694, 1683, 1745, 1686, 1732, 1751, 1719, 1732, 1772, 1725, 1754, 1770, 1736, 1763, 1794, 1722, 1724, 1782, 1739, 1724, 1882, +1698, 1678, 1697, 1670, 1695, 1709, 1713, 1703, 1732, 1688, 1672, 1737, 1689, 1690, 1743, 1713, 1717, 1736, 1707, 1717, 1751, 1713, 1703, 1765, 1688, 1683, 1756, 1699, 1680, 1699, 1686, 1809, +1649, 1661, 1691, 1636, 1683, 1689, 1683, 1679, 1709, 1660, 1654, 1712, 1664, 1674, 1724, 1690, 1703, 1720, 1692, 1714, 1744, 1705, 1706, 1762, 1682, 1686, 1755, 1694, 1690, 1730, 1677, 1815, +1653, 1670, 1682, 1637, 1683, 1690, 1684, 1681, 1710, 1661, 1655, 1714, 1665, 1674, 1726, 1690, 1702, 1721, 1692, 1715, 1746, 1706, 1707, 1764, 1682, 1685, 1754, 1691, 1682, 1720, 1668, 1802, +1656, 1673, 1687, 1639, 1686, 1694, 1686, 1682, 1713, 1662, 1657, 1716, 1666, 1675, 1727, 1690, 1702, 1722, 1691, 1714, 1745, 1703, 1701, 1755, 1672, 1672, 1739, 1677, 1669, 1705, 1654, 1783, +1660, 1680, 1693, 1644, 1690, 1698, 1691, 1687, 1718, 1665, 1661, 1720, 1669, 1679, 1734, 1697, 1707, 1727, 1693, 1713, 1740, 1699, 1696, 1740, 1666, 1667, 1730, 1671, 1663, 1698, 1649, 1776, +1661, 1678, 1698, 1646, 1688, 1697, 1691, 1685, 1718, 1667, 1657, 1723, 1673, 1678, 1734, 1702, 1699, 1719, 1686, 1699, 1730, 1687, 1677, 1728, 1654, 1647, 1714, 1656, 1644, 1679, 1637, 1755, +1667, 1675, 1699, 1652, 1689, 1699, 1697, 1685, 1716, 1672, 1661, 1728, 1681, 1683, 1735, 1705, 1695, 1712, 1682, 1693, 1721, 1681, 1667, 1717, 1648, 1640, 1708, 1650, 1638, 1674, 1634, 1749, +1695, 1683, 1705, 1658, 1692, 1702, 1701, 1689, 1720, 1674, 1660, 1726, 1678, 1678, 1730, 1701, 1688, 1702, 1673, 1691, 1722, 1670, 1656, 1708, 1637, 1627, 1694, 1638, 1628, 1660, 1627, 1740, +1844, 1811, 1828, 1782, 1817, 1824, 1825, 1812, 1845, 1796, 1778, 1841, 1799, 1798, 1849, 1822, 1809, 1845, 1842, 1857, 1879, 1844, 1830, 1881, 1813, 1802, 1869, 1814, 1805, 1840, 1820, 1979 +}; + +static short tddi_full_raw_limit_upper[TX_NUM_DEFAULT * RX_NUM_DEFAULT] = {3359, 3237, 3157, 3125, 3241, 3147, 3165, 3178, 3133, 3130, 3207, 3128, 3104, 3164, 3020, 3069, 3058, 2996, 3001, 3049, 2976, 3005, 3026, 2971, 3005, 3045, 2935, 2930, 3019, 2961, 2930, 3175, +2869, 2862, 2803, 2783, 2902, 2813, 2839, 2857, 2810, 2812, 2924, 2815, 2810, 2890, 2791, 2866, 2853, 2799, 2806, 2865, 2785, 2819, 2831, 2781, 2817, 2862, 2745, 2748, 2841, 2775, 2748, 2983, +2819, 2837, 2786, 2770, 2899, 2801, 2830, 2842, 2807, 2812, 2907, 2822, 2805, 2899, 2798, 2878, 2868, 2815, 2825, 2887, 2807, 2843, 2857, 2802, 2842, 2890, 2771, 2775, 2864, 2795, 2768, 3009, +2809, 2826, 2779, 2764, 2893, 2796, 2826, 2839, 2803, 2810, 2901, 2816, 2802, 2903, 2794, 2878, 2885, 2821, 2835, 2898, 2817, 2858, 2880, 2813, 2863, 2905, 2780, 2793, 2885, 2799, 2802, 3034, +2818, 2836, 2773, 2773, 2890, 2794, 2835, 2838, 2801, 2821, 2897, 2814, 2810, 2898, 2791, 2882, 2904, 2833, 2860, 2916, 2834, 2886, 2900, 2832, 2892, 2934, 2803, 2821, 2908, 2818, 2820, 3057, +2816, 2828, 2768, 2770, 2888, 2793, 2833, 2846, 2800, 2819, 2909, 2813, 2808, 2894, 2786, 2877, 2898, 2828, 2860, 2917, 2837, 2893, 2908, 2838, 2899, 2942, 2807, 2825, 2910, 2816, 2821, 3053, +2818, 2827, 2768, 2770, 2888, 2792, 2833, 2845, 2800, 2818, 2907, 2811, 2808, 2891, 2783, 2872, 2895, 2826, 2859, 2914, 2835, 2893, 2908, 2845, 2907, 2954, 2820, 2845, 2928, 2832, 2838, 3075, +2816, 2822, 2767, 2770, 2886, 2792, 2831, 2842, 2798, 2818, 2906, 2812, 2805, 2889, 2781, 2868, 2892, 2825, 2857, 2910, 2831, 2888, 2909, 2842, 2902, 2947, 2815, 2843, 2951, 2836, 2822, 3023, +2793, 2763, 2769, 2743, 2880, 2793, 2824, 2844, 2801, 2813, 2905, 2823, 2805, 2908, 2811, 2888, 2919, 2865, 2887, 2954, 2876, 2924, 2950, 2894, 2939, 2991, 2870, 2874, 2971, 2899, 2874, 3137, +2830, 2797, 2829, 2784, 2825, 2849, 2855, 2838, 2886, 2813, 2787, 2896, 2816, 2817, 2906, 2856, 2862, 2894, 2845, 2862, 2919, 2855, 2839, 2941, 2814, 2806, 2927, 2833, 2801, 2832, 2810, 3016, +2749, 2768, 2818, 2727, 2805, 2816, 2805, 2799, 2848, 2767, 2756, 2853, 2774, 2790, 2874, 2817, 2838, 2868, 2820, 2858, 2907, 2842, 2843, 2938, 2803, 2810, 2925, 2824, 2817, 2883, 2795, 3025, +2755, 2783, 2804, 2728, 2805, 2817, 2808, 2802, 2851, 2768, 2759, 2856, 2776, 2791, 2877, 2817, 2837, 2868, 2820, 2858, 2910, 2843, 2845, 2941, 2803, 2809, 2923, 2818, 2804, 2868, 2781, 3004, +2761, 2789, 2811, 2732, 2810, 2823, 2810, 2804, 2855, 2770, 2762, 2860, 2776, 2792, 2879, 2817, 2837, 2871, 2819, 2856, 2909, 2839, 2835, 2925, 2787, 2787, 2899, 2795, 2781, 2842, 2757, 2972, +2767, 2800, 2821, 2741, 2817, 2830, 2818, 2812, 2864, 2776, 2768, 2867, 2783, 2799, 2890, 2829, 2846, 2878, 2822, 2855, 2900, 2833, 2827, 2900, 2778, 2778, 2883, 2785, 2772, 2831, 2749, 2960, +2768, 2798, 2831, 2744, 2813, 2829, 2819, 2808, 2864, 2778, 2762, 2871, 2789, 2796, 2890, 2837, 2831, 2866, 2810, 2832, 2884, 2813, 2795, 2880, 2757, 2746, 2857, 2761, 2740, 2799, 2728, 2925, +2779, 2792, 2832, 2754, 2815, 2832, 2828, 2808, 2861, 2787, 2768, 2881, 2802, 2805, 2892, 2843, 2826, 2853, 2804, 2822, 2869, 2803, 2778, 2861, 2748, 2733, 2847, 2750, 2731, 2790, 2723, 2915, +2825, 2805, 2841, 2763, 2820, 2838, 2835, 2815, 2867, 2790, 2768, 2877, 2796, 2797, 2884, 2836, 2813, 2837, 2789, 2819, 2871, 2784, 2761, 2848, 2729, 2712, 2824, 2731, 2714, 2768, 2712, 2900, +3074, 3019, 3047, 2971, 3028, 3040, 3042, 3020, 3075, 2994, 2964, 3069, 2999, 2996, 3081, 3036, 3015, 3075, 3070, 3096, 3131, 3074, 3050, 3135, 3023, 3004, 3115, 3024, 3009, 3068, 3034, 3299 +}; + +#define FULL_RAW_CAP_TEST_LIMIT_LOWER 300 +#define FULL_RAW_CAP_TEST_LIMIT_UPPER 60000 + +#define NOISE_TEST_LIMIT 35 +#define NOISE_TEST_NUM_OF_FRAMES 10 + +#define EE_SHORT_TEST_LIMIT_PART1 60 +#define EE_SHORT_TEST_LIMIT_PART2 90 + +#define AMP_OPEN_INT_DUR_ONE 145 +#define AMP_OPEN_INT_DUR_TWO 10 +#define AMP_OPEN_TEST_LIMIT_PHASE1_LOWER 500 +#define AMP_OPEN_TEST_LIMIT_PHASE1_UPPER 3000 +#define AMP_OPEN_TEST_LIMIT_PHASE2_LOWER 70 +#define AMP_OPEN_TEST_LIMIT_PHASE2_UPPER 130 + +#define NUM_BUTTON 3 +#define ABS_0D_OPEN_FACTOR 15 +#define ABS_0D_OPEN_TEST_LIMIT 30 + +#define ELEC_OPEN_TEST_TX_ON_COUNT 2 +#define ELEC_OPEN_TEST_RX_ON_COUNT 2 +#define ELEC_OPEN_INT_DUR_ONE 12 +#define ELEC_OPEN_INT_DUR_TWO 50 +/*para add by HQ-zmc 20170919*/ +#define ELEC_OPEN_TEST_LIMIT_ONE_LOWER 382 +#define ELEC_OPEN_TEST_LIMIT_ONE_UPPER 2300 +#define ELEC_OPEN_TEST_LIMIT_TWO_LOWER 68 +#define ELEC_OPEN_TEST_LIMIT_TWO_UPPER 184 + +/* tddi f54 test reporting - */ + +#define _TEST_FAIL 1 +#define _TEST_PASS 0 + + +#define concat(a, b) a##b + +#define attrify(propname) (&dev_attr_##propname.attr) + +#define show_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_show)(\ + struct device *dev,\ + struct device_attribute *attr,\ + char *buf);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, S_IRUGO,\ + concat(test_sysfs, _##propname##_show),\ + synaptics_rmi4_store_error); + +#define store_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_store)(\ + struct device *dev,\ + struct device_attribute *attr,\ + const char *buf, size_t count);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, (S_IWUSR | S_IWGRP),\ + synaptics_rmi4_show_error,\ + concat(test_sysfs, _##propname##_store)); + +#define show_store_prototype(propname)\ +static ssize_t concat(test_sysfs, _##propname##_show)(\ + struct device *dev,\ + struct device_attribute *attr,\ + char *buf);\ +\ +static ssize_t concat(test_sysfs, _##propname##_store)(\ + struct device *dev,\ + struct device_attribute *attr,\ + const char *buf, size_t count);\ +\ +static struct device_attribute dev_attr_##propname =\ + __ATTR(propname, (S_IRUGO | S_IWUSR | S_IWGRP),\ + concat(test_sysfs, _##propname##_show),\ + concat(test_sysfs, _##propname##_store)); + +#define disable_cbc(ctrl_num)\ +do {\ + retval = synaptics_rmi4_reg_read(rmi4_data,\ + f54->control.ctrl_num->address,\ + f54->control.ctrl_num->data,\ + sizeof(f54->control.ctrl_num->data));\ + if (retval < 0) {\ + dev_err(rmi4_data->pdev->dev.parent,\ + "%s: Failed to disable CBC (" #ctrl_num ")\n",\ + __func__);\ + return retval;\ + } \ + f54->control.ctrl_num->cbc_tx_carrier_selection = 0;\ + retval = synaptics_rmi4_reg_write(rmi4_data,\ + f54->control.ctrl_num->address,\ + f54->control.ctrl_num->data,\ + sizeof(f54->control.ctrl_num->data));\ + if (retval < 0) {\ + dev_err(rmi4_data->pdev->dev.parent,\ + "%s: Failed to disable CBC (" #ctrl_num ")\n",\ + __func__);\ + return retval;\ + } \ +} while (0) + +enum f54_report_types { + F54_8BIT_IMAGE = 1, + F54_16BIT_IMAGE = 2, + F54_RAW_16BIT_IMAGE = 3, + F54_HIGH_RESISTANCE = 4, + F54_TX_TO_TX_SHORTS = 5, + F54_RX_TO_RX_SHORTS_1 = 7, + F54_TRUE_BASELINE = 9, + F54_FULL_RAW_CAP_MIN_MAX = 13, + F54_RX_OPENS_1 = 14, + F54_TX_OPENS = 15, + F54_TX_TO_GND_SHORTS = 16, + F54_RX_TO_RX_SHORTS_2 = 17, + F54_RX_OPENS_2 = 18, + F54_FULL_RAW_CAP = 19, + F54_FULL_RAW_CAP_NO_RX_COUPLING = 20, + F54_SENSOR_SPEED = 22, + F54_ADC_RANGE = 23, + F54_TRX_OPENS = 24, + F54_TRX_TO_GND_SHORTS = 25, + F54_TRX_SHORTS = 26, + F54_ABS_RAW_CAP = 38, + F54_ABS_DELTA_CAP = 40, + F54_ABS_HYBRID_DELTA_CAP = 59, + F54_ABS_HYBRID_RAW_CAP = 63, + F54_AMP_FULL_RAW_CAP = 78, + F54_AMP_RAW_ADC = 83, + /* tddi f54 test reporting + */ + F54_FULL_RAW_CAP_TDDI = 92, + F54_NOISE_TDDI = 94, + F54_EE_SHORT_TDDI = 95, + /* tddi f54 test reporting - */ + + INVALID_REPORT_TYPE = -1, +}; + +enum f54_afe_cal { + F54_AFE_CAL, + F54_AFE_IS_CAL, +}; + +struct f54_query { + union { + struct { + /* query 0 */ + unsigned char num_of_rx_electrodes; + + /* query 1 */ + unsigned char num_of_tx_electrodes; + + /* query 2 */ + unsigned char f54_query2_b0__1:2; + unsigned char has_baseline:1; + unsigned char has_image8:1; + unsigned char f54_query2_b4__5:2; + unsigned char has_image16:1; + unsigned char f54_query2_b7:1; + + /* queries 3.0 and 3.1 */ + unsigned short clock_rate; + + /* query 4 */ + unsigned char touch_controller_family; + + /* query 5 */ + unsigned char has_pixel_touch_threshold_adjustment:1; + unsigned char f54_query5_b1__7:7; + + /* query 6 */ + unsigned char has_sensor_assignment:1; + unsigned char has_interference_metric:1; + unsigned char has_sense_frequency_control:1; + unsigned char has_firmware_noise_mitigation:1; + unsigned char has_ctrl11:1; + unsigned char has_two_byte_report_rate:1; + unsigned char has_one_byte_report_rate:1; + unsigned char has_relaxation_control:1; + + /* query 7 */ + unsigned char curve_compensation_mode:2; + unsigned char f54_query7_b2__7:6; + + /* query 8 */ + unsigned char f54_query8_b0:1; + unsigned char has_iir_filter:1; + unsigned char has_cmn_removal:1; + unsigned char has_cmn_maximum:1; + unsigned char has_touch_hysteresis:1; + unsigned char has_edge_compensation:1; + unsigned char has_per_frequency_noise_control:1; + unsigned char has_enhanced_stretch:1; + + /* query 9 */ + unsigned char has_force_fast_relaxation:1; + unsigned char has_multi_metric_state_machine:1; + unsigned char has_signal_clarity:1; + unsigned char has_variance_metric:1; + unsigned char has_0d_relaxation_control:1; + unsigned char has_0d_acquisition_control:1; + unsigned char has_status:1; + unsigned char has_slew_metric:1; + + /* query 10 */ + unsigned char has_h_blank:1; + unsigned char has_v_blank:1; + unsigned char has_long_h_blank:1; + unsigned char has_startup_fast_relaxation:1; + unsigned char has_esd_control:1; + unsigned char has_noise_mitigation2:1; + unsigned char has_noise_state:1; + unsigned char has_energy_ratio_relaxation:1; + + /* query 11 */ + unsigned char has_excessive_noise_reporting:1; + unsigned char has_slew_option:1; + unsigned char has_two_overhead_bursts:1; + unsigned char has_query13:1; + unsigned char has_one_overhead_burst:1; + unsigned char f54_query11_b5:1; + unsigned char has_ctrl88:1; + unsigned char has_query15:1; + + /* query 12 */ + unsigned char number_of_sensing_frequencies:4; + unsigned char f54_query12_b4__7:4; + } __packed; + unsigned char data[14]; + }; +}; + +struct f54_query_13 { + union { + struct { + unsigned char has_ctrl86:1; + unsigned char has_ctrl87:1; + unsigned char has_ctrl87_sub0:1; + unsigned char has_ctrl87_sub1:1; + unsigned char has_ctrl87_sub2:1; + unsigned char has_cidim:1; + unsigned char has_noise_mitigation_enhancement:1; + unsigned char has_rail_im:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_15 { + union { + struct { + unsigned char has_ctrl90:1; + unsigned char has_transmit_strength:1; + unsigned char has_ctrl87_sub3:1; + unsigned char has_query16:1; + unsigned char has_query20:1; + unsigned char has_query21:1; + unsigned char has_query22:1; + unsigned char has_query25:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_16 { + union { + struct { + unsigned char has_query17:1; + unsigned char has_data17:1; + unsigned char has_ctrl92:1; + unsigned char has_ctrl93:1; + unsigned char has_ctrl94_query18:1; + unsigned char has_ctrl95_query19:1; + unsigned char has_ctrl99:1; + unsigned char has_ctrl100:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_21 { + union { + struct { + unsigned char has_abs_rx:1; + unsigned char has_abs_tx:1; + unsigned char has_ctrl91:1; + unsigned char has_ctrl96:1; + unsigned char has_ctrl97:1; + unsigned char has_ctrl98:1; + unsigned char has_data19:1; + unsigned char has_query24_data18:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_22 { + union { + struct { + unsigned char has_packed_image:1; + unsigned char has_ctrl101:1; + unsigned char has_dynamic_sense_display_ratio:1; + unsigned char has_query23:1; + unsigned char has_ctrl103_query26:1; + unsigned char has_ctrl104:1; + unsigned char has_ctrl105:1; + unsigned char has_query28:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_23 { + union { + struct { + unsigned char has_ctrl102:1; + unsigned char has_ctrl102_sub1:1; + unsigned char has_ctrl102_sub2:1; + unsigned char has_ctrl102_sub4:1; + unsigned char has_ctrl102_sub5:1; + unsigned char has_ctrl102_sub9:1; + unsigned char has_ctrl102_sub10:1; + unsigned char has_ctrl102_sub11:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_25 { + union { + struct { + unsigned char has_ctrl106:1; + unsigned char has_ctrl102_sub12:1; + unsigned char has_ctrl107:1; + unsigned char has_ctrl108:1; + unsigned char has_ctrl109:1; + unsigned char has_data20:1; + unsigned char f54_query25_b6:1; + unsigned char has_query27:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_27 { + union { + struct { + unsigned char has_ctrl110:1; + unsigned char has_data21:1; + unsigned char has_ctrl111:1; + unsigned char has_ctrl112:1; + unsigned char has_ctrl113:1; + unsigned char has_data22:1; + unsigned char has_ctrl114:1; + unsigned char has_query29:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_29 { + union { + struct { + unsigned char has_ctrl115:1; + unsigned char has_ground_ring_options:1; + unsigned char has_lost_bursts_tuning:1; + unsigned char has_aux_exvcom2_select:1; + unsigned char has_ctrl116:1; + unsigned char has_data23:1; + unsigned char has_ctrl117:1; + unsigned char has_query30:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_30 { + union { + struct { + unsigned char has_ctrl118:1; + unsigned char has_ctrl119:1; + unsigned char has_ctrl120:1; + unsigned char has_ctrl121:1; + unsigned char has_ctrl122_query31:1; + unsigned char has_ctrl123:1; + unsigned char has_ctrl124:1; + unsigned char has_query32:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_32 { + union { + struct { + unsigned char has_ctrl125:1; + unsigned char has_ctrl126:1; + unsigned char has_ctrl127:1; + unsigned char has_abs_charge_pump_disable:1; + unsigned char has_query33:1; + unsigned char has_data24:1; + unsigned char has_query34:1; + unsigned char has_query35:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_33 { + union { + struct { + unsigned char has_ctrl128:1; + unsigned char has_ctrl129:1; + unsigned char has_ctrl130:1; + unsigned char has_ctrl131:1; + unsigned char has_ctrl132:1; + unsigned char has_ctrl133:1; + unsigned char has_ctrl134:1; + unsigned char has_query36:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_35 { + union { + struct { + unsigned char has_data25:1; + unsigned char has_ctrl135:1; + unsigned char has_ctrl136:1; + unsigned char has_ctrl137:1; + unsigned char has_ctrl138:1; + unsigned char has_ctrl139:1; + unsigned char has_data26:1; + unsigned char has_ctrl140:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_36 { + union { + struct { + unsigned char has_ctrl141:1; + unsigned char has_ctrl142:1; + unsigned char has_query37:1; + unsigned char has_ctrl143:1; + unsigned char has_ctrl144:1; + unsigned char has_ctrl145:1; + unsigned char has_ctrl146:1; + unsigned char has_query38:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_38 { + union { + struct { + unsigned char has_ctrl147:1; + unsigned char has_ctrl148:1; + unsigned char has_ctrl149:1; + unsigned char has_ctrl150:1; + unsigned char has_ctrl151:1; + unsigned char has_ctrl152:1; + unsigned char has_ctrl153:1; + unsigned char has_query39:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_39 { + union { + struct { + unsigned char has_ctrl154:1; + unsigned char has_ctrl155:1; + unsigned char has_ctrl156:1; + unsigned char has_ctrl160:1; + unsigned char has_ctrl157_ctrl158:1; + unsigned char f54_query39_b5__6:2; + unsigned char has_query40:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_40 { + union { + struct { + unsigned char has_ctrl169:1; + unsigned char has_ctrl163_query41:1; + unsigned char f54_query40_b2:1; + unsigned char has_ctrl165_query42:1; + unsigned char has_ctrl166:1; + unsigned char has_ctrl167:1; + unsigned char has_ctrl168:1; + unsigned char has_query43:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_43 { + union { + struct { + unsigned char f54_query43_b0__1:2; + unsigned char has_ctrl171:1; + unsigned char has_ctrl172_query44_query45:1; + unsigned char has_ctrl173:1; + unsigned char has_ctrl174:1; + unsigned char has_ctrl175:1; + unsigned char has_query46:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_46 { + union { + struct { + unsigned char has_ctrl176:1; + unsigned char has_ctrl177_ctrl178:1; + unsigned char has_ctrl179:1; + unsigned char f54_query46_b3:1; + unsigned char has_data27:1; + unsigned char has_data28:1; + unsigned char f54_query46_b6:1; + unsigned char has_query47:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_47 { + union { + struct { + unsigned char f54_query47_b0:1; + unsigned char has_ctrl182:1; + unsigned char has_ctrl183:1; + unsigned char f54_query47_b3:1; + unsigned char has_ctrl185:1; + unsigned char has_ctrl186:1; + unsigned char has_ctrl187:1; + unsigned char has_query49:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_49 { + union { + struct { + unsigned char f54_query49_b0__1:2; + unsigned char has_ctrl188:1; + unsigned char has_data31:1; + unsigned char f54_query49_b4__6:3; + unsigned char has_query50:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_50 { + union { + struct { + unsigned char f54_query50_b0__6:7; + unsigned char has_query51:1; + } __packed; + unsigned char data[1]; + }; +}; + +/* tddi f54 test reporting + */ +struct f54_query_51 { + union { + struct { + unsigned char f54_query51_b0:1; + unsigned char has_ctrl196:1; + unsigned char f54_query51_b2:1; + unsigned char f54_query51_b3:1; + unsigned char f54_query51_b4:1; + unsigned char has_query53_query54_ctrl198:1; + unsigned char has_ctrl199:1; + unsigned char has_query55:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_55 { + union { + struct { + unsigned char has_query56:1; + unsigned char has_data33_data34:1; + unsigned char has_alternate_report_rate:1; + unsigned char has_ctrl200:1; + unsigned char has_ctrl201_ctrl202:1; + unsigned char has_ctrl203:1; + unsigned char has_ctrl204:1; + unsigned char has_query57:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_57 { + union { + struct { + unsigned char has_ctrl205:1; + unsigned char has_ctrl206:1; + unsigned char has_usb_bulk_read:1; + unsigned char has_ctrl207:1; + unsigned char has_ctrl208:1; + unsigned char has_ctrl209:1; + unsigned char has_ctrl210:1; + unsigned char has_query58:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_58 { + union { + struct { + unsigned char has_query59:1; + unsigned char has_query60:1; + unsigned char has_ctrl211:1; + unsigned char has_ctrl212:1; + unsigned char has_hybrid_abs_tx_axis_filtering:1; + unsigned char f54_query58_b5:1; + unsigned char has_ctrl213:1; + unsigned char has_query61:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_61 { + union { + struct { + unsigned char has_ctrl214:1; + unsigned char has_ctrl215_query62_query63:1; + unsigned char f54_query61_b2__4:3; + unsigned char has_ctrl218:1; + unsigned char has_hybrid_abs_buttons:1; + unsigned char has_query64:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_64 { + union { + struct { + unsigned char f54_query64_b0:1; + unsigned char has_ctrl220:1; + unsigned char f54_query64_b2__3:2; + unsigned char has_ctrl219_sub1:1; + unsigned char has_ctrl103_sub3:1; + unsigned char has_ctrl224_ctrl226_ctrl227:1; + unsigned char has_query65:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_65 { + union { + struct { + unsigned char f54_query65_b0__4:5; + unsigned char has_query66_ctrl231:1; + unsigned char has_ctrl232:1; + unsigned char has_query67:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_67 { + union { + struct { + unsigned char has_abs_doze_spatial_filter_enable:1; + unsigned char has_abs_doze_average_filter_enable:1; + unsigned char has_single_display_pulse:1; + unsigned char f54_query67_b3__6:4; + unsigned char has_query68:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_68 { + union { + struct { + unsigned char f54_query68_b0__4:5; + unsigned char has_freq_filter_bw_ext:1; + unsigned char f54_query68_b6:1; + unsigned char has_query69:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f54_query_69 { + union { + struct { + unsigned char has_ctrl240_sub0:1; + unsigned char has_ctrl240_sub1_sub2:1; + unsigned char has_ctrl240_sub3:1; + unsigned char has_ctrl240_sub4:1; + unsigned char burst_mode_report_type_enabled:1; + unsigned char f54_query69_b5__7:3; + } __packed; + unsigned char data[1]; + }; +}; +/* tddi f54 test reporting - */ + +struct f54_data_31 { + union { + struct { + unsigned char is_calibration_crc:1; + unsigned char calibration_crc:1; + unsigned char short_test_row_number:5; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_7 { + union { + struct { + unsigned char cbc_cap:3; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char f54_ctrl7_b5__7:3; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_41 { + union { + struct { + unsigned char no_signal_clarity:1; + unsigned char f54_ctrl41_b1__7:7; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_57 { + union { + struct { + unsigned char cbc_cap:3; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char f54_ctrl57_b5__7:3; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_86 { + union { + struct { + unsigned char enable_high_noise_state:1; + unsigned char dynamic_sense_display_ratio:2; + unsigned char f54_ctrl86_b3__7:5; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_88 { + union { + struct { + unsigned char tx_low_reference_polarity:1; + unsigned char tx_high_reference_polarity:1; + unsigned char abs_low_reference_polarity:1; + unsigned char abs_polarity:1; + unsigned char cbc_polarity:1; + unsigned char cbc_tx_carrier_selection:1; + unsigned char charge_pump_enable:1; + unsigned char cbc_abs_auto_servo:1; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +/* tddi f54 test reporting + */ +struct f54_control_91 { + union { + struct { + unsigned char reflo_transcap_capacitance; + unsigned char refhi_transcap_capacitance; + unsigned char receiver_feedback_capacitance; + unsigned char reference_receiver_feedback_capacitance; + unsigned char gain_ctrl; + } __packed; + struct { + unsigned char data[5]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_96 { + union { + struct { + unsigned char cbc_transcap[64]; + } __packed; + struct { + unsigned char data[64]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_99 { + union { + struct { + unsigned char integration_duration_lsb; + unsigned char integration_duration_msb; + unsigned char reset_duration; + } __packed; + struct { + unsigned char data[3]; + unsigned short address; + } __packed; + }; +}; +/* tddi f54 test reporting - */ + +struct f54_control_110 { + union { + struct { + unsigned char active_stylus_rx_feedback_cap; + unsigned char active_stylus_rx_feedback_cap_reference; + unsigned char active_stylus_low_reference; + unsigned char active_stylus_high_reference; + unsigned char active_stylus_gain_control; + unsigned char active_stylus_gain_control_reference; + unsigned char active_stylus_timing_mode; + unsigned char active_stylus_discovery_bursts; + unsigned char active_stylus_detection_bursts; + unsigned char active_stylus_discovery_noise_multiplier; + unsigned char active_stylus_detection_envelope_min; + unsigned char active_stylus_detection_envelope_max; + unsigned char active_stylus_lose_count; + } __packed; + struct { + unsigned char data[13]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_149 { + union { + struct { + unsigned char trans_cbc_global_cap_enable:1; + unsigned char f54_ctrl149_b1__7:7; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_182 { + union { + struct { + unsigned char cbc_timing_ctrl_tx_lsb; + unsigned char cbc_timing_ctrl_tx_msb; + unsigned char cbc_timing_ctrl_rx_lsb; + unsigned char cbc_timing_ctrl_rx_msb; + } __packed; + struct { + unsigned char data[4]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_188 { + union { + struct { + unsigned char start_calibration:1; + unsigned char start_is_calibration:1; + unsigned char frequency:2; + unsigned char start_production_test:1; + unsigned char short_test_calibration:1; + unsigned char f54_ctrl188_b7:1; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control_223 { + union { + struct { + unsigned char voltages_for_0d:8; + } __packed; + struct { + unsigned char data[1]; + unsigned short address; + } __packed; + }; +}; + +struct f54_control { + struct f54_control_7 *reg_7; + struct f54_control_41 *reg_41; + struct f54_control_57 *reg_57; + struct f54_control_86 *reg_86; + struct f54_control_88 *reg_88; + struct f54_control_91 *reg_91; + struct f54_control_96 *reg_96; + struct f54_control_99 *reg_99; + struct f54_control_110 *reg_110; + struct f54_control_149 *reg_149; + struct f54_control_182 *reg_182; + struct f54_control_188 *reg_188; + struct f54_control_223 *reg_223; +}; + +struct synaptics_rmi4_f54_handle { + bool is_burst; + bool no_auto_cal; + bool skip_preparation; + bool burst_read; + unsigned char status; + unsigned char intr_mask; + unsigned char intr_reg_num; + unsigned char tx_assigned; + unsigned char rx_assigned; + /* tddi f54 test reporting + */ + unsigned char swap_sensor_side; + unsigned char left_mux_size; + unsigned char right_mux_size; + /*tddi f54 test reporting - */ + unsigned char *report_data; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + unsigned short fifoindex; + unsigned int report_size; + unsigned int data_buffer_size; + unsigned int data_pos; + enum f54_report_types report_type; + struct f54_query query; + struct f54_query_13 query_13; + struct f54_query_15 query_15; + struct f54_query_16 query_16; + struct f54_query_21 query_21; + struct f54_query_22 query_22; + struct f54_query_23 query_23; + struct f54_query_25 query_25; + struct f54_query_27 query_27; + struct f54_query_29 query_29; + struct f54_query_30 query_30; + struct f54_query_32 query_32; + struct f54_query_33 query_33; + struct f54_query_35 query_35; + struct f54_query_36 query_36; + struct f54_query_38 query_38; + struct f54_query_39 query_39; + struct f54_query_40 query_40; + struct f54_query_43 query_43; + struct f54_query_46 query_46; + struct f54_query_47 query_47; + struct f54_query_49 query_49; + struct f54_query_50 query_50; + struct f54_query_51 query_51; + /* tddi f54 test reporting + */ + struct f54_query_55 query_55; + struct f54_query_57 query_57; + struct f54_query_58 query_58; + struct f54_query_61 query_61; + struct f54_query_64 query_64; + struct f54_query_65 query_65; + struct f54_query_67 query_67; + struct f54_query_68 query_68; + struct f54_query_69 query_69; + /* tddi f54 test reporting - */ + struct f54_data_31 data_31; + struct f54_control control; + struct mutex status_mutex; + struct kobject *sysfs_dir; + struct hrtimer watchdog; + struct work_struct timeout_work; + struct work_struct test_report_work; + struct workqueue_struct *test_report_workqueue; + struct synaptics_rmi4_data *rmi4_data; +}; + +struct f55_query { + union { + struct { + /* query 0 */ + unsigned char num_of_rx_electrodes; + + /* query 1 */ + unsigned char num_of_tx_electrodes; + + /* query 2 */ + unsigned char has_sensor_assignment:1; + unsigned char has_edge_compensation:1; + unsigned char curve_compensation_mode:2; + unsigned char has_ctrl6:1; + unsigned char has_alternate_transmitter_assignment:1; + unsigned char has_single_layer_multi_touch:1; + unsigned char has_query5:1; + } __packed; + unsigned char data[3]; + }; +}; + +struct f55_query_3 { + union { + struct { + unsigned char has_ctrl8:1; + unsigned char has_ctrl9:1; + unsigned char has_oncell_pattern_support:1; + unsigned char has_data0:1; + unsigned char has_single_wide_pattern_support:1; + unsigned char has_mirrored_tx_pattern_support:1; + unsigned char has_discrete_pattern_support:1; + unsigned char has_query9:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_5 { + union { + struct { + unsigned char has_corner_compensation:1; + unsigned char has_ctrl12:1; + unsigned char has_trx_configuration:1; + unsigned char has_ctrl13:1; + unsigned char f55_query5_b4:1; + unsigned char has_ctrl14:1; + unsigned char has_basis_function:1; + unsigned char has_query17:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_17 { + union { + struct { + unsigned char f55_query17_b0:1; + unsigned char has_ctrl16:1; + unsigned char has_ctrl18_ctrl19:1; + unsigned char has_ctrl17:1; + unsigned char has_ctrl20:1; + unsigned char has_ctrl21:1; + unsigned char has_ctrl22:1; + unsigned char has_query18:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_18 { + union { + struct { + unsigned char has_ctrl23:1; + unsigned char has_ctrl24:1; + unsigned char has_query19:1; + unsigned char has_ctrl25:1; + unsigned char has_ctrl26:1; + unsigned char has_ctrl27_query20:1; + unsigned char has_ctrl28_query21:1; + unsigned char has_query22:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_22 { + union { + struct { + unsigned char has_ctrl29:1; + unsigned char has_query23:1; + unsigned char has_guard_disable:1; + unsigned char has_ctrl30:1; + unsigned char has_ctrl31:1; + unsigned char has_ctrl32:1; + unsigned char has_query24_through_query27:1; + unsigned char has_query28:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_23 { + union { + struct { + unsigned char amp_sensor_enabled:1; + unsigned char image_transposed:1; + unsigned char first_column_at_left_side:1; + unsigned char size_of_column2mux:5; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_28 { + union { + struct { + unsigned char f55_query28_b0__4:5; + unsigned char has_ctrl37:1; + unsigned char has_query29:1; + unsigned char has_query30:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_30 { + union { + struct { + unsigned char has_ctrl38:1; + unsigned char has_query31_query32:1; + unsigned char has_ctrl39:1; + unsigned char has_ctrl40:1; + unsigned char has_ctrl41:1; + unsigned char has_ctrl42:1; + unsigned char has_ctrl43_ctrl44:1; + unsigned char has_query33:1; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_query_33 { + union { + struct { + unsigned char has_extended_amp_pad:1; + unsigned char has_extended_amp_btn:1; + unsigned char has_ctrl45_ctrl46:1; + unsigned char f55_query33_b3:1; + unsigned char has_ctrl47_sub0_sub1:1; + unsigned char f55_query33_b5__7:3; + } __packed; + unsigned char data[1]; + }; +}; + +struct f55_control_43 { + union { + struct { + unsigned char swap_sensor_side:1; + unsigned char f55_ctrl43_b1__7:7; + unsigned char afe_l_mux_size:4; + unsigned char afe_r_mux_size:4; + } __packed; + unsigned char data[2]; + }; +}; + +struct synaptics_rmi4_f55_handle { + bool amp_sensor; + bool extended_amp; + bool extended_amp_btn; + bool has_force; + unsigned char size_of_column2mux; + unsigned char afe_mux_offset; + unsigned char force_tx_offset; + unsigned char force_rx_offset; + unsigned char *tx_assignment; + unsigned char *rx_assignment; + unsigned char *force_tx_assignment; + unsigned char *force_rx_assignment; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; + struct f55_query query; + struct f55_query_3 query_3; + struct f55_query_5 query_5; + struct f55_query_17 query_17; + struct f55_query_18 query_18; + struct f55_query_22 query_22; + struct f55_query_23 query_23; + struct f55_query_28 query_28; + struct f55_query_30 query_30; + struct f55_query_33 query_33; +}; + +struct f21_query_2 { + union { + struct { + unsigned char size_of_query3; + struct { + unsigned char query0_is_present:1; + unsigned char query1_is_present:1; + unsigned char query2_is_present:1; + unsigned char query3_is_present:1; + unsigned char query4_is_present:1; + unsigned char query5_is_present:1; + unsigned char query6_is_present:1; + unsigned char query7_is_present:1; + } __packed; + struct { + unsigned char query8_is_present:1; + unsigned char query9_is_present:1; + unsigned char query10_is_present:1; + unsigned char query11_is_present:1; + unsigned char query12_is_present:1; + unsigned char query13_is_present:1; + unsigned char query14_is_present:1; + unsigned char query15_is_present:1; + } __packed; + }; + unsigned char data[3]; + }; +}; + +struct f21_query_5 { + union { + struct { + unsigned char size_of_query6; + struct { + unsigned char ctrl0_is_present:1; + unsigned char ctrl1_is_present:1; + unsigned char ctrl2_is_present:1; + unsigned char ctrl3_is_present:1; + unsigned char ctrl4_is_present:1; + unsigned char ctrl5_is_present:1; + unsigned char ctrl6_is_present:1; + unsigned char ctrl7_is_present:1; + } __packed; + struct { + unsigned char ctrl8_is_present:1; + unsigned char ctrl9_is_present:1; + unsigned char ctrl10_is_present:1; + unsigned char ctrl11_is_present:1; + unsigned char ctrl12_is_present:1; + unsigned char ctrl13_is_present:1; + unsigned char ctrl14_is_present:1; + unsigned char ctrl15_is_present:1; + } __packed; + struct { + unsigned char ctrl16_is_present:1; + unsigned char ctrl17_is_present:1; + unsigned char ctrl18_is_present:1; + unsigned char ctrl19_is_present:1; + unsigned char ctrl20_is_present:1; + unsigned char ctrl21_is_present:1; + unsigned char ctrl22_is_present:1; + unsigned char ctrl23_is_present:1; + } __packed; + }; + unsigned char data[4]; + }; +}; + +struct f21_query_11 { + union { + struct { + unsigned char has_high_resolution_force:1; + unsigned char has_force_sensing_txrx_mapping:1; + unsigned char f21_query11_00_b2__7:6; + unsigned char f21_query11_00_reserved; + unsigned char max_number_of_force_sensors; + unsigned char max_number_of_force_txs; + unsigned char max_number_of_force_rxs; + unsigned char f21_query11_01_reserved; + } __packed; + unsigned char data[6]; + }; +}; + +struct synaptics_rmi4_f21_handle { + bool has_force; + unsigned char tx_assigned; + unsigned char rx_assigned; + unsigned char max_num_of_tx; + unsigned char max_num_of_rx; + unsigned char max_num_of_txrx; + unsigned char *force_txrx_assignment; + unsigned short query_base_addr; + unsigned short control_base_addr; + unsigned short data_base_addr; + unsigned short command_base_addr; +}; + +show_prototype(num_of_mapped_tx) +show_prototype(num_of_mapped_rx) +show_prototype(tx_mapping) +show_prototype(rx_mapping) +show_prototype(num_of_mapped_force_tx) +show_prototype(num_of_mapped_force_rx) +show_prototype(force_tx_mapping) +show_prototype(force_rx_mapping) +show_prototype(report_size) +show_prototype(status) +show_prototype(ito_test_result) +store_prototype(do_preparation) +store_prototype(force_cal) +store_prototype(get_report) +store_prototype(resume_touch) +store_prototype(do_afe_calibration) +show_store_prototype(report_type) +show_store_prototype(fifoindex) +show_store_prototype(no_auto_cal) +show_store_prototype(read_report) +/* tddi f54 test reporting + */ +show_store_prototype(tddi_full_raw) +show_store_prototype(tddi_noise) +show_store_prototype(tddi_ee_short) +show_store_prototype(tddi_amp_open) +show_store_prototype(tddi_amp_electrode_open) +show_store_prototype(burst) +/* tddi f54 test reporting - */ + +static struct attribute *attrs[] = { + attrify(num_of_mapped_tx), + attrify(num_of_mapped_rx), + attrify(tx_mapping), + attrify(rx_mapping), + attrify(num_of_mapped_force_tx), + attrify(num_of_mapped_force_rx), + attrify(force_tx_mapping), + attrify(force_rx_mapping), + attrify(report_size), + attrify(status), + attrify(ito_test_result), + attrify(do_preparation), + attrify(force_cal), + attrify(get_report), + attrify(resume_touch), + attrify(do_afe_calibration), + attrify(report_type), + attrify(fifoindex), + attrify(no_auto_cal), + attrify(read_report), + /* tddi f54 test reporting + */ + attrify(tddi_full_raw), + attrify(tddi_noise), + attrify(tddi_ee_short), + attrify(tddi_amp_open), + attrify(tddi_amp_electrode_open), + attrify(burst), + /* tddi f54 test reporting - */ + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = attrs, +}; + +static ssize_t test_sysfs_data_read(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count); + +static struct bin_attribute test_report_data = { + .attr = { + .name = "report_data", + .mode = S_IRUGO, + }, + .size = 0, + .read = test_sysfs_data_read, +}; + +static struct synaptics_rmi4_f54_handle *f54; +static struct synaptics_rmi4_f55_handle *f55; +static struct synaptics_rmi4_f21_handle *f21; + + +/* tddi f54 test reporting + */ + + + +static unsigned char *g_tddi_full_raw_data_output; + + + +static signed short *g_tddi_noise_data_output; + + + +static unsigned char *g_tddi_ee_short_data_output; + + + +static unsigned char *g_tddi_amp_open_data_output; + + + + + + + +static bool g_flag_readrt_err; + +/* tddi f54 test reporting - */ + +DECLARE_COMPLETION(test_remove_complete_lansi); + +static bool test_report_type_valid(enum f54_report_types report_type) +{ + switch (report_type) { + case F54_8BIT_IMAGE: + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_HIGH_RESISTANCE: + case F54_TX_TO_TX_SHORTS: + case F54_RX_TO_RX_SHORTS_1: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP_MIN_MAX: + case F54_RX_OPENS_1: + case F54_TX_OPENS: + case F54_TX_TO_GND_SHORTS: + case F54_RX_TO_RX_SHORTS_2: + case F54_RX_OPENS_2: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_TRX_OPENS: + case F54_TRX_TO_GND_SHORTS: + case F54_TRX_SHORTS: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_AMP_FULL_RAW_CAP: + case F54_AMP_RAW_ADC: + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + case F54_NOISE_TDDI: + case F54_EE_SHORT_TDDI: + /* tddi f54 test reporting - */ + return true; + break; + default: + f54->report_type = INVALID_REPORT_TYPE; + f54->report_size = 0; + return false; + } +} + +static void test_set_report_size(void) +{ + int retval; + unsigned char tx = f54->tx_assigned; + unsigned char rx = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + switch (f54->report_type) { + case F54_8BIT_IMAGE: + f54->report_size = tx * rx; + break; + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_AMP_FULL_RAW_CAP: + case F54_AMP_RAW_ADC: + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + if (f55->extended_amp_btn) { + tx += 1; + } + f54->report_size = 2 * tx * rx; + break; + case F54_NOISE_TDDI: + /* tddi f54 test reporting - */ + f54->report_size = 2 * tx * rx; + break; + /* tddi f54 test reporting + */ + case F54_EE_SHORT_TDDI: + f54->report_size = 2 * 2 * tx * rx; + break; + /* tddi f54 test reporting - */ + case F54_HIGH_RESISTANCE: + f54->report_size = HIGH_RESISTANCE_DATA_SIZE; + break; + case F54_TX_TO_TX_SHORTS: + case F54_TX_OPENS: + case F54_TX_TO_GND_SHORTS: + f54->report_size = (tx + 7) / 8; + break; + case F54_RX_TO_RX_SHORTS_1: + case F54_RX_OPENS_1: + if (rx < tx) + f54->report_size = 2 * rx * rx; + else + f54->report_size = 2 * tx * rx; + break; + case F54_FULL_RAW_CAP_MIN_MAX: + f54->report_size = FULL_RAW_CAP_MIN_MAX_DATA_SIZE; + break; + case F54_RX_TO_RX_SHORTS_2: + case F54_RX_OPENS_2: + if (rx <= tx) + f54->report_size = 0; + else + f54->report_size = 2 * rx * (rx - tx); + break; + case F54_ADC_RANGE: + if (f54->query.has_signal_clarity) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_41->address, + f54->control.reg_41->data, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Failed to read control reg_41\n", + __func__); + f54->report_size = 0; + break; + } + if (!f54->control.reg_41->no_signal_clarity) { + if (tx % 4) + tx += 4 - (tx % 4); + } + } + f54->report_size = 2 * tx * rx; + break; + case F54_TRX_OPENS: + case F54_TRX_TO_GND_SHORTS: + case F54_TRX_SHORTS: + f54->report_size = TRX_OPEN_SHORT_DATA_SIZE; + break; + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + tx += f21->tx_assigned; + rx += f21->rx_assigned; + f54->report_size = 4 * (tx + rx); + break; + default: + f54->report_size = 0; + } + + return; +} + +static int test_set_interrupt(bool set) +{ + int retval; + unsigned char ii; + unsigned char zero = 0x00; + unsigned char *intr_mask; + unsigned short f01_ctrl_reg; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + intr_mask = rmi4_data->intr_mask; + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + f54->intr_reg_num; + + if (!set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } + + for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) { + if (intr_mask[ii] != 0x00) { + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + ii; + if (set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &zero, + sizeof(zero)); + if (retval < 0) + return retval; + } else { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &(intr_mask[ii]), + sizeof(intr_mask[ii])); + if (retval < 0) + return retval; + } + } + } + + f01_ctrl_reg = rmi4_data->f01_ctrl_base_addr + 1 + f54->intr_reg_num; + + if (set) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f01_ctrl_reg, + &f54->intr_mask, + 1); + if (retval < 0) + return retval; + } + + return 0; +} + +static int test_wait_for_command_completion(void) +{ + int retval; + unsigned char value; + unsigned char timeout_count; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + timeout_count = 0; + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->command_base_addr, + &value, + sizeof(value)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command register\n", + __func__); + return retval; + } + + if (value == 0x00) + break; + + msleep(100); + timeout_count++; + } while (timeout_count < COMMAND_TIMEOUT_100MS); + + if (timeout_count == COMMAND_TIMEOUT_100MS) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for command completion\n", + __func__); + return -ETIMEDOUT; + } + + return 0; +} + +static int test_do_command(unsigned char command) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write command\n", + __func__); + return retval; + } + + retval = test_wait_for_command_completion(); + if (retval < 0) + return retval; + + return 0; +} + +static int test_do_preparation(void) +{ + int retval; + unsigned char value; + unsigned char zero = 0x00; + unsigned char device_ctrl; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set no sleep\n", + __func__); + return retval; + } + + device_ctrl |= NO_SLEEP_ON; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set no sleep\n", + __func__); + return retval; + } + + if (f54->skip_preparation) + return 0; + + switch (f54->report_type) { + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + case F54_NOISE_TDDI: + case F54_EE_SHORT_TDDI: + /* tddi f54 test reporting - */ + break; + case F54_AMP_RAW_ADC: + if (f54->query_49.has_ctrl188) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + f54->control.reg_188->start_production_test = 1; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + } + break; + default: + if (f54->query.touch_controller_family == 1) + disable_cbc(reg_7); + else if (f54->query.has_ctrl88) + disable_cbc(reg_88); + + if (f54->query.has_0d_acquisition_control) + disable_cbc(reg_57); + + if ((f54->query.has_query15) && + (f54->query_15.has_query25) && + (f54->query_25.has_query27) && + (f54->query_27.has_query29) && + (f54->query_29.has_query30) && + (f54->query_30.has_query32) && + (f54->query_32.has_query33) && + (f54->query_33.has_query36) && + (f54->query_36.has_query38) && + (f54->query_38.has_ctrl149)) { + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_149->address, + &zero, + sizeof(f54->control.reg_149->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable global CBC\n", + __func__); + return retval; + } + } + + if (f54->query.has_signal_clarity) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_41->address, + &value, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable signal clarity\n", + __func__); + return retval; + } + value |= 0x01; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_41->address, + &value, + sizeof(f54->control.reg_41->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to disable signal clarity\n", + __func__); + return retval; + } + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update\n", + __func__); + return retval; + } + + retval = test_do_command(COMMAND_FORCE_CAL); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force cal\n", + __func__); + return retval; + } + } + + return 0; +} + +static int test_do_afe_calibration(enum f54_afe_cal mode) +{ + int retval; + unsigned char timeout = CALIBRATION_TIMEOUT_S; + unsigned char timeout_count = 0; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to start calibration\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) + f54->control.reg_188->start_calibration = 1; + else if (mode == F54_AFE_IS_CAL) + f54->control.reg_188->start_is_calibration = 1; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to start calibration\n", + __func__); + return retval; + } + + do { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to complete calibration\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) { + if (!f54->control.reg_188->start_calibration) + break; + } else if (mode == F54_AFE_IS_CAL) { + if (!f54->control.reg_188->start_is_calibration) + break; + } + + if (timeout_count == timeout) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Timed out waiting for calibration completion\n", + __func__); + return -EBUSY; + } + + timeout_count++; + msleep(1000); + } while (true); + + /* check CRC */ + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_31.address, + f54->data_31.data, + sizeof(f54->data_31.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read calibration CRC\n", + __func__); + return retval; + } + + if (mode == F54_AFE_CAL) { + if (f54->data_31.calibration_crc == 0) + return 0; + } else if (mode == F54_AFE_IS_CAL) { + if (f54->data_31.is_calibration_crc == 0) + return 0; + } + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read calibration CRC\n", + __func__); + + return -EINVAL; +} + +static int test_check_for_idle_status(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + switch (f54->status) { + case STATUS_IDLE: + retval = 0; + break; + case STATUS_BUSY: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Status busy\n", + __func__); + retval = -EINVAL; + break; + case STATUS_ERROR: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Status error\n", + __func__); + retval = -EINVAL; + break; + default: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid status (%d)\n", + __func__, f54->status); + retval = -EINVAL; + } + + return retval; +} + +static void test_timeout_work(struct work_struct *work) +{ + int retval; + unsigned char command; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + if (f54->status == STATUS_BUSY) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read command register\n", + __func__); + } else if (command & COMMAND_GET_REPORT) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type not supported by FW\n", + __func__); + } else { + queue_work(f54->test_report_workqueue, + &f54->test_report_work); + goto exit; + } + f54->status = STATUS_ERROR; + f54->report_size = 0; + } + +exit: + mutex_unlock(&f54->status_mutex); + + return; +} + +static enum hrtimer_restart test_get_report_timeout(struct hrtimer *timer) +{ + schedule_work(&(f54->timeout_work)); + + return HRTIMER_NORESTART; +} + +static ssize_t test_sysfs_num_of_mapped_tx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->tx_assigned); +} + +static ssize_t test_sysfs_num_of_mapped_rx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->rx_assigned); +} + +static ssize_t test_sysfs_tx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char tx_num; + unsigned char tx_electrodes; + + if (!f55) + return -EINVAL; + + tx_electrodes = f55->query.num_of_tx_electrodes; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f55->tx_assignment[ii]; + if (tx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", tx_num); + buf += cnt; + count += cnt; + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_rx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char rx_num; + unsigned char rx_electrodes; + + if (!f55) + return -EINVAL; + + rx_electrodes = f55->query.num_of_rx_electrodes; + + for (ii = 0; ii < rx_electrodes; ii++) { + rx_num = f55->rx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", rx_num); + buf += cnt; + count += cnt; + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_num_of_mapped_force_tx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f21->tx_assigned); +} + +static ssize_t test_sysfs_num_of_mapped_force_rx_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f21->rx_assigned); +} + +static ssize_t test_sysfs_force_tx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char tx_num; + unsigned char tx_electrodes; + + if ((!f55 || !f55->has_force) && (!f21 || !f21->has_force)) + return -EINVAL; + + if (f55->has_force) { + tx_electrodes = f55->query.num_of_tx_electrodes; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f55->force_tx_assignment[ii]; + if (tx_num == 0xff) { + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + tx_num); + } + buf += cnt; + count += cnt; + } + } else if (f21->has_force) { + tx_electrodes = f21->max_num_of_tx; + + for (ii = 0; ii < tx_electrodes; ii++) { + tx_num = f21->force_txrx_assignment[ii]; + if (tx_num == 0xff) { + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + } else { + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + tx_num); + } + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_force_rx_mapping_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int cnt; + int count = 0; + unsigned char ii; + unsigned char offset; + unsigned char rx_num; + unsigned char rx_electrodes; + + if ((!f55 || !f55->has_force) && (!f21 || !f21->has_force)) + return -EINVAL; + + if (f55->has_force) { + rx_electrodes = f55->query.num_of_rx_electrodes; + + for (ii = 0; ii < rx_electrodes; ii++) { + rx_num = f55->force_rx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + rx_num); + buf += cnt; + count += cnt; + } + } else if (f21->has_force) { + offset = f21->max_num_of_tx; + rx_electrodes = f21->max_num_of_rx; + + for (ii = offset; ii < (rx_electrodes + offset); ii++) { + rx_num = f21->force_txrx_assignment[ii]; + if (rx_num == 0xff) + cnt = snprintf(buf, PAGE_SIZE - count, "xx "); + else + cnt = snprintf(buf, PAGE_SIZE - count, "%02u ", + rx_num); + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + + return count; +} + +static ssize_t test_sysfs_report_size_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->report_size); +} + +static ssize_t test_sysfs_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + + mutex_lock(&f54->status_mutex); + + retval = snprintf(buf, PAGE_SIZE, "%u\n", f54->status); + + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_do_preparation_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + retval = test_do_preparation(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do preparation\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_force_cal_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + retval = test_do_command(COMMAND_FORCE_CAL); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force cal\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +/* tddi f54 test reporting + */ +#ifdef F54_POLLING_GET_REPORT +static ssize_t test_sysfs_get_report_polling(void) +{ + int retval = 0; + unsigned char report_index[2]; + unsigned int byte_delay_us; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_wait_for_command_completion(); + if (retval < 0) { + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + test_set_report_size(); + if (f54->report_size == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report data size = 0\n", __func__); + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + if (f54->data_buffer_size < f54->report_size) { + if (f54->data_buffer_size) + kfree(f54->report_data); + f54->report_data = kzalloc(f54->report_size, GFP_KERNEL); + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", __func__); + f54->data_buffer_size = 0; + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + f54->data_buffer_size = f54->report_size; + } + + report_index[0] = 0; + report_index[1] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + report_index, + sizeof(report_index)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report data index\n", __func__); + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) { + byte_delay_us = rmi4_data->hw_if->board_data->byte_delay_us; + rmi4_data->hw_if->board_data->byte_delay_us = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_DATA_OFFSET, + f54->report_data, + f54->report_size); + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) + rmi4_data->hw_if->board_data->byte_delay_us = byte_delay_us; + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report data\n", + __func__); + retval = -EIO; + f54->status = STATUS_ERROR; + return retval; + } + + f54->status = STATUS_IDLE; + return retval; +} +#endif +/* tddi f54 test reporting - */ + +static ssize_t test_sysfs_get_report_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char command; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!test_report_type_valid(f54->report_type)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Invalid report type\n", + __func__); + retval = -EINVAL; + goto exit; + } + + test_set_interrupt(true); + + command = (unsigned char)COMMAND_GET_REPORT; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->command_base_addr, + &command, + sizeof(command)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write get report command\n", + __func__); + goto exit; + } + +/* tddi f54 test reporting + */ +#ifdef F54_POLLING_GET_REPORT + + retval = test_sysfs_get_report_polling(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to get report image\n", + __func__); + goto exit; + } + +#else +/* tddi f54 test reporting - */ + + f54->status = STATUS_BUSY; + f54->report_size = 0; + f54->data_pos = 0; + + hrtimer_start(&f54->watchdog, + ktime_set(GET_REPORT_TIMEOUT_S, 0), + HRTIMER_MODE_REL); + + retval = count; + +#endif + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_resume_touch_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char device_ctrl; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore no sleep setting\n", + __func__); + return retval; + } + + device_ctrl = device_ctrl & ~NO_SLEEP_ON; + device_ctrl |= rmi4_data->no_sleep_setting; + + retval = synaptics_rmi4_reg_write(rmi4_data, + rmi4_data->f01_ctrl_base_addr, + &device_ctrl, + sizeof(device_ctrl)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore no sleep setting\n", + __func__); + return retval; + } + + test_set_interrupt(false); + + if (f54->skip_preparation) + return count; + + switch (f54->report_type) { + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_SENSOR_SPEED: + case F54_ADC_RANGE: + case F54_ABS_RAW_CAP: + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + case F54_ABS_HYBRID_RAW_CAP: + case F54_FULL_RAW_CAP_TDDI: + /* tddi f54 test reporting + */ + case F54_NOISE_TDDI: + case F54_EE_SHORT_TDDI: + /* tddi f54 test reporting - */ + break; + case F54_AMP_RAW_ADC: + if (f54->query_49.has_ctrl188) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + f54->control.reg_188->start_production_test = 0; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control.reg_188->address, + f54->control.reg_188->data, + sizeof(f54->control.reg_188->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set start production test\n", + __func__); + return retval; + } + } + break; + default: + rmi4_data->reset_device(rmi4_data, false); + } + + return count; +} + +static ssize_t test_sysfs_do_afe_calibration_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (!f54->query_49.has_ctrl188) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: F54_ANALOG_Ctrl188 not found\n", + __func__); + return -EINVAL; + } + + if (setting == 0 || setting == 1) + retval = test_do_afe_calibration((enum f54_afe_cal)setting); + else + return -EINVAL; + + if (retval) + return retval; + else + return count; +} + +static ssize_t test_sysfs_report_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->report_type); +} + +static ssize_t test_sysfs_report_type_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!test_report_type_valid((enum f54_report_types)setting)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type not supported by driver\n", + __func__); + retval = -EINVAL; + goto exit; + } + + f54->report_type = (enum f54_report_types)setting; + data = (unsigned char)setting; + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report type\n", + __func__); + goto exit; + } + + retval = count; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static ssize_t test_sysfs_fifoindex_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int retval; + unsigned char data[2]; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report index\n", + __func__); + return retval; + } + + batohs(&f54->fifoindex, data); + + return snprintf(buf, PAGE_SIZE, "%u\n", f54->fifoindex); +} + +static ssize_t test_sysfs_fifoindex_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data[2]; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + f54->fifoindex = setting; + + hstoba(data, (unsigned short)setting); + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report index\n", + __func__); + return retval; + } + + return count; +} + +static ssize_t test_sysfs_no_auto_cal_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", f54->no_auto_cal); +} + +static ssize_t test_sysfs_no_auto_cal_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char data; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting > 1) + return -EINVAL; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read no auto cal setting\n", + __func__); + return retval; + } + + if (setting) + data |= CONTROL_NO_AUTO_CAL; + else + data &= ~CONTROL_NO_AUTO_CAL; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->control_base_addr, + &data, + sizeof(data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write no auto cal setting\n", + __func__); + return retval; + } + + f54->no_auto_cal = (setting == 1); + + return count; +} + +static int check_ito_test_flag = 2; +#ifdef SYNAPTICS_ESD_CHECK +extern void synaptics_rmi4_esd_work(struct work_struct *work); +#define SYNAPTICS_ESD_CHECK_CIRCLE 2*HZ +extern struct synaptics_rmi4_data *rmi4_data; +#endif +static ssize_t test_sysfs_read_report_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int ii; + unsigned int jj; + int cnt; + int count = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + char *report_data_8; + short *report_data_16; + int *report_data_32; + unsigned short *report_data_u16; + unsigned int *report_data_u32; + +#ifdef SYNAPTICS_ESD_CHECK + printk("%s SYNAPTICS_ESD_CHECK is off\n", __func__); + cancel_delayed_work_sync(&(rmi4_data->esd_work)); +#endif + + switch (f54->report_type) { + case F54_8BIT_IMAGE: + printk("F54_8BIT_IMAGE\n"); + report_data_8 = (char *)f54->report_data; + for (ii = 0; ii < f54->report_size; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: %d\n", + ii, *report_data_8); + report_data_8++; + buf += cnt; + count += cnt; + } + break; + case F54_AMP_RAW_ADC: + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + break; + case F54_16BIT_IMAGE: + case F54_RAW_16BIT_IMAGE: + case F54_TRUE_BASELINE: + case F54_FULL_RAW_CAP: + case F54_FULL_RAW_CAP_NO_RX_COUPLING: + case F54_SENSOR_SPEED: + case F54_AMP_FULL_RAW_CAP: + /* tddi f54 test reporting + */ + case F54_NOISE_TDDI: + /* tddi f54 test reporting - */ + printk("start F54_NOISE_TDDI\n"); + report_data_16 = (short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", + *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d\n", + *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + break; + /* tddi f54 test reporting + */ + case F54_FULL_RAW_CAP_TDDI: + printk("start F54_FULL_RAW_CAP_TDDI\n"); + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", + *report_data_u16); + if (*report_data_16 <= 1700 || *report_data_16 >= 2300){ + if ((jj == 24) && (ii != 1) && (ii != 6) && (ii != 12)){ + check_ito_test_flag = 1; + } else{ + check_ito_test_flag = 0; + } + }else{ + check_ito_test_flag = 0; + } + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + if (1 == check_ito_test_flag){ + cnt = snprintf(buf, PAGE_SIZE - count, "fail\n"); + buf += cnt; + count += cnt; + printk("[synaptics]ITO test fail\n"); + }else{ + cnt = snprintf(buf, PAGE_SIZE - count, "pass\n"); + buf += cnt; + count += cnt; + printk("[synaptics]ITO test pass\n"); + } + break; + case F54_EE_SHORT_TDDI: + printk("start F54_EE_SHORT_TDDI\n"); + report_data_u16 = (unsigned short *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "tx = %d\nrx = %d\n\n", + tx_num, rx_num); + buf += cnt; + count += cnt; + + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + for (jj = 0; jj < (rx_num - 1); jj++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d ", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "%-4d\n", + *report_data_u16); + report_data_u16++; + buf += cnt; + count += cnt; + } + break; + /* tddi f54 test reporting - */ + case F54_HIGH_RESISTANCE: + case F54_FULL_RAW_CAP_MIN_MAX: + report_data_16 = (short *)f54->report_data; + for (ii = 0; ii < f54->report_size; ii += 2) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: %d\n", + ii / 2, *report_data_16); + report_data_16++; + buf += cnt; + count += cnt; + } + break; + case F54_ABS_RAW_CAP: + case F54_ABS_HYBRID_RAW_CAP: + tx_num += f21->tx_assigned; + rx_num += f21->rx_assigned; + report_data_u32 = (unsigned int *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "rx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5u", + *report_data_u32); + report_data_u32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, "tx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5u", + *report_data_u32); + report_data_u32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + break; + case F54_ABS_DELTA_CAP: + case F54_ABS_HYBRID_DELTA_CAP: + tx_num += f21->tx_assigned; + rx_num += f21->rx_assigned; + report_data_32 = (int *)f54->report_data; + cnt = snprintf(buf, PAGE_SIZE - count, "rx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < rx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5d", + *report_data_32); + report_data_32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, "tx "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %2d", ii); + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + + cnt = snprintf(buf, PAGE_SIZE - count, " "); + buf += cnt; + count += cnt; + for (ii = 0; ii < tx_num; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, " %5d", + *report_data_32); + report_data_32++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + break; + default: + for (ii = 0; ii < f54->report_size; ii++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%03d: 0x%02x\n", + ii, f54->report_data[ii]); + buf += cnt; + count += cnt; + } + } + + snprintf(buf, PAGE_SIZE - count, "\n"); + count++; + +#ifdef SYNAPTICS_ESD_CHECK + printk("%s SYNAPTICS_ESD_CHECK is on\n", __func__); + queue_delayed_work(rmi4_data->esd_workqueue, &(rmi4_data->esd_work), SYNAPTICS_ESD_CHECK_CIRCLE); +#endif + + return count; +} + +static ssize_t test_sysfs_read_report_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + unsigned char timeout = GET_REPORT_TIMEOUT_S * 10; + unsigned char timeout_count; + const char cmd[] = {'1', 0}; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_sysfs_report_type_store(dev, attr, buf, count); + if (retval < 0) + goto exit; + + retval = test_sysfs_do_preparation_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + retval = test_sysfs_get_report_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + timeout_count = 0; + do { + if (f54->status != STATUS_BUSY) + break; + msleep(100); + timeout_count++; + } while (timeout_count < timeout); + + if ((f54->status != STATUS_IDLE) || (f54->report_size == 0)) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report\n", + __func__); + retval = -EINVAL; + goto exit; + } + + retval = test_sysfs_resume_touch_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + return count; + +exit: + rmi4_data->reset_device(rmi4_data, false); + + return retval; +} + +static ssize_t test_sysfs_ito_test_result_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + printk("synaptics check_ito_test_flag = %d\n", check_ito_test_flag); + if (4 == check_ito_test_flag){ + return snprintf(buf, PAGE_SIZE, "%s\n", "pass"); + }else{ + return snprintf(buf, PAGE_SIZE, "%s\n", "fail"); + } +} + +/* tddi f54 test reporting + */ +static ssize_t test_sysfs_read_report(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count, + bool do_preparation, bool do_reset) +{ + int retval = count; + unsigned char timeout = GET_REPORT_TIMEOUT_S * 10; + unsigned char timeout_count; + const char cmd[] = {'1', 0}; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = test_sysfs_report_type_store(dev, attr, buf, count); + if (retval < 0) + goto exit; + + if (do_preparation){ + retval = test_sysfs_do_preparation_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + } + retval = test_sysfs_get_report_store(dev, attr, cmd, 1); + if (retval < 0) + goto exit; + + timeout_count = 0; + do { + if (f54->status != STATUS_BUSY) + break; + msleep(100); + timeout_count++; + } while (timeout_count < timeout); + + if ((f54->status != STATUS_IDLE) || (f54->report_size == 0)) { + + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report\n", + __func__); + retval = -EINVAL; + goto exit; + } + +exit: + if (do_reset) + rmi4_data->reset_device(rmi4_data, false); + + return retval; +} + +static short find_median(short *pdata, int num) +{ + int i, j; + short temp; + short *value; + short median; + + value = (short *)kzalloc(num * sizeof(short), GFP_KERNEL); + + for (i = 0; i < num; i++) + *(value+i) = *(pdata+i); + + + for (i = 1; i < = num-1; i++) + { + for (j = 1; j < = num-i; j++) + { + if (*(value+j-1) <= *(value+j)) + { + temp = *(value+j-1); + *(value+j-1) = *(value+j); + *(value+j) = temp; + } + else + continue ; + } + } + + + if (num % 2 == 0) + median = (*(value+(num/2 -1)) + *(value+(num/2)))/2; + else + median = *(value+(num/2)); + + if (value) + kfree(value); + + return median; +} + +static int tddi_ratio_calculation(signed short *p_image) +{ + int retval = 0; + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + unsigned char left_size = f54->left_mux_size; + unsigned char right_size = f54->right_mux_size; + signed short *p_data_16; + signed short *p_left_median = NULL; + signed short *p_right_median = NULL; + signed short *p_left_column_buf = NULL; + signed short *p_right_column_buf = NULL; + signed int temp; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + if (!p_image) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Fail. p_image is null\n", __func__); + retval = -EINVAL; + goto exit; + } + + + p_right_median = (signed short *) kzalloc(rx_num * sizeof(short), GFP_KERNEL); + if (!p_right_median) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_right_median\n", __func__); + retval = -ENOMEM; + goto exit; + } + + p_left_median = (signed short *) kzalloc(rx_num * sizeof(short), GFP_KERNEL); + if (!p_left_median) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_left_median\n", __func__); + retval = -ENOMEM; + goto exit; + } + + p_right_column_buf = (signed short *) kzalloc(right_size * rx_num * sizeof(short), GFP_KERNEL); + if (!p_right_column_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_right_column_buf\n", __func__); + retval = -ENOMEM; + goto exit; + } + + p_left_column_buf = (signed short *) kzalloc(left_size * rx_num * sizeof(short), GFP_KERNEL); + if (!p_left_column_buf) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_left_column_buf\n", __func__); + retval = -ENOMEM; + goto exit; + } + + + if (f54->swap_sensor_side) { + + + p_data_16 = p_image; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < left_size; j++) { + p_left_column_buf[i * left_size + j] = p_data_16[j * rx_num + i]; + } + } + + p_data_16 = p_image + left_size * rx_num; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < right_size; j++) { + p_right_column_buf[i * right_size + j] = p_data_16[j * rx_num + i]; + } + } + } + else { + + + p_data_16 = p_image; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < right_size; j++) { + p_right_column_buf[i * right_size + j] = p_data_16[j * rx_num + i]; + } + } + + p_data_16 = p_image + right_size * rx_num; + for (i = 0; i < rx_num; i++) { + for (j = 0; j < left_size; j++) { + p_left_column_buf[i * left_size + j] = p_data_16[j * rx_num + i]; + } + } + } + + + for (i = 0; i < rx_num; i++) { + p_left_median[i] = find_median(p_left_column_buf + i * left_size, left_size); + p_right_median[i] = find_median(p_right_column_buf + i * right_size, right_size); + } + + + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + + + if (f54->swap_sensor_side) { + + if (i < left_size) { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_left_median[j]; + } else { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_right_median[j]; + } + } + else { + + if (i < right_size) { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_right_median[j]; + } else { + temp = (signed int) p_image[i * rx_num + j]; + temp = temp * 100 / p_left_median[j]; + } + } + + + p_image[i * rx_num + j] = temp; + } + } + +exit: + kfree(p_right_median); + kfree(p_left_median); + kfree(p_right_column_buf); + kfree(p_left_column_buf); + return retval; +} + +static ssize_t test_sysfs_tddi_ee_short_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval; + int i, j, offset; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + signed short *tddi_rt95_part_one = NULL; + signed short *tddi_rt95_part_two = NULL; + unsigned int buffer_size = tx_num * rx_num * 2; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + /* allocate the g_tddi_ee_short_data_output */ + if (g_tddi_ee_short_data_output) + kfree(g_tddi_ee_short_data_output); + + g_tddi_ee_short_data_output = kzalloc(tx_num * rx_num, GFP_KERNEL); + if (!g_tddi_ee_short_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_ee_short_data_output\n", + __func__); + return -ENOMEM; + } + + + tddi_rt95_part_one = kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_rt95_part_one) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_rt95_part_one\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + tddi_rt95_part_two = kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_rt95_part_two) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for td43xx_rt95_part_two\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + g_flag_readrt_err = false; + + /* step 1 */ + /* get report image 95 */ + retval = test_sysfs_read_report(dev, attr, "95", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 95. exit\n", __func__); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + + /* step 2 */ + /* use the upper half as part 1 image */ + /* the data should be lower than TEST_LIMIT_PART1 ( fail, if > TEST_LIMIT_PART1 ) */ + for (i = 0, offset = 0; i < tx_num * rx_num; i++) { + tddi_rt95_part_one[i] = (signed short)(f54->report_data[offset]) | + ((signed short)(f54->report_data[offset + 1]) << 8); + offset += 2; + } + +#ifdef F54_SHOW_MAX_MIN + min = max = tddi_rt95_part_one[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, tddi_rt95_part_one[i*rx_num + j], min); + max = max_t(signed short, tddi_rt95_part_one[i*rx_num + j], max); +#endif + if (tddi_rt95_part_one[i*rx_num + j] > EE_SHORT_TEST_LIMIT_PART1) { + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d in part 1 image (limit = %d)\n", + __func__, i, j, tddi_rt95_part_one[i*rx_num + j], EE_SHORT_TEST_LIMIT_PART1); + + tddi_rt95_part_one[i*rx_num + j] = _TEST_FAIL; + } + else { + tddi_rt95_part_one[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : image part 1 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + /* step 3 */ + /* use the lower half as part 2 image */ + /* and perform the calculation */ + /* the calculated data should be over than TEST_LIMIT_PART2 ( fail, if < TEST_LIMIT_PART2 ) */ + for (i = 0, offset = buffer_size; i < tx_num * rx_num; i++) { + tddi_rt95_part_two[i] = (signed short)(f54->report_data[offset]) | + ((signed short)(f54->report_data[offset + 1]) << 8); + offset += 2; + } + + + tddi_ratio_calculation(tddi_rt95_part_two); + +#ifdef F54_SHOW_MAX_MIN + min = max = tddi_rt95_part_two[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, tddi_rt95_part_two[i*rx_num + j], min); + max = max_t(signed short, tddi_rt95_part_two[i*rx_num + j], max); +#endif + if (tddi_rt95_part_two[i*rx_num + j] < EE_SHORT_TEST_LIMIT_PART2) { + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d in part 2 image (limit = %d)\n", + __func__, i, j, tddi_rt95_part_two[i*rx_num + j], EE_SHORT_TEST_LIMIT_PART2); + + tddi_rt95_part_two[i*rx_num + j] = _TEST_FAIL; + } + else { + tddi_rt95_part_two[i*rx_num + j] = _TEST_PASS; + } + } + } + +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : image part 2 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + /* step 4 */ + /* filling out the g_tddi_ee_short_data_output */ + /* 1: fail / 0 : pass */ + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_ee_short_data_output[i * rx_num + j] = + (unsigned char)(tddi_rt95_part_one[i * rx_num + j]) || tddi_rt95_part_two[i * rx_num + j]; + } + } + + retval = count; + +exit: + kfree(tddi_rt95_part_one); + kfree(tddi_rt95_part_two); + + return retval; +} + +static ssize_t test_sysfs_tddi_ee_short_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + if (!g_tddi_ee_short_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_ee_short_data_output); + g_tddi_ee_short_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_ee_short_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_ee_short_data_output); + g_tddi_ee_short_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +static ssize_t test_sysfs_tddi_noise_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int i, j, offset; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int repeat; + + signed short report_data_16; + signed short *tddi_noise_max = NULL; + signed short *tddi_noise_min = NULL; + unsigned char *tddi_noise_data = NULL; + unsigned int buffer_size = tx_num * rx_num * 2; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + /* allocate the g_tddi_noise_data_output */ + if (g_tddi_noise_data_output) + kfree(g_tddi_noise_data_output); + + g_tddi_noise_data_output = (signed short *)kzalloc(tx_num * rx_num *sizeof(short), GFP_KERNEL); + if (!g_tddi_noise_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_noise_data_output\n", + __func__); + return -ENOMEM; + } + + tddi_noise_data = kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_noise_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_noise_data\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + tddi_noise_max = (unsigned short *)kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_noise_max) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_noise_max\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + tddi_noise_min = (unsigned short *) kzalloc(buffer_size, GFP_KERNEL); + if (!tddi_noise_min) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for tddi_noise_min\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + g_flag_readrt_err = false; + + /* get report image 94 repeatedly */ + /* and calculate the minimum and maximun value as well */ + for (repeat = 0 ; repeat < NOISE_TEST_NUM_OF_FRAMES; repeat++){ + + retval = test_sysfs_read_report(dev, attr, "94", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 94 at %d round. exit\n", + __func__, repeat); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + memset(tddi_noise_data, 0x00, buffer_size); + + secure_memcpy(tddi_noise_data, buffer_size, + f54->report_data, f54->report_size, f54->report_size); + + for (i = 0, offset = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + + report_data_16 = + (signed short)tddi_noise_data[offset] + + ((signed short)tddi_noise_data[offset+1] << 8); + offset += 2; + + tddi_noise_max[i*rx_num + j] = + max_t(signed short, tddi_noise_max[i*rx_num + j], report_data_16); + tddi_noise_min[i*rx_num + j] = + min_t(signed short, tddi_noise_min[i*rx_num + j], report_data_16); + } + } + + } + + + + + +#ifdef F54_SHOW_MAX_MIN + min = tddi_noise_max[0]; + max = tddi_noise_min[0]; +#endif + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_noise_data_output[i*rx_num + j] = + tddi_noise_max[i*rx_num + j] - tddi_noise_min[i*rx_num + j]; + +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, g_tddi_noise_data_output[i*rx_num + j], min); + max = max_t(signed short, g_tddi_noise_data_output[i*rx_num + j], max); +#endif + + if (g_tddi_noise_data_output[i*rx_num + j] > NOISE_TEST_LIMIT) { + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d (limit = %d)\n", + __func__, i, j, g_tddi_noise_data_output[i*rx_num + j], NOISE_TEST_LIMIT); + + g_tddi_noise_data_output[i*rx_num + j] = _TEST_FAIL; + } + else { + g_tddi_noise_data_output[i*rx_num + j] = _TEST_PASS; + } + + } + } + +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + retval = count; + +exit: + kfree(tddi_noise_max); + kfree(tddi_noise_min); + kfree(tddi_noise_data); + + return retval; +} + +static ssize_t test_sysfs_tddi_noise_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + if (!g_tddi_noise_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_noise_data_output); + g_tddi_noise_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_noise_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_noise_data_output); + g_tddi_noise_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +static ssize_t test_sysfs_tddi_full_raw_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + unsigned int full_raw_report_size; + unsigned long setting; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + + if (f55->extended_amp_btn) { + tx_num += 1; + } + full_raw_report_size = tx_num * rx_num * 2; + + g_flag_readrt_err = false; + + /* allocate the g_tddi_full_raw_data_output */ + if (g_tddi_full_raw_data_output) + kfree(g_tddi_full_raw_data_output); + + g_tddi_full_raw_data_output = kzalloc(full_raw_report_size, GFP_KERNEL); + if (!g_tddi_full_raw_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_full_raw_data_output\n", + __func__); + return -ENOMEM; + } + + /* get the report image 92 */ + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92. exit\n", __func__); + g_flag_readrt_err = true ; + return -EIO; + } + + secure_memcpy(g_tddi_full_raw_data_output, full_raw_report_size, + f54->report_data, f54->report_size, f54->report_size); + + retval = count; + + return retval; +} + +static ssize_t test_sysfs_tddi_full_raw_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + unsigned int i; + unsigned int j; + unsigned int k; + int cnt; + int count = 0; + int fail_count = 0; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + unsigned short *report_data_16; + + unsigned short min = 0, max = 0; + + if (!g_tddi_full_raw_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_full_raw_data_output); + g_tddi_full_raw_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + + + + + + report_data_16 = (unsigned short *)g_tddi_full_raw_data_output; + + min = max = *report_data_16; + + for (i = 0, k = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", *report_data_16); + + min = (min < *report_data_16)? min : *report_data_16; + max = (max > *report_data_16)? max : *report_data_16; + + /*if (((*report_data_16) < (tddi_full_raw_limit_lower[k]))|| ((*report_data_16) > (tddi_full_raw_limit_upper[k]))) { + fail_count ++; + }*/ + /*changed by HQ-zmc 20171025*/ + + + if (((*report_data_16) < (*(tddi_full_raw_limit_lower+k))) || ((*report_data_16) > (*(tddi_full_raw_limit_upper+k)))) { + fail_count ++; + } + k++; + report_data_16++; + + + } + + + + + } + + + + + + + + + if (f55->extended_amp_btn) { + cnt = snprintf(buf, PAGE_SIZE - count, "\namp button count = %d.\n", NUM_BUTTON); + buf += cnt; + count += cnt; + + for (i = 0; i < NUM_BUTTON; i++) { + cnt = snprintf(buf, PAGE_SIZE - count, "%-5d ", *report_data_16); + + report_data_16++; + buf += cnt; + count += cnt; + } + cnt = snprintf(buf, PAGE_SIZE - count, "\n"); + buf += cnt; + count += cnt; + } + + + + + + kfree(g_tddi_full_raw_data_output); + g_tddi_full_raw_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); + +} + +static ssize_t test_sysfs_tddi_amp_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int i, j, k; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + unsigned long setting; + unsigned char original_data_f54_ctrl99[3] = {0x00, 0x00, 0x00}; + struct f54_control control = f54->control; + unsigned char *p_report_data_8 = NULL; + signed short *p_rt92_delta_image = NULL; + signed short *p_rt92_image_1 = NULL; + signed short *p_rt92_image_2 = NULL; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + + + if (setting != 1) + return -EINVAL; + + + if (g_tddi_amp_open_data_output) + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = kzalloc(tx_num * rx_num, GFP_KERNEL); + if (!g_tddi_amp_open_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_amp_open_data_output\n", + __func__); + return -ENOMEM; + } + + g_flag_readrt_err = false; + + + p_report_data_8 = kzalloc(tx_num * rx_num * 2, GFP_KERNEL); + if (!p_report_data_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_report_data_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_delta_image = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_delta_image) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_delta_image\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_1 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_1\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_2 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_2\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + + + if (f54->query.touch_controller_family != 2) { + + dev_err(rmi4_data->pdev->dev.parent, + "%s: not support touch controller family = 0 or 1 \n", + __func__); + retval = -EINVAL; + goto exit; + } + + + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + original_data_f54_ctrl99, + sizeof(original_data_f54_ctrl99)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read integration duration\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 1 */ + /* set the in_iter_duration_1 setting */ + /* and read the first rt92 image */ + control.reg_99->integration_duration_lsb = AMP_OPEN_INT_DUR_ONE; + control.reg_99->integration_duration_msb = (AMP_OPEN_INT_DUR_ONE >> 8) & 0xff; + control.reg_99->reset_duration = original_data_f54_ctrl99[2]; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write the integration duration to f54_ctrl_99 in step 1\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 1\n", + __func__); + retval = -EIO; + goto exit; + } + + + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 1. exit\n", + __func__); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_1[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + + memset(p_report_data_8, 0x00, tx_num * rx_num * 2); + + /* step 2 */ + /* set the in_iter_duration_2 setting */ + /* and read the second rt92 image */ + control.reg_99->integration_duration_lsb = AMP_OPEN_INT_DUR_TWO; + control.reg_99->integration_duration_msb = (AMP_OPEN_INT_DUR_TWO >> 8) & 0xff; + control.reg_99->reset_duration = original_data_f54_ctrl99[2]; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write the integration duration to f54_ctrl_99 in step 2\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 2\n", + __func__); + retval = -EIO; + goto exit; + } + + + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 2. exit\n", + __func__); + retval = -EIO; + g_flag_readrt_err = true; + goto exit; + } + + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_2[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + + /* restore the original settings */ + control.reg_99->integration_duration_lsb = original_data_f54_ctrl99[0]; + control.reg_99->integration_duration_msb = original_data_f54_ctrl99[1]; + control.reg_99->reset_duration = original_data_f54_ctrl99[2]; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write the integration duration to f54_ctrl_99 in restore phase\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in restore phase\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 3 */ + /* generate the delta image, td43xx_rt92_delta_image */ + /* unit is femtofarad (fF) */ + for (i = 0; i < tx_num * rx_num; i++) { + p_rt92_delta_image[i] = p_rt92_image_1[i] - p_rt92_image_2[i]; + } + + memset(p_rt92_image_1, 0x00, tx_num * rx_num * 2); + + /* step 4 */ + /* phase 1, the delta value form the above two rt92 images */ + /* should be within the phase 1 test limit*/ + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < AMP_OPEN_TEST_LIMIT_PHASE1_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > AMP_OPEN_TEST_LIMIT_PHASE1_UPPER)) { + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 1 (limit = %d, %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + AMP_OPEN_TEST_LIMIT_PHASE1_LOWER, AMP_OPEN_TEST_LIMIT_PHASE1_UPPER); + + p_rt92_image_1[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_1[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.1 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + memset(p_rt92_image_2, 0x00, tx_num * rx_num * 2); + + /* step 5 */ + /* data calculation and verification */ + /* phase 2, the calculated ratio should be within the phase 2 test limit*/ + + + tddi_ratio_calculation(p_rt92_delta_image); + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < AMP_OPEN_TEST_LIMIT_PHASE2_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > AMP_OPEN_TEST_LIMIT_PHASE2_UPPER)) { + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 2 (limit = %d, %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + AMP_OPEN_TEST_LIMIT_PHASE2_LOWER, AMP_OPEN_TEST_LIMIT_PHASE2_UPPER); + + p_rt92_image_2[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_2[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.2 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + + /* step 6 */ + /* filling out the g_tddi_amp_open_data_output */ + /* 1: fail / 0 : pass */ + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_amp_open_data_output[i * rx_num + j] = + (unsigned char)(p_rt92_image_1[i * rx_num + j]) || p_rt92_image_2[i * rx_num + j]; + } + } + + retval = count; + +exit: + + kfree(p_rt92_image_1); + kfree(p_rt92_image_2); + kfree(p_rt92_delta_image); + kfree(p_report_data_8); + + return count; +} + +static ssize_t test_sysfs_tddi_amp_open_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + if (!g_tddi_amp_open_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_amp_open_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +static ssize_t test_sysfs_burst_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + unsigned long setting; + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting == 1) + f54->is_burst = 1; + else + f54->is_burst = 0; + + return count; +} + +static ssize_t test_sysfs_burst_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", (f54->is_burst == 1) ? "BURST" : "BYTE"); +} + + +static ssize_t test_sysfs_tddi_amp_electrode_open_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int retval = 0; + int i, j, k; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + struct f54_control control = f54->control; + unsigned long setting; + + struct f54_control_91 original_f54_ctrl91; + struct f54_control_99 original_f54_ctrl99; + struct f54_control_182 original_f54_ctrl182; + + unsigned char *p_report_data_8 = NULL; + signed short *p_rt92_image_1 = NULL; + signed short *p_rt92_image_2 = NULL; + signed short *p_rt92_delta_image = NULL; + +#ifdef F54_SHOW_MAX_MIN + signed short min = 0; + signed short max = 0; +#endif + + retval = sstrtoul(buf, 10, &setting); + if (retval) + return retval; + + if (setting != 1) + return -EINVAL; + + + if (g_tddi_amp_open_data_output) + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = kzalloc(tx_num * rx_num, GFP_KERNEL); + if (!g_tddi_amp_open_data_output) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for g_tddi_amp_open_data_output\n", + __func__); + return -ENOMEM; + } + + g_flag_readrt_err = false; + + + p_report_data_8 = kzalloc(tx_num * rx_num * 2, GFP_KERNEL); + if (!p_report_data_8) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_report_data_8\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_delta_image = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_delta_image) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_delta_image\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_1 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_1) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_1\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + p_rt92_image_2 = kzalloc(tx_num * rx_num * sizeof(signed short), GFP_KERNEL); + if (!p_rt92_image_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for p_rt92_image_2\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + + /* keep the original reference high/low capacitance */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_91->address, + original_f54_ctrl91.data, + sizeof(original_f54_ctrl91.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read original data from f54_ctrl91\n", + __func__); + retval = -EIO; + goto exit; + } + /* keep the original integration and reset duration */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + original_f54_ctrl99.data, + sizeof(original_f54_ctrl99.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read original data from f54_ctrl99\n", + __func__); + retval = -EIO; + goto exit; + } + /* keep the original timing control */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_182->address, + original_f54_ctrl182.data, + sizeof(original_f54_ctrl182.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read original data from f54_ctrl182\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 1 */ + /* Wide refcap hi/ lo and feedback, Write 0x0F to F54_ANALOG_CTRL91 */ + control.reg_91->reflo_transcap_capacitance = 0x0f; + control.reg_91->refhi_transcap_capacitance = 0x0f; + control.reg_91->receiver_feedback_capacitance = 0x0f; + control.reg_91->reference_receiver_feedback_capacitance = original_f54_ctrl91.reference_receiver_feedback_capacitance; + control.reg_91->gain_ctrl = original_f54_ctrl91.gain_ctrl; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_91->address, + control.reg_91->data, + sizeof(control.reg_91->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set f54_ctrl91 in step 1\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 2 */ + /* Increase RST_DUR to 1.53us, Write 0x5c to F54_ANALOG_CTRL99 */ + control.reg_99->integration_duration_lsb = original_f54_ctrl99.integration_duration_lsb; + control.reg_99->integration_duration_msb = original_f54_ctrl99.integration_duration_msb; + control.reg_99->reset_duration = 0x5c; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set f54_ctrl99 in step 2\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 3 */ + /* Write 0x02 to F54_ANALOG_CTRL182 (00)/00 and (00)/02 */ + control.reg_182->cbc_timing_ctrl_tx_lsb = ELEC_OPEN_TEST_TX_ON_COUNT & 0xff; + control.reg_182->cbc_timing_ctrl_tx_msb = (ELEC_OPEN_TEST_TX_ON_COUNT >> 8) & 0xff; + control.reg_182->cbc_timing_ctrl_rx_lsb = ELEC_OPEN_TEST_RX_ON_COUNT & 0xff; + control.reg_182->cbc_timing_ctrl_rx_msb = (ELEC_OPEN_TEST_RX_ON_COUNT >> 8) & 0xff; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_182->address, + control.reg_182->data, + sizeof(control.reg_182->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set f54_reg_182 in step 3\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 4 */ + /* Change the INT_DUR as ELEC_OPEN_INT_DUR_ONE */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data from f54_ctrl99 in step 4\n", + __func__); + retval = -EIO; + goto exit; + } + control.reg_99->integration_duration_lsb = ELEC_OPEN_INT_DUR_ONE; + control.reg_99->integration_duration_msb = (ELEC_OPEN_INT_DUR_ONE >> 8) & 0xff; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to seet ELEC_OPEN_INT_DUR_ONE(%d) in step 4\n", + __func__, ELEC_OPEN_INT_DUR_ONE); + retval = -EIO; + goto exit; + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 4\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 5 */ + /* Capture raw capacitance (rt92) image 1 */ + /* Run Report Type 92 */ + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 5. exit\n", + __func__); + retval = -EIO; + g_flag_readrt_err = false; + goto exit; + } + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_1[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + memset(p_report_data_8, 0x00, tx_num * rx_num * 2); + + /* step 6 */ + /* Change the INT_DUR into ELEC_OPEN_INT_DUR_TWO */ + retval = synaptics_rmi4_reg_read(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read data from f54_ctrl99 in step 6\n", + __func__); + retval = -EIO; + goto exit; + } + control.reg_99->integration_duration_lsb = ELEC_OPEN_INT_DUR_TWO; + control.reg_99->integration_duration_msb = (ELEC_OPEN_INT_DUR_TWO >> 8) & 0xff; + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + control.reg_99->data, + sizeof(control.reg_99->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to seet ELEC_OPEN_INT_DUR_TWO(%d) in step 6\n", + __func__, ELEC_OPEN_INT_DUR_TWO); + retval = -EIO; + goto exit; + } + + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 6\n", + __func__); + retval = -EIO; + goto exit; + } + + /* step 7 */ + /* Capture raw capacitance (rt92) image 2 */ + /* Run Report Type 92 */ + retval = test_sysfs_read_report(dev, attr, "92", count, + false, false); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report 92 in step 7. exit\n", + __func__); + retval = -EIO; + goto exit; + } + secure_memcpy(p_report_data_8, tx_num * rx_num * 2, + f54->report_data, f54->report_size, f54->report_size); + + k = 0; + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + p_rt92_image_2[i * rx_num + j] = + (signed short)(p_report_data_8[k] & 0xff) | (signed short)(p_report_data_8[k + 1] << 8); + + k += 2; + } + } + + /* step 8 */ + /* generate the delta image, which is equeal to image2 - image1 */ + /* unit is femtofarad (fF) */ + for (i = 0; i < tx_num * rx_num; i++) { + p_rt92_delta_image[i] = p_rt92_image_2[i] - p_rt92_image_1[i]; + } + + /* step 9 */ + /* restore the original configuration */ + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_91->address, + original_f54_ctrl91.data, + sizeof(original_f54_ctrl91.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore f54_ctrl91 data\n", + __func__); + retval = -EIO; + goto exit; + } + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_99->address, + original_f54_ctrl99.data, + sizeof(original_f54_ctrl99.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore f54_ctrl99 data\n", + __func__); + retval = -EIO; + goto exit; + } + retval = synaptics_rmi4_reg_write(rmi4_data, + control.reg_182->address, + original_f54_ctrl182.data, + sizeof(original_f54_ctrl182.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to restore f54_ctrl182 data\n", + __func__); + retval = -EIO; + goto exit; + } + retval = test_do_command(COMMAND_FORCE_UPDATE); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to do force update in step 9\n", + __func__); + retval = -EIO; + goto exit; + } + + memset(p_rt92_image_1, 0x00, tx_num * rx_num * 2); + + /* step 10 */ + /* phase 1, data verification */ + /* the delta value should be lower than the test limit */ + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < ELEC_OPEN_TEST_LIMIT_ONE_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > ELEC_OPEN_TEST_LIMIT_ONE_UPPER)){ + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 1 (limit: %d - %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + ELEC_OPEN_TEST_LIMIT_ONE_LOWER, ELEC_OPEN_TEST_LIMIT_ONE_UPPER); + + p_rt92_image_1[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_1[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.1 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + memset(p_rt92_image_2, 0x00, tx_num * rx_num * 2); + + /* step 11 */ + /* phase 2, data calculation and verification */ + /* the calculated ratio should be lower than the test limit */ + + + tddi_ratio_calculation(p_rt92_delta_image); + +#ifdef F54_SHOW_MAX_MIN + min = max = p_rt92_delta_image[0]; +#endif + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { +#ifdef F54_SHOW_MAX_MIN + min = min_t(signed short, p_rt92_delta_image[i*rx_num + j], min); + max = max_t(signed short, p_rt92_delta_image[i*rx_num + j], max); +#endif + if ((p_rt92_delta_image[i * rx_num + j] < ELEC_OPEN_TEST_LIMIT_TWO_LOWER) || + (p_rt92_delta_image[i * rx_num + j] > ELEC_OPEN_TEST_LIMIT_TWO_UPPER)){ + + dev_err(f54->rmi4_data->pdev->dev.parent, + "%s: fail at (tx%-2d, rx%-2d) = %-4d at phase 2 (limit: %d - %d)\n", + __func__, i, j, p_rt92_delta_image[i*rx_num + j], + ELEC_OPEN_TEST_LIMIT_TWO_LOWER, ELEC_OPEN_TEST_LIMIT_TWO_UPPER); + + p_rt92_image_2[i*rx_num + j] = _TEST_FAIL; + } + else { + p_rt92_image_2[i*rx_num + j] = _TEST_PASS; + } + } + } +#ifdef F54_SHOW_MAX_MIN + pr_info("%s : ph.2 data range (max, min) = (%-4d, %-4d)\n", __func__, max, min); +#endif + + /* step 12 */ + /* filling out the g_tddi_amp_open_data_output */ + /* 1: fail / 0 : pass */ + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + g_tddi_amp_open_data_output[i * rx_num + j] = + (unsigned char)(p_rt92_image_1[i * rx_num + j]) || p_rt92_image_2[i * rx_num + j]; + } + } + + retval = count; + +exit: + + kfree(p_report_data_8); + kfree(p_rt92_image_1); + kfree(p_rt92_image_2); + kfree(p_rt92_delta_image); + + return count; +} + +static ssize_t test_sysfs_tddi_amp_electrode_open_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, j; + int tx_num = f54->tx_assigned; + int rx_num = f54->rx_assigned; + int fail_count = 0; + + check_ito_test_flag = 0; + + if (!g_tddi_amp_open_data_output) + return -EINVAL; + + + + if (g_flag_readrt_err) { + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + return snprintf(buf, PAGE_SIZE, "\nERROR: fail to read report image\n"); + } + + for (i = 0; i < tx_num; i++) { + for (j = 0; j < rx_num; j++) { + if (g_tddi_amp_open_data_output[i * rx_num + j] != _TEST_PASS) { + + fail_count += 1; + } + } + } + + kfree(g_tddi_amp_open_data_output); + g_tddi_amp_open_data_output = NULL; + + if (!fail_count) + check_ito_test_flag += 1; + + return snprintf(buf, PAGE_SIZE, "%s\n", (fail_count == 0) ? "PASS" : "FAIL"); +} + +/* tddi f54 test reporting - */ + + +static ssize_t test_sysfs_data_read(struct file *data_file, + struct kobject *kobj, struct bin_attribute *attributes, + char *buf, loff_t pos, size_t count) +{ + int retval; + unsigned int read_size; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + retval = test_check_for_idle_status(); + if (retval < 0) + goto exit; + + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report type %d data not available\n", + __func__, f54->report_type); + retval = -EINVAL; + goto exit; + } + + if ((f54->data_pos + count) > f54->report_size) + read_size = f54->report_size - f54->data_pos; + else + read_size = min_t(unsigned int, count, f54->report_size); + + retval = secure_memcpy(buf, count, f54->report_data + f54->data_pos, + f54->data_buffer_size - f54->data_pos, read_size); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to copy report data\n", + __func__); + goto exit; + } + f54->data_pos += read_size; + retval = read_size; + +exit: + mutex_unlock(&f54->status_mutex); + + return retval; +} + +static void test_report_work(struct work_struct *work) +{ + int retval; + unsigned char report_index[2]; + unsigned int byte_delay_us; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + mutex_lock(&f54->status_mutex); + + if (f54->status != STATUS_BUSY) { + retval = f54->status; + goto exit; + } + + retval = test_wait_for_command_completion(); + if (retval < 0) { + retval = STATUS_ERROR; + goto exit; + } + + test_set_report_size(); + if (f54->report_size == 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Report data size = 0\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + if (f54->data_buffer_size < f54->report_size) { + if (f54->data_buffer_size) + kfree(f54->report_data); + f54->report_data = kzalloc(f54->report_size, GFP_KERNEL); + if (!f54->report_data) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for data buffer\n", + __func__); + f54->data_buffer_size = 0; + retval = STATUS_ERROR; + goto exit; + } + f54->data_buffer_size = f54->report_size; + } + + report_index[0] = 0; + report_index[1] = 0; + + retval = synaptics_rmi4_reg_write(rmi4_data, + f54->data_base_addr + REPORT_INDEX_OFFSET, + report_index, + sizeof(report_index)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to write report data index\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) { + byte_delay_us = rmi4_data->hw_if->board_data->byte_delay_us; + rmi4_data->hw_if->board_data->byte_delay_us = 0; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->data_base_addr + REPORT_DATA_OFFSET, + f54->report_data, + f54->report_size); + + if ((rmi4_data->hw_if->bus_access->type == BUS_SPI) && f54->burst_read && f54->is_burst) + rmi4_data->hw_if->board_data->byte_delay_us = byte_delay_us; + + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read report data\n", + __func__); + retval = STATUS_ERROR; + goto exit; + } + + retval = STATUS_IDLE; + +exit: + mutex_unlock(&f54->status_mutex); + + if (retval == STATUS_ERROR) + f54->report_size = 0; + + f54->status = retval; + return; +} + +static void test_remove_sysfs(void) +{ + sysfs_remove_group(f54->sysfs_dir, &attr_group); + sysfs_remove_bin_file(f54->sysfs_dir, &test_report_data); + kobject_put(f54->sysfs_dir); + + return; +} + + +static int tp_data_dump_proc_show(struct seq_file *m, void *v) { + int retval = 0; + int i, j, k; + unsigned short numberOfRows = f54->tx_assigned; + unsigned short numberOfColums = f54->rx_assigned; + short temp; + short *p_data = NULL; + + + seq_printf(m, "tx:%d\n", numberOfColums); + seq_printf(m, "rx:%d\n", numberOfRows); + retval = test_sysfs_read_report(NULL, NULL, "2", 2, true, false); + p_data = (unsigned short*)kzalloc(numberOfRows * numberOfColums * 2, GFP_KERNEL); + for (i = 0, k = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + temp = f54->report_data[k] | (f54->report_data[k+1] << 8); + p_data[i*numberOfColums+j] = temp; + k = k + 2; + } + } + + for (i = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + seq_printf(m, "%-5d ", p_data[i * numberOfColums + j]); + } + seq_printf(m, "\n"); + } + seq_printf(m, "tx:%d\n", numberOfColums); + seq_printf(m, "rx:%d\n", numberOfRows); + retval = test_sysfs_read_report(NULL, NULL, "92", 2, true, false); + p_data = (unsigned short*)kzalloc(numberOfRows * numberOfColums * 2, GFP_KERNEL); + for (i = 0, k = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + temp = f54->report_data[k] | (f54->report_data[k+1] << 8); + p_data[i*numberOfColums+j] = temp; + k = k + 2; + } + } + + for (i = 0; i < numberOfRows; i++) { + for (j = 0; j < numberOfColums; j++) { + seq_printf(m, "%-5d ", p_data[i * numberOfColums + j]); + } + seq_printf(m, "\n"); + } + if (p_data) + kfree(p_data); + return 0; +} + +static int tp_data_dump_proc_open(struct inode *inode, struct file *file) { + return single_open(file, tp_data_dump_proc_show, NULL); +} + +static const struct file_operations tp_data_dump_proc_fops = { + .owner = THIS_MODULE, + .open = tp_data_dump_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int test_set_sysfs(void) +{ + int retval; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + + proc_create("tp_data_dump", 0, NULL, &tp_data_dump_proc_fops); + + f54->sysfs_dir = kobject_create_and_add(SYSFS_FOLDER_NAME, + &rmi4_data->input_dev->dev.kobj); + if (!f54->sysfs_dir) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs directory\n", + __func__); + goto exit_directory; + } + + retval = sysfs_create_bin_file(f54->sysfs_dir, &test_report_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", + __func__); + goto exit_bin_file; + } + + retval = sysfs_create_group(f54->sysfs_dir, &attr_group); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs attributes\n", + __func__); + goto exit_attributes; + } + + return 0; + +exit_attributes: + sysfs_remove_group(f54->sysfs_dir, &attr_group); + sysfs_remove_bin_file(f54->sysfs_dir, &test_report_data); + +exit_bin_file: + kobject_put(f54->sysfs_dir); + +exit_directory: + return -ENODEV; +} + +static void test_free_control_mem(void) +{ + struct f54_control control = f54->control; + + kfree(control.reg_7); + kfree(control.reg_41); + kfree(control.reg_57); + kfree(control.reg_86); + kfree(control.reg_88); + kfree(control.reg_91); + kfree(control.reg_96); + kfree(control.reg_99); + kfree(control.reg_110); + kfree(control.reg_149); + kfree(control.reg_182); + kfree(control.reg_188); + kfree(control.reg_223); + + return; +} + +static void test_set_data(void) +{ + unsigned short reg_addr; + + reg_addr = f54->data_base_addr + REPORT_DATA_OFFSET + 1; + + /* data 4 */ + if (f54->query.has_sense_frequency_control) + reg_addr++; + + /* data 5 reserved */ + + /* data 6 */ + if (f54->query.has_interference_metric) + reg_addr += 2; + + /* data 7 */ + if (f54->query.has_one_byte_report_rate | + f54->query.has_two_byte_report_rate) + reg_addr++; + if (f54->query.has_two_byte_report_rate) + reg_addr++; + + /* data 8 */ + if (f54->query.has_variance_metric) + reg_addr += 2; + + /* data 9 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += 2; + + /* data 10 */ + if (f54->query.has_multi_metric_state_machine | + f54->query.has_noise_state) + reg_addr++; + + /* data 11 */ + if (f54->query.has_status) + reg_addr++; + + /* data 12 */ + if (f54->query.has_slew_metric) + reg_addr += 2; + + /* data 13 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += 2; + + /* data 14 */ + if (f54->query_13.has_cidim) + reg_addr++; + + /* data 15 */ + if (f54->query_13.has_rail_im) + reg_addr++; + + /* data 16 */ + if (f54->query_13.has_noise_mitigation_enhancement) + reg_addr++; + + /* data 17 */ + if (f54->query_16.has_data17) + reg_addr++; + + /* data 18 */ + if (f54->query_21.has_query24_data18) + reg_addr++; + + /* data 19 */ + if (f54->query_21.has_data19) + reg_addr++; + + /* data_20 */ + if (f54->query_25.has_ctrl109) + reg_addr++; + + /* data 21 */ + if (f54->query_27.has_data21) + reg_addr++; + + /* data 22 */ + if (f54->query_27.has_data22) + reg_addr++; + + /* data 23 */ + if (f54->query_29.has_data23) + reg_addr++; + + /* data 24 */ + if (f54->query_32.has_data24) + reg_addr++; + + /* data 25 */ + if (f54->query_35.has_data25) + reg_addr++; + + /* data 26 */ + if (f54->query_35.has_data26) + reg_addr++; + + /* data 27 */ + if (f54->query_46.has_data27) + reg_addr++; + + /* data 28 */ + if (f54->query_46.has_data28) + reg_addr++; + + /* data 29 30 reserved */ + + /* data 31 */ + if (f54->query_49.has_data31) { + f54->data_31.address = reg_addr; + reg_addr++; + } + + return; +} + +static int test_set_controls(void) +{ + int retval; + unsigned char length; + unsigned char num_of_sensing_freqs; + unsigned short reg_addr = f54->control_base_addr; + struct f54_control *control = &f54->control; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + num_of_sensing_freqs = f54->query.number_of_sensing_frequencies; + + /* control 0 */ + reg_addr += CONTROL_0_SIZE; + + /* control 1 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_1_SIZE; + + /* control 2 */ + reg_addr += CONTROL_2_SIZE; + + /* control 3 */ + if (f54->query.has_pixel_touch_threshold_adjustment) + reg_addr += CONTROL_3_SIZE; + + /* controls 4 5 6 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_4_6_SIZE; + + /* control 7 */ + if (f54->query.touch_controller_family == 1) { + control->reg_7 = kzalloc(sizeof(*(control->reg_7)), + GFP_KERNEL); + if (!control->reg_7) + goto exit_no_mem; + control->reg_7->address = reg_addr; + reg_addr += CONTROL_7_SIZE; + } + + /* controls 8 9 */ + if ((f54->query.touch_controller_family == 0) || + (f54->query.touch_controller_family == 1)) + reg_addr += CONTROL_8_9_SIZE; + + /* control 10 */ + if (f54->query.has_interference_metric) + reg_addr += CONTROL_10_SIZE; + + /* control 11 */ + if (f54->query.has_ctrl11) + reg_addr += CONTROL_11_SIZE; + + /* controls 12 13 */ + if (f54->query.has_relaxation_control) + reg_addr += CONTROL_12_13_SIZE; + + /* controls 14 15 16 */ + if (f54->query.has_sensor_assignment) { + reg_addr += CONTROL_14_SIZE; + reg_addr += CONTROL_15_SIZE * f54->query.num_of_rx_electrodes; + reg_addr += CONTROL_16_SIZE * f54->query.num_of_tx_electrodes; + } + + /* controls 17 18 19 */ + if (f54->query.has_sense_frequency_control) { + reg_addr += CONTROL_17_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_18_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_19_SIZE * num_of_sensing_freqs; + } + + /* control 20 */ + reg_addr += CONTROL_20_SIZE; + + /* control 21 */ + if (f54->query.has_sense_frequency_control) + reg_addr += CONTROL_21_SIZE; + + /* controls 22 23 24 25 26 */ + if (f54->query.has_firmware_noise_mitigation) + reg_addr += CONTROL_22_26_SIZE; + + /* control 27 */ + if (f54->query.has_iir_filter) + reg_addr += CONTROL_27_SIZE; + + /* control 28 */ + if (f54->query.has_firmware_noise_mitigation) + reg_addr += CONTROL_28_SIZE; + + /* control 29 */ + if (f54->query.has_cmn_removal) + reg_addr += CONTROL_29_SIZE; + + /* control 30 */ + if (f54->query.has_cmn_maximum) + reg_addr += CONTROL_30_SIZE; + + /* control 31 */ + if (f54->query.has_touch_hysteresis) + reg_addr += CONTROL_31_SIZE; + + /* controls 32 33 34 35 */ + if (f54->query.has_edge_compensation) + reg_addr += CONTROL_32_35_SIZE; + + /* control 36 */ + if ((f54->query.curve_compensation_mode == 1) || + (f54->query.curve_compensation_mode == 2)) { + if (f54->query.curve_compensation_mode == 1) { + length = max(f54->query.num_of_rx_electrodes, + f54->query.num_of_tx_electrodes); + } else if (f54->query.curve_compensation_mode == 2) { + length = f54->query.num_of_rx_electrodes; + } + reg_addr += CONTROL_36_SIZE * length; + } + + /* control 37 */ + if (f54->query.curve_compensation_mode == 2) + reg_addr += CONTROL_37_SIZE * f54->query.num_of_tx_electrodes; + + /* controls 38 39 40 */ + if (f54->query.has_per_frequency_noise_control) { + reg_addr += CONTROL_38_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_39_SIZE * num_of_sensing_freqs; + reg_addr += CONTROL_40_SIZE * num_of_sensing_freqs; + } + + /* control 41 */ + if (f54->query.has_signal_clarity) { + control->reg_41 = kzalloc(sizeof(*(control->reg_41)), + GFP_KERNEL); + if (!control->reg_41) + goto exit_no_mem; + control->reg_41->address = reg_addr; + reg_addr += CONTROL_41_SIZE; + } + + /* control 42 */ + if (f54->query.has_variance_metric) + reg_addr += CONTROL_42_SIZE; + + /* controls 43 44 45 46 47 48 49 50 51 52 53 54 */ + if (f54->query.has_multi_metric_state_machine) + reg_addr += CONTROL_43_54_SIZE; + + /* controls 55 56 */ + if (f54->query.has_0d_relaxation_control) + reg_addr += CONTROL_55_56_SIZE; + + /* control 57 */ + if (f54->query.has_0d_acquisition_control) { + control->reg_57 = kzalloc(sizeof(*(control->reg_57)), + GFP_KERNEL); + if (!control->reg_57) + goto exit_no_mem; + control->reg_57->address = reg_addr; + reg_addr += CONTROL_57_SIZE; + } + + /* control 58 */ + if (f54->query.has_0d_acquisition_control) + reg_addr += CONTROL_58_SIZE; + + /* control 59 */ + if (f54->query.has_h_blank) + reg_addr += CONTROL_59_SIZE; + + /* controls 60 61 62 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_60_62_SIZE; + + /* control 63 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank) || + (f54->query.has_slew_metric) || + (f54->query.has_slew_option) || + (f54->query.has_noise_mitigation2)) + reg_addr += CONTROL_63_SIZE; + + /* controls 64 65 66 67 */ + if (f54->query.has_h_blank) + reg_addr += CONTROL_64_67_SIZE * 7; + else if ((f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_64_67_SIZE; + + /* controls 68 69 70 71 72 73 */ + if ((f54->query.has_h_blank) || + (f54->query.has_v_blank) || + (f54->query.has_long_h_blank)) + reg_addr += CONTROL_68_73_SIZE; + + /* control 74 */ + if (f54->query.has_slew_metric) + reg_addr += CONTROL_74_SIZE; + + /* control 75 */ + if (f54->query.has_enhanced_stretch) + reg_addr += CONTROL_75_SIZE * num_of_sensing_freqs; + + /* control 76 */ + if (f54->query.has_startup_fast_relaxation) + reg_addr += CONTROL_76_SIZE; + + /* controls 77 78 */ + if (f54->query.has_esd_control) + reg_addr += CONTROL_77_78_SIZE; + + /* controls 79 80 81 82 83 */ + if (f54->query.has_noise_mitigation2) + reg_addr += CONTROL_79_83_SIZE; + + /* controls 84 85 */ + if (f54->query.has_energy_ratio_relaxation) + reg_addr += CONTROL_84_85_SIZE; + + /* control 86 */ + if (f54->query_13.has_ctrl86) { + control->reg_86 = kzalloc(sizeof(*(control->reg_86)), + GFP_KERNEL); + if (!control->reg_86) + goto exit_no_mem; + control->reg_86->address = reg_addr; + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->control.reg_86->address, + f54->control.reg_86->data, + sizeof(f54->control.reg_86->data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read sense display ratio\n", + __func__); + return retval; + } + reg_addr += CONTROL_86_SIZE; + } + + /* control 87 */ + if (f54->query_13.has_ctrl87) + reg_addr += CONTROL_87_SIZE; + + /* control 88 */ + if (f54->query.has_ctrl88) { + control->reg_88 = kzalloc(sizeof(*(control->reg_88)), + GFP_KERNEL); + if (!control->reg_88) + goto exit_no_mem; + control->reg_88->address = reg_addr; + reg_addr += CONTROL_88_SIZE; + } + + /* control 89 */ + if (f54->query_13.has_cidim || + f54->query_13.has_noise_mitigation_enhancement || + f54->query_13.has_rail_im) + reg_addr += CONTROL_89_SIZE; + + /* control 90 */ + if (f54->query_15.has_ctrl90) + reg_addr += CONTROL_90_SIZE; + + /* control 91 */ + if (f54->query_21.has_ctrl91) { + /* tddi f54 test reporting + */ + control->reg_91 = kzalloc(sizeof(*(control->reg_91)), + GFP_KERNEL); + if (!control->reg_91) + goto exit_no_mem; + control->reg_91->address = reg_addr; + /* tddi f54 test reporting - */ + reg_addr += CONTROL_91_SIZE; + } + + /* control 92 */ + if (f54->query_16.has_ctrl92) + reg_addr += CONTROL_92_SIZE; + + /* control 93 */ + if (f54->query_16.has_ctrl93) + reg_addr += CONTROL_93_SIZE; + + /* control 94 */ + if (f54->query_16.has_ctrl94_query18) + reg_addr += CONTROL_94_SIZE; + + /* control 95 */ + if (f54->query_16.has_ctrl95_query19) + reg_addr += CONTROL_95_SIZE; + + /* control 96 */ + if (f54->query_21.has_ctrl96) { + /* tddi f54 test reporting + */ + control->reg_96 = kzalloc(sizeof(*(control->reg_96)), + GFP_KERNEL); + if (!control->reg_96) + goto exit_no_mem; + control->reg_96->address = reg_addr; + /* tddi f54 test reporting - */ + reg_addr += CONTROL_96_SIZE; + } + + /* control 97 */ + if (f54->query_21.has_ctrl97) + reg_addr += CONTROL_97_SIZE; + + /* control 98 */ + if (f54->query_21.has_ctrl98) + reg_addr += CONTROL_98_SIZE; + + /* control 99 */ + if (f54->query.touch_controller_family == 2) { + /* tddi f54 test reporting + */ + control->reg_99 = kzalloc(sizeof(*(control->reg_99)), + GFP_KERNEL); + if (!control->reg_99) + goto exit_no_mem; + control->reg_99->address = reg_addr; + /* tddi f54 test reporting - */ + reg_addr += CONTROL_99_SIZE; + } + + /* control 100 */ + if (f54->query_16.has_ctrl100) + reg_addr += CONTROL_100_SIZE; + + /* control 101 */ + if (f54->query_22.has_ctrl101) + reg_addr += CONTROL_101_SIZE; + + + /* control 102 */ + if (f54->query_23.has_ctrl102) + reg_addr += CONTROL_102_SIZE; + + /* control 103 */ + if (f54->query_22.has_ctrl103_query26) { + f54->skip_preparation = true; + reg_addr += CONTROL_103_SIZE; + } + + /* control 104 */ + if (f54->query_22.has_ctrl104) + reg_addr += CONTROL_104_SIZE; + + /* control 105 */ + if (f54->query_22.has_ctrl105) + reg_addr += CONTROL_105_SIZE; + + /* control 106 */ + if (f54->query_25.has_ctrl106) + reg_addr += CONTROL_106_SIZE; + + /* control 107 */ + if (f54->query_25.has_ctrl107) + reg_addr += CONTROL_107_SIZE; + + /* control 108 */ + if (f54->query_25.has_ctrl108) + reg_addr += CONTROL_108_SIZE; + + /* control 109 */ + if (f54->query_25.has_ctrl109) + reg_addr += CONTROL_109_SIZE; + + /* control 110 */ + if (f54->query_27.has_ctrl110) { + control->reg_110 = kzalloc(sizeof(*(control->reg_110)), + GFP_KERNEL); + if (!control->reg_110) + goto exit_no_mem; + control->reg_110->address = reg_addr; + reg_addr += CONTROL_110_SIZE; + } + + /* control 111 */ + if (f54->query_27.has_ctrl111) + reg_addr += CONTROL_111_SIZE; + + /* control 112 */ + if (f54->query_27.has_ctrl112) + reg_addr += CONTROL_112_SIZE; + + /* control 113 */ + if (f54->query_27.has_ctrl113) + reg_addr += CONTROL_113_SIZE; + + /* control 114 */ + if (f54->query_27.has_ctrl114) + reg_addr += CONTROL_114_SIZE; + + /* control 115 */ + if (f54->query_29.has_ctrl115) + reg_addr += CONTROL_115_SIZE; + + /* control 116 */ + if (f54->query_29.has_ctrl116) + reg_addr += CONTROL_116_SIZE; + + /* control 117 */ + if (f54->query_29.has_ctrl117) + reg_addr += CONTROL_117_SIZE; + + /* control 118 */ + if (f54->query_30.has_ctrl118) + reg_addr += CONTROL_118_SIZE; + + /* control 119 */ + if (f54->query_30.has_ctrl119) + reg_addr += CONTROL_119_SIZE; + + /* control 120 */ + if (f54->query_30.has_ctrl120) + reg_addr += CONTROL_120_SIZE; + + /* control 121 */ + if (f54->query_30.has_ctrl121) + reg_addr += CONTROL_121_SIZE; + + /* control 122 */ + if (f54->query_30.has_ctrl122_query31) + reg_addr += CONTROL_122_SIZE; + + /* control 123 */ + if (f54->query_30.has_ctrl123) + reg_addr += CONTROL_123_SIZE; + + /* control 124 */ + if (f54->query_30.has_ctrl124) + reg_addr += CONTROL_124_SIZE; + + /* control 125 */ + if (f54->query_32.has_ctrl125) + reg_addr += CONTROL_125_SIZE; + + /* control 126 */ + if (f54->query_32.has_ctrl126) + reg_addr += CONTROL_126_SIZE; + + /* control 127 */ + if (f54->query_32.has_ctrl127) + reg_addr += CONTROL_127_SIZE; + + /* control 128 */ + if (f54->query_33.has_ctrl128) + reg_addr += CONTROL_128_SIZE; + + /* control 129 */ + if (f54->query_33.has_ctrl129) + reg_addr += CONTROL_129_SIZE; + + /* control 130 */ + if (f54->query_33.has_ctrl130) + reg_addr += CONTROL_130_SIZE; + + /* control 131 */ + if (f54->query_33.has_ctrl131) + reg_addr += CONTROL_131_SIZE; + + /* control 132 */ + if (f54->query_33.has_ctrl132) + reg_addr += CONTROL_132_SIZE; + + /* control 133 */ + if (f54->query_33.has_ctrl133) + reg_addr += CONTROL_133_SIZE; + + /* control 134 */ + if (f54->query_33.has_ctrl134) + reg_addr += CONTROL_134_SIZE; + + /* control 135 */ + if (f54->query_35.has_ctrl135) + reg_addr += CONTROL_135_SIZE; + + /* control 136 */ + if (f54->query_35.has_ctrl136) + reg_addr += CONTROL_136_SIZE; + + /* control 137 */ + if (f54->query_35.has_ctrl137) + reg_addr += CONTROL_137_SIZE; + + /* control 138 */ + if (f54->query_35.has_ctrl138) + reg_addr += CONTROL_138_SIZE; + + /* control 139 */ + if (f54->query_35.has_ctrl139) + reg_addr += CONTROL_139_SIZE; + + /* control 140 */ + if (f54->query_35.has_ctrl140) + reg_addr += CONTROL_140_SIZE; + + /* control 141 */ + if (f54->query_36.has_ctrl141) + reg_addr += CONTROL_141_SIZE; + + /* control 142 */ + if (f54->query_36.has_ctrl142) + reg_addr += CONTROL_142_SIZE; + + /* control 143 */ + if (f54->query_36.has_ctrl143) + reg_addr += CONTROL_143_SIZE; + + /* control 144 */ + if (f54->query_36.has_ctrl144) + reg_addr += CONTROL_144_SIZE; + + /* control 145 */ + if (f54->query_36.has_ctrl145) + reg_addr += CONTROL_145_SIZE; + + /* control 146 */ + if (f54->query_36.has_ctrl146) + reg_addr += CONTROL_146_SIZE; + + /* control 147 */ + if (f54->query_38.has_ctrl147) + reg_addr += CONTROL_147_SIZE; + + /* control 148 */ + if (f54->query_38.has_ctrl148) + reg_addr += CONTROL_148_SIZE; + + /* control 149 */ + if (f54->query_38.has_ctrl149) { + control->reg_149 = kzalloc(sizeof(*(control->reg_149)), + GFP_KERNEL); + if (!control->reg_149) + goto exit_no_mem; + control->reg_149->address = reg_addr; + reg_addr += CONTROL_149_SIZE; + } + + /* control 150 */ + if (f54->query_38.has_ctrl150) + reg_addr += CONTROL_150_SIZE; + + /* control 151 */ + if (f54->query_38.has_ctrl151) + reg_addr += CONTROL_151_SIZE; + + /* control 152 */ + if (f54->query_38.has_ctrl152) + reg_addr += CONTROL_152_SIZE; + + /* control 153 */ + if (f54->query_38.has_ctrl153) + reg_addr += CONTROL_153_SIZE; + + /* control 154 */ + if (f54->query_39.has_ctrl154) + reg_addr += CONTROL_154_SIZE; + + /* control 155 */ + if (f54->query_39.has_ctrl155) + reg_addr += CONTROL_155_SIZE; + + /* control 156 */ + if (f54->query_39.has_ctrl156) + reg_addr += CONTROL_156_SIZE; + + /* controls 157 158 */ + if (f54->query_39.has_ctrl157_ctrl158) + reg_addr += CONTROL_157_158_SIZE; + + /* controls 159 to 162 reserved */ + + /* control 163 */ + if (f54->query_40.has_ctrl163_query41) + reg_addr += CONTROL_163_SIZE; + + /* control 164 reserved */ + + /* control 165 */ + if (f54->query_40.has_ctrl165_query42) + reg_addr += CONTROL_165_SIZE; + + /* control 166 */ + if (f54->query_40.has_ctrl166) + reg_addr += CONTROL_166_SIZE; + + /* control 167 */ + if (f54->query_40.has_ctrl167) + reg_addr += CONTROL_167_SIZE; + + /* control 168 */ + if (f54->query_40.has_ctrl168) + reg_addr += CONTROL_168_SIZE; + + /* control 169 */ + if (f54->query_40.has_ctrl169) + reg_addr += CONTROL_169_SIZE; + + /* control 170 reserved */ + + /* control 171 */ + if (f54->query_43.has_ctrl171) + reg_addr += CONTROL_171_SIZE; + + /* control 172 */ + if (f54->query_43.has_ctrl172_query44_query45) + reg_addr += CONTROL_172_SIZE; + + /* control 173 */ + if (f54->query_43.has_ctrl173) + reg_addr += CONTROL_173_SIZE; + + /* control 174 */ + if (f54->query_43.has_ctrl174) + reg_addr += CONTROL_174_SIZE; + + /* control 175 */ + if (f54->query_43.has_ctrl175) + reg_addr += CONTROL_175_SIZE; + + /* control 176 */ + if (f54->query_46.has_ctrl176) + reg_addr += CONTROL_176_SIZE; + + /* controls 177 178 */ + if (f54->query_46.has_ctrl177_ctrl178) + reg_addr += CONTROL_177_178_SIZE; + + /* control 179 */ + if (f54->query_46.has_ctrl179) + reg_addr += CONTROL_179_SIZE; + + /* controls 180 to 181 reserved */ + + /* control 182 */ + if (f54->query_47.has_ctrl182) { + control->reg_182 = kzalloc(sizeof(*(control->reg_182)), + GFP_KERNEL); + if (!control->reg_182) + goto exit_no_mem; + control->reg_182->address = reg_addr; + reg_addr += CONTROL_182_SIZE; + } + + /* control 183 */ + if (f54->query_47.has_ctrl183) + reg_addr += CONTROL_183_SIZE; + + /* control 184 reserved */ + + /* control 185 */ + if (f54->query_47.has_ctrl185) + reg_addr += CONTROL_185_SIZE; + + /* control 186 */ + if (f54->query_47.has_ctrl186) + reg_addr += CONTROL_186_SIZE; + + /* control 187 */ + if (f54->query_47.has_ctrl187) + reg_addr += CONTROL_187_SIZE; + + /* control 188 */ + if (f54->query_49.has_ctrl188) { + control->reg_188 = kzalloc(sizeof(*(control->reg_188)), + GFP_KERNEL); + if (!control->reg_188) + goto exit_no_mem; + control->reg_188->address = reg_addr; + reg_addr += CONTROL_188_SIZE; + } + + /* control 189 - 195 reserved */ + + /* control 196 */ + if (f54->query_51.has_ctrl196) + reg_addr += CONTROL_196_SIZE; + + /* control 197 - 217 reserved */ + + /* control 218 reserved */ + if (f54->query_61.has_ctrl218) + reg_addr += CONTROL_218_SIZE; + + /* control 219 - 222 reserved */ + + /* control 223 reserved */ + if (f54->query_64.has_ctrl103_sub3) { + control->reg_223 = kzalloc(sizeof(*(control->reg_223)), + GFP_KERNEL); + if (!control->reg_223) + goto exit_no_mem; + control->reg_223->address = reg_addr; + reg_addr += CONTROL_223_SIZE; + } + + return 0; + +exit_no_mem: + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for control registers\n", + __func__); + return -ENOMEM; +} + +static int test_set_queries(void) +{ + int retval; + unsigned char offset; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr, + f54->query.data, + sizeof(f54->query.data)); + if (retval < 0) + return retval; + + offset = sizeof(f54->query.data); + + /* query 12 */ + if (f54->query.has_sense_frequency_control == 0) + offset -= 1; + + /* query 13 */ + if (f54->query.has_query13) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_13.data, + sizeof(f54->query_13.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 14 */ + if (f54->query_13.has_ctrl87) + offset += 1; + + /* query 15 */ + if (f54->query.has_query15) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_15.data, + sizeof(f54->query_15.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 16 */ + if (f54->query_15.has_query16) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_16.data, + sizeof(f54->query_16.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 17 */ + if (f54->query_16.has_query17) + offset += 1; + + /* query 18 */ + if (f54->query_16.has_ctrl94_query18) + offset += 1; + + /* query 19 */ + if (f54->query_16.has_ctrl95_query19) + offset += 1; + + /* query 20 */ + if (f54->query_15.has_query20) + offset += 1; + + /* query 21 */ + if (f54->query_15.has_query21) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_21.data, + sizeof(f54->query_21.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 22 */ + if (f54->query_15.has_query22) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_22.data, + sizeof(f54->query_22.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 23 */ + if (f54->query_22.has_query23) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_23.data, + sizeof(f54->query_23.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 24 */ + if (f54->query_21.has_query24_data18) + offset += 1; + + /* query 25 */ + if (f54->query_15.has_query25) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_25.data, + sizeof(f54->query_25.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 26 */ + if (f54->query_22.has_ctrl103_query26) + offset += 1; + + /* query 27 */ + if (f54->query_25.has_query27) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_27.data, + sizeof(f54->query_27.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 28 */ + if (f54->query_22.has_query28) + offset += 1; + + /* query 29 */ + if (f54->query_27.has_query29) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_29.data, + sizeof(f54->query_29.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 30 */ + if (f54->query_29.has_query30) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_30.data, + sizeof(f54->query_30.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 31 */ + if (f54->query_30.has_ctrl122_query31) + offset += 1; + + /* query 32 */ + if (f54->query_30.has_query32) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_32.data, + sizeof(f54->query_32.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 33 */ + if (f54->query_32.has_query33) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_33.data, + sizeof(f54->query_33.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 34 */ + if (f54->query_32.has_query34) + offset += 1; + + /* query 35 */ + if (f54->query_32.has_query35) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_35.data, + sizeof(f54->query_35.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 36 */ + if (f54->query_33.has_query36) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_36.data, + sizeof(f54->query_36.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 37 */ + if (f54->query_36.has_query37) + offset += 1; + + /* query 38 */ + if (f54->query_36.has_query38) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_38.data, + sizeof(f54->query_38.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 39 */ + if (f54->query_38.has_query39) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_39.data, + sizeof(f54->query_39.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 40 */ + if (f54->query_39.has_query40) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_40.data, + sizeof(f54->query_40.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 41 */ + if (f54->query_40.has_ctrl163_query41) + offset += 1; + + /* query 42 */ + if (f54->query_40.has_ctrl165_query42) + offset += 1; + + /* query 43 */ + if (f54->query_40.has_query43) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_43.data, + sizeof(f54->query_43.data)); + if (retval < 0) + return retval; + offset += 1; + } + + if (f54->query_43.has_ctrl172_query44_query45) + offset += 2; + + /* query 46 */ + if (f54->query_43.has_query46) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_46.data, + sizeof(f54->query_46.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 47 */ + if (f54->query_46.has_query47) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_47.data, + sizeof(f54->query_47.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 48 reserved */ + + /* query 49 */ + if (f54->query_47.has_query49) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_49.data, + sizeof(f54->query_49.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 50 */ + if (f54->query_49.has_query50) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_50.data, + sizeof(f54->query_50.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 51 */ + if (f54->query_50.has_query51) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_51.data, + sizeof(f54->query_51.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* tddi f54 test reporting + */ + + /* query 52 reserved */ + + /* queries 53 54 */ + if (f54->query_51.has_query53_query54_ctrl198) + offset += 2; + + /* query 55 */ + if (f54->query_51.has_query55) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_55.data, + sizeof(f54->query_55.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 56 */ + if (f54->query_55.has_query56) + offset += 1; + + /* query 57 */ + if (f54->query_55.has_query57) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_57.data, + sizeof(f54->query_57.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 58 */ + if (f54->query_57.has_query58) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_58.data, + sizeof(f54->query_58.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 59 */ + if (f54->query_58.has_query59) + offset += 1; + + /* queries 60 */ + if (f54->query_58.has_query60) + offset += 1; + + /* queries 61 */ + if (f54->query_58.has_query61) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_61.data, + sizeof(f54->query_61.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 62 63 */ + if (f54->query_61.has_ctrl215_query62_query63) + offset += 2; + + /* queries 64 */ + if (f54->query_61.has_query64) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_64.data, + sizeof(f54->query_64.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 65 */ + if (f54->query_64.has_query65) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_65.data, + sizeof(f54->query_65.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 66 */ + if (f54->query_65.has_query66_ctrl231) + offset += 1; + + /* queries 67 */ + if (f54->query_65.has_query67) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_67.data, + sizeof(f54->query_67.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 68 */ + if (f54->query_67.has_query68) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_68.data, + sizeof(f54->query_68.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 69 */ + if (f54->query_68.has_query69) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f54->query_base_addr + offset, + f54->query_69.data, + sizeof(f54->query_69.data)); + if (retval < 0) + return retval; + offset += 1; + } + + f54->burst_read = f54->query_69.burst_mode_report_type_enabled; + /* tddi f54 test reporting - */ + + return 0; +} + +static void test_f54_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count, + unsigned char page) +{ + unsigned char ii; + unsigned char intr_offset; + + f54->query_base_addr = fd->query_base_addr | (page << 8); + f54->control_base_addr = fd->ctrl_base_addr | (page << 8); + f54->data_base_addr = fd->data_base_addr | (page << 8); + f54->command_base_addr = fd->cmd_base_addr | (page << 8); + + f54->intr_reg_num = (intr_count + 7) / 8; + if (f54->intr_reg_num != 0) + f54->intr_reg_num -= 1; + + f54->intr_mask = 0; + intr_offset = intr_count % 8; + for (ii = intr_offset; + ii < (fd->intr_src_count + intr_offset); + ii++) { + f54->intr_mask |= 1 << ii; + } + + return; +} + +static int test_f55_set_controls(void) +{ + unsigned char offset = 0; + + /* controls 0 1 2 */ + if (f55->query.has_sensor_assignment) + offset += 3; + + /* control 3 */ + if (f55->query.has_edge_compensation) + offset++; + + /* control 4 */ + if (f55->query.curve_compensation_mode == 0x1 || + f55->query.curve_compensation_mode == 0x2) + offset++; + + /* control 5 */ + if (f55->query.curve_compensation_mode == 0x2) + offset++; + + /* control 6 */ + if (f55->query.has_ctrl6) + offset++; + + /* control 7 */ + if (f55->query.has_alternate_transmitter_assignment) + offset++; + + /* control 8 */ + if (f55->query_3.has_ctrl8) + offset++; + + /* control 9 */ + if (f55->query_3.has_ctrl9) + offset++; + + /* control 10 */ + if (f55->query_5.has_corner_compensation) + offset++; + + /* control 11 */ + if (f55->query.curve_compensation_mode == 0x3) + offset++; + + /* control 12 */ + if (f55->query_5.has_ctrl12) + offset++; + + /* control 13 */ + if (f55->query_5.has_ctrl13) + offset++; + + /* control 14 */ + if (f55->query_5.has_ctrl14) + offset++; + + /* control 15 */ + if (f55->query_5.has_basis_function) + offset++; + + /* control 16 */ + if (f55->query_17.has_ctrl16) + offset++; + + /* control 17 */ + if (f55->query_17.has_ctrl17) + offset++; + + /* controls 18 19 */ + if (f55->query_17.has_ctrl18_ctrl19) + offset += 2; + + /* control 20 */ + if (f55->query_17.has_ctrl20) + offset++; + + /* control 21 */ + if (f55->query_17.has_ctrl21) + offset++; + + /* control 22 */ + if (f55->query_17.has_ctrl22) + offset++; + + /* control 23 */ + if (f55->query_18.has_ctrl23) + offset++; + + /* control 24 */ + if (f55->query_18.has_ctrl24) + offset++; + + /* control 25 */ + if (f55->query_18.has_ctrl25) + offset++; + + /* control 26 */ + if (f55->query_18.has_ctrl26) + offset++; + + /* control 27 */ + if (f55->query_18.has_ctrl27_query20) + offset++; + + /* control 28 */ + if (f55->query_18.has_ctrl28_query21) + offset++; + + /* control 29 */ + if (f55->query_22.has_ctrl29) + offset++; + + /* control 30 */ + if (f55->query_22.has_ctrl30) + offset++; + + /* control 31 */ + if (f55->query_22.has_ctrl31) + offset++; + + /* control 32 */ + if (f55->query_22.has_ctrl32) + offset++; + + /* controls 33 34 35 36 reserved */ + + /* control 37 */ + if (f55->query_28.has_ctrl37) + offset++; + + /* control 38 */ + if (f55->query_30.has_ctrl38) + offset++; + + /* control 39 */ + if (f55->query_30.has_ctrl39) + offset++; + + /* control 40 */ + if (f55->query_30.has_ctrl40) + offset++; + + /* control 41 */ + if (f55->query_30.has_ctrl41) + offset++; + + /* control 42 */ + if (f55->query_30.has_ctrl42) + offset++; + + /* controls 43 44 */ + if (f55->query_30.has_ctrl43_ctrl44) { + f55->afe_mux_offset = offset; + offset += 2; + } + + /* controls 45 46 */ + if (f55->query_33.has_ctrl45_ctrl46) { + f55->has_force = true; + f55->force_tx_offset = offset; + f55->force_rx_offset = offset + 1; + offset += 2; + } + + return 0; +} + +static int test_f55_set_queries(void) +{ + int retval; + unsigned char offset; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr, + f55->query.data, + sizeof(f55->query.data)); + if (retval < 0) + return retval; + + offset = sizeof(f55->query.data); + + /* query 3 */ + if (f55->query.has_single_layer_multi_touch) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_3.data, + sizeof(f55->query_3.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 4 */ + if (f55->query_3.has_ctrl9) + offset += 1; + + /* query 5 */ + if (f55->query.has_query5) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_5.data, + sizeof(f55->query_5.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 6 7 */ + if (f55->query.curve_compensation_mode == 0x3) + offset += 2; + + /* query 8 */ + if (f55->query_3.has_ctrl8) + offset += 1; + + /* query 9 */ + if (f55->query_3.has_query9) + offset += 1; + + /* queries 10 11 12 13 14 15 16 */ + if (f55->query_5.has_basis_function) + offset += 7; + + /* query 17 */ + if (f55->query_5.has_query17) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_17.data, + sizeof(f55->query_17.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 18 */ + if (f55->query_17.has_query18) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_18.data, + sizeof(f55->query_18.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 19 */ + if (f55->query_18.has_query19) + offset += 1; + + /* query 20 */ + if (f55->query_18.has_ctrl27_query20) + offset += 1; + + /* query 21 */ + if (f55->query_18.has_ctrl28_query21) + offset += 1; + + /* query 22 */ + if (f55->query_18.has_query22) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_22.data, + sizeof(f55->query_22.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 23 */ + if (f55->query_22.has_query23) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_23.data, + sizeof(f55->query_23.data)); + if (retval < 0) + return retval; + offset += 1; + + f55->amp_sensor = f55->query_23.amp_sensor_enabled; + f55->size_of_column2mux = f55->query_23.size_of_column2mux; + } + + /* queries 24 25 26 27 reserved */ + + /* query 28 */ + if (f55->query_22.has_query28) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_28.data, + sizeof(f55->query_28.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* query 29 */ + if (f55->query_28.has_query29) + offset += 1; + + /* query 30 */ + if (f55->query_28.has_query30) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_30.data, + sizeof(f55->query_30.data)); + if (retval < 0) + return retval; + offset += 1; + } + + /* queries 31 32 */ + if (f55->query_30.has_query31_query32) + offset += 2; + + /* query 33 */ + if (f55->query_30.has_query33) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->query_base_addr + offset, + f55->query_33.data, + sizeof(f55->query_33.data)); + if (retval < 0) + return retval; + offset += 1; + + f55->extended_amp = f55->query_33.has_extended_amp_pad; + f55->extended_amp_btn = f55->query_33.has_extended_amp_btn; + } + + return 0; +} + +static void test_f55_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char rx_electrodes; + unsigned char tx_electrodes; + struct f55_control_43 ctrl_43; + + retval = test_f55_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 query registers\n", + __func__); + return; + } + + if (!f55->query.has_sensor_assignment) + return; + + retval = test_f55_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F55 control registers\n", + __func__); + return; + } + + tx_electrodes = f55->query.num_of_tx_electrodes; + rx_electrodes = f55->query.num_of_rx_electrodes; + + f55->tx_assignment = kzalloc(tx_electrodes, GFP_KERNEL); + f55->rx_assignment = kzalloc(rx_electrodes, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + SENSOR_TX_MAPPING_OFFSET, + f55->tx_assignment, + tx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 tx assignment\n", + __func__); + return; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + SENSOR_RX_MAPPING_OFFSET, + f55->rx_assignment, + rx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 rx assignment\n", + __func__); + return; + } + + f54->tx_assigned = 0; + for (ii = 0; ii < tx_electrodes; ii++) { + if (f55->tx_assignment[ii] != 0xff) + f54->tx_assigned++; + } + + f54->rx_assigned = 0; + for (ii = 0; ii < rx_electrodes; ii++) { + if (f55->rx_assignment[ii] != 0xff) + f54->rx_assigned++; + } + + if (f55->amp_sensor) { + f54->tx_assigned = f55->size_of_column2mux; + f54->rx_assigned /= 2; + } + + if (f55->extended_amp) { + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->afe_mux_offset, + ctrl_43.data, + sizeof(ctrl_43.data)); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 AFE mux sizes\n", + __func__); + return; + } + + f54->tx_assigned = ctrl_43.afe_l_mux_size + + ctrl_43.afe_r_mux_size; + /* tddi f54 test reporting + */ + f54->swap_sensor_side = ctrl_43.swap_sensor_side; + f54->left_mux_size = ctrl_43.afe_l_mux_size; + f54->right_mux_size = ctrl_43.afe_r_mux_size; + /* tddi f54 test reporting - */ + } + + /* force mapping */ + if (f55->has_force) { + f55->force_tx_assignment = kzalloc(tx_electrodes, GFP_KERNEL); + f55->force_rx_assignment = kzalloc(rx_electrodes, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->force_tx_offset, + f55->force_tx_assignment, + tx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 force tx assignment\n", + __func__); + return; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f55->control_base_addr + f55->force_rx_offset, + f55->force_rx_assignment, + rx_electrodes); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F55 force rx assignment\n", + __func__); + return; + } + + for (ii = 0; ii < tx_electrodes; ii++) { + if (f55->force_tx_assignment[ii] != 0xff) + f54->tx_assigned++; + } + + for (ii = 0; ii < rx_electrodes; ii++) { + if (f55->force_rx_assignment[ii] != 0xff) + f54->rx_assigned++; + } + } + + return; +} + +static void test_f55_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned char page) +{ + f55 = kzalloc(sizeof(*f55), GFP_KERNEL); + if (!f55) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F55\n", + __func__); + return; + } + + f55->query_base_addr = fd->query_base_addr | (page << 8); + f55->control_base_addr = fd->ctrl_base_addr | (page << 8); + f55->data_base_addr = fd->data_base_addr | (page << 8); + f55->command_base_addr = fd->cmd_base_addr | (page << 8); + + return; +} + +static void test_f21_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + unsigned char ii; + unsigned char size_of_query2; + unsigned char size_of_query5; + unsigned char query_11_offset; + unsigned char ctrl_4_offset; + struct f21_query_2 *query_2 = NULL; + struct f21_query_5 *query_5 = NULL; + struct f21_query_11 *query_11 = NULL; + + query_2 = kzalloc(sizeof(*query_2), GFP_KERNEL); + if (!query_2) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_2\n", + __func__); + goto exit; + } + + query_5 = kzalloc(sizeof(*query_5), GFP_KERNEL); + if (!query_5) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_5\n", + __func__); + goto exit; + } + + query_11 = kzalloc(sizeof(*query_11), GFP_KERNEL); + if (!query_11) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for query_11\n", + __func__); + goto exit; + } + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 1, + &size_of_query2, + sizeof(size_of_query2)); + if (retval < 0) + goto exit; + + if (size_of_query2 > sizeof(query_2->data)) + size_of_query2 = sizeof(query_2->data); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 2, + query_2->data, + size_of_query2); + if (retval < 0) + goto exit; + + if (!query_2->query11_is_present) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No F21 force capabilities\n", + __func__); + goto exit; + } + + query_11_offset = query_2->query0_is_present + + query_2->query1_is_present + + query_2->query2_is_present + + query_2->query3_is_present + + query_2->query4_is_present + + query_2->query5_is_present + + query_2->query6_is_present + + query_2->query7_is_present + + query_2->query8_is_present + + query_2->query9_is_present + + query_2->query10_is_present; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 11, + query_11->data, + sizeof(query_11->data)); + if (retval < 0) + goto exit; + + if (!query_11->has_force_sensing_txrx_mapping) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: No F21 force mapping\n", + __func__); + goto exit; + } + + f21->max_num_of_tx = query_11->max_number_of_force_txs; + f21->max_num_of_rx = query_11->max_number_of_force_rxs; + f21->max_num_of_txrx = f21->max_num_of_tx + f21->max_num_of_rx; + + f21->force_txrx_assignment = kzalloc(f21->max_num_of_txrx, GFP_KERNEL); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 4, + &size_of_query5, + sizeof(size_of_query5)); + if (retval < 0) + goto exit; + + if (size_of_query5 > sizeof(query_5->data)) + size_of_query5 = sizeof(query_5->data); + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->query_base_addr + 5, + query_5->data, + size_of_query5); + if (retval < 0) + goto exit; + + ctrl_4_offset = query_5->ctrl0_is_present + + query_5->ctrl1_is_present + + query_5->ctrl2_is_present + + query_5->ctrl3_is_present; + + retval = synaptics_rmi4_reg_read(rmi4_data, + f21->control_base_addr + ctrl_4_offset, + f21->force_txrx_assignment, + f21->max_num_of_txrx); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F21 force txrx assignment\n", + __func__); + goto exit; + } + + f21->has_force = true; + + for (ii = 0; ii < f21->max_num_of_tx; ii++) { + if (f21->force_txrx_assignment[ii] != 0xff) + f21->tx_assigned++; + } + + for (ii = f21->max_num_of_tx; ii < f21->max_num_of_txrx; ii++) { + if (f21->force_txrx_assignment[ii] != 0xff) + f21->rx_assigned++; + } + +exit: + kfree(query_2); + kfree(query_5); + kfree(query_11); + + return; +} + +static void test_f21_set_regs(struct synaptics_rmi4_data *rmi4_data, + struct synaptics_rmi4_fn_desc *fd, + unsigned char page) +{ + f21 = kzalloc(sizeof(*f21), GFP_KERNEL); + if (!f21) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F21\n", + __func__); + return; + } + + f21->query_base_addr = fd->query_base_addr | (page << 8); + f21->control_base_addr = fd->ctrl_base_addr | (page << 8); + f21->data_base_addr = fd->data_base_addr | (page << 8); + f21->command_base_addr = fd->cmd_base_addr | (page << 8); + + return; +} + +static int test_scan_pdt(void) +{ + int retval; + unsigned char intr_count = 0; + unsigned char page; + unsigned short addr; + bool f54found = false; + bool f55found = false; + struct synaptics_rmi4_fn_desc rmi_fd; + struct synaptics_rmi4_data *rmi4_data = f54->rmi4_data; + + for (page = 0; page < PAGES_TO_SERVICE; page++) { + for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { + addr |= (page << 8); + + retval = synaptics_rmi4_reg_read(rmi4_data, + addr, + (unsigned char *)&rmi_fd, + sizeof(rmi_fd)); + if (retval < 0) + return retval; + + addr &= ~(MASK_8BIT << 8); + + if (!rmi_fd.fn_number) + break; + + switch (rmi_fd.fn_number) { + case SYNAPTICS_RMI4_F54: + test_f54_set_regs(rmi4_data, + &rmi_fd, intr_count, page); + f54found = true; + break; + case SYNAPTICS_RMI4_F55: + test_f55_set_regs(rmi4_data, + &rmi_fd, page); + f55found = true; + break; + case SYNAPTICS_RMI4_F21: + test_f21_set_regs(rmi4_data, + &rmi_fd, page); + break; + default: + break; + } + + if (f54found && f55found) + goto pdt_done; + + intr_count += rmi_fd.intr_src_count; + } + } + + if (!f54found) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to find F54\n", + __func__); + return -EINVAL; + } + +pdt_done: + return 0; +} + +static void synaptics_rmi4_test_attn(struct synaptics_rmi4_data *rmi4_data, + unsigned char intr_mask) +{ + if (!f54) + return; + + if (f54->intr_mask & intr_mask) + queue_work(f54->test_report_workqueue, &f54->test_report_work); + + return; +} + +static int synaptics_rmi4_test_init(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (f54) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Handle already exists\n", + __func__); + return 0; + } + + f54 = kzalloc(sizeof(*f54), GFP_KERNEL); + if (!f54) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to alloc mem for F54\n", + __func__); + retval = -ENOMEM; + goto exit; + } + + f54->rmi4_data = rmi4_data; + + f55 = NULL; + + f21 = NULL; + + retval = test_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + retval = test_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F54 query registers\n", + __func__); + goto exit_free_mem; + } + + f54->tx_assigned = f54->query.num_of_tx_electrodes; + f54->rx_assigned = f54->query.num_of_rx_electrodes; + + retval = test_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F54 control registers\n", + __func__); + goto exit_free_control; + } + + test_set_data(); + + if (f55) + test_f55_init(rmi4_data); + + if (f21) + test_f21_init(rmi4_data); + + if (rmi4_data->external_afe_buttons) + f54->tx_assigned++; + + retval = test_set_sysfs(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs entries\n", + __func__); + goto exit_sysfs; + } + + f54->test_report_workqueue = + create_singlethread_workqueue("test_report_workqueue"); + INIT_WORK(&f54->test_report_work, test_report_work); + + hrtimer_init(&f54->watchdog, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + f54->watchdog.function = test_get_report_timeout; + INIT_WORK(&f54->timeout_work, test_timeout_work); + + mutex_init(&f54->status_mutex); + f54->status = STATUS_IDLE; + + return 0; + +exit_sysfs: + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + +exit_free_control: + test_free_control_mem(); + +exit_free_mem: + kfree(f21); + f21 = NULL; + kfree(f55); + f55 = NULL; + kfree(f54); + f54 = NULL; + +exit: + return retval; +} + +static void synaptics_rmi4_test_remove(struct synaptics_rmi4_data *rmi4_data) +{ + if (!f54) + goto exit; + + hrtimer_cancel(&f54->watchdog); + + cancel_work_sync(&f54->test_report_work); + flush_workqueue(f54->test_report_workqueue); + destroy_workqueue(f54->test_report_workqueue); + + test_remove_sysfs(); + + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + + test_free_control_mem(); + + if (f54->data_buffer_size) + kfree(f54->report_data); + + kfree(f21); + f21 = NULL; + + kfree(f55); + f55 = NULL; + + kfree(f54); + f54 = NULL; + +exit: + complete(&test_remove_complete_lansi); + + return; +} + +static void synaptics_rmi4_test_reset(struct synaptics_rmi4_data *rmi4_data) +{ + int retval; + + if (!f54) { + synaptics_rmi4_test_init(rmi4_data); + return; + } + + if (f21) + kfree(f21->force_txrx_assignment); + + if (f55) { + kfree(f55->tx_assignment); + kfree(f55->rx_assignment); + kfree(f55->force_tx_assignment); + kfree(f55->force_rx_assignment); + } + + test_free_control_mem(); + + kfree(f55); + f55 = NULL; + + kfree(f21); + f21 = NULL; + + retval = test_scan_pdt(); + if (retval < 0) + goto exit_free_mem; + + retval = test_set_queries(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to read F54 query registers\n", + __func__); + goto exit_free_mem; + } + + f54->tx_assigned = f54->query.num_of_tx_electrodes; + f54->rx_assigned = f54->query.num_of_rx_electrodes; + + retval = test_set_controls(); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to set up F54 control registers\n", + __func__); + goto exit_free_control; + } + + test_set_data(); + + if (f55) + test_f55_init(rmi4_data); + + if (f21) + test_f21_init(rmi4_data); + + if (rmi4_data->external_afe_buttons) + f54->tx_assigned++; + + f54->status = STATUS_IDLE; + + return; + +exit_free_control: + test_free_control_mem(); + +exit_free_mem: + hrtimer_cancel(&f54->watchdog); + + cancel_work_sync(&f54->test_report_work); + flush_workqueue(f54->test_report_workqueue); + destroy_workqueue(f54->test_report_workqueue); + + test_remove_sysfs(); + + if (f54->data_buffer_size) + kfree(f54->report_data); + + kfree(f21); + f21 = NULL; + + kfree(f55); + f55 = NULL; + + kfree(f54); + f54 = NULL; + + return; +} + +static struct synaptics_rmi4_exp_fn test_module = { + .fn_type = RMI_TEST_REPORTING, + .init = synaptics_rmi4_test_init, + .remove = synaptics_rmi4_test_remove, + .reset = synaptics_rmi4_test_reset, + .reinit = NULL, + .early_suspend = NULL, + .suspend = NULL, + .resume = NULL, + .late_resume = NULL, + .attn = synaptics_rmi4_test_attn, +}; + +static int __init rmi4_test_module_init(void) +{ + synaptics_rmi4_new_function_lansi(&test_module, true); + + return 0; +} + +static void __exit rmi4_test_module_exit(void) +{ + synaptics_rmi4_new_function_lansi(&test_module, false); + + wait_for_completion(&test_remove_complete_lansi); + + + remove_proc_entry("tp_data_dump", NULL); + + return; +} + +module_init(rmi4_test_module_init); +module_exit(rmi4_test_module_exit); + +MODULE_AUTHOR("Synaptics, Inc."); +MODULE_DESCRIPTION("Synaptics DSX Test Reporting Module"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/vituralsar_driver.c b/drivers/input/touchscreen/vituralsar_driver.c new file mode 100644 index 0000000000000..361d03fb44729 --- /dev/null +++ b/drivers/input/touchscreen/vituralsar_driver.c @@ -0,0 +1,313 @@ +/* + * File: fusb30x_driver.c + * Company: Fairchild Semiconductor + * + * Created on September 2, 2015, 10:22 AM + */ + +#define DEBUG + +/* Standard Linux includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "vituralsar_driver.h" +#include +#include + + + + +/****************************************************************************** +* Driver functions +******************************************************************************/ + + +int sar_int_gpio; +static int sar_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + + sar_int_gpio = of_get_named_gpio(np, "vituralsar,irq-gpio", 0); + if (sar_int_gpio == 130) + { + printk("parse irq gpio correctly\n "); + return 0; + } else + { + printk("parse irq gpio incorrectly\n "); + return -EPERM; + } +} + +void sar_irq_enable(struct vituralsar_data *sdata) +{ + unsigned long irqflags = 0; + + spin_lock_irqsave(&sdata->irq_lock, irqflags); + if (sdata->irq_is_disable) + { + enable_irq_wake(sdata->client->irq); + sdata->irq_is_disable = 0; + } + spin_unlock_irqrestore(&sdata->irq_lock, irqflags); +} + +void sar_irq_disable(struct vituralsar_data *sdata) +{ + unsigned long irqflags; + + + spin_lock_irqsave(&sdata->irq_lock, irqflags); + if (!sdata->irq_is_disable) + { + disable_irq_wake(sdata->client->irq); + sdata->irq_is_disable = 1; + } + spin_unlock_irqrestore(&sdata->irq_lock, irqflags); +} + +int input_data = -1; +static irqreturn_t sar_irq_handler(int irq, void *dev_id) +{ + struct vituralsar_data *sdata = dev_id; + unsigned long irqflags = 0; + + + spin_lock_irqsave(&sdata->irq_lock, irqflags); + + input_data = gpio_get_value(sar_int_gpio); + + + input_report_key(sdata->input_dev, gpio_key.code, 1); + input_report_key(sdata->input_dev, gpio_key.code, 0); + printk("input_report_key , status :%d\n", input_data); + input_sync(sdata->input_dev); + + spin_unlock_irqrestore(&sdata->irq_lock, irqflags); + + + printk("gpio_get_value : %d\n", input_data); + + return IRQ_HANDLED; +} + +static s8 sar_request_irq(struct vituralsar_data *sdata) +{ + s32 ret = -1; + const u8 irq_table[] = SAR_IRQ_TAB; + + ret = request_irq(sdata->client->irq, + sar_irq_handler, + irq_table[sdata->int_trigger_type], + sdata->client->name, + sdata); + if (ret) + { + printk("Request IRQ failed!ERRNO:%d.", ret); + } + else + { + + sdata->use_irq = 1; + return 0; + } + return -EPERM; +} + +static s8 sar_request_io_port(struct vituralsar_data *sdata) +{ + s32 ret = 0; + + ret = gpio_request(sar_int_gpio, "SAR_INT_IRQ"); + if (ret < 0) + { + printk("Failed to request GPIO:%d, ERRNO:%d", (s32)sar_int_gpio, ret); + gpio_free(sar_int_gpio); + return ret; + } + else + { + gpio_direction_input(sar_int_gpio); + sdata->client->irq = gpio_to_irq(sar_int_gpio); + } + + return ret; +} + +static s8 sar_request_input_dev(struct vituralsar_data *sdata) +{ + s8 ret = -1; + + sdata->input_dev = input_allocate_device(); + if (sdata->input_dev == NULL) + { + printk("Failed to allocate input device."); + return -ENOMEM; + } + + sdata->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ; + + __set_bit(EV_REP, sdata->input_dev->evbit); + + + sdata->input_dev->name = sar_name; + sdata->input_dev->phys = sar_input_phys; + sdata->input_dev->id.bustype = BUS_I2C; + + ret = input_register_device(sdata->input_dev); + if (ret) + { + printk("Register %s input device failed", sdata->input_dev->name); + return -ENODEV; + } + input_set_capability(sdata->input_dev, EV_KEY, gpio_key.code); + + + return 0; +} +static struct proc_dir_entry *gpio_status; +#define GOIP_STATUS "gpio_status" + +static int gpio_proc_show(struct seq_file *file, void *data) +{ + + seq_printf(file, "%d\n", input_data); + + return 0; +} + + +static int gpio_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, gpio_proc_show, inode->i_private); +} + + +static const struct file_operations gpio_status_ops = +{ + .open = gpio_proc_open, + .read = seq_read, +}; + +static int virtualsar_probe (struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret = 0; + struct vituralsar_data *sdata; + + if (!client) + { + pr_err("SAR %s - Error: Client structure is NULL!\n", __func__); + return -EINVAL; + } + dev_info(&client->dev, "%s\n", __func__); + + /* Make sure probe was called on a compatible device */ + if (!of_match_device(virtualsar_dt_match, &client->dev)) + { + dev_err(&client->dev, "FUSB %s - Error: Device tree mismatch!\n", __func__); + return -EINVAL; + } + pr_debug("SAR %s - Device tree matched!\n", __func__); + + sdata = kzalloc(sizeof(*sdata), GFP_KERNEL); + if (sdata == NULL) + { + printk("Alloc GFP_KERNEL memory failed."); + return -ENOMEM; + } + + if (client->dev.of_node) { + ret = sar_parse_dt(&client->dev); + if (!ret) + printk("sar_parse_dt success\n"); + } + + sdata->int_trigger_type = SAR_INT_TRIGGER; + + sdata->client = client; + spin_lock_init(&sdata->irq_lock); + + + if (gpio_is_valid(sar_int_gpio)) + { + ret = sar_request_io_port(sdata); + if (ret < 0) + { + printk("SAR %s -request io port fail\n", __func__); + return -ENOMEM; + } + }else + { + printk("SAR %s -gpio is not valid\n", __func__); + return -ENOMEM; + } + + + ret = sar_request_input_dev(sdata); + if (ret < 0) + { + printk("SAR request input dev failed"); + } + + + ret = sar_request_irq(sdata); + if (ret < 0) + { + printk("SAR %s -request irq fail\n", __func__); + } + + __set_bit(EV_REP, sdata->input_dev->evbit); + + + if (sdata->use_irq) + sar_irq_enable(sdata); + printk("after sar_irq_enable,probe end \n"); + + gpio_status = proc_create(GOIP_STATUS, 0644, NULL, &gpio_status_ops); + if (gpio_status == NULL) + { + printk("tpd, create_proc_entry gpio_status_ops failed\n"); + } + + return 0; +} + + +static int __init virtualsar_init(void) +{ + int ret = 0; + pr_debug("SAR %s - Start driver initialization...\n", __func__); + + ret = i2c_add_driver(&virtualsar_driver); + printk("ret : %d\n", ret); + return ret; +} + +static void __exit virtualsar_exit(void) +{ + i2c_del_driver(&virtualsar_driver); + pr_debug("SAR %s - Driver deleted...\n", __func__); +} + + +/******************************************************************************* + * Driver macros + ******************************************************************************/ + + + +module_init(virtualsar_init); + +module_exit(virtualsar_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VirtualSAR Driver"); +MODULE_AUTHOR("VirtualSar"); diff --git a/drivers/input/touchscreen/vituralsar_driver.h b/drivers/input/touchscreen/vituralsar_driver.h new file mode 100644 index 0000000000000..409e1f4aec14d --- /dev/null +++ b/drivers/input/touchscreen/vituralsar_driver.h @@ -0,0 +1,90 @@ +/* + * File: vituralsar_driver.h + * Company: Fairchild Semiconductor + * + * Created on September 2, 2015, 9:02 AM + */ + +#ifndef VITURALSAR_DRIVER_H +#define VITURALSAR_DRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +/******************************************************************************* + * Platform-specific configuration data + ******************************************************************************/ +#define VITURALSAR_I2C_DRIVER_NAME "virtualsar" +#define VIRTUAL_I2C_DEVICETREE_NAME "virtualsar,sar" + + +/******************************************************************************* +* Driver structs +******************************************************************************/ +#ifdef CONFIG_OF +static const struct of_device_id virtualsar_dt_match[] = { + { .compatible = VIRTUAL_I2C_DEVICETREE_NAME }, + {}, +}; +MODULE_DEVICE_TABLE(of, virtualsar_dt_match); +#endif /* CONFIG_OF */ + +/* This identifies our I2C driver in the kernel's driver module table */ +static const struct i2c_device_id virtualsar_i2c_device_id[] = { + { VIRTUAL_I2C_DEVICETREE_NAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, virtualsar_i2c_device_id); + +/******************************************************************************* + * Driver module functions + ******************************************************************************/ +static int __init virtualsar_init(void); +static void __exit virtualsar_exit(void); +static int virtualsar_probe(struct i2c_client *client, + const struct i2c_device_id *id); + +#define SAR_INT_TRIGGER 2 +#define SAR_IRQ_TAB {IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_EDGE_BOTH, IRQ_TYPE_LEVEL_LOW, IRQ_TYPE_LEVEL_HIGH} + +static const char *sar_name = "vitural-sar"; +static const char *sar_input_phys = "input/sar"; + + +struct vituralsar_data { + spinlock_t irq_lock; + struct i2c_client *client; + struct input_dev *input_dev; + u8 int_trigger_type; + s32 irq_is_disable; + s32 use_irq; +}; + +struct gpio_keys_button gpio_key = { + .code = KEY_F24, + .type = EV_KEY, + .wakeup = 1, + .debounce_interval = 0, + .can_disable = true, +}; + +/* Defines our driver's name, device-tree match, and required driver callbacks */ +static struct i2c_driver virtualsar_driver = { + .driver = { + .name = VIRTUAL_I2C_DEVICETREE_NAME, + .of_match_table = of_match_ptr(virtualsar_dt_match), + }, + .probe = virtualsar_probe, + .id_table = virtualsar_i2c_device_id, +}; + +#endif /* FUSB30X_DRIVER_H */ + diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 16649f62f3f83..d1150f5fe3404 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -559,6 +559,23 @@ config LEDS_AW2013 This option enables support for the AW2013 RGB LED connected through I2C. Say Y to enable support for the AW2013 LED. +config LEDS_AW2023 + tristate "LED support for AW2023" + depends on LEDS_CLASS && I2C + help + This option enables support for the AW2023 RGB LED connected + through I2C. Say Y to enable support for the AW2013 LED. + +config FLASHLIGHT_SAKURA + bool "config flashlight sakura" + help + config flashlight sakura. + +config FLASHLIGHT_VINCE_O + bool "config flashlight vince_o" + help + config flashlight vince_o. + comment "LED Triggers" source "drivers/leds/trigger/Kconfig" diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index b68d0a55e3429..fd182111f5848 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -62,6 +62,8 @@ obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_VERSATILE) += leds-versatile.o obj-$(CONFIG_LEDS_MENF21BMC) += leds-menf21bmc.o obj-$(CONFIG_LEDS_AW2013) += leds-aw2013.o +obj-$(CONFIG_LEDS_AW2023) += leds-aw2023.o + # LED SPI Drivers obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c index d0a39fab2821c..ffe26418b233c 100644 --- a/drivers/leds/leds-aw2013.c +++ b/drivers/leds/leds-aw2013.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +22,13 @@ #include #include #include +#include +#include +#include +#include + + + /* register address */ #define AW_REG_RESET 0x00 @@ -51,11 +59,17 @@ #define MAX_FALL_TIME_MS 7 #define MAX_OFF_TIME_MS 5 +#define AW2013_LED_PROC_FOLDER "aw2013_led" +#define AW2013_LED_PROC_BRIGHTNESS_FILE "brightness" +static struct i2c_client *aw2013_led_i2c_client; +static struct proc_dir_entry *aw2013_led_proc_dir; +static struct proc_dir_entry *aw2013_led_brightness_file; + struct aw2013_led { struct i2c_client *client; struct led_classdev cdev; struct aw2013_platform_data *pdata; - struct work_struct brightness_work; + struct mutex lock; struct regulator *vdd; struct regulator *vcc; @@ -198,7 +212,7 @@ static int aw2013_power_init(struct aw2013_led *led, bool on) regulator_put(led->vdd); return rc; } - +#if 0 static void aw2013_brightness_work(struct work_struct *work) { struct aw2013_led *led = container_of(work, struct aw2013_led, @@ -248,7 +262,52 @@ static void aw2013_brightness_work(struct work_struct *work) mutex_unlock(&led->pdata->led->lock); } +#else +static void aw2013_brightness_set(struct aw2013_led *led) +{ + u8 val; + + /* enable regulators if they are disabled */ + if (!led->pdata->led->poweron) { + if (aw2013_power_on(led->pdata->led, true)) { + dev_err(&led->pdata->led->client->dev, "power on failed"); + mutex_unlock(&led->pdata->led->lock); + return; + } + } + pr_err("aw2013----brightness = %d led_id = %d\n", led->cdev.brightness , led->id); + if (led->cdev.brightness > 0) { + if (led->cdev.brightness > led->cdev.max_brightness) + led->cdev.brightness = led->cdev.max_brightness; + aw2013_write(led, AW_REG_GLOBAL_CONTROL, + AW_LED_MOUDLE_ENABLE_MASK); + aw2013_write(led, AW_REG_LED_CONFIG_BASE + led->id, + led->pdata->max_current); + aw2013_write(led, AW_REG_LED_BRIGHTNESS_BASE + led->id, + led->cdev.brightness); + aw2013_read(led, AW_REG_LED_ENABLE, &val); + aw2013_write(led, AW_REG_LED_ENABLE, val | (1 << led->id)); + } else { + aw2013_read(led, AW_REG_LED_ENABLE, &val); + aw2013_write(led, AW_REG_LED_ENABLE, val & (~(1 << led->id))); + } + + aw2013_read(led, AW_REG_LED_ENABLE, &val); + + /* + * If value in AW_REG_LED_ENABLE is 0, it means the RGB leds are + * all off. So we need to power it off. + */ + if (val == 0) { + if (aw2013_power_on(led->pdata->led, false)) { + dev_err(&led->pdata->led->client->dev, + "power off failed"); + return; + } + } +} +#endif static void aw2013_led_blink_set(struct aw2013_led *led, unsigned long blinking) { u8 val; @@ -263,6 +322,7 @@ static void aw2013_led_blink_set(struct aw2013_led *led, unsigned long blinking) led->cdev.brightness = blinking ? led->cdev.max_brightness : 0; + pr_err("aw2013----blink = %d led_id = %d\n", (int)blinking , led->id); if (blinking > 0) { aw2013_write(led, AW_REG_GLOBAL_CONTROL, AW_LED_MOUDLE_ENABLE_MASK); @@ -303,9 +363,12 @@ static void aw2013_set_brightness(struct led_classdev *cdev, { struct aw2013_led *led = container_of(cdev, struct aw2013_led, cdev); + mutex_lock(&led->pdata->led->lock); led->cdev.brightness = brightness; - schedule_work(&led->brightness_work); + + aw2013_brightness_set(led); + mutex_unlock(&led->pdata->led->lock); } static ssize_t aw2013_store_blink(struct device *dev, @@ -340,6 +403,18 @@ static ssize_t aw2013_led_time_show(struct device *dev, led->pdata->fall_time_ms, led->pdata->off_time_ms); } +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 val = 0; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2013_led *led = + container_of(led_cdev, struct aw2013_led, cdev); + aw2013_read(led, AW_REG_LED_ENABLE, &val); + return snprintf(buf, PAGE_SIZE, "%d\n", + val); +} + static ssize_t aw2013_led_time_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) @@ -369,10 +444,12 @@ static ssize_t aw2013_led_time_store(struct device *dev, static DEVICE_ATTR(blink, 0664, NULL, aw2013_store_blink); static DEVICE_ATTR(led_time, 0664, aw2013_led_time_show, aw2013_led_time_store); +static DEVICE_ATTR(status, 0664, status_show, NULL); static struct attribute *aw2013_led_attributes[] = { &dev_attr_blink.attr, &dev_attr_led_time.attr, + &dev_attr_status.attr, NULL, }; @@ -383,9 +460,14 @@ static struct attribute_group aw2013_led_attr_group = { static int aw_2013_check_chipid(struct aw2013_led *led) { u8 val; - + if (aw2013_power_on(led->pdata->led, true)) { + dev_err(&led->pdata->led->client->dev, + "power off failed"); + return -EPERM; + } aw2013_write(led, AW_REG_RESET, AW_LED_RESET_MASK); - usleep(AW_LED_RESET_DELAY); + + udelay(2000); aw2013_read(led, AW_REG_RESET, &val); if (val == AW2013_CHIPID) return 0; @@ -405,7 +487,7 @@ static int aw2013_led_err_handle(struct aw2013_led *led_array, sysfs_remove_group(&led_array[i].cdev.dev->kobj, &aw2013_led_attr_group); led_classdev_unregister(&led_array[i].cdev); - cancel_work_sync(&led_array[i].brightness_work); + devm_kfree(&led_array->client->dev, led_array[i].pdata); led_array[i].pdata = NULL; } @@ -500,7 +582,7 @@ static int aw2013_led_parse_child_node(struct aw2013_led *led_array, goto free_pdata; } - INIT_WORK(&led->brightness_work, aw2013_brightness_work); + led->cdev.brightness_set = aw2013_set_brightness; @@ -526,7 +608,7 @@ static int aw2013_led_parse_child_node(struct aw2013_led *led_array, free_class: aw2013_led_err_handle(led_array, parsed_leds); led_classdev_unregister(&led_array[parsed_leds].cdev); - cancel_work_sync(&led_array[parsed_leds].brightness_work); + devm_kfree(&led->client->dev, led_array[parsed_leds].pdata); led_array[parsed_leds].pdata = NULL; return rc; @@ -541,6 +623,56 @@ static int aw2013_led_parse_child_node(struct aw2013_led *led_array, return rc; } +static ssize_t aw2013_led_brightness_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) +{ + char buf_tmp[6] = {0}; + s32 ret = 0; + enum led_brightness brightness = LED_OFF; + struct aw2013_led *led = i2c_get_clientdata(aw2013_led_i2c_client); + if (copy_from_user(buf_tmp, buffer, count)) + return -EFAULT; + + if (strncmp(buf_tmp, "255", 3) == 0) + brightness = LED_FULL; + pr_err("%s buf_tmp %s \n", __func__, buf_tmp); + mutex_lock(&led->pdata->led->lock); + led->cdev.brightness = brightness; + + aw2013_brightness_set(led); + mutex_unlock(&led->pdata->led->lock); + ret = count; + return ret; + +} + +static const struct file_operations aw2013_led_brightness_ops = { + .owner = THIS_MODULE, + .read = seq_read, + .write = aw2013_led_brightness_write, +}; +static int aw2013_led_proc_init(void) +{ + aw2013_led_proc_dir = proc_mkdir(AW2013_LED_PROC_FOLDER, NULL); + if (aw2013_led_proc_dir == NULL) { + pr_err(" %s: aw2013_led_proc_dir file create failed!\n", __func__); + return -ENOMEM; + } + + aw2013_led_brightness_file = proc_create(AW2013_LED_PROC_BRIGHTNESS_FILE, + 0664, aw2013_led_proc_dir, &aw2013_led_brightness_ops); + + if (aw2013_led_brightness_file == NULL) { + pr_err(" %s: proc aw2013_led_brightness file create failed!\n", __func__); + goto fail_1; + } + return 0; +fail_1: + remove_proc_entry(AW2013_LED_PROC_BRIGHTNESS_FILE, aw2013_led_brightness_file); + remove_proc_entry(AW2013_LED_PROC_FOLDER, NULL); + return -ENOMEM; +} + static int aw2013_led_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -567,12 +699,6 @@ static int aw2013_led_probe(struct i2c_client *client, mutex_init(&led_array->lock); - ret = aw_2013_check_chipid(led_array); - if (ret) { - dev_err(&client->dev, "Check chip id error\n"); - goto free_led_arry; - } - ret = aw2013_led_parse_child_node(led_array, node); if (ret) { dev_err(&client->dev, "parsed node error\n"); @@ -580,6 +706,7 @@ static int aw2013_led_probe(struct i2c_client *client, } i2c_set_clientdata(client, led_array); + aw2013_led_i2c_client = client; ret = aw2013_power_init(led_array, true); if (ret) { @@ -587,6 +714,13 @@ static int aw2013_led_probe(struct i2c_client *client, goto fail_parsed_node; } + ret = aw_2013_check_chipid(led_array); + if (ret) { + dev_err(&client->dev, "Check chip id error\n"); + goto fail_parsed_node; + } + + aw2013_led_proc_init(); return 0; fail_parsed_node: @@ -607,10 +741,12 @@ static int aw2013_led_remove(struct i2c_client *client) sysfs_remove_group(&led_array[i].cdev.dev->kobj, &aw2013_led_attr_group); led_classdev_unregister(&led_array[i].cdev); - cancel_work_sync(&led_array[i].brightness_work); + devm_kfree(&client->dev, led_array[i].pdata); led_array[i].pdata = NULL; } + remove_proc_entry(AW2013_LED_PROC_BRIGHTNESS_FILE, aw2013_led_brightness_file); + remove_proc_entry(AW2013_LED_PROC_FOLDER, NULL); mutex_destroy(&led_array->lock); devm_kfree(&client->dev, led_array); led_array = NULL; @@ -625,7 +761,7 @@ static const struct i2c_device_id aw2013_led_id[] = { MODULE_DEVICE_TABLE(i2c, aw2013_led_id); static struct of_device_id aw2013_match_table[] = { - { .compatible = "awinic,aw2013",}, + { .compatible = "awinic,aw2013_led",}, { }, }; diff --git a/drivers/leds/leds-aw2023.c b/drivers/leds/leds-aw2023.c new file mode 100644 index 0000000000000..be0c4fcc032b1 --- /dev/null +++ b/drivers/leds/leds-aw2023.c @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * Version: v1.0.0 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* register address */ +#define AW2023_REG_RESET 0x00 +#define AW2023_REG_GCR1 0x01 +#define AW_REG_LED_STATUS 0x02 +#define AW2023_REG_PATST 0x03 +#define AW2023_REG_GCR2 0x04 +#define AW2023_REG_LEDEN 0x30 +#define AW2023_REG_LCFG0 0x31 +#define AW2023_REG_LCFG1 0x32 +#define AW2023_REG_LCFG2 0x33 +#define AW2023_REG_PWM0 0x34 +#define AW2023_REG_PWM1 0x35 +#define AW2023_REG_PWM2 0x36 +#define AW2023_REG_LED0T0 0x37 +#define AW2023_REG_LED0T1 0x38 +#define AW2023_REG_LED0T2 0x39 +#define AW2023_REG_LED1T0 0x3A +#define AW2023_REG_LED1T1 0x3B +#define AW2023_REG_LED1T2 0x3C +#define AW2023_REG_LED2T0 0x3D +#define AW2023_REG_LED2T1 0x3E +#define AW2023_REG_LED2T2 0x3F + +/* register bits */ +#define AW2023_CHIPID 0x09 +#define AW2023_RESET_MASK 0x55 +#define AW2023_CHIP_DISABLE_MASK 0x00 +#define AW2023_CHIP_ENABLE_MASK 0x01 +#define AW2023_LED_BREATH_MODE_MASK 0x10 +#define AW2023_LED_MANUAL_MODE_MASK 0x00 +#define AW2023_LED_BREATHE_PWM_MASK 0xFF +#define AW2023_LED_MANUAL_PWM_MASK 0xFF +#define AW2023_LED_FADEIN_MODE_MASK 0x20 +#define AW2023_LED_FADEOUT_MODE_MASK 0x40 + +/* aw2023 config */ +#define AW_LED_RESET_DELAY 8 +#define AW_LED_POWER_ON_DELAY 2 +#define AW_LED_POWER_OFF_DELAY 2 +#define AW2023_VDD_MIN_UV 2600000 +#define AW2023_VDD_MAX_UV 3300000 +#define AW2023_VI2C_MIN_UV 1800000 +#define AW2023_VI2C_MAX_UV 1800000 + +#define MAX_RISE_TIME_MS 15 +#define MAX_HOLD_TIME_MS 15 +#define MAX_FALL_TIME_MS 15 +#define MAX_OFF_TIME_MS 15 + + + +/* aw2023 register read/write access*/ +#define REG_NONE_ACCESS 0 +#define REG_RD_ACCESS 1 << 0 +#define REG_WR_ACCESS 1 << 1 +#define AW2023_REG_MAX 0x7F + +const unsigned char aw2023_reg_access[AW2023_REG_MAX] = { + [AW2023_REG_RESET] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_GCR1] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_PATST] = REG_RD_ACCESS, + [AW2023_REG_GCR2] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LEDEN] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LCFG0] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LCFG1] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LCFG2] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_PWM0] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_PWM1] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_PWM2] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED0T0] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED0T1] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED0T2] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED1T0] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED1T1] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED1T2] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED2T0] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED2T1] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW2023_REG_LED2T2] = REG_RD_ACCESS|REG_WR_ACCESS, +}; + +#define AW2023_LED_PROC_FOLDER "aw2013_led" +#define AW2023_LED_PROC_BRIGHTNESS_FILE "brightness" +static struct i2c_client *aw2023_led_i2c_client; +static struct proc_dir_entry *aw2023_led_proc_dir; +static struct proc_dir_entry *aw2023_brightness; + +struct aw2023_led { + struct i2c_client *client; + struct led_classdev cdev; + struct aw2023_platform_data *pdata; + struct work_struct brightness_work; + struct mutex lock; + struct regulator *vdd; + struct regulator *vcc; + int num_leds; + int id; + bool poweron; +}; + +static int aw2023_write(struct aw2023_led *led, u8 reg, u8 val) +{ + int ret = -EINVAL, retry_times = 0; + + do { + ret = i2c_smbus_write_byte_data(led->client, reg, val); + retry_times ++; + if (retry_times == 5) + break; + }while (ret < 0); + + return ret; +} + +static int aw2023_read(struct aw2023_led *led, u8 reg, u8 *val) +{ + int ret = -EINVAL, retry_times = 0; + + do{ + ret = i2c_smbus_read_byte_data(led->client, reg); + retry_times ++; + if (retry_times == 5) + break; + }while (ret < 0); + if (ret < 0) + return ret; + + *val = ret; + return 0; +} + +static int aw2023_power_on(struct aw2023_led *led, bool on) +{ + int rc; + + if (on) { + rc = regulator_enable(led->vdd); + if (rc) { + dev_err(&led->client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + return rc; + } + + rc = regulator_enable(led->vcc); + if (rc) { + dev_err(&led->client->dev, + "Regulator vcc enable failed rc=%d\n", rc); + goto fail_enable_reg; + } + led->poweron = true; + msleep(AW_LED_POWER_ON_DELAY); + } else { + rc = regulator_disable(led->vdd); + if (rc) { + dev_err(&led->client->dev, + "Regulator vdd disable failed rc=%d\n", rc); + return rc; + } + + rc = regulator_disable(led->vcc); + if (rc) { + dev_err(&led->client->dev, + "Regulator vcc disable failed rc=%d\n", rc); + goto fail_disable_reg; + } + led->poweron = false; + msleep(AW_LED_POWER_OFF_DELAY); + } + return rc; + +fail_enable_reg: + rc = regulator_disable(led->vdd); + if (rc) + dev_err(&led->client->dev, + "Regulator vdd disable failed rc=%d\n", rc); + + return rc; + +fail_disable_reg: + rc = regulator_enable(led->vdd); + if (rc) + dev_err(&led->client->dev, + "Regulator vdd enable failed rc=%d\n", rc); + + return rc; +} + +static int aw2023_power_init(struct aw2023_led *led, bool on) +{ + int rc; + + if (on) { + led->vdd = regulator_get(&led->client->dev, "vdd"); + if (IS_ERR(led->vdd)) { + rc = PTR_ERR(led->vdd); + dev_err(&led->client->dev, + "Regulator get failed vdd rc=%d\n", rc); + return rc; + } + + if (regulator_count_voltages(led->vdd) > 0) { + rc = regulator_set_voltage(led->vdd, AW2023_VDD_MIN_UV, + AW2023_VDD_MAX_UV); + if (rc) { + dev_err(&led->client->dev, + "Regulator set_vtg failed vdd rc=%d\n", + rc); + goto reg_vdd_put; + } + } + + led->vcc = regulator_get(&led->client->dev, "vcc"); + if (IS_ERR(led->vcc)) { + rc = PTR_ERR(led->vcc); + dev_err(&led->client->dev, + "Regulator get failed vcc rc=%d\n", rc); + goto reg_vdd_set_vtg; + } + + if (regulator_count_voltages(led->vcc) > 0) { + rc = regulator_set_voltage(led->vcc, AW2023_VI2C_MIN_UV, + AW2023_VI2C_MAX_UV); + if (rc) { + dev_err(&led->client->dev, + "Regulator set_vtg failed vcc rc=%d\n", rc); + goto reg_vcc_put; + } + } + } else { + if (regulator_count_voltages(led->vdd) > 0) + regulator_set_voltage(led->vdd, 0, AW2023_VDD_MAX_UV); + + regulator_put(led->vdd); + + if (regulator_count_voltages(led->vcc) > 0) + regulator_set_voltage(led->vcc, 0, AW2023_VI2C_MAX_UV); + + regulator_put(led->vcc); + } + return 0; + +reg_vcc_put: + regulator_put(led->vcc); +reg_vdd_set_vtg: + if (regulator_count_voltages(led->vdd) > 0) + regulator_set_voltage(led->vdd, 0, AW2023_VDD_MAX_UV); +reg_vdd_put: + regulator_put(led->vdd); + return rc; +} + +static void aw2023_brightness_work(struct work_struct *work) +{ + struct aw2023_led *led = container_of(work, struct aw2023_led, + brightness_work); + u8 val; + + mutex_lock(&led->pdata->led->lock); + + /* enable regulators if they are disabled */ + if (!led->pdata->led->poweron) { + if (aw2023_power_on(led->pdata->led, true)) { + dev_err(&led->pdata->led->client->dev, "power on failed"); + mutex_unlock(&led->pdata->led->lock); + return; + } + } + + /* enable aw2023 if disabled */ + aw2023_read(led, AW2023_REG_GCR1, &val); + if (!(val&AW2023_CHIP_ENABLE_MASK)) { + aw2023_write(led, AW2023_REG_GCR1, AW2023_CHIP_ENABLE_MASK); + msleep(2); + } + + if (led->cdev.brightness > 0) { + if (led->cdev.brightness > led->cdev.max_brightness) + led->cdev.brightness = led->cdev.max_brightness; + aw2023_write(led, AW2023_REG_GCR2, led->pdata->imax); + aw2023_write(led, AW2023_REG_LCFG0 + led->id, + (AW2023_LED_MANUAL_MODE_MASK | led->pdata->led_current)); + aw2023_write(led, AW2023_REG_PWM0 + led->id, led->cdev.brightness); + aw2023_read(led, AW2023_REG_LEDEN, &val); + aw2023_write(led, AW2023_REG_LEDEN, val | (1 << led->id)); + } else { + aw2023_read(led, AW2023_REG_LEDEN, &val); + aw2023_write(led, AW2023_REG_LEDEN, val & (~(1 << led->id))); + } + + /* + * If value in AW_REG_LED_ENABLE is 0, it means the RGB leds are + * all off. So we need to power it off. + */ + aw2023_read(led, AW2023_REG_LEDEN, &val); + if (val == 0) { + aw2023_write(led, AW2023_REG_GCR1, AW2023_CHIP_DISABLE_MASK); + + if (aw2023_power_on(led->pdata->led, false)) { + dev_err(&led->pdata->led->client->dev, + "power off failed"); + mutex_unlock(&led->pdata->led->lock); + return; + } + } + + mutex_unlock(&led->pdata->led->lock); +} + +static void aw2023_led_blink_set(struct aw2023_led *led, unsigned long blinking) +{ + u8 val; + + /* enable regulators if they are disabled */ + if (!led->pdata->led->poweron) { + if (aw2023_power_on(led->pdata->led, true)) { + dev_err(&led->pdata->led->client->dev, "power on failed"); + return; + } + } + + /* enable aw2023 if disabled */ + aw2023_read(led, AW2023_REG_GCR1, &val); + if (!(val&AW2023_CHIP_ENABLE_MASK)) { + aw2023_write(led, AW2023_REG_GCR1, AW2023_CHIP_ENABLE_MASK); + msleep(2); + } + + led->cdev.brightness = blinking ? led->cdev.max_brightness : 0; + if (blinking > 0) { + aw2023_write(led, AW2023_REG_GCR2, led->pdata->imax); + aw2023_write(led, AW2023_REG_LCFG0 + led->id, + (AW2023_LED_BREATH_MODE_MASK | led->pdata->led_current)); + aw2023_write(led, AW2023_REG_PWM0 + led->id, led->cdev.brightness); + aw2023_write(led, AW2023_REG_LED0T0 + led->id*3, + (led->pdata->rise_time_ms << 4 | led->pdata->hold_time_ms)); + aw2023_write(led, AW2023_REG_LED0T1 + led->id*3, + (led->pdata->fall_time_ms << 4 | led->pdata->off_time_ms)); + aw2023_read(led, AW2023_REG_LEDEN, &val); + aw2023_write(led, AW2023_REG_LEDEN, val | (1 << led->id)); + } else { + aw2023_read(led, AW2023_REG_LEDEN, &val); + aw2023_write(led, AW2023_REG_LEDEN, val & (~(1 << led->id))); + } + + /* + * If value in AW_REG_LED_ENABLE is 0, it means the RGB leds are + * all off. So we need to power it off. + */ + aw2023_read(led, AW2023_REG_LEDEN, &val); + if (val == 0) { + aw2023_write(led, AW2023_REG_GCR1, AW2023_CHIP_DISABLE_MASK); + if (aw2023_power_on(led->pdata->led, false)) { + dev_err(&led->pdata->led->client->dev, + "power off failed"); + return; + } + } +} + +static void aw2023_set_brightness(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct aw2023_led *led = container_of(cdev, struct aw2023_led, cdev); + + led->cdev.brightness = brightness; + + schedule_work(&led->brightness_work); +} + +static ssize_t aw2023_store_blink(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + unsigned long blinking; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2023_led *led = + container_of(led_cdev, struct aw2023_led, cdev); + ssize_t ret = -EINVAL; + + ret = kstrtoul(buf, 10, &blinking); + if (ret) + return ret; + mutex_lock(&led->pdata->led->lock); + aw2023_led_blink_set(led, blinking); + mutex_unlock(&led->pdata->led->lock); + + return len; +} + +static ssize_t aw2023_led_time_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2023_led *led = + container_of(led_cdev, struct aw2023_led, cdev); + + return snprintf(buf, PAGE_SIZE, "%d %d %d %d\n", + led->pdata->rise_time_ms, led->pdata->hold_time_ms, + led->pdata->fall_time_ms, led->pdata->off_time_ms); +} + +static ssize_t status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 val = 0; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2023_led *led = + container_of(led_cdev, struct aw2023_led, cdev); + aw2023_read(led, AW2023_REG_LEDEN, &val); + return snprintf(buf, PAGE_SIZE, "%d\n", + val); +} + +static ssize_t aw2023_led_time_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2023_led *led = + container_of(led_cdev, struct aw2023_led, cdev); + int rc, rise_time_ms, hold_time_ms, fall_time_ms, off_time_ms; + + rc = sscanf(buf, "%d %d %d %d", + &rise_time_ms, &hold_time_ms, + &fall_time_ms, &off_time_ms); + + mutex_lock(&led->pdata->led->lock); + led->pdata->rise_time_ms = (rise_time_ms > MAX_RISE_TIME_MS) ? + MAX_RISE_TIME_MS : rise_time_ms; + led->pdata->hold_time_ms = (hold_time_ms > MAX_HOLD_TIME_MS) ? + MAX_HOLD_TIME_MS : hold_time_ms; + led->pdata->fall_time_ms = (fall_time_ms > MAX_FALL_TIME_MS) ? + MAX_FALL_TIME_MS : fall_time_ms; + led->pdata->off_time_ms = (off_time_ms > MAX_OFF_TIME_MS) ? + MAX_OFF_TIME_MS : off_time_ms; + aw2023_led_blink_set(led, 1); + mutex_unlock(&led->pdata->led->lock); + return len; +} + + + +static DEVICE_ATTR(status, 0664, status_show, NULL); + + +static ssize_t aw2023_reg_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2023_led *led = + container_of(led_cdev, struct aw2023_led, cdev); + + unsigned char i, reg_val; + ssize_t len = 0; + + for (i = 0; i < AW2023_REG_MAX; i++) { + if (!(aw2023_reg_access[i]®_RD_ACCESS)) + continue; + aw2023_read(led, i, ®_val); + len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%02x=0x%02x\n", i, reg_val); + } + + return len; +} + +static ssize_t aw2023_reg_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct aw2023_led *led = + container_of(led_cdev, struct aw2023_led, cdev); + + unsigned int databuf[2]; + + if (2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) + { + aw2023_write(led, (unsigned char)databuf[0], (unsigned char)databuf[1]); + } + + return len; +} +static DEVICE_ATTR(blink, 0664, NULL, aw2023_store_blink); +static DEVICE_ATTR(led_time, 0664, aw2023_led_time_show, aw2023_led_time_store); +static DEVICE_ATTR(reg, 0664, aw2023_reg_show, aw2023_reg_store); + +static struct attribute *aw2023_led_attributes[] = { + &dev_attr_blink.attr, + &dev_attr_led_time.attr, + &dev_attr_reg.attr, + &dev_attr_status.attr, + NULL, +}; + +static struct attribute_group aw2023_led_attr_group = { + .attrs = aw2023_led_attributes +}; + +static int aw2023_check_chipid(struct aw2023_led *led) +{ + u8 val; + u8 cnt; + + for (cnt = 5; cnt > 0; cnt --) + { + aw2023_read(led, AW2023_REG_RESET, &val); + dev_notice(&led->client->dev, "aw2023 chip id %0x", val); + if (val == AW2023_CHIPID) + return 0; + } + return -EINVAL; +} + +static int aw2023_led_err_handle(struct aw2023_led *led_array, + int parsed_leds) +{ + int i; + /* + * If probe fails, cannot free resource of all LEDs, only free + * resources of LEDs which have allocated these resource really. + */ + for (i = 0; i < parsed_leds; i++) { + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &aw2023_led_attr_group); + led_classdev_unregister(&led_array[i].cdev); + cancel_work_sync(&led_array[i].brightness_work); + devm_kfree(&led_array->client->dev, led_array[i].pdata); + led_array[i].pdata = NULL; + } + return i; +} + +static int aw2023_led_parse_child_node(struct aw2023_led *led_array, + struct device_node *node) +{ + struct aw2023_led *led; + struct device_node *temp; + struct aw2023_platform_data *pdata; + int rc = 0, parsed_leds = 0; + + for_each_child_of_node(node, temp) { + led = &led_array[parsed_leds]; + led->client = led_array->client; + + pdata = devm_kzalloc(&led->client->dev, + sizeof(struct aw2023_platform_data), + GFP_KERNEL); + if (!pdata) { + dev_err(&led->client->dev, + "Failed to allocate memory\n"); + goto free_err; + } + pdata->led = led_array; + led->pdata = pdata; + + rc = of_property_read_string(temp, "aw2023,name", + &led->cdev.name); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading led name, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,id", + &led->id); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading id, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,imax", + &led->pdata->imax); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading id, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,led-current", + &led->pdata->led_current); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading led-current, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,max-brightness", + &led->cdev.max_brightness); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading max-brightness, rc = %d\n", + rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,rise-time-ms", + &led->pdata->rise_time_ms); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading rise-time-ms, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,hold-time-ms", + &led->pdata->hold_time_ms); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading hold-time-ms, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,fall-time-ms", + &led->pdata->fall_time_ms); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading fall-time-ms, rc = %d\n", rc); + goto free_pdata; + } + + rc = of_property_read_u32(temp, "aw2023,off-time-ms", + &led->pdata->off_time_ms); + if (rc < 0) { + dev_err(&led->client->dev, + "Failure reading off-time-ms, rc = %d\n", rc); + goto free_pdata; + } + + INIT_WORK(&led->brightness_work, aw2023_brightness_work); + + led->cdev.brightness_set = aw2023_set_brightness; + + rc = led_classdev_register(&led->client->dev, &led->cdev); + if (rc) { + dev_err(&led->client->dev, + "unable to register led %d,rc=%d\n", + led->id, rc); + goto free_pdata; + } + + rc = sysfs_create_group(&led->cdev.dev->kobj, + &aw2023_led_attr_group); + if (rc) { + dev_err(&led->client->dev, "led sysfs rc: %d\n", rc); + goto free_class; + } + parsed_leds++; + } + + return 0; + +free_class: + aw2023_led_err_handle(led_array, parsed_leds); + led_classdev_unregister(&led_array[parsed_leds].cdev); + cancel_work_sync(&led_array[parsed_leds].brightness_work); + devm_kfree(&led->client->dev, led_array[parsed_leds].pdata); + led_array[parsed_leds].pdata = NULL; + return rc; + +free_pdata: + aw2023_led_err_handle(led_array, parsed_leds); + devm_kfree(&led->client->dev, led_array[parsed_leds].pdata); + return rc; + +free_err: + aw2023_led_err_handle(led_array, parsed_leds); + return rc; +} +static ssize_t aw2023_led_brightness_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) +{ + char buf_tmp[6] = {0}; + s32 ret = 0; + enum led_brightness brightness = LED_OFF; + struct aw2023_led *led = i2c_get_clientdata(aw2023_led_i2c_client); + + if (copy_from_user(buf_tmp, buffer, count)) + return -EFAULT; + + if (strncmp(buf_tmp, "255", 3) == 0) + brightness = LED_FULL; + pr_err("%s buf_tmp %s\n", __func__, buf_tmp); + led->cdev.brightness = brightness; + schedule_work(&led->brightness_work); + ret = count; + return ret; + +} + +static const struct file_operations aw2023_led_brightness_ops = { + .owner = THIS_MODULE, + .read = seq_read, + .write = aw2023_led_brightness_write, +}; +static int aw2023_led_proc_init(void) +{ + aw2023_led_proc_dir = proc_mkdir(AW2023_LED_PROC_FOLDER, NULL); + if (aw2023_led_proc_dir == NULL) { + pr_err(" %s: aw2023 dir file create failed!\n", __func__); + return -ENOMEM; + } + + aw2023_brightness = proc_create(AW2023_LED_PROC_BRIGHTNESS_FILE, + 0664, aw2023_led_proc_dir, &aw2023_led_brightness_ops); + + if (aw2023_brightness == NULL) { + pr_err("%s:aw2023 brightness file create failed!\n", __func__); + goto fail_1; + } + return 0; +fail_1: + remove_proc_entry(AW2023_LED_PROC_BRIGHTNESS_FILE, aw2023_brightness); + remove_proc_entry(AW2023_LED_PROC_FOLDER, NULL); + return -ENOMEM; +} + +static int aw2023_led_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct aw2023_led *led_array; + struct device_node *node; + int ret, num_leds = 0; + node = client->dev.of_node; + if (node == NULL) + return -EINVAL; + + num_leds = of_get_child_count(node); + + if (!num_leds) + return -EINVAL; + + led_array = devm_kzalloc(&client->dev, + (sizeof(struct aw2023_led) * num_leds), GFP_KERNEL); + if (!led_array) + return -ENOMEM; + + + client->addr = 0x45; + + led_array->client = client; + led_array->num_leds = num_leds; + + mutex_init(&led_array->lock); + + ret = aw2023_led_parse_child_node(led_array, node); + if (ret) { + dev_err(&client->dev, "parsed node error\n"); + goto free_led_arry; + } + + i2c_set_clientdata(client, led_array); + aw2023_led_i2c_client = client; + + ret = aw2023_power_init(led_array, true); + if (ret) { + dev_err(&client->dev, "power init failed"); + goto fail_parsed_node; + } + if (!led_array->poweron) + { + ret = aw2023_power_on(led_array->pdata->led, true); + if (ret) { + dev_err(&client->dev, "AW2023 Probe power on fail\n"); + goto fail_parsed_node; + } + } + + ret = aw2023_check_chipid(led_array); + if (ret) { + dev_err(&client->dev, "Check chip id error\n"); + goto fail_parsed_node; + } + + aw2023_led_proc_init(); + return 0; + +fail_parsed_node: + aw2023_led_err_handle(led_array, num_leds); +free_led_arry: + mutex_destroy(&led_array->lock); + devm_kfree(&client->dev, led_array); + led_array = NULL; + return ret; +} + +static int aw2023_led_remove(struct i2c_client *client) +{ + struct aw2023_led *led_array = i2c_get_clientdata(client); + int i, parsed_leds = led_array->num_leds; + + for (i = 0; i < parsed_leds; i++) { + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &aw2023_led_attr_group); + led_classdev_unregister(&led_array[i].cdev); + cancel_work_sync(&led_array[i].brightness_work); + devm_kfree(&client->dev, led_array[i].pdata); + led_array[i].pdata = NULL; + } + remove_proc_entry(AW2023_LED_PROC_BRIGHTNESS_FILE, aw2023_brightness); + remove_proc_entry(AW2023_LED_PROC_FOLDER, NULL); + mutex_destroy(&led_array->lock); + devm_kfree(&client->dev, led_array); + led_array = NULL; + return 0; +} + +static const struct i2c_device_id aw2023_led_id[] = { + {"aw2023_led", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, aw2023_led_id); + +static struct of_device_id aw2023_match_table[] = { + { .compatible = "awinic,aw2023_led",}, + { }, +}; + +static struct i2c_driver aw2023_led_driver = { + .probe = aw2023_led_probe, + .remove = aw2023_led_remove, + .driver = { + .name = "aw2023_led", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(aw2023_match_table), + }, + .id_table = aw2023_led_id, +}; + +static int __init aw2023_led_init(void) +{ + return i2c_add_driver(&aw2023_led_driver); +} +module_init(aw2023_led_init); + +static void __exit aw2023_led_exit(void) +{ + i2c_del_driver(&aw2023_led_driver); +} +module_exit(aw2023_led_exit); + +MODULE_AUTHOR(""); +MODULE_DESCRIPTION("AWINIC AW2023 LED driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 785fe5130672f..debcdc9541c7a 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -29,8 +30,8 @@ #include #include #include +#include #include "leds.h" - #define FLASH_LED_PERIPHERAL_SUBTYPE(base) (base + 0x05) #define FLASH_SAFETY_TIMER(base) (base + 0x40) #define FLASH_MAX_CURRENT(base) (base + 0x41) @@ -172,7 +173,11 @@ struct flash_regulator_data { const char *reg_name; u32 max_volt_uv; }; - +#ifdef CONFIG_FLASHLIGHT_SAKURA +char flashlight[] = {"flashlight"}; +char flashlight_switch[] = {"led:switch"}; +struct led_trigger *flashlight_switch_trigger = NULL; +#endif /* * Configurations for each individual LED */ @@ -1400,6 +1405,18 @@ static void qpnp_flash_led_work(struct work_struct *work) } } + if (led->flash_node[led->num_leds - 1].id == FLASH_LED_SWITCH && + flash_node->id != FLASH_LED_SWITCH) { + led->flash_node[led->num_leds - 1].trigger |= + (0x80 >> flash_node->id); + if (flash_node->id == FLASH_LED_0) + led->flash_node[led->num_leds - 1].prgm_current = + flash_node->prgm_current; + else if (flash_node->id == FLASH_LED_1) + led->flash_node[led->num_leds - 1].prgm_current2 = + flash_node->prgm_current; + } + if (flash_node->type == TORCH) { rc = qpnp_led_masked_write(led->spmi_dev, FLASH_LED_UNLOCK_SECURE(led->base), @@ -1811,6 +1828,10 @@ static void qpnp_flash_led_work(struct work_struct *work) return; turn_off: + if (led->flash_node[led->num_leds - 1].id == FLASH_LED_SWITCH && + flash_node->id != FLASH_LED_SWITCH) + led->flash_node[led->num_leds - 1].trigger &= + ~(0x80 >> flash_node->id); if (flash_node->type == TORCH) { /* * Checking LED fault status detects hardware open fault. @@ -1922,6 +1943,7 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, flash_node->prgm_current = value; flash_node->flash_on = value ? true : false; +#if 0 if (value) led->flash_node[led->num_leds - 1].trigger |= (0x80 >> flash_node->id); @@ -1938,6 +1960,7 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, flash_node->prgm_current; return; +#endif } else if (flash_node->id == FLASH_LED_SWITCH) { if (!value) { flash_node->prgm_current = 0; @@ -1954,7 +1977,17 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, return; } - +#ifdef CONFIG_FLASHLIGHT_SAKURA +/* lancelot add for mi flashlight*/ +static void mido_flash_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + printk(KERN_ERR "lancelot sakura mido_flash_led_brightness_set value %d.\n", value); + qpnp_flash_led_brightness_set(led_cdev, value); + led_trigger_event(flashlight_switch_trigger, (value?1:0)); +} +/* lancelot add end*/ +#endif static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) { int rc; @@ -2617,7 +2650,12 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) "Unable to read flash name\n"); return rc; } - +#ifdef CONFIG_FLASHLIGHT_SAKURA + if (!strncmp(led->flash_node[i].cdev.name, flashlight, strlen(flashlight))) + { + led->flash_node[i].cdev.brightness_set = mido_flash_led_brightness_set; + } +#endif rc = of_property_read_string(temp, "qcom,default-led-trigger", &led->flash_node[i].cdev.default_trigger); if (rc < 0) { @@ -2643,7 +2681,12 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) dev_err(&spmi->dev, "Unable to register led\n"); goto error_led_register; } - +#ifdef CONFIG_FLASHLIGHT_SAKURA + if (!strncmp(led->flash_node[i].cdev.name, flashlight_switch, strlen(flashlight_switch))) + { + flashlight_switch_trigger = led->flash_node[i].cdev.trigger; + } +#endif led->flash_node[i].cdev.dev->of_node = temp; rc = qpnp_flash_led_parse_each_led_dt(led, &led->flash_node[i]); diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c index 5b9b9f3b87b60..36c3a538c8256 100644 --- a/drivers/leds/leds-qpnp-wled.c +++ b/drivers/leds/leds-qpnp-wled.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -323,6 +324,8 @@ struct qpnp_wled { bool prev_state; }; +static int first_set_prev_state; + /* helper to read a pmic register */ static int qpnp_wled_read_reg(struct qpnp_wled *wled, u8 *data, u16 addr) { @@ -811,6 +814,11 @@ static void qpnp_wled_work(struct work_struct *work) } } + if (1 == first_set_prev_state) + { + wled->prev_state = true; + first_set_prev_state = 0; + } if (!!level != wled->prev_state) { rc = qpnp_wled_module_en(wled, wled->ctrl_base, !!level); @@ -1804,6 +1812,11 @@ static int qpnp_wled_probe(struct spmi_device *spmi) return rc; } + if (strnstr(saved_command_line, "androidboot.mode=ffbm-01", + strlen(saved_command_line))){ + printk("linson in ffbm mode\n"); + first_set_prev_state = 1; + } INIT_WORK(&wled->work, qpnp_wled_work); wled->ramp_ms = QPNP_WLED_RAMP_DLY_MS; wled->ramp_step = 1; diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index fbeb531f8d301..ccc95fc4736d4 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -591,6 +591,10 @@ static int32_t msm_actuator_move_focus( if (dest_step_pos == a_ctrl->curr_step_pos) return rc; + if (a_ctrl->step_position_table[dest_step_pos] == + a_ctrl->step_position_table[a_ctrl->curr_step_pos]) + return rc; + if ((sign_dir > MSM_ACTUATOR_MOVE_SIGNED_NEAR) || (sign_dir < MSM_ACTUATOR_MOVE_SIGNED_FAR)) { pr_err("Invalid sign_dir = %d\n", sign_dir); diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c index dd2f9192e32f7..26f31637277d8 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c +++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c @@ -1,4 +1,5 @@ /* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -151,6 +152,7 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, struct msm_eeprom_memory_map_t *emap = block->map; struct msm_eeprom_board_info *eb_info; uint8_t *memptr = block->mapdata; + uint8_t sensor_id[2] = {0}; if (!e_ctrl) { pr_err("%s e_ctrl is NULL", __func__); @@ -159,6 +161,17 @@ static int read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl, eb_info = e_ctrl->eboard_info; + e_ctrl->i2c_client.addr_type = 2; + rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq( + &(e_ctrl->i2c_client), 0x0000, + sensor_id, 2); + if (rc < 0) { + pr_err("%s %d error\n", __func__, __LINE__); + return rc; + } + + CDBG("%s %d addr [0x0000] = %x, [0x0001] = %x\n", __func__, __LINE__, sensor_id[0], sensor_id[1]); + for (j = 0; j < block->num_map; j++) { if (emap[j].saddr.addr) { eb_info->i2c_slaveaddr = emap[j].saddr.addr; diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile index 61301355558d6..dadeef5619160 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile @@ -7,4 +7,5 @@ obj-$(CONFIG_MSMB_CAMERA) += msm_led_flash.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_trigger.o obj-$(CONFIG_MSMB_CAMERA) += msm_led_i2c_trigger.o obj-$(CONFIG_MSMB_CAMERA) += adp1660.o -obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o \ No newline at end of file +obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o +obj-$(CONFIG_MSMB_CAMERA) += msm_frontflash.o diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index 2a32a4a02287f..fe114d285d11a 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -1,4 +1,5 @@ /* Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -36,7 +37,10 @@ static const struct i2c_device_id msm_flash_i2c_id[] = { {"qcom,camera-flash", (kernel_ulong_t)NULL}, { } }; - +#ifdef CONFIG_FLASHLIGHT_VINCE_O +static struct msm_flash_ctrl_t *flashlight_ctrl; +static unsigned char flashlight_brightness_value; +#endif static const struct of_device_id msm_flash_dt_match[] = { {.compatible = "qcom,camera-flash", .data = NULL}, {} @@ -102,7 +106,73 @@ static struct led_classdev msm_torch_led[MAX_LED_TRIGGERS] = { .brightness = LED_OFF, }, }; +#ifdef CONFIG_FLASHLIGHT_VINCE_O +static void msm_flashlight_brightness_vince_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + uint32_t torch_curr[2]; + int32_t i = 0; + struct msm_flash_ctrl_t *flash_ctrl = flashlight_ctrl; + + + torch_curr[0] = 200; + torch_curr[1] = 88; + + flashlight_brightness_value = value; + + if (value == 0) { + /* Turn off flash triggers */ + for (i = 0; i < flash_ctrl->torch_num_sources; i++) + if (flash_ctrl->torch_trigger[i]) + led_trigger_event(flash_ctrl->torch_trigger[i], 0); + + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 0); + + } else { + /* Turn on flash triggers */ + for (i = 0; i < flash_ctrl->torch_num_sources; i++) + led_trigger_event(flash_ctrl->torch_trigger[i], torch_curr[i]); + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 1); + + } +} + +static enum led_brightness msm_flashlight_brightness_vince_get(struct led_classdev *led_cdev) +{ + return flashlight_brightness_value; +} + +static struct led_classdev msm_pmic_flashlight_led = { + .name = "flashlight", + .brightness_set = msm_flashlight_brightness_vince_set, + .brightness_get = msm_flashlight_brightness_vince_get, + .brightness = LED_OFF, +}; +int32_t msm_flashlight_create_classdev(struct platform_device *pdev, + void *data) +{ + int32_t i, rc = 0; + struct msm_flash_ctrl_t *fctrl = + (struct msm_flash_ctrl_t *)data; + + if (!fctrl) { + pr_err("Invalid fctrl\n"); + return -EINVAL; + } + + flashlight_ctrl = fctrl; + + rc = led_classdev_register(&pdev->dev, &msm_pmic_flashlight_led); + if (rc) { + pr_err("Failed to register %d led dev. rc = %d\n", i, rc); + return rc; + } + return 0; +} +#endif static int32_t msm_torch_create_classdev(struct platform_device *pdev, void *data) { @@ -688,6 +758,9 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, switch (flash_data->cfg_type) { case CFG_FLASH_INIT: rc = msm_flash_init_prepare(flash_ctrl, flash_data); +#ifdef CONFIG_FLASHLIGHT_VINCE_O + flashlight_brightness_value = 0; +#endif break; case CFG_FLASH_RELEASE: if (flash_ctrl->flash_state != MSM_CAMERA_FLASH_RELEASE) { @@ -703,6 +776,9 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, (flash_ctrl->flash_state != MSM_CAMERA_FLASH_OFF)) { rc = flash_ctrl->func_tbl->camera_flash_off( flash_ctrl, flash_data); +#ifdef CONFIG_FLASHLIGHT_VINCE_O + flashlight_brightness_value = 0; +#endif if (!rc) flash_ctrl->flash_state = MSM_CAMERA_FLASH_OFF; } else { @@ -715,6 +791,9 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)) { rc = flash_ctrl->func_tbl->camera_flash_low( flash_ctrl, flash_data); +#ifdef CONFIG_FLASHLIGHT_VINCE_O + flashlight_brightness_value = 100; +#endif if (!rc) flash_ctrl->flash_state = MSM_CAMERA_FLASH_LOW; } else { @@ -727,6 +806,9 @@ static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl, (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT)) { rc = flash_ctrl->func_tbl->camera_flash_high( flash_ctrl, flash_data); +#ifdef CONFIG_FLASHLIGHT_VINCE_O + flashlight_brightness_value = 100; +#endif if (!rc) flash_ctrl->flash_state = MSM_CAMERA_FLASH_HIGH; } else { @@ -1273,7 +1355,9 @@ static int32_t msm_flash_platform_probe(struct platform_device *pdev) if (flash_ctrl->flash_driver_type == FLASH_DRIVER_PMIC) rc = msm_torch_create_classdev(pdev, flash_ctrl); - +#ifdef CONFIG_FLASHLIGHT_VINCE_O + msm_flashlight_create_classdev(pdev, flash_ctrl); +#endif CDBG("probe success\n"); return rc; } @@ -1306,6 +1390,10 @@ static int __init msm_flash_init_module(void) { int32_t rc = 0; CDBG("Enter\n"); +#ifdef CONFIG_FLASHLIGHT_VINCE_O + flashlight_ctrl = NULL; + flashlight_brightness_value = 0; +#endif rc = platform_driver_register(&msm_flash_platform_driver); if (!rc) return rc; diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_frontflash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_frontflash.c new file mode 100755 index 0000000000000..905bc849855ba --- /dev/null +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_frontflash.c @@ -0,0 +1,1276 @@ +/* Copyright (c) 2009-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__ + +#include +#include +#include "msm_flash.h" +#include "msm_camera_dt_util.h" +#include "msm_cci.h" + +#undef CDBG +#define CDBG(fmt, args...) pr_debug(fmt, ##args) + +DEFINE_MSM_MUTEX(msm_frontflash_mutex); + +static struct v4l2_file_operations msm_frontflash_v4l2_subdev_fops; + + +static const struct of_device_id msm_frontflash_dt_match[] = { + {.compatible = "qcom,camera-frontflash", .data = NULL}, + {} +}; + +static struct msm_flash_table msm_i2c_frontflash_table; +static struct msm_flash_table msm_gpio_frontflash_table; +static struct msm_flash_table msm_pmic_frontflash_table; + +static struct msm_flash_table *frontflash_table[] = { + &msm_i2c_frontflash_table, + &msm_gpio_frontflash_table, + &msm_pmic_frontflash_table +}; + +static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = { + .i2c_read = msm_camera_cci_i2c_read, + .i2c_read_seq = msm_camera_cci_i2c_read_seq, + .i2c_write = msm_camera_cci_i2c_write, + .i2c_write_table = msm_camera_cci_i2c_write_table, + .i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table, + .i2c_write_table_w_microdelay = + msm_camera_cci_i2c_write_table_w_microdelay, + .i2c_util = msm_sensor_cci_i2c_util, + .i2c_poll = msm_camera_cci_i2c_poll, +}; + +#if 1 +struct gpio_flash_led_pinctrl{ + bool gpio_enabled; + u32 en_gpio; + u32 en_gpio_flags; +}; + +static struct gpio_flash_led_pinctrl front_pinctrl; +#endif + +void msm_subtorch_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + uint16_t i = 0; + if (value) { + if (gpio_is_valid(front_pinctrl.en_gpio)) { + gpio_direction_output(front_pinctrl.en_gpio, 0); + gpio_direction_output(front_pinctrl.en_gpio, 1); + udelay(25); + for (i = 0; i < 10; i++) { + gpio_direction_output(front_pinctrl.en_gpio, 0); + udelay(1); + gpio_direction_output(front_pinctrl.en_gpio, 1); + udelay(1); + pr_err("[WENDELL] i= %d\n", i); + } + } + } else { + gpio_direction_output(front_pinctrl.en_gpio, 0); + } +}; + +static struct led_classdev msm_subtorch_led[MAX_LED_TRIGGERS] = { + { + .name = "subtorch-light0", + .brightness_set = msm_subtorch_brightness_set, + .brightness = LED_OFF, + }, + { + .name = "subtorch-light1", + .brightness_set = msm_subtorch_brightness_set, + .brightness = LED_OFF, + }, + { + .name = "subtorch-light2", + .brightness_set = msm_subtorch_brightness_set, + .brightness = LED_OFF, + }, +}; + +static int32_t msm_subtorch_create_classdev(struct platform_device *pdev, + void *data) +{ + int32_t rc = 0; + struct msm_flash_ctrl_t *fctrl = + (struct msm_flash_ctrl_t *)data; + + if (!fctrl) { + pr_err("Invalid fctrl\n"); + return -EINVAL; + } + + msm_subtorch_brightness_set(&msm_subtorch_led[0], LED_OFF); + + rc = led_classdev_register(&pdev->dev, &msm_subtorch_led[0]); + if (rc) { + pr_err("Failed to register led0 dev. rc = %d\n", rc); + return rc; + } + + return 0; +}; + +static int32_t msm_frontflash_get_subdev_id( + struct msm_flash_ctrl_t *flash_ctrl, void *arg) +{ + uint32_t *subdev_id = (uint32_t *)arg; + CDBG("Enter\n"); + if (!subdev_id) { + pr_err("failed\n"); + return -EINVAL; + } + if (flash_ctrl->flash_device_type == MSM_CAMERA_PLATFORM_DEVICE) + *subdev_id = flash_ctrl->pdev->id; + else + *subdev_id = flash_ctrl->subdev_id; + + CDBG("subdev_id %d\n", *subdev_id); + CDBG("Exit\n"); + return 0; +} + +static int32_t msm_flash_i2c_write_table( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_camera_i2c_reg_setting_array *settings) +{ + struct msm_camera_i2c_reg_setting conf_array; + + conf_array.addr_type = settings->addr_type; + conf_array.data_type = settings->data_type; + conf_array.delay = settings->delay; + conf_array.reg_setting = settings->reg_setting_a; + conf_array.size = settings->size; + + return flash_ctrl->flash_i2c_client.i2c_func_tbl->i2c_write_table( + &flash_ctrl->flash_i2c_client, &conf_array); +} + +#ifdef CONFIG_COMPAT +static void msm_flash_copy_power_settings_compat( + struct msm_sensor_power_setting *ps, + struct msm_sensor_power_setting32 *ps32, uint32_t size) +{ + uint16_t i = 0; + + for (i = 0; i < size; i++) { + ps[i].config_val = ps32[i].config_val; + ps[i].delay = ps32[i].delay; + ps[i].seq_type = ps32[i].seq_type; + ps[i].seq_val = ps32[i].seq_val; + } +} +#endif + +static int32_t msm_frontflash_i2c_init( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t rc = 0; + struct msm_flash_init_info_t *flash_init_info = + flash_data->cfg.flash_init_info; + struct msm_camera_i2c_reg_setting_array *settings = NULL; + struct msm_camera_cci_client *cci_client = NULL; +#ifdef CONFIG_COMPAT + struct msm_sensor_power_setting_array32 *power_setting_array32 = NULL; +#endif + if (!flash_init_info || !flash_init_info->power_setting_array) { + pr_err("%s:%d failed: Null pointer\n", __func__, __LINE__); + return -EFAULT; + } + +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + power_setting_array32 = kzalloc( + sizeof(struct msm_sensor_power_setting_array32), + GFP_KERNEL); + if (!power_setting_array32) { + pr_err("%s mem allocation failed %d\n", + __func__, __LINE__); + return -ENOMEM; + } + + if (copy_from_user(power_setting_array32, + (void *)flash_init_info->power_setting_array, + sizeof(struct msm_sensor_power_setting_array32))) { + pr_err("%s copy_from_user failed %d\n", + __func__, __LINE__); + kfree(power_setting_array32); + return -EFAULT; + } + + flash_ctrl->power_setting_array.size = + power_setting_array32->size; + flash_ctrl->power_setting_array.size_down = + power_setting_array32->size_down; + flash_ctrl->power_setting_array.power_down_setting = + compat_ptr(power_setting_array32->power_down_setting); + flash_ctrl->power_setting_array.power_setting = + compat_ptr(power_setting_array32->power_setting); + + /* Validate power_up array size and power_down array size */ + if ((!flash_ctrl->power_setting_array.size) || + (flash_ctrl->power_setting_array.size > + MAX_POWER_CONFIG) || + (!flash_ctrl->power_setting_array.size_down) || + (flash_ctrl->power_setting_array.size_down > + MAX_POWER_CONFIG)) { + + pr_err("failed: invalid size %d, size_down %d", + flash_ctrl->power_setting_array.size, + flash_ctrl->power_setting_array.size_down); + kfree(power_setting_array32); + power_setting_array32 = NULL; + return -EINVAL; + } + /* Copy the settings from compat struct to regular struct */ + msm_flash_copy_power_settings_compat( + flash_ctrl->power_setting_array.power_setting_a, + power_setting_array32->power_setting_a, + flash_ctrl->power_setting_array.size); + + msm_flash_copy_power_settings_compat( + flash_ctrl->power_setting_array.power_down_setting_a, + power_setting_array32->power_down_setting_a, + flash_ctrl->power_setting_array.size_down); + } else +#endif + if (copy_from_user(&flash_ctrl->power_setting_array, + (void *)flash_init_info->power_setting_array, + sizeof(struct msm_sensor_power_setting_array))) { + pr_err("%s copy_from_user failed %d\n", __func__, __LINE__); + return -EFAULT; + } + + if (flash_ctrl->flash_device_type == MSM_CAMERA_PLATFORM_DEVICE) { + cci_client = flash_ctrl->flash_i2c_client.cci_client; + cci_client->sid = flash_init_info->slave_addr >> 1; + cci_client->retries = 3; + cci_client->id_map = 0; + cci_client->i2c_freq_mode = flash_init_info->i2c_freq_mode; + } + + flash_ctrl->power_info.power_setting = + flash_ctrl->power_setting_array.power_setting_a; + flash_ctrl->power_info.power_down_setting = + flash_ctrl->power_setting_array.power_down_setting_a; + flash_ctrl->power_info.power_setting_size = + flash_ctrl->power_setting_array.size; + flash_ctrl->power_info.power_down_setting_size = + flash_ctrl->power_setting_array.size_down; + + if ((flash_ctrl->power_info.power_setting_size > MAX_POWER_CONFIG) || + (flash_ctrl->power_info.power_down_setting_size > MAX_POWER_CONFIG)) { + pr_err("%s:%d invalid power setting size=%d size_down=%d\n", + __func__, __LINE__, + flash_ctrl->power_info.power_setting_size, + flash_ctrl->power_info.power_down_setting_size); + rc = -EINVAL; + goto msm_flash_i2c_init_fail; + } + + rc = msm_camera_power_up(&flash_ctrl->power_info, + flash_ctrl->flash_device_type, + &flash_ctrl->flash_i2c_client); + if (rc < 0) { + pr_err("%s msm_camera_power_up failed %d\n", + __func__, __LINE__); + goto msm_flash_i2c_init_fail; + } + + if (flash_data->cfg.flash_init_info->settings) { + settings = kzalloc(sizeof( + struct msm_camera_i2c_reg_setting_array), GFP_KERNEL); + if (!settings) { + pr_err("%s mem allocation failed %d\n", + __func__, __LINE__); + return -ENOMEM; + } + + if (copy_from_user(settings, (void *)flash_init_info->settings, + sizeof(struct msm_camera_i2c_reg_setting_array))) { + kfree(settings); + pr_err("%s copy_from_user failed %d\n", + __func__, __LINE__); + return -EFAULT; + } + + rc = msm_flash_i2c_write_table(flash_ctrl, settings); + kfree(settings); + + if (rc < 0) { + pr_err("%s:%d msm_flash_i2c_write_table rc %d failed\n", + __func__, __LINE__, rc); + } + } + + return 0; + +msm_flash_i2c_init_fail: + return rc; +} + +static int32_t msm_frontflash_gpio_init( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t i = 0; + int32_t rc = 0; + + pr_err("[WENDELL]-%s: Enter\n", __func__); + for (i = 0; i < flash_ctrl->flash_num_sources; i++) + flash_ctrl->flash_op_current[i] = LED_FULL; + + for (i = 0; i < flash_ctrl->torch_num_sources; i++) + flash_ctrl->torch_op_current[i] = LED_HALF; + + for (i = 0; i < flash_ctrl->torch_num_sources; i++) { + if (!flash_ctrl->torch_trigger[i]) { + if (i < flash_ctrl->flash_num_sources) + flash_ctrl->torch_trigger[i] = + flash_ctrl->flash_trigger[i]; + else + flash_ctrl->torch_trigger[i] = + flash_ctrl->flash_trigger[ + flash_ctrl->flash_num_sources - 1]; + } + } + + rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, flash_data); + + CDBG("Exit"); + return rc; +} + +static int32_t msm_frontflash_i2c_release( + struct msm_flash_ctrl_t *flash_ctrl) +{ + int32_t rc = 0; + + if (!(&flash_ctrl->power_info) || !(&flash_ctrl->flash_i2c_client)) { + pr_err("%s:%d failed: %pK %pK\n", + __func__, __LINE__, &flash_ctrl->power_info, + &flash_ctrl->flash_i2c_client); + return -EINVAL; + } + + rc = msm_camera_power_down(&flash_ctrl->power_info, + flash_ctrl->flash_device_type, + &flash_ctrl->flash_i2c_client); + if (rc < 0) { + pr_err("%s msm_camera_power_down failed %d\n", + __func__, __LINE__); + return -EINVAL; + } + return 0; +} + +static int32_t msm_frontflash_off(struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t i = 0; + + pr_err("[WENDELL]-%s: Enter\n", __func__); + + for (i = 0; i < flash_ctrl->flash_num_sources; i++) + if (flash_ctrl->flash_trigger[i]) + led_trigger_event(flash_ctrl->flash_trigger[i], 0); + + for (i = 0; i < flash_ctrl->torch_num_sources; i++) + if (flash_ctrl->torch_trigger[i]) + led_trigger_event(flash_ctrl->torch_trigger[i], 0); + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 0); + + CDBG("Exit\n"); + return 0; +} + +static int32_t msm_frontflash_i2c_write_setting_array( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t rc = 0; + struct msm_camera_i2c_reg_setting_array *settings = NULL; + + if (!flash_data->cfg.settings) { + pr_err("%s:%d failed: Null pointer\n", __func__, __LINE__); + return -EFAULT; + } + + settings = kzalloc(sizeof(struct msm_camera_i2c_reg_setting_array), + GFP_KERNEL); + if (!settings) { + pr_err("%s mem allocation failed %d\n", __func__, __LINE__); + return -ENOMEM; + } + + if (copy_from_user(settings, (void *)flash_data->cfg.settings, + sizeof(struct msm_camera_i2c_reg_setting_array))) { + kfree(settings); + pr_err("%s copy_from_user failed %d\n", __func__, __LINE__); + return -EFAULT; + } + + rc = msm_flash_i2c_write_table(flash_ctrl, settings); + kfree(settings); + + if (rc < 0) { + pr_err("%s:%d msm_flash_i2c_write_table rc = %d failed\n", + __func__, __LINE__, rc); + } + return rc; +} + +static int32_t msm_frontflash_init( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + uint32_t i = 0; + int32_t rc = -EFAULT; + enum msm_flash_driver_type flash_driver_type = FLASH_DRIVER_DEFAULT; + + pr_err("[WENDELL]-%s: Enter\n", __func__); + + if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) { + pr_err("%s:%d Invalid flash state = %d", + __func__, __LINE__, flash_ctrl->flash_state); + return 0; + } + + if (flash_data->cfg.flash_init_info->flash_driver_type == + FLASH_DRIVER_DEFAULT) { + flash_driver_type = flash_ctrl->flash_driver_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data->flash_current[i] = + flash_ctrl->flash_max_current[i]; + flash_data->flash_duration[i] = + flash_ctrl->flash_max_duration[i]; + } + } else if (flash_data->cfg.flash_init_info->flash_driver_type == + flash_ctrl->flash_driver_type) { + flash_driver_type = flash_ctrl->flash_driver_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_ctrl->flash_max_current[i] = + flash_data->flash_current[i]; + flash_ctrl->flash_max_duration[i] = + flash_data->flash_duration[i]; + } + } + + if (flash_driver_type == FLASH_DRIVER_DEFAULT) { + pr_err("%s:%d invalid flash_driver_type", __func__, __LINE__); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(frontflash_table); i++) { + if (flash_driver_type == frontflash_table[i]->flash_driver_type) { + flash_ctrl->func_tbl = &frontflash_table[i]->func_tbl; + rc = 0; + } + } + + if (rc < 0) { + pr_err("%s:%d failed invalid flash_driver_type %d\n", + __func__, __LINE__, + flash_data->cfg.flash_init_info->flash_driver_type); + } + + if (flash_ctrl->func_tbl->camera_flash_init) { + rc = flash_ctrl->func_tbl->camera_flash_init( + flash_ctrl, flash_data); + if (rc < 0) { + pr_err("%s:%d camera_flash_init failed rc = %d", + __func__, __LINE__, rc); + return rc; + } + } + + flash_ctrl->flash_state = MSM_CAMERA_FLASH_INIT; + + CDBG("Exit"); + return 0; +} + +#if 1 +static int32_t msm_frontflash_gpio_low( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t i = 0, num = 10; + + pr_err("[WENDELL]-%s cur=%d: -Enter\n", __func__, flash_data->flash_current[0]); + + if (gpio_is_valid(front_pinctrl.en_gpio)) { + gpio_direction_output(front_pinctrl.en_gpio, 0); + gpio_direction_output(front_pinctrl.en_gpio, 1); + udelay(25); + if (flash_data->flash_current[0] != 5000) { + num -= 1; + } + for (; i < num; i++) { + gpio_direction_output(front_pinctrl.en_gpio, 0); + udelay(1); + gpio_direction_output(front_pinctrl.en_gpio, 1); + udelay(1); + pr_err("[WENDELL]low i= %d\n", i); + } + } + + return 0; +} + +static int32_t msm_frontflash_gpio_high( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t i = 0; + + pr_err("[WENDELL]-%s: -Enter\n", __func__); + + if (gpio_is_valid(front_pinctrl.en_gpio)) { + gpio_direction_output(front_pinctrl.en_gpio, 1); + udelay(25); + for (i = 0; i < 10; i++) { + gpio_direction_output(front_pinctrl.en_gpio, 0); + udelay(1); + gpio_direction_output(front_pinctrl.en_gpio, 1); + udelay(1); + pr_err("[WENDELL]high i= %d\n", i); + } + } + + return 0; +} + +static int32_t msm_frontflash_gpio_off( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + + + pr_err("[WENDELL]-%s: -Enter\n", __func__); + + if (gpio_is_valid(front_pinctrl.en_gpio)) { + gpio_direction_output(front_pinctrl.en_gpio, 0); + msleep(5); + } + + return 0; +} +#endif + +static int32_t msm_frontflash_low( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + uint32_t curr = 0, max_current = 0; + int32_t i = 0; + + pr_info("[WENDELL]-%s: Enter\n", __func__); + + + /* Turn off flash triggers */ + for (i = 0; i < flash_ctrl->flash_num_sources; i++) + if (flash_ctrl->flash_trigger[i]) + led_trigger_event(flash_ctrl->flash_trigger[i], 0); + + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 0); + + /* Turn on flash triggers */ + for (i = 0; i < flash_ctrl->torch_num_sources; i++) { + if (flash_ctrl->torch_trigger[i]) { + max_current = flash_ctrl->torch_max_current[i]; + if (flash_data->flash_current[i] >= 0 && + flash_data->flash_current[i] < + max_current) { + curr = flash_data->flash_current[i]; + } else { + curr = flash_ctrl->torch_op_current[i]; + pr_debug("LED current clamped to %d\n", + curr); + } + CDBG("low_flash_current[%d] = %d", i, curr); + led_trigger_event(flash_ctrl->torch_trigger[i], + curr); + } + } + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 1); + CDBG("Exit\n"); + return 0; +} + +static int32_t msm_frontflash_high( + struct msm_flash_ctrl_t *flash_ctrl, + struct msm_flash_cfg_data_t *flash_data) +{ + int32_t curr = 0; + int32_t max_current = 0; + int32_t i = 0; + + pr_err("[frontflash]torch_num = %d,flash_num = %d\n", + flash_ctrl->torch_num_sources, flash_ctrl->flash_num_sources); + + + + + /* Turn off torch triggers */ + for (i = 0; i < flash_ctrl->torch_num_sources; i++) + if (flash_ctrl->torch_trigger[i]) + led_trigger_event(flash_ctrl->torch_trigger[i], 0); + + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 0); + + /* Turn on flash triggers */ + for (i = 0; i < flash_ctrl->flash_num_sources; i++) { + if (flash_ctrl->flash_trigger[i]) { + max_current = flash_ctrl->flash_max_current[i]; + if (flash_data->flash_current[i] >= 0 && + flash_data->flash_current[i] < + max_current) { + curr = flash_data->flash_current[i]; + } else { + curr = flash_ctrl->flash_op_current[i]; + pr_debug("LED flash_current[%d] clamped %d\n", + i, curr); + } + CDBG("high_flash_current[%d] = %d", i, curr); + led_trigger_event(flash_ctrl->flash_trigger[i], + curr); + } + } + if (flash_ctrl->switch_trigger) + led_trigger_event(flash_ctrl->switch_trigger, 1); + return 0; +} + +static int32_t msm_frontflash_release( + struct msm_flash_ctrl_t *flash_ctrl) +{ + int32_t rc = 0; + + pr_info("[WENDELL]-%s: Enter\n", __func__); + if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_RELEASE) { + pr_err("%s:%d Invalid flash state = %d", + __func__, __LINE__, flash_ctrl->flash_state); + return 0; + } + + rc = flash_ctrl->func_tbl->camera_flash_off(flash_ctrl, NULL); + if (rc < 0) { + pr_err("%s:%d camera_flash_init failed rc = %d", + __func__, __LINE__, rc); + return rc; + } + flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE; + return 0; +} + +static int32_t msm_frontflash_config(struct msm_flash_ctrl_t *flash_ctrl, + void __user *argp) +{ + int32_t rc = 0; + struct msm_flash_cfg_data_t *flash_data = + (struct msm_flash_cfg_data_t *) argp; + + mutex_lock(flash_ctrl->flash_mutex); + + pr_err("[WENDELL]: Enter %s type %d\n", __func__, flash_data->cfg_type); + + + switch (flash_data->cfg_type) { + case CFG_FLASH_INIT: + rc = msm_frontflash_init(flash_ctrl, flash_data); + break; + case CFG_FLASH_RELEASE: + if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + rc = flash_ctrl->func_tbl->camera_flash_release( + flash_ctrl); + break; + case CFG_FLASH_OFF: + if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + rc = flash_ctrl->func_tbl->camera_flash_off( + flash_ctrl, flash_data); + break; + case CFG_FLASH_LOW: + if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + rc = flash_ctrl->func_tbl->camera_flash_low( + flash_ctrl, flash_data); + break; + case CFG_FLASH_HIGH: + if (flash_ctrl->flash_state == MSM_CAMERA_FLASH_INIT) + rc = flash_ctrl->func_tbl->camera_flash_high( + flash_ctrl, flash_data); + break; + default: + rc = -EFAULT; + break; + } + + mutex_unlock(flash_ctrl->flash_mutex); + + CDBG("Exit %s type %d\n", __func__, flash_data->cfg_type); + + return rc; +} + +static long msm_frontflash_subdev_ioctl(struct v4l2_subdev *sd, + unsigned int cmd, void *arg) +{ + struct msm_flash_ctrl_t *fctrl = NULL; + void __user *argp = (void __user *)arg; + + CDBG("Enter\n"); + + if (!sd) { + pr_err("sd NULL\n"); + return -EINVAL; + } + fctrl = v4l2_get_subdevdata(sd); + if (!fctrl) { + pr_err("fctrl NULL\n"); + return -EINVAL; + } + switch (cmd) { + case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID: + return msm_frontflash_get_subdev_id(fctrl, argp); + case VIDIOC_MSM_FLASH_CFG: + return msm_frontflash_config(fctrl, argp); + case MSM_SD_NOTIFY_FREEZE: + return 0; + case MSM_SD_UNNOTIFY_FREEZE: + return 0; + case MSM_SD_SHUTDOWN: + if (!fctrl->func_tbl) { + pr_err("fctrl->func_tbl NULL\n"); + return -EINVAL; + } else { + return fctrl->func_tbl->camera_flash_release(fctrl); + } + default: + pr_err_ratelimited("invalid cmd %d\n", cmd); + return -ENOIOCTLCMD; + } + CDBG("Exit\n"); +} + +static struct v4l2_subdev_core_ops msm_frontflash_subdev_core_ops = { + .ioctl = msm_frontflash_subdev_ioctl, +}; + +static struct v4l2_subdev_ops msm_frontflash_subdev_ops = { + .core = &msm_frontflash_subdev_core_ops, +}; + +static const struct v4l2_subdev_internal_ops msm_frontflash_internal_ops; + +static int32_t msm_frontflash_get_pmic_source_info( + struct device_node *of_node, + struct msm_flash_ctrl_t *fctrl) +{ + int32_t rc = 0; + uint32_t count = 0, i = 0; + struct device_node *flash_src_node = NULL; + struct device_node *torch_src_node = NULL; + struct device_node *switch_src_node = NULL; + + switch_src_node = of_parse_phandle(of_node, "qcom,switch-source", 0); + if (!switch_src_node) { + CDBG("%s:%d switch_src_node NULL\n", __func__, __LINE__); + } else { + rc = of_property_read_string(switch_src_node, + "qcom,default-led-trigger", + &fctrl->switch_trigger_name); + if (rc < 0) { + rc = of_property_read_string(switch_src_node, + "linux,default-trigger", + &fctrl->switch_trigger_name); + if (rc < 0) + pr_err("default-trigger read failed\n"); + } + of_node_put(switch_src_node); + switch_src_node = NULL; + if (!rc) { + CDBG("switch trigger %s\n", + fctrl->switch_trigger_name); + led_trigger_register_simple( + fctrl->switch_trigger_name, + &fctrl->switch_trigger); + } + } + + if (of_get_property(of_node, "qcom,flash-source", &count)) { + count /= sizeof(uint32_t); + CDBG("count %d\n", count); + if (count > MAX_LED_TRIGGERS) { + pr_err("invalid count\n"); + return -EINVAL; + } + fctrl->flash_num_sources = count; + CDBG("%s:%d flash_num_sources = %d", + __func__, __LINE__, fctrl->flash_num_sources); + for (i = 0; i < count; i++) { + flash_src_node = of_parse_phandle(of_node, + "qcom,flash-source", i); + if (!flash_src_node) { + pr_err("flash_src_node NULL\n"); + continue; + } + + rc = of_property_read_string(flash_src_node, + "qcom,default-led-trigger", + &fctrl->flash_trigger_name[i]); + if (rc < 0) { + rc = of_property_read_string(flash_src_node, + "linux,default-trigger", + &fctrl->flash_trigger_name[i]); + if (rc < 0) { + pr_err("default-trigger read failed\n"); + of_node_put(flash_src_node); + continue; + } + } + + CDBG("default trigger %s\n", + fctrl->flash_trigger_name[i]); + + /* Read operational-current */ + rc = of_property_read_u32(flash_src_node, + "qcom,current", + &fctrl->flash_op_current[i]); + if (rc < 0) { + pr_err("current: read failed\n"); + of_node_put(flash_src_node); + continue; + } + + /* Read max-current */ + rc = of_property_read_u32(flash_src_node, + "qcom,max-current", + &fctrl->flash_max_current[i]); + if (rc < 0) { + pr_err("current: read failed\n"); + of_node_put(flash_src_node); + continue; + } + + /* Read max-duration */ + rc = of_property_read_u32(flash_src_node, + "qcom,duration", + &fctrl->flash_max_duration[i]); + if (rc < 0) { + pr_err("duration: read failed\n"); + of_node_put(flash_src_node); + /* Non-fatal; this property is optional */ + } + + of_node_put(flash_src_node); + + CDBG("max_current[%d] %d\n", + i, fctrl->flash_op_current[i]); + + led_trigger_register_simple( + fctrl->flash_trigger_name[i], + &fctrl->flash_trigger[i]); + } + if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT) + fctrl->flash_driver_type = FLASH_DRIVER_PMIC; + CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__, + fctrl->flash_driver_type); + } + + if (of_get_property(of_node, "qcom,torch-source", &count)) { + count /= sizeof(uint32_t); + CDBG("count %d\n", count); + if (count > MAX_LED_TRIGGERS) { + pr_err("invalid count\n"); + return -EINVAL; + } + fctrl->torch_num_sources = count; + CDBG("%s:%d torch_num_sources = %d", + __func__, __LINE__, fctrl->torch_num_sources); + for (i = 0; i < count; i++) { + torch_src_node = of_parse_phandle(of_node, + "qcom,torch-source", i); + if (!torch_src_node) { + pr_err("torch_src_node NULL\n"); + continue; + } + + rc = of_property_read_string(torch_src_node, + "qcom,default-led-trigger", + &fctrl->torch_trigger_name[i]); + if (rc < 0) { + rc = of_property_read_string(torch_src_node, + "linux,default-trigger", + &fctrl->torch_trigger_name[i]); + if (rc < 0) { + pr_err("default-trigger read failed\n"); + of_node_put(torch_src_node); + continue; + } + } + + CDBG("default trigger %s\n", + fctrl->torch_trigger_name[i]); + + /* Read operational-current */ + rc = of_property_read_u32(torch_src_node, + "qcom,current", + &fctrl->torch_op_current[i]); + if (rc < 0) { + pr_err("current: read failed\n"); + of_node_put(torch_src_node); + continue; + } + + /* Read max-current */ + rc = of_property_read_u32(torch_src_node, + "qcom,max-current", + &fctrl->torch_max_current[i]); + if (rc < 0) { + pr_err("current: read failed\n"); + of_node_put(torch_src_node); + continue; + } + + of_node_put(torch_src_node); + + CDBG("max_current[%d] %d\n", + i, fctrl->torch_op_current[i]); + + led_trigger_register_simple( + fctrl->torch_trigger_name[i], + &fctrl->torch_trigger[i]); + } + if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT) + fctrl->flash_driver_type = FLASH_DRIVER_PMIC; + CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__, + fctrl->flash_driver_type); + } + + return 0; +} + +static int32_t msm_frontflash_get_dt_data(struct device_node *of_node, + struct msm_flash_ctrl_t *fctrl) +{ + int32_t rc = 0; + + CDBG("called\n"); + + if (!of_node) { + pr_err("of_node NULL\n"); + return -EINVAL; + } + + /* Read the sub device */ + rc = of_property_read_u32(of_node, "cell-index", &fctrl->pdev->id); + if (rc < 0) { + pr_err("failed rc %d\n", rc); + return rc; + } + + CDBG("subdev id %d\n", fctrl->subdev_id); + + fctrl->flash_driver_type = FLASH_DRIVER_DEFAULT; + + /* Read the CCI master. Use M0 if not available in the node */ + rc = of_property_read_u32(of_node, "qcom,cci-master", + &fctrl->cci_i2c_master); + CDBG("%s qcom,cci-master %d, rc %d\n", __func__, fctrl->cci_i2c_master, + rc); + if (rc < 0) { + /* Set default master 0 */ + fctrl->cci_i2c_master = MASTER_0; + rc = 0; + } else { + fctrl->flash_driver_type = FLASH_DRIVER_I2C; + } + + /* Read the flash and torch source info from device tree node */ + rc = msm_frontflash_get_pmic_source_info(of_node, fctrl); + if (rc < 0) { + pr_err("%s:%d msm_flash_get_pmic_source_info failed rc %d\n", + __func__, __LINE__, rc); + return rc; + } + + /* Read the gpio information from device tree */ + rc = msm_sensor_driver_get_gpio_data( + &(fctrl->power_info.gpio_conf), of_node); + if (rc < 0) { + pr_err("%s:%d msm_sensor_driver_get_gpio_data failed rc %d\n", + __func__, __LINE__, rc); + return rc; + } + + #if 1 + front_pinctrl.en_gpio = of_get_named_gpio_flags(of_node, "gpios", + 0, &front_pinctrl.en_gpio_flags); + + if (gpio_is_valid(front_pinctrl.en_gpio)) { + rc = gpio_request(front_pinctrl.en_gpio, "front_flash_en_gpio"); + if (rc) { + pr_err("[WENDELL]-%s: reset gpio request failed\n", __func__); + } else { + pr_err("[WENDELL]-%s: front_pinctrl.en_gpio=%d\n", __func__, front_pinctrl.en_gpio); + rc = gpio_direction_output(front_pinctrl.en_gpio, 0); + if (rc) { + pr_err("[WENDELL]-%s: set_direction for reset gpio failed\n", __func__); + } + } + } + #endif + + if (fctrl->flash_driver_type == FLASH_DRIVER_DEFAULT) + fctrl->flash_driver_type = FLASH_DRIVER_GPIO; + pr_info("[WENDELL]%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__, + fctrl->flash_driver_type); + + return rc; +} + +#ifdef CONFIG_COMPAT +static long msm_frontflash_subdev_do_ioctl( + struct file *file, unsigned int cmd, void *arg) +{ + int32_t i = 0; + int32_t rc = 0; + struct video_device *vdev; + struct v4l2_subdev *sd; + struct msm_flash_cfg_data_t32 *u32; + struct msm_flash_cfg_data_t flash_data; + struct msm_flash_init_info_t32 flash_init_info32; + struct msm_flash_init_info_t flash_init_info; + + CDBG("Enter"); + + if (!file || !arg) { + pr_err("%s:failed NULL parameter\n", __func__); + return -EINVAL; + } + vdev = video_devdata(file); + sd = vdev_to_v4l2_subdev(vdev); + u32 = (struct msm_flash_cfg_data_t32 *)arg; + + flash_data.cfg_type = u32->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data.flash_current[i] = u32->flash_current[i]; + flash_data.flash_duration[i] = u32->flash_duration[i]; + } + switch (cmd) { + case VIDIOC_MSM_FLASH_CFG32: + cmd = VIDIOC_MSM_FLASH_CFG; + switch (flash_data.cfg_type) { + case CFG_FLASH_OFF: + case CFG_FLASH_LOW: + case CFG_FLASH_HIGH: + flash_data.cfg.settings = compat_ptr(u32->cfg.settings); + break; + case CFG_FLASH_INIT: + flash_data.cfg.flash_init_info = &flash_init_info; + if (copy_from_user(&flash_init_info32, + (void *)compat_ptr(u32->cfg.flash_init_info), + sizeof(struct msm_flash_init_info_t32))) { + pr_err("%s copy_from_user failed %d\n", + __func__, __LINE__); + return -EFAULT; + } + flash_init_info.flash_driver_type = + flash_init_info32.flash_driver_type; + flash_init_info.slave_addr = + flash_init_info32.slave_addr; + flash_init_info.i2c_freq_mode = + flash_init_info32.i2c_freq_mode; + flash_init_info.settings = + compat_ptr(flash_init_info32.settings); + flash_init_info.power_setting_array = + compat_ptr( + flash_init_info32.power_setting_array); + break; + default: + break; + } + break; + default: + return msm_frontflash_subdev_ioctl(sd, cmd, arg); + } + + rc = msm_frontflash_subdev_ioctl(sd, cmd, &flash_data); + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + u32->flash_current[i] = flash_data.flash_current[i]; + u32->flash_duration[i] = flash_data.flash_duration[i]; + } + CDBG("Exit"); + return rc; +} + +static long msm_frontflash_subdev_fops_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(file, cmd, arg, msm_frontflash_subdev_do_ioctl); +} +#endif +static int32_t msm_frontflash_platform_probe(struct platform_device *pdev) +{ + int32_t rc = 0; + struct msm_flash_ctrl_t *flash_ctrl = NULL; + struct msm_camera_cci_client *cci_client = NULL; + + CDBG("Enter"); + if (!pdev->dev.of_node) { + pr_err("of_node NULL\n"); + return -EINVAL; + } + + flash_ctrl = kzalloc(sizeof(struct msm_flash_ctrl_t), GFP_KERNEL); + if (!flash_ctrl) { + pr_err("%s:%d failed no memory\n", __func__, __LINE__); + return -ENOMEM; + } + + memset(flash_ctrl, 0, sizeof(struct msm_flash_ctrl_t)); + + flash_ctrl->pdev = pdev; + + rc = msm_frontflash_get_dt_data(pdev->dev.of_node, flash_ctrl); + if (rc < 0) { + pr_err("%s:%d msm_flash_get_dt_data failed\n", + __func__, __LINE__); + kfree(flash_ctrl); + return -EINVAL; + } + + flash_ctrl->flash_state = MSM_CAMERA_FLASH_RELEASE; + flash_ctrl->power_info.dev = &flash_ctrl->pdev->dev; + flash_ctrl->flash_device_type = MSM_CAMERA_PLATFORM_DEVICE; + flash_ctrl->flash_mutex = &msm_frontflash_mutex; + flash_ctrl->flash_i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl; + flash_ctrl->flash_i2c_client.cci_client = kzalloc( + sizeof(struct msm_camera_cci_client), GFP_KERNEL); + if (!flash_ctrl->flash_i2c_client.cci_client) { + kfree(flash_ctrl); + pr_err("failed no memory\n"); + return -ENOMEM; + } + + cci_client = flash_ctrl->flash_i2c_client.cci_client; + cci_client->cci_subdev = msm_cci_get_subdev(); + cci_client->cci_i2c_master = flash_ctrl->cci_i2c_master; + + /* Initialize sub device */ + v4l2_subdev_init(&flash_ctrl->msm_sd.sd, &msm_frontflash_subdev_ops); + v4l2_set_subdevdata(&flash_ctrl->msm_sd.sd, flash_ctrl); + + flash_ctrl->msm_sd.sd.internal_ops = &msm_frontflash_internal_ops; + flash_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + snprintf(flash_ctrl->msm_sd.sd.name, + ARRAY_SIZE(flash_ctrl->msm_sd.sd.name), + "msm_camera_frontflash"); + media_entity_init(&flash_ctrl->msm_sd.sd.entity, 0, NULL, 0); + flash_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV; + flash_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_FLASH; + flash_ctrl->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x1; + msm_sd_register(&flash_ctrl->msm_sd); + + pr_err("[camera]%s:%d frontflash sd name = %s\n", __func__, __LINE__, + flash_ctrl->msm_sd.sd.entity.name); + msm_cam_copy_v4l2_subdev_fops(&msm_frontflash_v4l2_subdev_fops); +#ifdef CONFIG_COMPAT + msm_frontflash_v4l2_subdev_fops.compat_ioctl32 = + msm_frontflash_subdev_fops_ioctl; +#endif + flash_ctrl->msm_sd.sd.devnode->fops = &msm_frontflash_v4l2_subdev_fops; + + rc = msm_subtorch_create_classdev(pdev, flash_ctrl); + + pr_err("[frontflash]probe success\n"); + return rc; +} + +MODULE_DEVICE_TABLE(of, msm_frontflash_dt_match); + +static struct platform_driver msm_frontflash_platform_driver = { + .probe = msm_frontflash_platform_probe, + .driver = { + .name = "qcom,camera-frontflash", + .owner = THIS_MODULE, + .of_match_table = msm_frontflash_dt_match, + }, +}; + +static int __init msm_frontflash_init_module(void) +{ + int32_t rc = 0; + CDBG("Enter\n"); + rc = platform_driver_register(&msm_frontflash_platform_driver); + if (rc) + pr_err("platform probe for flash failed"); + + return rc; +} + +static void __exit msm_frontflash_exit_module(void) +{ + platform_driver_unregister(&msm_frontflash_platform_driver); + return; +} + +static struct msm_flash_table msm_pmic_frontflash_table = { + .flash_driver_type = FLASH_DRIVER_PMIC, + .func_tbl = { + .camera_flash_init = NULL, + .camera_flash_release = msm_frontflash_release, + .camera_flash_off = msm_frontflash_off, + .camera_flash_low = msm_frontflash_low, + .camera_flash_high = msm_frontflash_high, + }, +}; + +static struct msm_flash_table msm_gpio_frontflash_table = { + .flash_driver_type = FLASH_DRIVER_GPIO, + .func_tbl = { + .camera_flash_init = msm_frontflash_gpio_init, + .camera_flash_release = msm_frontflash_release, + .camera_flash_off = msm_frontflash_gpio_off, + .camera_flash_low = msm_frontflash_gpio_low, + .camera_flash_high = msm_frontflash_gpio_high, + }, +}; + +static struct msm_flash_table msm_i2c_frontflash_table = { + .flash_driver_type = FLASH_DRIVER_I2C, + .func_tbl = { + .camera_flash_init = msm_frontflash_i2c_init, + .camera_flash_release = msm_frontflash_i2c_release, + .camera_flash_off = msm_frontflash_i2c_write_setting_array, + .camera_flash_low = msm_frontflash_i2c_write_setting_array, + .camera_flash_high = msm_frontflash_i2c_write_setting_array, + }, +}; + +module_init(msm_frontflash_init_module); +module_exit(msm_frontflash_exit_module); +MODULE_DESCRIPTION("MSM FRONTFLASH"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index 20d7b9f9b1cb3..501ee41153f14 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,6 +18,7 @@ #include "camera.h" #include "msm_cci.h" #include "msm_camera_dt_util.h" +#include /* Logging macro */ #undef CDBG @@ -1023,6 +1025,14 @@ int32_t msm_sensor_driver_probe(void *setting, msm_sensor_fill_sensor_info(s_ctrl, probed_info, entity_name); + if (0 == s_ctrl->id){ + hq_regiser_hw_info(HWID_MAIN_CAM, (char *)(s_ctrl->sensordata->eeprom_name)); + }else if (1 == s_ctrl->id){ + hq_regiser_hw_info(HWID_MAIN_CAM_2, (char *)(s_ctrl->sensordata->eeprom_name)); + }else if (2 == s_ctrl->id){ + hq_regiser_hw_info(HWID_SUB_CAM, (char *)(s_ctrl->sensordata->eeprom_name)); + } + /* * Set probe succeeded flag to 1 so that no other camera shall * probed on this slot diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c index 9af43f4edb8d8..8c87bbed6d778 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,18 +43,23 @@ static const struct v4l2_subdev_internal_ops msm_sensor_init_internal_ops; static int msm_sensor_wait_for_probe_done(struct msm_sensor_init_t *s_init) { int rc; - int tm = 10000; + int tm = 30000; if (s_init->module_init_status == 1) { CDBG("msm_cam_get_module_init_status -2\n"); return 0; } + #if 0 rc = wait_event_timeout(s_init->state_wait, (s_init->module_init_status == 1), msecs_to_jiffies(tm)); if (rc == 0) { pr_err("%s:%d wait timeout\n", __func__, __LINE__); rc = -1; } - + #else + tm = 0; + wait_event(s_init->state_wait, + (s_init->module_init_status == 1)); + #endif return rc; } diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 8ce08107a69d5..d8860aded54b4 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -11,6 +11,13 @@ menuconfig RC_DECODERS depends on RC_CORE default y +config SPI_PEELIR + tristate "PEELIR" + default y + + ---help--- + Enable this option if you use peelir + if RC_DECODERS config LIRC tristate "LIRC interface driver" @@ -33,7 +40,6 @@ config IR_LIRC_CODEC Enable this option to pass raw IR to and from userspace via the LIRC interface. - config IR_NEC_DECODER tristate "Enable IR raw decoder for the NEC protocol" depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 0989f940e9cfa..c53a3dddded46 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o # stand-alone IR receivers/transmitters +# peelir using spi +obj-$(CONFIG_SPI_PEELIR) += peelir.o obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_IR_HIX5HD2) += ir-hix5hd2.o obj-$(CONFIG_IR_IMON) += imon.o diff --git a/drivers/media/rc/peelir.c b/drivers/media/rc/peelir.c new file mode 100644 index 0000000000000..b5120651a58ab --- /dev/null +++ b/drivers/media/rc/peelir.c @@ -0,0 +1,556 @@ +/* +* Copyright (C) 2014 Peel Technologies Inc +* Copyright (C) 2019 XiaoMi, Inc. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#endif +#include +#include +#include +#include "peelir.h" + +#include +#include + +#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ + | SPI_NO_CS | SPI_READY) + +#ifndef CONFIG_OF +#define LR_EN 73 +#endif + +#define TRACE printk("@@@@ %s, %d\n", __func__, __LINE__); + +/*uncoment below defintion to use map +for write*/ +#define USES_MMAP +struct peelir_data { + dev_t devt; + struct spi_device *spi; + struct mutex buf_lock; + spinlock_t spi_lock; + unsigned users; + u8 *buffer; +}; + +/*npages gets its value from the makefile +avoid changing it here*/ +/*static unsigned int npages = CONFIG_NPAGES; */ +static unsigned int npages = 150; +static unsigned bufsiz; /* Default buffer size */ +u32 is_gpio_used; +#ifndef CONFIG_OF +static int mode = 0, bpw = 32, spi_clk_freq = 960000; +#endif +static int lr_en, in_use , rcount; +static int prev_tx_status; /* Status of previous transaction */ +static u32 field; +static const char *reg_id; +static struct regulator *ir_reg; +u8 *p_buf; +struct peelir_data *peel_data_g; +#ifdef USES_MMAP +static void *kmalloc_ptr; +static int *kmalloc_area; +#endif +static struct spi_transfer t; + + +static int ir_regulator_set(bool enable) +{ + int rc = 0; +#ifdef CONFIG_OF + if (ir_reg) { + if (enable) + { + rc = regulator_enable(ir_reg); + } + else + { + rc = regulator_disable(ir_reg); + } + + } +#endif + return rc; +} + + +static inline int +peelir_read(struct peelir_data *peelir, size_t len) +{ + struct spi_message m; + t.rx_buf = peelir->buffer; + t.len = len; + t.tx_buf = NULL; + memset(peelir->buffer, 0, len); TRACE + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spi_sync(peelir->spi, &m); +} + +static int peelir_read_message(struct peelir_data *peelir, + struct spi_ioc_transfer *u_xfers) +{ + u8 *buf; + + memset(peelir->buffer, 0, bufsiz); /*Receive Buffer*/ + + buf = peelir->buffer; TRACE + if (u_xfers->len > bufsiz) { + printk("%s: Requested too large data\n", __func__); + return -EMSGSIZE; + } + + /* Receiving IR input */ + + pr_info("\n Waiting for IR data.... \n"); + pr_info("\n Press the Key\n"); + + peelir_read(peelir, bufsiz); TRACE + + /* copy any rx data to user space */ + if (u_xfers->rx_buf) { + pr_info("\n%s:Copying data to user space\n", __func__); + if (__copy_to_user((u8 __user *) + (uintptr_t) u_xfers->rx_buf, buf, u_xfers->len)) { + pr_info("\n%s:Copy to user space failed !!!\n", __func__); + return -EFAULT; + } + } + + return 0; +} + +static inline int +peelir_write(struct peelir_data *peelir, size_t len) +{ + struct spi_message m; + + t.tx_buf = peelir->buffer; + t.len = len; + t.bits_per_word = peelir->spi->bits_per_word; + spi_message_init(&m); TRACE + spi_message_add_tail(&t, &m); + return spi_sync(peelir->spi, &m); +} + +static int peelir_write_message(struct peelir_data *peelir, + struct spi_ioc_transfer *u_xfers) +{ + u8 *buf; + int status = -EFAULT; + + buf = peelir->buffer; TRACE + + if (u_xfers->len > bufsiz) + status = -EMSGSIZE; + + if (u_xfers->tx_buf) + if (copy_from_user(buf, (const u8 __user *) + (uintptr_t) u_xfers->tx_buf, + u_xfers->len)) + + peelir->spi->bits_per_word = u_xfers->bits_per_word; + + status = peelir_write(peelir, u_xfers->len); TRACE + return status; +} + +static long +peelir_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + struct peelir_data *peelir; + struct spi_ioc_transfer *ioc; + struct strIds *id; + int rc = 0; + + printk("%s:Invoked. cmd = %d\n", __func__, cmd); + peelir = filp->private_data; TRACE + + mutex_lock(&peelir->buf_lock); + + switch (cmd) { + /* read ioctls */ + + case SPI_IOC_WR_MSG: + /* copy into scratch area */ + ioc = kmalloc(sizeof(struct spi_ioc_transfer), GFP_KERNEL); + if (!ioc) { + retval = -ENOMEM; + break; + } + if (__copy_from_user(ioc, (void __user *)arg, sizeof(struct spi_ioc_transfer))) { + kfree(ioc); + retval = -EFAULT; + break; + } + + rc = ir_regulator_set(1); + if (!rc) + { + retval = peelir_write_message(peelir, ioc); + } + if (retval > 0) + prev_tx_status = 1; + else + prev_tx_status = 0; + ir_regulator_set(0); + kfree(ioc); + + break; + + case SPI_IOC_RD_MSG: + printk("%s: READ Invoked\n", __func__); + if (is_gpio_used) + gpio_set_value(lr_en, 1); /* LR Enable high for Rx*/ + /* copy into scratch area */ + ioc = kmalloc(sizeof(struct spi_ioc_transfer), GFP_KERNEL); + if (!ioc) { + pr_err("%s: No memory for ioc. Exiting\n", __func__); + retval = -ENOMEM; + break; + } + if (__copy_from_user(ioc, (void __user *)arg, + sizeof(struct spi_ioc_transfer))) { + pr_err("%s: Error performing copy from user of ioc\n", + __func__); + kfree(ioc); + retval = -EFAULT; + break; + } + printk("%s: Starting hw read\n", __func__); + rc = ir_regulator_set(1); + if (!rc) + { + retval = peelir_read_message(peelir, ioc); + } + ir_regulator_set(0); + if (is_gpio_used) + gpio_set_value(lr_en, 0); /* LR Enable default state*/ + break; + case SPI_IOC_RD_IDS: + id = kmalloc(sizeof(struct strIds), GFP_KERNEL); + if (!id) { + retval = -ENOMEM; + break; + } + id->u32ID1 = 0xad1a4100; + id->u32ID2 = 0x3c03d40; + id->u32ID3 = 0xb5300000; + + if (__copy_to_user((void __user *)arg , id, + sizeof(struct strIds))) { + kfree(id); + retval = -EFAULT; + break; + } + break; + } + + mutex_unlock(&peelir->buf_lock); + + return retval; +} + +static int peelir_open(struct inode *inode, struct file *filp) +{ + struct peelir_data *peelir; + int status = 0; + + peelir = peel_data_g; TRACE + if (in_use) { + dev_err(&peelir->spi->dev, "%s: Device in use. users = %d\n", + __func__, in_use); + return -EBUSY; + } + + peelir->buffer = p_buf; + if (!peelir->buffer) { + if (!peelir->buffer) { + dev_dbg(&peelir->spi->dev, "open/ENOMEM\n"); + status = -ENOMEM; + } + } + if (status == 0) { + peelir->users++; + filp->private_data = peel_data_g; + nonseekable_open(inode, filp); + } + rcount = 0; + + return status; +} + +static int peelir_release(struct inode *inode, struct file *filp) +{ + int status = 0; + in_use = 0; TRACE + peel_data_g->users = 0; + filp->private_data = NULL; + rcount = 0; + return status; +} + +#ifdef USES_MMAP +int peelir_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + struct peelir_data *peelir; + long length = vma->vm_end - vma->vm_start; + + printk(KERN_INFO "mmap is invoked\n"); + peelir = (struct peelir_data *)filp->private_data; TRACE + /* check length - do not allow larger mappings than the number of + pages allocated */ + if (length > bufsiz) + return -EIO; + + ret = remap_pfn_range(vma, vma->vm_start, + virt_to_phys((void *)kmalloc_area) >> PAGE_SHIFT, + length, + vma->vm_page_prot); + if (ret < 0) + return ret; + return 0; +} +#endif +/* + * sysfs layer + */ + +static ssize_t ir_tx_status(struct device *dev, + struct device_attribute *attr, char *buf) +{TRACE + return snprintf(buf, strlen(buf) + 1, "%d\n", prev_tx_status); +} + +static ssize_t field_show(struct device *dev, + struct device_attribute *attr, char *buf) +{TRACE + return snprintf(buf, strlen(buf) + 1, "%x\n", field); +} + +static ssize_t field_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{TRACE + sscanf(buf, "%x", &field); + return count; +} + +static DEVICE_ATTR(txstat, S_IRUGO, ir_tx_status, NULL); +static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field_show, field_store); + +static struct attribute *peel_attributes[] = { + &dev_attr_txstat.attr, + &dev_attr_field.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = peel_attributes, +}; + +/*-------------------------------------------------------------------------*/ +static const struct file_operations peel_dev_fops = { + .owner = THIS_MODULE, + .open = peelir_open, + .release = peelir_release, + .unlocked_ioctl = peelir_ioctl, + .compat_ioctl = peelir_ioctl, + #ifdef USES_MMAP + .mmap = peelir_mmap, + #endif +}; + +static struct miscdevice peel_dev_drv = { + .minor = MISC_DYNAMIC_MINOR, + .name = "peel_ir", + .fops = &peel_dev_fops, + .nodename = "peel_ir", + .mode = 0666 +}; + +static int peelir_probe(struct spi_device *spi) +{ + struct peelir_data *peelir; + int status; + + struct device_node *np = spi->dev.of_node; + #ifdef CONFIG_OF + u32 bpw, mode; TRACE + #endif + /* Allocate driver data */ + peelir = kzalloc(sizeof(*peelir), GFP_KERNEL); + if (!peelir) + return -ENOMEM; + + /* Initialize the driver data */ + peelir->spi = spi; + spin_lock_init(&peelir->spi_lock); + mutex_init(&peelir->buf_lock); + spi_set_drvdata(spi, peelir); + peel_data_g = peelir; + in_use = 0; + #ifdef CONFIG_OF + of_property_read_u32(np, "peel_ir,spi-bpw", &bpw); TRACE + of_property_read_u32(np, "peel_ir,spi-clk-speed", &spi->max_speed_hz); + of_property_read_u32(np, "peel_ir,spi-mode", &mode); + of_property_read_u32(np, "peel_ir,lr-gpio-valid", &is_gpio_used); + of_property_read_u32(np, "peel_ir,peel-field", &field); + of_property_read_u32(np, "peel_ir,lr-gpio", &lr_en); + of_property_read_string(np, "peel_ir,reg-id", ®_id); + if (reg_id) { + ir_reg = regulator_get(&(spi->dev), reg_id); + if (IS_ERR(ir_reg)) { + printk(KERN_ERR "ir regulator_get fail.\n"); + return PTR_ERR(ir_reg); + } + } + printk("%s: lr-gpio-valid = %d\n", __func__, is_gpio_used); + spi->bits_per_word = (u8)bpw; + spi->mode = (u8)mode; + #else + lr_en = LR_EN; TRACE + spi->bits_per_word = bpw; + spi->max_speed_hz = spi_clk_freq; + is_gpio_used = 1; + #endif + printk("%s:lr_en = %d\n", __func__, lr_en); + if (is_gpio_used) { + if (gpio_is_valid(lr_en)) { + /* configure LR enable gpio */ + status = gpio_request(lr_en, "lr_enable"); + if (status) { + printk("unable to request gpio [%d]: %d\n", + lr_en, status); + } + status = gpio_direction_output(lr_en, 0); + if (status) { + printk("unable to set direction for gpio [%d]: %d\n", + lr_en, status); + } + gpio_set_value(lr_en, 0); + } else + printk("gpio %d is not valid \n", lr_en); + } + misc_register(&peel_dev_drv); + /* sysfs entry */ + status = sysfs_create_group(&spi->dev.kobj, &attr_group); + if (status) + dev_dbg(&spi->dev, " Error creating sysfs entry "); + + return status; +} + +static int peelir_remove(struct spi_device *spi) +{ + struct peelir_data *peelir = spi_get_drvdata(spi); + + sysfs_remove_group(&spi->dev.kobj, &attr_group); TRACE + + /* make sure ops on existing fds can abort cleanly */ + spin_lock_irq(&peelir->spi_lock); + peelir->spi = NULL; + spi_set_drvdata(spi, NULL); + spin_unlock_irq(&peelir->spi_lock); + + /* prevent opening a new instance of the device + during the removal of the device + */ + if (peelir->users == 0) { + kfree(peelir); + kfree(p_buf); + } else { + return -EBUSY; + } + + return 0; +} +#ifdef CONFIG_OF +static const struct of_device_id peel_of_match[] = { + {.compatible = "peel_ir"}, +}; +MODULE_DEVICE_TABLE(of, peel_of_match); +#endif +static struct spi_driver peelir_spi_driver = { + .driver = { + .name = "peel_ir", + .owner = THIS_MODULE, + #ifdef CONFIG_OF + .of_match_table = peel_of_match, + #endif + }, + .probe = peelir_probe, + .remove = peelir_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init peelir_init(void) +{ + int status; + printk("%s:npages = %u\n", __func__, npages); + bufsiz = npages * PAGE_SIZE; + if (bufsiz % PAGE_SIZE) { + printk("%s:buffer size not aligned to page\n", __func__); + return -EINVAL; + } + p_buf = kzalloc(bufsiz, GFP_KERNEL|GFP_ATOMIC); + if (p_buf == NULL) + return -ENOMEM; + #ifdef USES_MMAP + kmalloc_ptr = p_buf; + kmalloc_area = (int *)((((unsigned long)kmalloc_ptr) + + PAGE_SIZE - 1) & PAGE_MASK); + #endif + status = spi_register_driver(&peelir_spi_driver); + if (status < 0 || p_buf == NULL) { + printk("%s: Error registerign peel driver\n", __func__); + return -ENODEV; + } + + return status; +} +module_init(peelir_init); + +static void __exit peelir_exit(void) +{ + spi_unregister_driver(&peelir_spi_driver); + misc_deregister(&peel_dev_drv); +} +module_exit(peelir_exit); + +MODULE_DESCRIPTION("Peel IR SPI driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("PEEL_IR"); +MODULE_AUTHOR("Preetam S Reddy "); + diff --git a/drivers/media/rc/peelir.h b/drivers/media/rc/peelir.h new file mode 100644 index 0000000000000..eaa37b6de2e51 --- /dev/null +++ b/drivers/media/rc/peelir.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) Peel Technologies Inc + * Copyright (C) 2019 XiaoMi, Inc. + */ + +#ifndef PEELIR_H +#define PEELIR_H + +#include + +/* User space versions of kernel symbols for SPI clocking modes, + * matching + */ + +#define SPI_CPHA 0x01 +#define SPI_CPOL 0x02 + +#define SPI_CS_HIGH 0x04 +#define SPI_LSB_FIRST 0x08 +#define SPI_3WIRE 0x10 +#define SPI_LOOP 0x20 +#define SPI_NO_CS 0x40 +#define SPI_READY 0x80 + +/*---------------------------------------------------------------------------*/ + +/* IOCTL commands */ + +#define SPI_IOC_MAGIC 'k' + +/** + * struct spi_ioc_transfer - describes a single SPI transfer + * @tx_buf: Holds pointer to userspace buffer with transmit data, or null. + * If no data is provided, zeroes are shifted out. + * @rx_buf: Holds pointer to userspace buffer for receive data, or null. + * @len: Length of tx and rx buffers, in bytes. + * @speed_hz: Temporary override of the device's bitrate. + * @bits_per_word: Temporary override of the device's wordsize. + * @delay_usecs: If nonzero, how long to delay after the last bit transfer + * before optionally deselecting the device before the next transfer. + * @cs_change: True to deselect device before starting the next transfer. + * + * This structure is mapped directly to the kernel spi_transfer structure; + * the fields have the same meanings, except of course that the pointers + * are in a different address space (and may be of different sizes in some + * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel). + */ +struct spi_ioc_transfer { + __u64 tx_buf; + __u64 rx_buf; + + __u32 len; + __u32 speed_hz; + + __u16 delay_usecs; + __u8 bits_per_word; + __u8 cs_change; + + /* If the contents of 'struct spi_ioc_transfer' ever change + * incompatibly, then the ioctl number (currently 0) must change; + * ioctls with constant size fields get a bit more in the way of + * error checking than ones (like this) where that field varies. + * + * NOTE: struct layout is the same in 64bit and 32bit userspace. + */ +}; + +struct strIds { + __u32 u32ID1; + __u32 u32ID2; + __u32 u32ID3; +}; + +/* Read/Write Message */ +#define SPI_IOC_RD_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) +#define SPI_IOC_WR_MSG _IOW(SPI_IOC_MAGIC, 2, __u8) +#define SPI_IOC_RD_MSG _IOR(SPI_IOC_MAGIC, 3, __u8) +#define SPI_IOC_RD_IDS _IOR(SPI_IOC_MAGIC, 4, __u8) + + +#endif /* PEELIR_H */ + diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 41a6864ab8d2e..ef8f22a5e9a69 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1687,6 +1687,8 @@ static int em28xx_dvb_fini(struct em28xx *dev) } } + em28xx_unregister_dvb(dvb); + /* remove I2C tuner */ if (client) { module_put(client->dev.driver->owner); @@ -1700,7 +1702,6 @@ static int em28xx_dvb_fini(struct em28xx *dev) i2c_unregister_device(client); } - em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; kref_put(&dev->ref, em28xx_free_device); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b78aefcd76a5f..928c8201dbcb8 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -627,4 +627,6 @@ source "drivers/misc/mic/Kconfig" source "drivers/misc/genwqe/Kconfig" source "drivers/misc/echo/Kconfig" source "drivers/misc/cxl/Kconfig" +source "drivers/misc/hqsysfs/Kconfig" +source "drivers/misc/xiaomi_fs/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index d08212274dce9..4b0049d2ff550 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -73,3 +73,5 @@ obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o obj-$(CONFIG_APDS9930) += apds993x.o obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o +obj-$(CONFIG_HQ_SYSFS_SUPPORT) += hqsysfs/ +obj-$(CONFIG_MI_FS) +=xiaomi_fs/ diff --git a/drivers/misc/hqsysfs/Kconfig b/drivers/misc/hqsysfs/Kconfig new file mode 100644 index 0000000000000..26e3e4a0adf31 --- /dev/null +++ b/drivers/misc/hqsysfs/Kconfig @@ -0,0 +1,6 @@ +config HQ_SYSFS_SUPPORT + bool "Enable Huaqin Sysfs Driver" + default n + help + Huaqin Sysfs information driver includes specific information about hardware info and other info for HQ tools + diff --git a/drivers/misc/hqsysfs/Makefile b/drivers/misc/hqsysfs/Makefile new file mode 100644 index 0000000000000..72f8872f2ea49 --- /dev/null +++ b/drivers/misc/hqsysfs/Makefile @@ -0,0 +1,19 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +# obj-$(CONFIG_HQ_SYSFS_SUPPORT) := hqsysfs.o +obj-y := hqsysfs.o +obj-y += hqsys_misc.o +obj-y += hqsys_pcba.o +#obj-y += hqsys_emmc_info.o +#obj-y += hqsys_cam_info.o diff --git a/drivers/misc/hqsysfs/hqsys_misc.c b/drivers/misc/hqsysfs/hqsys_misc.c new file mode 100755 index 0000000000000..56423d3d82a95 --- /dev/null +++ b/drivers/misc/hqsysfs/hqsys_misc.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "hqsys_misc.h" + + +MISC_INFO(MISC_EMMC_SIZE, emmc_size); +MISC_INFO(MISC_RAM_SIZE, ram_size); +MISC_INFO(MISC_BOOT_MODE, boot_mode); +MISC_INFO(MISC_OTP_SN, otp_sn); + +extern unsigned int msdc_get_capacity(int get_emmc_total); +extern char *get_emmc_name(void); + +unsigned int round_kbytes_to_readable_mbytes(unsigned int k){ + unsigned int r_size_m = 0; + unsigned int in_mega = k/1024; + + if (in_mega > 64*1024){ + r_size_m = 128*1024; + }else if (in_mega > 32*1024){ + r_size_m = 64*1024; + }else if (in_mega > 16*1024){ + r_size_m = 32*1024; + }else if (in_mega > 8*1024){ + r_size_m = 16*1024; + }else if (in_mega > 6*1024){ + r_size_m = 8*1024; + }else if (in_mega > 4*1024){ + r_size_m = 6*1024; + }else if (in_mega > 3*1024){ + r_size_m = 4*1024; + }else if (in_mega > 2*1024){ + r_size_m = 3*1024; + }else if (in_mega > 1024){ + r_size_m = 2*1024; + }else if (in_mega > 512){ + r_size_m = 1024; + }else if (in_mega > 256){ + r_size_m = 512; + }else if (in_mega > 128){ + r_size_m = 256; + }else{ + k = 0; + } + return r_size_m; +} + +ssize_t hq_emmcinfo(char *buf) +{ + ssize_t count = -1; + struct file *pfile = NULL; + mm_segment_t old_fs; + loff_t pos; + ssize_t ret = 0; + + unsigned long long Size_buf = 0; + char buf_size[qcom_emmc_len]; + memset(buf_size, 0, sizeof(buf_size)); + + pfile = filp_open(qcom_emmc, O_RDONLY, 0); + if (IS_ERR(pfile)) { + goto ERR_0; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + + ret = vfs_read(pfile, buf_size, qcom_emmc_len, &pos); + if (ret <=0) + { + goto ERR_1; + } + + Size_buf = simple_strtoull(buf_size, NULL, 0); + + Size_buf>>=1; + + + count = sprintf(buf, "%dGB", round_kbytes_to_readable_mbytes((unsigned int)Size_buf)/1024); + +ERR_1: + + filp_close(pfile, NULL); + + set_fs(old_fs); + + return count; + +ERR_0: + return count; + +} + +static struct attribute *hq_misc_attrs[] = { + &misc_info_emmc_size.attr, + &misc_info_ram_size.attr, + &misc_info_boot_mode.attr, + &misc_info_otp_sn.attr, + NULL +}; + +extern int hq_read_sn_from_otp(char *sn); +extern int hq_write_sn_to_otp(char *sn, unsigned int len); +#define SN_LEN (12) + +static ssize_t hq_misc_show(struct kobject *kobj, struct attribute *a, char *buf){ + ssize_t count = 0; + + struct misc_info *mi = container_of(a, struct misc_info , attr); + + switch(mi->m_id){ + case MISC_RAM_SIZE: + { + #define K(x) ((x) << (PAGE_SHIFT - 10)) + struct sysinfo i; + si_meminfo(&i); + + + if (round_kbytes_to_readable_mbytes(K(i.totalram)) >= 1024){ + count = sprintf(buf, "%dGB", round_kbytes_to_readable_mbytes(K(i.totalram))/1024); + }else{ + count = sprintf(buf, "%dMB", round_kbytes_to_readable_mbytes(K(i.totalram))); + } + + } + break; + case MISC_EMMC_SIZE: + + count = hq_emmcinfo(buf); + break; + case MISC_OTP_SN: +#ifdef CONFIG_MTK_EMMC_SUPPORT_OTP + { + char temp[SN_LEN+1] = {0}; + int result = 0; + int i = 0; + + result = hq_read_sn_from_otp(temp); + + if (0 == result){ + #if 0 + + for (i = 0; i < SN_LEN; i++){ + if (!isalnum(temp[i])){ + count = sprintf(buf, "Not Valid SN\n"); + goto r_error; + } + } + #endif + count = sprintf(buf, "%s", temp); + }else{ + count = sprintf(buf, "Read SN in OTP error %d\n", result); + } + } + +#else + count = sprintf(buf, "SN in OTP not enabled\n"); +#endif + break; + default: + count = sprintf(buf, "Not support"); + break; + } + + + return count; +} + +static ssize_t hq_misc_store(struct kobject *kobj, struct attribute *a, const char *buf, size_t count){ + + struct misc_info *mi = container_of(a, struct misc_info , attr); + + switch(mi->m_id){ +#ifdef CONFIG_MTK_EMMC_SUPPORT_OTP + case MISC_OTP_SN: + { + char temp[SN_LEN+1] = {0}; + int result = 0; + int i = 0; + + if (0 != strncmp(buf, "SN:=", 4)){ + printk("[%s] invalid write sn command\n"); + break; + } + for (i = 0; i < SN_LEN; i++){ + temp[i] = buf[i+4]; + if (('\n' == buf[i+4]) || ('\r' == buf[i+4])){ + temp[i] = 0; + break; + } + } + + + result = hq_write_sn_to_otp(temp, strlen(temp)); + if (0 != result) + printk("[%s] called write error %d\n", __func__, result); + + } + break; +#endif + default: + break; + } + return count; +} + +/* hq_misc object */ +static struct kobject hq_misc_kobj; +static const struct sysfs_ops hq_misc_sysfs_ops = { + .show = hq_misc_show, + .store = hq_misc_store, +}; + +/* hq_misc type */ +static struct kobj_type hq_misc_ktype = { + .sysfs_ops = &hq_misc_sysfs_ops, + .default_attrs = hq_misc_attrs +}; + + +static int __init create_misc(void){ + int ret; + + /* add kobject */ + ret = register_kboj_under_hqsysfs(&hq_misc_kobj, &hq_misc_ktype, HUAQIN_MISC_NAME); + if (ret < 0) { + pr_err("%s fail to add hq_misc_kobj\n", __func__); + return ret; + } + return 0; +} + + + +static int __init hq_misc_sys_init(void) +{ + /* create sysfs entry at /sys/class/hq_misc/interface/misc */ + create_misc(); + + return 0; +} + + +late_initcall(hq_misc_sys_init); +MODULE_AUTHOR("KaKa Ni "); +MODULE_DESCRIPTION("Huaqin Hardware Info Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/hqsysfs/hqsys_misc.h b/drivers/misc/hqsysfs/hqsys_misc.h new file mode 100644 index 0000000000000..322c98a7ad1e9 --- /dev/null +++ b/drivers/misc/hqsysfs/hqsys_misc.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __HQ_SYSFS_MISC_H__ +#define __HQ_SYSFS_MISC_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#endif +#include +#include + +#include + +#define qcom_emmc "/sys/class/mmc_host/mmc0/mmc0:0001/block/mmcblk0/size" +#define qcom_emmc_len 16 + +#define HUAQIN_MISC_NAME "misc" + + +enum misc_id{ + MISC_EMMC_SIZE = 0, + MISC_RAM_SIZE, + MISC_BOOT_MODE, + MISC_OTP_SN, + MISC_NONE +}; + +struct emmc_info{ + unsigned int cid[4] ; + const char *emmc_name; +}; + + + +struct misc_info{ + enum misc_id m_id; + struct attribute attr; +}; + +struct cam_info{ + char *cam_drv_name; + char *cam_vendro_name; +}; + + + +#define __MISC(_id, _misc_name) { \ + .m_id = _id, \ + .attr = {.name = __stringify(_misc_name), \ + .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR|S_IRUGO) }, \ + } + + +#define MISC_INFO(_id, _misc_name) \ + struct misc_info misc_info_##_misc_name = __MISC(_id, _misc_name) + + + +#define __EMMC(cid_0, cid_1, cid_2, cid_3, _emmc_name) { \ + .cid[0] = cid_0, \ + .cid[1] = cid_1, \ + .cid[2] = cid_2, \ + .cid[3] = cid_3, \ + .emmc_name = __stringify(_emmc_name), \ + } + + +#define EMMC_INFO(cid_0, cid_1, cid_2, cid_3, _emmc_name) \ + struct emmc_info emmc_info_##_emmc_name = __EMMC(cid_0, cid_1, cid_2, cid_3, _emmc_name) + + + +#define CAM_MAP_INFO(_drv, _vendor) \ + struct cam_info cam_info_##_drv = { \ + .cam_drv_name = __stringify(_drv), \ + .cam_vendro_name = __stringify(_vendor), \ + } + +char *get_emmc_name(void); +char *map_cam_drv_to_vendor(char *drv); + + +#endif diff --git a/drivers/misc/hqsysfs/hqsys_pcba.c b/drivers/misc/hqsysfs/hqsys_pcba.c new file mode 100644 index 0000000000000..f1a15904e7982 --- /dev/null +++ b/drivers/misc/hqsysfs/hqsys_pcba.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hqsys_pcba.h" + + +static PCBA_CONFIG huaqin_pcba_config; + + + + + +static void read_pcba_config_form_smem(void) +{ + PCBA_CONFIG *pcba_config = NULL; + pcba_config = (PCBA_CONFIG *)smem_find(SMEM_ID_VENDOR1, sizeof(PCBA_CONFIG), 0, SMEM_ANY_HOST_FLAG); + if (pcba_config) + { + printk(KERN_ERR "pcba config =%d.\n", *(pcba_config)); + if (*(pcba_config) > PCBA_UNKNOW && *(pcba_config) < PCBA_END) + { + huaqin_pcba_config = *pcba_config; + } + else + { + huaqin_pcba_config = PCBA_UNKNOW; + } + } + else + { + printk(KERN_ERR "pcba config fail\n"); + + huaqin_pcba_config = PCBA_UNKNOW; + } +} + +PCBA_CONFIG get_huaqin_pcba_config(void) +{ + return huaqin_pcba_config; +} +EXPORT_SYMBOL_GPL(get_huaqin_pcba_config); + + +#if 0 + +int huaqin_pcba_vadc_probe(struct platform_device *ppcba_vadc) +{ + struct qpnp_vadc_result vadc_result; + int64_t vadc; + vadc = 0; + printk("%s\n", __func__); + huaqin_pcba_vadc_of_node = ppcba_vadc->dev.of_node; + pcba_vadc = qpnp_get_vadc(&(ppcba_vadc->dev), "huaqin-pcba"); + if (!IS_ERR(pcba_vadc)) + { + qpnp_vadc_read(pcba_vadc, P_MUX1_1_1, &vadc_result); + vadc = vadc_result.physical/1000; + printk(KERN_ERR "%s %lld\n", __func__, vadc); + } + return 0; +} +static struct of_device_id huaqin_pcba_vadc_match_table[] = { + {.compatible = "huaqin_pcba_vadc"}, + {} +}; + +static struct platform_driver huaqin_pcba_vadc_driver = { + .probe = huaqin_pcba_vadc_probe, + .driver = { + .name = "huaqinc_pcba_vadc_8940", + .of_match_table = huaqin_pcba_vadc_match_table, + .owner = THIS_MODULE, + }, +}; +static int __init huaqin_pcba_module_init(void) +{ + + platform_driver_register(&huaqin_pcba_vadc_driver); + + return 0; +} +#endif + +static int __init huaqin_pcba_early_init(void) +{ + + read_pcba_config_form_smem(); + return 0; +} + +subsys_initcall(huaqin_pcba_early_init); + + + +MODULE_AUTHOR("ninjia "); +MODULE_DESCRIPTION("huaqin sys pcba"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/hqsysfs/hqsys_pcba.h b/drivers/misc/hqsysfs/hqsys_pcba.h new file mode 100644 index 0000000000000..2796a44a74609 --- /dev/null +++ b/drivers/misc/hqsysfs/hqsys_pcba.h @@ -0,0 +1,38 @@ +#ifndef HQSYS_PCBA +#define HQSYS_PCBA + + +typedef enum +{ + PCBA_UNKNOW = 0, + + PCBA_V1_CN = 0x20, + PCBA_V1_SA, + PCBA_V1_GLOBAL, + PCBA_V1_IN, + + PCBA_V2_CN, + PCBA_V2_GLOBAL, + PCBA_V2_IN, + + PCBA_E7 = 0x80, + PCBA_E7_CN, + PCBA_E7_IN, + PCBA_E7_GLOBAL, + + PCBA_END, + + +}PCBA_CONFIG; + +struct pcba_info +{ + PCBA_CONFIG pcba_config; + char pcba_name[32]; +}; + + + +PCBA_CONFIG get_huaqin_pcba_config(void); + +#endif diff --git a/drivers/misc/hqsysfs/hqsysfs.c b/drivers/misc/hqsysfs/hqsysfs.c new file mode 100644 index 0000000000000..3fb6136359e9b --- /dev/null +++ b/drivers/misc/hqsysfs/hqsysfs.c @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include "hqsys_misc.h" +#include "hqsys_pcba.h" + +#define HQ_SYS_FS_VER "2016-03-11 V0.2" + +static HW_INFO(HWID_VER, ver); +static HW_INFO(HWID_SUMMARY, hw_summary); +static HW_INFO(HWID_DDR, ram); +static HW_INFO(HWID_EMMC, emmc); +static HW_INFO(HWID_LCM, lcm); + +static HW_INFO(HWID_CTP, ctp); +static HW_INFO(HWID_MAIN_CAM, main_cam); +static HW_INFO(HWID_MAIN_CAM_2, main_cam_2); +static HW_INFO(HWID_MAIN_LENS, main_cam_len); +static HW_INFO(HWID_FLASHLIGHT, flashlight); +static HW_INFO(HWID_SUB_CAM, sub_cam); +static HW_INFO(HWID_GSENSOR, gsensor); +static HW_INFO(HWID_ALSPS, alsps); +static HW_INFO(HWID_MSENSOR, msensor); +static HW_INFO(HWID_GYRO, gyro); +static HW_INFO(HWID_IRDA, irda); +static HW_INFO(HWID_FUEL_GAUGE_IC, fuel_gauge_ic); +static HW_INFO(HWID_NFC, nfc); +static HW_INFO(HWID_FP, fingerprint); + +static HW_INFO(HWID_PCBA, pcba_config); + + +struct pcba_info pcba[] = { + + {PCBA_UNKNOW, "PCBA_UNKNOW"}, + {PCBA_V1_CN, "PCBA_V1_CN"}, + {PCBA_V1_SA, "PCBA_V1_SA"}, + {PCBA_V1_GLOBAL, "PCBA_V1_GLOBAL"}, + {PCBA_V1_IN, "PCBA_V1_IN"}, + {PCBA_V2_CN, "PCBA_V2_CN"}, + {PCBA_V2_GLOBAL, "PCBA_V2_GLOBAL"}, + {PCBA_V2_IN, "PCBA_V2_IN"}, + {PCBA_E7_CN, "PCBA_E7_CN"}, + {PCBA_E7_IN, "PCBA_E7_IN"}, + {PCBA_E7_GLOBAL, "PCBA_E7_GLOBAL"} + + +}; +static PCBA_CONFIG huaqin_pcba_config = PCBA_UNKNOW; + +static struct attribute *huaqin_attrs[] = { + &hw_info_ver.attr, + &hw_info_hw_summary.attr, + &hw_info_ram.attr, + &hw_info_emmc.attr, + &hw_info_lcm.attr, + + &hw_info_ctp.attr, + &hw_info_main_cam.attr, + &hw_info_main_cam_2.attr, + &hw_info_main_cam_len.attr, + &hw_info_flashlight.attr, + &hw_info_sub_cam.attr, + &hw_info_gsensor.attr, + &hw_info_alsps.attr, + &hw_info_msensor.attr, + &hw_info_gyro.attr, + &hw_info_irda.attr, + &hw_info_fuel_gauge_ic.attr, + &hw_info_nfc.attr, + &hw_info_fingerprint.attr, + &hw_info_pcba_config.attr, + + NULL +}; + +static ssize_t huaqin_show(struct kobject *kobj, struct attribute *a, char *buf) +{ + ssize_t count = 0; + int i = 0; + struct hw_info *hw = container_of(a, struct hw_info , attr); + + if (NULL == hw){ + return sprintf(buf, "Data error\n"); + } + + if (HWID_VER == hw->hw_id){ + count = sprintf(buf, "%s\n", HQ_SYS_FS_VER); + }else if (HWID_SUMMARY == hw->hw_id){ + + int iterator = 0; + struct hw_info *curent_hw = NULL; + struct attribute *attr = huaqin_attrs[iterator]; + + while(attr){ + curent_hw = container_of(attr, struct hw_info , attr); + iterator += 1; + attr = huaqin_attrs[iterator]; + + if (curent_hw->hw_exist && (NULL != curent_hw->hw_device_name)){ + count += sprintf(buf+count, "%s: %s\n" , curent_hw->attr.name, curent_hw->hw_device_name); + } + } + + }else if (HWID_PCBA == hw->hw_id){ + + if (get_huaqin_pcba_config() > PCBA_UNKNOW && get_huaqin_pcba_config() < PCBA_END) + { + huaqin_pcba_config = get_huaqin_pcba_config(); + } + else + { + huaqin_pcba_config = PCBA_UNKNOW; + } + + for (i = 0; i < sizeof(pcba)/sizeof(struct pcba_info); i++) + { + if (huaqin_pcba_config == pcba[i].pcba_config) + { + count = sprintf(buf, "%s\n", pcba[i].pcba_name); + return count; + } + } + + + + count = sprintf(buf, "%s\n", "PCBA_UNKNOW"); + + }else{ + + if (0 == hw->hw_exist){ + count = sprintf(buf, "Not support\n"); + }else if (NULL == hw->hw_device_name){ + count = sprintf(buf, "Installed with no device Name\n"); + }else{ + count = sprintf(buf, "%s\n" , hw->hw_device_name); + } + } + + return count; +} + +static ssize_t huaqin_store(struct kobject *kobj, struct attribute *a, const char *buf, size_t count) +{ + return count; +} + +/* huaqin object */ +static struct kobject huaqin_kobj; +static const struct sysfs_ops huaqin_sysfs_ops = { + .show = huaqin_show, + .store = huaqin_store, +}; + +/* huaqin type */ +static struct kobj_type huaqin_ktype = { + .sysfs_ops = &huaqin_sysfs_ops, + .default_attrs = huaqin_attrs +}; + +/* huaqin device class */ +static struct class *huaqin_class; +static struct device *huaqin_hw_device; + + +int register_kboj_under_hqsysfs(struct kobject *kobj, struct kobj_type *ktype, const char *fmt, ...){ + return kobject_init_and_add(kobj, ktype, &(huaqin_hw_device->kobj), fmt); +} + +static int __init create_sysfs(void) +{ + int ret; + + /* create class (device model) */ + huaqin_class = class_create(THIS_MODULE, HUAQIN_CLASS_NAME); + if (IS_ERR(huaqin_class)) { + pr_err("%s fail to create class\n", __func__); + return -EPERM; + } + + huaqin_hw_device = device_create(huaqin_class, NULL, MKDEV(0, 0), NULL, HUAIN_INTERFACE_NAME); + if (IS_ERR(huaqin_hw_device)) { + pr_warn("fail to create device\n"); + return -EPERM; + } + + /* add kobject */ + ret = kobject_init_and_add(&huaqin_kobj, &huaqin_ktype, &(huaqin_hw_device->kobj), HUAQIN_HWID_NAME); + if (ret < 0) { + pr_err("%s fail to add kobject\n", __func__); + return ret; + } + + return 0; +} + +int hq_deregister_hw_info(enum hardware_id id, char *device_name){ + int ret = 0; + int find_hw_id = 0; + int iterator = 0; + + struct hw_info *hw = NULL; + struct attribute *attr = huaqin_attrs[iterator]; + + if (NULL == device_name){ + pr_err("[%s]: device_name does not allow empty\n", __func__); + ret = -2; + goto err; + } + + while(attr){ + hw = container_of(attr, struct hw_info , attr); + + iterator += 1; + attr = huaqin_attrs[iterator]; + + if (NULL == hw){ + continue; + } + + if (id == hw->hw_id){ + find_hw_id = 1; + + if (0 == hw->hw_exist){ + pr_err("[%s]: device has not registed hw->id:0x%x . Cant be deregistered\n" + , __func__ + , hw->hw_id); + + ret = -4; + goto err; + }else if (NULL == hw->hw_device_name){ + + pr_err("[%s]:hw_id is 0x%x Device name cant be NULL\n" + , __func__ + , hw->hw_id); + ret = -5; + goto err; + } + else{ + if (0 == strncmp(hw->hw_device_name, device_name, strlen(hw->hw_device_name))){ + hw->hw_device_name = NULL; + hw->hw_exist = 0; + }else{ + pr_err("[%s]: hw_id is 0x%x Registered device name %s , want to deregister: %s\n" + , __func__ + , hw->hw_id + , hw->hw_device_name + , device_name); + ret = -6; + goto err; + } + } + + goto err; + + }else + continue; + + } + + if (0 == find_hw_id){ + pr_err("[%s]: Cant find correct hardware_id: 0x%x\n", __func__, id); + ret = -3; + } + +err: + return ret; + +} + + +int hq_regiser_hw_info(enum hardware_id id, char *device_name){ + + int ret = 0; + int find_hw_id = 0; + int iterator = 0; + + struct hw_info *hw = NULL; + struct attribute *attr = huaqin_attrs[iterator]; + + if (NULL == device_name){ + pr_err("[%s]: device_name does not allow empty\n", __func__); + ret = -2; + goto err; + } + + while(attr){ + hw = container_of(attr, struct hw_info , attr); + + iterator += 1; + attr = huaqin_attrs[iterator]; + + if (NULL == hw){ + continue; + } + + if (id == hw->hw_id){ + find_hw_id = 1; + + if (hw->hw_exist){ + pr_err("[%s]: device has already registed hw->id:0x%x hw_device_name:%s\n" + , __func__ + , hw->hw_id + , hw->hw_device_name); + ret = -4; + goto err; + } + + switch(hw->hw_id){ + case HWID_MAIN_CAM: + case HWID_SUB_CAM: + case HWID_MAIN_CAM_2: + case HWID_SUB_CAM_2: + /* + if(map_cam_drv_to_vendor(device_name)) + hw->hw_device_name = map_cam_drv_to_vendor(device_name); + else + hw->hw_device_name = "Can't find Camera Vendor"; + break; + */ + default: + hw->hw_device_name = device_name; + break; + } + + + hw->hw_exist = 1; + goto err; + + }else + continue; + + } + + if (0 == find_hw_id){ + pr_err("[%s]: Cant find correct hardware_id: 0x%x\n", __func__, id); + ret = -3; + } + +err: + return ret; +} + +#include + +#define PROC_BOOT_REASON_FILE "boot_status" +static struct proc_dir_entry *boot_reason_proc; +static unsigned int boot_into_factory; +static int boot_reason_proc_show(struct seq_file *file, void *data) +{ + char temp[40] = {0}; + + sprintf(temp, "%d\n", boot_into_factory); + seq_printf(file, "%s\n", temp); + return 0; +} + +static int boot_reason_proc_open (struct inode *inode, struct file *file) +{ + return single_open(file, boot_reason_proc_show, inode->i_private); +} + +static const struct file_operations boot_reason_proc_fops = +{ + .open = boot_reason_proc_open, + .read = seq_read, +}; + +static int __init get_boot_rease(char *str) +{ + if (strcmp("boot_with_factory", str) == 0) { + boot_into_factory = 1; + } + + return 0; +} +__setup("androidboot.boot_reason=", get_boot_rease); + +static int __init hq_harware_init(void) +{ + /* create sysfs entry at /sys/class/huaqin/interface/hw_info */ + create_sysfs(); + + boot_reason_proc = proc_create(PROC_BOOT_REASON_FILE, 0644, NULL, &boot_reason_proc_fops); + if (boot_reason_proc == NULL) + { + pr_err("[%s]: create_proc_entry boot_reason_proc failed\n", __func__); + } + + return 0; +} + +core_initcall(hq_harware_init); +MODULE_AUTHOR("KaKa Ni "); +MODULE_DESCRIPTION("Huaqin Hardware Info Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/xiaomi_fs/Kconfig b/drivers/misc/xiaomi_fs/Kconfig new file mode 100644 index 0000000000000..6d1f8558dd922 --- /dev/null +++ b/drivers/misc/xiaomi_fs/Kconfig @@ -0,0 +1,5 @@ +config MI_FS + bool "Enable Mi fs Driver" + default n + help + MI fs information driver includes specific information about hardware info diff --git a/drivers/misc/xiaomi_fs/Makefile b/drivers/misc/xiaomi_fs/Makefile new file mode 100644 index 0000000000000..d40cb826c0a09 --- /dev/null +++ b/drivers/misc/xiaomi_fs/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_MI_FS)+=mi_fs.o diff --git a/drivers/misc/xiaomi_fs/mi_fs.c b/drivers/misc/xiaomi_fs/mi_fs.c new file mode 100644 index 0000000000000..4e6d70ca50ca6 --- /dev/null +++ b/drivers/misc/xiaomi_fs/mi_fs.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include +#define cpumaxfreq_proc_name "cpumaxfreq" +static struct proc_dir_entry *cpumaxfreq_proc; +#define CPU_PRESENT "/sys/devices/system/cpu/present" + +int find_symbol_form_string(char *string, char symbol) +{ + + int i = 0; + while(!(string[i] == symbol)) + { + ++i; + } + return i+1; +} + +int read_file(char *file_path, char *buf, int size) +{ + + struct file *file_p = NULL; + mm_segment_t old_fs; + loff_t pos; + int ret; + file_p = filp_open(file_path, 0444, 0); + if (IS_ERR(file_p)) + { + pr_err("%s fail to open file \n", __func__); + return -EPERM; + } + else{ + old_fs = get_fs(); + set_fs(KERNEL_DS); + pos = 0; + ret = vfs_read(file_p, buf, size, &pos); + filp_close(file_p, NULL); + set_fs(old_fs); + file_p = NULL; + } + + return ret; +} +int get_core_count(void) +{ + char buf[8] = {0}; + int symbol_position = 0; + int core_count = 0; + read_file(CPU_PRESENT, buf, sizeof(buf)); + symbol_position = find_symbol_form_string(buf, '-'); + + core_count = buf[symbol_position]-'0'+1; + + return core_count; + + + +} +void read_cpumaxfreq(char *cpumaxfreq_buf) +{ + uint16_t i = 0; + char buf[16] = {0}; + char path[128] = {0}; + long cpumaxfreq = 0; + int core_count = 0; + core_count = get_core_count(); + + while(i < core_count) + { + memset(buf, sizeof(buf), 0); + snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", i); + read_file(path, buf, sizeof(buf)); + if (simple_strtoul(buf, NULL, 0) > cpumaxfreq) + cpumaxfreq = simple_strtoul(buf, NULL, 0); + + ++i; + } + + sprintf(cpumaxfreq_buf, "%u.%u", (uint16_t)(cpumaxfreq/1000000), + (uint16_t)((cpumaxfreq/100000)%10)); +} + +static int cpumaxfreq_show(struct seq_file *file, void *data) +{ + char cpumaxfreq_buf[16]; +#if 0 + char *cpumaxfreq_buf = NULL; + cpumaxfreq_buf = kmalloc(sizeof(*cpumaxfreq_buf)*cpu_num*32, GFP_KERNEL); + if (IS_ERR(cpumaxfreq_buf)) + { + pr_err("%s cpumaxfreq_buf kmalloc fail.\n", __func__); + return PTR_ERR(cpumaxfreq_buf); + } + memset(cpumaxfreq_buf, 0, sizeof(*cpumaxfreq_buf)*cpu_num*32); +#endif + memset(cpumaxfreq_buf, 0, sizeof(cpumaxfreq_buf)); + read_cpumaxfreq(cpumaxfreq_buf); + seq_printf(file, "%s", cpumaxfreq_buf); +#if 0 + if (!cpumaxfreq_buf) + kfree(cpumaxfreq_buf); +#endif + return 0; + + +} +static int cpumaxfreq_open(struct inode *inode, struct file *file) +{ + return single_open(file, cpumaxfreq_show, inode->i_private); +} +static const struct file_operations cpumaxfreq_ops = { + .owner = THIS_MODULE, + .open = cpumaxfreq_open, + .read = seq_read, +}; +int create_fs(void) +{ + /*proc/cpumaxfreq*/ + long rc = 1; + cpumaxfreq_proc = proc_create(cpumaxfreq_proc_name, 0444, NULL, &cpumaxfreq_ops); + if (IS_ERR(cpumaxfreq_proc)) + { + pr_err("%s cpumaxfreq proc create fail.\n", __func__); + rc = PTR_ERR(cpumaxfreq_proc); + } + + return rc; + +} + +static int __init mi_fs_init(void) +{ + /* create fs*/ + create_fs(); + + return 0; +} + + +late_initcall(mi_fs_init); +MODULE_AUTHOR("ninjia "); +MODULE_DESCRIPTION("MI FS For Adaptation"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 49edfb620026f..96a57048aa95b 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1178,7 +1178,11 @@ static void mmc_sd_detect(struct mmc_host *host) err = mmc_send_status(host->card, NULL); if (err) { retries--; +#ifdef CONFIG_PROJECT_DAISY + mmc_delay(20); +#else udelay(5); +#endif continue; } break; diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index 674c2151fc3a7..c6a6eec1d9e94 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -2382,6 +2382,7 @@ static void wcnss_nvbin_dnld(void) const struct firmware *nv = NULL; struct device *dev = &penv->pdev->dev; + down_read(&wcnss_pm_sem); ret = request_firmware(&nv, NVBIN_FILE, dev); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index d34d227fc139a..e5ef32554e3a4 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -2,6 +2,7 @@ * Functions for working with the Flattened Device Tree data format * * Copyright 2009 Benjamin Herrenschmidt, IBM Corp + * Copyright (C) 2019 XiaoMi, Inc. * benh@kernel.crashing.org * * This program is free software; you can redistribute it and/or @@ -729,6 +730,23 @@ const void * __init of_flat_dt_match_machine(const void *default_match, return best_data; } +void __init early_init_dt_check_for_powerup_reason(unsigned long node) +{ + unsigned long pu_reason; + int len; + const __be32 *prop; + + pr_debug("Looking for powerup reason properties... \n"); + + prop = of_get_flat_dt_prop(node, "pureason", &len); + if (!prop) + return; + pu_reason = of_read_ulong(prop, len/4); + early_init_dt_setup_pureason_arch(pu_reason); + + pr_debug("Powerup reason %d\n", (int)pu_reason); +} + #ifdef CONFIG_BLK_DEV_INITRD /** * early_init_dt_check_for_initrd - Decode initrd location from flat tree @@ -968,6 +986,8 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, pr_debug("Command line is: %s\n", (char*)data); + early_init_dt_check_for_powerup_reason(node); + /* break now */ return 1; } diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c index 4fddbdefce5b5..5b1a984783b62 100644 --- a/drivers/of/of_batterydata.c +++ b/drivers/of/of_batterydata.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -310,19 +311,23 @@ static int64_t of_batterydata_convert_battery_id_kohm(int batt_id_uv, return resistor_value_kohm; } +#define Desay_24Kohm 24 +#define FMT_200_41Kohm 200 +#define GY_50Kohm 50 struct device_node *of_batterydata_get_best_profile( const struct device_node *batterydata_container_node, const char *psy_name, const char *batt_type) { struct batt_ids batt_ids; struct device_node *node, *best_node = NULL; + struct device_node *default_node = NULL; struct power_supply *psy; const char *battery_type = NULL; union power_supply_propval ret = {0, }; int delta = 0, best_delta = 0, best_id_kohm = 0, id_range_pct, batt_id_kohm = 0, i = 0, rc = 0, limit = 0; bool in_range = false; - + int checknum = 0, match = 0; psy = power_supply_get_by_name(psy_name); if (!psy) { pr_err("%s supply not found. defer\n", psy_name); @@ -371,12 +376,25 @@ struct device_node *of_batterydata_get_best_profile( for (i = 0; i < batt_ids.num; i++) { delta = abs(batt_ids.kohm[i] - batt_id_kohm); limit = (batt_ids.kohm[i] * id_range_pct) / 100; + if (batt_ids.kohm[i] == Desay_24Kohm) { + limit++; + pr_err("Desay_limit=%dKohm.\n", limit); + } in_range = (delta <= limit); + if (in_range != 0) + match = 1; /* * Check if the delta is the lowest one * and also if the limits are in range * before selecting the best node. */ + if (batt_ids.kohm[i] == FMT_200_41Kohm) { + pr_err("Default_node:FMT_41Kohm.\n"); + default_node = node; + } else if (batt_ids.kohm[i] == GY_50Kohm) { + pr_err("Default_node:GY_50Kohm.\n"); + default_node = node; + } if ((delta < best_delta || !best_node) && in_range) { best_node = node; @@ -386,14 +404,19 @@ struct device_node *of_batterydata_get_best_profile( } } } - + checknum = abs(best_id_kohm - batt_id_kohm); + if (match == 0) + { + best_node = default_node; + checknum = 0; + } if (best_node == NULL) { pr_err("No battery data found\n"); return best_node; } /* check that profile id is in range of the measured batt_id */ - if (abs(best_id_kohm - batt_id_kohm) > + if (checknum > ((best_id_kohm * id_range_pct) / 100)) { pr_err("out of range: profile id %d batt id %d pct %d", best_id_kohm, batt_id_kohm, id_range_pct); diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c index f7f0f739fbd7a..fdd3cf4d90b2b 100644 --- a/drivers/platform/msm/qpnp-power-on.c +++ b/drivers/platform/msm/qpnp-power-on.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +33,7 @@ #include #include +#include #define CREATE_MASK(NUM_BITS, POS) \ ((unsigned char) (((1 << (NUM_BITS)) - 1) << (POS))) #define PON_MASK(MSB_BIT, LSB_BIT) \ @@ -71,6 +73,7 @@ #define QPNP_POFF_REASON1(pon) \ ((pon)->base + PON_OFFSET((pon)->subtype, 0xC, 0xC5)) #define QPNP_PON_WARM_RESET_REASON2(pon) ((pon)->base + 0xB) +#define QPNP_POFF_REASON2(pon) ((pon)->base + 0xD) #define QPNP_PON_OFF_REASON(pon) ((pon)->base + 0xC7) #define QPNP_FAULT_REASON1(pon) ((pon)->base + 0xC8) #define QPNP_S3_RESET_REASON(pon) ((pon)->base + 0xCA) @@ -676,6 +679,77 @@ int qpnp_pon_is_warm_reset(void) } EXPORT_SYMBOL(qpnp_pon_is_warm_reset); +int qpnp_pon_is_ps_hold_reset(void) +{ + struct qpnp_pon *pon = sys_reset_dev; + int rc; + u8 reg = 0; + + if (!pon) + return 0; + + rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid, + QPNP_POFF_REASON1(pon), ®, 1); + if (rc) { + dev_err(&pon->spmi->dev, + "Unable to read addr=%x, rc(%d)\n", + QPNP_POFF_REASON1(pon), rc); + return 0; + } + + /* The bit 1 is 1, means by PS_HOLD/MSM controlled shutdown */ + if (reg & 0x2) + return 1; + dev_info(&pon->spmi->dev, + "hw_reset reason1 is 0x%x\n", + reg); + + rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid, + QPNP_POFF_REASON2(pon), ®, 1); + + dev_info(&pon->spmi->dev, + "hw_reset reason2 is 0x%x\n", + reg); + return 0; +} +EXPORT_SYMBOL(qpnp_pon_is_ps_hold_reset); + +int qpnp_pon_is_lpk(void) +{ + struct qpnp_pon *pon = sys_reset_dev; + int rc; + u8 reg = 0; + + if (!pon) + return 0; + + rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid, + QPNP_POFF_REASON1(pon), ®, 1); + if (rc) { + dev_err(&pon->spmi->dev, + "Unable to read addr=%x, rc(%d)\n", + QPNP_POFF_REASON1(pon), rc); + return 0; + } + + + if (reg & 0x80) + return 1; + + dev_info(&pon->spmi->dev, + "hw_reset reason1 is 0x%x\n", + reg); + + rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid, + QPNP_POFF_REASON2(pon), ®, 1); + + dev_info(&pon->spmi->dev, + "hw_reset reason2 is 0x%x\n", + reg); + return 0; +} +EXPORT_SYMBOL(qpnp_pon_is_lpk); + /** * qpnp_pon_wd_config - Disable the wd in a warm reset. * @enable: to enable or disable the PON watch dog @@ -2046,6 +2120,54 @@ static int pon_register_twm_notifier(struct qpnp_pon *pon) return rc; } + + + + +static ssize_t qpnp_kpdpwr_reset_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qpnp_pon *pon = dev_get_drvdata(dev); + u8 val; + spmi_ext_register_readl(pon->spmi->ctrl, + pon->spmi->sid, QPNP_PON_KPDPWR_S2_CNTL2(pon), + &val, 1); + + val &= QPNP_PON_S2_RESET_ENABLE; + val = val >> 7; + + return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d\n", val); +} + +static ssize_t qpnp_kpdpwr_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct qpnp_pon *pon = dev_get_drvdata(dev); + u8 value; + int rc; + + if (size > QPNP_PON_BUFFER_SIZE) + return -EINVAL; + + rc = kstrtou8(buf, 10, &value); + if (rc) + return rc; + + value = value << 7; + value &= QPNP_PON_S2_RESET_ENABLE; + + rc = qpnp_pon_masked_write(pon, + QPNP_PON_KPDPWR_S2_CNTL2(pon), + QPNP_PON_S2_CNTL_EN, value); + return size; +} + +static DEVICE_ATTR(kpdpwr_reset, 0664, qpnp_kpdpwr_reset_show, qpnp_kpdpwr_reset_store); + + + + static int qpnp_pon_probe(struct spmi_device *spmi) { struct qpnp_pon *pon; @@ -2213,6 +2335,7 @@ static int qpnp_pon_probe(struct spmi_device *spmi) "PMIC@SID%d: Power-off reason: %s\n", pon->spmi->sid, qpnp_poff_reason[index]); + set_poweroff_reason(index); } if (pon->pon_trigger_reason == PON_SMPL || @@ -2400,6 +2523,13 @@ static int qpnp_pon_probe(struct spmi_device *spmi) return rc; } + rc = device_create_file(&spmi->dev, &dev_attr_kpdpwr_reset); + if (rc) { + dev_err(&spmi->dev, "sys file creation failed rc: %d\n", rc); + return rc; + } + + if (of_property_read_bool(spmi->dev.of_node, "qcom,pon-reset-off")) { rc = qpnp_pon_trigger_config(PON_CBLPWR_N, false); @@ -2438,6 +2568,7 @@ static int qpnp_pon_remove(struct spmi_device *spmi) unsigned long flags; device_remove_file(&spmi->dev, &dev_attr_debounce_us); + device_remove_file(&spmi->dev, &dev_attr_kpdpwr_reset); cancel_delayed_work_sync(&pon->bark_work); diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 05fa08be8a255..f9233ad851677 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -506,6 +506,16 @@ config QPNP_SMBCHARGER The driver also offers relevant information to userspace via the power supply framework. +config QPNP_SMBCHARGER_E7 + tristate "QPNP SMB Charger driver" + depends on SPMI || MSM_SPMI + depends on OF_SPMI + help + Say Y here to enable the dual path switch mode battery charger which + supports USB detection and battery charging up to 3A. + The driver also offers relevant information to userspace via the + power supply framework. + config QPNP_SMB2 tristate "QPNP SMB Charger driver" depends on SPMI || MSM_SPMI @@ -536,6 +546,16 @@ config QPNP_FG fuel gauge. The state of charge is reported through a BMS power supply property and also sends uevents when the capacity is updated. +config QPNP_FG_E7 + tristate "QPNP fuel gauge driver" + depends on SPMI || MSM_SPMI + depends on OF_SPMI + help + Say Y here to enable the Fuel Gauge driver. This adds support for + battery fuel gauging and state of charge of battery connected to the + fuel gauge. The state of charge is reported through a BMS power + supply property and also sends uevents when the capacity is updated. + config QPNP_FG_GEN3 tristate "QPNP GEN3 fuel gauge driver" depends on SPMI || MSM_SPMI diff --git a/drivers/power/Makefile b/drivers/power/Makefile index d24e86368ec07..979ee751360e8 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -71,10 +71,12 @@ obj-$(CONFIG_BATTERY_BQ28400) += bq28400_battery.o obj-$(CONFIG_QPNP_BMS) += qpnp-bms.o batterydata-lib.o obj-$(CONFIG_QPNP_VM_BMS) += qpnp-vm-bms.o batterydata-lib.o batterydata-interface.o obj-$(CONFIG_QPNP_FG) += qpnp-fg.o +obj-$(CONFIG_QPNP_FG_E7) += qpnp-fg_e7.o obj-$(CONFIG_QPNP_FG_GEN3) += qpnp-fg-gen3.o fg-memif.o fg-util.o pmic-voter.o obj-$(CONFIG_QPNP_CHARGER) += qpnp-charger.o obj-$(CONFIG_QPNP_LINEAR_CHARGER) += qpnp-linear-charger.o obj-$(CONFIG_QPNP_SMBCHARGER) += qpnp-smbcharger.o pmic-voter.o +obj-$(CONFIG_QPNP_SMBCHARGER_E7) += qpnp-smbcharger_e7.o pmic-voter.o obj-$(CONFIG_QPNP_SMB2) += battery.o qpnp-smb2.o pmic-voter.o smb-lib.o storm-watch.o obj-$(CONFIG_QPNP_TYPEC) += qpnp-typec.o obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 0fd9357b0cea4..b8b063774851d 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -78,7 +78,10 @@ static ssize_t power_supply_show_property(struct device *dev, "Source attached (default current)", "Source attached (medium current)", "Source attached (high current)", - "Non compliant", + "Non compliant", "none", + "none", "none", "none", + "none", "none", "none", + "none", "sink", "source", }; static const char * const typec_pr_text[] = { "none", "dual power role", "sink", "source" diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c index 7b110598681d8..624374bad9fa4 100644 --- a/drivers/power/qpnp-fg.c +++ b/drivers/power/qpnp-fg.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -237,10 +238,10 @@ enum fg_mem_data_index { static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { /* ID Address, Offset, Value*/ - SETTING(SOFT_COLD, 0x454, 0, 100), - SETTING(SOFT_HOT, 0x454, 1, 400), - SETTING(HARD_COLD, 0x454, 2, 50), - SETTING(HARD_HOT, 0x454, 3, 450), + SETTING(SOFT_COLD, 0x454, 0, 150), + SETTING(SOFT_HOT, 0x454, 1, 450), + SETTING(HARD_COLD, 0x454, 2, 0), + SETTING(HARD_HOT, 0x454, 3, 600), SETTING(RESUME_SOC, 0x45C, 1, 0), SETTING(BCL_LM_THRESHOLD, 0x47C, 2, 50), SETTING(BCL_MH_THRESHOLD, 0x47C, 3, 752), @@ -248,7 +249,7 @@ static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { SETTING(CHG_TERM_CURRENT, 0x4F8, 2, 250), SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3100), SETTING(CUTOFF_VOLTAGE, 0x40C, 0, 3200), - SETTING(VBAT_EST_DIFF, 0x000, 0, 30), + SETTING(VBAT_EST_DIFF, 0x000, 0, 200), SETTING(DELTA_SOC, 0x450, 3, 1), SETTING(BATT_LOW, 0x458, 0, 4200), SETTING(THERM_DELAY, 0x4AC, 3, 0), @@ -330,7 +331,7 @@ module_param_named( battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR ); -static int fg_sram_update_period_ms = 30000; +static int fg_sram_update_period_ms = 3000; module_param_named( sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR ); @@ -2026,10 +2027,10 @@ static void fg_handle_battery_insertion(struct fg_chip *chip) } -static int soc_to_setpoint(int soc) +/*static int soc_to_setpoint(int soc) { return DIV_ROUND_CLOSEST(soc * 255, 100); -} +}*/ static void batt_to_setpoint_adc(int vbatt_mv, u8 *data) { @@ -2244,7 +2245,7 @@ static int get_monotonic_soc_raw(struct fg_chip *chip) #define FULL_SOC_RAW 0xFF static int get_prop_capacity(struct fg_chip *chip) { - int msoc, rc; + int msoc, rc, soc_tmp; bool vbatt_low_sts; if (chip->use_last_soc && chip->last_soc) { @@ -2294,8 +2295,15 @@ static int get_prop_capacity(struct fg_chip *chip) return FULL_CAPACITY; } - return DIV_ROUND_CLOSEST((msoc - 1) * (FULL_CAPACITY - 2), + soc_tmp = DIV_ROUND_CLOSEST((msoc - 1) * (FULL_CAPACITY - 2), FULL_SOC_RAW - 2) + 1; + + if (chip->status == POWER_SUPPLY_STATUS_FULL && soc_tmp == 99) { + soc_tmp = 100; + pr_err("Full, Update soc_tmp.\n"); + } + + return soc_tmp; } #define HIGH_BIAS 3 @@ -4035,7 +4043,7 @@ static void status_change_work(struct work_struct *work) if (chip->status == POWER_SUPPLY_STATUS_FULL) { if (capacity >= 99 && chip->hold_soc_while_full - && chip->health == POWER_SUPPLY_HEALTH_GOOD) { + && (chip->health == POWER_SUPPLY_HEALTH_GOOD || chip->health == POWER_SUPPLY_HEALTH_COOL)) { if (fg_debug_mask & FG_STATUS) pr_info("holding soc at 100\n"); chip->charge_full = true; @@ -4643,7 +4651,7 @@ static int fg_power_get_property(struct power_supply *psy, val->intval = 1; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - val->intval = chip->nom_cap_uah; + val->intval = 4000000; break; case POWER_SUPPLY_PROP_CHARGE_FULL: val->intval = chip->learning_data.learned_cc_uah; @@ -6306,21 +6314,105 @@ static int fg_do_restart(struct fg_chip *chip, bool write_profile) return -EINVAL; } +#ifdef FACTORY_VERSION_ENABLE +#define REDO_BATID_DURING_FIRST_EST BIT(4) +static void fg_hw_restart(struct fg_chip *chip) +{ + u8 reg = 0; + int rc = 0, batt_id; + u8 data[4]; + + reg = 0x80; + batt_id = get_sram_prop_now(chip, FG_DATA_BATT_ID); + printk("fg_hw_restart old battery id = %d\n", batt_id); + + fg_masked_write(chip, 0x4150, reg, reg, 1); + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, 0xFF, 0, 1); + mdelay(5); + + reg = REDO_BATID_DURING_FIRST_EST|REDO_FIRST_ESTIMATE; + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); + mdelay(5); + + reg = REDO_BATID_DURING_FIRST_EST |REDO_FIRST_ESTIMATE| RESTART_GO; + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); + mdelay(1000); + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, 0xFF, 0, 1); + fg_masked_write(chip, 0x4150, 0x80, 0, 1); + + mdelay(2000); + + rc = fg_mem_read(chip, data, fg_data[FG_DATA_BATT_ID].address, fg_data[FG_DATA_BATT_ID].len, fg_data[FG_DATA_BATT_ID].offset, 0); + + if (rc) { + printk("Failed to get sram battery id data\n"); + } + else { + fg_data[FG_DATA_BATT_ID].value = data[0] * LSB_8B; + } + + batt_id = get_sram_prop_now(chip, FG_DATA_BATT_ID); + printk("fg_hw_restart new batt_id=%d\n", batt_id); +} +#endif + #define FG_PROFILE_LEN 128 #define PROFILE_COMPARE_LEN 32 #define THERMAL_COEFF_ADDR 0x444 #define THERMAL_COEFF_OFFSET 0x2 #define BATTERY_PSY_WAIT_MS 2000 + +#ifdef FACTORY_VERSION_ENABLE +#define SCUD_ID_MAX 43600 +#define SCUD_ID_MIN 39000 +#define COSLIGHT_ID_MAX 53600 +#define COSLIGHT_ID_MIN 48000 +#define SUNWODA_ID_MAX 82000 +#define SUNWODA_ID_MIN 73000 +#endif static int fg_batt_profile_init(struct fg_chip *chip) { int rc = 0, ret; int len; + + #ifdef FACTORY_VERSION_ENABLE + int batt_id = 0, match = 0; + #endif + struct device_node *node = chip->spmi->dev.of_node; struct device_node *batt_node, *profile_node; const char *data, *batt_type_str; bool tried_again = false, vbat_in_range, profiles_same; u8 reg = 0; + #ifdef FACTORY_VERSION_ENABLE + batt_id = get_sram_prop_now(chip, FG_DATA_BATT_ID); + printk("batt_id_ohm=%d\n", batt_id); + + + + + if (batt_id >= SCUD_ID_MIN && batt_id <= SCUD_ID_MAX) { + match = 1; + printk("SCUD match succ.\n"); + } else if (batt_id >= COSLIGHT_ID_MIN && batt_id <= COSLIGHT_ID_MAX) { + match = 1; + printk("COSLIGHT match succ.\n"); + } else if (batt_id >= SUNWODA_ID_MIN && batt_id <= SUNWODA_ID_MAX) { + match = 1; + printk("SUNWODA match succ.\n"); + } + if (match == 0) { + fg_hw_restart(chip); + printk("re-read bat id\n"); + } + printk("batt_id=%d\n", get_sram_prop_now(chip, FG_DATA_BATT_ID)); + #endif + wait: fg_stay_awake(&chip->profile_wakeup_source); ret = wait_for_completion_interruptible_timeout(&chip->batt_id_avail, @@ -6702,6 +6794,7 @@ static void charge_full_work(struct work_struct *work) int resume_soc_raw = settings[FG_MEM_RESUME_SOC].value; bool disable = false; u8 reg; + int msoc, retry = 0; if (chip->status != POWER_SUPPLY_STATUS_FULL) { if (fg_debug_mask & FG_STATUS) @@ -6744,6 +6837,14 @@ static void charge_full_work(struct work_struct *work) pr_info("wrote %06x into soc full\n", bsoc); } fg_mem_release(chip); + + + while(msoc != 0xFF && retry != 8) { + msleep(200); + msoc = get_monotonic_soc_raw(chip); + retry++; + } + /* * wait one cycle to make sure the soc is updated before clearing * the soc mask bit @@ -7113,9 +7214,13 @@ static int fg_of_init(struct fg_chip *chip) chip->use_otp_profile = of_property_read_bool( chip->spmi->dev.of_node, "qcom,use-otp-profile"); +#ifdef FACTORY_VERSION_ENABLE + chip->hold_soc_while_full = false; +#else chip->hold_soc_while_full = of_property_read_bool( chip->spmi->dev.of_node, "qcom,hold-soc-while-full"); +#endif sense_type = of_property_read_bool(chip->spmi->dev.of_node, "qcom,ext-sense-type"); @@ -8044,7 +8149,7 @@ static int fg_common_hw_init(struct fg_chip *chip) } rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, - soc_to_setpoint(settings[FG_MEM_DELTA_SOC].value), + /*soc_to_setpoint(settings[FG_MEM_DELTA_SOC].value)*/1, settings[FG_MEM_DELTA_SOC].offset); if (rc) { pr_err("failed to write delta soc rc=%d\n", rc); @@ -8681,6 +8786,51 @@ static void delayed_init_work(struct work_struct *work) fg_cleanup(chip); } +#define SOC_LOW_PWR_CFG 0xF5 +#define LO_FRQ_CLKSWITCH_EN BIT(0) + +static void fg_adc_clk_change(struct fg_chip *chip, int val) +{ + u8 reg = 0; + int rc = 0; + + if (val > 1 || val < 0) { + pr_err(":%s Invalid Value %d, Return!\n", __func__, val); + return; + } + chip->fg_restarting = true; + + rc = fg_read(chip, ®, chip->soc_base + SOC_LOW_PWR_CFG, 1); + if (rc) { + pr_err(":%s failed to read SOC_LOW_PWR_CFG\n", __func__); + + } + pr_err(":%s SOC_LOW_PWR_CFG = 0x%02x\n", __func__, reg); + usleep_range(5000, 6000); + + rc = fg_sec_masked_write(chip, chip->soc_base + SOC_LOW_PWR_CFG, LO_FRQ_CLKSWITCH_EN, val, 1); + if (rc) { + pr_err(":%s failed to change FG ADC Clk\n", __func__); + goto adc_clk_change_fail; + } + usleep_range(5000, 6000); + + rc = fg_read(chip, ®, chip->soc_base + SOC_LOW_PWR_CFG, 1); + if (rc) { + pr_err(":%s failed to read SOC_LOW_PWR_CFG\n", __func__); + goto adc_clk_change_fail; + } + pr_err(":%s SOC_LOW_PWR_CFG = 0x%02x\n", __func__, reg); + + chip->fg_restarting = false; + pr_err(":%s Success change FG ADC Clk\n", __func__); + return; + +adc_clk_change_fail: + chip->fg_restarting = false; +} + + static int fg_probe(struct spmi_device *spmi) { struct device *dev = &(spmi->dev); @@ -8869,7 +9019,7 @@ static int fg_probe(struct spmi_device *spmi) pr_err("failed to clear interrupts %d\n", rc); goto of_init_fail; } - + fg_adc_clk_change(chip, 1); rc = fg_init_irqs(chip); if (rc) { pr_err("failed to request interrupts %d\n", rc); diff --git a/drivers/power/qpnp-fg_e7.c b/drivers/power/qpnp-fg_e7.c new file mode 100644 index 0000000000000..b5337aed62bd7 --- /dev/null +++ b/drivers/power/qpnp-fg_e7.c @@ -0,0 +1,9407 @@ +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "FG: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register offsets */ + +/* Interrupt offsets */ +#define INT_RT_STS(base) (base + 0x10) +#define INT_EN_CLR(base) (base + 0x16) + +/* SPMI Register offsets */ +#define SOC_MONOTONIC_SOC 0x09 +#define SOC_BOOT_MOD 0x50 +#define SOC_RESTART 0x51 + +#define REG_OFFSET_PERP_SUBTYPE 0x05 + +/* RAM register offsets */ +#define RAM_OFFSET 0x400 + +/* Bit/Mask definitions */ +#define FULL_PERCENT 0xFF +#define MAX_TRIES_SOC 5 +#define MA_MV_BIT_RES 39 +#define MSB_SIGN BIT(7) +#define IBAT_VBAT_MASK 0x7F +#define NO_OTP_PROF_RELOAD BIT(6) +#define REDO_FIRST_ESTIMATE BIT(3) +#define RESTART_GO BIT(0) +#define THERM_DELAY_MASK 0xE0 + +/* SUBTYPE definitions */ +#define FG_SOC 0x9 +#define FG_BATT 0xA +#define FG_ADC 0xB +#define FG_MEMIF 0xC + +#define QPNP_FG_DEV_NAME "qcom,qpnp-fg" +#define MEM_IF_TIMEOUT_MS 5000 +#define FG_CYCLE_MS 1500 +#define BUCKET_COUNT 8 +#define BUCKET_SOC_PCT (256 / BUCKET_COUNT) + +#define BCL_MA_TO_ADC(_current, _adc_val) { \ + _adc_val = (u8)((_current) * 100 / 976); \ +} + +/* Debug Flag Definitions */ +enum { + FG_SPMI_DEBUG_WRITES = BIT(0), /* Show SPMI writes */ + FG_SPMI_DEBUG_READS = BIT(1), /* Show SPMI reads */ + FG_IRQS = BIT(2), /* Show interrupts */ + FG_MEM_DEBUG_WRITES = BIT(3), /* Show SRAM writes */ + FG_MEM_DEBUG_READS = BIT(4), /* Show SRAM reads */ + FG_POWER_SUPPLY = BIT(5), /* Show POWER_SUPPLY */ + FG_STATUS = BIT(6), /* Show FG status changes */ + FG_AGING = BIT(7), /* Show FG aging algorithm */ +}; + +/* PMIC REVISIONS */ +#define REVID_RESERVED 0 +#define REVID_VARIANT 1 +#define REVID_ANA_MAJOR 2 +#define REVID_DIG_MAJOR 3 + +enum dig_major { + DIG_REV_1 = 0x1, + DIG_REV_2 = 0x2, + DIG_REV_3 = 0x3, +}; + +enum pmic_subtype { + PMI8994 = 10, + PMI8950 = 17, + PMI8996 = 19, + PMI8937 = 55, + PMI8940 = 64, +}; + +enum wa_flags { + IADC_GAIN_COMP_WA = BIT(0), + USE_CC_SOC_REG = BIT(1), + PULSE_REQUEST_WA = BIT(2), + BCL_HI_POWER_FOR_CHGLED_WA = BIT(3) +}; + +enum current_sense_type { + INTERNAL_CURRENT_SENSE, + EXTERNAL_CURRENT_SENSE, +}; + +struct fg_mem_setting { + u16 address; + u8 offset; + int value; +}; + +struct fg_mem_data { + u16 address; + u8 offset; + unsigned int len; + int value; +}; + +struct fg_learning_data { + int64_t cc_uah; + int64_t learned_cc_uah; + int init_cc_pc_val; + bool active; + bool feedback_on; + struct mutex learning_lock; + ktime_t time_stamp; + /* configuration properties */ + int max_start_soc; + int max_increment; + int max_decrement; + int min_temp; + int max_temp; + int vbat_est_thr_uv; + int max_cap_limit; + int min_cap_limit; +}; + +struct fg_rslow_data { + u8 rslow_cfg; + u8 rslow_thr; + u8 rs_to_rslow[2]; + u8 rslow_comp[4]; + uint32_t chg_rs_to_rslow; + uint32_t chg_rslow_comp_c1; + uint32_t chg_rslow_comp_c2; + uint32_t chg_rslow_comp_thr; + bool active; + struct mutex lock; +}; + +struct fg_cyc_ctr_data { + bool en; + bool started[BUCKET_COUNT]; + u16 count[BUCKET_COUNT]; + u8 last_soc[BUCKET_COUNT]; + int id; + struct mutex lock; +}; + +struct fg_iadc_comp_data { + u8 dfl_gain_reg[2]; + bool gain_active; + int64_t dfl_gain; +}; + +struct fg_cc_soc_data { + int init_sys_soc; + int init_cc_soc; + int full_capacity; + int delta_soc; +}; + +/* FG_MEMIF setting index */ +enum fg_mem_setting_index { + FG_MEM_SOFT_COLD = 0, + FG_MEM_SOFT_HOT, + FG_MEM_HARD_COLD, + FG_MEM_HARD_HOT, + FG_MEM_RESUME_SOC, + FG_MEM_BCL_LM_THRESHOLD, + FG_MEM_BCL_MH_THRESHOLD, + FG_MEM_TERM_CURRENT, + FG_MEM_CHG_TERM_CURRENT, + FG_MEM_IRQ_VOLT_EMPTY, + FG_MEM_CUTOFF_VOLTAGE, + FG_MEM_VBAT_EST_DIFF, + FG_MEM_DELTA_SOC, + FG_MEM_BATT_LOW, + FG_MEM_THERM_DELAY, + FG_MEM_SETTING_MAX, +}; + +/* FG_MEMIF data index */ +enum fg_mem_data_index { + FG_DATA_BATT_TEMP = 0, + FG_DATA_OCV, + FG_DATA_VOLTAGE, + FG_DATA_CURRENT, + FG_DATA_BATT_ESR, + FG_DATA_BATT_ESR_COUNT, + FG_DATA_BATT_SOC, + FG_DATA_CC_CHARGE, + FG_DATA_VINT_ERR, + FG_DATA_CPRED_VOLTAGE, + /* values below this only gets read once per profile reload */ + FG_DATA_BATT_ID, + FG_DATA_BATT_ID_INFO, + FG_DATA_MAX, +}; + +#define SETTING(_idx, _address, _offset, _value) \ + [FG_MEM_##_idx] = { \ + .address = _address, \ + .offset = _offset, \ + .value = _value, \ + } \ + +static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { + /* ID Address, Offset, Value*/ + SETTING(SOFT_COLD, 0x454, 0, 150), + SETTING(SOFT_HOT, 0x454, 1, 450), + SETTING(HARD_COLD, 0x454, 2, 0), + SETTING(HARD_HOT, 0x454, 3, 550), + SETTING(RESUME_SOC, 0x45C, 1, 0), + SETTING(BCL_LM_THRESHOLD, 0x47C, 2, 50), + SETTING(BCL_MH_THRESHOLD, 0x47C, 3, 752), + SETTING(TERM_CURRENT, 0x40C, 2, 250), + SETTING(CHG_TERM_CURRENT, 0x4F8, 2, 250), + SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3100), + SETTING(CUTOFF_VOLTAGE, 0x40C, 0, 3200), + SETTING(VBAT_EST_DIFF, 0x000, 0, 200), + SETTING(DELTA_SOC, 0x450, 3, 1), + SETTING(BATT_LOW, 0x458, 0, 4200), + SETTING(THERM_DELAY, 0x4AC, 3, 0), +}; + +#define DATA(_idx, _address, _offset, _length, _value) \ + [FG_DATA_##_idx] = { \ + .address = _address, \ + .offset = _offset, \ + .len = _length, \ + .value = _value, \ + } \ + +static struct fg_mem_data fg_data[FG_DATA_MAX] = { + /* ID Address, Offset, Length, Value*/ + DATA(BATT_TEMP, 0x550, 2, 2, -EINVAL), + DATA(OCV, 0x588, 3, 2, -EINVAL), + DATA(VOLTAGE, 0x5CC, 1, 2, -EINVAL), + DATA(CURRENT, 0x5CC, 3, 2, -EINVAL), + DATA(BATT_ESR, 0x554, 2, 2, -EINVAL), + DATA(BATT_ESR_COUNT, 0x558, 2, 2, -EINVAL), + DATA(BATT_SOC, 0x56C, 1, 3, -EINVAL), + DATA(CC_CHARGE, 0x570, 0, 4, -EINVAL), + DATA(VINT_ERR, 0x560, 0, 4, -EINVAL), + DATA(CPRED_VOLTAGE, 0x540, 0, 2, -EINVAL), + DATA(BATT_ID, 0x594, 1, 1, -EINVAL), + DATA(BATT_ID_INFO, 0x594, 3, 1, -EINVAL), +}; + +enum fg_mem_backup_index { + FG_BACKUP_SOC = 0, + FG_BACKUP_CYCLE_COUNT, + FG_BACKUP_CC_SOC_COEFF, + FG_BACKUP_IGAIN, + FG_BACKUP_VCOR, + FG_BACKUP_TEMP_COUNTER, + FG_BACKUP_AGING_STORAGE, + FG_BACKUP_MAH_TO_SOC, + FG_BACKUP_MAX, +}; + +#define BACKUP(_idx, _address, _offset, _length, _value) \ + [FG_BACKUP_##_idx] = { \ + .address = _address, \ + .offset = _offset, \ + .len = _length, \ + .value = _value, \ + } \ + +static struct fg_mem_data fg_backup_regs[FG_BACKUP_MAX] = { + /* ID Address, Offset, Length, Value*/ + BACKUP(SOC, 0x564, 0, 24, -EINVAL), + BACKUP(CYCLE_COUNT, 0x5E8, 0, 16, -EINVAL), + BACKUP(CC_SOC_COEFF, 0x5BC, 0, 8, -EINVAL), + BACKUP(IGAIN, 0x424, 0, 4, -EINVAL), + BACKUP(VCOR, 0x484, 0, 4, -EINVAL), + BACKUP(TEMP_COUNTER, 0x580, 0, 4, -EINVAL), + BACKUP(AGING_STORAGE, 0x5E4, 0, 4, -EINVAL), + BACKUP(MAH_TO_SOC, 0x4A0, 0, 4, -EINVAL), +}; + +static int fg_debug_mask; +module_param_named( + debug_mask, fg_debug_mask, int, S_IRUSR | S_IWUSR +); + +static int fg_reset_on_lockup; + +static int fg_sense_type = -EINVAL; +static int fg_restart; + +static int fg_est_dump; +module_param_named( + first_est_dump, fg_est_dump, int, S_IRUSR | S_IWUSR +); + +static char *fg_batt_type; +module_param_named( + battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR +); + +static int fg_sram_update_period_ms = 3000; +module_param_named( + sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR +); + +static bool fg_batt_valid_ocv; +module_param_named(batt_valid_ocv, fg_batt_valid_ocv, bool, S_IRUSR | S_IWUSR); + +static int fg_batt_range_pct; +module_param_named(batt_range_pct, fg_batt_range_pct, int, S_IRUSR | S_IWUSR); + +struct fg_irq { + int irq; + bool disabled; + bool wakeup; +}; + +enum fg_soc_irq { + HIGH_SOC, + LOW_SOC, + FULL_SOC, + EMPTY_SOC, + DELTA_SOC, + FIRST_EST_DONE, + SW_FALLBK_OCV, + SW_FALLBK_NEW_BATT, + FG_SOC_IRQ_COUNT, +}; + +enum fg_batt_irq { + JEITA_SOFT_COLD, + JEITA_SOFT_HOT, + VBATT_LOW, + BATT_IDENTIFIED, + BATT_ID_REQ, + BATTERY_UNKNOWN, + BATT_MISSING, + BATT_MATCH, + FG_BATT_IRQ_COUNT, +}; + +enum fg_mem_if_irq { + FG_MEM_AVAIL, + TA_RCVRY_SUG, + FG_MEM_IF_IRQ_COUNT, +}; + +enum fg_batt_aging_mode { + FG_AGING_NONE, + FG_AGING_ESR, + FG_AGING_CC, +}; + +enum register_type { + MEM_INTF_CFG, + MEM_INTF_CTL, + MEM_INTF_ADDR_LSB, + MEM_INTF_RD_DATA0, + MEM_INTF_WR_DATA0, + MAX_ADDRESS, +}; + +enum batt_info_params { + BATT_INFO_NOTIFY = 0, + BATT_INFO_SOC, + BATT_INFO_RES_ID, + BATT_INFO_VOLTAGE, + BATT_INFO_TEMP, + BATT_INFO_FCC, + BATT_INFO_MAX, +}; + +struct register_offset { + u16 address[MAX_ADDRESS]; +}; + +static struct register_offset offset[] = { + [0] = { + /* CFG CTL LSB RD0 WD0 */ + .address = {0x40, 0x41, 0x42, 0x4C, 0x48}, + }, + [1] = { + /* CFG CTL LSB RD0 WD0 */ + .address = {0x50, 0x51, 0x61, 0x67, 0x63}, + }, +}; + +#define MEM_INTF_CFG(chip) \ + ((chip)->mem_base + (chip)->offset[MEM_INTF_CFG]) +#define MEM_INTF_CTL(chip) \ + ((chip)->mem_base + (chip)->offset[MEM_INTF_CTL]) +#define MEM_INTF_ADDR_LSB(chip) \ + ((chip)->mem_base + (chip)->offset[MEM_INTF_ADDR_LSB]) +#define MEM_INTF_RD_DATA0(chip) \ + ((chip)->mem_base + (chip)->offset[MEM_INTF_RD_DATA0]) +#define MEM_INTF_WR_DATA0(chip) \ + ((chip)->mem_base + (chip)->offset[MEM_INTF_WR_DATA0]) + +struct fg_wakeup_source { + struct wakeup_source source; + unsigned long enabled; +}; + +static void fg_stay_awake(struct fg_wakeup_source *source) +{ + if (!__test_and_set_bit(0, &source->enabled)) { + __pm_stay_awake(&source->source); + pr_debug("enabled source %s\n", source->source.name); + } +} + +static void fg_relax(struct fg_wakeup_source *source) +{ + if (__test_and_clear_bit(0, &source->enabled)) { + __pm_relax(&source->source); + pr_debug("disabled source %s\n", source->source.name); + } +} + +enum slope_limit_status { + LOW_TEMP_CHARGE, + HIGH_TEMP_CHARGE, + LOW_TEMP_DISCHARGE, + HIGH_TEMP_DISCHARGE, + SLOPE_LIMIT_MAX, +}; + +#define VOLT_GAIN_MAX 3 +struct dischg_gain_soc { + bool enable; + u32 soc[VOLT_GAIN_MAX]; + u32 medc_gain[VOLT_GAIN_MAX]; + u32 highc_gain[VOLT_GAIN_MAX]; +}; + +#define THERMAL_COEFF_N_BYTES 6 +struct fg_chip { + struct device *dev; + struct spmi_device *spmi; + u8 pmic_subtype; + u8 pmic_revision[4]; + u8 revision[4]; + u16 soc_base; + u16 batt_base; + u16 mem_base; + u16 vbat_adc_addr; + u16 ibat_adc_addr; + u16 tp_rev_addr; + u32 wa_flag; + atomic_t memif_user_cnt; + struct fg_irq soc_irq[FG_SOC_IRQ_COUNT]; + struct fg_irq batt_irq[FG_BATT_IRQ_COUNT]; + struct fg_irq mem_irq[FG_MEM_IF_IRQ_COUNT]; + struct completion sram_access_granted; + struct completion sram_access_revoked; + struct completion batt_id_avail; + struct completion first_soc_done; + struct power_supply bms_psy; + spinlock_t sec_access_lock; + struct mutex rw_lock; + struct mutex sysfs_restart_lock; + struct delayed_work batt_profile_init; + struct work_struct dump_sram; + struct work_struct status_change_work; + struct work_struct cycle_count_work; + struct work_struct battery_age_work; + struct work_struct update_esr_work; + struct work_struct set_resume_soc_work; + struct work_struct rslow_comp_work; + struct work_struct sysfs_restart_work; + struct work_struct init_work; + struct work_struct charge_full_work; + struct work_struct gain_comp_work; + struct work_struct bcl_hi_power_work; + struct power_supply *batt_psy; + struct power_supply *usb_psy; + struct power_supply *dc_psy; + struct fg_wakeup_source memif_wakeup_source; + struct fg_wakeup_source profile_wakeup_source; + struct fg_wakeup_source empty_check_wakeup_source; + struct fg_wakeup_source resume_soc_wakeup_source; + struct fg_wakeup_source gain_comp_wakeup_source; + struct fg_wakeup_source capacity_learning_wakeup_source; + bool first_profile_loaded; + struct fg_wakeup_source update_temp_wakeup_source; + struct fg_wakeup_source update_sram_wakeup_source; + bool fg_restarting; + bool profile_loaded; + bool soc_reporting_ready; + bool use_otp_profile; + bool battery_missing; + bool power_supply_registered; + bool sw_rbias_ctrl; + bool use_thermal_coefficients; + bool esr_strict_filter; + bool soc_empty; + bool charge_done; + bool resume_soc_lowered; + bool vbat_low_irq_enabled; + bool full_soc_irq_enabled; + bool charge_full; + bool hold_soc_while_full; + bool input_present; + bool otg_present; + bool safety_timer_expired; + bool bad_batt_detection_en; + bool bcl_lpm_disabled; + bool charging_disabled; + bool use_vbat_low_empty_soc; + bool fg_shutdown; + bool use_soft_jeita_irq; + bool allow_false_negative_isense; + struct delayed_work update_jeita_setting; + struct delayed_work update_sram_data; + struct delayed_work update_temp_work; + struct delayed_work check_empty_work; + char *batt_profile; + u8 thermal_coefficients[THERMAL_COEFF_N_BYTES]; + u32 cc_cv_threshold_mv; + unsigned int batt_profile_len; + unsigned int batt_max_voltage_uv; + const char *batt_type; + const char *batt_psy_name; + unsigned long last_sram_update_time; + unsigned long last_temp_update_time; + int64_t ocv_coeffs[12]; + int64_t cutoff_voltage; + int evaluation_current; + int ocv_junction_p1p2; + int ocv_junction_p2p3; + int nom_cap_uah; + int actual_cap_uah; + int status; + int prev_status; + int health; + enum fg_batt_aging_mode batt_aging_mode; + struct alarm hard_jeita_alarm; + /* capacity learning */ + struct fg_learning_data learning_data; + struct alarm fg_cap_learning_alarm; + struct work_struct fg_cap_learning_work; + struct fg_cc_soc_data sw_cc_soc_data; + /* rslow compensation */ + struct fg_rslow_data rslow_comp; + int rconn_mohm; + /* cycle counter */ + struct fg_cyc_ctr_data cyc_ctr; + /* iadc compensation */ + struct fg_iadc_comp_data iadc_comp_data; + /* interleaved memory access */ + u16 *offset; + bool ima_supported; + bool init_done; + /* jeita hysteresis */ + bool jeita_hysteresis_support; + bool batt_hot; + bool batt_cold; + bool batt_warm; + bool batt_cool; + int cold_hysteresis; + int hot_hysteresis; + /* ESR pulse tuning */ + struct fg_wakeup_source esr_extract_wakeup_source; + struct work_struct esr_extract_config_work; + bool esr_extract_disabled; + bool imptr_pulse_slow_en; + bool esr_pulse_tune_en; + /* Slope limiter */ + struct work_struct slope_limiter_work; + struct fg_wakeup_source slope_limit_wakeup_source; + bool soc_slope_limiter_en; + enum slope_limit_status slope_limit_sts; + u32 slope_limit_temp; + u32 slope_limit_coeffs[SLOPE_LIMIT_MAX]; + /* Discharge soc gain */ + struct work_struct dischg_gain_work; + struct fg_wakeup_source dischg_gain_wakeup_source; + struct dischg_gain_soc dischg_gain; + /* IMA error recovery */ + struct completion fg_reset_done; + struct work_struct ima_error_recovery_work; + struct fg_wakeup_source fg_reset_wakeup_source; + struct mutex ima_recovery_lock; + bool ima_error_handling; + bool block_sram_access; + bool irqs_enabled; + bool use_last_soc; + int last_soc; + /* Validating temperature */ + int last_good_temp; + int batt_temp_low_limit; + int batt_temp_high_limit; + /* Validating CC_SOC */ + struct work_struct cc_soc_store_work; + struct fg_wakeup_source cc_soc_wakeup_source; + int cc_soc_limit_pct; + bool use_last_cc_soc; + int64_t last_cc_soc; + /* Sanity check */ + struct delayed_work check_sanity_work; + struct fg_wakeup_source sanity_wakeup_source; + u8 last_beat_count; + /* Batt_info restore */ + int batt_info[BATT_INFO_MAX]; + int batt_info_id; + bool batt_info_restore; + bool *batt_range_ocv; + int *batt_range_pct; + char *debug_dump; +}; + +/* FG_MEMIF DEBUGFS structures */ +#define ADDR_LEN 4 /* 3 byte address + 1 space character */ +#define CHARS_PER_ITEM 3 /* Format is 'XX ' */ +#define ITEMS_PER_LINE 4 /* 4 data items per line */ +#define MAX_LINE_LENGTH (ADDR_LEN + (ITEMS_PER_LINE * CHARS_PER_ITEM) + 1) +#define MAX_REG_PER_TRANSACTION (8) + +static const char *DFS_ROOT_NAME = "fg_memif"; +static const mode_t DFS_MODE = S_IRUSR | S_IWUSR; +static const char *default_batt_type = "Unknown Battery"; +static const char *loading_batt_type = "Loading Battery Data"; +static const char *missing_batt_type = "Disconnected Battery"; + +/* Log buffer */ +struct fg_log_buffer { + size_t rpos; /* Current 'read' position in buffer */ + size_t wpos; /* Current 'write' position in buffer */ + size_t len; /* Length of the buffer */ + char data[0]; /* Log buffer */ +}; + +/* transaction parameters */ +struct fg_trans { + u32 cnt; /* Number of bytes to read */ + u16 addr; /* 12-bit address in SRAM */ + u32 offset; /* Offset of last read data + byte offset */ + struct fg_chip *chip; + struct fg_log_buffer *log; /* log buffer */ + u8 *data; /* fg data that is read */ + struct mutex memif_dfs_lock; /* Prevent thread concurrency */ +}; + +struct fg_dbgfs { + u32 cnt; + u32 addr; + struct fg_chip *chip; + struct dentry *root; + struct mutex lock; + struct debugfs_blob_wrapper help_msg; +}; + +static struct fg_dbgfs dbgfs_data = { + .lock = __MUTEX_INITIALIZER(dbgfs_data.lock), + .help_msg = { + .data = +"FG Debug-FS support\n" +"\n" +"Hierarchy schema:\n" +"/sys/kernel/debug/fg_memif\n" +" /help -- Static help text\n" +" /address -- Starting register address for reads or writes\n" +" /count -- Number of registers to read (only used for reads)\n" +" /data -- Initiates the SRAM read (formatted output)\n" +"\n", + }, +}; + +static const struct of_device_id fg_match_table[] = { + { .compatible = QPNP_FG_DEV_NAME, }, + {} +}; + +static char *fg_supplicants[] = { + "battery", + "bcl", + "fg_adc" +}; + +static void dump_debug(struct work_struct *work); +#define DEBUG_PRINT_BUFFER_SIZE 64 +static void fill_string(char *str, size_t str_len, u8 *buf, int buf_len) +{ + int pos = 0; + int i; + + for (i = 0; i < buf_len; i++) { + pos += scnprintf(str + pos, str_len - pos, "%02X", buf[i]); + if (i < buf_len - 1) + pos += scnprintf(str + pos, str_len - pos, " "); + } +} + +static int fg_write(struct fg_chip *chip, u8 *val, u16 addr, int len) +{ + int rc = 0; + struct spmi_device *spmi = chip->spmi; + char str[DEBUG_PRINT_BUFFER_SIZE]; + + if ((addr & 0xff00) == 0) { + pr_err("addr cannot be zero base=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return -EINVAL; + } + + rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, len); + if (rc) { + pr_err("write failed addr=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return rc; + } + + if (!rc && (fg_debug_mask & FG_SPMI_DEBUG_WRITES)) { + str[0] = '\0'; + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, len); + pr_info("write(0x%04X), sid=%d, len=%d; %s\n", + addr, spmi->sid, len, str); + } + + return rc; +} + +static int fg_read(struct fg_chip *chip, u8 *val, u16 addr, int len) +{ + int rc = 0; + struct spmi_device *spmi = chip->spmi; + char str[DEBUG_PRINT_BUFFER_SIZE]; + + if ((addr & 0xff00) == 0) { + pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return -EINVAL; + } + + rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, len); + if (rc) { + pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", addr, + spmi->sid, rc); + return rc; + } + + if (!rc && (fg_debug_mask & FG_SPMI_DEBUG_READS)) { + str[0] = '\0'; + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, len); + pr_info("read(0x%04x), sid=%d, len=%d; %s\n", + addr, spmi->sid, len, str); + } + + return rc; +} + +static int fg_masked_write_raw(struct fg_chip *chip, u16 addr, + u8 mask, u8 val, int len) +{ + int rc; + u8 reg; + + rc = fg_read(chip, ®, addr, len); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", addr, rc); + return rc; + } + pr_debug("addr = 0x%x read 0x%x\n", addr, reg); + + reg &= ~mask; + reg |= val & mask; + + pr_debug("Writing 0x%x\n", reg); + + rc = fg_write(chip, ®, addr, len); + if (rc) + pr_err("spmi write failed: addr=%03X, rc=%d\n", addr, rc); + + return rc; +} + +static int fg_masked_write(struct fg_chip *chip, u16 addr, + u8 mask, u8 val, int len) +{ + int rc; + unsigned long flags; + + spin_lock_irqsave(&chip->sec_access_lock, flags); + rc = fg_masked_write_raw(chip, addr, mask, val, len); + spin_unlock_irqrestore(&chip->sec_access_lock, flags); + + return rc; +} + +#define SEC_ACCESS_OFFSET 0xD0 +#define SEC_ACCESS_VALUE 0xA5 +#define PERIPHERAL_MASK 0xFF +static int fg_sec_masked_write(struct fg_chip *chip, u16 addr, u8 mask, u8 val, + int len) +{ + int rc; + unsigned long flags; + u8 temp; + u16 base = addr & (~PERIPHERAL_MASK); + + spin_lock_irqsave(&chip->sec_access_lock, flags); + temp = SEC_ACCESS_VALUE; + rc = fg_write(chip, &temp, base + SEC_ACCESS_OFFSET, 1); + if (rc) { + pr_err("Unable to unlock sec_access: %d\n", rc); + goto out; + } + + rc = fg_masked_write_raw(chip, addr, mask, val, len); + if (rc) + pr_err("Unable to write securely to address 0x%x: %d", addr, + rc); +out: + spin_unlock_irqrestore(&chip->sec_access_lock, flags); + return rc; +} + +#define RIF_MEM_ACCESS_REQ BIT(7) +static int fg_check_rif_mem_access(struct fg_chip *chip, bool *status) +{ + int rc; + u8 mem_if_sts; + + rc = fg_read(chip, &mem_if_sts, MEM_INTF_CFG(chip), 1); + if (rc) { + pr_err("failed to read rif_mem status rc=%d\n", rc); + return rc; + } + + *status = mem_if_sts & RIF_MEM_ACCESS_REQ; + return 0; +} + +static bool fg_check_sram_access(struct fg_chip *chip) +{ + int rc; + u8 mem_if_sts; + bool rif_mem_sts = false; + + rc = fg_read(chip, &mem_if_sts, INT_RT_STS(chip->mem_base), 1); + if (rc) { + pr_err("failed to read mem status rc=%d\n", rc); + return false; + } + + if ((mem_if_sts & BIT(FG_MEM_AVAIL)) == 0) + return false; + + rc = fg_check_rif_mem_access(chip, &rif_mem_sts); + if (rc) + return false; + + return rif_mem_sts; +} + +static inline int fg_assert_sram_access(struct fg_chip *chip) +{ + int rc; + u8 mem_if_sts; + + rc = fg_read(chip, &mem_if_sts, INT_RT_STS(chip->mem_base), 1); + if (rc) { + pr_err("failed to read mem status rc=%d\n", rc); + return rc; + } + + if ((mem_if_sts & BIT(FG_MEM_AVAIL)) == 0) { + pr_err("mem_avail not high: %02x\n", mem_if_sts); + return -EINVAL; + } + + rc = fg_read(chip, &mem_if_sts, MEM_INTF_CFG(chip), 1); + if (rc) { + pr_err("failed to read mem status rc=%d\n", rc); + return rc; + } + + if ((mem_if_sts & RIF_MEM_ACCESS_REQ) == 0) { + pr_err("mem_avail not high: %02x\n", mem_if_sts); + return -EINVAL; + } + + return 0; +} + +#define INTF_CTL_BURST BIT(7) +#define INTF_CTL_WR_EN BIT(6) +static int fg_config_access(struct fg_chip *chip, bool write, + bool burst) +{ + int rc; + u8 intf_ctl = 0; + + intf_ctl = (write ? INTF_CTL_WR_EN : 0) | (burst ? INTF_CTL_BURST : 0); + + rc = fg_write(chip, &intf_ctl, MEM_INTF_CTL(chip), 1); + if (rc) { + pr_err("failed to set mem access bit\n"); + return -EIO; + } + + return rc; +} + +static int fg_req_and_wait_access(struct fg_chip *chip, int timeout) +{ + int rc = 0, ret = 0; + bool tried_again = false; + + if (!fg_check_sram_access(chip)) { + rc = fg_masked_write(chip, MEM_INTF_CFG(chip), + RIF_MEM_ACCESS_REQ, RIF_MEM_ACCESS_REQ, 1); + if (rc) { + pr_err("failed to set mem access bit\n"); + return -EIO; + } + fg_stay_awake(&chip->memif_wakeup_source); + } + +wait: + /* Wait for MEM_AVAIL IRQ. */ + ret = wait_for_completion_interruptible_timeout( + &chip->sram_access_granted, + msecs_to_jiffies(timeout)); + /* If we were interrupted wait again one more time. */ + if (ret == -ERESTARTSYS && !tried_again) { + tried_again = true; + goto wait; + } else if (ret <= 0) { + rc = -ETIMEDOUT; + pr_err("transaction timed out rc=%d\n", rc); + return rc; + } + + return rc; +} + +static int fg_release_access(struct fg_chip *chip) +{ + int rc; + + rc = fg_masked_write(chip, MEM_INTF_CFG(chip), + RIF_MEM_ACCESS_REQ, 0, 1); + fg_relax(&chip->memif_wakeup_source); + reinit_completion(&chip->sram_access_granted); + + return rc; +} + +static void fg_release_access_if_necessary(struct fg_chip *chip) +{ + mutex_lock(&chip->rw_lock); + if (atomic_sub_return(1, &chip->memif_user_cnt) <= 0) { + fg_release_access(chip); + } + mutex_unlock(&chip->rw_lock); +} + +/* + * fg_mem_lock disallows the fuel gauge to release access until it has been + * released. + * + * an equal number of calls must be made to fg_mem_release for the fuel gauge + * driver to release the sram access. + */ +static void fg_mem_lock(struct fg_chip *chip) +{ + mutex_lock(&chip->rw_lock); + atomic_add_return(1, &chip->memif_user_cnt); + mutex_unlock(&chip->rw_lock); +} + +static void fg_mem_release(struct fg_chip *chip) +{ + fg_release_access_if_necessary(chip); +} + +static int fg_set_ram_addr(struct fg_chip *chip, u16 *address) +{ + int rc; + + rc = fg_write(chip, (u8 *) address, + chip->mem_base + chip->offset[MEM_INTF_ADDR_LSB], 2); + if (rc) { + pr_err("spmi write failed: addr=%03X, rc=%d\n", + chip->mem_base + chip->offset[MEM_INTF_ADDR_LSB], rc); + return rc; + } + + return rc; +} + +#define BUF_LEN 4 +static int fg_sub_mem_read(struct fg_chip *chip, u8 *val, u16 address, int len, + int offset) +{ + int rc, total_len; + u8 *rd_data = val; + char str[DEBUG_PRINT_BUFFER_SIZE]; + + rc = fg_config_access(chip, 0, (len > 4)); + if (rc) + return rc; + + rc = fg_set_ram_addr(chip, &address); + if (rc) + return rc; + + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("length %d addr=%02X\n", len, address); + + total_len = len; + while (len > 0) { + if (!offset) { + rc = fg_read(chip, rd_data, MEM_INTF_RD_DATA0(chip), + min(len, BUF_LEN)); + } else { + rc = fg_read(chip, rd_data, + MEM_INTF_RD_DATA0(chip) + offset, + min(len, BUF_LEN - offset)); + + /* manually set address to allow continous reads */ + address += BUF_LEN; + + rc = fg_set_ram_addr(chip, &address); + if (rc) + return rc; + } + if (rc) { + pr_err("spmi read failed: addr=%03x, rc=%d\n", + MEM_INTF_RD_DATA0(chip) + offset, rc); + return rc; + } + rd_data += (BUF_LEN - offset); + len -= (BUF_LEN - offset); + offset = 0; + } + + if (fg_debug_mask & FG_MEM_DEBUG_READS) { + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, total_len); + pr_info("data: %s\n", str); + } + return rc; +} + +static int fg_conventional_mem_read(struct fg_chip *chip, u8 *val, u16 address, + int len, int offset, bool keep_access) +{ + int rc = 0, user_cnt = 0, orig_address = address; + + if (offset > 3) { + pr_err("offset too large %d\n", offset); + return -EINVAL; + } + + address = ((orig_address + offset) / 4) * 4; + offset = (orig_address + offset) % 4; + + user_cnt = atomic_add_return(1, &chip->memif_user_cnt); + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("user_cnt %d\n", user_cnt); + mutex_lock(&chip->rw_lock); + if (!fg_check_sram_access(chip)) { + rc = fg_req_and_wait_access(chip, MEM_IF_TIMEOUT_MS); + if (rc) + goto out; + } + + rc = fg_sub_mem_read(chip, val, address, len, offset); + +out: + user_cnt = atomic_sub_return(1, &chip->memif_user_cnt); + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("user_cnt %d\n", user_cnt); + + fg_assert_sram_access(chip); + + if (!keep_access && (user_cnt == 0) && !rc) { + rc = fg_release_access(chip); + if (rc) { + pr_err("failed to set mem access bit\n"); + rc = -EIO; + } + } + + mutex_unlock(&chip->rw_lock); + return rc; +} + +static int fg_conventional_mem_write(struct fg_chip *chip, u8 *val, u16 address, + int len, int offset, bool keep_access) +{ + int rc = 0, user_cnt = 0, sublen; + bool access_configured = false; + u8 *wr_data = val, word[4]; + u16 orig_address = address; + char str[DEBUG_PRINT_BUFFER_SIZE]; + + if (address < RAM_OFFSET) + return -EINVAL; + + if (offset > 3) + return -EINVAL; + + address = ((orig_address + offset) / 4) * 4; + offset = (orig_address + offset) % 4; + + user_cnt = atomic_add_return(1, &chip->memif_user_cnt); + if (fg_debug_mask & FG_MEM_DEBUG_WRITES) + pr_info("user_cnt %d\n", user_cnt); + mutex_lock(&chip->rw_lock); + if (!fg_check_sram_access(chip)) { + rc = fg_req_and_wait_access(chip, MEM_IF_TIMEOUT_MS); + if (rc) + goto out; + } + + if (fg_debug_mask & FG_MEM_DEBUG_WRITES) { + pr_info("length %d addr=%02X offset=%d\n", + len, address, offset); + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, wr_data, len); + pr_info("writing: %s\n", str); + } + + while (len > 0) { + if (offset != 0) { + sublen = min(4 - offset, len); + rc = fg_sub_mem_read(chip, word, address, 4, 0); + if (rc) + goto out; + memcpy(word + offset, wr_data, sublen); + /* configure access as burst if more to write */ + rc = fg_config_access(chip, 1, (len - sublen) > 0); + if (rc) + goto out; + rc = fg_set_ram_addr(chip, &address); + if (rc) + goto out; + offset = 0; + access_configured = true; + } else if (len >= 4) { + if (!access_configured) { + rc = fg_config_access(chip, 1, len > 4); + if (rc) + goto out; + rc = fg_set_ram_addr(chip, &address); + if (rc) + goto out; + access_configured = true; + } + sublen = 4; + memcpy(word, wr_data, 4); + } else if (len > 0 && len < 4) { + sublen = len; + rc = fg_sub_mem_read(chip, word, address, 4, 0); + if (rc) + goto out; + memcpy(word, wr_data, sublen); + rc = fg_config_access(chip, 1, 0); + if (rc) + goto out; + rc = fg_set_ram_addr(chip, &address); + if (rc) + goto out; + access_configured = true; + } else { + pr_err("Invalid length: %d\n", len); + break; + } + rc = fg_write(chip, word, MEM_INTF_WR_DATA0(chip), 4); + if (rc) { + pr_err("spmi write failed: addr=%03x, rc=%d\n", + MEM_INTF_WR_DATA0(chip), rc); + goto out; + } + len -= sublen; + wr_data += sublen; + address += 4; + } + +out: + user_cnt = atomic_sub_return(1, &chip->memif_user_cnt); + if (fg_debug_mask & FG_MEM_DEBUG_WRITES) + pr_info("user_cnt %d\n", user_cnt); + + fg_assert_sram_access(chip); + + if (!keep_access && (user_cnt == 0) && !rc) { + rc = fg_release_access(chip); + if (rc) { + pr_err("failed to set mem access bit\n"); + rc = -EIO; + } + } + + mutex_unlock(&chip->rw_lock); + return rc; +} + +#define MEM_INTF_IMA_CFG 0x52 +#define MEM_INTF_IMA_OPR_STS 0x54 +#define MEM_INTF_IMA_ERR_STS 0x5F +#define MEM_INTF_IMA_EXP_STS 0x55 +#define MEM_INTF_IMA_HW_STS 0x56 +#define MEM_INTF_IMA_BYTE_EN 0x60 +#define IMA_IACS_CLR BIT(2) +#define IMA_IACS_RDY BIT(1) +static int fg_run_iacs_clear_sequence(struct fg_chip *chip) +{ + int rc = 0; + u8 temp; + + if (fg_debug_mask & FG_STATUS) + pr_info("Running IACS clear sequence\n"); + + /* clear the error */ + rc = fg_masked_write(chip, chip->mem_base + MEM_INTF_IMA_CFG, + IMA_IACS_CLR, IMA_IACS_CLR, 1); + if (rc) { + pr_err("Error writing to IMA_CFG, rc=%d\n", rc); + return rc; + } + + temp = 0x4; + rc = fg_write(chip, &temp, MEM_INTF_ADDR_LSB(chip) + 1, 1); + if (rc) { + pr_err("Error writing to MEM_INTF_ADDR_MSB, rc=%d\n", rc); + return rc; + } + + temp = 0x0; + rc = fg_write(chip, &temp, MEM_INTF_WR_DATA0(chip) + 3, 1); + if (rc) { + pr_err("Error writing to WR_DATA3, rc=%d\n", rc); + return rc; + } + + rc = fg_read(chip, &temp, MEM_INTF_RD_DATA0(chip) + 3, 1); + if (rc) { + pr_err("Error writing to RD_DATA3, rc=%d\n", rc); + return rc; + } + + rc = fg_masked_write(chip, chip->mem_base + MEM_INTF_IMA_CFG, + IMA_IACS_CLR, 0, 1); + if (rc) { + pr_err("Error writing to IMA_CFG, rc=%d\n", rc); + return rc; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("IACS clear sequence complete!\n"); + return rc; +} + +#define IACS_ERR_BIT BIT(0) +#define XCT_ERR_BIT BIT(1) +#define DATA_RD_ERR_BIT BIT(3) +#define DATA_WR_ERR_BIT BIT(4) +#define ADDR_BURST_WRAP_BIT BIT(5) +#define ADDR_RNG_ERR_BIT BIT(6) +#define ADDR_SRC_ERR_BIT BIT(7) +static int fg_check_ima_exception(struct fg_chip *chip, bool check_hw_sts) +{ + int rc = 0, ret = 0; + u8 err_sts = 0, exp_sts = 0, hw_sts = 0; + bool run_err_clr_seq = false; + + rc = fg_read(chip, &err_sts, + chip->mem_base + MEM_INTF_IMA_ERR_STS, 1); + if (rc) { + pr_err("failed to read IMA_ERR_STS, rc=%d\n", rc); + return rc; + } + + rc = fg_read(chip, &exp_sts, + chip->mem_base + MEM_INTF_IMA_EXP_STS, 1); + if (rc) { + pr_err("Error in reading IMA_EXP_STS, rc=%d\n", rc); + return rc; + } + + rc = fg_read(chip, &hw_sts, + chip->mem_base + MEM_INTF_IMA_HW_STS, 1); + if (rc) { + pr_err("Error in reading IMA_HW_STS, rc=%d\n", rc); + return rc; + } + + pr_info_once("Initial ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n", + err_sts, exp_sts, hw_sts); + + if (fg_debug_mask & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) + pr_info("ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n", + err_sts, exp_sts, hw_sts); + + if (check_hw_sts) { + /* + * Lower nibble should be equal to upper nibble before SRAM + * transactions begins from SW side. If they are unequal, then + * the error clear sequence should be run irrespective of IMA + * exception errors. + */ + if ((hw_sts & 0x0F) != hw_sts >> 4) { + pr_err("IMA HW not in correct state, hw_sts=%x\n", + hw_sts); + run_err_clr_seq = true; + } + } + + if (exp_sts & (IACS_ERR_BIT | XCT_ERR_BIT | DATA_RD_ERR_BIT | + DATA_WR_ERR_BIT | ADDR_BURST_WRAP_BIT | ADDR_RNG_ERR_BIT | + ADDR_SRC_ERR_BIT)) { + pr_err("IMA exception bit set, exp_sts=%x\n", exp_sts); + run_err_clr_seq = true; + } + + if (run_err_clr_seq) { + ret = fg_run_iacs_clear_sequence(chip); + if (!ret) + return -EAGAIN; + else + pr_err("Error clearing IMA exception ret=%d\n", ret); + } + + return rc; +} + +static void fg_enable_irqs(struct fg_chip *chip, bool enable) +{ + if (!(enable ^ chip->irqs_enabled)) + return; + + if (enable) { + enable_irq(chip->soc_irq[DELTA_SOC].irq); + enable_irq_wake(chip->soc_irq[DELTA_SOC].irq); + if (!chip->full_soc_irq_enabled) { + enable_irq(chip->soc_irq[FULL_SOC].irq); + enable_irq_wake(chip->soc_irq[FULL_SOC].irq); + chip->full_soc_irq_enabled = true; + } + enable_irq(chip->batt_irq[BATT_MISSING].irq); + if (!chip->vbat_low_irq_enabled) { + enable_irq(chip->batt_irq[VBATT_LOW].irq); + enable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = true; + } + if (!chip->use_vbat_low_empty_soc) { + enable_irq(chip->soc_irq[EMPTY_SOC].irq); + enable_irq_wake(chip->soc_irq[EMPTY_SOC].irq); + } + chip->irqs_enabled = true; + } else { + disable_irq_wake(chip->soc_irq[DELTA_SOC].irq); + disable_irq_nosync(chip->soc_irq[DELTA_SOC].irq); + if (chip->full_soc_irq_enabled) { + disable_irq_wake(chip->soc_irq[FULL_SOC].irq); + disable_irq_nosync(chip->soc_irq[FULL_SOC].irq); + chip->full_soc_irq_enabled = false; + } + disable_irq(chip->batt_irq[BATT_MISSING].irq); + if (chip->vbat_low_irq_enabled) { + disable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + disable_irq_nosync(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = false; + } + if (!chip->use_vbat_low_empty_soc) { + disable_irq_wake(chip->soc_irq[EMPTY_SOC].irq); + disable_irq_nosync(chip->soc_irq[EMPTY_SOC].irq); + } + chip->irqs_enabled = false; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("FG interrupts are %sabled\n", enable ? "en" : "dis"); +} + +static void fg_check_ima_error_handling(struct fg_chip *chip) +{ + if (chip->ima_error_handling) { + if (fg_debug_mask & FG_STATUS) + pr_info("IMA error is handled already!\n"); + return; + } + mutex_lock(&chip->ima_recovery_lock); + fg_enable_irqs(chip, false); + chip->use_last_cc_soc = true; + chip->ima_error_handling = true; + if (!work_pending(&chip->ima_error_recovery_work)) + schedule_work(&chip->ima_error_recovery_work); + mutex_unlock(&chip->ima_recovery_lock); +} + +#define SOC_ALG_ST 0xCF +#define FGXCT_PRD BIT(7) +#define ALG_ST_CHECK_COUNT 20 +static int fg_check_alg_status(struct fg_chip *chip) +{ + int rc = 0, timeout = ALG_ST_CHECK_COUNT, count = 0; + u8 ima_opr_sts, alg_sts = 0, temp = 0; + + if (!fg_reset_on_lockup) { + pr_info("FG lockup detection cannot be run\n"); + return 0; + } + + rc = fg_read(chip, &alg_sts, chip->soc_base + SOC_ALG_ST, 1); + if (rc) { + pr_err("Error in reading SOC_ALG_ST, rc=%d\n", rc); + return rc; + } + + while (1) { + rc = fg_read(chip, &ima_opr_sts, + chip->mem_base + MEM_INTF_IMA_OPR_STS, 1); + if (!rc && !(ima_opr_sts & FGXCT_PRD)) + break; + + if (rc) { + pr_err("Error in reading IMA_OPR_STS, rc=%d\n", + rc); + break; + } + + rc = fg_read(chip, &temp, chip->soc_base + SOC_ALG_ST, + 1); + if (rc) { + pr_err("Error in reading SOC_ALG_ST, rc=%d\n", + rc); + break; + } + + if ((ima_opr_sts & FGXCT_PRD) && (temp == alg_sts)) + count++; + + /* Wait for ~10ms while polling ALG_ST & IMA_OPR_STS */ + usleep_range(9000, 11000); + + if (!(--timeout)) + break; + } + + if (fg_debug_mask & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) + pr_info("ima_opr_sts: %x alg_sts: %x count=%d\n", ima_opr_sts, + alg_sts, count); + + if (count == ALG_ST_CHECK_COUNT) { + /* If we are here, that means FG ALG is stuck */ + pr_err("ALG is stuck\n"); + fg_check_ima_error_handling(chip); + rc = -EBUSY; + } + return rc; +} + +static int fg_check_iacs_ready(struct fg_chip *chip) +{ + int rc = 0, timeout = 250; + u8 ima_opr_sts = 0; + + /* + * Additional delay to make sure IACS ready bit is set after + * Read/Write operation. + */ + + usleep_range(30, 35); + while (1) { + rc = fg_read(chip, &ima_opr_sts, + chip->mem_base + MEM_INTF_IMA_OPR_STS, 1); + if (!rc && (ima_opr_sts & IMA_IACS_RDY)) { + break; + } else { + if (!(--timeout) || rc) + break; + + /* delay for iacs_ready to be asserted */ + usleep_range(5000, 7000); + } + } + + if (!timeout || rc) { + pr_err("IACS_RDY not set, ima_opr_sts: %x\n", ima_opr_sts); + rc = fg_check_alg_status(chip); + if (rc && rc != -EBUSY) + pr_err("Couldn't check FG ALG status, rc=%d\n", + rc); + /* perform IACS_CLR sequence */ + fg_check_ima_exception(chip, false); + return -EBUSY; + } + + return 0; +} + +#define IACS_SLCT BIT(5) +static int __fg_interleaved_mem_write(struct fg_chip *chip, u8 *val, + u16 address, int offset, int len) +{ + int rc = 0, i; + u8 *word = val, byte_enable = 0, num_bytes = 0; + + if (fg_debug_mask & FG_MEM_DEBUG_WRITES) + pr_info("length %d addr=%02X offset=%d\n", + len, address, offset); + + while (len > 0) { + num_bytes = (offset + len) > BUF_LEN ? + (BUF_LEN - offset) : len; + /* write to byte_enable */ + for (i = offset; i < (offset + num_bytes); i++) + byte_enable |= BIT(i); + + rc = fg_write(chip, &byte_enable, + chip->mem_base + MEM_INTF_IMA_BYTE_EN, 1); + if (rc) { + pr_err("Unable to write to byte_en_reg rc=%d\n", + rc); + return rc; + } + /* write data */ + rc = fg_write(chip, word, MEM_INTF_WR_DATA0(chip) + offset, + num_bytes); + if (rc) { + pr_err("spmi write failed: addr=%03x, rc=%d\n", + MEM_INTF_WR_DATA0(chip) + offset, rc); + return rc; + } + /* + * The last-byte WR_DATA3 starts the write transaction. + * Write a dummy value to WR_DATA3 if it does not have + * valid data. This dummy data is not written to the + * SRAM as byte_en for WR_DATA3 is not set. + */ + if (!(byte_enable & BIT(3))) { + u8 dummy_byte = 0x0; + rc = fg_write(chip, &dummy_byte, + MEM_INTF_WR_DATA0(chip) + 3, 1); + if (rc) { + pr_err("Unable to write dummy-data to WR_DATA3 rc=%d\n", + rc); + return rc; + } + } + + rc = fg_check_iacs_ready(chip); + if (rc) { + pr_err("IACS_RDY failed post write to address %x offset %d rc=%d\n", + address, offset, rc); + return rc; + } + + /* check for error condition */ + rc = fg_check_ima_exception(chip, false); + if (rc) { + pr_err("IMA transaction failed rc=%d", rc); + return rc; + } + + word += num_bytes; + len -= num_bytes; + offset = byte_enable = 0; + } + + return rc; +} + +static int __fg_interleaved_mem_read(struct fg_chip *chip, u8 *val, u16 address, + int offset, int len) +{ + int rc = 0, total_len; + u8 *rd_data = val, num_bytes; + char str[DEBUG_PRINT_BUFFER_SIZE]; + + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("length %d addr=%02X\n", len, address); + + total_len = len; + while (len > 0) { + num_bytes = (offset + len) > BUF_LEN ? (BUF_LEN - offset) : len; + rc = fg_read(chip, rd_data, MEM_INTF_RD_DATA0(chip) + offset, + num_bytes); + if (rc) { + pr_err("spmi read failed: addr=%03x, rc=%d\n", + MEM_INTF_RD_DATA0(chip) + offset, rc); + return rc; + } + + rd_data += num_bytes; + len -= num_bytes; + offset = 0; + + rc = fg_check_iacs_ready(chip); + if (rc) { + pr_err("IACS_RDY failed post read for address %x offset %d rc=%d\n", + address, offset, rc); + return rc; + } + + /* check for error condition */ + rc = fg_check_ima_exception(chip, false); + if (rc) { + pr_err("IMA transaction failed rc=%d", rc); + return rc; + } + + if (len && (len + offset) < BUF_LEN) { + /* move to single mode */ + u8 intr_ctl = 0; + + rc = fg_write(chip, &intr_ctl, MEM_INTF_CTL(chip), 1); + if (rc) { + pr_err("failed to move to single mode rc=%d\n", + rc); + return -EIO; + } + } + } + + if (fg_debug_mask & FG_MEM_DEBUG_READS) { + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, val, total_len); + pr_info("data: %s\n", str); + } + + return rc; +} + +#define IMA_REQ_ACCESS (IACS_SLCT | RIF_MEM_ACCESS_REQ) +static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val, + u16 address, int len, int offset, int op) +{ + int rc = 0; + bool rif_mem_sts = true; + int time_count = 0; + + while (1) { + rc = fg_check_rif_mem_access(chip, &rif_mem_sts); + if (rc) + return rc; + + if (!rif_mem_sts) + break; + + if (fg_debug_mask & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) + pr_info("RIF_MEM_ACCESS_REQ is not clear yet for IMA_%s\n", + op ? "write" : "read"); + + /* + * Try this no more than 4 times. If RIF_MEM_ACCESS_REQ is not + * clear, then return an error instead of waiting for it again. + */ + if (time_count > 4) { + pr_err("Waited for ~16ms polling RIF_MEM_ACCESS_REQ\n"); + return -ETIMEDOUT; + } + + /* Wait for 4ms before reading RIF_MEM_ACCESS_REQ again */ + usleep_range(4000, 4100); + time_count++; + } + + /* configure for IMA access */ + rc = fg_masked_write(chip, MEM_INTF_CFG(chip), + IMA_REQ_ACCESS, IMA_REQ_ACCESS, 1); + if (rc) { + pr_err("failed to set mem access bit rc = %d\n", rc); + return rc; + } + + /* configure for the read/write single/burst mode */ + rc = fg_config_access(chip, op, (offset + len) > 4); + if (rc) { + pr_err("failed to set configure memory access rc = %d\n", rc); + return rc; + } + + rc = fg_check_iacs_ready(chip); + if (rc) { + pr_err("IACS_RDY failed before setting address: %x offset: %d rc=%d\n", + address, offset, rc); + return rc; + } + + /* write addresses to the register */ + rc = fg_set_ram_addr(chip, &address); + if (rc) { + pr_err("failed to set SRAM address rc = %d\n", rc); + return rc; + } + + rc = fg_check_iacs_ready(chip); + if (rc) + pr_err("IACS_RDY failed after setting address: %x offset: %d rc=%d\n", + address, offset, rc); + + return rc; +} + +#define MEM_INTF_FG_BEAT_COUNT 0x57 +#define BEAT_COUNT_MASK 0x0F +#define RETRY_COUNT 3 +static int fg_interleaved_mem_read(struct fg_chip *chip, u8 *val, u16 address, + int len, int offset) +{ + int rc = 0, ret, orig_address = address; + u8 start_beat_count, end_beat_count, count = 0; + bool retry = false; + + if (chip->fg_shutdown) + return -EINVAL; + + if (offset > 3) { + pr_err("offset too large %d\n", offset); + return -EINVAL; + } + + fg_stay_awake(&chip->memif_wakeup_source); + address = ((orig_address + offset) / 4) * 4; + offset = (orig_address + offset) % 4; + + if (address < RAM_OFFSET) { + /* + * OTP memory reads need a conventional memory access, do a + * conventional read when SRAM offset < RAM_OFFSET. + */ + rc = fg_conventional_mem_read(chip, val, address, len, offset, + 0); + if (rc) + pr_err("Failed to read OTP memory %d\n", rc); + goto exit; + } + + mutex_lock(&chip->rw_lock); + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("Read for %d bytes is attempted @ 0x%x[%d]\n", + len, address, offset); + +retry: + if (count >= RETRY_COUNT) { + pr_err("Retried reading 3 times\n"); + retry = false; + goto out; + } + + rc = fg_interleaved_mem_config(chip, val, address, offset, len, 0); + if (rc) { + pr_err("failed to configure SRAM for IMA rc = %d\n", rc); + retry = true; + count++; + goto out; + } + + /* read the start beat count */ + rc = fg_read(chip, &start_beat_count, + chip->mem_base + MEM_INTF_FG_BEAT_COUNT, 1); + if (rc) { + pr_err("failed to read beat count rc=%d\n", rc); + retry = true; + count++; + goto out; + } + + /* read data */ + rc = __fg_interleaved_mem_read(chip, val, address, offset, len); + if (rc) { + count++; + if ((rc == -EAGAIN) && (count < RETRY_COUNT)) { + pr_err("IMA access failed retry_count = %d\n", count); + goto retry; + } else { + pr_err("failed to read SRAM address rc = %d\n", rc); + retry = true; + goto out; + } + } + + /* read the end beat count */ + rc = fg_read(chip, &end_beat_count, + chip->mem_base + MEM_INTF_FG_BEAT_COUNT, 1); + if (rc) { + pr_err("failed to read beat count rc=%d\n", rc); + retry = true; + count++; + goto out; + } + + start_beat_count &= BEAT_COUNT_MASK; + end_beat_count &= BEAT_COUNT_MASK; + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("Start beat_count = %x End beat_count = %x\n", + start_beat_count, end_beat_count); + if (start_beat_count != end_beat_count) { + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("Beat count do not match - retry transaction\n"); + retry = true; + count++; + } +out: + /* Release IMA access */ + ret = fg_masked_write(chip, MEM_INTF_CFG(chip), IMA_REQ_ACCESS, 0, 1); + if (ret) + pr_err("failed to reset IMA access bit ret = %d\n", ret); + + if (retry) { + retry = false; + goto retry; + } + + mutex_unlock(&chip->rw_lock); +exit: + fg_relax(&chip->memif_wakeup_source); + return rc; +} + +static int fg_interleaved_mem_write(struct fg_chip *chip, u8 *val, u16 address, + int len, int offset) +{ + int rc = 0, ret, orig_address = address; + u8 count = 0; + bool retry = false; + + if (chip->fg_shutdown) + return -EINVAL; + + if (address < RAM_OFFSET) + return -EINVAL; + + if (offset > 3) { + pr_err("offset too large %d\n", offset); + return -EINVAL; + } + + fg_stay_awake(&chip->memif_wakeup_source); + address = ((orig_address + offset) / 4) * 4; + offset = (orig_address + offset) % 4; + + mutex_lock(&chip->rw_lock); + if (fg_debug_mask & FG_MEM_DEBUG_WRITES) + pr_info("Write for %d bytes is attempted @ 0x%x[%d]\n", + len, address, offset); + +retry: + if (count >= RETRY_COUNT) { + pr_err("Retried writing 3 times\n"); + retry = false; + goto out; + } + + rc = fg_interleaved_mem_config(chip, val, address, offset, len, 1); + if (rc) { + pr_err("failed to configure SRAM for IMA rc = %d\n", rc); + retry = true; + count++; + goto out; + } + + /* write data */ + rc = __fg_interleaved_mem_write(chip, val, address, offset, len); + if (rc) { + count++; + if ((rc == -EAGAIN) && (count < RETRY_COUNT)) { + pr_err("IMA access failed retry_count = %d\n", count); + goto retry; + } else { + pr_err("failed to write SRAM address rc = %d\n", rc); + retry = true; + goto out; + } + } + +out: + /* Release IMA access */ + ret = fg_masked_write(chip, MEM_INTF_CFG(chip), IMA_REQ_ACCESS, 0, 1); + if (ret) + pr_err("failed to reset IMA access bit ret = %d\n", ret); + + if (retry) { + retry = false; + goto retry; + } + + mutex_unlock(&chip->rw_lock); + fg_relax(&chip->memif_wakeup_source); + return rc; +} + +static int fg_mem_read(struct fg_chip *chip, u8 *val, u16 address, + int len, int offset, bool keep_access) +{ + if (chip->block_sram_access) + return -EBUSY; + + if (chip->ima_supported) + return fg_interleaved_mem_read(chip, val, address, + len, offset); + else + return fg_conventional_mem_read(chip, val, address, + len, offset, keep_access); +} + +static int fg_mem_write(struct fg_chip *chip, u8 *val, u16 address, + int len, int offset, bool keep_access) +{ + if (chip->block_sram_access) + return -EBUSY; + + if (chip->ima_supported) + return fg_interleaved_mem_write(chip, val, address, + len, offset); + else + return fg_conventional_mem_write(chip, val, address, + len, offset, keep_access); +} + +static int fg_mem_masked_write(struct fg_chip *chip, u16 addr, + u8 mask, u8 val, u8 offset) +{ + int rc = 0; + u8 reg[4]; + char str[DEBUG_PRINT_BUFFER_SIZE]; + + rc = fg_mem_read(chip, reg, addr, 4, 0, 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", addr, rc); + return rc; + } + + reg[offset] &= ~mask; + reg[offset] |= val & mask; + + str[0] = '\0'; + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, reg, 4); + pr_debug("Writing %s address %03x, offset %d\n", str, addr, offset); + + rc = fg_mem_write(chip, reg, addr, 4, 0, 0); + if (rc) { + pr_err("spmi write failed: addr=%03X, rc=%d\n", addr, rc); + return rc; + } + + return rc; +} + +static u8 sram_backup_buffer[100]; +static int fg_backup_sram_registers(struct fg_chip *chip, bool save) +{ + int rc, i, len, offset; + u16 address; + u8 *ptr; + + if (fg_debug_mask & FG_STATUS) + pr_info("%sing SRAM registers\n", save ? "Back" : "Restor"); + + ptr = sram_backup_buffer; + for (i = 0; i < FG_BACKUP_MAX; i++) { + address = fg_backup_regs[i].address; + offset = fg_backup_regs[i].offset; + len = fg_backup_regs[i].len; + if (save) + rc = fg_interleaved_mem_read(chip, ptr, address, + len, offset); + else + rc = fg_interleaved_mem_write(chip, ptr, address, + len, offset); + if (rc) { + pr_err("Error in reading %d bytes from %x[%d], rc=%d\n", + len, address, offset, rc); + break; + } + ptr += len; + } + + return rc; +} + +#define SOC_FG_RESET 0xF3 +#define RESET_MASK (BIT(7) | BIT(5)) +static int fg_reset(struct fg_chip *chip, bool reset) +{ + int rc; + + rc = fg_sec_masked_write(chip, chip->soc_base + SOC_FG_RESET, + 0xFF, reset ? RESET_MASK : 0, 1); + if (rc) + pr_err("Error in writing to 0x%x, rc=%d\n", SOC_FG_RESET, rc); + + return rc; +} + +static void fg_handle_battery_insertion(struct fg_chip *chip) +{ + reinit_completion(&chip->batt_id_avail); + reinit_completion(&chip->fg_reset_done); + schedule_delayed_work(&chip->batt_profile_init, 0); + cancel_delayed_work(&chip->update_sram_data); + schedule_delayed_work(&chip->update_sram_data, msecs_to_jiffies(0)); +} + + +/*static int soc_to_setpoint(int soc) +{ + return DIV_ROUND_CLOSEST(soc * 255, 100); +}*/ + +static void batt_to_setpoint_adc(int vbatt_mv, u8 *data) +{ + int val; + /* Battery voltage is an offset from 0 V and LSB is 1/2^15. */ + val = DIV_ROUND_CLOSEST(vbatt_mv * 32768, 5000); + data[0] = val & 0xFF; + data[1] = val >> 8; + return; +} + +static u8 batt_to_setpoint_8b(int vbatt_mv) +{ + int val; + /* Battery voltage is an offset from 2.5 V and LSB is 5/2^9. */ + val = (vbatt_mv - 2500) * 512 / 1000; + return DIV_ROUND_CLOSEST(val, 5); +} + +static u8 therm_delay_to_setpoint(u32 delay_us) +{ + u8 val; + + if (delay_us < 2560) + val = 0; + else if (delay_us > 163840) + val = 7; + else + val = ilog2(delay_us / 10) - 7; + return val << 5; +} + +static int get_current_time(unsigned long *now_tm_sec) +{ + struct rtc_time tm; + struct rtc_device *rtc; + int rc; + + rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); + if (rtc == NULL) { + pr_err("%s: unable to open rtc device (%s)\n", + __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); + return -EINVAL; + } + + rc = rtc_read_time(rtc, &tm); + if (rc) { + pr_err("Error reading rtc device (%s) : %d\n", + CONFIG_RTC_HCTOSYS_DEVICE, rc); + goto close_time; + } + + rc = rtc_valid_tm(&tm); + if (rc) { + pr_err("Invalid RTC time (%s): %d\n", + CONFIG_RTC_HCTOSYS_DEVICE, rc); + goto close_time; + } + rtc_tm_to_time(&tm, now_tm_sec); + +close_time: + rtc_class_close(rtc); + return rc; +} + +#define BATTERY_SOC_REG 0x56C +#define BATTERY_SOC_OFFSET 1 +#define FULL_PERCENT_3B 0xFFFFFF +static int get_battery_soc_raw(struct fg_chip *chip) +{ + int rc; + u8 buffer[3]; + + rc = fg_mem_read(chip, buffer, BATTERY_SOC_REG, 3, 1, 0); + if (rc) { + pr_err("Unable to read battery soc: %d\n", rc); + return 0; + } + return (int)(buffer[2] << 16 | buffer[1] << 8 | buffer[0]); +} + +#define COUNTER_IMPTR_REG 0X558 +#define COUNTER_PULSE_REG 0X55C +#define SOC_FULL_REG 0x564 +#define COUNTER_IMPTR_OFFSET 2 +#define COUNTER_PULSE_OFFSET 0 +#define SOC_FULL_OFFSET 3 +#define ESR_PULSE_RECONFIG_SOC 0xFFF971 +static int fg_configure_soc(struct fg_chip *chip) +{ + u32 batt_soc; + u8 cntr[2] = {0, 0}; + int rc = 0; + + mutex_lock(&chip->rw_lock); + atomic_add_return(1, &chip->memif_user_cnt); + mutex_unlock(&chip->rw_lock); + + /* Read Battery SOC */ + batt_soc = get_battery_soc_raw(chip); + + if (batt_soc > ESR_PULSE_RECONFIG_SOC) { + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info("Configuring soc registers batt_soc: %x\n", + batt_soc); + batt_soc = ESR_PULSE_RECONFIG_SOC; + rc = fg_mem_write(chip, (u8 *)&batt_soc, BATTERY_SOC_REG, 3, + BATTERY_SOC_OFFSET, 1); + if (rc) { + pr_err("failed to write BATT_SOC rc=%d\n", rc); + goto out; + } + + rc = fg_mem_write(chip, (u8 *)&batt_soc, SOC_FULL_REG, 3, + SOC_FULL_OFFSET, 1); + if (rc) { + pr_err("failed to write SOC_FULL rc=%d\n", rc); + goto out; + } + + rc = fg_mem_write(chip, cntr, COUNTER_IMPTR_REG, 2, + COUNTER_IMPTR_OFFSET, 1); + if (rc) { + pr_err("failed to write COUNTER_IMPTR rc=%d\n", rc); + goto out; + } + + rc = fg_mem_write(chip, cntr, COUNTER_PULSE_REG, 2, + COUNTER_PULSE_OFFSET, 0); + if (rc) + pr_err("failed to write COUNTER_IMPTR rc=%d\n", rc); + } +out: + fg_release_access_if_necessary(chip); + return rc; +} + +#define VBATT_LOW_STS_BIT BIT(2) +static int fg_get_vbatt_status(struct fg_chip *chip, bool *vbatt_low_sts) +{ + int rc = 0; + u8 fg_batt_sts; + + rc = fg_read(chip, &fg_batt_sts, INT_RT_STS(chip->batt_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + else + *vbatt_low_sts = !!(fg_batt_sts & VBATT_LOW_STS_BIT); + + return rc; +} + +#define SOC_EMPTY BIT(3) +static bool fg_is_batt_empty(struct fg_chip *chip) +{ + u8 fg_soc_sts; + int rc; + bool vbatt_low_sts; + + if (chip->use_vbat_low_empty_soc) { + if (fg_get_vbatt_status(chip, &vbatt_low_sts)) + return false; + + return vbatt_low_sts; + } + + rc = fg_read(chip, &fg_soc_sts, INT_RT_STS(chip->soc_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + return false; + } + + return (fg_soc_sts & SOC_EMPTY) != 0; +} + +static int get_monotonic_soc_raw(struct fg_chip *chip) +{ + u8 cap[2]; + int rc, tries = 0; + + while (tries < MAX_TRIES_SOC) { + rc = fg_read(chip, cap, + chip->soc_base + SOC_MONOTONIC_SOC, 2); + if (rc) { + pr_err("spmi read failed: addr=%03x, rc=%d\n", + chip->soc_base + SOC_MONOTONIC_SOC, rc); + return rc; + } + + if (cap[0] == cap[1]) + break; + + tries++; + } + + if (tries == MAX_TRIES_SOC) { + pr_err("shadow registers do not match\n"); + return -EINVAL; + } + + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info_ratelimited("raw: 0x%02x\n", cap[0]); + return cap[0]; +} + +#define EMPTY_CAPACITY 0 +#define DEFAULT_CAPACITY 50 +#define MISSING_CAPACITY 100 +#define FULL_CAPACITY 100 +#define FULL_SOC_RAW 0xFF +static int get_prop_capacity(struct fg_chip *chip) +{ + int msoc, rc; + bool vbatt_low_sts; + + if (chip->use_last_soc && chip->last_soc) { + if (chip->last_soc == FULL_SOC_RAW) + return FULL_CAPACITY; + return DIV_ROUND_CLOSEST((chip->last_soc - 1) * + (FULL_CAPACITY - 2), + FULL_SOC_RAW - 2) + 1; + } + + if (chip->battery_missing) + return MISSING_CAPACITY; + + if (!chip->profile_loaded && !chip->use_otp_profile) + return DEFAULT_CAPACITY; + + if (chip->charge_full) + return FULL_CAPACITY; + + if (chip->soc_empty) { + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info_ratelimited("capacity: %d, EMPTY\n", + EMPTY_CAPACITY); + return EMPTY_CAPACITY; + } + + msoc = get_monotonic_soc_raw(chip); + if (msoc == 0) { + if (fg_reset_on_lockup && chip->use_vbat_low_empty_soc) { + rc = fg_get_vbatt_status(chip, &vbatt_low_sts); + if (rc) { + pr_err("Error in reading vbatt_status, rc=%d\n", + rc); + return EMPTY_CAPACITY; + } + + if (!vbatt_low_sts) + return DIV_ROUND_CLOSEST((chip->last_soc - 1) * + (FULL_CAPACITY - 2), + FULL_SOC_RAW - 2) + 1; + else + return EMPTY_CAPACITY; + } else { + return EMPTY_CAPACITY; + } + } else if (msoc == FULL_SOC_RAW) { + return FULL_CAPACITY; + } + + return DIV_ROUND_CLOSEST((msoc - 1) * (FULL_CAPACITY - 2), + FULL_SOC_RAW - 2) + 1; +} + +#define HIGH_BIAS 3 +#define MED_BIAS BIT(1) +#define LOW_BIAS BIT(0) +static u8 bias_ua[] = { + [HIGH_BIAS] = 150, + [MED_BIAS] = 15, + [LOW_BIAS] = 5, +}; + +static int64_t get_batt_id(unsigned int battery_id_uv, u8 bid_info) +{ + u64 battery_id_ohm; + + if ((bid_info & 0x3) == 0) { + pr_err("can't determine battery id 0x%02x\n", bid_info); + return -EINVAL; + } + + battery_id_ohm = div_u64(battery_id_uv, bias_ua[bid_info & 0x3]); + + return battery_id_ohm; +} + +#define DEFAULT_TEMP_DEGC 250 +static int get_sram_prop_now(struct fg_chip *chip, unsigned int type) +{ + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info("addr 0x%02X, offset %d value %d\n", + fg_data[type].address, fg_data[type].offset, + fg_data[type].value); + + if (type == FG_DATA_BATT_ID) + return get_batt_id(fg_data[type].value, + fg_data[FG_DATA_BATT_ID_INFO].value); + + return fg_data[type].value; +} + +#define MIN_TEMP_DEGC -300 +#define MAX_TEMP_DEGC 970 +static int get_prop_jeita_temp(struct fg_chip *chip, unsigned int type) +{ + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info("addr 0x%02X, offset %d\n", settings[type].address, + settings[type].offset); + + return settings[type].value; +} + +static int set_prop_jeita_temp(struct fg_chip *chip, + unsigned int type, int decidegc) +{ + int rc = 0; + + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info("addr 0x%02X, offset %d temp%d\n", + settings[type].address, + settings[type].offset, decidegc); + + settings[type].value = decidegc; + + cancel_delayed_work_sync( + &chip->update_jeita_setting); + schedule_delayed_work( + &chip->update_jeita_setting, 0); + + return rc; +} + +#define EXTERNAL_SENSE_SELECT 0x4AC +#define EXTERNAL_SENSE_OFFSET 0x2 +#define EXTERNAL_SENSE_BIT BIT(2) +static int set_prop_sense_type(struct fg_chip *chip, int ext_sense_type) +{ + int rc; + + rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, + EXTERNAL_SENSE_BIT, + ext_sense_type ? EXTERNAL_SENSE_BIT : 0, + EXTERNAL_SENSE_OFFSET); + if (rc) { + pr_err("failed to write profile rc=%d\n", rc); + return rc; + } + + return 0; +} + +#define IGNORE_FALSE_NEGATIVE_ISENSE_BIT BIT(3) +static int set_prop_ignore_false_negative_isense(struct fg_chip *chip, + bool ignore) +{ + int rc; + + rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, + IGNORE_FALSE_NEGATIVE_ISENSE_BIT, + ignore ? IGNORE_FALSE_NEGATIVE_ISENSE_BIT : 0, + EXTERNAL_SENSE_OFFSET); + if (rc) { + pr_err("failed to %s isense false negative ignore rc=%d\n", + ignore ? "enable" : "disable", rc); + return rc; + } + + return 0; +} + +#define EXPONENT_MASK 0xF800 +#define MANTISSA_MASK 0x3FF +#define SIGN BIT(10) +#define EXPONENT_SHIFT 11 +#define MICRO_UNIT 1000000ULL +static int64_t float_decode(u16 reg) +{ + int64_t final_val, exponent_val, mantissa_val; + int exponent, mantissa, n; + bool sign; + + exponent = (reg & EXPONENT_MASK) >> EXPONENT_SHIFT; + mantissa = (reg & MANTISSA_MASK); + sign = !!(reg & SIGN); + + pr_debug("exponent=%d mantissa=%d sign=%d\n", exponent, mantissa, sign); + + mantissa_val = mantissa * MICRO_UNIT; + + n = exponent - 15; + if (n < 0) + exponent_val = MICRO_UNIT >> -n; + else + exponent_val = MICRO_UNIT << n; + + n = n - 10; + if (n < 0) + mantissa_val >>= -n; + else + mantissa_val <<= n; + + final_val = exponent_val + mantissa_val; + + if (sign) + final_val *= -1; + + return final_val; +} + +#define MIN_HALFFLOAT_EXP_N -15 +#define MAX_HALFFLOAT_EXP_N 16 +static int log2_floor(int64_t uval) +{ + int n = 0; + int64_t i = MICRO_UNIT; + + if (uval > i) { + while (uval > i && n > MIN_HALFFLOAT_EXP_N) { + i <<= 1; + n += 1; + } + if (uval < i) + n -= 1; + } else if (uval < i) { + while (uval < i && n < MAX_HALFFLOAT_EXP_N) { + i >>= 1; + n -= 1; + } + } + + return n; +} + +static int64_t exp2_int(int64_t n) +{ + int p = n - 1; + + if (p > 0) + return (2 * MICRO_UNIT) << p; + else + return (2 * MICRO_UNIT) >> abs(p); +} + +static u16 float_encode(int64_t uval) +{ + int sign = 0, n, exp, mantissa; + u16 half = 0; + + if (uval < 0) { + sign = 1; + uval = abs(uval); + } + n = log2_floor(uval); + exp = n + 15; + mantissa = div_s64(div_s64((uval - exp2_int(n)) * exp2_int(10 - n), + MICRO_UNIT) + MICRO_UNIT / 2, MICRO_UNIT); + + half = (mantissa & MANTISSA_MASK) | ((sign << 10) & SIGN) + | ((exp << 11) & EXPONENT_MASK); + + if (fg_debug_mask & FG_STATUS) + pr_info("uval = %lld, m = 0x%02x, sign = 0x%02x, exp = 0x%02x, half = 0x%04x\n", + uval, mantissa, sign, exp, half); + return half; +} + +#define BATT_IDED BIT(3) +static int fg_is_batt_id_valid(struct fg_chip *chip) +{ + u8 fg_batt_sts; + int rc; + + rc = fg_read(chip, &fg_batt_sts, + INT_RT_STS(chip->batt_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + return rc; + } + + pr_debug("fg batt sts 0x%x\n", fg_batt_sts); + + return (fg_batt_sts & BATT_IDED) ? 1 : 0; +} + +static int64_t twos_compliment_extend(int64_t val, int nbytes) +{ + int i; + int64_t mask; + + mask = 0x80LL << ((nbytes - 1) * 8); + if (val & mask) { + for (i = 8; i > nbytes; i--) { + mask = 0xFFLL << ((i - 1) * 8); + val |= mask; + } + } + + return val; +} + +#define LSB_24B_NUMRTR 596046 +#define LSB_24B_DENMTR 1000000 +#define LSB_16B_NUMRTR 152587 +#define LSB_16B_DENMTR 1000 +#define LSB_8B 9800 +#define TEMP_LSB_16B 625 +#define DECIKELVIN 2730 +#define SRAM_PERIOD_NO_ID_UPDATE_MS 100 +#define FULL_PERCENT_28BIT 0xFFFFFFF +static int update_sram_data(struct fg_chip *chip, int *resched_ms) +{ + int i, j, rc = 0; + u8 reg[4]; + int64_t temp; + int battid_valid = fg_is_batt_id_valid(chip); + + fg_stay_awake(&chip->update_sram_wakeup_source); + if (chip->fg_restarting) + goto resched; + + fg_mem_lock(chip); + for (i = 1; i < FG_DATA_MAX; i++) { + if (chip->profile_loaded && i >= FG_DATA_BATT_ID) + continue; + rc = fg_mem_read(chip, reg, fg_data[i].address, + fg_data[i].len, fg_data[i].offset, 0); + if (rc) { + pr_err("Failed to update sram data\n"); + break; + } + + temp = 0; + for (j = 0; j < fg_data[i].len; j++) + temp |= reg[j] << (8 * j); + + switch (i) { + case FG_DATA_OCV: + case FG_DATA_VOLTAGE: + case FG_DATA_CPRED_VOLTAGE: + fg_data[i].value = div_u64( + (u64)(u16)temp * LSB_16B_NUMRTR, + LSB_16B_DENMTR); + break; + case FG_DATA_CURRENT: + temp = twos_compliment_extend(temp, fg_data[i].len); + fg_data[i].value = div_s64( + (s64)temp * LSB_16B_NUMRTR, + LSB_16B_DENMTR); + break; + case FG_DATA_BATT_ESR: + fg_data[i].value = float_decode((u16) temp); + break; + case FG_DATA_BATT_ESR_COUNT: + fg_data[i].value = (u16)temp; + break; + case FG_DATA_BATT_ID: + if (battid_valid) + fg_data[i].value = reg[0] * LSB_8B; + break; + case FG_DATA_BATT_ID_INFO: + if (battid_valid) + fg_data[i].value = reg[0]; + break; + case FG_DATA_BATT_SOC: + fg_data[i].value = div64_s64((temp * 10000), + FULL_PERCENT_3B); + break; + case FG_DATA_CC_CHARGE: + temp = twos_compliment_extend(temp, fg_data[i].len); + fg_data[i].value = div64_s64( + temp * (int64_t)chip->nom_cap_uah, + FULL_PERCENT_28BIT); + break; + case FG_DATA_VINT_ERR: + temp = twos_compliment_extend(temp, fg_data[i].len); + fg_data[i].value = div64_s64(temp * chip->nom_cap_uah, + FULL_PERCENT_3B); + break; + }; + + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("%d %lld %d\n", i, temp, fg_data[i].value); + } + fg_mem_release(chip); + + /* Backup the registers whenever no error happens during update */ + if (fg_reset_on_lockup && !chip->ima_error_handling) { + if (!rc) { + if (fg_debug_mask & FG_STATUS) + pr_info("backing up SRAM registers\n"); + rc = fg_backup_sram_registers(chip, true); + if (rc) { + pr_err("Couldn't save sram registers\n"); + goto out; + } + if (!chip->use_last_soc) { + chip->last_soc = get_monotonic_soc_raw(chip); + chip->last_cc_soc = div64_s64( + (int64_t)chip->last_soc * + FULL_PERCENT_28BIT, FULL_SOC_RAW); + } + if (fg_debug_mask & FG_STATUS) + pr_info("last_soc: %d last_cc_soc: %lld\n", + chip->last_soc, chip->last_cc_soc); + } else { + pr_err("update_sram failed\n"); + goto out; + } + } + + if (!rc) + get_current_time(&chip->last_sram_update_time); + +resched: + if (battid_valid) { + complete_all(&chip->batt_id_avail); + *resched_ms = fg_sram_update_period_ms; + } else { + *resched_ms = SRAM_PERIOD_NO_ID_UPDATE_MS; + } +out: + fg_relax(&chip->update_sram_wakeup_source); + return rc; +} + +#define SANITY_CHECK_PERIOD_MS 5000 +static void check_sanity_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + check_sanity_work.work); + int rc = 0; + u8 beat_count; + bool tried_once = false; + + fg_stay_awake(&chip->sanity_wakeup_source); + +try_again: + rc = fg_read(chip, &beat_count, + chip->mem_base + MEM_INTF_FG_BEAT_COUNT, 1); + if (rc) { + pr_err("failed to read beat count rc=%d\n", rc); + goto resched; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("current: %d, prev: %d\n", beat_count, + chip->last_beat_count); + + if (chip->last_beat_count == beat_count) { + if (!tried_once) { + /* Wait for 1 FG cycle and read it once again */ + msleep(1500); + tried_once = true; + goto try_again; + } else { + pr_err("Beat count not updating\n"); + fg_check_ima_error_handling(chip); + goto out; + } + } else { + chip->last_beat_count = beat_count; + } +resched: + schedule_delayed_work( + &chip->check_sanity_work, + msecs_to_jiffies(SANITY_CHECK_PERIOD_MS)); +out: + fg_relax(&chip->sanity_wakeup_source); +} + +#define SRAM_TIMEOUT_MS 3000 +static void update_sram_data_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + update_sram_data.work); + int resched_ms, ret; + bool tried_again = false; + int rc = 0; + +wait: + /* Wait for MEMIF access revoked */ + ret = wait_for_completion_interruptible_timeout( + &chip->sram_access_revoked, + msecs_to_jiffies(SRAM_TIMEOUT_MS)); + + /* If we were interrupted wait again one more time. */ + if (ret == -ERESTARTSYS && !tried_again) { + tried_again = true; + goto wait; + } else if (ret <= 0) { + pr_err("transaction timed out ret=%d\n", ret); + if (fg_is_batt_id_valid(chip)) + resched_ms = fg_sram_update_period_ms; + else + resched_ms = SRAM_PERIOD_NO_ID_UPDATE_MS; + goto out; + } + rc = update_sram_data(chip, &resched_ms); + +out: + if (!rc) + schedule_delayed_work( + &chip->update_sram_data, + msecs_to_jiffies(resched_ms)); +} + +#define BATT_TEMP_OFFSET 3 +#define BATT_TEMP_CNTRL_MASK 0x17 +#define DISABLE_THERM_BIT BIT(0) +#define TEMP_SENSE_ALWAYS_BIT BIT(1) +#define TEMP_SENSE_CHARGE_BIT BIT(2) +#define FORCE_RBIAS_ON_BIT BIT(4) +#define BATT_TEMP_OFF DISABLE_THERM_BIT +#define BATT_TEMP_ON (FORCE_RBIAS_ON_BIT | TEMP_SENSE_ALWAYS_BIT | \ + TEMP_SENSE_CHARGE_BIT) +#define TEMP_PERIOD_UPDATE_MS 10000 +#define TEMP_PERIOD_TIMEOUT_MS 3000 +#define BATT_TEMP_LOW_LIMIT -600 +#define BATT_TEMP_HIGH_LIMIT 1500 +static void update_temp_data(struct work_struct *work) +{ + s16 temp; + u8 reg[2]; + bool tried_again = false; + int rc, ret, timeout = TEMP_PERIOD_TIMEOUT_MS; + struct fg_chip *chip = container_of(work, + struct fg_chip, + update_temp_work.work); + + if (chip->fg_restarting) + goto resched; + + fg_stay_awake(&chip->update_temp_wakeup_source); + if (chip->sw_rbias_ctrl) { + rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, + BATT_TEMP_CNTRL_MASK, + BATT_TEMP_ON, + BATT_TEMP_OFFSET); + if (rc) { + pr_err("failed to write BATT_TEMP_ON rc=%d\n", rc); + goto out; + } + +wait: + /* Wait for MEMIF access revoked */ + ret = wait_for_completion_interruptible_timeout( + &chip->sram_access_revoked, + msecs_to_jiffies(timeout)); + + /* If we were interrupted wait again one more time. */ + if (ret == -ERESTARTSYS && !tried_again) { + tried_again = true; + goto wait; + } else if (ret <= 0) { + rc = -ETIMEDOUT; + pr_err("transaction timed out ret=%d\n", ret); + goto out; + } + } + + /* Read FG_DATA_BATT_TEMP now */ + rc = fg_mem_read(chip, reg, fg_data[0].address, + fg_data[0].len, fg_data[0].offset, + chip->sw_rbias_ctrl ? 1 : 0); + if (rc) { + pr_err("Failed to update temp data\n"); + goto out; + } + + temp = reg[0] | (reg[1] << 8); + temp = (temp * TEMP_LSB_16B / 1000) - DECIKELVIN; + + /* + * If temperature is within the specified range (e.g. -60C and 150C), + * update it to the userspace. Otherwise, use the last read good + * temperature. + */ + if (temp > chip->batt_temp_low_limit && + temp < chip->batt_temp_high_limit) { + chip->last_good_temp = temp; + fg_data[0].value = temp; + } else { + fg_data[0].value = chip->last_good_temp; + + /* + * If the temperature is read before and seems to be in valid + * range, then a bad temperature reading could be because of + * FG lockup. Trigger the FG reset sequence in such cases. + */ + if (chip->last_temp_update_time && fg_reset_on_lockup && + (chip->last_good_temp > chip->batt_temp_low_limit && + chip->last_good_temp < chip->batt_temp_high_limit)) { + pr_err("Batt_temp is %d !, triggering FG reset\n", + temp); + fg_check_ima_error_handling(chip); + } + } + + if (fg_debug_mask & FG_MEM_DEBUG_READS) + pr_info("BATT_TEMP %d %d\n", temp, fg_data[0].value); + + get_current_time(&chip->last_temp_update_time); + + if (chip->soc_slope_limiter_en) { + fg_stay_awake(&chip->slope_limit_wakeup_source); + schedule_work(&chip->slope_limiter_work); + } + +out: + if (chip->sw_rbias_ctrl) { + rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, + BATT_TEMP_CNTRL_MASK, + BATT_TEMP_OFF, + BATT_TEMP_OFFSET); + if (rc) + pr_err("failed to write BATT_TEMP_OFF rc=%d\n", rc); + } + fg_relax(&chip->update_temp_wakeup_source); + +resched: + schedule_delayed_work( + &chip->update_temp_work, + msecs_to_jiffies(TEMP_PERIOD_UPDATE_MS)); +} + +static void update_jeita_setting(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + update_jeita_setting.work); + u8 reg[4]; + int i, rc; + + for (i = 0; i < 4; i++) + reg[i] = (settings[FG_MEM_SOFT_COLD + i].value / 10) + 30; + + rc = fg_mem_write(chip, reg, settings[FG_MEM_SOFT_COLD].address, + 4, settings[FG_MEM_SOFT_COLD].offset, 0); + if (rc) + pr_err("failed to update JEITA setting rc=%d\n", rc); +} + +static int fg_set_resume_soc(struct fg_chip *chip, u8 threshold) +{ + u16 address; + int offset, rc; + + address = settings[FG_MEM_RESUME_SOC].address; + offset = settings[FG_MEM_RESUME_SOC].offset; + + rc = fg_mem_masked_write(chip, address, 0xFF, threshold, offset); + + if (rc) + pr_err("write failed rc=%d\n", rc); + else + pr_debug("setting resume-soc to %x\n", threshold); + + return rc; +} + +#define BATT_CYCLE_NUMBER_REG 0x5E8 +#define BATT_CYCLE_OFFSET 0 +static void restore_cycle_counter(struct fg_chip *chip) +{ + int rc = 0, i, address; + u8 data[2]; + + fg_mem_lock(chip); + for (i = 0; i < BUCKET_COUNT; i++) { + address = BATT_CYCLE_NUMBER_REG + i * 2; + rc = fg_mem_read(chip, (u8 *)&data, address, 2, + BATT_CYCLE_OFFSET, 0); + if (rc) + pr_err("Failed to read BATT_CYCLE_NUMBER[%d] rc: %d\n", + i, rc); + else + chip->cyc_ctr.count[i] = data[0] | data[1] << 8; + } + fg_mem_release(chip); +} + +static void clear_cycle_counter(struct fg_chip *chip) +{ + int rc = 0, len, i; + + if (!chip->cyc_ctr.en) + return; + + len = sizeof(chip->cyc_ctr.count); + memset(chip->cyc_ctr.count, 0, len); + for (i = 0; i < BUCKET_COUNT; i++) { + chip->cyc_ctr.started[i] = false; + chip->cyc_ctr.last_soc[i] = 0; + } + rc = fg_mem_write(chip, (u8 *)&chip->cyc_ctr.count, + BATT_CYCLE_NUMBER_REG, len, + BATT_CYCLE_OFFSET, 0); + if (rc) + pr_err("failed to write BATT_CYCLE_NUMBER rc=%d\n", rc); +} + +static int fg_inc_store_cycle_ctr(struct fg_chip *chip, int bucket) +{ + int rc = 0, address; + u16 cyc_count; + u8 data[2]; + + if (bucket < 0 || (bucket > BUCKET_COUNT - 1)) + return 0; + + cyc_count = chip->cyc_ctr.count[bucket]; + cyc_count++; + data[0] = cyc_count & 0xFF; + data[1] = cyc_count >> 8; + + address = BATT_CYCLE_NUMBER_REG + bucket * 2; + + rc = fg_mem_write(chip, data, address, 2, BATT_CYCLE_OFFSET, 0); + if (rc) + pr_err("failed to write BATT_CYCLE_NUMBER[%d] rc=%d\n", + bucket, rc); + else + chip->cyc_ctr.count[bucket] = cyc_count; + + if (fg_debug_mask & FG_POWER_SUPPLY) + pr_info("Stored bucket %d cyc_count: %d\n", bucket, cyc_count); + return rc; +} + +static void update_cycle_count(struct work_struct *work) +{ + int rc = 0, bucket, i; + u8 reg[3], batt_soc; + struct fg_chip *chip = container_of(work, + struct fg_chip, + cycle_count_work); + + mutex_lock(&chip->cyc_ctr.lock); + rc = fg_mem_read(chip, reg, BATTERY_SOC_REG, 3, + BATTERY_SOC_OFFSET, 0); + if (rc) { + pr_err("Failed to read battery soc rc: %d\n", rc); + goto out; + } + batt_soc = reg[2]; + + if (chip->status == POWER_SUPPLY_STATUS_CHARGING) { + /* Find out which bucket the SOC falls in */ + bucket = batt_soc / BUCKET_SOC_PCT; + + if (fg_debug_mask & FG_STATUS) + pr_info("batt_soc: %x bucket: %d\n", reg[2], bucket); + + /* + * If we've started counting for the previous bucket, + * then store the counter for that bucket if the + * counter for current bucket is getting started. + */ + if (bucket > 0 && chip->cyc_ctr.started[bucket - 1] && + !chip->cyc_ctr.started[bucket]) { + rc = fg_inc_store_cycle_ctr(chip, bucket - 1); + if (rc) { + pr_err("Error in storing cycle_ctr rc: %d\n", + rc); + goto out; + } else { + chip->cyc_ctr.started[bucket - 1] = false; + chip->cyc_ctr.last_soc[bucket - 1] = 0; + } + } + if (!chip->cyc_ctr.started[bucket]) { + chip->cyc_ctr.started[bucket] = true; + chip->cyc_ctr.last_soc[bucket] = batt_soc; + } + } else { + for (i = 0; i < BUCKET_COUNT; i++) { + if (chip->cyc_ctr.started[i] && + batt_soc > chip->cyc_ctr.last_soc[i]) { + rc = fg_inc_store_cycle_ctr(chip, i); + if (rc) + pr_err("Error in storing cycle_ctr rc: %d\n", + rc); + chip->cyc_ctr.last_soc[i] = 0; + } + chip->cyc_ctr.started[i] = false; + } + } +out: + mutex_unlock(&chip->cyc_ctr.lock); +} + +static int fg_get_cycle_count(struct fg_chip *chip) +{ + int count; + + if (!chip->cyc_ctr.en) + return 0; + + if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT)) + return -EINVAL; + + mutex_lock(&chip->cyc_ctr.lock); + count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1]; + mutex_unlock(&chip->cyc_ctr.lock); + return count; +} + +static void half_float_to_buffer(int64_t uval, u8 *buffer) +{ + u16 raw; + + raw = float_encode(uval); + buffer[0] = (u8)(raw & 0xFF); + buffer[1] = (u8)((raw >> 8) & 0xFF); +} + +static int64_t half_float(u8 *buffer) +{ + u16 val; + + val = buffer[1] << 8 | buffer[0]; + return float_decode(val); +} + +static int voltage_2b(u8 *buffer) +{ + u16 val; + + val = buffer[1] << 8 | buffer[0]; + /* the range of voltage 2b is [-5V, 5V], so it will fit in an int */ + return (int)div_u64(((u64)val) * LSB_16B_NUMRTR, LSB_16B_DENMTR); +} + +static int bcap_uah_2b(u8 *buffer) +{ + u16 val; + + val = buffer[1] << 8 | buffer[0]; + return ((int)val) * 1000; +} + +#define SLOPE_LIMITER_COEFF_REG 0x430 +#define SLOPE_LIMITER_COEFF_OFFSET 3 +#define SLOPE_LIMIT_TEMP_THRESHOLD 100 +#define SLOPE_LIMIT_LOW_TEMP_CHG 45 +#define SLOPE_LIMIT_HIGH_TEMP_CHG 2 +#define SLOPE_LIMIT_LOW_TEMP_DISCHG 45 +#define SLOPE_LIMIT_HIGH_TEMP_DISCHG 2 +static void slope_limiter_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, struct fg_chip, + slope_limiter_work); + enum slope_limit_status status; + int batt_temp, rc; + u8 buf[2]; + int64_t val; + + batt_temp = get_sram_prop_now(chip, FG_DATA_BATT_TEMP); + + if (chip->status == POWER_SUPPLY_STATUS_CHARGING || + chip->status == POWER_SUPPLY_STATUS_FULL) { + if (batt_temp < chip->slope_limit_temp) + status = LOW_TEMP_CHARGE; + else + status = HIGH_TEMP_CHARGE; + } else if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) { + if (batt_temp < chip->slope_limit_temp) + status = LOW_TEMP_DISCHARGE; + else + status = HIGH_TEMP_DISCHARGE; + } else { + goto out; + } + + if (status == chip->slope_limit_sts) + goto out; + + val = chip->slope_limit_coeffs[status]; + val *= MICRO_UNIT; + half_float_to_buffer(val, buf); + rc = fg_mem_write(chip, buf, + SLOPE_LIMITER_COEFF_REG, 2, + SLOPE_LIMITER_COEFF_OFFSET, 0); + if (rc) { + pr_err("Couldn't write to slope_limiter_coeff_reg, rc=%d\n", + rc); + goto out; + } + + chip->slope_limit_sts = status; + if (fg_debug_mask & FG_STATUS) + pr_info("Slope limit sts: %d val: %lld buf[%x %x] written\n", + status, val, buf[0], buf[1]); +out: + fg_relax(&chip->slope_limit_wakeup_source); +} + +static int lookup_ocv_for_soc(struct fg_chip *chip, int soc) +{ + int64_t *coeffs; + + if (soc > chip->ocv_junction_p1p2 * 10) + coeffs = chip->ocv_coeffs; + else if (soc > chip->ocv_junction_p2p3 * 10) + coeffs = chip->ocv_coeffs + 4; + else + coeffs = chip->ocv_coeffs + 8; + /* the range of ocv will fit in a 32 bit int */ + return (int)(coeffs[0] + + div_s64(coeffs[1] * soc, 1000LL) + + div_s64(coeffs[2] * soc * soc, 1000000LL) + + div_s64(coeffs[3] * soc * soc * soc, 1000000000LL)); +} + +static int lookup_soc_for_ocv(struct fg_chip *chip, int ocv) +{ + int64_t val; + int soc = -EINVAL; + /* + * binary search variables representing the valid start and end + * percentages to search + */ + int start = 0, end = 1000, mid; + + if (fg_debug_mask & FG_AGING) + pr_info("target_ocv = %d\n", ocv); + /* do a binary search for the closest soc to match the ocv */ + while (end - start > 1) { + mid = (start + end) / 2; + val = lookup_ocv_for_soc(chip, mid); + if (fg_debug_mask & FG_AGING) + pr_info("start = %d, mid = %d, end = %d, ocv = %lld\n", + start, mid, end, val); + if (ocv < val) { + end = mid; + } else if (ocv > val) { + start = mid; + } else { + soc = mid; + break; + } + } + /* + * if the exact soc was not found and there are two or less values + * remaining, just compare them and see which one is closest to the ocv + */ + if (soc == -EINVAL) { + if (abs(ocv - lookup_ocv_for_soc(chip, start)) + > abs(ocv - lookup_ocv_for_soc(chip, end))) + soc = end; + else + soc = start; + } + if (fg_debug_mask & FG_AGING) + pr_info("closest = %d, target_ocv = %d, ocv_found = %d\n", + soc, ocv, lookup_ocv_for_soc(chip, soc)); + return soc; +} + +#define ESR_ACTUAL_REG 0x554 +#define BATTERY_ESR_REG 0x4F4 +#define TEMP_RS_TO_RSLOW_REG 0x514 +#define ESR_OFFSET 2 +static int estimate_battery_age(struct fg_chip *chip, int *actual_capacity) +{ + int64_t ocv_cutoff_new, ocv_cutoff_aged, temp_rs_to_rslow; + int64_t esr_actual, battery_esr, val; + int soc_cutoff_aged, soc_cutoff_new, rc; + int battery_soc, unusable_soc, batt_temp; + u8 buffer[3]; + + if (chip->batt_aging_mode != FG_AGING_ESR) + return 0; + + if (chip->nom_cap_uah == 0) { + if (fg_debug_mask & FG_AGING) + pr_info("ocv coefficients not loaded, aborting\n"); + return 0; + } + fg_mem_lock(chip); + + batt_temp = get_sram_prop_now(chip, FG_DATA_BATT_TEMP); + if (batt_temp < 150 || batt_temp > 400) { + if (fg_debug_mask & FG_AGING) + pr_info("Battery temp (%d) out of range, aborting\n", + (int)batt_temp); + rc = 0; + goto done; + } + + battery_soc = get_battery_soc_raw(chip) * 100 / FULL_PERCENT_3B; + if (rc) { + goto error_done; + } else if (battery_soc < 25 || battery_soc > 75) { + if (fg_debug_mask & FG_AGING) + pr_info("Battery SoC (%d) out of range, aborting\n", + (int)battery_soc); + rc = 0; + goto done; + } + + rc = fg_mem_read(chip, buffer, ESR_ACTUAL_REG, 2, 2, 0); + esr_actual = half_float(buffer); + rc |= fg_mem_read(chip, buffer, BATTERY_ESR_REG, 2, ESR_OFFSET, 0); + battery_esr = half_float(buffer); + + if (rc) { + goto error_done; + } else if (esr_actual < battery_esr) { + if (fg_debug_mask & FG_AGING) + pr_info("Batt ESR lower than ESR actual, aborting\n"); + rc = 0; + goto done; + } + rc = fg_mem_read(chip, buffer, TEMP_RS_TO_RSLOW_REG, 2, 0, 0); + temp_rs_to_rslow = half_float(buffer); + + if (rc) + goto error_done; + + fg_mem_release(chip); + + if (fg_debug_mask & FG_AGING) { + pr_info("batt_soc = %d, cutoff_voltage = %lld, eval current = %d\n", + battery_soc, chip->cutoff_voltage, + chip->evaluation_current); + pr_info("temp_rs_to_rslow = %lld, batt_esr = %lld, esr_actual = %lld\n", + temp_rs_to_rslow, battery_esr, esr_actual); + } + + /* calculate soc_cutoff_new */ + val = (1000000LL + temp_rs_to_rslow) * battery_esr; + do_div(val, 1000000); + ocv_cutoff_new = div64_s64(chip->evaluation_current * val, 1000) + + chip->cutoff_voltage; + + /* calculate soc_cutoff_aged */ + val = (1000000LL + temp_rs_to_rslow) * esr_actual; + do_div(val, 1000000); + ocv_cutoff_aged = div64_s64(chip->evaluation_current * val, 1000) + + chip->cutoff_voltage; + + if (fg_debug_mask & FG_AGING) + pr_info("ocv_cutoff_new = %lld, ocv_cutoff_aged = %lld\n", + ocv_cutoff_new, ocv_cutoff_aged); + + soc_cutoff_new = lookup_soc_for_ocv(chip, ocv_cutoff_new); + soc_cutoff_aged = lookup_soc_for_ocv(chip, ocv_cutoff_aged); + + if (fg_debug_mask & FG_AGING) + pr_info("aged soc = %d, new soc = %d\n", + soc_cutoff_aged, soc_cutoff_new); + unusable_soc = soc_cutoff_aged - soc_cutoff_new; + + *actual_capacity = div64_s64(((int64_t)chip->nom_cap_uah) + * (1000 - unusable_soc), 1000); + if (fg_debug_mask & FG_AGING) + pr_info("nom cap = %d, actual cap = %d\n", + chip->nom_cap_uah, *actual_capacity); + + return rc; + +error_done: + pr_err("some register reads failed: %d\n", rc); +done: + fg_mem_release(chip); + return rc; +} + +static void battery_age_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + battery_age_work); + + estimate_battery_age(chip, &chip->actual_cap_uah); +} + +static int correction_times[] = { + 1470, + 2940, + 4410, + 5880, + 7350, + 8820, + 10290, + 11760, + 13230, + 14700, + 16170, + 17640, + 19110, + 20580, + 22050, + 23520, + 24990, + 26460, + 27930, + 29400, + 30870, + 32340, + 33810, + 35280, + 36750, + 38220, + 39690, + 41160, + 42630, + 44100, + 45570, + 47040, +}; + +static int correction_factors[] = { + 1000000, + 1007874, + 1015789, + 1023745, + 1031742, + 1039780, + 1047859, + 1055979, + 1064140, + 1072342, + 1080584, + 1088868, + 1097193, + 1105558, + 1113964, + 1122411, + 1130899, + 1139427, + 1147996, + 1156606, + 1165256, + 1173947, + 1182678, + 1191450, + 1200263, + 1209115, + 1218008, + 1226942, + 1235915, + 1244929, + 1253983, + 1263076, +}; + +#define FG_CONVERSION_FACTOR (64198531LL) +static int iavg_3b_to_uah(u8 *buffer, int delta_ms) +{ + int64_t val, i_filtered; + int i, correction_factor; + + for (i = 0; i < ARRAY_SIZE(correction_times); i++) { + if (correction_times[i] > delta_ms) + break; + } + if (i >= ARRAY_SIZE(correction_times)) { + if (fg_debug_mask & FG_STATUS) + pr_info("fuel gauge took more than 32 cycles\n"); + i = ARRAY_SIZE(correction_times) - 1; + } + correction_factor = correction_factors[i]; + if (fg_debug_mask & FG_STATUS) + pr_info("delta_ms = %d, cycles = %d, correction = %d\n", + delta_ms, i, correction_factor); + val = buffer[2] << 16 | buffer[1] << 8 | buffer[0]; + /* convert val from signed 24b to signed 64b */ + i_filtered = (val << 40) >> 40; + val = i_filtered * correction_factor; + val = div64_s64(val + FG_CONVERSION_FACTOR / 2, FG_CONVERSION_FACTOR); + if (fg_debug_mask & FG_STATUS) + pr_info("i_filtered = 0x%llx/%lld, cc_uah = %lld\n", + i_filtered, i_filtered, val); + + return val; +} + +static bool fg_is_temperature_ok_for_learning(struct fg_chip *chip) +{ + int batt_temp = get_sram_prop_now(chip, FG_DATA_BATT_TEMP); + + if (batt_temp > chip->learning_data.max_temp + || batt_temp < chip->learning_data.min_temp) { + if (fg_debug_mask & FG_AGING) + pr_info("temp (%d) out of range [%d, %d], aborting\n", + batt_temp, + chip->learning_data.min_temp, + chip->learning_data.max_temp); + return false; + } + return true; +} + +static void fg_cap_learning_stop(struct fg_chip *chip) +{ + chip->learning_data.cc_uah = 0; + chip->learning_data.active = false; +} + +#define I_FILTERED_REG 0x584 +static void fg_cap_learning_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + fg_cap_learning_work); + u8 i_filtered[3], data[3]; + int rc, cc_uah, delta_ms; + ktime_t now_kt, delta_kt; + + mutex_lock(&chip->learning_data.learning_lock); + if (!chip->learning_data.active) + goto fail; + if (!fg_is_temperature_ok_for_learning(chip)) { + fg_cap_learning_stop(chip); + goto fail; + } + + if (chip->wa_flag & USE_CC_SOC_REG) + goto fail; + + fg_mem_lock(chip); + + rc = fg_mem_read(chip, i_filtered, I_FILTERED_REG, 3, 0, 0); + if (rc) { + pr_err("Failed to read i_filtered: %d\n", rc); + fg_mem_release(chip); + goto fail; + } + memset(data, 0, 3); + rc = fg_mem_write(chip, data, I_FILTERED_REG, 3, 0, 0); + if (rc) { + pr_err("Failed to clear i_filtered: %d\n", rc); + fg_mem_release(chip); + goto fail; + } + fg_mem_release(chip); + + now_kt = ktime_get_boottime(); + delta_kt = ktime_sub(now_kt, chip->learning_data.time_stamp); + chip->learning_data.time_stamp = now_kt; + + delta_ms = (int)div64_s64(ktime_to_ns(delta_kt), 1000000); + + cc_uah = iavg_3b_to_uah(i_filtered, delta_ms); + chip->learning_data.cc_uah -= cc_uah; + if (fg_debug_mask & FG_AGING) + pr_info("total_cc_uah = %lld\n", chip->learning_data.cc_uah); + +fail: + if (chip->wa_flag & USE_CC_SOC_REG) + fg_relax(&chip->capacity_learning_wakeup_source); + mutex_unlock(&chip->learning_data.learning_lock); + return; + +} + +#define CC_SOC_BASE_REG 0x5BC +#define CC_SOC_OFFSET 3 +static int fg_get_cc_soc(struct fg_chip *chip, int *cc_soc) +{ + int rc; + u8 reg[4]; + int temp; + + rc = fg_mem_read(chip, reg, CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0); + if (rc) { + pr_err("Failed to read CC_SOC_REG rc=%d\n", rc); + return rc; + } + + temp = reg[3] << 24 | reg[2] << 16 | reg[1] << 8 | reg[0]; + *cc_soc = sign_extend32(temp, 29); + return 0; +} + +static int fg_get_current_cc(struct fg_chip *chip) +{ + int cc_soc, rc; + int64_t current_capacity; + + if (!(chip->wa_flag & USE_CC_SOC_REG)) + return chip->learning_data.cc_uah; + + if (!chip->learning_data.learned_cc_uah) + return -EINVAL; + + rc = fg_get_cc_soc(chip, &cc_soc); + if (rc < 0) { + pr_err("Failed to get cc_soc, rc=%d\n", rc); + return rc; + } + + current_capacity = cc_soc * chip->learning_data.learned_cc_uah; + do_div(current_capacity, FULL_PERCENT_28BIT); + return current_capacity; +} + +#define BATT_MISSING_STS BIT(6) +static bool is_battery_missing(struct fg_chip *chip) +{ + int rc; + u8 fg_batt_sts; + + rc = fg_read(chip, &fg_batt_sts, + INT_RT_STS(chip->batt_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + return false; + } + + return (fg_batt_sts & BATT_MISSING_STS) ? true : false; +} + +static int fg_cap_learning_process_full_data(struct fg_chip *chip) +{ + int cc_pc_val, rc = -EINVAL; + unsigned int cc_soc_delta_pc; + int64_t delta_cc_uah; + uint64_t temp; + bool batt_missing = is_battery_missing(chip); + + if (batt_missing) { + pr_err("Battery is missing!\n"); + goto fail; + } + + if (!chip->learning_data.active) + goto fail; + + if (!fg_is_temperature_ok_for_learning(chip)) { + fg_cap_learning_stop(chip); + goto fail; + } + + rc = fg_get_cc_soc(chip, &cc_pc_val); + if (rc) { + pr_err("failed to get CC_SOC, stopping capacity learning\n"); + fg_cap_learning_stop(chip); + goto fail; + } + + temp = abs(cc_pc_val - chip->learning_data.init_cc_pc_val); + cc_soc_delta_pc = DIV_ROUND_CLOSEST_ULL(temp * 100, FULL_PERCENT_28BIT); + + delta_cc_uah = div64_s64( + chip->learning_data.learned_cc_uah * cc_soc_delta_pc, + 100); + chip->learning_data.cc_uah = delta_cc_uah + chip->learning_data.cc_uah; + + if (fg_debug_mask & FG_AGING) + pr_info("current cc_soc=%d cc_soc_pc=%d init_cc_pc_val=%d delta_cc_uah=%lld learned_cc_uah=%lld total_cc_uah = %lld\n", + cc_pc_val, cc_soc_delta_pc, + chip->learning_data.init_cc_pc_val, + delta_cc_uah, + chip->learning_data.learned_cc_uah, + chip->learning_data.cc_uah); + + return 0; + +fail: + return rc; +} + +#define FG_CAP_LEARNING_INTERVAL_NS 30000000000 +static enum alarmtimer_restart fg_cap_learning_alarm_cb(struct alarm *alarm, + ktime_t now) +{ + struct fg_chip *chip = container_of(alarm, struct fg_chip, + fg_cap_learning_alarm); + + if (chip->learning_data.active) { + if (fg_debug_mask & FG_AGING) + pr_info("alarm fired\n"); + schedule_work(&chip->fg_cap_learning_work); + alarm_forward_now(alarm, + ns_to_ktime(FG_CAP_LEARNING_INTERVAL_NS)); + return ALARMTIMER_RESTART; + } + if (fg_debug_mask & FG_AGING) + pr_info("alarm misfired\n"); + return ALARMTIMER_NORESTART; +} + +#define FG_AGING_STORAGE_REG 0x5E4 +#define ACTUAL_CAPACITY_REG 0x578 +#define MAH_TO_SOC_CONV_REG 0x4A0 +#define CC_SOC_COEFF_OFFSET 0 +#define ACTUAL_CAPACITY_OFFSET 2 +#define MAH_TO_SOC_CONV_CS_OFFSET 0 +static int fg_calc_and_store_cc_soc_coeff(struct fg_chip *chip, int16_t cc_mah) +{ + int rc; + int64_t cc_to_soc_coeff, mah_to_soc; + u8 data[2]; + + rc = fg_mem_write(chip, (u8 *)&cc_mah, ACTUAL_CAPACITY_REG, 2, + ACTUAL_CAPACITY_OFFSET, 0); + if (rc) { + pr_err("Failed to store actual capacity: %d\n", rc); + return rc; + } + + rc = fg_mem_read(chip, (u8 *)&data, MAH_TO_SOC_CONV_REG, 2, + MAH_TO_SOC_CONV_CS_OFFSET, 0); + if (rc) { + pr_err("Failed to read mah_to_soc_conv_cs: %d\n", rc); + } else { + mah_to_soc = data[1] << 8 | data[0]; + mah_to_soc *= MICRO_UNIT; + cc_to_soc_coeff = div64_s64(mah_to_soc, cc_mah); + half_float_to_buffer(cc_to_soc_coeff, data); + rc = fg_mem_write(chip, (u8 *)data, + ACTUAL_CAPACITY_REG, 2, + CC_SOC_COEFF_OFFSET, 0); + if (rc) + pr_err("Failed to write cc_soc_coeff_offset: %d\n", + rc); + else if (fg_debug_mask & FG_AGING) + pr_info("new cc_soc_coeff %lld [%x %x] saved to sram\n", + cc_to_soc_coeff, data[0], data[1]); + } + return rc; +} + +static void fg_cap_learning_load_data(struct fg_chip *chip) +{ + int16_t cc_mah; + int64_t old_cap = chip->learning_data.learned_cc_uah; + int rc; + + rc = fg_mem_read(chip, (u8 *)&cc_mah, FG_AGING_STORAGE_REG, 2, 0, 0); + if (rc) { + pr_err("Failed to load aged capacity: %d\n", rc); + } else { + chip->learning_data.learned_cc_uah = cc_mah * 1000; + if (fg_debug_mask & FG_AGING) + pr_info("learned capacity %lld-> %lld/%x uah\n", + old_cap, + chip->learning_data.learned_cc_uah, + cc_mah); + } +} + +static void fg_cap_learning_save_data(struct fg_chip *chip) +{ + int16_t cc_mah; + int rc; + bool batt_missing = is_battery_missing(chip); + + if (batt_missing) { + pr_err("Battery is missing!\n"); + return; + } + + cc_mah = div64_s64(chip->learning_data.learned_cc_uah, 1000); + + rc = fg_mem_write(chip, (u8 *)&cc_mah, FG_AGING_STORAGE_REG, 2, 0, 0); + if (rc) + pr_err("Failed to store aged capacity: %d\n", rc); + else if (fg_debug_mask & FG_AGING) + pr_info("learned capacity %lld uah (%d/0x%x uah) saved to sram\n", + chip->learning_data.learned_cc_uah, + cc_mah, cc_mah); + + if (chip->learning_data.feedback_on) { + rc = fg_calc_and_store_cc_soc_coeff(chip, cc_mah); + if (rc) + pr_err("Error in storing cc_soc_coeff, rc:%d\n", rc); + } +} + +static void fg_cap_learning_post_process(struct fg_chip *chip) +{ + int64_t max_inc_val, min_dec_val, old_cap; + bool batt_missing = is_battery_missing(chip); + + if (batt_missing) { + pr_err("Battery is missing!\n"); + return; + } + + max_inc_val = chip->learning_data.learned_cc_uah + * (1000 + chip->learning_data.max_increment); + do_div(max_inc_val, 1000); + + min_dec_val = chip->learning_data.learned_cc_uah + * (1000 - chip->learning_data.max_decrement); + do_div(min_dec_val, 1000); + + old_cap = chip->learning_data.learned_cc_uah; + if (chip->learning_data.cc_uah > max_inc_val) + chip->learning_data.learned_cc_uah = max_inc_val; + else if (chip->learning_data.cc_uah < min_dec_val) + chip->learning_data.learned_cc_uah = min_dec_val; + else + chip->learning_data.learned_cc_uah = + chip->learning_data.cc_uah; + + if (chip->learning_data.max_cap_limit) { + max_inc_val = (int64_t)chip->nom_cap_uah * (1000 + + chip->learning_data.max_cap_limit); + do_div(max_inc_val, 1000); + if (chip->learning_data.cc_uah > max_inc_val) { + if (fg_debug_mask & FG_AGING) + pr_info("learning capacity %lld goes above max limit %lld\n", + chip->learning_data.cc_uah, + max_inc_val); + chip->learning_data.learned_cc_uah = max_inc_val; + } + } + + if (chip->learning_data.min_cap_limit) { + min_dec_val = (int64_t)chip->nom_cap_uah * (1000 - + chip->learning_data.min_cap_limit); + do_div(min_dec_val, 1000); + if (chip->learning_data.cc_uah < min_dec_val) { + if (fg_debug_mask & FG_AGING) + pr_info("learning capacity %lld goes below min limit %lld\n", + chip->learning_data.cc_uah, + min_dec_val); + chip->learning_data.learned_cc_uah = min_dec_val; + } + } + + fg_cap_learning_save_data(chip); + if (fg_debug_mask & FG_AGING) + pr_info("final cc_uah = %lld, learned capacity %lld -> %lld uah\n", + chip->learning_data.cc_uah, + old_cap, chip->learning_data.learned_cc_uah); +} + +static int get_vbat_est_diff(struct fg_chip *chip) +{ + return abs(fg_data[FG_DATA_VOLTAGE].value + - fg_data[FG_DATA_CPRED_VOLTAGE].value); +} + +#define CBITS_INPUT_FILTER_REG 0x4B4 +#define IBATTF_TAU_MASK 0x38 +#define IBATTF_TAU_99_S 0x30 +static int fg_cap_learning_check(struct fg_chip *chip) +{ + u8 data[4]; + int rc = 0, battery_soc, cc_pc_val; + int vbat_est_diff, vbat_est_thr_uv; + unsigned int cc_pc_100 = FULL_PERCENT_28BIT; + + mutex_lock(&chip->learning_data.learning_lock); + if (chip->status == POWER_SUPPLY_STATUS_CHARGING + && !chip->learning_data.active + && chip->batt_aging_mode == FG_AGING_CC) { + if (chip->learning_data.learned_cc_uah == 0) { + if (fg_debug_mask & FG_AGING) + pr_info("no capacity, aborting\n"); + goto fail; + } + + if (!fg_is_temperature_ok_for_learning(chip)) + goto fail; + + fg_mem_lock(chip); + if (!chip->learning_data.feedback_on) { + vbat_est_diff = get_vbat_est_diff(chip); + vbat_est_thr_uv = chip->learning_data.vbat_est_thr_uv; + if (vbat_est_diff >= vbat_est_thr_uv && + vbat_est_thr_uv > 0) { + if (fg_debug_mask & FG_AGING) + pr_info("vbat_est_diff (%d) < threshold (%d)\n", + vbat_est_diff, vbat_est_thr_uv); + fg_mem_release(chip); + fg_cap_learning_stop(chip); + goto fail; + } + } + battery_soc = get_battery_soc_raw(chip); + if (fg_debug_mask & FG_AGING) + pr_info("checking battery soc (%d vs %d)\n", + battery_soc * 100 / FULL_PERCENT_3B, + chip->learning_data.max_start_soc); + /* check if the battery is low enough to start soc learning */ + if (battery_soc * 100 / FULL_PERCENT_3B + > chip->learning_data.max_start_soc) { + if (fg_debug_mask & FG_AGING) + pr_info("battery soc too high (%d > %d), aborting\n", + battery_soc * 100 / FULL_PERCENT_3B, + chip->learning_data.max_start_soc); + fg_mem_release(chip); + fg_cap_learning_stop(chip); + goto fail; + } + + /* set the coulomb counter to a percentage of the capacity */ + chip->learning_data.cc_uah = div64_s64( + (chip->learning_data.learned_cc_uah * battery_soc), + FULL_PERCENT_3B); + + /* Use CC_SOC_REG based capacity learning */ + if (chip->wa_flag & USE_CC_SOC_REG) { + fg_mem_release(chip); + /* SW_CC_SOC based capacity learning */ + if (fg_get_cc_soc(chip, &cc_pc_val)) { + pr_err("failed to get CC_SOC, stop capacity learning\n"); + fg_cap_learning_stop(chip); + goto fail; + } + + chip->learning_data.init_cc_pc_val = cc_pc_val; + chip->learning_data.active = true; + if (fg_debug_mask & FG_AGING) + pr_info("SW_CC_SOC based learning init_CC_SOC=%d\n", + chip->learning_data.init_cc_pc_val); + } else { + rc = fg_mem_masked_write(chip, CBITS_INPUT_FILTER_REG, + IBATTF_TAU_MASK, IBATTF_TAU_99_S, 0); + if (rc) { + pr_err("Failed to write IF IBAT Tau: %d\n", + rc); + fg_mem_release(chip); + fg_cap_learning_stop(chip); + goto fail; + } + + /* clear the i_filtered register */ + memset(data, 0, 4); + rc = fg_mem_write(chip, data, I_FILTERED_REG, 3, 0, 0); + if (rc) { + pr_err("Failed to clear i_filtered: %d\n", rc); + fg_mem_release(chip); + fg_cap_learning_stop(chip); + goto fail; + } + fg_mem_release(chip); + chip->learning_data.time_stamp = ktime_get_boottime(); + chip->learning_data.active = true; + + if (fg_debug_mask & FG_AGING) + pr_info("cap learning started, soc = %d cc_uah = %lld\n", + battery_soc * 100 / FULL_PERCENT_3B, + chip->learning_data.cc_uah); + rc = alarm_start_relative(&chip->fg_cap_learning_alarm, + ns_to_ktime(FG_CAP_LEARNING_INTERVAL_NS)); + if (rc) { + pr_err("Failed to start alarm: %d\n", rc); + fg_cap_learning_stop(chip); + goto fail; + } + } + } else if ((chip->status != POWER_SUPPLY_STATUS_CHARGING) + && chip->learning_data.active) { + if (fg_debug_mask & FG_AGING) + pr_info("capacity learning stopped\n"); + if (!(chip->wa_flag & USE_CC_SOC_REG)) + alarm_try_to_cancel(&chip->fg_cap_learning_alarm); + + if (chip->status == POWER_SUPPLY_STATUS_FULL) { + if (chip->wa_flag & USE_CC_SOC_REG) { + rc = fg_cap_learning_process_full_data(chip); + if (rc) { + fg_cap_learning_stop(chip); + goto fail; + } + /* reset SW_CC_SOC register to 100% */ + rc = fg_mem_write(chip, (u8 *)&cc_pc_100, + CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0); + if (rc) + pr_err("Failed to reset CC_SOC_REG rc=%d\n", + rc); + } + fg_cap_learning_post_process(chip); + } + + fg_cap_learning_stop(chip); + } else if (chip->status == POWER_SUPPLY_STATUS_FULL) { + if (chip->wa_flag & USE_CC_SOC_REG) { + /* reset SW_CC_SOC register to 100% upon charge_full */ + rc = fg_mem_write(chip, (u8 *)&cc_pc_100, + CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0); + if (rc) + pr_err("Failed to reset CC_SOC_REG rc=%d\n", + rc); + else if (fg_debug_mask & FG_STATUS) + pr_info("Reset SW_CC_SOC to full value\n"); + } + } + +fail: + mutex_unlock(&chip->learning_data.learning_lock); + return rc; +} + +static bool is_usb_present(struct fg_chip *chip) +{ + union power_supply_propval prop = {0,}; + if (!chip->usb_psy) + chip->usb_psy = power_supply_get_by_name("usb"); + + if (chip->usb_psy) + chip->usb_psy->get_property(chip->usb_psy, + POWER_SUPPLY_PROP_PRESENT, &prop); + return prop.intval != 0; +} + +static bool is_dc_present(struct fg_chip *chip) +{ + union power_supply_propval prop = {0,}; + if (!chip->dc_psy) + chip->dc_psy = power_supply_get_by_name("dc"); + + if (chip->dc_psy) + chip->dc_psy->get_property(chip->dc_psy, + POWER_SUPPLY_PROP_PRESENT, &prop); + return prop.intval != 0; +} + +static bool is_input_present(struct fg_chip *chip) +{ + return is_usb_present(chip) || is_dc_present(chip); +} + +static bool is_otg_present(struct fg_chip *chip) +{ + union power_supply_propval prop = {0,}; + + if (!chip->usb_psy) + chip->usb_psy = power_supply_get_by_name("usb"); + + if (chip->usb_psy) + chip->usb_psy->get_property(chip->usb_psy, + POWER_SUPPLY_PROP_USB_OTG, &prop); + return prop.intval != 0; +} + +static bool is_charger_available(struct fg_chip *chip) +{ + if (!chip->batt_psy_name) + return false; + + if (!chip->batt_psy) + chip->batt_psy = power_supply_get_by_name(chip->batt_psy_name); + + if (!chip->batt_psy) + return false; + + return true; +} + +static int set_prop_enable_charging(struct fg_chip *chip, bool enable) +{ + int rc = 0; + union power_supply_propval ret = {enable, }; + + if (!is_charger_available(chip)) { + pr_err("Charger not available yet!\n"); + return -EINVAL; + } + + rc = chip->batt_psy->set_property(chip->batt_psy, + POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED, + &ret); + if (rc) { + pr_err("couldn't configure batt chg %d\n", rc); + return rc; + } + + chip->charging_disabled = !enable; + if (fg_debug_mask & FG_STATUS) + pr_info("%sabling charging\n", enable ? "en" : "dis"); + + return rc; +} + +#define MAX_BATTERY_CC_SOC_CAPACITY 150 +static void status_change_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + status_change_work); + unsigned long current_time = 0; + int cc_soc, batt_soc, rc, capacity = get_prop_capacity(chip); + bool batt_missing = is_battery_missing(chip); + + if (batt_missing) { + if (fg_debug_mask & FG_STATUS) + pr_info("Battery is missing\n"); + return; + } + + if (chip->esr_pulse_tune_en) { + fg_stay_awake(&chip->esr_extract_wakeup_source); + schedule_work(&chip->esr_extract_config_work); + } + + if (chip->status == POWER_SUPPLY_STATUS_FULL) { + if (capacity >= 99 && chip->hold_soc_while_full + && (chip->health == POWER_SUPPLY_HEALTH_GOOD || chip->health == POWER_SUPPLY_HEALTH_COOL)) { + if (fg_debug_mask & FG_STATUS) + pr_info("holding soc at 100\n"); + chip->charge_full = true; + } else if (fg_debug_mask & FG_STATUS) { + pr_info("terminated charging at %d/0x%02x\n", + capacity, get_monotonic_soc_raw(chip)); + } + } + if (chip->status == POWER_SUPPLY_STATUS_FULL || + chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (!chip->vbat_low_irq_enabled && + !chip->use_vbat_low_empty_soc) { + enable_irq(chip->batt_irq[VBATT_LOW].irq); + enable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = true; + } + + if (!chip->full_soc_irq_enabled) { + enable_irq(chip->soc_irq[FULL_SOC].irq); + enable_irq_wake(chip->soc_irq[FULL_SOC].irq); + chip->full_soc_irq_enabled = true; + } + + if (!!(chip->wa_flag & PULSE_REQUEST_WA) && capacity == 100) + fg_configure_soc(chip); + } else if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) { + if (chip->vbat_low_irq_enabled && + !chip->use_vbat_low_empty_soc) { + disable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + disable_irq_nosync(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = false; + } + + if (chip->full_soc_irq_enabled) { + disable_irq_wake(chip->soc_irq[FULL_SOC].irq); + disable_irq_nosync(chip->soc_irq[FULL_SOC].irq); + chip->full_soc_irq_enabled = false; + } + } + fg_cap_learning_check(chip); + schedule_work(&chip->update_esr_work); + + if (chip->wa_flag & USE_CC_SOC_REG) { + if (fg_get_cc_soc(chip, &cc_soc)) { + pr_err("failed to get CC_SOC\n"); + return; + } + } + + if (chip->prev_status != chip->status && chip->last_sram_update_time) { + /* + * Reset SW_CC_SOC to a value based off battery SOC when + * the device is discharging. + */ + if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) { + batt_soc = get_battery_soc_raw(chip); + if (!batt_soc) + return; + + batt_soc = div64_s64((int64_t)batt_soc * + FULL_PERCENT_28BIT, FULL_PERCENT_3B); + rc = fg_mem_write(chip, (u8 *)&batt_soc, + CC_SOC_BASE_REG, 4, CC_SOC_OFFSET, 0); + if (rc) + pr_err("Failed to reset CC_SOC_REG rc=%d\n", + rc); + else if (fg_debug_mask & FG_STATUS) + pr_info("Reset SW_CC_SOC to %x\n", batt_soc); + } + + /* + * Schedule the update_temp_work whenever there is a status + * change. This is essential for applying the slope limiter + * coefficients when that feature is enabled. + */ + if (chip->last_temp_update_time && chip->soc_slope_limiter_en) { + cancel_delayed_work_sync(&chip->update_temp_work); + schedule_delayed_work(&chip->update_temp_work, + msecs_to_jiffies(0)); + } + + if (chip->dischg_gain.enable) { + fg_stay_awake(&chip->dischg_gain_wakeup_source); + schedule_work(&chip->dischg_gain_work); + } + + get_current_time(¤t_time); + /* + * When charging status changes, update SRAM parameters if it + * was not updated before 5 seconds from now. + */ + if (chip->last_sram_update_time + 5 < current_time) { + cancel_delayed_work(&chip->update_sram_data); + schedule_delayed_work(&chip->update_sram_data, + msecs_to_jiffies(0)); + } + + if (chip->cyc_ctr.en) + schedule_work(&chip->cycle_count_work); + + if ((chip->wa_flag & USE_CC_SOC_REG) && + chip->bad_batt_detection_en && + chip->status == POWER_SUPPLY_STATUS_CHARGING) { + chip->sw_cc_soc_data.init_sys_soc = capacity; + chip->sw_cc_soc_data.init_cc_soc = cc_soc; + if (fg_debug_mask & FG_STATUS) + pr_info(" Init_sys_soc %d init_cc_soc %d\n", + chip->sw_cc_soc_data.init_sys_soc, + chip->sw_cc_soc_data.init_cc_soc); + } + } + + if ((chip->wa_flag & USE_CC_SOC_REG) && chip->bad_batt_detection_en + && chip->safety_timer_expired) { + uint64_t delta_cc_soc = abs(cc_soc - + chip->sw_cc_soc_data.init_cc_soc); + chip->sw_cc_soc_data.delta_soc = DIV_ROUND_CLOSEST_ULL( + delta_cc_soc * 100, FULL_PERCENT_28BIT); + chip->sw_cc_soc_data.full_capacity = + chip->sw_cc_soc_data.delta_soc + + chip->sw_cc_soc_data.init_sys_soc; + pr_info("Init_sys_soc %d init_cc_soc %d cc_soc %d delta_soc %d full_capacity %d\n", + chip->sw_cc_soc_data.init_sys_soc, + chip->sw_cc_soc_data.init_cc_soc, cc_soc, + chip->sw_cc_soc_data.delta_soc, + chip->sw_cc_soc_data.full_capacity); + /* + * If sw_cc_soc capacity greater than 150, then it's a bad + * battery. else, reset timer and restart charging. + */ + if (chip->sw_cc_soc_data.full_capacity > + MAX_BATTERY_CC_SOC_CAPACITY) { + pr_info("Battery possibly damaged, do not restart charging\n"); + } else { + pr_info("Reset safety-timer and restart charging\n"); + rc = set_prop_enable_charging(chip, false); + if (rc) { + pr_err("failed to disable charging %d\n", rc); + return; + } + + chip->safety_timer_expired = false; + msleep(200); + + rc = set_prop_enable_charging(chip, true); + if (rc) { + pr_err("failed to enable charging %d\n", rc); + return; + } + } + } +} + +/* + * Check for change in the status of input or OTG and schedule + * IADC gain compensation work. + */ +static void check_gain_compensation(struct fg_chip *chip) +{ + bool input_present = is_input_present(chip); + bool otg_present = is_otg_present(chip); + + if ((chip->wa_flag & IADC_GAIN_COMP_WA) + && ((chip->input_present ^ input_present) + || (chip->otg_present ^ otg_present))) { + fg_stay_awake(&chip->gain_comp_wakeup_source); + chip->input_present = input_present; + chip->otg_present = otg_present; + cancel_work_sync(&chip->gain_comp_work); + schedule_work(&chip->gain_comp_work); + } +} + +static void fg_hysteresis_config(struct fg_chip *chip) +{ + int hard_hot = 0, hard_cold = 0; + + hard_hot = get_prop_jeita_temp(chip, FG_MEM_HARD_HOT); + hard_cold = get_prop_jeita_temp(chip, FG_MEM_HARD_COLD); + if (chip->health == POWER_SUPPLY_HEALTH_OVERHEAT && !chip->batt_hot) { + /* turn down the hard hot threshold */ + chip->batt_hot = true; + set_prop_jeita_temp(chip, FG_MEM_HARD_HOT, + hard_hot - chip->hot_hysteresis); + if (fg_debug_mask & FG_STATUS) + pr_info("hard hot hysteresis: old hot=%d, new hot=%d\n", + hard_hot, hard_hot - chip->hot_hysteresis); + } else if (chip->health == POWER_SUPPLY_HEALTH_COLD && + !chip->batt_cold) { + /* turn up the hard cold threshold */ + chip->batt_cold = true; + set_prop_jeita_temp(chip, FG_MEM_HARD_COLD, + hard_cold + chip->cold_hysteresis); + if (fg_debug_mask & FG_STATUS) + pr_info("hard cold hysteresis: old cold=%d, new cold=%d\n", + hard_cold, hard_cold + chip->hot_hysteresis); + } else if (chip->health != POWER_SUPPLY_HEALTH_OVERHEAT && + chip->batt_hot) { + /* restore the hard hot threshold */ + set_prop_jeita_temp(chip, FG_MEM_HARD_HOT, + hard_hot + chip->hot_hysteresis); + chip->batt_hot = !chip->batt_hot; + if (fg_debug_mask & FG_STATUS) + pr_info("restore hard hot threshold: old hot=%d, new hot=%d\n", + hard_hot, + hard_hot + chip->hot_hysteresis); + } else if (chip->health != POWER_SUPPLY_HEALTH_COLD && + chip->batt_cold) { + /* restore the hard cold threshold */ + set_prop_jeita_temp(chip, FG_MEM_HARD_COLD, + hard_cold - chip->cold_hysteresis); + chip->batt_cold = !chip->batt_cold; + if (fg_debug_mask & FG_STATUS) + pr_info("restore hard cold threshold: old cold=%d, new cold=%d\n", + hard_cold, + hard_cold - chip->cold_hysteresis); + } +} + +#define BATT_INFO_STS(base) (base + 0x09) +#define JEITA_HARD_HOT_RT_STS BIT(6) +#define JEITA_HARD_COLD_RT_STS BIT(5) +static int fg_init_batt_temp_state(struct fg_chip *chip) +{ + int rc = 0; + u8 batt_info_sts; + int hard_hot = 0, hard_cold = 0; + + /* + * read the batt_info_sts register to parse battery's + * initial status and do hysteresis config accordingly. + */ + rc = fg_read(chip, &batt_info_sts, + BATT_INFO_STS(chip->batt_base), 1); + if (rc) { + pr_err("failed to read batt info sts, rc=%d\n", rc); + return rc; + } + + hard_hot = get_prop_jeita_temp(chip, FG_MEM_HARD_HOT); + hard_cold = get_prop_jeita_temp(chip, FG_MEM_HARD_COLD); + chip->batt_hot = + (batt_info_sts & JEITA_HARD_HOT_RT_STS) ? true : false; + chip->batt_cold = + (batt_info_sts & JEITA_HARD_COLD_RT_STS) ? true : false; + if (chip->batt_hot || chip->batt_cold) { + if (chip->batt_hot) { + chip->health = POWER_SUPPLY_HEALTH_OVERHEAT; + set_prop_jeita_temp(chip, FG_MEM_HARD_HOT, + hard_hot - chip->hot_hysteresis); + } else { + chip->health = POWER_SUPPLY_HEALTH_COLD; + set_prop_jeita_temp(chip, FG_MEM_HARD_COLD, + hard_cold + chip->cold_hysteresis); + } + } + + return rc; +} + +static int fg_restore_cc_soc(struct fg_chip *chip) +{ + int rc; + + if (!chip->use_last_cc_soc || !chip->last_cc_soc) + return 0; + + if (fg_debug_mask & FG_STATUS) + pr_info("Restoring cc_soc: %lld\n", chip->last_cc_soc); + + rc = fg_mem_write(chip, (u8 *)&chip->last_cc_soc, + fg_data[FG_DATA_CC_CHARGE].address, 4, + fg_data[FG_DATA_CC_CHARGE].offset, 0); + if (rc) + pr_err("failed to update CC_SOC rc=%d\n", rc); + else + chip->use_last_cc_soc = false; + + return rc; +} + +#define SRAM_MONOTONIC_SOC_REG 0x574 +#define SRAM_MONOTONIC_SOC_OFFSET 2 +static int fg_restore_soc(struct fg_chip *chip) +{ + int rc; + u16 msoc; + + if (chip->use_last_soc && chip->last_soc) + msoc = DIV_ROUND_CLOSEST(chip->last_soc * 0xFFFF, + FULL_SOC_RAW); + else + return 0; + + if (fg_debug_mask & FG_STATUS) + pr_info("Restored soc: %d\n", msoc); + + rc = fg_mem_write(chip, (u8 *)&msoc, SRAM_MONOTONIC_SOC_REG, 2, + SRAM_MONOTONIC_SOC_OFFSET, 0); + if (rc) + pr_err("failed to write M_SOC_REG rc=%d\n", rc); + + return rc; +} + +#define NOM_CAP_REG 0x4F4 +#define CAPACITY_DELTA_DECIPCT 500 +static int load_battery_aging_data(struct fg_chip *chip) +{ + int rc = 0; + u8 buffer[2]; + int16_t cc_mah; + int64_t delta_cc_uah, pct_nom_cap_uah; + + rc = fg_mem_read(chip, buffer, NOM_CAP_REG, 2, 0, 0); + if (rc) { + pr_err("Failed to read nominal capacitance: %d\n", rc); + goto out; + } + + chip->nom_cap_uah = bcap_uah_2b(buffer); + chip->actual_cap_uah = chip->nom_cap_uah; + + if (chip->learning_data.learned_cc_uah == 0) { + chip->learning_data.learned_cc_uah = chip->nom_cap_uah; + fg_cap_learning_save_data(chip); + } else if (chip->learning_data.feedback_on) { + delta_cc_uah = abs(chip->learning_data.learned_cc_uah - + chip->nom_cap_uah); + pct_nom_cap_uah = div64_s64((int64_t)chip->nom_cap_uah * + CAPACITY_DELTA_DECIPCT, 1000); + /* + * If the learned capacity is out of range, say by 50% + * from the nominal capacity, then overwrite the learned + * capacity with the nominal capacity. + */ + if (chip->nom_cap_uah && delta_cc_uah > pct_nom_cap_uah) { + if (fg_debug_mask & FG_AGING) { + pr_info("learned_cc_uah: %lld is higher than expected\n", + chip->learning_data.learned_cc_uah); + pr_info("Capping it to nominal:%d\n", + chip->nom_cap_uah); + } + chip->learning_data.learned_cc_uah = chip->nom_cap_uah; + fg_cap_learning_save_data(chip); + } else { + cc_mah = div64_s64(chip->learning_data.learned_cc_uah, + 1000); + rc = fg_calc_and_store_cc_soc_coeff(chip, cc_mah); + if (rc) + pr_err("Error in restoring cc_soc_coeff, rc:%d\n", + rc); + } + } +out: + return rc; +} + +static void fg_restore_battery_info(struct fg_chip *chip) +{ + int rc; + char buf[4] = {0, 0, 0, 0}; + + chip->last_soc = DIV_ROUND_CLOSEST(chip->batt_info[BATT_INFO_SOC] * + FULL_SOC_RAW, FULL_CAPACITY); + chip->last_cc_soc = div64_s64((int64_t)chip->last_soc * + FULL_PERCENT_28BIT, FULL_SOC_RAW); + chip->use_last_soc = true; + chip->use_last_cc_soc = true; + rc = fg_restore_soc(chip); + if (rc) { + pr_err("Error in restoring soc, rc=%d\n", rc); + goto out; + } + + rc = fg_restore_cc_soc(chip); + if (rc) { + pr_err("Error in restoring cc_soc, rc=%d\n", rc); + goto out; + } + + rc = fg_mem_write(chip, buf, + fg_data[FG_DATA_VINT_ERR].address, + fg_data[FG_DATA_VINT_ERR].len, + fg_data[FG_DATA_VINT_ERR].offset, 0); + if (rc) { + pr_err("Failed to write to VINT_ERR, rc=%d\n", rc); + goto out; + } + + chip->learning_data.learned_cc_uah = chip->batt_info[BATT_INFO_FCC]; + rc = load_battery_aging_data(chip); + if (rc) { + pr_err("Failed to load battery aging data, rc:%d\n", rc); + goto out; + } + + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + + if (fg_debug_mask & FG_STATUS) + pr_info("Restored battery info!\n"); + +out: + return; +} + +#define DELTA_BATT_TEMP 30 +static bool fg_validate_battery_info(struct fg_chip *chip) +{ + int i, delta_pct, batt_id_kohm, batt_temp, batt_volt_mv, batt_soc; + + for (i = 1; i < BATT_INFO_MAX; i++) { + if (fg_debug_mask & FG_STATUS) + pr_info("batt_info[%d]: %d\n", i, chip->batt_info[i]); + + if ((chip->batt_info[i] == 0 && i != BATT_INFO_TEMP) || + chip->batt_info[i] == INT_MAX) { + if (fg_debug_mask & FG_STATUS) + pr_info("batt_info[%d]:%d is invalid\n", i, + chip->batt_info[i]); + return false; + } + } + + batt_id_kohm = get_sram_prop_now(chip, FG_DATA_BATT_ID) / 1000; + if (batt_id_kohm != chip->batt_info[BATT_INFO_RES_ID]) { + if (fg_debug_mask & FG_STATUS) + pr_info("batt_id(%dK) does not match the stored batt_id(%dK)\n", + batt_id_kohm, + chip->batt_info[BATT_INFO_RES_ID]); + return false; + } + + batt_temp = get_sram_prop_now(chip, FG_DATA_BATT_TEMP); + if (abs(chip->batt_info[BATT_INFO_TEMP] - batt_temp) > + DELTA_BATT_TEMP) { + if (fg_debug_mask & FG_STATUS) + pr_info("batt_temp(%d) is higher/lower than stored batt_temp(%d)\n", + batt_temp, chip->batt_info[BATT_INFO_TEMP]); + return false; + } + + if (chip->batt_info[BATT_INFO_FCC] < 0) { + if (fg_debug_mask & FG_STATUS) + pr_info("batt_fcc cannot be %d\n", + chip->batt_info[BATT_INFO_FCC]); + return false; + } + + batt_volt_mv = get_sram_prop_now(chip, FG_DATA_VOLTAGE) / 1000; + batt_soc = get_monotonic_soc_raw(chip); + if (batt_soc != 0 && batt_soc != FULL_SOC_RAW) + batt_soc = DIV_ROUND_CLOSEST((batt_soc - 1) * + (FULL_CAPACITY - 2), FULL_SOC_RAW - 2) + 1; + if (batt_soc == FULL_SOC_RAW) + chip->batt_info[BATT_INFO_SOC] = 100; + + if (*chip->batt_range_ocv && chip->batt_max_voltage_uv > 1000) + delta_pct = DIV_ROUND_CLOSEST(abs(batt_volt_mv - + chip->batt_info[BATT_INFO_VOLTAGE]) * 100, + chip->batt_max_voltage_uv / 1000); + else + delta_pct = abs(batt_soc - chip->batt_info[BATT_INFO_SOC]); + + if (fg_debug_mask & FG_STATUS) + pr_info("Validating by %s batt_voltage:%d capacity:%d delta_pct:%d\n", + *chip->batt_range_ocv ? "OCV" : "SOC", batt_volt_mv, + batt_soc, delta_pct); + + if (*chip->batt_range_pct && delta_pct > *chip->batt_range_pct) { + if (fg_debug_mask & FG_STATUS) + pr_info("delta_pct(%d) is higher than batt_range_pct(%d)\n", + delta_pct, *chip->batt_range_pct); + return false; + } + + return true; +} + +static int fg_set_battery_info(struct fg_chip *chip, int val) +{ + if (chip->batt_info_id < 0 || + chip->batt_info_id >= BATT_INFO_MAX) { + pr_err("Invalid batt_info_id %d\n", chip->batt_info_id); + chip->batt_info_id = 0; + return -EINVAL; + } + + if (chip->batt_info_id == BATT_INFO_NOTIFY && val == INT_MAX - 1) { + if (fg_debug_mask & FG_STATUS) + pr_info("Notified from userspace\n"); + if (chip->batt_info_restore && !chip->ima_error_handling) { + if (!fg_validate_battery_info(chip)) { + if (fg_debug_mask & FG_STATUS) + pr_info("Validating battery info failed\n"); + } else { + fg_restore_battery_info(chip); + } + } + } + + chip->batt_info[chip->batt_info_id] = val; + return 0; +} + +static enum power_supply_property fg_power_props[] = { + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CAPACITY_RAW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_OCV, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_NOW_RAW, + POWER_SUPPLY_PROP_CHARGE_NOW_ERROR, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_COOL_TEMP, + POWER_SUPPLY_PROP_WARM_TEMP, + POWER_SUPPLY_PROP_RESISTANCE, + POWER_SUPPLY_PROP_RESISTANCE_ID, + POWER_SUPPLY_PROP_BATTERY_TYPE, + POWER_SUPPLY_PROP_DUMP_SRAM, + POWER_SUPPLY_PROP_UPDATE_NOW, + POWER_SUPPLY_PROP_ESR_COUNT, + POWER_SUPPLY_PROP_VOLTAGE_MIN, + POWER_SUPPLY_PROP_CYCLE_COUNT, + POWER_SUPPLY_PROP_CYCLE_COUNT_ID, + POWER_SUPPLY_PROP_HI_POWER, + POWER_SUPPLY_PROP_SOC_REPORTING_READY, + POWER_SUPPLY_PROP_IGNORE_FALSE_NEGATIVE_ISENSE, + POWER_SUPPLY_PROP_ENABLE_JEITA_DETECTION, + POWER_SUPPLY_PROP_BATTERY_INFO, + POWER_SUPPLY_PROP_BATTERY_INFO_ID, +}; + +static int fg_power_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct fg_chip *chip = container_of(psy, struct fg_chip, bms_psy); + bool vbatt_low_sts; + + switch (psp) { + case POWER_SUPPLY_PROP_BATTERY_TYPE: + if (chip->battery_missing) + val->strval = missing_batt_type; + else if (chip->fg_restarting) + val->strval = loading_batt_type; + else + val->strval = chip->batt_type; + break; + case POWER_SUPPLY_PROP_DUMP_SRAM: + val->strval = chip->debug_dump; + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_prop_capacity(chip); + break; + case POWER_SUPPLY_PROP_CAPACITY_RAW: + val->intval = get_sram_prop_now(chip, FG_DATA_BATT_SOC); + break; + case POWER_SUPPLY_PROP_CHARGE_NOW_ERROR: + val->intval = get_sram_prop_now(chip, FG_DATA_VINT_ERR); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = get_sram_prop_now(chip, FG_DATA_CURRENT); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_sram_prop_now(chip, FG_DATA_VOLTAGE); + break; + case POWER_SUPPLY_PROP_VOLTAGE_OCV: + val->intval = get_sram_prop_now(chip, FG_DATA_OCV); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = chip->batt_max_voltage_uv; + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = get_sram_prop_now(chip, FG_DATA_BATT_TEMP); + break; + case POWER_SUPPLY_PROP_COOL_TEMP: + val->intval = get_prop_jeita_temp(chip, FG_MEM_SOFT_COLD); + break; + case POWER_SUPPLY_PROP_WARM_TEMP: + val->intval = get_prop_jeita_temp(chip, FG_MEM_SOFT_HOT); + break; + case POWER_SUPPLY_PROP_RESISTANCE: + val->intval = get_sram_prop_now(chip, FG_DATA_BATT_ESR); + break; + case POWER_SUPPLY_PROP_ESR_COUNT: + val->intval = get_sram_prop_now(chip, FG_DATA_BATT_ESR_COUNT); + break; + case POWER_SUPPLY_PROP_CYCLE_COUNT: + val->intval = fg_get_cycle_count(chip); + break; + case POWER_SUPPLY_PROP_CYCLE_COUNT_ID: + val->intval = chip->cyc_ctr.id; + break; + case POWER_SUPPLY_PROP_RESISTANCE_ID: + val->intval = get_sram_prop_now(chip, FG_DATA_BATT_ID); + break; + case POWER_SUPPLY_PROP_UPDATE_NOW: + val->intval = 0; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN: + if (!fg_get_vbatt_status(chip, &vbatt_low_sts)) + val->intval = (int)vbatt_low_sts; + else + val->intval = 1; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + val->intval = chip->nom_cap_uah; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + val->intval = chip->learning_data.learned_cc_uah; + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + val->intval = chip->learning_data.cc_uah; + break; + case POWER_SUPPLY_PROP_CHARGE_NOW_RAW: + val->intval = get_sram_prop_now(chip, FG_DATA_CC_CHARGE); + break; + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + val->intval = fg_get_current_cc(chip); + break; + case POWER_SUPPLY_PROP_HI_POWER: + val->intval = !!chip->bcl_lpm_disabled; + break; + case POWER_SUPPLY_PROP_SOC_REPORTING_READY: + val->intval = !!chip->soc_reporting_ready; + break; + case POWER_SUPPLY_PROP_IGNORE_FALSE_NEGATIVE_ISENSE: + val->intval = !chip->allow_false_negative_isense; + break; + case POWER_SUPPLY_PROP_ENABLE_JEITA_DETECTION: + val->intval = chip->use_soft_jeita_irq; + break; + case POWER_SUPPLY_PROP_BATTERY_INFO: + if (chip->batt_info_id < 0 || + chip->batt_info_id >= BATT_INFO_MAX) + return -EINVAL; + val->intval = chip->batt_info[chip->batt_info_id]; + break; + case POWER_SUPPLY_PROP_BATTERY_INFO_ID: + val->intval = chip->batt_info_id; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int fg_power_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct fg_chip *chip = container_of(psy, struct fg_chip, bms_psy); + int rc = 0, unused; + + switch (psp) { + case POWER_SUPPLY_PROP_COOL_TEMP: + rc = set_prop_jeita_temp(chip, FG_MEM_SOFT_COLD, val->intval); + break; + case POWER_SUPPLY_PROP_WARM_TEMP: + rc = set_prop_jeita_temp(chip, FG_MEM_SOFT_HOT, val->intval); + break; + case POWER_SUPPLY_PROP_DUMP_SRAM: + dump_debug(&chip->dump_sram); + break; + case POWER_SUPPLY_PROP_UPDATE_NOW: + if (val->intval) + update_sram_data(chip, &unused); + break; + case POWER_SUPPLY_PROP_IGNORE_FALSE_NEGATIVE_ISENSE: + rc = set_prop_ignore_false_negative_isense(chip, !!val->intval); + if (rc) + pr_err("set_prop_ignore_false_negative_isense failed, rc=%d\n", + rc); + else + chip->allow_false_negative_isense = !val->intval; + break; + case POWER_SUPPLY_PROP_ENABLE_JEITA_DETECTION: + if (chip->use_soft_jeita_irq == !!val->intval) { + pr_debug("JEITA irq %s, ignore!\n", + chip->use_soft_jeita_irq ? + "enabled" : "disabled"); + break; + } + chip->use_soft_jeita_irq = !!val->intval; + if (chip->use_soft_jeita_irq) { + if (chip->batt_irq[JEITA_SOFT_COLD].disabled) { + enable_irq( + chip->batt_irq[JEITA_SOFT_COLD].irq); + chip->batt_irq[JEITA_SOFT_COLD].disabled = + false; + } + if (!chip->batt_irq[JEITA_SOFT_COLD].wakeup) { + enable_irq_wake( + chip->batt_irq[JEITA_SOFT_COLD].irq); + chip->batt_irq[JEITA_SOFT_COLD].wakeup = true; + } + if (chip->batt_irq[JEITA_SOFT_HOT].disabled) { + enable_irq( + chip->batt_irq[JEITA_SOFT_HOT].irq); + chip->batt_irq[JEITA_SOFT_HOT].disabled = false; + } + if (!chip->batt_irq[JEITA_SOFT_HOT].wakeup) { + enable_irq_wake( + chip->batt_irq[JEITA_SOFT_HOT].irq); + chip->batt_irq[JEITA_SOFT_HOT].wakeup = true; + } + } else { + if (chip->batt_irq[JEITA_SOFT_COLD].wakeup) { + disable_irq_wake( + chip->batt_irq[JEITA_SOFT_COLD].irq); + chip->batt_irq[JEITA_SOFT_COLD].wakeup = false; + } + if (!chip->batt_irq[JEITA_SOFT_COLD].disabled) { + disable_irq_nosync( + chip->batt_irq[JEITA_SOFT_COLD].irq); + chip->batt_irq[JEITA_SOFT_COLD].disabled = true; + } + if (chip->batt_irq[JEITA_SOFT_HOT].wakeup) { + disable_irq_wake( + chip->batt_irq[JEITA_SOFT_HOT].irq); + chip->batt_irq[JEITA_SOFT_HOT].wakeup = false; + } + if (!chip->batt_irq[JEITA_SOFT_HOT].disabled) { + disable_irq_nosync( + chip->batt_irq[JEITA_SOFT_HOT].irq); + chip->batt_irq[JEITA_SOFT_HOT].disabled = true; + } + } + break; + case POWER_SUPPLY_PROP_STATUS: + chip->prev_status = chip->status; + chip->status = val->intval; + schedule_work(&chip->status_change_work); + check_gain_compensation(chip); + break; + case POWER_SUPPLY_PROP_HEALTH: + chip->health = val->intval; + if (chip->health == POWER_SUPPLY_HEALTH_GOOD) { + fg_stay_awake(&chip->resume_soc_wakeup_source); + schedule_work(&chip->set_resume_soc_work); + } + + if (chip->jeita_hysteresis_support) + fg_hysteresis_config(chip); + break; + case POWER_SUPPLY_PROP_CHARGE_DONE: + chip->charge_done = val->intval; + if (!chip->resume_soc_lowered) { + fg_stay_awake(&chip->resume_soc_wakeup_source); + schedule_work(&chip->set_resume_soc_work); + } + break; + case POWER_SUPPLY_PROP_CYCLE_COUNT_ID: + if ((val->intval > 0) && (val->intval <= BUCKET_COUNT)) { + chip->cyc_ctr.id = val->intval; + } else { + pr_err("rejecting invalid cycle_count_id = %d\n", + val->intval); + rc = -EINVAL; + } + break; + case POWER_SUPPLY_PROP_SAFETY_TIMER_EXPIRED: + chip->safety_timer_expired = val->intval; + schedule_work(&chip->status_change_work); + break; + case POWER_SUPPLY_PROP_HI_POWER: + if (chip->wa_flag & BCL_HI_POWER_FOR_CHGLED_WA) { + chip->bcl_lpm_disabled = !!val->intval; + schedule_work(&chip->bcl_hi_power_work); + } + break; + case POWER_SUPPLY_PROP_BATTERY_INFO: + rc = fg_set_battery_info(chip, val->intval); + break; + case POWER_SUPPLY_PROP_BATTERY_INFO_ID: + chip->batt_info_id = val->intval; + break; + default: + return -EINVAL; + }; + + return rc; +}; + +static int fg_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_COOL_TEMP: + case POWER_SUPPLY_PROP_WARM_TEMP: + case POWER_SUPPLY_PROP_DUMP_SRAM: + case POWER_SUPPLY_PROP_CYCLE_COUNT_ID: + case POWER_SUPPLY_PROP_BATTERY_INFO: + case POWER_SUPPLY_PROP_BATTERY_INFO_ID: + return 1; + default: + break; + } + + return 0; +} + +#define SRAM_DUMP_START 0x400 +#define SRAM_DUMP_LEN 0x200 +static void dump_debug(struct work_struct *work) +{ + int i, rc, pos = 0; + u8 *buffer, rt_sts; + char str[16]; + + struct fg_chip *chip = container_of(work, + struct fg_chip, + dump_sram); + + buffer = devm_kzalloc(chip->dev, SRAM_DUMP_LEN, GFP_KERNEL); + memset(buffer, 0, SRAM_DUMP_LEN); + + if (buffer == NULL) { + pr_err("Can't allocate buffer\n"); + return; + } + + rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->soc_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + else + pos += sprintf(chip->debug_dump + pos, "soc-rt-sts: 0x%0x ", rt_sts); + + pos -= 1; + rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->batt_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + else + pos += sprintf(chip->debug_dump + pos, "batt-rt-sts: 0x%0x ", rt_sts); + + pos -= 1; + rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->mem_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->mem_base), rc); + else + pos += sprintf(chip->debug_dump + pos, "memif rt-sts: 0x%0x ", rt_sts); + + rc = fg_mem_read(chip, buffer, SRAM_DUMP_START, SRAM_DUMP_LEN, 0, 0); + if (rc) { + pr_err("dump failed: rc = %d\n", rc); + return; + } + + for (i = 0; i < SRAM_DUMP_LEN; i += 4) { + pos -= 1; + str[0] = '\0'; + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, buffer + i, 4); + pos += sprintf((chip->debug_dump + pos), "addr:%03x:%s ", SRAM_DUMP_START + i, str); + } + + devm_kfree(chip->dev, buffer); +} + +static void dump_sram(struct work_struct *work) +{ + int i, rc; + u8 *buffer, rt_sts; + char str[16]; + struct fg_chip *chip = container_of(work, + struct fg_chip, + dump_sram); + + buffer = devm_kzalloc(chip->dev, SRAM_DUMP_LEN, GFP_KERNEL); + if (buffer == NULL) { + pr_err("Can't allocate buffer\n"); + return; + } + + rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->soc_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + else + pr_info("soc rt_sts: 0x%x\n", rt_sts); + + rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->batt_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + else + pr_info("batt rt_sts: 0x%x\n", rt_sts); + + rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->mem_base), 1); + if (rc) + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->mem_base), rc); + else + pr_info("memif rt_sts: 0x%x\n", rt_sts); + + rc = fg_mem_read(chip, buffer, SRAM_DUMP_START, SRAM_DUMP_LEN, 0, 0); + if (rc) { + pr_err("dump failed: rc = %d\n", rc); + return; + } + + for (i = 0; i < SRAM_DUMP_LEN; i += 4) { + str[0] = '\0'; + fill_string(str, DEBUG_PRINT_BUFFER_SIZE, buffer + i, 4); + pr_info("%03X %s\n", SRAM_DUMP_START + i, str); + } + devm_kfree(chip->dev, buffer); +} + +#define MAXRSCHANGE_REG 0x434 +#define ESR_VALUE_OFFSET 1 +#define ESR_STRICT_VALUE 0x4120391F391F3019 +#define ESR_DEFAULT_VALUE 0x58CD4A6761C34A67 +static void update_esr_value(struct work_struct *work) +{ + union power_supply_propval prop = {0, }; + u64 esr_value; + int rc = 0; + struct fg_chip *chip = container_of(work, + struct fg_chip, + update_esr_work); + + if (!is_charger_available(chip)) + return; + + chip->batt_psy->get_property(chip->batt_psy, + POWER_SUPPLY_PROP_CHARGE_TYPE, &prop); + + if (!chip->esr_strict_filter) { + if ((prop.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER && + chip->status == POWER_SUPPLY_STATUS_CHARGING) || + (chip->status == POWER_SUPPLY_STATUS_FULL)) { + esr_value = ESR_STRICT_VALUE; + rc = fg_mem_write(chip, (u8 *)&esr_value, + MAXRSCHANGE_REG, 8, + ESR_VALUE_OFFSET, 0); + if (rc) + pr_err("failed to write strict ESR value rc=%d\n", + rc); + else + chip->esr_strict_filter = true; + } + } else if ((prop.intval != POWER_SUPPLY_CHARGE_TYPE_TAPER && + chip->status == POWER_SUPPLY_STATUS_CHARGING) || + (chip->status == POWER_SUPPLY_STATUS_DISCHARGING)) { + esr_value = ESR_DEFAULT_VALUE; + rc = fg_mem_write(chip, (u8 *)&esr_value, MAXRSCHANGE_REG, 8, + ESR_VALUE_OFFSET, 0); + if (rc) + pr_err("failed to write default ESR value rc=%d\n", rc); + else + chip->esr_strict_filter = false; + } +} + +#define TEMP_COUNTER_REG 0x580 +#define VBAT_FILTERED_OFFSET 1 +#define GAIN_REG 0x424 +#define GAIN_OFFSET 1 +#define K_VCOR_REG 0x484 +#define DEF_GAIN_OFFSET 2 +#define PICO_UNIT 0xE8D4A51000LL +#define ATTO_UNIT 0xDE0B6B3A7640000LL +#define VBAT_REF 3800000 + +/* + * IADC Gain compensation steps: + * If Input/OTG absent: + * - read VBAT_FILTERED, KVCOR, GAIN + * - calculate the gain compensation using following formula: + * gain = (1 + gain) * (1 + kvcor * (vbat_filtered - 3800000)) - 1; + * else + * - reset to the default gain compensation + */ +static void iadc_gain_comp_work(struct work_struct *work) +{ + u8 reg[4]; + int rc; + uint64_t vbat_filtered; + int64_t gain, kvcor, temp, numerator; + struct fg_chip *chip = container_of(work, struct fg_chip, + gain_comp_work); + bool input_present = is_input_present(chip); + bool otg_present = is_otg_present(chip); + + if (!chip->init_done) + goto done; + + if (!input_present && !otg_present) { + /* read VBAT_FILTERED */ + rc = fg_mem_read(chip, reg, TEMP_COUNTER_REG, 3, + VBAT_FILTERED_OFFSET, 0); + if (rc) { + pr_err("Failed to read VBAT: rc=%d\n", rc); + goto done; + } + temp = (reg[2] << 16) | (reg[1] << 8) | reg[0]; + vbat_filtered = div_u64((u64)temp * LSB_24B_NUMRTR, + LSB_24B_DENMTR); + + /* read K_VCOR */ + rc = fg_mem_read(chip, reg, K_VCOR_REG, 2, 0, 0); + if (rc) { + pr_err("Failed to KVCOR rc=%d\n", rc); + goto done; + } + kvcor = half_float(reg); + + /* calculate gain */ + numerator = (MICRO_UNIT + chip->iadc_comp_data.dfl_gain) + * (PICO_UNIT + kvcor * (vbat_filtered - VBAT_REF)) + - ATTO_UNIT; + gain = div64_s64(numerator, PICO_UNIT); + + /* write back gain */ + half_float_to_buffer(gain, reg); + rc = fg_mem_write(chip, reg, GAIN_REG, 2, GAIN_OFFSET, 0); + if (rc) { + pr_err("Failed to write gain reg rc=%d\n", rc); + goto done; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("IADC gain update [%x %x]\n", reg[1], reg[0]); + chip->iadc_comp_data.gain_active = true; + } else { + /* reset gain register */ + rc = fg_mem_write(chip, chip->iadc_comp_data.dfl_gain_reg, + GAIN_REG, 2, GAIN_OFFSET, 0); + if (rc) { + pr_err("unable to write gain comp: %d\n", rc); + goto done; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("IADC gain reset [%x %x]\n", + chip->iadc_comp_data.dfl_gain_reg[1], + chip->iadc_comp_data.dfl_gain_reg[0]); + chip->iadc_comp_data.gain_active = false; + } + +done: + fg_relax(&chip->gain_comp_wakeup_source); +} + +static void cc_soc_store_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, struct fg_chip, + cc_soc_store_work); + int cc_soc_pct; + + if (!chip->nom_cap_uah) { + pr_err("nom_cap_uah zero!\n"); + fg_relax(&chip->cc_soc_wakeup_source); + return; + } + + cc_soc_pct = get_sram_prop_now(chip, FG_DATA_CC_CHARGE); + cc_soc_pct = div64_s64(cc_soc_pct * 100, + chip->nom_cap_uah); + chip->last_cc_soc = div64_s64((int64_t)chip->last_soc * + FULL_PERCENT_28BIT, FULL_SOC_RAW); + + if (fg_debug_mask & FG_STATUS) + pr_info("cc_soc_pct: %d last_cc_soc: %lld\n", cc_soc_pct, + chip->last_cc_soc); + + if (fg_reset_on_lockup && (chip->cc_soc_limit_pct > 0 && + cc_soc_pct >= chip->cc_soc_limit_pct)) { + pr_err("CC_SOC out of range\n"); + fg_check_ima_error_handling(chip); + } + + fg_relax(&chip->cc_soc_wakeup_source); +} + +#define HARD_JEITA_ALARM_CHECK_NS 10000000000 +static enum alarmtimer_restart fg_hard_jeita_alarm_cb(struct alarm *alarm, + ktime_t now) +{ + struct fg_chip *chip = container_of(alarm, + struct fg_chip, hard_jeita_alarm); + int rc, health = POWER_SUPPLY_HEALTH_UNKNOWN; + u8 regval; + bool batt_hot, batt_cold; + union power_supply_propval val = {0, }; + + if (!is_usb_present(chip)) { + pr_debug("USB plugged out, stop the timer!\n"); + return ALARMTIMER_NORESTART; + } + + rc = fg_read(chip, ®val, BATT_INFO_STS(chip->batt_base), 1); + if (rc) { + pr_err("read batt_sts failed, rc=%d\n", rc); + goto recheck; + } + + batt_hot = !!(regval & JEITA_HARD_HOT_RT_STS); + batt_cold = !!(regval & JEITA_HARD_COLD_RT_STS); + if (batt_hot && batt_cold) { + pr_debug("Hot && cold can't co-exist\n"); + goto recheck; + } + + if ((batt_hot == chip->batt_hot) && (batt_cold == chip->batt_cold)) { + pr_debug("battery JEITA state not changed, ignore\n"); + goto recheck; + } + + if (batt_cold != chip->batt_cold) { + /* cool --> cold */ + if (chip->batt_cool) { + chip->batt_cool = false; + chip->batt_cold = true; + health = POWER_SUPPLY_HEALTH_COLD; + } else if (chip->batt_cold) { /* cold --> cool */ + chip->batt_cool = true; + chip->batt_cold = false; + health = POWER_SUPPLY_HEALTH_COOL; + } + } + + if (batt_hot != chip->batt_hot) { + /* warm --> hot */ + if (chip->batt_warm) { + chip->batt_warm = false; + chip->batt_hot = true; + health = POWER_SUPPLY_HEALTH_OVERHEAT; + } else if (chip->batt_hot) { /* hot --> warm */ + chip->batt_hot = false; + chip->batt_warm = true; + health = POWER_SUPPLY_HEALTH_WARM; + } + } + + if (health != POWER_SUPPLY_HEALTH_UNKNOWN) { + pr_debug("FG report battery health: %d\n", health); + val.intval = health; + rc = chip->batt_psy->set_property(chip->batt_psy, + POWER_SUPPLY_PROP_HEALTH, &val); + if (rc) + pr_err("Set batt_psy health: %d failed\n", health); + } + +recheck: + alarm_forward_now(alarm, ns_to_ktime(HARD_JEITA_ALARM_CHECK_NS)); + return ALARMTIMER_RESTART; +} + +#define BATT_SOFT_COLD_STS BIT(0) +#define BATT_SOFT_HOT_STS BIT(1) +static irqreturn_t fg_jeita_soft_hot_irq_handler(int irq, void *_chip) +{ + int rc; + struct fg_chip *chip = _chip; + u8 regval; + bool batt_warm; + union power_supply_propval val = {0, }; + + if (!is_charger_available(chip)) + return IRQ_HANDLED; + + rc = fg_read(chip, ®val, INT_RT_STS(chip->batt_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + return IRQ_HANDLED; + } + + batt_warm = !!(regval & BATT_SOFT_HOT_STS); + if (chip->batt_warm == batt_warm) { + pr_debug("warm state not change, ignore!\n"); + return IRQ_HANDLED; + } + + chip->batt_warm = batt_warm; + if (batt_warm) { + val.intval = POWER_SUPPLY_HEALTH_WARM; + chip->batt_psy->set_property(chip->batt_psy, + POWER_SUPPLY_PROP_HEALTH, &val); + /* kick the alarm timer for hard hot polling */ + rc = alarm_start_relative(&chip->hard_jeita_alarm, + ns_to_ktime(HARD_JEITA_ALARM_CHECK_NS)); + if (rc) + pr_err("start alarm for hard HOT detection failed, rc=%d\n", + rc); + } else { + val.intval = POWER_SUPPLY_HEALTH_GOOD; + chip->batt_psy->set_property(chip->batt_psy, + POWER_SUPPLY_PROP_HEALTH, &val); + /* cancel the alarm timer */ + alarm_try_to_cancel(&chip->hard_jeita_alarm); + } + + return IRQ_HANDLED; +} + +static irqreturn_t fg_jeita_soft_cold_irq_handler(int irq, void *_chip) +{ + int rc; + struct fg_chip *chip = _chip; + u8 regval; + bool batt_cool; + union power_supply_propval val = {0, }; + + if (!is_charger_available(chip)) + return IRQ_HANDLED; + + rc = fg_read(chip, ®val, INT_RT_STS(chip->batt_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->batt_base), rc); + return IRQ_HANDLED; + } + + batt_cool = !!(regval & BATT_SOFT_COLD_STS); + if (chip->batt_cool == batt_cool) { + pr_debug("cool state not change, ignore\n"); + return IRQ_HANDLED; + } + + chip->batt_cool = batt_cool; + if (batt_cool) { + val.intval = POWER_SUPPLY_HEALTH_COOL; + chip->batt_psy->set_property(chip->batt_psy, + POWER_SUPPLY_PROP_HEALTH, &val); + /* kick the alarm timer for hard cold polling */ + rc = alarm_start_relative(&chip->hard_jeita_alarm, + ns_to_ktime(HARD_JEITA_ALARM_CHECK_NS)); + if (rc) + pr_err("start alarm for hard COLD detection failed, rc=%d\n", + rc); + } else { + val.intval = POWER_SUPPLY_HEALTH_GOOD; + chip->batt_psy->set_property(chip->batt_psy, + POWER_SUPPLY_PROP_HEALTH, &val); + /* cancel the alarm timer */ + alarm_try_to_cancel(&chip->hard_jeita_alarm); + } + + return IRQ_HANDLED; +} + +#define SOC_FIRST_EST_DONE BIT(5) +static bool is_first_est_done(struct fg_chip *chip) +{ + int rc; + u8 fg_soc_sts; + + rc = fg_read(chip, &fg_soc_sts, + INT_RT_STS(chip->soc_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + return false; + } + + return (fg_soc_sts & SOC_FIRST_EST_DONE) ? true : false; +} + +#define FG_EMPTY_DEBOUNCE_MS 1500 +static irqreturn_t fg_vbatt_low_handler(int irq, void *_chip) +{ + struct fg_chip *chip = _chip; + bool vbatt_low_sts; + + if (fg_debug_mask & FG_IRQS) + pr_info("vbatt-low triggered\n"); + + /* handle empty soc based on vbatt-low interrupt */ + if (chip->use_vbat_low_empty_soc) { + if (fg_get_vbatt_status(chip, &vbatt_low_sts)) + goto out; + + if (vbatt_low_sts) { + if (fg_debug_mask & FG_IRQS) + pr_info("Vbatt is low\n"); + disable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + disable_irq_nosync(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = false; + fg_stay_awake(&chip->empty_check_wakeup_source); + schedule_delayed_work(&chip->check_empty_work, + msecs_to_jiffies(FG_EMPTY_DEBOUNCE_MS)); + } else { + if (fg_debug_mask & FG_IRQS) + pr_info("Vbatt is high\n"); + chip->soc_empty = false; + } + goto out; + } + + if (chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (fg_get_vbatt_status(chip, &vbatt_low_sts)) + goto out; + if (!vbatt_low_sts && chip->vbat_low_irq_enabled) { + if (fg_debug_mask & FG_IRQS) + pr_info("disabling vbatt_low irq\n"); + disable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + disable_irq_nosync(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = false; + } + } + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); +out: + return IRQ_HANDLED; +} + +static irqreturn_t fg_batt_missing_irq_handler(int irq, void *_chip) +{ + struct fg_chip *chip = _chip; + bool batt_missing = is_battery_missing(chip); + + if (batt_missing) { + fg_cap_learning_stop(chip); + chip->battery_missing = true; + chip->profile_loaded = false; + chip->soc_reporting_ready = false; + chip->batt_type = default_batt_type; + mutex_lock(&chip->cyc_ctr.lock); + if (fg_debug_mask & FG_IRQS) + pr_info("battery missing, clearing cycle counters\n"); + clear_cycle_counter(chip); + mutex_unlock(&chip->cyc_ctr.lock); + } else { + if (!chip->use_otp_profile) + fg_handle_battery_insertion(chip); + else + chip->battery_missing = false; + } + + if (fg_debug_mask & FG_IRQS) + pr_info("batt-missing triggered: %s\n", + batt_missing ? "missing" : "present"); + + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + return IRQ_HANDLED; +} + +static irqreturn_t fg_mem_avail_irq_handler(int irq, void *_chip) +{ + struct fg_chip *chip = _chip; + u8 mem_if_sts; + int rc; + + rc = fg_read(chip, &mem_if_sts, INT_RT_STS(chip->mem_base), 1); + if (rc) { + pr_err("failed to read mem status rc=%d\n", rc); + return IRQ_HANDLED; + } + + if (fg_check_sram_access(chip)) { + if ((fg_debug_mask & FG_IRQS) + & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) + pr_info("sram access granted\n"); + reinit_completion(&chip->sram_access_revoked); + complete_all(&chip->sram_access_granted); + } else { + if ((fg_debug_mask & FG_IRQS) + & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) + pr_info("sram access revoked\n"); + complete_all(&chip->sram_access_revoked); + } + + if (!rc && (fg_debug_mask & FG_IRQS) + & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) + pr_info("mem_if sts 0x%02x\n", mem_if_sts); + + return IRQ_HANDLED; +} + +static irqreturn_t fg_soc_irq_handler(int irq, void *_chip) +{ + struct fg_chip *chip = _chip; + u8 soc_rt_sts; + int rc, msoc; + + rc = fg_read(chip, &soc_rt_sts, INT_RT_STS(chip->soc_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + } + + if (fg_debug_mask & FG_IRQS) + pr_info("triggered 0x%x\n", soc_rt_sts); + + if (chip->dischg_gain.enable) { + fg_stay_awake(&chip->dischg_gain_wakeup_source); + schedule_work(&chip->dischg_gain_work); + } + + if (chip->soc_slope_limiter_en) { + fg_stay_awake(&chip->slope_limit_wakeup_source); + schedule_work(&chip->slope_limiter_work); + } + + /* Backup last soc every delta soc interrupt */ + chip->use_last_soc = false; + if (fg_reset_on_lockup) { + if (!chip->ima_error_handling) + chip->last_soc = get_monotonic_soc_raw(chip); + if (fg_debug_mask & FG_STATUS) + pr_info("last_soc: %d\n", chip->last_soc); + + fg_stay_awake(&chip->cc_soc_wakeup_source); + schedule_work(&chip->cc_soc_store_work); + } + + if (chip->use_vbat_low_empty_soc) { + msoc = get_monotonic_soc_raw(chip); + if (msoc == 0 || chip->soc_empty) { + fg_stay_awake(&chip->empty_check_wakeup_source); + schedule_delayed_work(&chip->check_empty_work, + msecs_to_jiffies(FG_EMPTY_DEBOUNCE_MS)); + } + } + + schedule_work(&chip->battery_age_work); + + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + + if (chip->rslow_comp.chg_rs_to_rslow > 0 && + chip->rslow_comp.chg_rslow_comp_c1 > 0 && + chip->rslow_comp.chg_rslow_comp_c2 > 0) + schedule_work(&chip->rslow_comp_work); + + if (chip->cyc_ctr.en) + schedule_work(&chip->cycle_count_work); + + schedule_work(&chip->update_esr_work); + + if (chip->charge_full) + schedule_work(&chip->charge_full_work); + + if (chip->wa_flag & IADC_GAIN_COMP_WA + && chip->iadc_comp_data.gain_active) { + fg_stay_awake(&chip->gain_comp_wakeup_source); + schedule_work(&chip->gain_comp_work); + } + + if (chip->wa_flag & USE_CC_SOC_REG + && chip->learning_data.active) { + fg_stay_awake(&chip->capacity_learning_wakeup_source); + schedule_work(&chip->fg_cap_learning_work); + } + + if (chip->esr_pulse_tune_en) { + fg_stay_awake(&chip->esr_extract_wakeup_source); + schedule_work(&chip->esr_extract_config_work); + } + + return IRQ_HANDLED; +} + +static irqreturn_t fg_empty_soc_irq_handler(int irq, void *_chip) +{ + struct fg_chip *chip = _chip; + u8 soc_rt_sts; + int rc; + + rc = fg_read(chip, &soc_rt_sts, INT_RT_STS(chip->soc_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + goto done; + } + + if (fg_debug_mask & FG_IRQS) + pr_info("triggered 0x%x\n", soc_rt_sts); + if (fg_is_batt_empty(chip)) { + fg_stay_awake(&chip->empty_check_wakeup_source); + schedule_delayed_work(&chip->check_empty_work, + msecs_to_jiffies(FG_EMPTY_DEBOUNCE_MS)); + } else { + chip->soc_empty = false; + } + +done: + return IRQ_HANDLED; +} + +static irqreturn_t fg_first_soc_irq_handler(int irq, void *_chip) +{ + struct fg_chip *chip = _chip; + + if (fg_debug_mask & FG_IRQS) + pr_info("triggered\n"); + + if (fg_est_dump) + schedule_work(&chip->dump_sram); + + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + + complete_all(&chip->first_soc_done); + + return IRQ_HANDLED; +} + +static void fg_external_power_changed(struct power_supply *psy) +{ + struct fg_chip *chip = container_of(psy, struct fg_chip, bms_psy); + bool input_present = is_input_present(chip); + + if (input_present ^ chip->rslow_comp.active && + chip->rslow_comp.chg_rs_to_rslow > 0 && + chip->rslow_comp.chg_rslow_comp_c1 > 0 && + chip->rslow_comp.chg_rslow_comp_c2 > 0) + schedule_work(&chip->rslow_comp_work); + if (!input_present && chip->resume_soc_lowered) { + fg_stay_awake(&chip->resume_soc_wakeup_source); + schedule_work(&chip->set_resume_soc_work); + } + if (!input_present && chip->charge_full) + schedule_work(&chip->charge_full_work); +} + +static void set_resume_soc_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + set_resume_soc_work); + int rc, resume_soc_raw; + + if (is_input_present(chip) && !chip->resume_soc_lowered) { + if (!chip->charge_done) + goto done; + resume_soc_raw = get_monotonic_soc_raw(chip) + - (0xFF - settings[FG_MEM_RESUME_SOC].value); + if (resume_soc_raw > 0 && resume_soc_raw < FULL_SOC_RAW) { + rc = fg_set_resume_soc(chip, resume_soc_raw); + if (rc) { + pr_err("Couldn't set resume SOC for FG\n"); + goto done; + } + if (fg_debug_mask & FG_STATUS) { + pr_info("resume soc lowered to 0x%02x\n", + resume_soc_raw); + } + } else if (settings[FG_MEM_RESUME_SOC].value > 0) { + pr_err("bad resume soc 0x%02x\n", resume_soc_raw); + } + chip->charge_done = false; + chip->resume_soc_lowered = true; + } else if (chip->resume_soc_lowered && (!is_input_present(chip) + || chip->health == POWER_SUPPLY_HEALTH_GOOD)) { + resume_soc_raw = settings[FG_MEM_RESUME_SOC].value; + if (resume_soc_raw > 0 && resume_soc_raw < FULL_SOC_RAW) { + rc = fg_set_resume_soc(chip, resume_soc_raw); + if (rc) { + pr_err("Couldn't set resume SOC for FG\n"); + goto done; + } + if (fg_debug_mask & FG_STATUS) { + pr_info("resume soc set to 0x%02x\n", + resume_soc_raw); + } + } else if (settings[FG_MEM_RESUME_SOC].value > 0) { + pr_err("bad resume soc 0x%02x\n", resume_soc_raw); + } + chip->resume_soc_lowered = false; + } +done: + fg_relax(&chip->resume_soc_wakeup_source); +} + +#define OCV_COEFFS_START_REG 0x4C0 +#define OCV_JUNCTION_REG 0x4D8 +#define CUTOFF_VOLTAGE_REG 0x40C +#define RSLOW_CFG_REG 0x538 +#define RSLOW_CFG_OFFSET 2 +#define RSLOW_THRESH_REG 0x52C +#define RSLOW_THRESH_OFFSET 0 +#define RS_TO_RSLOW_CHG_OFFSET 2 +#define RS_TO_RSLOW_DISCHG_OFFSET 0 +#define RSLOW_COMP_REG 0x528 +#define RSLOW_COMP_C1_OFFSET 0 +#define RSLOW_COMP_C2_OFFSET 2 +#define BATT_PROFILE_OFFSET 0x4C0 +static void get_default_rslow_comp_settings(struct fg_chip *chip) +{ + int offset; + + offset = RSLOW_CFG_REG + RSLOW_CFG_OFFSET - BATT_PROFILE_OFFSET; + memcpy(&chip->rslow_comp.rslow_cfg, chip->batt_profile + offset, 1); + + offset = RSLOW_THRESH_REG + RSLOW_THRESH_OFFSET - BATT_PROFILE_OFFSET; + memcpy(&chip->rslow_comp.rslow_thr, chip->batt_profile + offset, 1); + + offset = TEMP_RS_TO_RSLOW_REG + RS_TO_RSLOW_CHG_OFFSET - + BATT_PROFILE_OFFSET; + memcpy(&chip->rslow_comp.rs_to_rslow, chip->batt_profile + offset, 2); + + offset = RSLOW_COMP_REG + RSLOW_COMP_C1_OFFSET - BATT_PROFILE_OFFSET; + memcpy(&chip->rslow_comp.rslow_comp, chip->batt_profile + offset, 4); +} + +static int populate_system_data(struct fg_chip *chip) +{ + u8 buffer[24]; + int rc, i; + + fg_mem_lock(chip); + rc = fg_mem_read(chip, buffer, OCV_COEFFS_START_REG, 24, 0, 0); + if (rc) { + pr_err("Failed to read ocv coefficients: %d\n", rc); + goto done; + } + for (i = 0; i < 12; i += 1) + chip->ocv_coeffs[i] = half_float(buffer + (i * 2)); + if (fg_debug_mask & FG_AGING) { + pr_info("coeffs1 = %lld %lld %lld %lld\n", + chip->ocv_coeffs[0], chip->ocv_coeffs[1], + chip->ocv_coeffs[2], chip->ocv_coeffs[3]); + pr_info("coeffs2 = %lld %lld %lld %lld\n", + chip->ocv_coeffs[4], chip->ocv_coeffs[5], + chip->ocv_coeffs[6], chip->ocv_coeffs[7]); + pr_info("coeffs3 = %lld %lld %lld %lld\n", + chip->ocv_coeffs[8], chip->ocv_coeffs[9], + chip->ocv_coeffs[10], chip->ocv_coeffs[11]); + } + rc = fg_mem_read(chip, buffer, OCV_JUNCTION_REG, 2, 0, 0); + if (rc) { + pr_err("Failed to read ocv junctions: %d\n", rc); + goto done; + } + + chip->ocv_junction_p1p2 = buffer[0] * 100 / 255; + chip->ocv_junction_p2p3 = buffer[1] * 100 / 255; + + rc = load_battery_aging_data(chip); + if (rc) { + pr_err("Failed to load battery aging data, rc:%d\n", rc); + goto done; + } + + rc = fg_mem_read(chip, buffer, CUTOFF_VOLTAGE_REG, 2, 0, 0); + if (rc) { + pr_err("Failed to read cutoff voltage: %d\n", rc); + goto done; + } + + chip->cutoff_voltage = voltage_2b(buffer); + if (fg_debug_mask & FG_AGING) + pr_info("cutoff_voltage = %lld, nom_cap_uah = %d p1p2 = %d, p2p3 = %d\n", + chip->cutoff_voltage, chip->nom_cap_uah, + chip->ocv_junction_p1p2, + chip->ocv_junction_p2p3); + + get_default_rslow_comp_settings(chip); +done: + fg_mem_release(chip); + return rc; +} + +static int fg_update_batt_rslow_settings(struct fg_chip *chip) +{ + int64_t rs_to_rslow_chg, rs_to_rslow_dischg, batt_esr, rconn_uohm; + u8 buffer[2]; + int rc; + + rc = fg_mem_read(chip, buffer, BATTERY_ESR_REG, 2, ESR_OFFSET, 0); + if (rc) { + pr_err("unable to read battery_esr: %d\n", rc); + goto done; + } + batt_esr = half_float(buffer); + + rc = fg_mem_read(chip, buffer, TEMP_RS_TO_RSLOW_REG, 2, + RS_TO_RSLOW_DISCHG_OFFSET, 0); + if (rc) { + pr_err("unable to read rs to rslow dischg: %d\n", rc); + goto done; + } + rs_to_rslow_dischg = half_float(buffer); + + rc = fg_mem_read(chip, buffer, TEMP_RS_TO_RSLOW_REG, 2, + RS_TO_RSLOW_CHG_OFFSET, 0); + if (rc) { + pr_err("unable to read rs to rslow chg: %d\n", rc); + goto done; + } + rs_to_rslow_chg = half_float(buffer); + + if (fg_debug_mask & FG_STATUS) + pr_info("rs_rslow_chg: %lld, rs_rslow_dischg: %lld, esr: %lld\n", + rs_to_rslow_chg, rs_to_rslow_dischg, batt_esr); + + rconn_uohm = chip->rconn_mohm * 1000; + rs_to_rslow_dischg = div64_s64(rs_to_rslow_dischg * batt_esr, + batt_esr + rconn_uohm); + rs_to_rslow_chg = div64_s64(rs_to_rslow_chg * batt_esr, + batt_esr + rconn_uohm); + + half_float_to_buffer(rs_to_rslow_chg, buffer); + rc = fg_mem_write(chip, buffer, TEMP_RS_TO_RSLOW_REG, 2, + RS_TO_RSLOW_CHG_OFFSET, 0); + if (rc) { + pr_err("unable to write rs_to_rslow_chg: %d\n", rc); + goto done; + } + + half_float_to_buffer(rs_to_rslow_dischg, buffer); + rc = fg_mem_write(chip, buffer, TEMP_RS_TO_RSLOW_REG, 2, + RS_TO_RSLOW_DISCHG_OFFSET, 0); + if (rc) { + pr_err("unable to write rs_to_rslow_dischg: %d\n", rc); + goto done; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("Modified rs_rslow_chg: %lld, rs_rslow_dischg: %lld\n", + rs_to_rslow_chg, rs_to_rslow_dischg); +done: + return rc; +} + +#define RSLOW_CFG_MASK (BIT(2) | BIT(3) | BIT(4) | BIT(5)) +#define RSLOW_CFG_ON_VAL (BIT(2) | BIT(3)) +#define RSLOW_THRESH_FULL_VAL 0xFF +static int fg_rslow_charge_comp_set(struct fg_chip *chip) +{ + int rc; + u8 buffer[2]; + + mutex_lock(&chip->rslow_comp.lock); + fg_mem_lock(chip); + + rc = fg_mem_masked_write(chip, RSLOW_CFG_REG, + RSLOW_CFG_MASK, RSLOW_CFG_ON_VAL, RSLOW_CFG_OFFSET); + if (rc) { + pr_err("unable to write rslow cfg: %d\n", rc); + goto done; + } + rc = fg_mem_masked_write(chip, RSLOW_THRESH_REG, + 0xFF, RSLOW_THRESH_FULL_VAL, RSLOW_THRESH_OFFSET); + if (rc) { + pr_err("unable to write rslow thresh: %d\n", rc); + goto done; + } + + half_float_to_buffer(chip->rslow_comp.chg_rs_to_rslow, buffer); + rc = fg_mem_write(chip, buffer, + TEMP_RS_TO_RSLOW_REG, 2, RS_TO_RSLOW_CHG_OFFSET, 0); + if (rc) { + pr_err("unable to write rs to rslow: %d\n", rc); + goto done; + } + half_float_to_buffer(chip->rslow_comp.chg_rslow_comp_c1, buffer); + rc = fg_mem_write(chip, buffer, + RSLOW_COMP_REG, 2, RSLOW_COMP_C1_OFFSET, 0); + if (rc) { + pr_err("unable to write rslow comp: %d\n", rc); + goto done; + } + half_float_to_buffer(chip->rslow_comp.chg_rslow_comp_c2, buffer); + rc = fg_mem_write(chip, buffer, + RSLOW_COMP_REG, 2, RSLOW_COMP_C2_OFFSET, 0); + if (rc) { + pr_err("unable to write rslow comp: %d\n", rc); + goto done; + } + chip->rslow_comp.active = true; + if (fg_debug_mask & FG_STATUS) + pr_info("Activated rslow charge comp values\n"); + +done: + fg_mem_release(chip); + mutex_unlock(&chip->rslow_comp.lock); + return rc; +} + +#define RSLOW_CFG_ORIG_MASK (BIT(4) | BIT(5)) +static int fg_rslow_charge_comp_clear(struct fg_chip *chip) +{ + u8 reg; + int rc; + + mutex_lock(&chip->rslow_comp.lock); + fg_mem_lock(chip); + + reg = chip->rslow_comp.rslow_cfg & RSLOW_CFG_ORIG_MASK; + rc = fg_mem_masked_write(chip, RSLOW_CFG_REG, + RSLOW_CFG_MASK, reg, RSLOW_CFG_OFFSET); + if (rc) { + pr_err("unable to write rslow cfg: %d\n", rc); + goto done; + } + rc = fg_mem_masked_write(chip, RSLOW_THRESH_REG, + 0xFF, chip->rslow_comp.rslow_thr, RSLOW_THRESH_OFFSET); + if (rc) { + pr_err("unable to write rslow thresh: %d\n", rc); + goto done; + } + + rc = fg_mem_write(chip, chip->rslow_comp.rs_to_rslow, + TEMP_RS_TO_RSLOW_REG, 2, RS_TO_RSLOW_CHG_OFFSET, 0); + if (rc) { + pr_err("unable to write rs to rslow: %d\n", rc); + goto done; + } + rc = fg_mem_write(chip, chip->rslow_comp.rslow_comp, + RSLOW_COMP_REG, 4, RSLOW_COMP_C1_OFFSET, 0); + if (rc) { + pr_err("unable to write rslow comp: %d\n", rc); + goto done; + } + chip->rslow_comp.active = false; + if (fg_debug_mask & FG_STATUS) + pr_info("Cleared rslow charge comp values\n"); + +done: + fg_mem_release(chip); + mutex_unlock(&chip->rslow_comp.lock); + return rc; +} + +static void rslow_comp_work(struct work_struct *work) +{ + int battery_soc_1b; + struct fg_chip *chip = container_of(work, + struct fg_chip, + rslow_comp_work); + + battery_soc_1b = get_battery_soc_raw(chip) >> 16; + if (battery_soc_1b > chip->rslow_comp.chg_rslow_comp_thr + && chip->status == POWER_SUPPLY_STATUS_CHARGING) { + if (!chip->rslow_comp.active) + fg_rslow_charge_comp_set(chip); + } else { + if (chip->rslow_comp.active) + fg_rslow_charge_comp_clear(chip); + } +} + +#define MICROUNITS_TO_ADC_RAW(units) \ + div64_s64(units * LSB_16B_DENMTR, LSB_16B_NUMRTR) +static int update_chg_iterm(struct fg_chip *chip) +{ + u8 data[2]; + u16 converted_current_raw; + s64 current_ma = -settings[FG_MEM_CHG_TERM_CURRENT].value; + + converted_current_raw = (s16)MICROUNITS_TO_ADC_RAW(current_ma * 1000); + data[0] = cpu_to_le16(converted_current_raw) & 0xFF; + data[1] = cpu_to_le16(converted_current_raw) >> 8; + + if (fg_debug_mask & FG_STATUS) + pr_info("current = %lld, converted_raw = %04x, data = %02x %02x\n", + current_ma, converted_current_raw, data[0], data[1]); + return fg_mem_write(chip, data, + settings[FG_MEM_CHG_TERM_CURRENT].address, + 2, settings[FG_MEM_CHG_TERM_CURRENT].offset, 0); +} + +#define CC_CV_SETPOINT_REG 0x4F8 +#define CC_CV_SETPOINT_OFFSET 0 +static void update_cc_cv_setpoint(struct fg_chip *chip) +{ + int rc; + u8 tmp[2]; + + if (!chip->cc_cv_threshold_mv) + return; + batt_to_setpoint_adc(chip->cc_cv_threshold_mv, tmp); + rc = fg_mem_write(chip, tmp, CC_CV_SETPOINT_REG, 2, + CC_CV_SETPOINT_OFFSET, 0); + if (rc) { + pr_err("failed to write CC_CV_VOLT rc=%d\n", rc); + return; + } + if (fg_debug_mask & FG_STATUS) + pr_info("Wrote %x %x to address %x for CC_CV setpoint\n", + tmp[0], tmp[1], CC_CV_SETPOINT_REG); +} + +#define CBITS_INPUT_FILTER_REG 0x4B4 +#define CBITS_RMEAS1_OFFSET 1 +#define CBITS_RMEAS2_OFFSET 2 +#define CBITS_RMEAS1_DEFAULT_VAL 0x65 +#define CBITS_RMEAS2_DEFAULT_VAL 0x65 +#define IMPTR_FAST_TIME_SHIFT 1 +#define IMPTR_LONG_TIME_SHIFT (1 << 4) +#define IMPTR_PULSE_CTR_CHG 1 +#define IMPTR_PULSE_CTR_DISCHG (1 << 4) +static int fg_config_imptr_pulse(struct fg_chip *chip, bool slow) +{ + int rc; + u8 cntr[2] = {0, 0}; + u8 val; + + if (slow == chip->imptr_pulse_slow_en) { + if (fg_debug_mask & FG_STATUS) + pr_info("imptr_pulse_slow is %sabled already\n", + slow ? "en" : "dis"); + return 0; + } + + fg_mem_lock(chip); + + val = slow ? (IMPTR_FAST_TIME_SHIFT | IMPTR_LONG_TIME_SHIFT) : + CBITS_RMEAS1_DEFAULT_VAL; + rc = fg_mem_write(chip, &val, CBITS_INPUT_FILTER_REG, 1, + CBITS_RMEAS1_OFFSET, 0); + if (rc) { + pr_err("unable to write cbits_rmeas1_offset rc=%d\n", rc); + goto done; + } + + val = slow ? (IMPTR_PULSE_CTR_CHG | IMPTR_PULSE_CTR_DISCHG) : + CBITS_RMEAS2_DEFAULT_VAL; + rc = fg_mem_write(chip, &val, CBITS_INPUT_FILTER_REG, 1, + CBITS_RMEAS2_OFFSET, 0); + if (rc) { + pr_err("unable to write cbits_rmeas2_offset rc=%d\n", rc); + goto done; + } + + if (slow) { + rc = fg_mem_write(chip, cntr, COUNTER_IMPTR_REG, 4, + COUNTER_IMPTR_OFFSET, 0); + if (rc) { + pr_err("failed to write COUNTER_IMPTR rc=%d\n", rc); + goto done; + } + + rc = fg_mem_write(chip, cntr, COUNTER_PULSE_REG, 2, + COUNTER_PULSE_OFFSET, 0); + if (rc) { + pr_err("failed to write COUNTER_IMPTR rc=%d\n", rc); + goto done; + } + } + + chip->imptr_pulse_slow_en = slow; + if (fg_debug_mask & FG_STATUS) + pr_info("imptr_pulse_slow is %sabled\n", slow ? "en" : "dis"); +done: + fg_mem_release(chip); + return rc; +} + +#define CURRENT_DELTA_MIN_REG 0x42C +#define CURRENT_DELTA_MIN_OFFSET 1 +#define SYS_CFG_1_REG 0x4AC +#define SYS_CFG_1_OFFSET 0 +#define CURRENT_DELTA_MIN_DEFAULT 0x16 +#define CURRENT_DELTA_MIN_500MA 0xCD +#define RSLOW_CFG_USE_FIX_RSER_VAL BIT(7) +#define ENABLE_ESR_PULSE_VAL BIT(3) +static int fg_config_esr_extract(struct fg_chip *chip, bool disable) +{ + int rc; + u8 val; + + if (disable == chip->esr_extract_disabled) { + if (fg_debug_mask & FG_STATUS) + pr_info("ESR extract already %sabled\n", + disable ? "dis" : "en"); + return 0; + } + + fg_mem_lock(chip); + + val = disable ? CURRENT_DELTA_MIN_500MA : + CURRENT_DELTA_MIN_DEFAULT; + rc = fg_mem_write(chip, &val, CURRENT_DELTA_MIN_REG, 1, + CURRENT_DELTA_MIN_OFFSET, 0); + if (rc) { + pr_err("unable to write curr_delta_min rc=%d\n", rc); + goto done; + } + + val = disable ? RSLOW_CFG_USE_FIX_RSER_VAL : 0; + rc = fg_mem_masked_write(chip, RSLOW_CFG_REG, + RSLOW_CFG_USE_FIX_RSER_VAL, val, RSLOW_CFG_OFFSET); + if (rc) { + pr_err("unable to write rslow cfg rc= %d\n", rc); + goto done; + } + + val = disable ? 0 : ENABLE_ESR_PULSE_VAL; + rc = fg_mem_masked_write(chip, SYS_CFG_1_REG, + ENABLE_ESR_PULSE_VAL, val, SYS_CFG_1_OFFSET); + if (rc) { + pr_err("unable to write sys_cfg_1 rc= %d\n", rc); + goto done; + } + + chip->esr_extract_disabled = disable; + if (fg_debug_mask & FG_STATUS) + pr_info("ESR extract is %sabled\n", disable ? "dis" : "en"); +done: + fg_mem_release(chip); + return rc; +} + +#define ESR_EXTRACT_STOP_SOC 2 +#define IMPTR_PULSE_CONFIG_SOC 5 +static void esr_extract_config_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, struct fg_chip, + esr_extract_config_work); + bool input_present = is_input_present(chip); + int capacity = get_prop_capacity(chip); + + if (input_present && capacity <= ESR_EXTRACT_STOP_SOC) { + fg_config_esr_extract(chip, true); + } else if (capacity > ESR_EXTRACT_STOP_SOC) { + fg_config_esr_extract(chip, false); + + if (capacity <= IMPTR_PULSE_CONFIG_SOC) + fg_config_imptr_pulse(chip, true); + else + fg_config_imptr_pulse(chip, false); + } + + fg_relax(&chip->esr_extract_wakeup_source); +} + +#define KI_COEFF_MEDC_REG 0x400 +#define KI_COEFF_MEDC_OFFSET 0 +#define KI_COEFF_HIGHC_REG 0x404 +#define KI_COEFF_HIGHC_OFFSET 0 +#define DEFAULT_MEDC_VOLTAGE_GAIN 3 +#define DEFAULT_HIGHC_VOLTAGE_GAIN 2 +static void discharge_gain_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, struct fg_chip, + dischg_gain_work); + u8 buf[2]; + int capacity, rc, i; + int64_t medc_val = DEFAULT_MEDC_VOLTAGE_GAIN; + int64_t highc_val = DEFAULT_HIGHC_VOLTAGE_GAIN; + + capacity = get_prop_capacity(chip); + if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) { + for (i = VOLT_GAIN_MAX - 1; i >= 0; i--) { + if (capacity <= chip->dischg_gain.soc[i]) { + medc_val = chip->dischg_gain.medc_gain[i]; + highc_val = chip->dischg_gain.highc_gain[i]; + } + } + } + + if (fg_debug_mask & FG_STATUS) + pr_info("Capacity: %d, medc_gain: %lld highc_gain: %lld\n", + capacity, medc_val, highc_val); + + medc_val *= MICRO_UNIT; + half_float_to_buffer(medc_val, buf); + rc = fg_mem_write(chip, buf, KI_COEFF_MEDC_REG, 2, + KI_COEFF_MEDC_OFFSET, 0); + if (rc) + pr_err("Couldn't write to ki_coeff_medc_reg, rc=%d\n", rc); + else if (fg_debug_mask & FG_STATUS) + pr_info("Value [%x %x] written to ki_coeff_medc\n", buf[0], + buf[1]); + + highc_val *= MICRO_UNIT; + half_float_to_buffer(highc_val, buf); + rc = fg_mem_write(chip, buf, KI_COEFF_HIGHC_REG, 2, + KI_COEFF_HIGHC_OFFSET, 0); + if (rc) + pr_err("Couldn't write to ki_coeff_highc_reg, rc=%d\n", rc); + else if (fg_debug_mask & FG_STATUS) + pr_info("Value [%x %x] written to ki_coeff_highc\n", buf[0], + buf[1]); + + fg_relax(&chip->dischg_gain_wakeup_source); +} + +#define LOW_LATENCY BIT(6) +#define PROFILE_INTEGRITY_REG 0x53C +#define PROFILE_INTEGRITY_BIT BIT(0) +#define FIRST_EST_DONE_BIT BIT(5) +#define MAX_TRIES_FIRST_EST 3 +#define FIRST_EST_WAIT_MS 2000 +#define PROFILE_LOAD_TIMEOUT_MS 5000 +static int fg_do_restart(struct fg_chip *chip, bool write_profile) +{ + int rc, ibat_ua; + u8 reg = 0; + u8 buf[2]; + bool tried_once = false; + + if (fg_debug_mask & FG_STATUS) + pr_info("restarting fuel gauge...\n"); + +try_again: + if (write_profile && !chip->ima_error_handling) { + if (!chip->charging_disabled) { + pr_err("Charging not yet disabled!\n"); + return -EINVAL; + } + + ibat_ua = get_sram_prop_now(chip, FG_DATA_CURRENT); + if (ibat_ua == -EINVAL) { + pr_err("SRAM not updated yet!\n"); + return ibat_ua; + } + + if (ibat_ua < 0) { + pr_warn("Charging enabled?, ibat_ua: %d\n", ibat_ua); + + if (!tried_once) { + cancel_delayed_work(&chip->update_sram_data); + schedule_delayed_work(&chip->update_sram_data, + msecs_to_jiffies(0)); + msleep(1000); + tried_once = true; + goto try_again; + } + } + } + + chip->fg_restarting = true; + /* + * save the temperature if the sw rbias control is active so that there + * is no gap of time when there is no valid temperature read after the + * restart + */ + if (chip->sw_rbias_ctrl) { + rc = fg_mem_read(chip, buf, + fg_data[FG_DATA_BATT_TEMP].address, + fg_data[FG_DATA_BATT_TEMP].len, + fg_data[FG_DATA_BATT_TEMP].offset, 0); + if (rc) { + pr_err("failed to read batt temp rc=%d\n", rc); + goto sub_and_fail; + } + } + /* + * release the sram access and configure the correct settings + * before re-requesting access. + */ + mutex_lock(&chip->rw_lock); + fg_release_access(chip); + + rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, + NO_OTP_PROF_RELOAD, 0, 1); + if (rc) { + pr_err("failed to set no otp reload bit\n"); + goto unlock_and_fail; + } + + /* unset the restart bits so the fg doesn't continuously restart */ + reg = REDO_FIRST_ESTIMATE | RESTART_GO; + rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, + reg, 0, 1); + if (rc) { + pr_err("failed to unset fg restart: %d\n", rc); + goto unlock_and_fail; + } + + rc = fg_masked_write(chip, MEM_INTF_CFG(chip), + LOW_LATENCY, LOW_LATENCY, 1); + if (rc) { + pr_err("failed to set low latency access bit\n"); + goto unlock_and_fail; + } + mutex_unlock(&chip->rw_lock); + + /* read once to get a fg cycle in */ + rc = fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 0); + if (rc) { + pr_err("failed to read profile integrity rc=%d\n", rc); + goto fail; + } + + /* + * If this is not the first time a profile has been loaded, sleep for + * 3 seconds to make sure the NO_OTP_RELOAD is cleared in memory + */ + if (chip->first_profile_loaded) + msleep(3000); + + mutex_lock(&chip->rw_lock); + fg_release_access(chip); + rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, 0, 1); + if (rc) { + pr_err("failed to set low latency access bit\n"); + goto unlock_and_fail; + } + + atomic_add_return(1, &chip->memif_user_cnt); + mutex_unlock(&chip->rw_lock); + + if (write_profile) { + /* write the battery profile */ + rc = fg_mem_write(chip, chip->batt_profile, BATT_PROFILE_OFFSET, + chip->batt_profile_len, 0, 1); + if (rc) { + pr_err("failed to write profile rc=%d\n", rc); + goto sub_and_fail; + } + /* write the integrity bits and release access */ + rc = fg_mem_masked_write(chip, PROFILE_INTEGRITY_REG, + PROFILE_INTEGRITY_BIT, + PROFILE_INTEGRITY_BIT, 0); + if (rc) { + pr_err("failed to write profile rc=%d\n", rc); + goto sub_and_fail; + } + } + + /* decrement the user count so that memory access can be released */ + fg_release_access_if_necessary(chip); + + /* + * make sure that the first estimate has completed + * in case of a hotswap + */ + rc = wait_for_completion_interruptible_timeout(&chip->first_soc_done, + msecs_to_jiffies(PROFILE_LOAD_TIMEOUT_MS)); + if (rc <= 0) { + pr_err("transaction timed out rc=%d\n", rc); + rc = -ETIMEDOUT; + goto fail; + } + + /* + * reinitialize the completion so that the driver knows when the restart + * finishes + */ + reinit_completion(&chip->first_soc_done); + + if (chip->esr_pulse_tune_en) { + fg_stay_awake(&chip->esr_extract_wakeup_source); + schedule_work(&chip->esr_extract_config_work); + } + + /* + * set the restart bits so that the next fg cycle will not reload + * the profile + */ + rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, + NO_OTP_PROF_RELOAD, NO_OTP_PROF_RELOAD, 1); + if (rc) { + pr_err("failed to set no otp reload bit\n"); + goto fail; + } + + reg = REDO_FIRST_ESTIMATE | RESTART_GO; + rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, + reg, reg, 1); + if (rc) { + pr_err("failed to set fg restart: %d\n", rc); + goto fail; + } + + /* wait for the first estimate to complete */ + rc = wait_for_completion_interruptible_timeout(&chip->first_soc_done, + msecs_to_jiffies(PROFILE_LOAD_TIMEOUT_MS)); + if (rc <= 0) { + pr_err("transaction timed out rc=%d\n", rc); + rc = -ETIMEDOUT; + goto fail; + } + rc = fg_read(chip, ®, INT_RT_STS(chip->soc_base), 1); + if (rc) { + pr_err("spmi read failed: addr=%03X, rc=%d\n", + INT_RT_STS(chip->soc_base), rc); + goto fail; + } + if ((reg & FIRST_EST_DONE_BIT) == 0) + pr_err("Battery profile reloading failed, no first estimate\n"); + + rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, + NO_OTP_PROF_RELOAD, 0, 1); + if (rc) { + pr_err("failed to set no otp reload bit\n"); + goto fail; + } + /* unset the restart bits so the fg doesn't continuously restart */ + reg = REDO_FIRST_ESTIMATE | RESTART_GO; + rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, + reg, 0, 1); + if (rc) { + pr_err("failed to unset fg restart: %d\n", rc); + goto fail; + } + + /* restore the battery temperature reading here */ + if (chip->sw_rbias_ctrl) { + if (fg_debug_mask & FG_STATUS) + pr_info("reloaded 0x%02x%02x into batt temp", + buf[0], buf[1]); + rc = fg_mem_write(chip, buf, + fg_data[FG_DATA_BATT_TEMP].address, + fg_data[FG_DATA_BATT_TEMP].len, + fg_data[FG_DATA_BATT_TEMP].offset, 0); + if (rc) { + pr_err("failed to write batt temp rc=%d\n", rc); + goto fail; + } + } + + /* Enable charging now as the first estimate is done now */ + if (chip->charging_disabled) { + rc = set_prop_enable_charging(chip, true); + if (rc) + pr_err("Failed to enable charging, rc=%d\n", rc); + else + chip->charging_disabled = false; + } + + chip->fg_restarting = false; + + if (fg_debug_mask & FG_STATUS) + pr_info("done!\n"); + return 0; + +unlock_and_fail: + mutex_unlock(&chip->rw_lock); + goto fail; +sub_and_fail: + fg_release_access_if_necessary(chip); + goto fail; +fail: + chip->fg_restarting = false; + return -EINVAL; +} + +#define REDO_BATID_DURING_FIRST_EST BIT(4) +static void fg_hw_restart(struct fg_chip *chip) +{ + u8 reg = 0; + int rc = 0, batt_id; + u8 data[4]; + + reg = 0x80; + batt_id = get_sram_prop_now(chip, FG_DATA_BATT_ID); + printk("fg_hw_restart old battery id = %d\n", batt_id); + + fg_masked_write(chip, 0x4150, reg, reg, 1); + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, 0xFF, 0, 1); + mdelay(5); + + reg = REDO_BATID_DURING_FIRST_EST|REDO_FIRST_ESTIMATE; + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); + mdelay(5); + + reg = REDO_BATID_DURING_FIRST_EST |REDO_FIRST_ESTIMATE| RESTART_GO; + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); + mdelay(1000); + + fg_masked_write(chip, chip->soc_base + SOC_RESTART, 0xFF, 0, 1); + fg_masked_write(chip, 0x4150, 0x80, 0, 1); + + mdelay(2000); + + rc = fg_mem_read(chip, data, fg_data[FG_DATA_BATT_ID].address, fg_data[FG_DATA_BATT_ID].len, fg_data[FG_DATA_BATT_ID].offset, 0); + + if (rc) { + printk("Failed to get sram battery id data\n"); + } + else { + fg_data[FG_DATA_BATT_ID].value = data[0] * LSB_8B; + } + + batt_id = get_sram_prop_now(chip, FG_DATA_BATT_ID); + printk("fg_hw_restart new batt_id=%d\n", batt_id); +} + +#define FG_PROFILE_LEN 128 +#define PROFILE_COMPARE_LEN 32 +#define THERMAL_COEFF_ADDR 0x444 +#define THERMAL_COEFF_OFFSET 0x2 +#define BATTERY_PSY_WAIT_MS 2000 +static int fg_batt_profile_init(struct fg_chip *chip) +{ + int rc = 0, ret; + int len; + + int i; + int batts_id_ohm[3] = {24000, 40000, 50000}; + int delta = 0, limit = 0, batt_id = 0, match = 0, id_range_pct = 5; + bool in_range = false; + + struct device_node *node = chip->spmi->dev.of_node; + struct device_node *batt_node, *profile_node; + const char *data, *batt_type_str; + bool tried_again = false, vbat_in_range, profiles_same; + u8 reg = 0; + + batt_id = get_sram_prop_now(chip, FG_DATA_BATT_ID); + printk("batt_id_ohm=%d\n", batt_id); + for (i = 0; i < 3; i++) { + delta = abs(batts_id_ohm[i] - batt_id); + printk("delta=%d\n", delta); + limit = (batts_id_ohm[i] * id_range_pct / 100); + if (batts_id_ohm[i] == 24000) + limit += 800; + printk("limit=%d\n", limit); + in_range = (delta <= limit); + printk("in_range=%d\n", in_range); + if (in_range != 0) { + match = 1; + printk("match=%d\n", match); + } + } + if (match == 0) { + fg_hw_restart(chip); + printk("re-read bat id\n"); + } + printk("batt_id=%d\n", get_sram_prop_now(chip, FG_DATA_BATT_ID)); + +wait: + fg_stay_awake(&chip->profile_wakeup_source); + ret = wait_for_completion_interruptible_timeout(&chip->batt_id_avail, + msecs_to_jiffies(PROFILE_LOAD_TIMEOUT_MS)); + /* If we were interrupted wait again one more time. */ + if (ret == -ERESTARTSYS && !tried_again) { + tried_again = true; + pr_debug("interrupted, waiting again\n"); + goto wait; + } else if (ret <= 0) { + rc = -ETIMEDOUT; + pr_err("profile loading timed out rc=%d\n", rc); + goto no_profile; + } + + /* Check whether the charger is ready */ + if (!is_charger_available(chip)) + goto reschedule; + + /* Disable charging for a FG cycle before calculating vbat_in_range */ + if (!chip->charging_disabled) { + rc = set_prop_enable_charging(chip, false); + if (rc) + pr_err("Failed to disable charging, rc=%d\n", rc); + + goto update; + } + + batt_node = of_find_node_by_name(node, "qcom,battery-data"); + if (!batt_node) { + pr_warn("No available batterydata, using OTP defaults\n"); + rc = 0; + goto no_profile; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("battery id = %d\n", + get_sram_prop_now(chip, FG_DATA_BATT_ID)); + profile_node = of_batterydata_get_best_profile(batt_node, "bms", + fg_batt_type); + if (IS_ERR_OR_NULL(profile_node)) { + rc = PTR_ERR(profile_node); + if (rc == -EPROBE_DEFER) { + goto reschedule; + } else { + pr_err("couldn't find profile handle rc=%d\n", rc); + goto no_profile; + } + } + + /* read rslow compensation values if they're available */ + rc = of_property_read_u32(profile_node, "qcom,chg-rs-to-rslow", + &chip->rslow_comp.chg_rs_to_rslow); + if (rc) { + chip->rslow_comp.chg_rs_to_rslow = -EINVAL; + if (rc != -EINVAL) + pr_err("Could not read rs to rslow: %d\n", rc); + } + rc = of_property_read_u32(profile_node, "qcom,chg-rslow-comp-c1", + &chip->rslow_comp.chg_rslow_comp_c1); + if (rc) { + chip->rslow_comp.chg_rslow_comp_c1 = -EINVAL; + if (rc != -EINVAL) + pr_err("Could not read rslow comp c1: %d\n", rc); + } + rc = of_property_read_u32(profile_node, "qcom,chg-rslow-comp-c2", + &chip->rslow_comp.chg_rslow_comp_c2); + if (rc) { + chip->rslow_comp.chg_rslow_comp_c2 = -EINVAL; + if (rc != -EINVAL) + pr_err("Could not read rslow comp c2: %d\n", rc); + } + rc = of_property_read_u32(profile_node, "qcom,chg-rslow-comp-thr", + &chip->rslow_comp.chg_rslow_comp_thr); + if (rc) { + chip->rslow_comp.chg_rslow_comp_thr = -EINVAL; + if (rc != -EINVAL) + pr_err("Could not read rslow comp thr: %d\n", rc); + } + + rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv", + &chip->batt_max_voltage_uv); + + if (rc) + pr_warn("couldn't find battery max voltage\n"); + + /* + * Only configure from profile if fg-cc-cv-threshold-mv is not + * defined in the charger device node. + */ + if (!of_find_property(chip->spmi->dev.of_node, + "qcom,fg-cc-cv-threshold-mv", NULL)) { + of_property_read_u32(profile_node, + "qcom,fg-cc-cv-threshold-mv", + &chip->cc_cv_threshold_mv); + } + + data = of_get_property(profile_node, "qcom,fg-profile-data", &len); + if (!data) { + pr_err("no battery profile loaded\n"); + rc = 0; + goto no_profile; + } + + if (len != FG_PROFILE_LEN) { + pr_err("battery profile incorrect size: %d\n", len); + rc = -EINVAL; + goto no_profile; + } + + rc = of_property_read_string(profile_node, "qcom,battery-type", + &batt_type_str); + if (rc) { + pr_err("Could not find battery data type: %d\n", rc); + rc = 0; + goto no_profile; + } + + if (!chip->batt_profile) + chip->batt_profile = devm_kzalloc(chip->dev, + sizeof(char) * len, GFP_KERNEL); + + if (!chip->batt_profile) { + pr_err("out of memory\n"); + rc = -ENOMEM; + goto no_profile; + } + + rc = fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 1); + if (rc) { + pr_err("failed to read profile integrity rc=%d\n", rc); + goto no_profile; + } + + rc = fg_mem_read(chip, chip->batt_profile, BATT_PROFILE_OFFSET, + len, 0, 1); + if (rc) { + pr_err("failed to read profile rc=%d\n", rc); + goto no_profile; + } + + + vbat_in_range = get_vbat_est_diff(chip) + < settings[FG_MEM_VBAT_EST_DIFF].value * 1000; + profiles_same = memcmp(chip->batt_profile, data, + PROFILE_COMPARE_LEN) == 0; + if (reg & PROFILE_INTEGRITY_BIT) { + fg_cap_learning_load_data(chip); + if (vbat_in_range && !fg_is_batt_empty(chip) && profiles_same) { + if (fg_debug_mask & FG_STATUS) + pr_info("Battery profiles same, using default\n"); + if (fg_est_dump) + schedule_work(&chip->dump_sram); + /* + * Copy the profile read from device tree for + * getting profile parameters later. + */ + memcpy(chip->batt_profile, data, len); + chip->batt_profile_len = len; + goto done; + } + } else { + pr_info("Battery profile not same, clearing data\n"); + clear_cycle_counter(chip); + chip->learning_data.learned_cc_uah = 0; + } + + if (fg_est_dump) + dump_sram(&chip->dump_sram); + + if ((fg_debug_mask & FG_STATUS) && !vbat_in_range) + pr_info("Vbat out of range: v_current_pred: %d, v:%d\n", + fg_data[FG_DATA_CPRED_VOLTAGE].value, + fg_data[FG_DATA_VOLTAGE].value); + + if ((fg_debug_mask & FG_STATUS) && fg_is_batt_empty(chip)) + pr_info("battery empty\n"); + + if ((fg_debug_mask & FG_STATUS) && !profiles_same) + pr_info("profiles differ\n"); + + if (fg_debug_mask & FG_STATUS) { + pr_info("Using new profile\n"); + print_hex_dump(KERN_INFO, "FG: loaded profile: ", + DUMP_PREFIX_NONE, 16, 1, + chip->batt_profile, len, false); + } + + memcpy(chip->batt_profile, data, len); + chip->batt_profile_len = len; + + if (fg_debug_mask & FG_STATUS) + print_hex_dump(KERN_INFO, "FG: new profile: ", + DUMP_PREFIX_NONE, 16, 1, chip->batt_profile, + chip->batt_profile_len, false); + + rc = fg_do_restart(chip, true); + if (rc) { + pr_err("restart failed: %d\n", rc); + goto no_profile; + } + + /* + * Only configure from profile if thermal-coefficients is not + * defined in the FG device node. + */ + if (!of_find_property(chip->spmi->dev.of_node, + "qcom,thermal-coefficients", NULL)) { + data = of_get_property(profile_node, + "qcom,thermal-coefficients", &len); + if (data && len == THERMAL_COEFF_N_BYTES) { + memcpy(chip->thermal_coefficients, data, len); + rc = fg_mem_write(chip, chip->thermal_coefficients, + THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, + THERMAL_COEFF_OFFSET, 0); + if (rc) + pr_err("spmi write failed addr:%03x, ret:%d\n", + THERMAL_COEFF_ADDR, rc); + else if (fg_debug_mask & FG_STATUS) + pr_info("Battery thermal coefficients changed\n"); + } + } + + if (chip->rconn_mohm > 0) { + rc = fg_update_batt_rslow_settings(chip); + if (rc) + pr_err("Error in updating ESR, rc=%d\n", rc); + } +done: + if (chip->charging_disabled) { + rc = set_prop_enable_charging(chip, true); + if (rc) + pr_err("Failed to enable charging, rc=%d\n", rc); + else + chip->charging_disabled = false; + } + + if (fg_batt_type) + chip->batt_type = fg_batt_type; + else + chip->batt_type = batt_type_str; + + if (chip->first_profile_loaded && fg_reset_on_lockup) { + if (fg_debug_mask & FG_STATUS) + pr_info("restoring SRAM registers\n"); + rc = fg_backup_sram_registers(chip, false); + if (rc) + pr_err("Couldn't restore sram registers\n"); + + /* Read the cycle counter back from FG SRAM */ + if (chip->cyc_ctr.en) + restore_cycle_counter(chip); + } + + chip->first_profile_loaded = true; + chip->profile_loaded = true; + chip->soc_reporting_ready = true; + chip->battery_missing = is_battery_missing(chip); + update_chg_iterm(chip); + update_cc_cv_setpoint(chip); + rc = populate_system_data(chip); + if (rc) { + pr_err("failed to read ocv properties=%d\n", rc); + return rc; + } + estimate_battery_age(chip, &chip->actual_cap_uah); + schedule_work(&chip->status_change_work); + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + fg_relax(&chip->profile_wakeup_source); + pr_info("Battery SOC: %d, V: %duV\n", get_prop_capacity(chip), + fg_data[FG_DATA_VOLTAGE].value); + complete_all(&chip->fg_reset_done); + return rc; +no_profile: + chip->soc_reporting_ready = true; + if (chip->charging_disabled) { + rc = set_prop_enable_charging(chip, true); + if (rc) + pr_err("Failed to enable charging, rc=%d\n", rc); + else + chip->charging_disabled = false; + } + + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + fg_relax(&chip->profile_wakeup_source); + return rc; +update: + cancel_delayed_work(&chip->update_sram_data); + schedule_delayed_work( + &chip->update_sram_data, + msecs_to_jiffies(0)); +reschedule: + schedule_delayed_work( + &chip->batt_profile_init, + msecs_to_jiffies(BATTERY_PSY_WAIT_MS)); + fg_relax(&chip->profile_wakeup_source); + return 0; +} + +static void check_empty_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + check_empty_work.work); + bool vbatt_low_sts; + int msoc; + + /* handle empty soc based on vbatt-low interrupt */ + if (chip->use_vbat_low_empty_soc) { + if (fg_get_vbatt_status(chip, &vbatt_low_sts)) + goto out; + + msoc = get_monotonic_soc_raw(chip); + + if (fg_debug_mask & FG_STATUS) + pr_info("Vbatt_low: %d, msoc: %d\n", vbatt_low_sts, + msoc); + if (vbatt_low_sts || (msoc == 0)) + chip->soc_empty = true; + else + chip->soc_empty = false; + + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + + if (!chip->vbat_low_irq_enabled) { + enable_irq(chip->batt_irq[VBATT_LOW].irq); + enable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = true; + } + } else if (fg_is_batt_empty(chip)) { + if (fg_debug_mask & FG_STATUS) + pr_info("EMPTY SOC high\n"); + chip->soc_empty = true; + if (chip->power_supply_registered) + power_supply_changed(&chip->bms_psy); + } + +out: + fg_relax(&chip->empty_check_wakeup_source); +} + +static void batt_profile_init(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + batt_profile_init.work); + + if (fg_batt_profile_init(chip)) + pr_err("failed to initialize profile\n"); +} + +static void sysfs_restart_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + sysfs_restart_work); + int rc; + + rc = fg_do_restart(chip, false); + if (rc) + pr_err("fg restart failed: %d\n", rc); + mutex_lock(&chip->sysfs_restart_lock); + fg_restart = 0; + mutex_unlock(&chip->sysfs_restart_lock); +} + +#define SRAM_RELEASE_TIMEOUT_MS 500 +static void charge_full_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + charge_full_work); + int rc; + u8 buffer[3]; + int bsoc; + int resume_soc_raw = settings[FG_MEM_RESUME_SOC].value; + bool disable = false; + u8 reg; + int msoc, retry = 0; + + if (chip->status != POWER_SUPPLY_STATUS_FULL) { + if (fg_debug_mask & FG_STATUS) + pr_info("battery not full: %d\n", chip->status); + disable = true; + } + + fg_mem_lock(chip); + rc = fg_mem_read(chip, buffer, BATTERY_SOC_REG, 3, 1, 0); + if (rc) { + pr_err("Unable to read battery soc: %d\n", rc); + goto out; + } + if (buffer[2] <= resume_soc_raw) { + if (fg_debug_mask & FG_STATUS) + pr_info("bsoc = 0x%02x <= resume = 0x%02x\n", + buffer[2], resume_soc_raw); + disable = true; + } + if (!disable) + goto out; + + rc = fg_mem_write(chip, buffer, SOC_FULL_REG, 3, + SOC_FULL_OFFSET, 0); + if (rc) { + pr_err("failed to write SOC_FULL rc=%d\n", rc); + goto out; + } + /* force a full soc value into the monotonic in order to display 100 */ + buffer[0] = 0xFF; + buffer[1] = 0xFF; + rc = fg_mem_write(chip, buffer, SRAM_MONOTONIC_SOC_REG, 2, + SRAM_MONOTONIC_SOC_OFFSET, 0); + if (rc) { + pr_err("failed to write SOC_FULL rc=%d\n", rc); + goto out; + } + if (fg_debug_mask & FG_STATUS) { + bsoc = buffer[0] | buffer[1] << 8 | buffer[2] << 16; + pr_info("wrote %06x into soc full\n", bsoc); + } + fg_mem_release(chip); + + + while(msoc != 0xFF && retry != 8) { + msleep(200); + msoc = get_monotonic_soc_raw(chip); + retry++; + } + + /* + * wait one cycle to make sure the soc is updated before clearing + * the soc mask bit + */ + fg_mem_lock(chip); + fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 0); +out: + fg_mem_release(chip); + if (disable) + chip->charge_full = false; +} + +static void update_bcl_thresholds(struct fg_chip *chip) +{ + u8 data[4]; + u8 mh_offset = 0, lm_offset = 0; + u16 address = 0; + int ret = 0; + + address = settings[FG_MEM_BCL_MH_THRESHOLD].address; + mh_offset = settings[FG_MEM_BCL_MH_THRESHOLD].offset; + lm_offset = settings[FG_MEM_BCL_LM_THRESHOLD].offset; + ret = fg_mem_read(chip, data, address, 4, 0, 1); + if (ret) + pr_err("Error reading BCL LM & MH threshold rc:%d\n", ret); + else + pr_debug("Old BCL LM threshold:%x MH threshold:%x\n", + data[lm_offset], data[mh_offset]); + BCL_MA_TO_ADC(settings[FG_MEM_BCL_MH_THRESHOLD].value, data[mh_offset]); + BCL_MA_TO_ADC(settings[FG_MEM_BCL_LM_THRESHOLD].value, data[lm_offset]); + + ret = fg_mem_write(chip, data, address, 4, 0, 0); + if (ret) + pr_err("spmi write failed. addr:%03x, ret:%d\n", + address, ret); + else + pr_debug("New BCL LM threshold:%x MH threshold:%x\n", + data[lm_offset], data[mh_offset]); +} + +static int disable_bcl_lpm(struct fg_chip *chip) +{ + u8 data[4]; + u8 lm_offset = 0; + u16 address = 0; + int rc = 0; + + address = settings[FG_MEM_BCL_LM_THRESHOLD].address; + lm_offset = settings[FG_MEM_BCL_LM_THRESHOLD].offset; + rc = fg_mem_read(chip, data, address, 4, 0, 1); + if (rc) { + pr_err("Error reading BCL LM & MH threshold rc:%d\n", rc); + return rc; + } + pr_debug("Old BCL LM threshold:%x\n", data[lm_offset]); + + /* Put BCL always above LPM */ + BCL_MA_TO_ADC(0, data[lm_offset]); + + rc = fg_mem_write(chip, data, address, 4, 0, 0); + if (rc) + pr_err("spmi write failed. addr:%03x, rc:%d\n", + address, rc); + else + pr_debug("New BCL LM threshold:%x\n", data[lm_offset]); + + return rc; +} + +static void bcl_hi_power_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + bcl_hi_power_work); + int rc; + + if (chip->bcl_lpm_disabled) { + rc = disable_bcl_lpm(chip); + if (rc) + pr_err("failed to disable bcl low mode %d\n", + rc); + } else { + update_bcl_thresholds(chip); + } +} + +#define VOLT_UV_TO_VOLTCMP8(volt_uv) \ + ((volt_uv - 2500000) / 9766) +static int update_irq_volt_empty(struct fg_chip *chip) +{ + u8 data; + int volt_mv = settings[FG_MEM_IRQ_VOLT_EMPTY].value; + + data = (u8)VOLT_UV_TO_VOLTCMP8(volt_mv * 1000); + + if (fg_debug_mask & FG_STATUS) + pr_info("voltage = %d, converted_raw = %04x\n", volt_mv, data); + return fg_mem_write(chip, &data, + settings[FG_MEM_IRQ_VOLT_EMPTY].address, 1, + settings[FG_MEM_IRQ_VOLT_EMPTY].offset, 0); +} + +static int update_cutoff_voltage(struct fg_chip *chip) +{ + u8 data[2]; + u16 converted_voltage_raw; + s64 voltage_mv = settings[FG_MEM_CUTOFF_VOLTAGE].value; + + converted_voltage_raw = (s16)MICROUNITS_TO_ADC_RAW(voltage_mv * 1000); + data[0] = cpu_to_le16(converted_voltage_raw) & 0xFF; + data[1] = cpu_to_le16(converted_voltage_raw) >> 8; + + if (fg_debug_mask & FG_STATUS) + pr_info("voltage = %lld, converted_raw = %04x, data = %02x %02x\n", + voltage_mv, converted_voltage_raw, data[0], data[1]); + return fg_mem_write(chip, data, settings[FG_MEM_CUTOFF_VOLTAGE].address, + 2, settings[FG_MEM_CUTOFF_VOLTAGE].offset, 0); +} + +static int update_iterm(struct fg_chip *chip) +{ + u8 data[2]; + u16 converted_current_raw; + s64 current_ma = -settings[FG_MEM_TERM_CURRENT].value; + + converted_current_raw = (s16)MICROUNITS_TO_ADC_RAW(current_ma * 1000); + data[0] = cpu_to_le16(converted_current_raw) & 0xFF; + data[1] = cpu_to_le16(converted_current_raw) >> 8; + + if (fg_debug_mask & FG_STATUS) + pr_info("current = %lld, converted_raw = %04x, data = %02x %02x\n", + current_ma, converted_current_raw, data[0], data[1]); + return fg_mem_write(chip, data, settings[FG_MEM_TERM_CURRENT].address, + 2, settings[FG_MEM_TERM_CURRENT].offset, 0); +} + +#define OF_READ_SETTING(type, qpnp_dt_property, retval, optional) \ +do { \ + if (retval) \ + break; \ + \ + retval = of_property_read_u32(chip->spmi->dev.of_node, \ + "qcom," qpnp_dt_property, \ + &settings[type].value); \ + \ + if ((retval == -EINVAL) && optional) \ + retval = 0; \ + else if (retval) \ + pr_err("Error reading " #qpnp_dt_property \ + " property rc = %d\n", rc); \ +} while (0) + +#define OF_READ_PROPERTY(store, qpnp_dt_property, retval, default_val) \ +do { \ + if (retval) \ + break; \ + \ + retval = of_property_read_u32(chip->spmi->dev.of_node, \ + "qcom," qpnp_dt_property, \ + &store); \ + \ + if (retval == -EINVAL) { \ + retval = 0; \ + store = default_val; \ + } else if (retval) { \ + pr_err("Error reading " #qpnp_dt_property \ + " property rc = %d\n", rc); \ + } \ +} while (0) + +static int fg_dischg_gain_dt_init(struct fg_chip *chip) +{ + struct device_node *node = chip->spmi->dev.of_node; + struct property *prop; + int i, rc = 0; + size_t size; + + prop = of_find_property(node, "qcom,fg-dischg-voltage-gain-soc", + NULL); + if (!prop) { + pr_err("qcom-fg-dischg-voltage-gain-soc not specified\n"); + goto out; + } + + size = prop->length / sizeof(u32); + if (size != VOLT_GAIN_MAX) { + pr_err("Voltage gain SOC specified is of incorrect size\n"); + goto out; + } + + rc = of_property_read_u32_array(node, + "qcom,fg-dischg-voltage-gain-soc", chip->dischg_gain.soc, size); + if (rc < 0) { + pr_err("Reading qcom-fg-dischg-voltage-gain-soc failed, rc=%d\n", + rc); + goto out; + } + + for (i = 0; i < VOLT_GAIN_MAX; i++) { + if (chip->dischg_gain.soc[i] < 0 || + chip->dischg_gain.soc[i] > 100) { + pr_err("Incorrect dischg-voltage-gain-soc\n"); + goto out; + } + } + + prop = of_find_property(node, "qcom,fg-dischg-med-voltage-gain", + NULL); + if (!prop) { + pr_err("qcom-fg-dischg-med-voltage-gain not specified\n"); + goto out; + } + + size = prop->length / sizeof(u32); + if (size != VOLT_GAIN_MAX) { + pr_err("med-voltage-gain specified is of incorrect size\n"); + goto out; + } + + rc = of_property_read_u32_array(node, + "qcom,fg-dischg-med-voltage-gain", chip->dischg_gain.medc_gain, + size); + if (rc < 0) { + pr_err("Reading qcom-fg-dischg-med-voltage-gain failed, rc=%d\n", + rc); + goto out; + } + + prop = of_find_property(node, "qcom,fg-dischg-high-voltage-gain", + NULL); + if (!prop) { + pr_err("qcom-fg-dischg-high-voltage-gain not specified\n"); + goto out; + } + + size = prop->length / sizeof(u32); + if (size != VOLT_GAIN_MAX) { + pr_err("high-voltage-gain specified is of incorrect size\n"); + goto out; + } + + rc = of_property_read_u32_array(node, + "qcom,fg-dischg-high-voltage-gain", + chip->dischg_gain.highc_gain, size); + if (rc < 0) { + pr_err("Reading qcom-fg-dischg-high-voltage-gain failed, rc=%d\n", + rc); + goto out; + } + + if (fg_debug_mask & FG_STATUS) { + for (i = 0; i < VOLT_GAIN_MAX; i++) + pr_info("SOC:%d MedC_Gain:%d HighC_Gain: %d\n", + chip->dischg_gain.soc[i], + chip->dischg_gain.medc_gain[i], + chip->dischg_gain.highc_gain[i]); + } + return 0; +out: + chip->dischg_gain.enable = false; + return rc; +} + +#define DEFAULT_EVALUATION_CURRENT_MA 1000 +static int fg_of_init(struct fg_chip *chip) +{ + int rc = 0, sense_type, len = 0; + const char *data; + struct device_node *node = chip->spmi->dev.of_node; + u32 temp[2] = {0}; + + OF_READ_SETTING(FG_MEM_SOFT_HOT, "warm-bat-decidegc", rc, 1); + OF_READ_SETTING(FG_MEM_SOFT_COLD, "cool-bat-decidegc", rc, 1); + OF_READ_SETTING(FG_MEM_HARD_HOT, "hot-bat-decidegc", rc, 1); + OF_READ_SETTING(FG_MEM_HARD_COLD, "cold-bat-decidegc", rc, 1); + + if (of_find_property(node, "qcom,cold-hot-jeita-hysteresis", NULL)) { + int hard_hot = 0, soft_hot = 0, hard_cold = 0, soft_cold = 0; + + rc = of_property_read_u32_array(node, + "qcom,cold-hot-jeita-hysteresis", temp, 2); + if (rc) { + pr_err("Error reading cold-hot-jeita-hysteresis rc=%d\n", + rc); + return rc; + } + + chip->jeita_hysteresis_support = true; + chip->cold_hysteresis = temp[0]; + chip->hot_hysteresis = temp[1]; + hard_hot = settings[FG_MEM_HARD_HOT].value; + soft_hot = settings[FG_MEM_SOFT_HOT].value; + hard_cold = settings[FG_MEM_HARD_COLD].value; + soft_cold = settings[FG_MEM_SOFT_COLD].value; + if (((hard_hot - chip->hot_hysteresis) < soft_hot) || + ((hard_cold + chip->cold_hysteresis) > soft_cold)) { + chip->jeita_hysteresis_support = false; + pr_err("invalid hysteresis: hot_hysterresis = %d cold_hysteresis = %d\n", + chip->hot_hysteresis, chip->cold_hysteresis); + } else { + pr_debug("cold_hysteresis = %d, hot_hysteresis = %d\n", + chip->cold_hysteresis, chip->hot_hysteresis); + } + } + + OF_READ_SETTING(FG_MEM_BCL_LM_THRESHOLD, "bcl-lm-threshold-ma", + rc, 1); + OF_READ_SETTING(FG_MEM_BCL_MH_THRESHOLD, "bcl-mh-threshold-ma", + rc, 1); + OF_READ_SETTING(FG_MEM_TERM_CURRENT, "fg-iterm-ma", rc, 1); + OF_READ_SETTING(FG_MEM_CHG_TERM_CURRENT, "fg-chg-iterm-ma", rc, 1); + OF_READ_SETTING(FG_MEM_CUTOFF_VOLTAGE, "fg-cutoff-voltage-mv", rc, 1); + data = of_get_property(chip->spmi->dev.of_node, + "qcom,thermal-coefficients", &len); + if (data && len == THERMAL_COEFF_N_BYTES) { + memcpy(chip->thermal_coefficients, data, len); + chip->use_thermal_coefficients = true; + } + OF_READ_SETTING(FG_MEM_RESUME_SOC, "resume-soc", rc, 1); + settings[FG_MEM_RESUME_SOC].value = + DIV_ROUND_CLOSEST(settings[FG_MEM_RESUME_SOC].value + * FULL_SOC_RAW, FULL_CAPACITY); + OF_READ_SETTING(FG_MEM_RESUME_SOC, "resume-soc-raw", rc, 1); + OF_READ_SETTING(FG_MEM_IRQ_VOLT_EMPTY, "irq-volt-empty-mv", rc, 1); + OF_READ_SETTING(FG_MEM_VBAT_EST_DIFF, "vbat-estimate-diff-mv", rc, 1); + OF_READ_SETTING(FG_MEM_DELTA_SOC, "fg-delta-soc", rc, 1); + OF_READ_SETTING(FG_MEM_BATT_LOW, "fg-vbatt-low-threshold", rc, 1); + OF_READ_SETTING(FG_MEM_THERM_DELAY, "fg-therm-delay-us", rc, 1); + OF_READ_PROPERTY(chip->learning_data.max_increment, + "cl-max-increment-deciperc", rc, 5); + OF_READ_PROPERTY(chip->learning_data.max_decrement, + "cl-max-decrement-deciperc", rc, 100); + OF_READ_PROPERTY(chip->learning_data.max_temp, + "cl-max-temp-decidegc", rc, 450); + OF_READ_PROPERTY(chip->learning_data.min_temp, + "cl-min-temp-decidegc", rc, 150); + OF_READ_PROPERTY(chip->learning_data.max_start_soc, + "cl-max-start-capacity", rc, 15); + OF_READ_PROPERTY(chip->learning_data.vbat_est_thr_uv, + "cl-vbat-est-thr-uv", rc, 40000); + OF_READ_PROPERTY(chip->learning_data.max_cap_limit, + "cl-max-limit-deciperc", rc, 0); + OF_READ_PROPERTY(chip->learning_data.min_cap_limit, + "cl-min-limit-deciperc", rc, 0); + OF_READ_PROPERTY(chip->evaluation_current, + "aging-eval-current-ma", rc, + DEFAULT_EVALUATION_CURRENT_MA); + OF_READ_PROPERTY(chip->cc_cv_threshold_mv, + "fg-cc-cv-threshold-mv", rc, 0); + if (of_property_read_bool(chip->spmi->dev.of_node, + "qcom,capacity-learning-on")) + chip->batt_aging_mode = FG_AGING_CC; + else if (of_property_read_bool(chip->spmi->dev.of_node, + "qcom,capacity-estimation-on")) + chip->batt_aging_mode = FG_AGING_ESR; + else + chip->batt_aging_mode = FG_AGING_NONE; + if (chip->batt_aging_mode == FG_AGING_CC) { + chip->learning_data.feedback_on = of_property_read_bool( + chip->spmi->dev.of_node, + "qcom,capacity-learning-feedback"); + } + if (fg_debug_mask & FG_AGING) + pr_info("battery aging mode: %d\n", chip->batt_aging_mode); + + /* Get the use-otp-profile property */ + chip->use_otp_profile = of_property_read_bool( + chip->spmi->dev.of_node, + "qcom,use-otp-profile"); + chip->hold_soc_while_full = of_property_read_bool( + chip->spmi->dev.of_node, + "qcom,hold-soc-while-full"); + + sense_type = of_property_read_bool(chip->spmi->dev.of_node, + "qcom,ext-sense-type"); + if (rc == 0) { + if (fg_sense_type < 0) + fg_sense_type = sense_type; + + if (fg_debug_mask & FG_STATUS) { + if (fg_sense_type == INTERNAL_CURRENT_SENSE) + pr_info("Using internal sense\n"); + else if (fg_sense_type == EXTERNAL_CURRENT_SENSE) + pr_info("Using external sense\n"); + else + pr_info("Using default sense\n"); + } + } else { + rc = 0; + } + + chip->bad_batt_detection_en = of_property_read_bool(node, + "qcom,bad-battery-detection-enable"); + + chip->sw_rbias_ctrl = of_property_read_bool(node, + "qcom,sw-rbias-control"); + + chip->cyc_ctr.en = of_property_read_bool(node, + "qcom,cycle-counter-en"); + if (chip->cyc_ctr.en) + chip->cyc_ctr.id = 1; + + chip->esr_pulse_tune_en = of_property_read_bool(node, + "qcom,esr-pulse-tuning-en"); + + chip->soc_slope_limiter_en = of_property_read_bool(node, + "qcom,fg-control-slope-limiter"); + if (chip->soc_slope_limiter_en) { + OF_READ_PROPERTY(chip->slope_limit_temp, + "fg-slope-limit-temp-threshold", rc, + SLOPE_LIMIT_TEMP_THRESHOLD); + + OF_READ_PROPERTY(chip->slope_limit_coeffs[LOW_TEMP_CHARGE], + "fg-slope-limit-low-temp-chg", rc, + SLOPE_LIMIT_LOW_TEMP_CHG); + + OF_READ_PROPERTY(chip->slope_limit_coeffs[HIGH_TEMP_CHARGE], + "fg-slope-limit-high-temp-chg", rc, + SLOPE_LIMIT_HIGH_TEMP_CHG); + + OF_READ_PROPERTY(chip->slope_limit_coeffs[LOW_TEMP_DISCHARGE], + "fg-slope-limit-low-temp-dischg", rc, + SLOPE_LIMIT_LOW_TEMP_DISCHG); + + OF_READ_PROPERTY(chip->slope_limit_coeffs[HIGH_TEMP_DISCHARGE], + "fg-slope-limit-high-temp-dischg", rc, + SLOPE_LIMIT_HIGH_TEMP_DISCHG); + + if (fg_debug_mask & FG_STATUS) + pr_info("slope-limiter, temp: %d coeffs: [%d %d %d %d]\n", + chip->slope_limit_temp, + chip->slope_limit_coeffs[LOW_TEMP_CHARGE], + chip->slope_limit_coeffs[HIGH_TEMP_CHARGE], + chip->slope_limit_coeffs[LOW_TEMP_DISCHARGE], + chip->slope_limit_coeffs[HIGH_TEMP_DISCHARGE]); + } + + OF_READ_PROPERTY(chip->rconn_mohm, "fg-rconn-mohm", rc, 0); + + chip->dischg_gain.enable = of_property_read_bool(node, + "qcom,fg-dischg-voltage-gain-ctrl"); + if (chip->dischg_gain.enable) { + rc = fg_dischg_gain_dt_init(chip); + if (rc) { + pr_err("Error in reading dischg_gain parameters, rc=%d\n", + rc); + rc = 0; + } + } + + chip->use_vbat_low_empty_soc = of_property_read_bool(node, + "qcom,fg-use-vbat-low-empty-soc"); + + OF_READ_PROPERTY(chip->batt_temp_low_limit, + "fg-batt-temp-low-limit", rc, BATT_TEMP_LOW_LIMIT); + + OF_READ_PROPERTY(chip->batt_temp_high_limit, + "fg-batt-temp-high-limit", rc, BATT_TEMP_HIGH_LIMIT); + + if (fg_debug_mask & FG_STATUS) + pr_info("batt-temp-low_limit: %d batt-temp-high_limit: %d\n", + chip->batt_temp_low_limit, chip->batt_temp_high_limit); + + OF_READ_PROPERTY(chip->cc_soc_limit_pct, "fg-cc-soc-limit-pct", rc, 0); + + if (fg_debug_mask & FG_STATUS) + pr_info("cc-soc-limit-pct: %d\n", chip->cc_soc_limit_pct); + + chip->batt_info_restore = of_property_read_bool(node, + "qcom,fg-restore-batt-info"); + + if (fg_debug_mask & FG_STATUS) + pr_info("restore: %d validate_by_ocv: %d range_pct: %d\n", + chip->batt_info_restore, fg_batt_valid_ocv, + fg_batt_range_pct); + + return rc; +} + +static int fg_init_irqs(struct fg_chip *chip) +{ + int rc = 0; + struct resource *resource; + struct spmi_resource *spmi_resource; + u8 subtype; + struct spmi_device *spmi = chip->spmi; + + spmi_for_each_container_dev(spmi_resource, spmi) { + if (!spmi_resource) { + pr_err("fg: spmi resource absent\n"); + return rc; + } + + resource = spmi_get_resource(spmi, spmi_resource, + IORESOURCE_MEM, 0); + if (!(resource && resource->start)) { + pr_err("node %s IO resource absent!\n", + spmi->dev.of_node->full_name); + return rc; + } + + if ((resource->start == chip->vbat_adc_addr) || + (resource->start == chip->ibat_adc_addr) || + (resource->start == chip->tp_rev_addr)) + continue; + + rc = fg_read(chip, &subtype, + resource->start + REG_OFFSET_PERP_SUBTYPE, 1); + if (rc) { + pr_err("Peripheral subtype read failed rc=%d\n", rc); + return rc; + } + + switch (subtype) { + case FG_SOC: + chip->soc_irq[FULL_SOC].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, "full-soc"); + if (chip->soc_irq[FULL_SOC].irq < 0) { + pr_err("Unable to get full-soc irq\n"); + return rc; + } + chip->soc_irq[EMPTY_SOC].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, "empty-soc"); + if (chip->soc_irq[EMPTY_SOC].irq < 0) { + pr_err("Unable to get empty-soc irq\n"); + return rc; + } + chip->soc_irq[DELTA_SOC].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, "delta-soc"); + if (chip->soc_irq[DELTA_SOC].irq < 0) { + pr_err("Unable to get delta-soc irq\n"); + return rc; + } + chip->soc_irq[FIRST_EST_DONE].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, "first-est-done"); + if (chip->soc_irq[FIRST_EST_DONE].irq < 0) { + pr_err("Unable to get first-est-done irq\n"); + return rc; + } + + rc = devm_request_irq(chip->dev, + chip->soc_irq[FULL_SOC].irq, + fg_soc_irq_handler, IRQF_TRIGGER_RISING, + "full-soc", chip); + if (rc < 0) { + pr_err("Can't request %d full-soc: %d\n", + chip->soc_irq[FULL_SOC].irq, rc); + return rc; + } + enable_irq_wake(chip->soc_irq[FULL_SOC].irq); + chip->full_soc_irq_enabled = true; + + if (!chip->use_vbat_low_empty_soc) { + rc = devm_request_irq(chip->dev, + chip->soc_irq[EMPTY_SOC].irq, + fg_empty_soc_irq_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "empty-soc", chip); + if (rc < 0) { + pr_err("Can't request %d empty-soc: %d\n", + chip->soc_irq[EMPTY_SOC].irq, + rc); + return rc; + } + } + + rc = devm_request_irq(chip->dev, + chip->soc_irq[DELTA_SOC].irq, + fg_soc_irq_handler, IRQF_TRIGGER_RISING, + "delta-soc", chip); + if (rc < 0) { + pr_err("Can't request %d delta-soc: %d\n", + chip->soc_irq[DELTA_SOC].irq, rc); + return rc; + } + rc = devm_request_irq(chip->dev, + chip->soc_irq[FIRST_EST_DONE].irq, + fg_first_soc_irq_handler, IRQF_TRIGGER_RISING, + "first-est-done", chip); + if (rc < 0) { + pr_err("Can't request %d delta-soc: %d\n", + chip->soc_irq[FIRST_EST_DONE].irq, rc); + return rc; + } + + enable_irq_wake(chip->soc_irq[DELTA_SOC].irq); + if (!chip->use_vbat_low_empty_soc) + enable_irq_wake(chip->soc_irq[EMPTY_SOC].irq); + break; + case FG_MEMIF: + chip->mem_irq[FG_MEM_AVAIL].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, "mem-avail"); + if (chip->mem_irq[FG_MEM_AVAIL].irq < 0) { + pr_err("Unable to get mem-avail irq\n"); + return rc; + } + rc = devm_request_irq(chip->dev, + chip->mem_irq[FG_MEM_AVAIL].irq, + fg_mem_avail_irq_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "mem-avail", chip); + if (rc < 0) { + pr_err("Can't request %d mem-avail: %d\n", + chip->mem_irq[FG_MEM_AVAIL].irq, rc); + return rc; + } + break; + case FG_BATT: + chip->batt_irq[JEITA_SOFT_COLD].irq = + spmi_get_irq_byname(chip->spmi, spmi_resource, + "soft-cold"); + if (chip->batt_irq[JEITA_SOFT_COLD].irq < 0) { + pr_err("Unable to get soft-cold irq\n"); + rc = -EINVAL; + return rc; + } + rc = devm_request_threaded_irq(chip->dev, + chip->batt_irq[JEITA_SOFT_COLD].irq, + NULL, + fg_jeita_soft_cold_irq_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "soft-cold", chip); + if (rc < 0) { + pr_err("Can't request %d soft-cold: %d\n", + chip->batt_irq[JEITA_SOFT_COLD].irq, + rc); + return rc; + } + disable_irq(chip->batt_irq[JEITA_SOFT_COLD].irq); + chip->batt_irq[JEITA_SOFT_COLD].disabled = true; + chip->batt_irq[JEITA_SOFT_HOT].irq = + spmi_get_irq_byname(chip->spmi, spmi_resource, + "soft-hot"); + if (chip->batt_irq[JEITA_SOFT_HOT].irq < 0) { + pr_err("Unable to get soft-hot irq\n"); + rc = -EINVAL; + return rc; + } + rc = devm_request_threaded_irq(chip->dev, + chip->batt_irq[JEITA_SOFT_HOT].irq, + NULL, + fg_jeita_soft_hot_irq_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "soft-hot", chip); + if (rc < 0) { + pr_err("Can't request %d soft-hot: %d\n", + chip->batt_irq[JEITA_SOFT_HOT].irq, rc); + return rc; + } + disable_irq(chip->batt_irq[JEITA_SOFT_HOT].irq); + chip->batt_irq[JEITA_SOFT_HOT].disabled = true; + chip->batt_irq[BATT_MISSING].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, + "batt-missing"); + if (chip->batt_irq[BATT_MISSING].irq < 0) { + pr_err("Unable to get batt-missing irq\n"); + rc = -EINVAL; + return rc; + } + rc = devm_request_threaded_irq(chip->dev, + chip->batt_irq[BATT_MISSING].irq, + NULL, + fg_batt_missing_irq_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT, + "batt-missing", chip); + if (rc < 0) { + pr_err("Can't request %d batt-missing: %d\n", + chip->batt_irq[BATT_MISSING].irq, rc); + return rc; + } + chip->batt_irq[VBATT_LOW].irq = spmi_get_irq_byname( + chip->spmi, spmi_resource, + "vbatt-low"); + if (chip->batt_irq[VBATT_LOW].irq < 0) { + pr_err("Unable to get vbatt-low irq\n"); + rc = -EINVAL; + return rc; + } + rc = devm_request_irq(chip->dev, + chip->batt_irq[VBATT_LOW].irq, + fg_vbatt_low_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "vbatt-low", chip); + if (rc < 0) { + pr_err("Can't request %d vbatt-low: %d\n", + chip->batt_irq[VBATT_LOW].irq, rc); + return rc; + } + if (chip->use_vbat_low_empty_soc) { + enable_irq_wake(chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = true; + } else { + disable_irq_nosync( + chip->batt_irq[VBATT_LOW].irq); + chip->vbat_low_irq_enabled = false; + } + break; + case FG_ADC: + break; + default: + pr_err("subtype %d\n", subtype); + return -EINVAL; + } + } + + chip->irqs_enabled = true; + return rc; +} + +static void fg_cancel_all_works(struct fg_chip *chip) +{ + cancel_delayed_work_sync(&chip->check_sanity_work); + cancel_delayed_work_sync(&chip->update_sram_data); + cancel_delayed_work_sync(&chip->update_temp_work); + cancel_delayed_work_sync(&chip->update_jeita_setting); + cancel_delayed_work_sync(&chip->check_empty_work); + cancel_delayed_work_sync(&chip->batt_profile_init); + alarm_try_to_cancel(&chip->fg_cap_learning_alarm); + alarm_try_to_cancel(&chip->hard_jeita_alarm); + if (!chip->ima_error_handling) + cancel_work_sync(&chip->ima_error_recovery_work); + cancel_work_sync(&chip->rslow_comp_work); + cancel_work_sync(&chip->set_resume_soc_work); + cancel_work_sync(&chip->fg_cap_learning_work); + cancel_work_sync(&chip->dump_sram); + cancel_work_sync(&chip->status_change_work); + cancel_work_sync(&chip->cycle_count_work); + cancel_work_sync(&chip->update_esr_work); + cancel_work_sync(&chip->sysfs_restart_work); + cancel_work_sync(&chip->gain_comp_work); + cancel_work_sync(&chip->init_work); + cancel_work_sync(&chip->charge_full_work); + cancel_work_sync(&chip->bcl_hi_power_work); + cancel_work_sync(&chip->esr_extract_config_work); + cancel_work_sync(&chip->slope_limiter_work); + cancel_work_sync(&chip->dischg_gain_work); + cancel_work_sync(&chip->cc_soc_store_work); +} + +static void fg_cleanup(struct fg_chip *chip) +{ + fg_cancel_all_works(chip); + power_supply_unregister(&chip->bms_psy); + mutex_destroy(&chip->rslow_comp.lock); + mutex_destroy(&chip->rw_lock); + mutex_destroy(&chip->cyc_ctr.lock); + mutex_destroy(&chip->learning_data.learning_lock); + mutex_destroy(&chip->sysfs_restart_lock); + mutex_destroy(&chip->ima_recovery_lock); + wakeup_source_trash(&chip->resume_soc_wakeup_source.source); + wakeup_source_trash(&chip->empty_check_wakeup_source.source); + wakeup_source_trash(&chip->memif_wakeup_source.source); + wakeup_source_trash(&chip->profile_wakeup_source.source); + wakeup_source_trash(&chip->update_temp_wakeup_source.source); + wakeup_source_trash(&chip->update_sram_wakeup_source.source); + wakeup_source_trash(&chip->gain_comp_wakeup_source.source); + wakeup_source_trash(&chip->capacity_learning_wakeup_source.source); + wakeup_source_trash(&chip->esr_extract_wakeup_source.source); + wakeup_source_trash(&chip->slope_limit_wakeup_source.source); + wakeup_source_trash(&chip->dischg_gain_wakeup_source.source); + wakeup_source_trash(&chip->fg_reset_wakeup_source.source); + wakeup_source_trash(&chip->cc_soc_wakeup_source.source); + wakeup_source_trash(&chip->sanity_wakeup_source.source); +} + +static int fg_remove(struct spmi_device *spmi) +{ + struct fg_chip *chip = dev_get_drvdata(&spmi->dev); + + fg_cleanup(chip); + dev_set_drvdata(&spmi->dev, NULL); + return 0; +} + +static int fg_memif_data_open(struct inode *inode, struct file *file) +{ + struct fg_log_buffer *log; + struct fg_trans *trans; + u8 *data_buf; + + size_t logbufsize = SZ_4K; + size_t databufsize = SZ_4K; + + if (!dbgfs_data.chip) { + pr_err("Not initialized data\n"); + return -EINVAL; + } + + /* Per file "transaction" data */ + trans = kzalloc(sizeof(*trans), GFP_KERNEL); + if (!trans) { + pr_err("Unable to allocate memory for transaction data\n"); + return -ENOMEM; + } + + /* Allocate log buffer */ + log = kzalloc(logbufsize, GFP_KERNEL); + + if (!log) { + kfree(trans); + pr_err("Unable to allocate memory for log buffer\n"); + return -ENOMEM; + } + + log->rpos = 0; + log->wpos = 0; + log->len = logbufsize - sizeof(*log); + + /* Allocate data buffer */ + data_buf = kzalloc(databufsize, GFP_KERNEL); + + if (!data_buf) { + kfree(trans); + kfree(log); + pr_err("Unable to allocate memory for data buffer\n"); + return -ENOMEM; + } + + trans->log = log; + trans->data = data_buf; + trans->cnt = dbgfs_data.cnt; + trans->addr = dbgfs_data.addr; + trans->chip = dbgfs_data.chip; + trans->offset = trans->addr; + mutex_init(&trans->memif_dfs_lock); + + file->private_data = trans; + return 0; +} + +static int fg_memif_dfs_close(struct inode *inode, struct file *file) +{ + struct fg_trans *trans = file->private_data; + + if (trans && trans->log && trans->data) { + file->private_data = NULL; + mutex_destroy(&trans->memif_dfs_lock); + kfree(trans->log); + kfree(trans->data); + kfree(trans); + } + + return 0; +} + +/** + * print_to_log: format a string and place into the log buffer + * @log: The log buffer to place the result into. + * @fmt: The format string to use. + * @...: The arguments for the format string. + * + * The return value is the number of characters written to @log buffer + * not including the trailing '\0'. + */ +static int print_to_log(struct fg_log_buffer *log, const char *fmt, ...) +{ + va_list args; + int cnt; + char *buf = &log->data[log->wpos]; + size_t size = log->len - log->wpos; + + va_start(args, fmt); + cnt = vscnprintf(buf, size, fmt, args); + va_end(args); + + log->wpos += cnt; + return cnt; +} + +/** + * write_next_line_to_log: Writes a single "line" of data into the log buffer + * @trans: Pointer to SRAM transaction data. + * @offset: SRAM address offset to start reading from. + * @pcnt: Pointer to 'cnt' variable. Indicates the number of bytes to read. + * + * The 'offset' is a 12-bit SRAM address. + * + * On a successful read, the pcnt is decremented by the number of data + * bytes read from the SRAM. When the cnt reaches 0, all requested bytes have + * been read. + */ +static int +write_next_line_to_log(struct fg_trans *trans, int offset, size_t *pcnt) +{ + int i, j; + u8 data[ITEMS_PER_LINE]; + struct fg_log_buffer *log = trans->log; + + int cnt = 0; + int padding = offset % ITEMS_PER_LINE; + int items_to_read = min(ARRAY_SIZE(data) - padding, *pcnt); + int items_to_log = min(ITEMS_PER_LINE, padding + items_to_read); + + /* Buffer needs enough space for an entire line */ + if ((log->len - log->wpos) < MAX_LINE_LENGTH) + goto done; + + memcpy(data, trans->data + (offset - trans->addr), items_to_read); + + *pcnt -= items_to_read; + + /* Each line starts with the aligned offset (12-bit address) */ + cnt = print_to_log(log, "%3.3X ", offset & 0xfff); + if (cnt == 0) + goto done; + + /* If the offset is unaligned, add padding to right justify items */ + for (i = 0; i < padding; ++i) { + cnt = print_to_log(log, "-- "); + if (cnt == 0) + goto done; + } + + /* Log the data items */ + for (j = 0; i < items_to_log; ++i, ++j) { + cnt = print_to_log(log, "%2.2X ", data[j]); + if (cnt == 0) + goto done; + } + + /* If the last character was a space, then replace it with a newline */ + if (log->wpos > 0 && log->data[log->wpos - 1] == ' ') + log->data[log->wpos - 1] = '\n'; + +done: + return cnt; +} + +/** + * get_log_data - reads data from SRAM and saves to the log buffer + * @trans: Pointer to SRAM transaction data. + * + * Returns the number of "items" read or SPMI error code for read failures. + */ +static int get_log_data(struct fg_trans *trans) +{ + int cnt, rc; + int last_cnt; + int items_read; + int total_items_read = 0; + u32 offset = trans->offset; + size_t item_cnt = trans->cnt; + struct fg_log_buffer *log = trans->log; + + if (item_cnt == 0) + return 0; + + if (item_cnt > SZ_4K) { + pr_err("Reading too many bytes\n"); + return -EINVAL; + } + + rc = fg_mem_read(trans->chip, trans->data, + trans->addr, trans->cnt, 0, 0); + if (rc) { + pr_err("dump failed: rc = %d\n", rc); + return rc; + } + /* Reset the log buffer 'pointers' */ + log->wpos = log->rpos = 0; + + /* Keep reading data until the log is full */ + do { + last_cnt = item_cnt; + cnt = write_next_line_to_log(trans, offset, &item_cnt); + items_read = last_cnt - item_cnt; + offset += items_read; + total_items_read += items_read; + } while (cnt && item_cnt > 0); + + /* Adjust the transaction offset and count */ + trans->cnt = item_cnt; + trans->offset += total_items_read; + + return total_items_read; +} + +/** + * fg_memif_dfs_reg_read: reads value(s) from SRAM and fills user's buffer a + * byte array (coded as string) + * @file: file pointer + * @buf: where to put the result + * @count: maximum space available in @buf + * @ppos: starting position + * @return number of user bytes read, or negative error value + */ +static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct fg_trans *trans = file->private_data; + struct fg_log_buffer *log = trans->log; + size_t ret; + size_t len; + + mutex_lock(&trans->memif_dfs_lock); + /* Is the the log buffer empty */ + if (log->rpos >= log->wpos) { + if (get_log_data(trans) <= 0) { + len = 0; + goto unlock_mutex; + } + } + + len = min(count, log->wpos - log->rpos); + + ret = copy_to_user(buf, &log->data[log->rpos], len); + if (ret == len) { + pr_err("error copy sram register values to user\n"); + len = -EFAULT; + goto unlock_mutex; + } + + /* 'ret' is the number of bytes not copied */ + len -= ret; + + *ppos += len; + log->rpos += len; + +unlock_mutex: + mutex_unlock(&trans->memif_dfs_lock); + return len; +} + +/** + * fg_memif_dfs_reg_write: write user's byte array (coded as string) to SRAM. + * @file: file pointer + * @buf: user data to be written. + * @count: maximum space available in @buf + * @ppos: starting position + * @return number of user byte written, or negative error value + */ +static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + int bytes_read; + int data; + int pos = 0; + int cnt = 0; + u8 *values; + size_t ret = 0; + char *kbuf; + u32 offset; + + struct fg_trans *trans = file->private_data; + + mutex_lock(&trans->memif_dfs_lock); + offset = trans->offset; + + /* Make a copy of the user data */ + kbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kbuf) { + ret = -ENOMEM; + goto unlock_mutex; + } + + ret = copy_from_user(kbuf, buf, count); + if (ret == count) { + pr_err("failed to copy data from user\n"); + ret = -EFAULT; + goto free_buf; + } + + count -= ret; + *ppos += count; + kbuf[count] = '\0'; + + /* Override the text buffer with the raw data */ + values = kbuf; + + /* Parse the data in the buffer. It should be a string of numbers */ + while (sscanf(kbuf + pos, "%i%n", &data, &bytes_read) == 1) { + pos += bytes_read; + values[cnt++] = data & 0xff; + } + + if (!cnt) + goto free_buf; + + pr_info("address %x, count %d\n", offset, cnt); + /* Perform the write(s) */ + + ret = fg_mem_write(trans->chip, values, offset, + cnt, 0, 0); + if (ret) { + pr_err("SPMI write failed, err = %zu\n", ret); + } else { + ret = count; + trans->offset += cnt > 4 ? 4 : cnt; + } + +free_buf: + kfree(kbuf); +unlock_mutex: + mutex_unlock(&trans->memif_dfs_lock); + return ret; +} + +static const struct file_operations fg_memif_dfs_reg_fops = { + .open = fg_memif_data_open, + .release = fg_memif_dfs_close, + .read = fg_memif_dfs_reg_read, + .write = fg_memif_dfs_reg_write, +}; + +/** + * fg_dfs_create_fs: create debugfs file system. + * @return pointer to root directory or NULL if failed to create fs + */ +static struct dentry *fg_dfs_create_fs(void) +{ + struct dentry *root, *file; + + pr_debug("Creating FG_MEM debugfs file-system\n"); + root = debugfs_create_dir(DFS_ROOT_NAME, NULL); + if (IS_ERR_OR_NULL(root)) { + pr_err("Error creating top level directory err:%ld", + (long)root); + if (PTR_ERR(root) == -ENODEV) + pr_err("debugfs is not enabled in the kernel"); + return NULL; + } + + dbgfs_data.help_msg.size = strlen(dbgfs_data.help_msg.data); + + file = debugfs_create_blob("help", S_IRUGO, root, &dbgfs_data.help_msg); + if (!file) { + pr_err("error creating help entry\n"); + goto err_remove_fs; + } + return root; + +err_remove_fs: + debugfs_remove_recursive(root); + return NULL; +} + +/** + * fg_dfs_get_root: return a pointer to FG debugfs root directory. + * @return a pointer to the existing directory, or if no root + * directory exists then create one. Directory is created with file that + * configures SRAM transaction, namely: address, and count. + * @returns valid pointer on success or NULL + */ +struct dentry *fg_dfs_get_root(void) +{ + if (dbgfs_data.root) + return dbgfs_data.root; + + if (mutex_lock_interruptible(&dbgfs_data.lock) < 0) + return NULL; + /* critical section */ + if (!dbgfs_data.root) { /* double checking idiom */ + dbgfs_data.root = fg_dfs_create_fs(); + } + mutex_unlock(&dbgfs_data.lock); + return dbgfs_data.root; +} + +/* + * fg_dfs_create: adds new fg_mem if debugfs entry + * @return zero on success + */ +int fg_dfs_create(struct fg_chip *chip) +{ + struct dentry *root; + struct dentry *file; + + root = fg_dfs_get_root(); + if (!root) + return -ENOENT; + + dbgfs_data.chip = chip; + + file = debugfs_create_u32("count", DFS_MODE, root, &(dbgfs_data.cnt)); + if (!file) { + pr_err("error creating 'count' entry\n"); + goto err_remove_fs; + } + + file = debugfs_create_x32("address", DFS_MODE, + root, &(dbgfs_data.addr)); + if (!file) { + pr_err("error creating 'address' entry\n"); + goto err_remove_fs; + } + + file = debugfs_create_file("data", DFS_MODE, root, &dbgfs_data, + &fg_memif_dfs_reg_fops); + if (!file) { + pr_err("error creating 'data' entry\n"); + goto err_remove_fs; + } + + return 0; + +err_remove_fs: + debugfs_remove_recursive(root); + return -ENOMEM; +} + +#define EXTERNAL_SENSE_OFFSET_REG 0x41C +#define EXT_OFFSET_TRIM_REG 0xF8 +#define SEC_ACCESS_REG 0xD0 +#define SEC_ACCESS_UNLOCK 0xA5 +#define BCL_TRIM_REV_FIXED 12 +static int bcl_trim_workaround(struct fg_chip *chip) +{ + u8 reg, rc; + + if (chip->tp_rev_addr == 0) + return 0; + + rc = fg_read(chip, ®, chip->tp_rev_addr, 1); + if (rc) { + pr_err("Failed to read tp reg, rc = %d\n", rc); + return rc; + } + if (reg >= BCL_TRIM_REV_FIXED) { + if (fg_debug_mask & FG_STATUS) + pr_info("workaround not applied, tp_rev = %d\n", reg); + return 0; + } + + rc = fg_mem_read(chip, ®, EXTERNAL_SENSE_OFFSET_REG, 1, 2, 0); + if (rc) { + pr_err("Failed to read ext sense offset trim, rc = %d\n", rc); + return rc; + } + rc = fg_masked_write(chip, chip->soc_base + SEC_ACCESS_REG, + SEC_ACCESS_UNLOCK, SEC_ACCESS_UNLOCK, 1); + + rc |= fg_masked_write(chip, chip->soc_base + EXT_OFFSET_TRIM_REG, + 0xFF, reg, 1); + if (rc) { + pr_err("Failed to write ext sense offset trim, rc = %d\n", rc); + return rc; + } + + return 0; +} + +#define FG_ALG_SYSCTL_1 0x4B0 +#define KI_COEFF_PRED_FULL_ADDR 0x408 +#define TEMP_FRAC_SHIFT_REG 0x4A4 +#define FG_ADC_CONFIG_REG 0x4B8 +#define KI_COEFF_PRED_FULL_4_0_MSB 0x88 +#define KI_COEFF_PRED_FULL_4_0_LSB 0x00 +#define FG_BCL_CONFIG_OFFSET 0x3 +#define ALERT_CFG_OFFSET 3 +#define I_TERM_QUAL_BIT BIT(1) +#define PATCH_NEG_CURRENT_BIT BIT(3) +#define BCL_FORCED_HPM_IN_CHARGE BIT(2) +#define IRQ_USE_VOLTAGE_HYST_BIT BIT(0) +#define EMPTY_FROM_VOLTAGE_BIT BIT(1) +#define EMPTY_FROM_SOC_BIT BIT(2) +#define EMPTY_SOC_IRQ_MASK (IRQ_USE_VOLTAGE_HYST_BIT | \ + EMPTY_FROM_SOC_BIT | \ + EMPTY_FROM_VOLTAGE_BIT) +static int fg_common_hw_init(struct fg_chip *chip) +{ + int rc; + int resume_soc_raw; + u8 val; + + update_iterm(chip); + update_cutoff_voltage(chip); + update_bcl_thresholds(chip); + if (!chip->use_vbat_low_empty_soc) + update_irq_volt_empty(chip); + + resume_soc_raw = settings[FG_MEM_RESUME_SOC].value; + if (resume_soc_raw > 0) { + rc = fg_set_resume_soc(chip, resume_soc_raw); + if (rc) { + pr_err("Couldn't set resume SOC for FG\n"); + return rc; + } + } else { + pr_info("FG auto recharge threshold not specified in DT\n"); + } + + if (fg_sense_type >= 0) { + rc = set_prop_sense_type(chip, fg_sense_type); + if (rc) { + pr_err("failed to config sense type %d rc=%d\n", + fg_sense_type, rc); + return rc; + } + } + + rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, + /*soc_to_setpoint(settings[FG_MEM_DELTA_SOC].value)*/1, + settings[FG_MEM_DELTA_SOC].offset); + if (rc) { + pr_err("failed to write delta soc rc=%d\n", rc); + return rc; + } + + /* Override the voltage threshold for vbatt_low with empty_volt */ + if (chip->use_vbat_low_empty_soc) + settings[FG_MEM_BATT_LOW].value = + settings[FG_MEM_IRQ_VOLT_EMPTY].value; + + rc = fg_mem_masked_write(chip, settings[FG_MEM_BATT_LOW].address, 0xFF, + batt_to_setpoint_8b(settings[FG_MEM_BATT_LOW].value), + settings[FG_MEM_BATT_LOW].offset); + if (rc) { + pr_err("failed to write Vbatt_low rc=%d\n", rc); + return rc; + } + + rc = fg_mem_masked_write(chip, settings[FG_MEM_THERM_DELAY].address, + THERM_DELAY_MASK, + therm_delay_to_setpoint(settings[FG_MEM_THERM_DELAY].value), + settings[FG_MEM_THERM_DELAY].offset); + if (rc) { + pr_err("failed to write therm_delay rc=%d\n", rc); + return rc; + } + + if (chip->use_thermal_coefficients) { + fg_mem_write(chip, chip->thermal_coefficients, + THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, + THERMAL_COEFF_OFFSET, 0); + } + + if (!chip->sw_rbias_ctrl) { + rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, + BATT_TEMP_CNTRL_MASK, + TEMP_SENSE_ALWAYS_BIT, + BATT_TEMP_OFFSET); + if (rc) { + pr_err("failed to write BATT_TEMP_OFFSET rc=%d\n", rc); + return rc; + } + } + + /* Read the cycle counter back from FG SRAM */ + if (chip->cyc_ctr.en) + restore_cycle_counter(chip); + + if (chip->esr_pulse_tune_en) { + rc = fg_mem_read(chip, &val, SYS_CFG_1_REG, 1, SYS_CFG_1_OFFSET, + 0); + if (rc) { + pr_err("unable to read sys_cfg_1: %d\n", rc); + return rc; + } + + if (!(val & ENABLE_ESR_PULSE_VAL)) + chip->esr_extract_disabled = true; + + if (fg_debug_mask & FG_STATUS) + pr_info("ESR extract is %sabled\n", + chip->esr_extract_disabled ? "dis" : "en"); + + rc = fg_mem_read(chip, &val, CBITS_INPUT_FILTER_REG, 1, + CBITS_RMEAS1_OFFSET, 0); + if (rc) { + pr_err("unable to read cbits_input_filter_reg: %d\n", + rc); + return rc; + } + + if (val & (IMPTR_FAST_TIME_SHIFT | IMPTR_LONG_TIME_SHIFT)) + chip->imptr_pulse_slow_en = true; + + if (fg_debug_mask & FG_STATUS) + pr_info("imptr_pulse_slow is %sabled\n", + chip->imptr_pulse_slow_en ? "en" : "dis"); + } + + rc = fg_mem_read(chip, &val, RSLOW_CFG_REG, 1, RSLOW_CFG_OFFSET, + 0); + if (rc) { + pr_err("unable to read rslow cfg: %d\n", rc); + return rc; + } + + if (val & RSLOW_CFG_ON_VAL) + chip->rslow_comp.active = true; + + if (fg_debug_mask & FG_STATUS) + pr_info("rslow_comp active is %sabled\n", + chip->rslow_comp.active ? "en" : "dis"); + + /* + * Clear bits 0-2 in 0x4B3 and set them again to make empty_soc irq + * trigger again. + */ + rc = fg_mem_masked_write(chip, FG_ALG_SYSCTL_1, EMPTY_SOC_IRQ_MASK, + 0, ALERT_CFG_OFFSET); + if (rc) { + pr_err("failed to write to 0x4B3 rc=%d\n", rc); + return rc; + } + + /* Wait for a FG cycle before enabling empty soc irq configuration */ + msleep(FG_CYCLE_MS); + + rc = fg_mem_masked_write(chip, FG_ALG_SYSCTL_1, EMPTY_SOC_IRQ_MASK, + EMPTY_SOC_IRQ_MASK, ALERT_CFG_OFFSET); + if (rc) { + pr_err("failed to write to 0x4B3 rc=%d\n", rc); + return rc; + } + + return 0; +} + +static int fg_8994_hw_init(struct fg_chip *chip) +{ + int rc = 0; + u8 data[4]; + u64 esr_value; + + rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, + PATCH_NEG_CURRENT_BIT, + PATCH_NEG_CURRENT_BIT, + EXTERNAL_SENSE_OFFSET); + if (rc) { + pr_err("failed to write patch current bit rc=%d\n", rc); + return rc; + } + + rc = bcl_trim_workaround(chip); + if (rc) { + pr_err("failed to redo bcl trim rc=%d\n", rc); + return rc; + } + + rc = fg_mem_masked_write(chip, FG_ADC_CONFIG_REG, + BCL_FORCED_HPM_IN_CHARGE, + BCL_FORCED_HPM_IN_CHARGE, + FG_BCL_CONFIG_OFFSET); + if (rc) { + pr_err("failed to force hpm in charge rc=%d\n", rc); + return rc; + } + + fg_mem_masked_write(chip, FG_ALG_SYSCTL_1, I_TERM_QUAL_BIT, 0, 0); + + data[0] = 0xA2; + data[1] = 0x12; + + rc = fg_mem_write(chip, data, TEMP_FRAC_SHIFT_REG, 2, 2, 0); + if (rc) { + pr_err("failed to write temp ocv constants rc=%d\n", rc); + return rc; + } + + data[0] = KI_COEFF_PRED_FULL_4_0_LSB; + data[1] = KI_COEFF_PRED_FULL_4_0_MSB; + fg_mem_write(chip, data, KI_COEFF_PRED_FULL_ADDR, 2, 2, 0); + + esr_value = ESR_DEFAULT_VALUE; + rc = fg_mem_write(chip, (u8 *)&esr_value, MAXRSCHANGE_REG, 8, + ESR_VALUE_OFFSET, 0); + if (rc) + pr_err("failed to write default ESR value rc=%d\n", rc); + else + pr_debug("set default value to esr filter\n"); + + return 0; +} + +#define FG_USBID_CONFIG_OFFSET 0x2 +#define DISABLE_USBID_DETECT_BIT BIT(0) +static int fg_8996_hw_init(struct fg_chip *chip) +{ + int rc; + + rc = fg_mem_masked_write(chip, FG_ADC_CONFIG_REG, + BCL_FORCED_HPM_IN_CHARGE, + BCL_FORCED_HPM_IN_CHARGE, + FG_BCL_CONFIG_OFFSET); + if (rc) { + pr_err("failed to force hpm in charge rc=%d\n", rc); + return rc; + } + + /* enable usbid conversions for PMi8996 V1.0 */ + if (chip->pmic_revision[REVID_DIG_MAJOR] == 1 + && chip->pmic_revision[REVID_ANA_MAJOR] == 0) { + rc = fg_mem_masked_write(chip, FG_ADC_CONFIG_REG, + DISABLE_USBID_DETECT_BIT, + 0, FG_USBID_CONFIG_OFFSET); + if (rc) { + pr_err("failed to enable usbid conversions: %d\n", rc); + return rc; + } + } + + return rc; +} + +static int fg_8950_hw_init(struct fg_chip *chip) +{ + int rc; + + rc = fg_mem_masked_write(chip, FG_ADC_CONFIG_REG, + BCL_FORCED_HPM_IN_CHARGE, + BCL_FORCED_HPM_IN_CHARGE, + FG_BCL_CONFIG_OFFSET); + if (rc) + pr_err("failed to force hpm in charge rc=%d\n", rc); + + return rc; +} + +static int fg_hw_init(struct fg_chip *chip) +{ + int rc = 0; + + rc = fg_common_hw_init(chip); + if (rc) { + pr_err("Unable to initialize FG HW rc=%d\n", rc); + return rc; + } + + /* add PMIC specific hw init */ + switch (chip->pmic_subtype) { + case PMI8994: + rc = fg_8994_hw_init(chip); + chip->wa_flag |= PULSE_REQUEST_WA; + break; + case PMI8996: + rc = fg_8996_hw_init(chip); + /* Setup workaround flag based on PMIC type */ + if (fg_sense_type == INTERNAL_CURRENT_SENSE) + chip->wa_flag |= IADC_GAIN_COMP_WA; + if (chip->pmic_revision[REVID_DIG_MAJOR] >= 1) + chip->wa_flag |= USE_CC_SOC_REG; + + break; + case PMI8950: + case PMI8937: + case PMI8940: + rc = fg_8950_hw_init(chip); + /* Setup workaround flag based on PMIC type */ + chip->wa_flag |= BCL_HI_POWER_FOR_CHGLED_WA; + if (fg_sense_type == INTERNAL_CURRENT_SENSE) + chip->wa_flag |= IADC_GAIN_COMP_WA; + if (chip->pmic_revision[REVID_DIG_MAJOR] > 1) + chip->wa_flag |= USE_CC_SOC_REG; + + break; + } + if (rc) + pr_err("Unable to initialize PMIC specific FG HW rc=%d\n", rc); + + pr_debug("wa_flag=0x%x\n", chip->wa_flag); + + return rc; +} + +static int fg_init_iadc_config(struct fg_chip *chip) +{ + u8 reg[2]; + int rc; + + /* read default gain config */ + rc = fg_mem_read(chip, reg, K_VCOR_REG, 2, DEF_GAIN_OFFSET, 0); + if (rc) { + pr_err("Failed to read default gain rc=%d\n", rc); + return rc; + } + + if (reg[1] || reg[0]) { + /* + * Default gain register has valid value: + * - write to gain register. + */ + rc = fg_mem_write(chip, reg, GAIN_REG, 2, + GAIN_OFFSET, 0); + if (rc) { + pr_err("Failed to write gain rc=%d\n", rc); + return rc; + } + } else { + /* + * Default gain register is invalid: + * - read gain register for default gain value + * - write to default gain register. + */ + rc = fg_mem_read(chip, reg, GAIN_REG, 2, + GAIN_OFFSET, 0); + if (rc) { + pr_err("Failed to read gain rc=%d\n", rc); + return rc; + } + rc = fg_mem_write(chip, reg, K_VCOR_REG, 2, + DEF_GAIN_OFFSET, 0); + if (rc) { + pr_err("Failed to write default gain rc=%d\n", + rc); + return rc; + } + } + + chip->iadc_comp_data.dfl_gain_reg[0] = reg[0]; + chip->iadc_comp_data.dfl_gain_reg[1] = reg[1]; + chip->iadc_comp_data.dfl_gain = half_float(reg); + + pr_debug("IADC gain initial config reg_val 0x%x%x gain %lld\n", + reg[1], reg[0], chip->iadc_comp_data.dfl_gain); + return 0; +} + +#define EN_WR_FGXCT_PRD BIT(6) +#define EN_RD_FGXCT_PRD BIT(5) +#define FG_RESTART_TIMEOUT_MS 12000 +static void ima_error_recovery_work(struct work_struct *work) +{ + struct fg_chip *chip = container_of(work, + struct fg_chip, + ima_error_recovery_work); + bool tried_again = false; + int rc; + u8 buf[4] = {0, 0, 0, 0}; + + fg_stay_awake(&chip->fg_reset_wakeup_source); + mutex_lock(&chip->ima_recovery_lock); + if (!chip->ima_error_handling) { + pr_err("Scheduled by mistake?\n"); + mutex_unlock(&chip->ima_recovery_lock); + fg_relax(&chip->fg_reset_wakeup_source); + return; + } + + /* + * SOC should be read and used until the error recovery completes. + * Without this, there could be a fluctuation in SOC values notified + * to the userspace. + */ + chip->use_last_soc = true; + + /* Block SRAM access till FG reset is complete */ + chip->block_sram_access = true; + + /* Release the mutex to avoid deadlock while cancelling the works */ + mutex_unlock(&chip->ima_recovery_lock); + + /* Cancel all the works */ + fg_cancel_all_works(chip); + + if (fg_debug_mask & FG_STATUS) + pr_info("last_soc: %d\n", chip->last_soc); + + mutex_lock(&chip->ima_recovery_lock); + /* Acquire IMA access forcibly from FG ALG */ + rc = fg_masked_write(chip, chip->mem_base + MEM_INTF_IMA_CFG, + EN_WR_FGXCT_PRD | EN_RD_FGXCT_PRD, + EN_WR_FGXCT_PRD | EN_RD_FGXCT_PRD, 1); + if (rc) { + pr_err("Error in writing to IMA_CFG, rc=%d\n", rc); + goto out; + } + + /* Release the IMA access now so that FG reset can go through */ + rc = fg_masked_write(chip, chip->mem_base + MEM_INTF_IMA_CFG, + EN_WR_FGXCT_PRD | EN_RD_FGXCT_PRD, 0, 1); + if (rc) { + pr_err("Error in writing to IMA_CFG, rc=%d\n", rc); + goto out; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("resetting FG\n"); + + /* Assert FG reset */ + rc = fg_reset(chip, true); + if (rc) { + pr_err("Couldn't reset FG\n"); + goto out; + } + + /* Wait for a small time before deasserting FG reset */ + msleep(100); + + if (fg_debug_mask & FG_STATUS) + pr_info("clearing FG from reset\n"); + + /* Deassert FG reset */ + rc = fg_reset(chip, false); + if (rc) { + pr_err("Couldn't clear FG reset\n"); + goto out; + } + + /* Wait for at least a FG cycle before doing SRAM access */ + msleep(2000); + + chip->block_sram_access = false; + + if (!chip->init_done) { + schedule_work(&chip->init_work); + goto wait; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("Calling hw_init\n"); + + /* + * Once FG is reset, everything in SRAM will be wiped out. Redo + * hw_init, update jeita settings etc., again to make sure all + * the settings got restored again. + */ + rc = fg_hw_init(chip); + if (rc) { + pr_err("Error in hw_init, rc=%d\n", rc); + goto out; + } + + update_jeita_setting(&chip->update_jeita_setting.work); + + if (chip->wa_flag & IADC_GAIN_COMP_WA) { + rc = fg_init_iadc_config(chip); + if (rc) + goto out; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("loading battery profile\n"); + if (!chip->use_otp_profile) { + chip->battery_missing = true; + chip->profile_loaded = false; + chip->soc_reporting_ready = false; + chip->batt_type = default_batt_type; + fg_handle_battery_insertion(chip); + } + +wait: + rc = wait_for_completion_interruptible_timeout(&chip->fg_reset_done, + msecs_to_jiffies(FG_RESTART_TIMEOUT_MS)); + + /* If we were interrupted wait again one more time. */ + if (rc == -ERESTARTSYS && !tried_again) { + tried_again = true; + pr_debug("interrupted, waiting again\n"); + goto wait; + } else if (rc <= 0) { + pr_err("fg_restart taking long time rc=%d\n", rc); + goto out; + } + + rc = fg_mem_write(chip, buf, fg_data[FG_DATA_VINT_ERR].address, + fg_data[FG_DATA_VINT_ERR].len, + fg_data[FG_DATA_VINT_ERR].offset, 0); + if (rc < 0) + pr_err("Error in clearing VACT_INT_ERR, rc=%d\n", rc); + + if (fg_debug_mask & FG_STATUS) + pr_info("IMA error recovery done...\n"); +out: + fg_restore_soc(chip); + fg_restore_cc_soc(chip); + fg_enable_irqs(chip, true); + update_sram_data_work(&chip->update_sram_data.work); + update_temp_data(&chip->update_temp_work.work); + schedule_delayed_work(&chip->check_sanity_work, + msecs_to_jiffies(1000)); + chip->ima_error_handling = false; + mutex_unlock(&chip->ima_recovery_lock); + fg_relax(&chip->fg_reset_wakeup_source); +} + +#define DIG_MINOR 0x0 +#define DIG_MAJOR 0x1 +#define ANA_MINOR 0x2 +#define ANA_MAJOR 0x3 +#define IACS_INTR_SRC_SLCT BIT(3) +static int fg_memif_init(struct fg_chip *chip) +{ + int rc; + u8 dig_major; + + rc = fg_read(chip, chip->revision, chip->mem_base + DIG_MINOR, 4); + if (rc) { + pr_err("Unable to read FG revision rc=%d\n", rc); + return rc; + } + + switch (chip->revision[DIG_MAJOR]) { + case DIG_REV_1: + case DIG_REV_2: + chip->offset = offset[0].address; + break; + case DIG_REV_3: + chip->offset = offset[1].address; + chip->ima_supported = true; + break; + default: + pr_err("Digital Major rev=%d not supported\n", dig_major); + return -EINVAL; + } + + if (chip->ima_supported) { + /* + * Change the FG_MEM_INT interrupt to track IACS_READY + * condition instead of end-of-transaction. This makes sure + * that the next transaction starts only after the hw is ready. + */ + rc = fg_masked_write(chip, + chip->mem_base + MEM_INTF_IMA_CFG, IACS_INTR_SRC_SLCT, + IACS_INTR_SRC_SLCT, 1); + if (rc) { + pr_err("failed to configure interrupt source %d\n", rc); + return rc; + } + + /* check for error condition */ + rc = fg_check_ima_exception(chip, true); + if (rc) { + pr_err("Error in clearing IMA exception rc=%d", rc); + return rc; + } + } + + return 0; +} + +static int fg_detect_pmic_type(struct fg_chip *chip) +{ + struct pmic_revid_data *pmic_rev_id; + struct device_node *revid_dev_node; + + revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node, + "qcom,pmic-revid", 0); + if (!revid_dev_node) { + pr_err("Missing qcom,pmic-revid property - driver failed\n"); + return -EINVAL; + } + + pmic_rev_id = get_revid_data(revid_dev_node); + if (IS_ERR(pmic_rev_id)) { + pr_err("Unable to get pmic_revid rc=%ld\n", + PTR_ERR(pmic_rev_id)); + /* + * the revid peripheral must be registered, any failure + * here only indicates that the rev-id module has not + * probed yet. + */ + return -EPROBE_DEFER; + } + + switch (pmic_rev_id->pmic_subtype) { + case PMI8994: + case PMI8950: + case PMI8937: + case PMI8996: + case PMI8940: + chip->pmic_subtype = pmic_rev_id->pmic_subtype; + chip->pmic_revision[REVID_RESERVED] = pmic_rev_id->rev1; + chip->pmic_revision[REVID_VARIANT] = pmic_rev_id->rev2; + chip->pmic_revision[REVID_ANA_MAJOR] = pmic_rev_id->rev3; + chip->pmic_revision[REVID_DIG_MAJOR] = pmic_rev_id->rev4; + break; + default: + pr_err("PMIC subtype %d not supported\n", + pmic_rev_id->pmic_subtype); + return -EINVAL; + } + + return 0; +} + +#define INIT_JEITA_DELAY_MS 1000 +static void delayed_init_work(struct work_struct *work) +{ + int rc; + struct fg_chip *chip = container_of(work, + struct fg_chip, + init_work); + + /* hold memory access until initialization finishes */ + fg_mem_lock(chip); + + rc = fg_hw_init(chip); + if (rc) { + pr_err("failed to hw init rc = %d\n", rc); + if (!chip->init_done && chip->ima_supported) { + rc = fg_check_alg_status(chip); + if (rc && rc != -EBUSY) + pr_err("Couldn't check FG ALG status, rc=%d\n", + rc); + fg_mem_release(chip); + return; + } + fg_mem_release(chip); + fg_cleanup(chip); + return; + } + /* release memory access before update_sram_data is called */ + fg_mem_release(chip); + + schedule_delayed_work( + &chip->update_jeita_setting, + msecs_to_jiffies(INIT_JEITA_DELAY_MS)); + + if (chip->last_sram_update_time == 0) + update_sram_data_work(&chip->update_sram_data.work); + + if (chip->last_temp_update_time == 0) + update_temp_data(&chip->update_temp_work.work); + + if (!chip->use_otp_profile) + schedule_delayed_work(&chip->batt_profile_init, 0); + + if (chip->ima_supported && fg_reset_on_lockup) + schedule_delayed_work(&chip->check_sanity_work, + msecs_to_jiffies(1000)); + + if (chip->wa_flag & IADC_GAIN_COMP_WA) { + rc = fg_init_iadc_config(chip); + if (rc) + goto done; + } + + chip->input_present = is_input_present(chip); + chip->otg_present = is_otg_present(chip); + chip->init_done = true; + pr_debug("FG: HW_init success\n"); + return; +done: + fg_cleanup(chip); +} + +#define SOC_LOW_PWR_CFG 0xF5 +#define LO_FRQ_CLKSWITCH_EN BIT(0) + +static void fg_adc_clk_change(struct fg_chip *chip, int val) +{ + u8 reg = 0; + int rc = 0; + + if (val > 1 || val < 0) { + pr_err(":%s Invalid Value %d, Return!\n", __func__, val); + return; + } + chip->fg_restarting = true; + + rc = fg_read(chip, ®, chip->soc_base + SOC_LOW_PWR_CFG, 1); + if (rc) { + pr_err(":%s failed to read SOC_LOW_PWR_CFG\n", __func__); + + } + pr_err(":%s SOC_LOW_PWR_CFG = 0x%02x\n", __func__, reg); + usleep_range(5000, 6000); + + rc = fg_sec_masked_write(chip, chip->soc_base + SOC_LOW_PWR_CFG, LO_FRQ_CLKSWITCH_EN, val, 1); + if (rc) { + pr_err(":%s failed to change FG ADC Clk\n", __func__); + goto adc_clk_change_fail; + } + usleep_range(5000, 6000); + + rc = fg_read(chip, ®, chip->soc_base + SOC_LOW_PWR_CFG, 1); + if (rc) { + pr_err(":%s failed to read SOC_LOW_PWR_CFG\n", __func__); + goto adc_clk_change_fail; + } + pr_err(":%s SOC_LOW_PWR_CFG = 0x%02x\n", __func__, reg); + + chip->fg_restarting = false; + pr_err(":%s Success change FG ADC Clk\n", __func__); + return; + +adc_clk_change_fail: + chip->fg_restarting = false; +} + + +static int fg_probe(struct spmi_device *spmi) +{ + struct device *dev = &(spmi->dev); + struct fg_chip *chip; + struct spmi_resource *spmi_resource; + struct resource *resource; + u8 subtype, reg; + int rc = 0; + + if (!spmi) { + pr_err("no valid spmi pointer\n"); + return -ENODEV; + } + + if (!spmi->dev.of_node) { + pr_err("device node missing\n"); + return -ENODEV; + } + + chip = devm_kzalloc(dev, sizeof(struct fg_chip), GFP_KERNEL); + if (chip == NULL) { + pr_err("Can't allocate fg_chip\n"); + return -ENOMEM; + } + + chip->spmi = spmi; + chip->dev = &(spmi->dev); + + wakeup_source_init(&chip->empty_check_wakeup_source.source, + "qpnp_fg_empty_check"); + wakeup_source_init(&chip->memif_wakeup_source.source, + "qpnp_fg_memaccess"); + wakeup_source_init(&chip->profile_wakeup_source.source, + "qpnp_fg_profile"); + wakeup_source_init(&chip->update_temp_wakeup_source.source, + "qpnp_fg_update_temp"); + wakeup_source_init(&chip->update_sram_wakeup_source.source, + "qpnp_fg_update_sram"); + wakeup_source_init(&chip->resume_soc_wakeup_source.source, + "qpnp_fg_set_resume_soc"); + wakeup_source_init(&chip->gain_comp_wakeup_source.source, + "qpnp_fg_gain_comp"); + wakeup_source_init(&chip->capacity_learning_wakeup_source.source, + "qpnp_fg_cap_learning"); + wakeup_source_init(&chip->esr_extract_wakeup_source.source, + "qpnp_fg_esr_extract"); + wakeup_source_init(&chip->slope_limit_wakeup_source.source, + "qpnp_fg_slope_limit"); + wakeup_source_init(&chip->dischg_gain_wakeup_source.source, + "qpnp_fg_dischg_gain"); + wakeup_source_init(&chip->fg_reset_wakeup_source.source, + "qpnp_fg_reset"); + wakeup_source_init(&chip->cc_soc_wakeup_source.source, + "qpnp_fg_cc_soc"); + wakeup_source_init(&chip->sanity_wakeup_source.source, + "qpnp_fg_sanity_check"); + spin_lock_init(&chip->sec_access_lock); + mutex_init(&chip->rw_lock); + mutex_init(&chip->cyc_ctr.lock); + mutex_init(&chip->learning_data.learning_lock); + mutex_init(&chip->rslow_comp.lock); + mutex_init(&chip->sysfs_restart_lock); + mutex_init(&chip->ima_recovery_lock); + INIT_DELAYED_WORK(&chip->update_jeita_setting, update_jeita_setting); + INIT_DELAYED_WORK(&chip->update_sram_data, update_sram_data_work); + INIT_DELAYED_WORK(&chip->update_temp_work, update_temp_data); + INIT_DELAYED_WORK(&chip->check_empty_work, check_empty_work); + INIT_DELAYED_WORK(&chip->batt_profile_init, batt_profile_init); + INIT_DELAYED_WORK(&chip->check_sanity_work, check_sanity_work); + INIT_WORK(&chip->ima_error_recovery_work, ima_error_recovery_work); + INIT_WORK(&chip->rslow_comp_work, rslow_comp_work); + INIT_WORK(&chip->fg_cap_learning_work, fg_cap_learning_work); + INIT_WORK(&chip->dump_sram, dump_sram); + INIT_WORK(&chip->status_change_work, status_change_work); + INIT_WORK(&chip->cycle_count_work, update_cycle_count); + INIT_WORK(&chip->battery_age_work, battery_age_work); + INIT_WORK(&chip->update_esr_work, update_esr_value); + INIT_WORK(&chip->set_resume_soc_work, set_resume_soc_work); + INIT_WORK(&chip->sysfs_restart_work, sysfs_restart_work); + INIT_WORK(&chip->init_work, delayed_init_work); + INIT_WORK(&chip->charge_full_work, charge_full_work); + INIT_WORK(&chip->gain_comp_work, iadc_gain_comp_work); + INIT_WORK(&chip->bcl_hi_power_work, bcl_hi_power_work); + INIT_WORK(&chip->esr_extract_config_work, esr_extract_config_work); + INIT_WORK(&chip->slope_limiter_work, slope_limiter_work); + INIT_WORK(&chip->dischg_gain_work, discharge_gain_work); + INIT_WORK(&chip->cc_soc_store_work, cc_soc_store_work); + alarm_init(&chip->fg_cap_learning_alarm, ALARM_BOOTTIME, + fg_cap_learning_alarm_cb); + alarm_init(&chip->hard_jeita_alarm, ALARM_BOOTTIME, + fg_hard_jeita_alarm_cb); + init_completion(&chip->sram_access_granted); + init_completion(&chip->sram_access_revoked); + complete_all(&chip->sram_access_revoked); + init_completion(&chip->batt_id_avail); + init_completion(&chip->first_soc_done); + init_completion(&chip->fg_reset_done); + dev_set_drvdata(&spmi->dev, chip); + chip->debug_dump = kmalloc(sizeof(char)*2048, GFP_KERNEL); + memset(chip->debug_dump, '\0', sizeof(char)*2048); + + spmi_for_each_container_dev(spmi_resource, spmi) { + if (!spmi_resource) { + pr_err("qpnp_chg: spmi resource absent\n"); + rc = -ENXIO; + goto of_init_fail; + } + + resource = spmi_get_resource(spmi, spmi_resource, + IORESOURCE_MEM, 0); + if (!(resource && resource->start)) { + pr_err("node %s IO resource absent!\n", + spmi->dev.of_node->full_name); + rc = -ENXIO; + goto of_init_fail; + } + + if (strcmp("qcom,fg-adc-vbat", + spmi_resource->of_node->name) == 0) { + chip->vbat_adc_addr = resource->start; + continue; + } else if (strcmp("qcom,fg-adc-ibat", + spmi_resource->of_node->name) == 0) { + chip->ibat_adc_addr = resource->start; + continue; + } else if (strcmp("qcom,revid-tp-rev", + spmi_resource->of_node->name) == 0) { + chip->tp_rev_addr = resource->start; + continue; + } + + rc = fg_read(chip, &subtype, + resource->start + REG_OFFSET_PERP_SUBTYPE, 1); + if (rc) { + pr_err("Peripheral subtype read failed rc=%d\n", rc); + goto of_init_fail; + } + + switch (subtype) { + case FG_SOC: + chip->soc_base = resource->start; + break; + case FG_MEMIF: + chip->mem_base = resource->start; + break; + case FG_BATT: + chip->batt_base = resource->start; + break; + default: + pr_err("Invalid peripheral subtype=0x%x\n", subtype); + rc = -EINVAL; + } + } + + rc = fg_detect_pmic_type(chip); + if (rc) { + pr_err("Unable to detect PMIC type rc=%d\n", rc); + return rc; + } + + rc = fg_memif_init(chip); + if (rc) { + pr_err("Unable to setup mem_if offsets rc=%d\n", rc); + goto of_init_fail; + } + + rc = fg_of_init(chip); + if (rc) { + pr_err("failed to parse devicetree rc%d\n", rc); + goto of_init_fail; + } + + if (chip->jeita_hysteresis_support) { + rc = fg_init_batt_temp_state(chip); + if (rc) { + pr_err("failed to get battery status rc%d\n", rc); + goto of_init_fail; + } + } + + /* check if the first estimate is already finished at this time */ + if (is_first_est_done(chip)) + complete_all(&chip->first_soc_done); + + reg = 0xFF; + rc = fg_write(chip, ®, INT_EN_CLR(chip->mem_base), 1); + if (rc) { + pr_err("failed to clear interrupts %d\n", rc); + goto of_init_fail; + } + fg_adc_clk_change(chip, 1); + rc = fg_init_irqs(chip); + if (rc) { + pr_err("failed to request interrupts %d\n", rc); + goto cancel_work; + } + + chip->batt_type = default_batt_type; + + chip->bms_psy.name = "bms"; + chip->bms_psy.type = POWER_SUPPLY_TYPE_BMS; + chip->bms_psy.properties = fg_power_props; + chip->bms_psy.num_properties = ARRAY_SIZE(fg_power_props); + chip->bms_psy.get_property = fg_power_get_property; + chip->bms_psy.set_property = fg_power_set_property; + chip->bms_psy.external_power_changed = fg_external_power_changed; + chip->bms_psy.supplied_to = fg_supplicants; + chip->bms_psy.num_supplicants = ARRAY_SIZE(fg_supplicants); + chip->bms_psy.property_is_writeable = fg_property_is_writeable; + + rc = power_supply_register(chip->dev, &chip->bms_psy); + if (rc < 0) { + pr_err("batt failed to register rc = %d\n", rc); + goto of_init_fail; + } + chip->power_supply_registered = true; + /* + * Just initialize the batt_psy_name here. Power supply + * will be obtained later. + */ + chip->batt_psy_name = "battery"; + + if (chip->mem_base) { + rc = fg_dfs_create(chip); + if (rc < 0) { + pr_err("failed to create debugfs rc = %d\n", rc); + goto power_supply_unregister; + } + } + + /* Fake temperature till the actual temperature is read */ + chip->last_good_temp = 250; + + /* Initialize batt_info variables */ + chip->batt_range_ocv = &fg_batt_valid_ocv; + chip->batt_range_pct = &fg_batt_range_pct; + memset(chip->batt_info, INT_MAX, sizeof(chip->batt_info)); + + schedule_work(&chip->init_work); + + pr_info("FG Probe success - FG Revision DIG:%d.%d ANA:%d.%d PMIC subtype=%d\n", + chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR], + chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR], + chip->pmic_subtype); + + return rc; + +power_supply_unregister: + power_supply_unregister(&chip->bms_psy); +cancel_work: + fg_cancel_all_works(chip); +of_init_fail: + mutex_destroy(&chip->rslow_comp.lock); + mutex_destroy(&chip->rw_lock); + mutex_destroy(&chip->cyc_ctr.lock); + mutex_destroy(&chip->learning_data.learning_lock); + mutex_destroy(&chip->sysfs_restart_lock); + mutex_destroy(&chip->ima_recovery_lock); + wakeup_source_trash(&chip->resume_soc_wakeup_source.source); + wakeup_source_trash(&chip->empty_check_wakeup_source.source); + wakeup_source_trash(&chip->memif_wakeup_source.source); + wakeup_source_trash(&chip->profile_wakeup_source.source); + wakeup_source_trash(&chip->update_temp_wakeup_source.source); + wakeup_source_trash(&chip->update_sram_wakeup_source.source); + wakeup_source_trash(&chip->gain_comp_wakeup_source.source); + wakeup_source_trash(&chip->capacity_learning_wakeup_source.source); + wakeup_source_trash(&chip->esr_extract_wakeup_source.source); + wakeup_source_trash(&chip->slope_limit_wakeup_source.source); + wakeup_source_trash(&chip->dischg_gain_wakeup_source.source); + wakeup_source_trash(&chip->fg_reset_wakeup_source.source); + wakeup_source_trash(&chip->cc_soc_wakeup_source.source); + wakeup_source_trash(&chip->sanity_wakeup_source.source); + return rc; +} + +static void check_and_update_sram_data(struct fg_chip *chip) +{ + unsigned long current_time = 0, next_update_time, time_left; + + get_current_time(¤t_time); + + next_update_time = chip->last_temp_update_time + + (TEMP_PERIOD_UPDATE_MS / 1000); + + if (next_update_time > current_time) + time_left = next_update_time - current_time; + else + time_left = 0; + + schedule_delayed_work( + &chip->update_temp_work, msecs_to_jiffies(time_left * 1000)); + + next_update_time = chip->last_sram_update_time + + (fg_sram_update_period_ms / 1000); + + if (next_update_time > current_time) + time_left = next_update_time - current_time; + else + time_left = 0; + + schedule_delayed_work( + &chip->update_sram_data, msecs_to_jiffies(time_left * 1000)); +} + +static int fg_suspend(struct device *dev) +{ + struct fg_chip *chip = dev_get_drvdata(dev); + + if (!chip->sw_rbias_ctrl) + return 0; + + cancel_delayed_work(&chip->update_temp_work); + cancel_delayed_work(&chip->update_sram_data); + + return 0; +} + +static int fg_resume(struct device *dev) +{ + struct fg_chip *chip = dev_get_drvdata(dev); + + if (!chip->sw_rbias_ctrl) + return 0; + + check_and_update_sram_data(chip); + return 0; +} + +static void fg_check_ima_idle(struct fg_chip *chip) +{ + bool rif_mem_sts = true; + int rc, time_count = 0; + + mutex_lock(&chip->rw_lock); + /* Make sure IMA is idle */ + while (1) { + rc = fg_check_rif_mem_access(chip, &rif_mem_sts); + if (rc) + break; + + if (!rif_mem_sts) + break; + + if (time_count > 4) { + pr_err("Waited for ~16ms polling RIF_MEM_ACCESS_REQ\n"); + fg_run_iacs_clear_sequence(chip); + break; + } + + /* Wait for 4ms before reading RIF_MEM_ACCESS_REQ again */ + usleep_range(4000, 4100); + time_count++; + } + mutex_unlock(&chip->rw_lock); +} + +static void fg_shutdown(struct spmi_device *spmi) +{ + struct fg_chip *chip = dev_get_drvdata(&spmi->dev); + + if (fg_debug_mask & FG_STATUS) + pr_emerg("FG shutdown started\n"); + if (chip->rslow_comp.active) + fg_rslow_charge_comp_clear(chip); + fg_cancel_all_works(chip); + fg_check_ima_idle(chip); + chip->fg_shutdown = true; + if (fg_debug_mask & FG_STATUS) + pr_emerg("FG shutdown complete\n"); +} + +static const struct dev_pm_ops qpnp_fg_pm_ops = { + .suspend = fg_suspend, + .resume = fg_resume, +}; + +static int fg_reset_lockup_set(const char *val, const struct kernel_param *kp) +{ + int rc; + struct power_supply *bms_psy; + struct fg_chip *chip; + int old_val = fg_reset_on_lockup; + + rc = param_set_int(val, kp); + if (rc) { + pr_err("Unable to set fg_reset_on_lockup: %d\n", rc); + return rc; + } + + if (fg_reset_on_lockup != 0 && fg_reset_on_lockup != 1) { + pr_err("Bad value %d\n", fg_reset_on_lockup); + fg_reset_on_lockup = old_val; + return -EINVAL; + } + + bms_psy = power_supply_get_by_name("bms"); + if (!bms_psy) { + pr_err("bms psy not found\n"); + return 0; + } + + chip = container_of(bms_psy, struct fg_chip, bms_psy); + if (!chip->ima_supported) { + pr_err("Cannot set this for non-IMA supported FG\n"); + fg_reset_on_lockup = old_val; + return -EINVAL; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("fg_reset_on_lockup set to %d\n", fg_reset_on_lockup); + + if (fg_reset_on_lockup) + schedule_delayed_work(&chip->check_sanity_work, + msecs_to_jiffies(1000)); + else + cancel_delayed_work_sync(&chip->check_sanity_work); + + return rc; +} + +static struct kernel_param_ops fg_reset_ops = { + .set = fg_reset_lockup_set, + .get = param_get_int, +}; + +module_param_cb(reset_on_lockup, &fg_reset_ops, &fg_reset_on_lockup, 0644); + +static int fg_sense_type_set(const char *val, const struct kernel_param *kp) +{ + int rc; + struct power_supply *bms_psy; + struct fg_chip *chip; + int old_fg_sense_type = fg_sense_type; + + rc = param_set_int(val, kp); + if (rc) { + pr_err("Unable to set fg_sense_type: %d\n", rc); + return rc; + } + + if (fg_sense_type != 0 && fg_sense_type != 1) { + pr_err("Bad value %d\n", fg_sense_type); + fg_sense_type = old_fg_sense_type; + return -EINVAL; + } + + if (fg_debug_mask & FG_STATUS) + pr_info("fg_sense_type set to %d\n", fg_sense_type); + + bms_psy = power_supply_get_by_name("bms"); + if (!bms_psy) { + pr_err("bms psy not found\n"); + return 0; + } + + chip = container_of(bms_psy, struct fg_chip, bms_psy); + rc = set_prop_sense_type(chip, fg_sense_type); + return rc; +} + +static struct kernel_param_ops fg_sense_type_ops = { + .set = fg_sense_type_set, + .get = param_get_int, +}; + +module_param_cb(sense_type, &fg_sense_type_ops, &fg_sense_type, 0644); + +static int fg_restart_set(const char *val, const struct kernel_param *kp) +{ + struct power_supply *bms_psy; + struct fg_chip *chip; + + bms_psy = power_supply_get_by_name("bms"); + if (!bms_psy) { + pr_err("bms psy not found\n"); + return 0; + } + chip = container_of(bms_psy, struct fg_chip, bms_psy); + + mutex_lock(&chip->sysfs_restart_lock); + if (fg_restart != 0) { + mutex_unlock(&chip->sysfs_restart_lock); + return 0; + } + fg_restart = 1; + mutex_unlock(&chip->sysfs_restart_lock); + + if (fg_debug_mask & FG_STATUS) + pr_info("fuel gauge restart initiated from sysfs...\n"); + + schedule_work(&chip->sysfs_restart_work); + return 0; +} + +static struct kernel_param_ops fg_restart_ops = { + .set = fg_restart_set, + .get = param_get_int, +}; + +module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644); + +static struct spmi_driver fg_driver = { + .driver = { + .name = QPNP_FG_DEV_NAME, + .of_match_table = fg_match_table, + .pm = &qpnp_fg_pm_ops, + }, + .probe = fg_probe, + .remove = fg_remove, + .shutdown = fg_shutdown, +}; + +static int __init fg_init(void) +{ + return spmi_driver_register(&fg_driver); +} + +static void __exit fg_exit(void) +{ + return spmi_driver_unregister(&fg_driver); +} + +module_init(fg_init); +module_exit(fg_exit); + +MODULE_DESCRIPTION("QPNP Fuel Gauge Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" QPNP_FG_DEV_NAME); diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 473c314683796..f1698882e942b 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -39,6 +40,7 @@ #include #include #include +#include /* Mask/Bit helpers */ #define _SMB_MASK(BITS, POS) \ @@ -163,6 +165,7 @@ struct smbchg_chip { bool wipower_dyn_icl_avail; struct ilim_entry current_ilim; struct mutex wipower_config; + struct mutex cool_current; bool wipower_configured; struct qpnp_adc_tm_btm_param param; @@ -254,6 +257,8 @@ struct smbchg_chip { struct work_struct usb_set_online_work; struct delayed_work vfloat_adjust_work; struct delayed_work hvdcp_det_work; + struct delayed_work cool_limit_work; + struct delayed_work temp_check_work; spinlock_t sec_access_lock; struct mutex therm_lvl_lock; struct mutex usb_set_online_lock; @@ -451,7 +456,7 @@ module_param_named( int, S_IRUSR | S_IWUSR ); -static int smbchg_default_dcp_icl_ma = 1800; +static int smbchg_default_dcp_icl_ma = 2000; module_param_named( default_dcp_icl_ma, smbchg_default_dcp_icl_ma, int, S_IRUSR | S_IWUSR @@ -937,12 +942,16 @@ static int get_prop_batt_status(struct smbchg_chip *chip) return POWER_SUPPLY_STATUS_UNKNOWN; } - if (reg & BAT_TCC_REACHED_BIT) + if (reg & BAT_TCC_REACHED_BIT && !chip->batt_warm) return POWER_SUPPLY_STATUS_FULL; + else if (reg & BAT_TCC_REACHED_BIT && chip->batt_warm) + return POWER_SUPPLY_STATUS_CHARGING; chg_inhibit = reg & CHG_INHIBIT_BIT; - if (chg_inhibit) + if (chg_inhibit && !chip->batt_warm) return POWER_SUPPLY_STATUS_FULL; + else if (chg_inhibit && chip->batt_warm) + return POWER_SUPPLY_STATUS_CHARGING; rc = smbchg_read(chip, ®, chip->chgr_base + CHGR_STS, 1); if (rc < 0) { @@ -1076,6 +1085,34 @@ static int get_prop_batt_capacity(struct smbchg_chip *chip) return capacity; } +static int get_prop_battery_charge_full_design(struct smbchg_chip *chip) +{ + union power_supply_propval ret = {0,}; + if (chip->bms_psy) { + chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret); + return ret.intval; + } else { + pr_debug("No BMS supply registered return 0\n"); + } + return 0; +} + +static int get_prop_battery_charge_full(struct smbchg_chip *chip) +{ + union power_supply_propval ret = {0,}; + + if (chip->bms_psy) { + chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_CHARGE_FULL, &ret); + return ret.intval; + } else { + pr_debug("No BMS supply registered return 0\n"); + } + + return 0; +} + #define DEFAULT_BATT_TEMP 200 static int get_prop_batt_temp(struct smbchg_chip *chip) { @@ -1116,19 +1153,6 @@ static int get_prop_batt_resistance_id(struct smbchg_chip *chip) return rbatt; } -#define DEFAULT_BATT_FULL_CHG_CAPACITY 0 -static int get_prop_batt_full_charge(struct smbchg_chip *chip) -{ - int bfc, rc; - - rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CHARGE_FULL, &bfc); - if (rc) { - pr_smb(PR_STATUS, "Couldn't get charge_full rc = %d\n", rc); - bfc = DEFAULT_BATT_FULL_CHG_CAPACITY; - } - return bfc; -} - #define DEFAULT_BATT_VOLTAGE_NOW 0 static int get_prop_batt_voltage_now(struct smbchg_chip *chip) { @@ -3034,6 +3058,7 @@ static int set_usb_current_limit_vote_cb(struct votable *votable, return 0; aicl_ma = smbchg_get_aicl_level_ma(chip); + pr_err("[SMBCHG]aicl_ma=%d\n", aicl_ma); if (icl_ma > aicl_ma) smbchg_rerun_aicl(chip); @@ -3042,6 +3067,9 @@ static int set_usb_current_limit_vote_cb(struct votable *votable, return 0; } +#define PCBA_V1_IN 35 +#define PCBA_V2_IN 38 +#define PCBA_V2_CN 36 static int smbchg_system_temp_level_set(struct smbchg_chip *chip, int lvl_sel) { @@ -3049,6 +3077,12 @@ static int smbchg_system_temp_level_set(struct smbchg_chip *chip, int prev_therm_lvl; int thermal_icl_ma; + unsigned int India_thermal_mitigation[7] = {2500, 2500, 1900, 1900, 1000, 1000, 0}; + + int *pcba_config = NULL; + pcba_config = (int *)smem_find(SMEM_ID_VENDOR1, sizeof(int), 0, SMEM_ANY_HOST_FLAG); + pr_err("pcba config check=%d.\n", *(pcba_config)); + if (!chip->thermal_mitigation) { dev_err(chip->dev, "Thermal mitigation not supported\n"); return -EINVAL; @@ -3102,8 +3136,16 @@ static int smbchg_system_temp_level_set(struct smbchg_chip *chip, pr_err("Couldn't disable DC thermal ICL vote rc=%d\n", rc); } else { - thermal_icl_ma = - (int)chip->thermal_mitigation[chip->therm_lvl_sel]; + if (*(pcba_config) == PCBA_V1_IN + || *(pcba_config) == PCBA_V2_IN) { + thermal_icl_ma = + (int)India_thermal_mitigation[chip->therm_lvl_sel]; + pr_err("Thermal_India.\n"); + } else { + thermal_icl_ma = + (int)chip->thermal_mitigation[chip->therm_lvl_sel]; + pr_err("Thermal_CN&Global.\n"); + } rc = vote(chip->usb_icl_votable, THERMAL_ICL_VOTER, true, thermal_icl_ma); if (rc < 0) @@ -4509,6 +4551,32 @@ static int smbchg_adjust_vfloat_mv_trim(struct smbchg_chip *chip, return rc; } +#define SMBCHG_UPDATE_MS 1000 +static void smbchg_cool_limit_work(struct work_struct *work) +{ + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + cool_limit_work.work); + + int temp, rc; + + temp = get_prop_batt_temp(chip); + + if (temp > 0 && temp <= 50){ + mutex_lock(&chip->cool_current); + rc = smbchg_fastchg_current_comp_set(chip, 250); + mutex_unlock(&chip->cool_current); + } + if (temp > 50 && temp < 150){ + mutex_lock(&chip->cool_current); + rc = smbchg_fastchg_current_comp_set(chip, 1200); + mutex_unlock(&chip->cool_current); + } + + schedule_delayed_work(&chip->cool_limit_work, msecs_to_jiffies(SMBCHG_UPDATE_MS)); + +} + #define VFLOAT_RESAMPLE_DELAY_MS 10000 static void smbchg_vfloat_adjust_work(struct work_struct *work) { @@ -4656,6 +4724,7 @@ static int smbchg_set_optimal_charging_mode(struct smbchg_chip *chip, int type) #define DEFAULT_SDP_MA 100 #define DEFAULT_CDP_MA 1500 +enum power_supply_type hvdcp_flag = 0; static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, enum power_supply_type type) { @@ -4689,7 +4758,7 @@ static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, current_limit_ma = smbchg_default_hvdcp3_icl_ma; else current_limit_ma = smbchg_default_dcp_icl_ma; - + hvdcp_flag = type; pr_smb(PR_STATUS, "Type %d: setting mA = %d\n", type, current_limit_ma); rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, @@ -4902,11 +4971,20 @@ static int smbchg_restricted_charging(struct smbchg_chip *chip, bool enable) return rc; } +/*Modifiy by HQ-zmc [Date: 2018-04-04 15:23:36]*/ +static bool tp_usb_plugin; + +bool *check_charge_mode(void){ + return &tp_usb_plugin; +} + static void handle_usb_removal(struct smbchg_chip *chip) { struct power_supply *parallel_psy = get_parallel_psy(chip); int rc; + tp_usb_plugin = 0; + pr_smb(PR_STATUS, "triggered\n"); smbchg_aicl_deglitch_wa_check(chip); /* Clear the OV detected status set before */ @@ -4983,6 +5061,8 @@ static void handle_usb_insertion(struct smbchg_chip *chip) int rc; char *usb_type_name = "null"; + tp_usb_plugin = 1; + pr_smb(PR_STATUS, "triggered\n"); /* usb inserted */ read_usb_type(chip, &usb_type_name, &usb_supply_type); @@ -6074,52 +6154,8 @@ static void smbchg_external_power_changed(struct power_supply *psy) POWER_SUPPLY_PROP_CURRENT_MAX, &prop); if (rc == 0) current_limit = prop.intval / 1000; - - rc = chip->usb_psy->get_property(chip->usb_psy, - POWER_SUPPLY_PROP_REAL_TYPE, &prop); - read_usb_type(chip, &usb_type_name, &usb_supply_type); - if (!rc && usb_supply_type == POWER_SUPPLY_TYPE_USB && - prop.intval != POWER_SUPPLY_TYPE_USB && - is_usb_present(chip)) { - /* incorrect type detected */ - pr_smb(PR_MISC, - "Incorrect charger type detetced - rerun APSD\n"); - chip->hvdcp_3_det_ignore_uv = true; - pr_smb(PR_MISC, "setting usb psy dp=f dm=f\n"); - power_supply_set_dp_dm(chip->usb_psy, - POWER_SUPPLY_DP_DM_DPF_DMF); - rc = rerun_apsd(chip); - if (rc) - pr_err("APSD re-run failed\n"); - chip->hvdcp_3_det_ignore_uv = false; - if (!is_src_detect_high(chip)) { - pr_smb(PR_MISC, "Charger removed - force removal\n"); - update_usb_status(chip, is_usb_present(chip), true); - return; - } - - read_usb_type(chip, &usb_type_name, &usb_supply_type); - if (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP) { - schedule_delayed_work(&chip->hvdcp_det_work, - msecs_to_jiffies(HVDCP_NOTIFY_MS)); - if (chip->parallel.use_parallel_aicl) { - reinit_completion(&chip->hvdcp_det_done); - pr_smb(PR_MISC, "init hvdcp_det_done\n"); - } - smbchg_change_usb_supply_type(chip, usb_supply_type); - } - - read_usb_type(chip, &usb_type_name, &usb_supply_type); - if (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP) - schedule_delayed_work(&chip->hvdcp_det_work, - msecs_to_jiffies(HVDCP_NOTIFY_MS)); - } - - if (usb_supply_type != POWER_SUPPLY_TYPE_USB) - goto skip_current_for_non_sdp; - pr_smb(PR_MISC, "usb type = %s current_limit = %d\n", usb_type_name, current_limit); @@ -6128,8 +6164,6 @@ static void smbchg_external_power_changed(struct power_supply *psy) if (rc < 0) pr_err("Couldn't update USB PSY ICL vote rc=%d\n", rc); -skip_current_for_non_sdp: - smbchg_vfloat_adjust_check(chip); power_supply_changed(&chip->batt_psy); } @@ -6141,9 +6175,12 @@ static enum power_supply_property smbchg_battery_properties[] = { POWER_SUPPLY_PROP_CHARGING_ENABLED, POWER_SUPPLY_PROP_CHARGE_TYPE, POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL, + POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, POWER_SUPPLY_PROP_FLASH_CURRENT_MAX, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX, @@ -6197,6 +6234,9 @@ static int smbchg_battery_set_property(struct power_supply *psy, case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: smbchg_system_temp_level_set(chip, val->intval); break; + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + smbchg_system_temp_level_set(chip, val->intval); + break; case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: rc = smbchg_set_fastchg_current_user(chip, val->intval / 1000); break; @@ -6321,7 +6361,7 @@ static int smbchg_battery_get_property(struct power_supply *psy, val->intval = get_prop_batt_health(chip); break; case POWER_SUPPLY_PROP_TECHNOLOGY: - val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; break; case POWER_SUPPLY_PROP_FLASH_CURRENT_MAX: val->intval = smbchg_calc_max_flash_current(chip); @@ -6332,6 +6372,12 @@ static int smbchg_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: val->intval = chip->therm_lvl_sel; break; + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: + val->intval = chip->therm_lvl_sel; + break; + case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: + val->intval = chip->thermal_levels; + break; case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: val->intval = smbchg_get_aicl_level_ma(chip) * 1000; break; @@ -6345,6 +6391,12 @@ static int smbchg_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CAPACITY: val->intval = get_prop_batt_capacity(chip); break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + val->intval = get_prop_battery_charge_full_design(chip); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + val->intval = get_prop_battery_charge_full(chip); + break; case POWER_SUPPLY_PROP_CURRENT_NOW: val->intval = get_prop_batt_current_now(chip); break; @@ -6354,9 +6406,6 @@ static int smbchg_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_RESISTANCE_ID: val->intval = get_prop_batt_resistance_id(chip); break; - case POWER_SUPPLY_PROP_CHARGE_FULL: - val->intval = get_prop_batt_full_charge(chip); - break; case POWER_SUPPLY_PROP_TEMP: val->intval = get_prop_batt_temp(chip); break; @@ -6534,6 +6583,15 @@ static irqreturn_t batt_warm_handler(int irq, void *_chip) struct smbchg_chip *chip = _chip; u8 reg = 0; + int rc; + /* set the warm float voltage compensation,set the warm float voltage to 4.1V */ + if (chip->float_voltage_comp != -EINVAL) { + rc = smbchg_float_voltage_comp_set(chip, chip->float_voltage_comp); + if (rc < 0) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", rc); + pr_smb(PR_STATUS, "set float voltage comp to %d\n", chip->float_voltage_comp); + } + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); chip->batt_warm = !!(reg & HOT_BAT_SOFT_BIT); pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); @@ -6550,6 +6608,12 @@ static irqreturn_t batt_cool_handler(int irq, void *_chip) struct smbchg_chip *chip = _chip; u8 reg = 0; + int rc; + /* set the cool float voltage compensation ,set the cool float voltage to 4.4V*/ + rc = smbchg_float_voltage_comp_set(chip, 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", rc); + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); chip->batt_cool = !!(reg & COLD_BAT_SOFT_BIT); pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); @@ -6577,6 +6641,40 @@ static irqreturn_t batt_pres_handler(int irq, void *_chip) return IRQ_HANDLED; } +static void smbchg_temp_check_work(struct work_struct *work) +{ + u8 reg = 0; + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + temp_check_work.work); + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_warm = !!(reg & HOT_BAT_SOFT_BIT); + chip->batt_cool = !!(reg & COLD_BAT_SOFT_BIT); + chip->batt_hot = !!(reg & HOT_BAT_HARD_BIT); + chip->batt_cold = !!(reg & COLD_BAT_HARD_BIT); + + pr_err("temp_check_work:chip->batt_warm:%d. chip->batt_cool:%d. chip->batt_hot:%d. chip->batt_cold:%d.\n", + chip->batt_warm, chip->batt_cool, chip->batt_hot, chip->batt_cold); + + if (chip->batt_warm && !chip->batt_hot) { + batt_warm_handler(0, chip); + pr_err("batt_warm_handler.\n"); + } + if (chip->batt_cool && !chip->batt_cold) { + batt_cool_handler(0, chip); + pr_err("batt_cool_handler.\n"); + } + if (chip->batt_hot) { + batt_hot_handler(0, chip); + pr_err("batt_hot_handler.\n"); + } + if (chip->batt_cold) { + batt_cold_handler(0, chip); + pr_err("batt_cold_handler.\n"); + } +} + static irqreturn_t vbat_low_handler(int irq, void *_chip) { pr_warn_ratelimited("vbat low\n"); @@ -7050,10 +7148,7 @@ static int determine_initial_status(struct smbchg_chip *chip) */ batt_pres_handler(0, chip); - batt_hot_handler(0, chip); - batt_warm_handler(0, chip); - batt_cool_handler(0, chip); - batt_cold_handler(0, chip); + if (chip->typec_psy) { get_property_from_typec(chip, POWER_SUPPLY_PROP_TYPE, &type); update_typec_otg_status(chip, type.intval, true); @@ -7267,6 +7362,12 @@ static int smbchg_hw_init(struct smbchg_chip *chip) return rc; } } + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + 0xFF, 0x00); + if (rc < 0) + dev_err(chip->dev, "Couldn't set only 5v OVP 6.4V rc=%d\n", + rc); rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + TR_RID_REG, FG_INPUT_FET_DELAY_BIT, FG_INPUT_FET_DELAY_BIT); @@ -8573,6 +8674,8 @@ static int smbchg_probe(struct spmi_device *spmi) smbchg_parallel_usb_en_work); INIT_DELAYED_WORK(&chip->vfloat_adjust_work, smbchg_vfloat_adjust_work); INIT_DELAYED_WORK(&chip->hvdcp_det_work, smbchg_hvdcp_det_work); + INIT_DELAYED_WORK(&chip->cool_limit_work, smbchg_cool_limit_work); + schedule_delayed_work(&chip->cool_limit_work, msecs_to_jiffies(SMBCHG_UPDATE_MS)); init_completion(&chip->src_det_lowered); init_completion(&chip->src_det_raised); init_completion(&chip->usbin_uv_lowered); @@ -8596,6 +8699,7 @@ static int smbchg_probe(struct spmi_device *spmi) mutex_init(&chip->pm_lock); mutex_init(&chip->wipower_config); mutex_init(&chip->usb_status_lock); + mutex_init(&chip->cool_current); device_init_wakeup(chip->dev, true); rc = smbchg_parse_peripherals(chip); @@ -8604,6 +8708,9 @@ static int smbchg_probe(struct spmi_device *spmi) goto votables_cleanup; } + printk("[SMBCHG]hvdcp disable\n"); + chip->hvdcp_not_supported = true; + rc = smbchg_check_chg_version(chip); if (rc) { pr_err("Unable to check schg version rc=%d\n", rc); @@ -8630,6 +8737,9 @@ static int smbchg_probe(struct spmi_device *spmi) goto out; } + INIT_DELAYED_WORK(&chip->temp_check_work, smbchg_temp_check_work); + schedule_delayed_work(&chip->temp_check_work, msecs_to_jiffies(SMBCHG_UPDATE_MS * 5)); + rc = determine_initial_status(chip); if (rc < 0) { dev_err(&spmi->dev, diff --git a/drivers/power/qpnp-smbcharger_e7.c b/drivers/power/qpnp-smbcharger_e7.c new file mode 100644 index 0000000000000..1bf5eff877a5d --- /dev/null +++ b/drivers/power/qpnp-smbcharger_e7.c @@ -0,0 +1,9094 @@ +/* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#define pr_fmt(fmt) "SMBCHG: %s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Mask/Bit helpers */ +#define _SMB_MASK(BITS, POS) \ + ((unsigned char)(((1 << (BITS)) - 1) << (POS))) +#define SMB_MASK(LEFT_BIT_POS, RIGHT_BIT_POS) \ + _SMB_MASK((LEFT_BIT_POS) - (RIGHT_BIT_POS) + 1, \ + (RIGHT_BIT_POS)) +/* Config registers */ +struct smbchg_regulator { + struct regulator_desc rdesc; + struct regulator_dev *rdev; +}; + +struct parallel_usb_cfg { + struct power_supply *psy; + int min_current_thr_ma; + int min_9v_current_thr_ma; + int allowed_lowering_ma; + int current_max_ma; + bool avail; + struct mutex lock; + int initial_aicl_ma; + ktime_t last_disabled; + bool enabled_once; + int parallel_aicl_ma; + int min_main_icl_ma; + bool use_parallel_aicl; + bool parallel_en_in_progress; +}; + +struct ilim_entry { + int vmin_uv; + int vmax_uv; + int icl_pt_ma; + int icl_lv_ma; + int icl_hv_ma; +}; + +struct ilim_map { + int num; + struct ilim_entry *entries; +}; + +struct smbchg_version_tables { + const int *dc_ilim_ma_table; + int dc_ilim_ma_len; + const int *usb_ilim_ma_table; + int usb_ilim_ma_len; + const int *iterm_ma_table; + int iterm_ma_len; + const int *fcc_comp_table; + int fcc_comp_len; + const int *aicl_rerun_period_table; + int aicl_rerun_period_len; + int rchg_thr_mv; +}; + +struct smbchg_chip { + struct device *dev; + struct spmi_device *spmi; + int schg_version; + char *debug_dump; + + /* peripheral register address bases */ + u16 chgr_base; + u16 bat_if_base; + u16 usb_chgpth_base; + u16 dc_chgpth_base; + u16 otg_base; + u16 misc_base; + + int fake_battery_soc; + u8 revision[4]; + + /* configuration parameters */ + int iterm_ma; + int usb_max_current_ma; + int typec_current_ma; + int dc_max_current_ma; + int dc_target_current_ma; + int cfg_fastchg_current_ma; + int fastchg_current_ma; + int vfloat_mv; + int fastchg_current_comp; + int float_voltage_comp; + int resume_delta_mv; + int safety_time; + int prechg_safety_time; + int bmd_pin_src; + int jeita_temp_hard_limit; + int aicl_rerun_period_s; + bool use_vfloat_adjustments; + bool iterm_disabled; + bool bmd_algo_disabled; + bool soft_vfloat_comp_disabled; + bool chg_enabled; + bool charge_unknown_battery; + bool chg_inhibit_en; + bool chg_inhibit_source_fg; + bool low_volt_dcin; + bool cfg_chg_led_support; + bool cfg_chg_led_sw_ctrl; + bool vbat_above_headroom; + bool force_aicl_rerun; + bool hvdcp3_supported; + bool allow_hvdcp3_detection; + bool restricted_charging; + bool skip_usb_suspend_for_fake_battery; + bool hvdcp_not_supported; + bool otg_pinctrl; + bool cfg_override_usb_current; + u8 original_usbin_allowance; + struct parallel_usb_cfg parallel; + struct delayed_work parallel_en_work; + struct dentry *debug_root; + struct smbchg_version_tables tables; + + /* wipower params */ + struct ilim_map wipower_default; + struct ilim_map wipower_pt; + struct ilim_map wipower_div2; + struct qpnp_vadc_chip *vadc_dev; + bool wipower_dyn_icl_avail; + struct ilim_entry current_ilim; + struct mutex wipower_config; + struct mutex cool_current; + bool wipower_configured; + struct qpnp_adc_tm_btm_param param; + + /* flash current prediction */ + int rpara_uohm; + int rslow_uohm; + int vled_max_uv; + + /* vfloat adjustment */ + int max_vbat_sample; + int n_vbat_samples; + + /* status variables */ + int max_pulse_allowed; + int wake_reasons; + int previous_soc; + int usb_online; + bool dc_present; + bool usb_present; + bool batt_present; + int otg_retries; + ktime_t otg_enable_time; + bool aicl_deglitch_short; + bool safety_timer_en; + bool aicl_complete; + bool usb_ov_det; + bool otg_pulse_skip_dis; + const char *battery_type; + enum power_supply_type usb_supply_type; + bool very_weak_charger; + bool parallel_charger_detected; + bool chg_otg_enabled; + bool flash_triggered; + bool flash_active; + bool icl_disabled; + u32 wa_flags; + int usb_icl_delta; + bool typec_dfp; + + /* jeita and temperature */ + bool batt_hot; + bool batt_cold; + bool batt_warm; + bool batt_cool; + unsigned int thermal_levels; + unsigned int therm_lvl_sel; + unsigned int *thermal_mitigation; + + /* irqs */ + int batt_hot_irq; + int batt_warm_irq; + int batt_cool_irq; + int batt_cold_irq; + int batt_missing_irq; + int vbat_low_irq; + int chg_hot_irq; + int chg_term_irq; + int taper_irq; + bool taper_irq_enabled; + struct mutex taper_irq_lock; + int recharge_irq; + int fastchg_irq; + int wdog_timeout_irq; + int power_ok_irq; + int dcin_uv_irq; + int usbin_uv_irq; + int usbin_ov_irq; + int src_detect_irq; + int otg_fail_irq; + int otg_oc_irq; + int aicl_done_irq; + int usbid_change_irq; + int chg_error_irq; + bool enable_aicl_wake; + + /* psy */ + struct power_supply *usb_psy; + struct power_supply batt_psy; + struct power_supply dc_psy; + struct power_supply *bms_psy; + struct power_supply *typec_psy; + int dc_psy_type; + const char *bms_psy_name; + const char *battery_psy_name; + bool psy_registered; + + struct smbchg_regulator otg_vreg; + struct smbchg_regulator ext_otg_vreg; + struct work_struct usb_set_online_work; + struct delayed_work vfloat_adjust_work; + struct delayed_work hvdcp_det_work; + struct delayed_work cool_limit_work; + struct delayed_work temp_check_work; + spinlock_t sec_access_lock; + struct mutex therm_lvl_lock; + struct mutex usb_set_online_lock; + struct mutex pm_lock; + /* aicl deglitch workaround */ + unsigned long first_aicl_seconds; + int aicl_irq_count; + struct mutex usb_status_lock; + bool hvdcp_3_det_ignore_uv; + struct completion src_det_lowered; + struct completion src_det_raised; + struct completion usbin_uv_lowered; + struct completion usbin_uv_raised; + struct completion hvdcp_det_done; + int pulse_cnt; + struct led_classdev led_cdev; + bool skip_usb_notification; + u32 vchg_adc_channel; + struct qpnp_vadc_chip *vchg_vadc_dev; + + /* voters */ + struct votable *fcc_votable; + struct votable *usb_icl_votable; + struct votable *dc_icl_votable; + struct votable *usb_suspend_votable; + struct votable *dc_suspend_votable; + struct votable *battchg_suspend_votable; + struct votable *hw_aicl_rerun_disable_votable; + struct votable *hw_aicl_rerun_enable_indirect_votable; + struct votable *aicl_deglitch_short_votable; + struct votable *hvdcp_enable_votable; +}; + +enum qpnp_schg { + QPNP_SCHG, + QPNP_SCHG_LITE, +}; + +static char *version_str[] = { + [QPNP_SCHG] = "SCHG", + [QPNP_SCHG_LITE] = "SCHG_LITE", +}; + +enum pmic_subtype { + PMI8994 = 10, + PMI8950 = 17, + PMI8996 = 19, + PMI8937 = 55, + PMI8940 = 64, +}; + +enum smbchg_wa { + SMBCHG_AICL_DEGLITCH_WA = BIT(0), + SMBCHG_HVDCP_9V_EN_WA = BIT(1), + SMBCHG_USB100_WA = BIT(2), + SMBCHG_BATT_OV_WA = BIT(3), + SMBCHG_CC_ESR_WA = BIT(4), + SMBCHG_FLASH_ICL_DISABLE_WA = BIT(5), + SMBCHG_RESTART_WA = BIT(6), + SMBCHG_FLASH_BUCK_SWITCH_FREQ_WA = BIT(7), + SMBCHG_ICL_CONTROL_WA = BIT(8), +}; + +enum print_reason { + PR_REGISTER = BIT(0), + PR_INTERRUPT = BIT(1), + PR_STATUS = BIT(2), + PR_DUMP = BIT(3), + PR_PM = BIT(4), + PR_MISC = BIT(5), + PR_WIPOWER = BIT(6), + PR_TYPEC = BIT(7), +}; + +enum wake_reason { + PM_PARALLEL_CHECK = BIT(0), + PM_REASON_VFLOAT_ADJUST = BIT(1), + PM_ESR_PULSE = BIT(2), + PM_PARALLEL_TAPER = BIT(3), + PM_DETECT_HVDCP = BIT(4), +}; + +/* fcc_voters */ +#define ESR_PULSE_FCC_VOTER "ESR_PULSE_FCC_VOTER" +#define BATT_TYPE_FCC_VOTER "BATT_TYPE_FCC_VOTER" +#define RESTRICTED_CHG_FCC_VOTER "RESTRICTED_CHG_FCC_VOTER" + +/* ICL VOTERS */ +#define PSY_ICL_VOTER "PSY_ICL_VOTER" +#define THERMAL_ICL_VOTER "THERMAL_ICL_VOTER" +#define HVDCP_ICL_VOTER "HVDCP_ICL_VOTER" +#define USER_ICL_VOTER "USER_ICL_VOTER" +#define WEAK_CHARGER_ICL_VOTER "WEAK_CHARGER_ICL_VOTER" +#define SW_AICL_ICL_VOTER "SW_AICL_ICL_VOTER" +#define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER" +#define SHUTDOWN_WORKAROUND_ICL_VOTER "SHUTDOWN_WORKAROUND_ICL_VOTER" +#define PARALLEL_ICL_VOTER "PARALLEL_ICL_VOTER" + +/* USB SUSPEND VOTERS */ +/* userspace has suspended charging altogether */ +#define USER_EN_VOTER "USER_EN_VOTER" +/* + * this specific path has been suspended through the power supply + * framework + */ +#define POWER_SUPPLY_EN_VOTER "POWER_SUPPLY_EN_VOTER" +/* + * the usb driver has suspended this path by setting a current limit + * of < 2MA + */ +#define USB_EN_VOTER "USB_EN_VOTER" +/* + * the thermal daemon can suspend a charge path when the system + * temperature levels rise + */ +#define THERMAL_EN_VOTER "THERMAL_EN_VOTER" +/* + * an external OTG supply is being used, suspend charge path so the + * charger does not accidentally try to charge from the external supply. + */ +#define OTG_EN_VOTER "OTG_EN_VOTER" +/* + * the charger is very weak, do not draw any current from it + */ +#define WEAK_CHARGER_EN_VOTER "WEAK_CHARGER_EN_VOTER" +/* + * fake battery voter, if battery id-resistance around 7.5 Kohm + */ +#define FAKE_BATTERY_EN_VOTER "FAKE_BATTERY_EN_VOTER" + +/* battchg_enable_voters */ + /* userspace has disabled battery charging */ +#define BATTCHG_USER_EN_VOTER "BATTCHG_USER_EN_VOTER" + /* battery charging disabled while loading battery profiles */ +#define BATTCHG_UNKNOWN_BATTERY_EN_VOTER "BATTCHG_UNKNOWN_BATTERY_EN_VOTER" + +/* hw_aicl_rerun_enable_indirect_voters */ +/* enabled via device tree */ +#define DEFAULT_CONFIG_HW_AICL_VOTER "DEFAULT_CONFIG_HW_AICL_VOTER" +/* Varb workaround voter */ +#define VARB_WORKAROUND_VOTER "VARB_WORKAROUND_VOTER" +/* SHUTDOWN workaround voter */ +#define SHUTDOWN_WORKAROUND_VOTER "SHUTDOWN_WORKAROUND_VOTER" + +/* hw_aicl_rerun_disable_voters */ +/* the results from enabling clients */ +#define HW_AICL_RERUN_ENABLE_INDIRECT_VOTER \ + "HW_AICL_RERUN_ENABLE_INDIRECT_VOTER" +/* Weak charger voter */ +#define WEAK_CHARGER_HW_AICL_VOTER "WEAK_CHARGER_HW_AICL_VOTER" + +/* aicl_short_deglitch_voters */ +/* Varb workaround voter */ +#define VARB_WORKAROUND_SHORT_DEGLITCH_VOTER \ + "VARB_WRKARND_SHORT_DEGLITCH_VOTER" +/* QC 2.0 */ +#define HVDCP_SHORT_DEGLITCH_VOTER "HVDCP_SHORT_DEGLITCH_VOTER" + +/* HVDCP voters */ +#define HVDCP_PMIC_VOTER "HVDCP_PMIC_VOTER" +#define HVDCP_OTG_VOTER "HVDCP_OTG_VOTER" +#define HVDCP_PULSING_VOTER "HVDCP_PULSING_VOTER" + +static int smbchg_debug_mask; +module_param_named( + debug_mask, smbchg_debug_mask, int, S_IRUSR | S_IWUSR +); + +static int smbchg_parallel_en = 1; +module_param_named( + parallel_en, smbchg_parallel_en, int, S_IRUSR | S_IWUSR +); + +static int smbchg_main_chg_fcc_percent = 50; +module_param_named( + main_chg_fcc_percent, smbchg_main_chg_fcc_percent, + int, S_IRUSR | S_IWUSR +); + +static int smbchg_main_chg_icl_percent = 60; +module_param_named( + main_chg_icl_percent, smbchg_main_chg_icl_percent, + int, S_IRUSR | S_IWUSR +); + +static int smbchg_default_hvdcp_icl_ma = 2500; +module_param_named( + default_hvdcp_icl_ma, smbchg_default_hvdcp_icl_ma, + int, S_IRUSR | S_IWUSR +); + +static int smbchg_default_hvdcp3_icl_ma = 2500; +module_param_named( + default_hvdcp3_icl_ma, smbchg_default_hvdcp3_icl_ma, + int, S_IRUSR | S_IWUSR +); + +static int smbchg_default_dcp_icl_ma = 1800; +module_param_named( + default_dcp_icl_ma, smbchg_default_dcp_icl_ma, + int, S_IRUSR | S_IWUSR +); + +static int wipower_dyn_icl_en; +module_param_named( + dynamic_icl_wipower_en, wipower_dyn_icl_en, + int, S_IRUSR | S_IWUSR +); + +static int wipower_dcin_interval = ADC_MEAS1_INTERVAL_2P0MS; +module_param_named( + wipower_dcin_interval, wipower_dcin_interval, + int, S_IRUSR | S_IWUSR +); + +static int hvdcp_type; +#define WIPOWER_DEFAULT_HYSTERISIS_UV 250000 +static int wipower_dcin_hyst_uv = WIPOWER_DEFAULT_HYSTERISIS_UV; +module_param_named( + wipower_dcin_hyst_uv, wipower_dcin_hyst_uv, + int, S_IRUSR | S_IWUSR +); + +static void dump_debug(struct smbchg_chip *chip); +#define pr_smb(reason, fmt, ...) \ + do { \ + if (smbchg_debug_mask & (reason)) \ + pr_info(fmt, ##__VA_ARGS__); \ + else \ + pr_debug(fmt, ##__VA_ARGS__); \ + } while (0) + +#define pr_smb_rt(reason, fmt, ...) \ + do { \ + if (smbchg_debug_mask & (reason)) \ + pr_info_ratelimited(fmt, ##__VA_ARGS__); \ + else \ + pr_debug_ratelimited(fmt, ##__VA_ARGS__); \ + } while (0) + +static int smbchg_read(struct smbchg_chip *chip, u8 *val, + u16 addr, int count) +{ + int rc = 0; + struct spmi_device *spmi = chip->spmi; + + if (addr == 0) { + dev_err(chip->dev, "addr cannot be zero addr=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return -EINVAL; + } + + rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, val, count); + if (rc) { + dev_err(chip->dev, "spmi read failed addr=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return rc; + } + return 0; +} + +/* + * Writes an arbitrary number of bytes to a specified register + * + * Do not use this function for register writes if possible. Instead use the + * smbchg_masked_write function. + * + * The sec_access_lock must be held for all register writes and this function + * does not do that. If this function is used, please hold the spinlock or + * random secure access writes may fail. + */ +static int smbchg_write(struct smbchg_chip *chip, u8 *val, + u16 addr, int count) +{ + int rc = 0; + struct spmi_device *spmi = chip->spmi; + + if (addr == 0) { + dev_err(chip->dev, "addr cannot be zero addr=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return -EINVAL; + } + + rc = spmi_ext_register_writel(spmi->ctrl, spmi->sid, addr, val, count); + if (rc) { + dev_err(chip->dev, "write failed addr=0x%02x sid=0x%02x rc=%d\n", + addr, spmi->sid, rc); + return rc; + } + + return 0; +} + +/* + * Writes a register to the specified by the base and limited by the bit mask + * + * Do not use this function for register writes if possible. Instead use the + * smbchg_masked_write function. + * + * The sec_access_lock must be held for all register writes and this function + * does not do that. If this function is used, please hold the spinlock or + * random secure access writes may fail. + */ +static int smbchg_masked_write_raw(struct smbchg_chip *chip, u16 base, u8 mask, + u8 val) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, base, 1); + if (rc) { + dev_err(chip->dev, "spmi read failed: addr=%03X, rc=%d\n", + base, rc); + return rc; + } + + reg &= ~mask; + reg |= val & mask; + + pr_smb(PR_REGISTER, "addr = 0x%x writing 0x%x\n", base, reg); + + rc = smbchg_write(chip, ®, base, 1); + if (rc) { + dev_err(chip->dev, "spmi write failed: addr=%03X, rc=%d\n", + base, rc); + return rc; + } + + return 0; +} + +/* + * Writes a register to the specified by the base and limited by the bit mask + * + * This function holds a spin lock to ensure secure access register writes goes + * through. If the secure access unlock register is armed, any old register + * write can unarm the secure access unlock, causing the next write to fail. + * + * Note: do not use this for sec_access registers. Instead use the function + * below: smbchg_sec_masked_write + */ +static int smbchg_masked_write(struct smbchg_chip *chip, u16 base, u8 mask, + u8 val) +{ + unsigned long flags; + int rc; + + spin_lock_irqsave(&chip->sec_access_lock, flags); + rc = smbchg_masked_write_raw(chip, base, mask, val); + spin_unlock_irqrestore(&chip->sec_access_lock, flags); + + return rc; +} + +/* + * Unlocks sec access and writes to the register specified. + * + * This function holds a spin lock to exclude other register writes while + * the two writes are taking place. + */ +#define SEC_ACCESS_OFFSET 0xD0 +#define SEC_ACCESS_VALUE 0xA5 +#define PERIPHERAL_MASK 0xFF +static int smbchg_sec_masked_write(struct smbchg_chip *chip, u16 base, u8 mask, + u8 val) +{ + unsigned long flags; + int rc; + u16 peripheral_base = base & (~PERIPHERAL_MASK); + + spin_lock_irqsave(&chip->sec_access_lock, flags); + + rc = smbchg_masked_write_raw(chip, peripheral_base + SEC_ACCESS_OFFSET, + SEC_ACCESS_VALUE, SEC_ACCESS_VALUE); + if (rc) { + dev_err(chip->dev, "Unable to unlock sec_access: %d", rc); + goto out; + } + + rc = smbchg_masked_write_raw(chip, base, mask, val); + +out: + spin_unlock_irqrestore(&chip->sec_access_lock, flags); + return rc; +} + +static void smbchg_stay_awake(struct smbchg_chip *chip, int reason) +{ + int reasons; + + mutex_lock(&chip->pm_lock); + reasons = chip->wake_reasons | reason; + if (reasons != 0 && chip->wake_reasons == 0) { + pr_smb(PR_PM, "staying awake: 0x%02x (bit %d)\n", + reasons, reason); + pm_stay_awake(chip->dev); + } + chip->wake_reasons = reasons; + mutex_unlock(&chip->pm_lock); +} + +static void smbchg_relax(struct smbchg_chip *chip, int reason) +{ + int reasons; + + mutex_lock(&chip->pm_lock); + reasons = chip->wake_reasons & (~reason); + if (reasons == 0 && chip->wake_reasons != 0) { + pr_smb(PR_PM, "relaxing: 0x%02x (bit %d)\n", + reasons, reason); + pm_relax(chip->dev); + } + chip->wake_reasons = reasons; + mutex_unlock(&chip->pm_lock); +}; + +enum pwr_path_type { + UNKNOWN = 0, + PWR_PATH_BATTERY = 1, + PWR_PATH_USB = 2, + PWR_PATH_DC = 3, +}; + +#define PWR_PATH 0x08 +#define PWR_PATH_MASK 0x03 +static enum pwr_path_type smbchg_get_pwr_path(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + PWR_PATH, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read PWR_PATH rc = %d\n", rc); + return PWR_PATH_BATTERY; + } + + return reg & PWR_PATH_MASK; +} + +#define RID_STS 0xB +#define RID_MASK 0xF +#define IDEV_STS 0x8 +#define RT_STS 0x10 +#define USBID_MSB 0xE +#define USBIN_UV_BIT BIT(0) +#define USBIN_OV_BIT BIT(1) +#define USBIN_SRC_DET_BIT BIT(2) +#define FMB_STS_MASK SMB_MASK(3, 0) +#define USBID_GND_THRESHOLD 0x495 +static bool is_otg_present_schg(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + u8 usbid_reg[2]; + u16 usbid_val; + /* + * After the falling edge of the usbid change interrupt occurs, + * there may still be some time before the ADC conversion for USB RID + * finishes in the fuel gauge. In the worst case, this could be up to + * 15 ms. + * + * Sleep for 20 ms (minimum msleep time) to wait for the conversion to + * finish and the USB RID status register to be updated before trying + * to detect OTG insertions. + */ + + msleep(20); + + /* + * There is a problem with USBID conversions on PMI8994 revisions + * 2.0.0. As a workaround, check that the cable is not + * detected as factory test before enabling OTG. + */ + rc = smbchg_read(chip, ®, chip->misc_base + IDEV_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read IDEV_STS rc = %d\n", rc); + return false; + } + + if ((reg & FMB_STS_MASK) != 0) { + pr_smb(PR_STATUS, "IDEV_STS = %02x, not ground\n", reg); + return false; + } + + rc = smbchg_read(chip, usbid_reg, chip->usb_chgpth_base + USBID_MSB, 2); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read USBID rc = %d\n", rc); + return false; + } + usbid_val = (usbid_reg[0] << 8) | usbid_reg[1]; + + if (usbid_val > USBID_GND_THRESHOLD) { + pr_smb(PR_STATUS, "USBID = 0x%04x, too high to be ground\n", + usbid_val); + return false; + } + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RID_STS, 1); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't read usb rid status rc = %d\n", rc); + return false; + } + + pr_smb(PR_STATUS, "RID_STS = %02x\n", reg); + + return (reg & RID_MASK) == 0; +} + +#define RID_GND_DET_STS BIT(2) +static bool is_otg_present_schg_lite(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->otg_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't read otg RT status rc = %d\n", rc); + return false; + } + + return !!(reg & RID_GND_DET_STS); +} + +static bool is_otg_present(struct smbchg_chip *chip) +{ + if (chip->schg_version == QPNP_SCHG_LITE) + return is_otg_present_schg_lite(chip); + + return is_otg_present_schg(chip); +} + +#define USBIN_9V BIT(5) +#define USBIN_UNREG BIT(4) +#define USBIN_LV BIT(3) +#define DCIN_9V BIT(2) +#define DCIN_UNREG BIT(1) +#define DCIN_LV BIT(0) +#define INPUT_STS 0x0D +#define DCIN_UV_BIT BIT(0) +#define DCIN_OV_BIT BIT(1) +static bool is_dc_present(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->dc_chgpth_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read dc status rc = %d\n", rc); + return false; + } + + if ((reg & DCIN_UV_BIT) || (reg & DCIN_OV_BIT)) + return false; + + return true; +} + +static bool is_usb_present(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb rt status rc = %d\n", rc); + return false; + } + if (!(reg & USBIN_SRC_DET_BIT) || (reg & USBIN_OV_BIT)) + return false; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + INPUT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb status rc = %d\n", rc); + return false; + } + + return !!(reg & (USBIN_9V | USBIN_UNREG | USBIN_LV)); +} + +static char *usb_type_str[] = { + "SDP", /* bit 0 */ + "OTHER", /* bit 1 */ + "DCP", /* bit 2 */ + "CDP", /* bit 3 */ + "NONE", /* bit 4 error case */ +}; + +#define N_TYPE_BITS 4 +#define TYPE_BITS_OFFSET 4 + +static int get_type(u8 type_reg) +{ + unsigned long type = type_reg; + type >>= TYPE_BITS_OFFSET; + return find_first_bit(&type, N_TYPE_BITS); +} + +/* helper to return the string of USB type */ +static inline char *get_usb_type_name(int type) +{ + return usb_type_str[type]; +} + +static enum power_supply_type usb_type_enum[] = { + POWER_SUPPLY_TYPE_USB, /* bit 0 */ + POWER_SUPPLY_TYPE_USB_DCP, /* bit 1 */ + POWER_SUPPLY_TYPE_USB_DCP, /* bit 2 */ + POWER_SUPPLY_TYPE_USB_CDP, /* bit 3 */ + POWER_SUPPLY_TYPE_USB_DCP, /* bit 4 error case, report DCP */ +}; + +/* helper to return enum power_supply_type of USB type */ +static inline enum power_supply_type get_usb_supply_type(int type) +{ + return usb_type_enum[type]; +} + +static bool is_src_detect_high(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb rt status rc = %d\n", rc); + return false; + } + return reg &= USBIN_SRC_DET_BIT; +} + +static void read_usb_type(struct smbchg_chip *chip, char **usb_type_name, + enum power_supply_type *usb_supply_type) +{ + int rc, type; + u8 reg; + + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "src det low\n"); + *usb_type_name = "Absent"; + *usb_supply_type = POWER_SUPPLY_TYPE_UNKNOWN; + return; + } + + rc = smbchg_read(chip, ®, chip->misc_base + IDEV_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read status 5 rc = %d\n", rc); + *usb_type_name = "Other"; + *usb_supply_type = POWER_SUPPLY_TYPE_UNKNOWN; + return; + } + type = get_type(reg); + *usb_type_name = get_usb_type_name(type); + *usb_supply_type = get_usb_supply_type(type); +} + +#define CHGR_STS 0x0E +#define BATT_LESS_THAN_2V BIT(4) +#define CHG_HOLD_OFF_BIT BIT(3) +#define CHG_TYPE_MASK SMB_MASK(2, 1) +#define CHG_TYPE_SHIFT 1 +#define BATT_NOT_CHG_VAL 0x0 +#define BATT_PRE_CHG_VAL 0x1 +#define BATT_FAST_CHG_VAL 0x2 +#define BATT_TAPER_CHG_VAL 0x3 +#define CHG_INHIBIT_BIT BIT(1) +#define BAT_TCC_REACHED_BIT BIT(7) +static int get_prop_batt_status(struct smbchg_chip *chip) +{ + int rc, status = POWER_SUPPLY_STATUS_DISCHARGING; + u8 reg = 0, chg_type; + bool charger_present, chg_inhibit; + + charger_present = is_usb_present(chip) | is_dc_present(chip) | + chip->hvdcp_3_det_ignore_uv; + if (!charger_present) + return POWER_SUPPLY_STATUS_DISCHARGING; + + rc = smbchg_read(chip, ®, chip->chgr_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Unable to read RT_STS rc = %d\n", rc); + return POWER_SUPPLY_STATUS_UNKNOWN; + } + + if (reg & BAT_TCC_REACHED_BIT) + return POWER_SUPPLY_STATUS_FULL; + + chg_inhibit = reg & CHG_INHIBIT_BIT; + if (chg_inhibit) + return POWER_SUPPLY_STATUS_FULL; + + rc = smbchg_read(chip, ®, chip->chgr_base + CHGR_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Unable to read CHGR_STS rc = %d\n", rc); + return POWER_SUPPLY_STATUS_UNKNOWN; + } + + if (reg & CHG_HOLD_OFF_BIT) { + /* + * when chg hold off happens the battery is + * not charging + */ + status = POWER_SUPPLY_STATUS_NOT_CHARGING; + goto out; + } + + chg_type = (reg & CHG_TYPE_MASK) >> CHG_TYPE_SHIFT; + + if (chg_type == BATT_NOT_CHG_VAL && !chip->hvdcp_3_det_ignore_uv) + status = POWER_SUPPLY_STATUS_DISCHARGING; + else + status = POWER_SUPPLY_STATUS_CHARGING; +out: + pr_smb_rt(PR_MISC, "CHGR_STS = 0x%02x\n", reg); + return status; +} + +#define BAT_PRES_STATUS 0x08 +#define BAT_PRES_BIT BIT(7) +static int get_prop_batt_present(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->bat_if_base + BAT_PRES_STATUS, 1); + if (rc < 0) { + dev_err(chip->dev, "Unable to read CHGR_STS rc = %d\n", rc); + return 0; + } + + return !!(reg & BAT_PRES_BIT); +} + +static int get_prop_charge_type(struct smbchg_chip *chip) +{ + int rc; + u8 reg, chg_type; + + rc = smbchg_read(chip, ®, chip->chgr_base + CHGR_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Unable to read CHGR_STS rc = %d\n", rc); + return 0; + } + + chg_type = (reg & CHG_TYPE_MASK) >> CHG_TYPE_SHIFT; + if (chg_type == BATT_NOT_CHG_VAL) + return POWER_SUPPLY_CHARGE_TYPE_NONE; + else if (chg_type == BATT_TAPER_CHG_VAL) + return POWER_SUPPLY_CHARGE_TYPE_TAPER; + else if (chg_type == BATT_FAST_CHG_VAL) + return POWER_SUPPLY_CHARGE_TYPE_FAST; + else if (chg_type == BATT_PRE_CHG_VAL) + return POWER_SUPPLY_CHARGE_TYPE_TRICKLE; + + return POWER_SUPPLY_CHARGE_TYPE_NONE; +} + +static int set_property_on_fg(struct smbchg_chip *chip, + enum power_supply_property prop, int val) +{ + int rc; + union power_supply_propval ret = {0, }; + + if (!chip->bms_psy && chip->bms_psy_name) + chip->bms_psy = + power_supply_get_by_name((char *)chip->bms_psy_name); + if (!chip->bms_psy) { + pr_smb(PR_STATUS, "no bms psy found\n"); + return -EINVAL; + } + + ret.intval = val; + rc = chip->bms_psy->set_property(chip->bms_psy, prop, &ret); + if (rc) + pr_smb(PR_STATUS, + "bms psy does not allow updating prop %d rc = %d\n", + prop, rc); + + return rc; +} + +static int get_property_from_fg(struct smbchg_chip *chip, + enum power_supply_property prop, int *val) +{ + int rc; + union power_supply_propval ret = {0, }; + + if (!chip->bms_psy && chip->bms_psy_name) + chip->bms_psy = + power_supply_get_by_name((char *)chip->bms_psy_name); + if (!chip->bms_psy) { + pr_smb(PR_STATUS, "no bms psy found\n"); + return -EINVAL; + } + + rc = chip->bms_psy->get_property(chip->bms_psy, prop, &ret); + if (rc) { + pr_smb(PR_STATUS, + "bms psy doesn't support reading prop %d rc = %d\n", + prop, rc); + return rc; + } + + *val = ret.intval; + return rc; +} + +#define DEFAULT_BATT_CAPACITY 50 +static int get_prop_batt_capacity(struct smbchg_chip *chip) +{ + int capacity, rc; + + if (chip->fake_battery_soc >= 0) + return chip->fake_battery_soc; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CAPACITY, &capacity); + if (rc) { + pr_smb(PR_STATUS, "Couldn't get capacity rc = %d\n", rc); + capacity = DEFAULT_BATT_CAPACITY; + } + return capacity; +} + +static int get_prop_battery_charge_full_design(struct smbchg_chip *chip) +{ + union power_supply_propval ret = {0,}; + if (chip->bms_psy) { + chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &ret); + return 4000000; + } else { + pr_debug("No BMS supply registered return 0\n"); + } + return 0; +} + +static int get_prop_battery_charge_full(struct smbchg_chip *chip) +{ + union power_supply_propval ret = {0,}; + + if (chip->bms_psy) { + chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_CHARGE_FULL, &ret); + return 4000000; + } else { + pr_debug("No BMS supply registered return 0\n"); + } + + return 0; +} + +#define DEFAULT_BATT_TEMP 200 +static int get_prop_batt_temp(struct smbchg_chip *chip) +{ + int temp, rc; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_TEMP, &temp); + if (rc) { + pr_smb(PR_STATUS, "Couldn't get temperature rc = %d\n", rc); + temp = DEFAULT_BATT_TEMP; + } + return temp; +} + +#define DEFAULT_BATT_CURRENT_NOW 0 +static int get_prop_batt_current_now(struct smbchg_chip *chip) +{ + int ua, rc; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CURRENT_NOW, &ua); + if (rc) { + pr_smb(PR_STATUS, "Couldn't get current rc = %d\n", rc); + ua = DEFAULT_BATT_CURRENT_NOW; + } + return ua; +} + +#define DEFAULT_BATT_RESISTANCE_ID 0 +static int get_prop_batt_resistance_id(struct smbchg_chip *chip) +{ + int rbatt, rc; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE_ID, + &rbatt); + if (rc) { + pr_smb(PR_STATUS, "Couldn't get resistance id rc = %d\n", rc); + rbatt = DEFAULT_BATT_RESISTANCE_ID; + } + return rbatt; +} + +#define DEFAULT_BATT_VOLTAGE_NOW 0 +static int get_prop_batt_voltage_now(struct smbchg_chip *chip) +{ + int uv, rc; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_VOLTAGE_NOW, &uv); + if (rc) { + pr_smb(PR_STATUS, "Couldn't get voltage rc = %d\n", rc); + uv = DEFAULT_BATT_VOLTAGE_NOW; + } + return uv; +} + +#define DEFAULT_BATT_VOLTAGE_MAX_DESIGN 4200000 +static int get_prop_batt_voltage_max_design(struct smbchg_chip *chip) +{ + int uv, rc; + + rc = get_property_from_fg(chip, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, &uv); + if (rc) { + pr_smb(PR_STATUS, "Couldn't get voltage rc = %d\n", rc); + uv = DEFAULT_BATT_VOLTAGE_MAX_DESIGN; + } + return uv; +} + +static int get_prop_batt_health(struct smbchg_chip *chip) +{ + if (chip->batt_hot) + return POWER_SUPPLY_HEALTH_OVERHEAT; + else if (chip->batt_cold) + return POWER_SUPPLY_HEALTH_COLD; + else if (chip->batt_warm) + return POWER_SUPPLY_HEALTH_WARM; + else if (chip->batt_cool) + return POWER_SUPPLY_HEALTH_COOL; + else + return POWER_SUPPLY_HEALTH_GOOD; +} + +static void get_property_from_typec(struct smbchg_chip *chip, + enum power_supply_property property, + union power_supply_propval *prop) +{ + int rc; + + rc = chip->typec_psy->get_property(chip->typec_psy, property, prop); + if (rc) + pr_smb(PR_TYPEC, + "typec psy doesn't support reading prop %d rc = %d\n", + property, rc); +} + +static void update_typec_status(struct smbchg_chip *chip) +{ + union power_supply_propval type = {0, }; + union power_supply_propval capability = {0, }; + int rc; + + get_property_from_typec(chip, POWER_SUPPLY_PROP_TYPE, &type); + if (type.intval != POWER_SUPPLY_TYPE_UNKNOWN) { + get_property_from_typec(chip, + POWER_SUPPLY_PROP_CURRENT_CAPABILITY, + &capability); + chip->typec_current_ma = capability.intval; + + if (!chip->skip_usb_notification) { + rc = chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, + &capability); + if (rc) + pr_err("typec failed to set current max rc=%d\n", + rc); + pr_smb(PR_TYPEC, "SMB Type-C mode = %d, current=%d\n", + type.intval, capability.intval); + } + } else { + pr_smb(PR_TYPEC, + "typec detection not completed continuing with USB update\n"); + } +} + +/* + * finds the index of the closest value in the array. If there are two that + * are equally close, the lower index will be returned + */ +static int find_closest_in_array(const int *arr, int len, int val) +{ + int i, closest = 0; + + if (len == 0) + return closest; + for (i = 0; i < len; i++) + if (abs(val - arr[i]) < abs(val - arr[closest])) + closest = i; + + return closest; +} + +/* finds the index of the closest smaller value in the array. */ +static int find_smaller_in_array(const int *table, int val, int len) +{ + int i; + + for (i = len - 1; i >= 0; i--) { + if (val >= table[i]) + break; + } + + return i; +} + +static const int iterm_ma_table_8994[] = { + 300, + 50, + 100, + 150, + 200, + 250, + 500, + 600 +}; + +static const int iterm_ma_table_8996[] = { + 300, + 50, + 100, + 150, + 200, + 250, + 400, + 500 +}; + +static const int usb_ilim_ma_table_8994[] = { + 300, + 400, + 450, + 475, + 500, + 550, + 600, + 650, + 700, + 900, + 950, + 1000, + 1100, + 1200, + 1400, + 1450, + 1500, + 1600, + 1800, + 1850, + 1880, + 1910, + 1930, + 1950, + 1970, + 2000, + 2050, + 2100, + 2300, + 2400, + 2500, + 3000 +}; + +static const int usb_ilim_ma_table_8996[] = { + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, + 1100, + 1200, + 1300, + 1400, + 1450, + 1500, + 1550, + 1600, + 1700, + 1800, + 1900, + 1950, + 2000, + 2050, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000 +}; + +static int dc_ilim_ma_table_8994[] = { + 300, + 400, + 450, + 475, + 500, + 550, + 600, + 650, + 700, + 900, + 950, + 1000, + 1100, + 1200, + 1400, + 1450, + 1500, + 1600, + 1800, + 1850, + 1880, + 1910, + 1930, + 1950, + 1970, + 2000, +}; + +static int dc_ilim_ma_table_8996[] = { + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, + 1100, + 1200, + 1300, + 1400, + 1450, + 1500, + 1550, + 1600, + 1700, + 1800, + 1900, + 1950, + 2000, + 2050, + 2100, + 2200, + 2300, + 2400, +}; + +static const int fcc_comp_table_8994[] = { + 250, + 700, + 900, + 1200, +}; + +static const int fcc_comp_table_8996[] = { + 250, + 1100, + 1200, + 1500, +}; + +static const int aicl_rerun_period[] = { + 45, + 90, + 180, + 360, +}; + +static const int aicl_rerun_period_schg_lite[] = { + 3, /* 2.8s */ + 6, /* 5.6s */ + 11, /* 11.3s */ + 23, /* 22.5s */ + 45, + 90, + 180, + 360, +}; + +static void use_pmi8994_tables(struct smbchg_chip *chip) +{ + chip->tables.usb_ilim_ma_table = usb_ilim_ma_table_8994; + chip->tables.usb_ilim_ma_len = ARRAY_SIZE(usb_ilim_ma_table_8994); + chip->tables.dc_ilim_ma_table = dc_ilim_ma_table_8994; + chip->tables.dc_ilim_ma_len = ARRAY_SIZE(dc_ilim_ma_table_8994); + chip->tables.iterm_ma_table = iterm_ma_table_8994; + chip->tables.iterm_ma_len = ARRAY_SIZE(iterm_ma_table_8994); + chip->tables.fcc_comp_table = fcc_comp_table_8994; + chip->tables.fcc_comp_len = ARRAY_SIZE(fcc_comp_table_8994); + chip->tables.rchg_thr_mv = 200; + chip->tables.aicl_rerun_period_table = aicl_rerun_period; + chip->tables.aicl_rerun_period_len = ARRAY_SIZE(aicl_rerun_period); +} + +static void use_pmi8996_tables(struct smbchg_chip *chip) +{ + chip->tables.usb_ilim_ma_table = usb_ilim_ma_table_8996; + chip->tables.usb_ilim_ma_len = ARRAY_SIZE(usb_ilim_ma_table_8996); + chip->tables.dc_ilim_ma_table = dc_ilim_ma_table_8996; + chip->tables.dc_ilim_ma_len = ARRAY_SIZE(dc_ilim_ma_table_8996); + chip->tables.iterm_ma_table = iterm_ma_table_8996; + chip->tables.iterm_ma_len = ARRAY_SIZE(iterm_ma_table_8996); + chip->tables.fcc_comp_table = fcc_comp_table_8996; + chip->tables.fcc_comp_len = ARRAY_SIZE(fcc_comp_table_8996); + chip->tables.rchg_thr_mv = 150; + chip->tables.aicl_rerun_period_table = aicl_rerun_period; + chip->tables.aicl_rerun_period_len = ARRAY_SIZE(aicl_rerun_period); +} + +#define CMD_CHG_REG 0x42 +#define EN_BAT_CHG_BIT BIT(1) +static int smbchg_charging_en(struct smbchg_chip *chip, bool en) +{ + /* The en bit is configured active low */ + return smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_REG, + EN_BAT_CHG_BIT, en ? 0 : EN_BAT_CHG_BIT); +} + +#define CMD_IL 0x40 +#define USBIN_SUSPEND_BIT BIT(4) +#define CURRENT_100_MA 100 +#define CURRENT_150_MA 150 +#define CURRENT_500_MA 500 +#define CURRENT_900_MA 900 +#define CURRENT_1500_MA 1500 +#define SUSPEND_CURRENT_MA 2 +#define ICL_OVERRIDE_BIT BIT(2) +static int smbchg_usb_suspend(struct smbchg_chip *chip, bool suspend) +{ + int rc; + + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + USBIN_SUSPEND_BIT, suspend ? USBIN_SUSPEND_BIT : 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't set usb suspend rc = %d\n", rc); + return rc; +} + +#define DCIN_SUSPEND_BIT BIT(3) +static int smbchg_dc_suspend(struct smbchg_chip *chip, bool suspend) +{ + int rc = 0; + + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + DCIN_SUSPEND_BIT, suspend ? DCIN_SUSPEND_BIT : 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't set dc suspend rc = %d\n", rc); + return rc; +} + +#define IL_CFG 0xF2 +#define DCIN_INPUT_MASK SMB_MASK(4, 0) +static int smbchg_set_dc_current_max(struct smbchg_chip *chip, int current_ma) +{ + int i; + u8 dc_cur_val; + + i = find_smaller_in_array(chip->tables.dc_ilim_ma_table, + current_ma, chip->tables.dc_ilim_ma_len); + + if (i < 0) { + dev_err(chip->dev, "Cannot find %dma current_table\n", + current_ma); + return -EINVAL; + } + + chip->dc_max_current_ma = chip->tables.dc_ilim_ma_table[i]; + dc_cur_val = i & DCIN_INPUT_MASK; + + pr_smb(PR_STATUS, "dc current set to %d mA\n", + chip->dc_max_current_ma); + return smbchg_sec_masked_write(chip, chip->dc_chgpth_base + IL_CFG, + DCIN_INPUT_MASK, dc_cur_val); +} + +#define AICL_WL_SEL_CFG 0xF5 +#define AICL_WL_SEL_MASK SMB_MASK(1, 0) +#define AICL_WL_SEL_SCHG_LITE_MASK SMB_MASK(2, 0) +static int smbchg_set_aicl_rerun_period_s(struct smbchg_chip *chip, + int period_s) +{ + int i; + u8 reg, mask; + + i = find_smaller_in_array(chip->tables.aicl_rerun_period_table, + period_s, chip->tables.aicl_rerun_period_len); + + if (i < 0) { + dev_err(chip->dev, "Cannot find %ds in aicl rerun period\n", + period_s); + return -EINVAL; + } + + if (chip->schg_version == QPNP_SCHG_LITE) + mask = AICL_WL_SEL_SCHG_LITE_MASK; + else + mask = AICL_WL_SEL_MASK; + + reg = i & mask; + + pr_smb(PR_STATUS, "aicl rerun period set to %ds\n", + chip->tables.aicl_rerun_period_table[i]); + return smbchg_sec_masked_write(chip, + chip->dc_chgpth_base + AICL_WL_SEL_CFG, + mask, reg); +} + +static struct power_supply *get_parallel_psy(struct smbchg_chip *chip) +{ + if (!chip->parallel.avail) + return NULL; + if (chip->parallel.psy) + return chip->parallel.psy; + chip->parallel.psy = power_supply_get_by_name("usb-parallel"); + if (!chip->parallel.psy) + pr_smb(PR_STATUS, "parallel charger not found\n"); + return chip->parallel.psy; +} + +static void smbchg_usb_update_online_work(struct work_struct *work) +{ + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + usb_set_online_work); + bool user_enabled = !get_client_vote(chip->usb_suspend_votable, + USER_EN_VOTER); + int online; + + online = user_enabled && chip->usb_present && !chip->very_weak_charger; + + mutex_lock(&chip->usb_set_online_lock); + if (chip->usb_online != online) { + pr_smb(PR_MISC, "setting usb psy online = %d\n", online); + power_supply_set_online(chip->usb_psy, online); + chip->usb_online = online; + } + mutex_unlock(&chip->usb_set_online_lock); +} + +#define CHGPTH_CFG 0xF4 +#define CFG_USB_2_3_SEL_BIT BIT(7) +#define CFG_USB_2 0 +#define CFG_USB_3 BIT(7) +#define USBIN_INPUT_MASK SMB_MASK(4, 0) +#define USBIN_MODE_CHG_BIT BIT(0) +#define USBIN_LIMITED_MODE 0 +#define USBIN_HC_MODE BIT(0) +#define USB51_MODE_BIT BIT(1) +#define USB51_100MA 0 +#define USB51_500MA BIT(1) +static int smbchg_set_high_usb_chg_current(struct smbchg_chip *chip, + int current_ma) +{ + int i, rc; + u8 usb_cur_val; + + if (current_ma == CURRENT_100_MA) { + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + CFG_USB_2_3_SEL_BIT, CFG_USB_2); + if (rc < 0) { + pr_err("Couldn't set CFG_USB_2 rc=%d\n", rc); + return rc; + } + + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT | USB51_MODE_BIT | ICL_OVERRIDE_BIT, + USBIN_LIMITED_MODE | USB51_100MA | ICL_OVERRIDE_BIT); + if (rc < 0) { + pr_err("Couldn't set ICL_OVERRIDE rc=%d\n", rc); + return rc; + } + + pr_smb(PR_STATUS, + "Forcing 100mA current limit\n"); + chip->usb_max_current_ma = CURRENT_100_MA; + return rc; + } + + i = find_smaller_in_array(chip->tables.usb_ilim_ma_table, + current_ma, chip->tables.usb_ilim_ma_len); + if (i < 0) { + dev_err(chip->dev, + "Cannot find %dma current_table using %d\n", + current_ma, CURRENT_150_MA); + + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + CFG_USB_2_3_SEL_BIT, CFG_USB_3); + rc |= smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT | USB51_MODE_BIT, + USBIN_LIMITED_MODE | USB51_100MA); + if (rc < 0) + dev_err(chip->dev, "Couldn't set %dmA rc=%d\n", + CURRENT_150_MA, rc); + else + chip->usb_max_current_ma = 150; + return rc; + } + + usb_cur_val = i & USBIN_INPUT_MASK; + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + IL_CFG, + USBIN_INPUT_MASK, usb_cur_val); + if (rc < 0) { + dev_err(chip->dev, "cannot write to config c rc = %d\n", rc); + return rc; + } + + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT, USBIN_HC_MODE); + if (rc < 0) + dev_err(chip->dev, "Couldn't write cfg 5 rc = %d\n", rc); + chip->usb_max_current_ma = chip->tables.usb_ilim_ma_table[i]; + return rc; +} + +/* if APSD results are used + * if SDP is detected it will look at 500mA setting + * if set it will draw 500mA + * if unset it will draw 100mA + * if CDP/DCP it will look at 0x0C setting + * i.e. values in 0x41[1, 0] does not matter + */ +static int smbchg_set_usb_current_max(struct smbchg_chip *chip, + int current_ma) +{ + int rc = 0; + + /* + * if the battery is not present, do not allow the usb ICL to lower in + * order to avoid browning out the device during a hotswap. + */ + if (!chip->batt_present && current_ma < chip->usb_max_current_ma) { + pr_info_ratelimited("Ignoring usb current->%d, battery is absent\n", + current_ma); + return 0; + } + pr_smb(PR_STATUS, "USB current_ma = %d\n", current_ma); + + if (current_ma <= SUSPEND_CURRENT_MA) { + /* suspend the usb if current <= 2mA */ + rc = vote(chip->usb_suspend_votable, USB_EN_VOTER, true, 0); + chip->usb_max_current_ma = 0; + goto out; + } else { + rc = vote(chip->usb_suspend_votable, USB_EN_VOTER, false, 0); + } + + switch (chip->usb_supply_type) { + case POWER_SUPPLY_TYPE_USB: + if ((current_ma < CURRENT_150_MA) && + (chip->wa_flags & SMBCHG_USB100_WA)) + current_ma = CURRENT_150_MA; + + /* handle special SDP case when USB reports high current */ + if (current_ma > CURRENT_900_MA) { + if (chip->cfg_override_usb_current) { + /* + * allow setting the current value as reported + * by USB driver. + */ + rc = smbchg_set_high_usb_chg_current(chip, + current_ma); + if (rc < 0) { + pr_err("Couldn't set %dmA rc = %d\n", + current_ma, rc); + goto out; + } + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + CMD_IL, + ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); + if (rc < 0) + pr_err("Couldn't set ICL override rc = %d\n", + rc); + } else { + /* default to 500mA */ + current_ma = CURRENT_500_MA; + } + pr_smb(PR_STATUS, + "override_usb_current=%d current_ma set to %d\n", + chip->cfg_override_usb_current, current_ma); + } + + if (current_ma < CURRENT_150_MA) { + /* force 100mA */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + CFG_USB_2_3_SEL_BIT, CFG_USB_2); + if (rc < 0) { + pr_err("Couldn't set CHGPTH_CFG rc = %d\n", rc); + goto out; + } + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT | USB51_MODE_BIT, + USBIN_LIMITED_MODE | USB51_100MA); + if (rc < 0) { + pr_err("Couldn't set CMD_IL rc = %d\n", rc); + goto out; + } + chip->usb_max_current_ma = 100; + } + /* specific current values */ + if (current_ma == CURRENT_150_MA) { + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + CFG_USB_2_3_SEL_BIT, CFG_USB_3); + if (rc < 0) { + pr_err("Couldn't set CHGPTH_CFG rc = %d\n", rc); + goto out; + } + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT | USB51_MODE_BIT, + USBIN_LIMITED_MODE | USB51_100MA); + if (rc < 0) { + pr_err("Couldn't set CMD_IL rc = %d\n", rc); + goto out; + } + chip->usb_max_current_ma = 150; + } + if (current_ma == CURRENT_500_MA) { + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + CFG_USB_2_3_SEL_BIT, CFG_USB_2); + if (rc < 0) { + pr_err("Couldn't set CHGPTH_CFG rc = %d\n", rc); + goto out; + } + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT | USB51_MODE_BIT, + USBIN_LIMITED_MODE | USB51_500MA); + if (rc < 0) { + pr_err("Couldn't set CMD_IL rc = %d\n", rc); + goto out; + } + chip->usb_max_current_ma = 500; + } + if (current_ma == CURRENT_900_MA) { + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + CFG_USB_2_3_SEL_BIT, CFG_USB_3); + if (rc < 0) { + pr_err("Couldn't set CHGPTH_CFG rc = %d\n", rc); + goto out; + } + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + CMD_IL, + USBIN_MODE_CHG_BIT | USB51_MODE_BIT, + USBIN_LIMITED_MODE | USB51_500MA); + if (rc < 0) { + pr_err("Couldn't set CMD_IL rc = %d\n", rc); + goto out; + } + chip->usb_max_current_ma = 900; + } + break; + case POWER_SUPPLY_TYPE_USB_CDP: + if (current_ma < CURRENT_1500_MA) { + /* use override for CDP */ + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + CMD_IL, + ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT); + if (rc < 0) + pr_err("Couldn't set override rc = %d\n", rc); + } + /* fall through */ + default: + rc = smbchg_set_high_usb_chg_current(chip, current_ma); + if (rc < 0) + pr_err("Couldn't set %dmA rc = %d\n", current_ma, rc); + break; + } + +out: + pr_smb(PR_STATUS, "usb type = %d current set to %d mA\n", + chip->usb_supply_type, chip->usb_max_current_ma); + return rc; +} + +#define USBIN_HVDCP_STS 0x0C +#define USBIN_HVDCP_SEL_BIT BIT(4) +#define USBIN_HVDCP_SEL_9V_BIT BIT(1) +#define SCHG_LITE_USBIN_HVDCP_SEL_9V_BIT BIT(2) +#define SCHG_LITE_USBIN_HVDCP_SEL_BIT BIT(0) +static int smbchg_get_min_parallel_current_ma(struct smbchg_chip *chip) +{ + int rc; + u8 reg, hvdcp_sel, hvdcp_sel_9v; + + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + USBIN_HVDCP_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb status rc = %d\n", rc); + return 0; + } + if (chip->schg_version == QPNP_SCHG_LITE) { + hvdcp_sel = SCHG_LITE_USBIN_HVDCP_SEL_BIT; + hvdcp_sel_9v = SCHG_LITE_USBIN_HVDCP_SEL_9V_BIT; + } else { + hvdcp_sel = USBIN_HVDCP_SEL_BIT; + hvdcp_sel_9v = USBIN_HVDCP_SEL_9V_BIT; + } + + if ((reg & hvdcp_sel) && (reg & hvdcp_sel_9v)) + return chip->parallel.min_9v_current_thr_ma; + return chip->parallel.min_current_thr_ma; +} + +static bool is_hvdcp_present(struct smbchg_chip *chip) +{ + int rc; + u8 reg, hvdcp_sel; + + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + USBIN_HVDCP_STS, 1); + if (rc < 0) { + pr_err("Couldn't read hvdcp status rc = %d\n", rc); + return false; + } + + pr_smb(PR_STATUS, "HVDCP_STS = 0x%02x\n", reg); + /* + * If a valid HVDCP is detected, notify it to the usb_psy only + * if USB is still present. + */ + if (chip->schg_version == QPNP_SCHG_LITE) + hvdcp_sel = SCHG_LITE_USBIN_HVDCP_SEL_BIT; + else + hvdcp_sel = USBIN_HVDCP_SEL_BIT; + + if ((reg & hvdcp_sel) && is_usb_present(chip)) + return true; + + return false; +} + +#define FCC_CFG 0xF2 +#define FCC_500MA_VAL 0x4 +#define FCC_MASK SMB_MASK(4, 0) +static int smbchg_set_fastchg_current_raw(struct smbchg_chip *chip, + int current_ma) +{ + int i, rc; + u8 cur_val; + + /* the fcc enumerations are the same as the usb currents */ + i = find_smaller_in_array(chip->tables.usb_ilim_ma_table, + current_ma, chip->tables.usb_ilim_ma_len); + if (i < 0) { + dev_err(chip->dev, + "Cannot find %dma current_table using %d\n", + current_ma, CURRENT_500_MA); + + rc = smbchg_sec_masked_write(chip, chip->chgr_base + FCC_CFG, + FCC_MASK, + FCC_500MA_VAL); + if (rc < 0) + dev_err(chip->dev, "Couldn't set %dmA rc=%d\n", + CURRENT_500_MA, rc); + else + chip->fastchg_current_ma = 500; + return rc; + } + + if (chip->tables.usb_ilim_ma_table[i] == chip->fastchg_current_ma) { + pr_smb(PR_STATUS, "skipping fastchg current request: %d\n", + chip->fastchg_current_ma); + return 0; + } + + cur_val = i & FCC_MASK; + rc = smbchg_sec_masked_write(chip, chip->chgr_base + FCC_CFG, + FCC_MASK, cur_val); + if (rc < 0) { + dev_err(chip->dev, "cannot write to fcc cfg rc = %d\n", rc); + return rc; + } + pr_smb(PR_STATUS, "fastcharge current requested %d, set to %d\n", + current_ma, chip->tables.usb_ilim_ma_table[cur_val]); + + chip->fastchg_current_ma = chip->tables.usb_ilim_ma_table[cur_val]; + return rc; +} + +#define ICL_STS_1_REG 0x7 +#define ICL_STS_2_REG 0x9 +#define ICL_STS_MASK 0x1F +#define AICL_SUSP_BIT BIT(6) +#define AICL_STS_BIT BIT(5) +#define USBIN_SUSPEND_STS_BIT BIT(3) +#define USBIN_ACTIVE_PWR_SRC_BIT BIT(1) +#define DCIN_ACTIVE_PWR_SRC_BIT BIT(0) +#define PARALLEL_REENABLE_TIMER_MS 1000 +#define PARALLEL_CHG_THRESHOLD_CURRENT 1800 +static bool smbchg_is_usbin_active_pwr_src(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + ICL_STS_2_REG, 1); + if (rc < 0) { + dev_err(chip->dev, "Could not read usb icl sts 2: %d\n", rc); + return false; + } + + return !(reg & USBIN_SUSPEND_STS_BIT) + && (reg & USBIN_ACTIVE_PWR_SRC_BIT); +} + +static void smbchg_detect_parallel_charger(struct smbchg_chip *chip) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + + if (parallel_psy) + chip->parallel_charger_detected = + power_supply_set_present(parallel_psy, true) ? + false : true; +} + +static int smbchg_parallel_usb_charging_en(struct smbchg_chip *chip, bool en) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + union power_supply_propval pval = {0, }; + + if (!parallel_psy || !chip->parallel_charger_detected) + return 0; + + pval.intval = en; + return parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_CHARGING_ENABLED, &pval); +} + +#define ESR_PULSE_CURRENT_DELTA_MA 200 +static int smbchg_sw_esr_pulse_en(struct smbchg_chip *chip, bool en) +{ + int rc, fg_current_now, icl_ma; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CURRENT_NOW, + &fg_current_now); + if (rc) { + pr_smb(PR_STATUS, "bms psy does not support OCV\n"); + return 0; + } + + fg_current_now = abs(fg_current_now) / 1000; + icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA, + fg_current_now - ESR_PULSE_CURRENT_DELTA_MA); + rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma); + if (rc < 0) { + pr_err("Couldn't Vote FCC en = %d rc = %d\n", en, rc); + return rc; + } + rc = smbchg_parallel_usb_charging_en(chip, !en); + return rc; +} + +#define USB_AICL_CFG 0xF3 +#define AICL_EN_BIT BIT(2) +static void smbchg_rerun_aicl(struct smbchg_chip *chip) +{ + pr_smb(PR_STATUS, "Rerunning AICL...\n"); + smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, 0); + /* Add a delay so that AICL successfully clears */ + msleep(50); + smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, AICL_EN_BIT); +} + +static void taper_irq_en(struct smbchg_chip *chip, bool en) +{ + mutex_lock(&chip->taper_irq_lock); + if (en != chip->taper_irq_enabled) { + if (en) { + enable_irq(chip->taper_irq); + enable_irq_wake(chip->taper_irq); + } else { + disable_irq_wake(chip->taper_irq); + disable_irq_nosync(chip->taper_irq); + } + chip->taper_irq_enabled = en; + } + mutex_unlock(&chip->taper_irq_lock); +} + +static int smbchg_get_aicl_level_ma(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + ICL_STS_1_REG, 1); + if (rc < 0) { + dev_err(chip->dev, "Could not read usb icl sts 1: %d\n", rc); + return 0; + } + if (reg & AICL_SUSP_BIT) { + pr_warn("AICL suspended: %02x\n", reg); + return 0; + } + reg &= ICL_STS_MASK; + if (reg >= chip->tables.usb_ilim_ma_len) { + pr_warn("invalid AICL value: %02x\n", reg); + return 0; + } + return chip->tables.usb_ilim_ma_table[reg]; +} + +static int smbchg_run_parallel_aicl(struct smbchg_chip *chip) +{ + int rc, aicl_ma, fcc_ma, icl_ma; + union power_supply_propval pval = {0, }; + struct power_supply *parallel_psy = get_parallel_psy(chip); + + if (!parallel_psy) { + pr_err("parallel charger not found\n"); + return 0; + } + + rc = power_supply_set_present(parallel_psy, true); + if (rc) { + pr_err("Unable to set_present for parallel_psy rc=%d\n", rc); + return rc; + } + + rc = power_supply_set_voltage_limit(parallel_psy, chip->vfloat_mv); + if (rc) { + pr_err("Unable to set vfloat for parallel_psy rc=%d\n", + rc); + return rc; + } + + /* Enable slave AICL */ + pval.intval = 1; + rc = parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_ENABLE_AICL, &pval); + if (rc) { + pr_err("Unable to enable AICL on parallel_psy rc=%d\n", rc); + return rc; + } + + /* Set max allowable FCC to slave */ + fcc_ma = get_effective_result_locked(chip->fcc_votable); + pval.intval = fcc_ma * 1000; + rc = parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); + if (rc) { + pr_err("Unable to set FCC for parallel_psy rc=%d\n", + rc); + goto restore_icl; + } + + /* Get max allowable ICL */ + icl_ma = get_effective_result_locked(chip->usb_icl_votable); + + /* + * Force main charger to draw 100mA as the minimal input current + * but don't suspend it to keep the slave charger online. + * Set effective ICL value to slave charger to use it detecting + * adapter's real capability. The 100mA draw in main charger path + * will be added on slave's ICL status. + */ + vote(chip->usb_icl_votable, PARALLEL_ICL_VOTER, true, CURRENT_100_MA); + + rc = power_supply_set_current_limit(parallel_psy, icl_ma * 1000); + if (rc) { + pr_err("Unable to set ICL for parallel_psy rc=%d\n", rc); + goto restore_icl; + } + + rc = parallel_psy->get_property(parallel_psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, &pval); + if (rc) { + pr_err("Unable to read AICL from parallel_psy rc=%d\n", rc); + goto restore_icl; + } + + aicl_ma = pval.intval / 1000; + + if (aicl_ma == 0) { + pr_err("Parallel_psy ICL status is 0mA\n"); + goto restore_icl; + } + + chip->parallel.parallel_aicl_ma = min(icl_ma, CURRENT_100_MA + aicl_ma); + pr_smb(PR_STATUS, "parallel AICL = %d mA\n", + chip->parallel.parallel_aicl_ma); + +restore_icl: + /* Disable slave AICL */ + pval.intval = 0; + rc = parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_ENABLE_AICL, &pval); + if (rc) + pr_err("Unable to disable AICL on parallel_psy rc=%d\n", rc); + + /* Suspend slave and set back last ICL value for main charger */ + pval.intval = 1; + rc = parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval); + if (rc) + pr_err("Unable to suspend-input to parallel_psy rc=%d\n", rc); + + vote(chip->usb_icl_votable, PARALLEL_ICL_VOTER, false, 0); + + return rc; +} + +static void smbchg_parallel_usb_disable(struct smbchg_chip *chip) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + int fcc_ma, usb_icl_ma; + + if (!parallel_psy || !chip->parallel_charger_detected) + return; + pr_smb(PR_STATUS, "disabling parallel charger\n"); + chip->parallel.last_disabled = ktime_get_boottime(); + taper_irq_en(chip, false); + chip->parallel.initial_aicl_ma = 0; + chip->parallel.current_max_ma = 0; + chip->parallel.parallel_aicl_ma = 0; + power_supply_set_current_limit(parallel_psy, + SUSPEND_CURRENT_MA * 1000); + power_supply_set_present(parallel_psy, false); + + fcc_ma = get_effective_result_locked(chip->fcc_votable); + usb_icl_ma = get_effective_result_locked(chip->usb_icl_votable); + if (fcc_ma < 0) + pr_err("no voters for fcc, skip it\n"); + else + smbchg_set_fastchg_current_raw(chip, fcc_ma); + + if (usb_icl_ma < 0) + pr_err("no voters for usb_icl, skip it\n"); + else + smbchg_set_usb_current_max(chip, usb_icl_ma); + + smbchg_rerun_aicl(chip); +} + +#define PARALLEL_TAPER_MAX_TRIES 3 +#define PARALLEL_FCC_PERCENT_REDUCTION 75 +#define MINIMUM_PARALLEL_FCC_MA 500 +#define CHG_ERROR_BIT BIT(0) +#define BAT_TAPER_MODE_BIT BIT(6) +static void smbchg_parallel_usb_taper(struct smbchg_chip *chip) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + union power_supply_propval pval = {0, }; + int parallel_fcc_ma, tries = 0; + u8 reg = 0; + + smbchg_detect_parallel_charger(chip); + if (!parallel_psy || !chip->parallel_charger_detected) + return; + + smbchg_stay_awake(chip, PM_PARALLEL_TAPER); +try_again: + mutex_lock(&chip->parallel.lock); + if (chip->parallel.current_max_ma == 0) { + pr_smb(PR_STATUS, "Not parallel charging, skipping\n"); + goto done; + } + parallel_psy->get_property(parallel_psy, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); + tries += 1; + parallel_fcc_ma = pval.intval / 1000; + pr_smb(PR_STATUS, "try #%d parallel charger fcc = %d\n", + tries, parallel_fcc_ma); + if (parallel_fcc_ma < MINIMUM_PARALLEL_FCC_MA + || tries > PARALLEL_TAPER_MAX_TRIES) { + smbchg_parallel_usb_disable(chip); + goto done; + } + pval.intval = ((parallel_fcc_ma + * PARALLEL_FCC_PERCENT_REDUCTION) / 100); + pr_smb(PR_STATUS, "reducing FCC of parallel charger to %d\n", + pval.intval); + /* Change it to uA */ + pval.intval *= 1000; + parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); + /* + * sleep here for 100 ms in order to make sure the charger has a chance + * to go back into constant current charging + */ + mutex_unlock(&chip->parallel.lock); + msleep(100); + + mutex_lock(&chip->parallel.lock); + if (chip->parallel.current_max_ma == 0) { + pr_smb(PR_STATUS, "Not parallel charging, skipping\n"); + goto done; + } + smbchg_read(chip, ®, chip->chgr_base + RT_STS, 1); + if (reg & BAT_TAPER_MODE_BIT) { + mutex_unlock(&chip->parallel.lock); + goto try_again; + } + taper_irq_en(chip, true); +done: + mutex_unlock(&chip->parallel.lock); + smbchg_relax(chip, PM_PARALLEL_TAPER); +} + +static void smbchg_parallel_usb_enable(struct smbchg_chip *chip, + int total_current_ma) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + union power_supply_propval pval = {0, }; + int new_parallel_cl_ma, set_parallel_cl_ma, new_pmi_cl_ma, rc; + int current_table_index, target_icl_ma, pmi_icl_ma; + int fcc_ma, main_fastchg_current_ma; + int target_parallel_fcc_ma, supplied_parallel_fcc_ma; + int parallel_chg_fcc_percent; + + if (!parallel_psy || !chip->parallel_charger_detected) + return; + + pr_smb(PR_STATUS, "Attempting to enable parallel charger\n"); + + rc = power_supply_set_voltage_limit(parallel_psy, chip->vfloat_mv + 50); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set Vflt on parallel psy rc: %d\n", rc); + return; + } + /* Set USB ICL */ + target_icl_ma = get_effective_result_locked(chip->usb_icl_votable); + if (target_icl_ma < 0) { + pr_err("no voters for usb_icl, skip it\n"); + return; + } + + pmi_icl_ma = total_current_ma * smbchg_main_chg_icl_percent / 100; + pmi_icl_ma = max(chip->parallel.min_main_icl_ma, pmi_icl_ma); + new_parallel_cl_ma = total_current_ma - pmi_icl_ma; + + taper_irq_en(chip, true); + power_supply_set_present(parallel_psy, true); + power_supply_set_current_limit(parallel_psy, + new_parallel_cl_ma * 1000); + /* read back the real amount of current we are getting */ + parallel_psy->get_property(parallel_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, &pval); + set_parallel_cl_ma = pval.intval / 1000; + chip->parallel.current_max_ma = new_parallel_cl_ma; + pr_smb(PR_MISC, "Requested ICL = %d from parallel, got %d\n", + new_parallel_cl_ma, set_parallel_cl_ma); + new_pmi_cl_ma = max(0, target_icl_ma - set_parallel_cl_ma); + pr_smb(PR_STATUS, "New Total USB current = %d[%d, %d]\n", + total_current_ma, new_pmi_cl_ma, + set_parallel_cl_ma); + smbchg_set_usb_current_max(chip, new_pmi_cl_ma); + + /* begin splitting the fast charge current */ + fcc_ma = get_effective_result_locked(chip->fcc_votable); + if (fcc_ma < 0) { + pr_err("no voters for fcc, skip it\n"); + return; + } + parallel_chg_fcc_percent = 100 - smbchg_main_chg_fcc_percent; + target_parallel_fcc_ma = (fcc_ma * parallel_chg_fcc_percent) / 100; + pval.intval = target_parallel_fcc_ma * 1000; + parallel_psy->set_property(parallel_psy, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); + /* check how much actual current is supplied by the parallel charger */ + parallel_psy->get_property(parallel_psy, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval); + supplied_parallel_fcc_ma = pval.intval / 1000; + pr_smb(PR_MISC, "Requested FCC = %d from parallel, got %d\n", + target_parallel_fcc_ma, supplied_parallel_fcc_ma); + + /* then for the main charger, use the left over FCC */ + current_table_index = find_smaller_in_array( + chip->tables.usb_ilim_ma_table, + fcc_ma - supplied_parallel_fcc_ma, + chip->tables.usb_ilim_ma_len); + main_fastchg_current_ma = + chip->tables.usb_ilim_ma_table[current_table_index]; + smbchg_set_fastchg_current_raw(chip, main_fastchg_current_ma); + pr_smb(PR_STATUS, "FCC = %d[%d, %d]\n", fcc_ma, main_fastchg_current_ma, + supplied_parallel_fcc_ma); + + chip->parallel.enabled_once = true; + + return; +} + +static bool smbchg_is_parallel_usb_ok(struct smbchg_chip *chip, + int *ret_total_current_ma) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + union power_supply_propval pval = {0, }; + int min_current_thr_ma, rc, type; + int total_current_ma, current_limit_ma, parallel_cl_ma; + ktime_t kt_since_last_disable; + u8 reg; + int fcc_ma = get_effective_result_locked(chip->fcc_votable); + int usb_icl_ma = get_effective_result_locked(chip->usb_icl_votable); + const char *fcc_voter = get_effective_client_locked(chip->fcc_votable); + + if (!parallel_psy || !smbchg_parallel_en + || !chip->parallel_charger_detected) { + pr_smb(PR_STATUS, "Parallel charging not enabled\n"); + return false; + } + + if (fcc_ma < 0) { + pr_err("no voters for fcc! Can't enable parallel\n"); + return false; + } + if (usb_icl_ma < 0) { + pr_err("no voters for usb_icl, Can't enable parallel\n"); + return false; + } + + kt_since_last_disable = ktime_sub(ktime_get_boottime(), + chip->parallel.last_disabled); + if (chip->parallel.current_max_ma == 0 + && chip->parallel.enabled_once + && ktime_to_ms(kt_since_last_disable) + < PARALLEL_REENABLE_TIMER_MS) { + pr_smb(PR_STATUS, "Only been %lld since disable, skipping\n", + ktime_to_ms(kt_since_last_disable)); + return false; + } + + /* + * If the battery is not present, try not to change parallel charging + * from OFF to ON or from ON to OFF, as it could cause the device to + * brown out in the instant that the USB settings are changed. + * + * Only allow parallel charging check to report false (thereby turnin + * off parallel charging) if the battery is still there, or if parallel + * charging is disabled in the first place. + */ + if (get_prop_charge_type(chip) != POWER_SUPPLY_CHARGE_TYPE_FAST + && (get_prop_batt_present(chip) + || chip->parallel.current_max_ma == 0)) { + pr_smb(PR_STATUS, "Not in fast charge, skipping\n"); + return false; + } + + if (get_prop_batt_health(chip) != POWER_SUPPLY_HEALTH_GOOD) { + pr_smb(PR_STATUS, "JEITA active, skipping\n"); + return false; + } + + rc = smbchg_read(chip, ®, chip->misc_base + IDEV_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read status 5 rc = %d\n", rc); + return false; + } + + type = get_type(reg); + if (get_usb_supply_type(type) == POWER_SUPPLY_TYPE_USB_CDP) { + pr_smb(PR_STATUS, "CDP adapter, skipping\n"); + return false; + } + + if (get_usb_supply_type(type) == POWER_SUPPLY_TYPE_USB) { + pr_smb(PR_STATUS, "SDP adapter, skipping\n"); + return false; + } + + /* + * If USBIN is suspended or not the active power source, do not enable + * parallel charging. The device may be charging off of DCIN. + */ + if (!smbchg_is_usbin_active_pwr_src(chip)) { + pr_smb(PR_STATUS, "USB not active power source: %02x\n", reg); + return false; + } + + min_current_thr_ma = smbchg_get_min_parallel_current_ma(chip); + if (min_current_thr_ma <= 0) { + pr_smb(PR_STATUS, "parallel charger unavailable for thr: %d\n", + min_current_thr_ma); + return false; + } + + if (usb_icl_ma < min_current_thr_ma) { + pr_smb(PR_STATUS, "Weak USB chg skip enable: %d < %d\n", + usb_icl_ma, min_current_thr_ma); + return false; + } + + /* + * Suspend the parallel charger if the charging current is < 1800 mA + * and is not because of an ESR pulse. + */ + if ((!fcc_voter || strcmp(fcc_voter, ESR_PULSE_FCC_VOTER) != 0) + && fcc_ma < PARALLEL_CHG_THRESHOLD_CURRENT) { + pr_smb(PR_STATUS, "FCC %d lower than %d\n", + fcc_ma, + PARALLEL_CHG_THRESHOLD_CURRENT); + return false; + } + + current_limit_ma = smbchg_get_aicl_level_ma(chip); + if (current_limit_ma <= 0) + return false; + + if (chip->parallel.initial_aicl_ma == 0) { + if (current_limit_ma < min_current_thr_ma) { + pr_smb(PR_STATUS, "Initial AICL very low: %d < %d\n", + current_limit_ma, min_current_thr_ma); + return false; + } + chip->parallel.initial_aicl_ma = current_limit_ma; + } + + parallel_psy->get_property(parallel_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, &pval); + parallel_cl_ma = pval.intval / 1000; + /* + * Read back the real amount of current we are getting + * Treat 2mA as 0 because that is the suspend current setting + */ + if (parallel_cl_ma <= SUSPEND_CURRENT_MA) + parallel_cl_ma = 0; + + if (chip->parallel.use_parallel_aicl) { + rc = smbchg_run_parallel_aicl(chip); + if (rc) { + pr_err("Failed to run parallel AICL rc=%d\n", rc); + return false; + } + total_current_ma = chip->parallel.parallel_aicl_ma; + pr_smb(PR_STATUS, "use parallel AICL result: %dmA\n", + total_current_ma); + *ret_total_current_ma = total_current_ma; + + return true; + } + /* + * Set the parallel charge path's input current limit (ICL) + * to the total current / 2 + */ + total_current_ma = min(current_limit_ma + parallel_cl_ma, usb_icl_ma); + + if (total_current_ma < chip->parallel.initial_aicl_ma + - chip->parallel.allowed_lowering_ma) { + pr_smb(PR_STATUS, + "Total current reduced a lot: %d (%d + %d) < %d - %d\n", + total_current_ma, + current_limit_ma, parallel_cl_ma, + chip->parallel.initial_aicl_ma, + chip->parallel.allowed_lowering_ma); + return false; + } + + *ret_total_current_ma = total_current_ma; + return true; +} + +#define HVDCP_DETECTION_DONE_MS 5000 +#define PARALLEL_CHARGER_EN_DELAY_MS 500 +static void smbchg_parallel_usb_en_work(struct work_struct *work) +{ + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + parallel_en_work.work); + int previous_aicl_ma, total_current_ma, aicl_ma; + bool in_progress; + int rc, tries = 3; + + pr_smb(PR_MISC, "started\n"); + chip->parallel.parallel_en_in_progress = true; + /* + * If use-parallel-aicl is enabled, we run parallel AICL to detect + * the total input current from the adapter which could be split and + * allotted to main and slave chargers. Running parallel AICL would + * cost ~2 seconds which is the same delay for hvdcp detection. This + * would cause the concurrence of parallel charging checking and + * hvdcp detection. + * The concurrence would result a mess on the parallel charger settings + * because both logics manipulate ICL setting as well as the parallel + * enabling/disabling. + * Wait here before parallel charging logic running, until hvdcp/ + * hvdcp3 detection logic has finished/confirmed the charger type + * detection, to provide a stable ICL value for parallel charging + * splitting logic. + */ + if (chip->parallel.use_parallel_aicl) { + while (tries--) { + rc = wait_for_completion_interruptible_timeout( + &chip->hvdcp_det_done, + msecs_to_jiffies(HVDCP_DETECTION_DONE_MS)); + if (rc >= 0) { + pr_smb(PR_STATUS, "hvdcp detection done\n"); + break; + } + pr_smb(PR_STATUS, "wait hvdcp_det_done interrupted\n"); + } + } + + /* do a check to see if the aicl is stable */ + previous_aicl_ma = smbchg_get_aicl_level_ma(chip); + msleep(PARALLEL_CHARGER_EN_DELAY_MS); + aicl_ma = smbchg_get_aicl_level_ma(chip); + if (previous_aicl_ma == aicl_ma) { + pr_smb(PR_STATUS, "AICL at %d\n", aicl_ma); + } else { + pr_smb(PR_STATUS, + "AICL changed [%d -> %d], recheck %d ms\n", + previous_aicl_ma, aicl_ma, + PARALLEL_CHARGER_EN_DELAY_MS); + goto recheck; + } + + mutex_lock(&chip->parallel.lock); + in_progress = (chip->parallel.current_max_ma != 0); + if (smbchg_is_parallel_usb_ok(chip, &total_current_ma)) { + smbchg_parallel_usb_enable(chip, total_current_ma); + } else { + if (in_progress) { + pr_smb(PR_STATUS, "parallel charging unavailable\n"); + smbchg_parallel_usb_disable(chip); + } + } + mutex_unlock(&chip->parallel.lock); + pr_smb(PR_STATUS, "Parallel check complete!\n"); + + chip->parallel.parallel_en_in_progress = false; + smbchg_relax(chip, PM_PARALLEL_CHECK); + return; + +recheck: + chip->parallel.parallel_en_in_progress = false; + schedule_delayed_work(&chip->parallel_en_work, 0); +} + +static void smbchg_parallel_usb_check_ok(struct smbchg_chip *chip) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + + if (!parallel_psy || !chip->parallel_charger_detected) + return; + + if (chip->parallel.parallel_en_in_progress) { + pr_smb(PR_MISC, "parallel logic run in progress, ignore\n"); + return; + } + + smbchg_stay_awake(chip, PM_PARALLEL_CHECK); + schedule_delayed_work(&chip->parallel_en_work, 0); +} + +static int charging_suspend_vote_cb(struct votable *votable, void *data, + int suspend, + const char *client) +{ + int rc; + struct smbchg_chip *chip = data; + + if (suspend < 0) { + pr_err("No voters\n"); + suspend = false; + } + + rc = smbchg_charging_en(chip, !suspend); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't configure batt chg: 0x%x rc = %d\n", + !suspend, rc); + } + + return rc; +} + +static int usb_suspend_vote_cb(struct votable *votable, + void *data, + int suspend, + const char *client) +{ + int rc; + struct smbchg_chip *chip = data; + + if (suspend < 0) { + pr_err("No voters\n"); + suspend = false; + } + + rc = smbchg_usb_suspend(chip, suspend); + if (rc < 0) + return rc; + + if ((strcmp(client, THERMAL_EN_VOTER) == 0) + || (strcmp(client, POWER_SUPPLY_EN_VOTER) == 0) + || (strcmp(client, USER_EN_VOTER) == 0) + || (strcmp(client, FAKE_BATTERY_EN_VOTER) == 0)) + smbchg_parallel_usb_check_ok(chip); + + return rc; +} + +static int dc_suspend_vote_cb(struct votable *votable, + void *data, + int suspend, + const char *client) +{ + int rc; + struct smbchg_chip *chip = data; + + if (suspend < 0) { + pr_err("No voters\n"); + suspend = false; + } + + rc = smbchg_dc_suspend(chip, suspend); + if (rc < 0) + return rc; + + if (chip->dc_psy_type != -EINVAL && chip->psy_registered) + power_supply_changed(&chip->dc_psy); + + return rc; +} + +#define HVDCP_EN_BIT BIT(3) +static int smbchg_hvdcp_enable_cb(struct votable *votable, + void *data, + int enable, + const char *client) +{ + int rc = 0; + struct smbchg_chip *chip = data; + + pr_err("smbchg_hvdcp_enable_cb enable %d\n", enable); + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_EN_BIT, enable ? HVDCP_EN_BIT : 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't %s HVDCP rc=%d\n", + enable ? "enable" : "disable", rc); + + return rc; +} + +static int set_fastchg_current_vote_cb(struct votable *votable, + void *data, + int fcc_ma, + const char *client) +{ + struct smbchg_chip *chip = data; + int rc; + + if (fcc_ma < 0) { + pr_err("No voters\n"); + return 0; + } + + if (chip->parallel.current_max_ma == 0) { + rc = smbchg_set_fastchg_current_raw(chip, fcc_ma); + if (rc < 0) { + pr_err("Can't set FCC fcc_ma=%d rc=%d\n", fcc_ma, rc); + return rc; + } + } + /* + * check if parallel charging can be enabled, and if enabled, + * distribute the fcc + */ + smbchg_parallel_usb_check_ok(chip); + return 0; +} + +static int smbchg_set_fastchg_current_user(struct smbchg_chip *chip, + int current_ma) +{ + int rc = 0; + + pr_smb(PR_STATUS, "User setting FCC to %d\n", current_ma); + + rc = vote(chip->fcc_votable, BATT_TYPE_FCC_VOTER, true, current_ma); + if (rc < 0) + pr_err("Couldn't vote en rc %d\n", rc); + return rc; +} + +static struct ilim_entry *smbchg_wipower_find_entry(struct smbchg_chip *chip, + struct ilim_map *map, int uv) +{ + int i; + struct ilim_entry *ret = &(chip->wipower_default.entries[0]); + + for (i = 0; i < map->num; i++) { + if (is_between(map->entries[i].vmin_uv, map->entries[i].vmax_uv, + uv)) + ret = &map->entries[i]; + } + return ret; +} + +#define ZIN_ICL_PT 0xFC +#define ZIN_ICL_LV 0xFD +#define ZIN_ICL_HV 0xFE +#define ZIN_ICL_MASK SMB_MASK(4, 0) +static int smbchg_dcin_ilim_config(struct smbchg_chip *chip, int offset, int ma) +{ + int i, rc; + + i = find_smaller_in_array(chip->tables.dc_ilim_ma_table, + ma, chip->tables.dc_ilim_ma_len); + + if (i < 0) + i = 0; + + rc = smbchg_sec_masked_write(chip, chip->bat_if_base + offset, + ZIN_ICL_MASK, i); + if (rc) + dev_err(chip->dev, "Couldn't write bat if offset %d value = %d rc = %d\n", + offset, i, rc); + return rc; +} + +static int smbchg_wipower_ilim_config(struct smbchg_chip *chip, + struct ilim_entry *ilim) +{ + int rc = 0; + + if (chip->current_ilim.icl_pt_ma != ilim->icl_pt_ma) { + rc = smbchg_dcin_ilim_config(chip, ZIN_ICL_PT, ilim->icl_pt_ma); + if (rc) + dev_err(chip->dev, "failed to write batif offset %d %dma rc = %d\n", + ZIN_ICL_PT, ilim->icl_pt_ma, rc); + else + chip->current_ilim.icl_pt_ma = ilim->icl_pt_ma; + } + + if (chip->current_ilim.icl_lv_ma != ilim->icl_lv_ma) { + rc = smbchg_dcin_ilim_config(chip, ZIN_ICL_LV, ilim->icl_lv_ma); + if (rc) + dev_err(chip->dev, "failed to write batif offset %d %dma rc = %d\n", + ZIN_ICL_LV, ilim->icl_lv_ma, rc); + else + chip->current_ilim.icl_lv_ma = ilim->icl_lv_ma; + } + + if (chip->current_ilim.icl_hv_ma != ilim->icl_hv_ma) { + rc = smbchg_dcin_ilim_config(chip, ZIN_ICL_HV, ilim->icl_hv_ma); + if (rc) + dev_err(chip->dev, "failed to write batif offset %d %dma rc = %d\n", + ZIN_ICL_HV, ilim->icl_hv_ma, rc); + else + chip->current_ilim.icl_hv_ma = ilim->icl_hv_ma; + } + return rc; +} + +static void btm_notify_dcin(enum qpnp_tm_state state, void *ctx); +static int smbchg_wipower_dcin_btm_configure(struct smbchg_chip *chip, + struct ilim_entry *ilim) +{ + int rc; + + if (ilim->vmin_uv == chip->current_ilim.vmin_uv + && ilim->vmax_uv == chip->current_ilim.vmax_uv) + return 0; + + chip->param.channel = DCIN; + chip->param.btm_ctx = chip; + if (wipower_dcin_interval < ADC_MEAS1_INTERVAL_0MS) + wipower_dcin_interval = ADC_MEAS1_INTERVAL_0MS; + + if (wipower_dcin_interval > ADC_MEAS1_INTERVAL_16S) + wipower_dcin_interval = ADC_MEAS1_INTERVAL_16S; + + chip->param.timer_interval = wipower_dcin_interval; + chip->param.threshold_notification = &btm_notify_dcin; + chip->param.high_thr = ilim->vmax_uv + wipower_dcin_hyst_uv; + chip->param.low_thr = ilim->vmin_uv - wipower_dcin_hyst_uv; + chip->param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE; + rc = qpnp_vadc_channel_monitor(chip->vadc_dev, &chip->param); + if (rc) { + dev_err(chip->dev, "Couldn't configure btm for dcin rc = %d\n", + rc); + } else { + chip->current_ilim.vmin_uv = ilim->vmin_uv; + chip->current_ilim.vmax_uv = ilim->vmax_uv; + pr_smb(PR_STATUS, "btm ilim = (%duV %duV %dmA %dmA %dmA)\n", + ilim->vmin_uv, ilim->vmax_uv, + ilim->icl_pt_ma, ilim->icl_lv_ma, ilim->icl_hv_ma); + } + return rc; +} + +static int smbchg_wipower_icl_configure(struct smbchg_chip *chip, + int dcin_uv, bool div2) +{ + int rc = 0; + struct ilim_map *map = div2 ? &chip->wipower_div2 : &chip->wipower_pt; + struct ilim_entry *ilim = smbchg_wipower_find_entry(chip, map, dcin_uv); + + rc = smbchg_wipower_ilim_config(chip, ilim); + if (rc) { + dev_err(chip->dev, "failed to config ilim rc = %d, dcin_uv = %d , div2 = %d, ilim = (%duV %duV %dmA %dmA %dmA)\n", + rc, dcin_uv, div2, + ilim->vmin_uv, ilim->vmax_uv, + ilim->icl_pt_ma, ilim->icl_lv_ma, ilim->icl_hv_ma); + return rc; + } + + rc = smbchg_wipower_dcin_btm_configure(chip, ilim); + if (rc) { + dev_err(chip->dev, "failed to config btm rc = %d, dcin_uv = %d , div2 = %d, ilim = (%duV %duV %dmA %dmA %dmA)\n", + rc, dcin_uv, div2, + ilim->vmin_uv, ilim->vmax_uv, + ilim->icl_pt_ma, ilim->icl_lv_ma, ilim->icl_hv_ma); + return rc; + } + chip->wipower_configured = true; + return 0; +} + +static void smbchg_wipower_icl_deconfigure(struct smbchg_chip *chip) +{ + int rc; + struct ilim_entry *ilim = &(chip->wipower_default.entries[0]); + + if (!chip->wipower_configured) + return; + + rc = smbchg_wipower_ilim_config(chip, ilim); + if (rc) + dev_err(chip->dev, "Couldn't config default ilim rc = %d\n", + rc); + + rc = qpnp_vadc_end_channel_monitor(chip->vadc_dev); + if (rc) + dev_err(chip->dev, "Couldn't de configure btm for dcin rc = %d\n", + rc); + + chip->wipower_configured = false; + chip->current_ilim.vmin_uv = 0; + chip->current_ilim.vmax_uv = 0; + chip->current_ilim.icl_pt_ma = ilim->icl_pt_ma; + chip->current_ilim.icl_lv_ma = ilim->icl_lv_ma; + chip->current_ilim.icl_hv_ma = ilim->icl_hv_ma; + pr_smb(PR_WIPOWER, "De config btm\n"); +} + +#define FV_STS 0x0C +#define DIV2_ACTIVE BIT(7) +static void __smbchg_wipower_check(struct smbchg_chip *chip) +{ + int chg_type; + bool usb_present, dc_present; + int rc; + int dcin_uv; + bool div2; + struct qpnp_vadc_result adc_result; + u8 reg; + + if (!wipower_dyn_icl_en) { + smbchg_wipower_icl_deconfigure(chip); + return; + } + + chg_type = get_prop_charge_type(chip); + usb_present = is_usb_present(chip); + dc_present = is_dc_present(chip); + if (chg_type != POWER_SUPPLY_CHARGE_TYPE_NONE + && !usb_present + && dc_present + && chip->dc_psy_type == POWER_SUPPLY_TYPE_WIPOWER) { + rc = qpnp_vadc_read(chip->vadc_dev, DCIN, &adc_result); + if (rc) { + pr_smb(PR_STATUS, "error DCIN read rc = %d\n", rc); + return; + } + dcin_uv = adc_result.physical; + + /* check div_by_2 */ + rc = smbchg_read(chip, ®, chip->chgr_base + FV_STS, 1); + if (rc) { + pr_smb(PR_STATUS, "error DCIN read rc = %d\n", rc); + return; + } + div2 = !!(reg & DIV2_ACTIVE); + + pr_smb(PR_WIPOWER, + "config ICL chg_type = %d usb = %d dc = %d dcin_uv(adc_code) = %d (0x%x) div2 = %d\n", + chg_type, usb_present, dc_present, dcin_uv, + adc_result.adc_code, div2); + smbchg_wipower_icl_configure(chip, dcin_uv, div2); + } else { + pr_smb(PR_WIPOWER, + "deconfig ICL chg_type = %d usb = %d dc = %d\n", + chg_type, usb_present, dc_present); + smbchg_wipower_icl_deconfigure(chip); + } +} + +static void smbchg_wipower_check(struct smbchg_chip *chip) +{ + if (!chip->wipower_dyn_icl_avail) + return; + + mutex_lock(&chip->wipower_config); + __smbchg_wipower_check(chip); + mutex_unlock(&chip->wipower_config); +} + +static void btm_notify_dcin(enum qpnp_tm_state state, void *ctx) +{ + struct smbchg_chip *chip = ctx; + + mutex_lock(&chip->wipower_config); + pr_smb(PR_WIPOWER, "%s state\n", + state == ADC_TM_LOW_STATE ? "low" : "high"); + chip->current_ilim.vmin_uv = 0; + chip->current_ilim.vmax_uv = 0; + __smbchg_wipower_check(chip); + mutex_unlock(&chip->wipower_config); +} + +static int force_dcin_icl_write(void *data, u64 val) +{ + struct smbchg_chip *chip = data; + + smbchg_wipower_check(chip); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(force_dcin_icl_ops, NULL, + force_dcin_icl_write, "0x%02llx\n"); + +/* + * set the dc charge path's maximum allowed current draw + * that may be limited by the system's thermal level + */ +static int set_dc_current_limit_vote_cb(struct votable *votable, + void *data, + int icl_ma, + const char *client) +{ + struct smbchg_chip *chip = data; + + if (icl_ma < 0) { + pr_err("No voters\n"); + return 0; + } + + return smbchg_set_dc_current_max(chip, icl_ma); +} + +/* + * set the usb charge path's maximum allowed current draw + * that may be limited by the system's thermal level + */ +static int set_usb_current_limit_vote_cb(struct votable *votable, + void *data, + int icl_ma, + const char *client) +{ + struct smbchg_chip *chip = data; + int rc, aicl_ma; + const char *effective_client; + + if (icl_ma < 0) { + pr_err("No voters\n"); + return 0; + } + + effective_client = get_effective_client_locked(chip->usb_icl_votable); + + /* disable parallel charging if HVDCP is voting for 300mA */ + if (effective_client && strcmp(effective_client, HVDCP_ICL_VOTER) == 0) + smbchg_parallel_usb_disable(chip); + + if (chip->parallel.current_max_ma == 0) { + rc = smbchg_set_usb_current_max(chip, icl_ma); + if (rc) { + pr_err("Failed to set usb current max: %d\n", rc); + return rc; + } + } + + /* skip the aicl rerun if hvdcp icl voter or parallel voter is active */ + if (effective_client && (!strcmp(effective_client, HVDCP_ICL_VOTER) || + !strcmp(effective_client, PARALLEL_ICL_VOTER))) + return 0; + + aicl_ma = smbchg_get_aicl_level_ma(chip); + pr_err("[SMBCHG]aicl_ma=%d\n", aicl_ma); + if (icl_ma > aicl_ma) + smbchg_rerun_aicl(chip); + + smbchg_parallel_usb_check_ok(chip); + + return 0; +} + +static int smbchg_system_temp_level_set(struct smbchg_chip *chip, + int lvl_sel) +{ + int rc = 0; + int prev_therm_lvl; + int thermal_icl_ma; + unsigned int hvdcp_thermal_mitigation[7] = {2500, 2500, 1500, 1000, 1000, 500, 0}; + if (!chip->thermal_mitigation) { + dev_err(chip->dev, "Thermal mitigation not supported\n"); + return -EINVAL; + } + + if (lvl_sel < 0) { + dev_err(chip->dev, "Unsupported level selected %d\n", lvl_sel); + return -EINVAL; + } + + if (lvl_sel >= chip->thermal_levels) { + dev_err(chip->dev, "Unsupported level selected %d forcing %d\n", + lvl_sel, chip->thermal_levels - 1); + lvl_sel = chip->thermal_levels - 1; + } + + if (lvl_sel == chip->therm_lvl_sel) + return 0; + + mutex_lock(&chip->therm_lvl_lock); + prev_therm_lvl = chip->therm_lvl_sel; + chip->therm_lvl_sel = lvl_sel; + if (chip->therm_lvl_sel == (chip->thermal_levels - 1)) { + /* + * Disable charging if highest value selected by + * setting the DC and USB path in suspend + */ + rc = vote(chip->dc_suspend_votable, THERMAL_EN_VOTER, true, 0); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set dc suspend rc %d\n", rc); + goto out; + } + rc = vote(chip->usb_suspend_votable, THERMAL_EN_VOTER, true, 0); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set usb suspend rc %d\n", rc); + goto out; + } + goto out; + } + + if (chip->therm_lvl_sel == 0) { + rc = vote(chip->usb_icl_votable, THERMAL_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't disable USB thermal ICL vote rc=%d\n", + rc); + + rc = vote(chip->dc_icl_votable, THERMAL_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't disable DC thermal ICL vote rc=%d\n", + rc); + } else { + if (hvdcp_type == POWER_SUPPLY_TYPE_USB_HVDCP || hvdcp_type == POWER_SUPPLY_TYPE_USB_HVDCP_3){ + thermal_icl_ma = + (int)hvdcp_thermal_mitigation[chip->therm_lvl_sel]; + } else{ + thermal_icl_ma = + (int)chip->thermal_mitigation[chip->therm_lvl_sel]; + } + rc = vote(chip->usb_icl_votable, THERMAL_ICL_VOTER, true, + thermal_icl_ma); + if (rc < 0) + pr_err("Couldn't vote for USB thermal ICL rc=%d\n", rc); + + rc = vote(chip->dc_icl_votable, THERMAL_ICL_VOTER, true, + thermal_icl_ma); + if (rc < 0) + pr_err("Couldn't vote for DC thermal ICL rc=%d\n", rc); + } + + if (prev_therm_lvl == chip->thermal_levels - 1) { + /* + * If previously highest value was selected charging must have + * been disabed. Enable charging by taking the DC and USB path + * out of suspend. + */ + rc = vote(chip->dc_suspend_votable, THERMAL_EN_VOTER, false, 0); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set dc suspend rc %d\n", rc); + goto out; + } + rc = vote(chip->usb_suspend_votable, THERMAL_EN_VOTER, + false, 0); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set usb suspend rc %d\n", rc); + goto out; + } + } +out: + mutex_unlock(&chip->therm_lvl_lock); + return rc; +} + +static int smbchg_ibat_ocp_threshold_ua = 4500000; +module_param(smbchg_ibat_ocp_threshold_ua, int, 0644); + +#define UCONV 1000000LL +#define MCONV 1000LL +#define FLASH_V_THRESHOLD 3000000 +#define FLASH_VDIP_MARGIN 100000 +#define VPH_FLASH_VDIP (FLASH_V_THRESHOLD + FLASH_VDIP_MARGIN) +#define BUCK_EFFICIENCY 800LL +static int smbchg_calc_max_flash_current(struct smbchg_chip *chip) +{ + int ocv_uv, esr_uohm, rbatt_uohm, ibat_now, rc; + int64_t ibat_flash_ua, avail_flash_ua, avail_flash_power_fw; + int64_t ibat_safe_ua, vin_flash_uv, vph_flash_uv; + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv); + if (rc) { + pr_smb(PR_STATUS, "bms psy does not support OCV\n"); + return 0; + } + + rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE, + &esr_uohm); + if (rc) { + pr_smb(PR_STATUS, "bms psy does not support resistance\n"); + return 0; + } + + rc = msm_bcl_read(BCL_PARAM_CURRENT, &ibat_now); + if (rc) { + pr_smb(PR_STATUS, "BCL current read failed: %d\n", rc); + return 0; + } + + rbatt_uohm = esr_uohm + chip->rpara_uohm + chip->rslow_uohm; + /* + * Calculate the maximum current that can pulled out of the battery + * before the battery voltage dips below a safe threshold. + */ + ibat_safe_ua = div_s64((ocv_uv - VPH_FLASH_VDIP) * UCONV, + rbatt_uohm); + + if (ibat_safe_ua <= smbchg_ibat_ocp_threshold_ua) { + /* + * If the calculated current is below the OCP threshold, then + * use it as the possible flash current. + */ + ibat_flash_ua = ibat_safe_ua - ibat_now; + vph_flash_uv = VPH_FLASH_VDIP; + } else { + /* + * If the calculated current is above the OCP threshold, then + * use the ocp threshold instead. + * + * Any higher current will be tripping the battery OCP. + */ + ibat_flash_ua = smbchg_ibat_ocp_threshold_ua - ibat_now; + vph_flash_uv = ocv_uv - div64_s64((int64_t)rbatt_uohm + * smbchg_ibat_ocp_threshold_ua, UCONV); + } + /* Calculate the input voltage of the flash module. */ + vin_flash_uv = max((chip->vled_max_uv + 500000LL), + div64_s64((vph_flash_uv * 1200), 1000)); + /* Calculate the available power for the flash module. */ + avail_flash_power_fw = BUCK_EFFICIENCY * vph_flash_uv * ibat_flash_ua; + /* + * Calculate the available amount of current the flash module can draw + * before collapsing the battery. (available power/ flash input voltage) + */ + avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV); + pr_smb(PR_MISC, + "avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d\n", + avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm); + return (int)avail_flash_ua; +} + +#define FCC_CMP_CFG 0xF3 +#define FCC_COMP_MASK SMB_MASK(1, 0) +static int smbchg_fastchg_current_comp_set(struct smbchg_chip *chip, + int comp_current) +{ + int rc; + u8 i; + + for (i = 0; i < chip->tables.fcc_comp_len; i++) + if (comp_current == chip->tables.fcc_comp_table[i]) + break; + + if (i >= chip->tables.fcc_comp_len) + return -EINVAL; + + rc = smbchg_sec_masked_write(chip, chip->chgr_base + FCC_CMP_CFG, + FCC_COMP_MASK, i); + + if (rc) + dev_err(chip->dev, "Couldn't set fastchg current comp rc = %d\n", + rc); + + return rc; +} + +#define CFG_TCC_REG 0xF9 +#define CHG_ITERM_MASK SMB_MASK(2, 0) +static int smbchg_iterm_set(struct smbchg_chip *chip, int iterm_ma) +{ + int rc; + u8 reg; + + reg = find_closest_in_array( + chip->tables.iterm_ma_table, + chip->tables.iterm_ma_len, + iterm_ma); + + rc = smbchg_sec_masked_write(chip, + chip->chgr_base + CFG_TCC_REG, + CHG_ITERM_MASK, reg); + if (rc) { + dev_err(chip->dev, + "Couldn't set iterm rc = %d\n", rc); + return rc; + } + pr_smb(PR_STATUS, "set tcc (%d) to 0x%02x\n", + iterm_ma, reg); + chip->iterm_ma = iterm_ma; + + return 0; +} + +#define FV_CMP_CFG 0xF5 +#define FV_COMP_MASK SMB_MASK(5, 0) +static int smbchg_float_voltage_comp_set(struct smbchg_chip *chip, int code) +{ + int rc; + u8 val; + + val = code & FV_COMP_MASK; + rc = smbchg_sec_masked_write(chip, chip->chgr_base + FV_CMP_CFG, + FV_COMP_MASK, val); + + if (rc) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", + rc); + + return rc; +} + +#define VFLOAT_CFG_REG 0xF4 +#define MIN_FLOAT_MV 3600 +#define MAX_FLOAT_MV 4500 +#define VFLOAT_MASK SMB_MASK(5, 0) + +#define MID_RANGE_FLOAT_MV_MIN 3600 +#define MID_RANGE_FLOAT_MIN_VAL 0x05 +#define MID_RANGE_FLOAT_STEP_MV 20 + +#define HIGH_RANGE_FLOAT_MIN_MV 4340 +#define HIGH_RANGE_FLOAT_MIN_VAL 0x2A +#define HIGH_RANGE_FLOAT_STEP_MV 10 + +#define VHIGH_RANGE_FLOAT_MIN_MV 4360 +#define VHIGH_RANGE_FLOAT_MIN_VAL 0x2C +#define VHIGH_RANGE_FLOAT_STEP_MV 20 +static int smbchg_float_voltage_set(struct smbchg_chip *chip, int vfloat_mv) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + int rc, delta; + u8 temp; + + if ((vfloat_mv < MIN_FLOAT_MV) || (vfloat_mv > MAX_FLOAT_MV)) { + dev_err(chip->dev, "bad float voltage mv =%d asked to set\n", + vfloat_mv); + return -EINVAL; + } + + if (vfloat_mv <= HIGH_RANGE_FLOAT_MIN_MV) { + /* mid range */ + delta = vfloat_mv - MID_RANGE_FLOAT_MV_MIN; + temp = MID_RANGE_FLOAT_MIN_VAL + delta + / MID_RANGE_FLOAT_STEP_MV; + vfloat_mv -= delta % MID_RANGE_FLOAT_STEP_MV; + } else if (vfloat_mv <= VHIGH_RANGE_FLOAT_MIN_MV) { + /* high range */ + delta = vfloat_mv - HIGH_RANGE_FLOAT_MIN_MV; + temp = HIGH_RANGE_FLOAT_MIN_VAL + delta + / HIGH_RANGE_FLOAT_STEP_MV; + vfloat_mv -= delta % HIGH_RANGE_FLOAT_STEP_MV; + } else { + /* very high range */ + delta = vfloat_mv - VHIGH_RANGE_FLOAT_MIN_MV; + temp = VHIGH_RANGE_FLOAT_MIN_VAL + delta + / VHIGH_RANGE_FLOAT_STEP_MV; + vfloat_mv -= delta % VHIGH_RANGE_FLOAT_STEP_MV; + } + + if (parallel_psy) { + rc = power_supply_set_voltage_limit(parallel_psy, + vfloat_mv + 50); + if (rc) + dev_err(chip->dev, "Couldn't set float voltage on parallel psy rc: %d\n", + rc); + } + + rc = smbchg_sec_masked_write(chip, chip->chgr_base + VFLOAT_CFG_REG, + VFLOAT_MASK, temp); + + if (rc) + dev_err(chip->dev, "Couldn't set float voltage rc = %d\n", rc); + else + chip->vfloat_mv = vfloat_mv; + + return rc; +} + +static int smbchg_float_voltage_get(struct smbchg_chip *chip) +{ + return chip->vfloat_mv; +} + +#define SFT_CFG 0xFD +#define SFT_EN_MASK SMB_MASK(5, 4) +#define SFT_TO_MASK SMB_MASK(3, 2) +#define PRECHG_SFT_TO_MASK SMB_MASK(1, 0) +#define SFT_TIMER_DISABLE_BIT BIT(5) +#define PRECHG_SFT_TIMER_DISABLE_BIT BIT(4) +#define SAFETY_TIME_MINUTES_SHIFT 2 +static int smbchg_safety_timer_enable(struct smbchg_chip *chip, bool enable) +{ + int rc; + u8 reg; + + if (enable == chip->safety_timer_en) + return 0; + + if (enable) + reg = 0; + else + reg = SFT_TIMER_DISABLE_BIT | PRECHG_SFT_TIMER_DISABLE_BIT; + + rc = smbchg_sec_masked_write(chip, chip->chgr_base + SFT_CFG, + SFT_EN_MASK, reg); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't %s safety timer rc = %d\n", + enable ? "enable" : "disable", rc); + return rc; + } + chip->safety_timer_en = enable; + return 0; +} + +enum skip_reason { + REASON_OTG_ENABLED = BIT(0), + REASON_FLASH_ENABLED = BIT(1) +}; + +#define BAT_IF_TRIM7_REG 0xF7 +#define CFG_750KHZ_BIT BIT(1) +#define MISC_CFG_NTC_VOUT_REG 0xF3 +#define CFG_NTC_VOUT_FSW_BIT BIT(0) +static int smbchg_switch_buck_frequency(struct smbchg_chip *chip, + bool flash_active) +{ + int rc; + + if (!(chip->wa_flags & SMBCHG_FLASH_BUCK_SWITCH_FREQ_WA)) + return 0; + + if (chip->flash_active == flash_active) { + pr_smb(PR_STATUS, "Fsw not changed, flash_active: %d\n", + flash_active); + return 0; + } + + /* + * As per the systems team recommendation, before the flash fires, + * buck switching frequency(Fsw) needs to be increased to 1MHz. Once the + * flash is disabled, Fsw needs to be set back to 750KHz. + */ + rc = smbchg_sec_masked_write(chip, chip->misc_base + + MISC_CFG_NTC_VOUT_REG, CFG_NTC_VOUT_FSW_BIT, + flash_active ? CFG_NTC_VOUT_FSW_BIT : 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set switching frequency multiplier rc=%d\n", + rc); + return rc; + } + + rc = smbchg_sec_masked_write(chip, chip->bat_if_base + BAT_IF_TRIM7_REG, + CFG_750KHZ_BIT, flash_active ? 0 : CFG_750KHZ_BIT); + if (rc < 0) { + dev_err(chip->dev, "Cannot set switching freq: %d\n", rc); + return rc; + } + + pr_smb(PR_STATUS, "Fsw @ %sHz\n", flash_active ? "1M" : "750K"); + chip->flash_active = flash_active; + return 0; +} + +#define OTG_TRIM6 0xF6 +#define TR_ENB_SKIP_BIT BIT(2) +#define OTG_EN_BIT BIT(0) +static int smbchg_otg_pulse_skip_disable(struct smbchg_chip *chip, + enum skip_reason reason, bool disable) +{ + int rc; + bool disabled; + + disabled = !!chip->otg_pulse_skip_dis; + pr_smb(PR_STATUS, "%s pulse skip, reason %d\n", + disable ? "disabling" : "enabling", reason); + if (disable) + chip->otg_pulse_skip_dis |= reason; + else + chip->otg_pulse_skip_dis &= ~reason; + if (disabled == !!chip->otg_pulse_skip_dis) + return 0; + disabled = !!chip->otg_pulse_skip_dis; + + rc = smbchg_sec_masked_write(chip, chip->otg_base + OTG_TRIM6, + TR_ENB_SKIP_BIT, disabled ? TR_ENB_SKIP_BIT : 0); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't %s otg pulse skip rc = %d\n", + disabled ? "disable" : "enable", rc); + return rc; + } + pr_smb(PR_STATUS, "%s pulse skip\n", disabled ? "disabled" : "enabled"); + return 0; +} + +#define ICL_BUF_CONFIG_REG 0xFC +#define ICL_BUF_CFG_BIT BIT(2) +#define ICL_BUF_SS_DONE_VAL 0 +#define ICL_BUF_SYSON_LDO_VAL BIT(2) +static int smbchg_configure_icl_buffer(struct smbchg_chip *chip, u8 val) +{ + int rc; + + if ((val != ICL_BUF_SS_DONE_VAL) && (val != ICL_BUF_SYSON_LDO_VAL)) { + pr_err("Invalid val 0x%02x\n", val); + return -EINVAL; + } + + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + ICL_BUF_CONFIG_REG, + ICL_BUF_CFG_BIT, val); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't write 0x%02x to icl buf ctrl rc = %d\n", + val, rc); + return rc; + } + return 0; +} + +static int configure_icl_control(struct smbchg_chip *chip, u8 val) +{ + if (!(chip->wa_flags & SMBCHG_ICL_CONTROL_WA)) + return 0; + + return smbchg_configure_icl_buffer(chip, val); +} + +#define LOW_PWR_OPTIONS_REG 0xFF +#define FORCE_TLIM_BIT BIT(4) +static int smbchg_force_tlim_en(struct smbchg_chip *chip, bool enable) +{ + int rc; + + rc = smbchg_sec_masked_write(chip, chip->otg_base + LOW_PWR_OPTIONS_REG, + FORCE_TLIM_BIT, enable ? FORCE_TLIM_BIT : 0); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't %s otg force tlim rc = %d\n", + enable ? "enable" : "disable", rc); + return rc; + } + return rc; +} + +static void smbchg_vfloat_adjust_check(struct smbchg_chip *chip) +{ + if (!chip->use_vfloat_adjustments) + return; + + smbchg_stay_awake(chip, PM_REASON_VFLOAT_ADJUST); + pr_smb(PR_STATUS, "Starting vfloat adjustments\n"); + schedule_delayed_work(&chip->vfloat_adjust_work, 0); +} + +#define FV_STS_REG 0xC +#define AICL_INPUT_STS_BIT BIT(6) +static bool smbchg_is_input_current_limited(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->chgr_base + FV_STS_REG, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read FV_STS rc=%d\n", rc); + return false; + } + + return !!(reg & AICL_INPUT_STS_BIT); +} + +#define SW_ESR_PULSE_MS 1500 +static void smbchg_cc_esr_wa_check(struct smbchg_chip *chip) +{ + int rc, esr_count; + + if (!(chip->wa_flags & SMBCHG_CC_ESR_WA)) + return; + + if (!is_usb_present(chip) && !is_dc_present(chip)) { + pr_smb(PR_STATUS, "No inputs present, skipping\n"); + return; + } + + if (get_prop_charge_type(chip) != POWER_SUPPLY_CHARGE_TYPE_FAST) { + pr_smb(PR_STATUS, "Not in fast charge, skipping\n"); + return; + } + + if (!smbchg_is_input_current_limited(chip)) { + pr_smb(PR_STATUS, "Not input current limited, skipping\n"); + return; + } + + set_property_on_fg(chip, POWER_SUPPLY_PROP_UPDATE_NOW, 1); + rc = get_property_from_fg(chip, + POWER_SUPPLY_PROP_ESR_COUNT, &esr_count); + if (rc) { + pr_smb(PR_STATUS, + "could not read ESR counter rc = %d\n", rc); + return; + } + + /* + * The esr_count is counting down the number of fuel gauge cycles + * before a ESR pulse is needed. + * + * After a successful ESR pulse, this count is reset to some + * high number like 28. If this reaches 0, then the fuel gauge + * hardware should force a ESR pulse. + * + * However, if the device is in constant current charge mode while + * being input current limited, the ESR pulse will not affect the + * battery current, so the measurement will fail. + * + * As a failsafe, force a manual ESR pulse if this value is read as + * 0. + */ + if (esr_count != 0) { + pr_smb(PR_STATUS, "ESR count is not zero, skipping\n"); + return; + } + + pr_smb(PR_STATUS, "Lowering charge current for ESR pulse\n"); + smbchg_stay_awake(chip, PM_ESR_PULSE); + smbchg_sw_esr_pulse_en(chip, true); + msleep(SW_ESR_PULSE_MS); + pr_smb(PR_STATUS, "Raising charge current for ESR pulse\n"); + smbchg_relax(chip, PM_ESR_PULSE); + smbchg_sw_esr_pulse_en(chip, false); +} + +static void smbchg_soc_changed(struct smbchg_chip *chip) +{ + smbchg_cc_esr_wa_check(chip); +} + +#define DC_AICL_CFG 0xF3 +#define MISC_TRIM_OPT_15_8 0xF5 +#define USB_AICL_DEGLITCH_MASK (BIT(5) | BIT(4) | BIT(3)) +#define USB_AICL_DEGLITCH_SHORT (BIT(5) | BIT(4) | BIT(3)) +#define USB_AICL_DEGLITCH_LONG 0 +#define DC_AICL_DEGLITCH_MASK (BIT(5) | BIT(4) | BIT(3)) +#define DC_AICL_DEGLITCH_SHORT (BIT(5) | BIT(4) | BIT(3)) +#define DC_AICL_DEGLITCH_LONG 0 +#define AICL_RERUN_MASK (BIT(5) | BIT(4)) +#define AICL_RERUN_ON (BIT(5) | BIT(4)) +#define AICL_RERUN_OFF 0 + +static int smbchg_hw_aicl_rerun_enable_indirect_cb(struct votable *votable, + void *data, + int enable, + const char *client) +{ + int rc = 0; + struct smbchg_chip *chip = data; + + if (enable < 0) { + pr_err("No voters\n"); + enable = 0; + } + /* + * If the indirect voting result of all the clients is to enable hw aicl + * rerun, then remove our vote to disable hw aicl rerun + */ + rc = vote(chip->hw_aicl_rerun_disable_votable, + HW_AICL_RERUN_ENABLE_INDIRECT_VOTER, !enable, 0); + if (rc < 0) { + pr_err("Couldn't vote for hw rerun rc= %d\n", rc); + return rc; + } + + return rc; +} + +static int smbchg_hw_aicl_rerun_disable_cb(struct votable *votable, void *data, + int disable, + const char *client) +{ + int rc = 0; + struct smbchg_chip *chip = data; + + if (disable < 0) { + pr_err("No voters\n"); + disable = 0; + } + + rc = smbchg_sec_masked_write(chip, + chip->misc_base + MISC_TRIM_OPT_15_8, + AICL_RERUN_MASK, disable ? AICL_RERUN_OFF : AICL_RERUN_ON); + if (rc < 0) + pr_err("Couldn't write to MISC_TRIM_OPTIONS_15_8 rc=%d\n", rc); + + return rc; +} + +static int smbchg_aicl_deglitch_config_cb(struct votable *votable, void *data, + int shorter, + const char *client) +{ + int rc = 0; + struct smbchg_chip *chip = data; + + if (shorter < 0) { + pr_err("No voters\n"); + shorter = 0; + } + + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USB_AICL_CFG, + USB_AICL_DEGLITCH_MASK, + shorter ? USB_AICL_DEGLITCH_SHORT : USB_AICL_DEGLITCH_LONG); + if (rc < 0) { + pr_err("Couldn't write to USB_AICL_CFG rc=%d\n", rc); + return rc; + } + rc = smbchg_sec_masked_write(chip, + chip->dc_chgpth_base + DC_AICL_CFG, + DC_AICL_DEGLITCH_MASK, + shorter ? DC_AICL_DEGLITCH_SHORT : DC_AICL_DEGLITCH_LONG); + if (rc < 0) { + pr_err("Couldn't write to DC_AICL_CFG rc=%d\n", rc); + return rc; + } + return rc; +} + +static void smbchg_aicl_deglitch_wa_en(struct smbchg_chip *chip, bool en) +{ + int rc; + + rc = vote(chip->aicl_deglitch_short_votable, + VARB_WORKAROUND_VOTER, en, 0); + if (rc < 0) { + pr_err("Couldn't vote %s deglitch rc=%d\n", + en ? "short" : "long", rc); + return; + } + pr_smb(PR_STATUS, "AICL deglitch set to %s\n", en ? "short" : "long"); + + rc = vote(chip->hw_aicl_rerun_enable_indirect_votable, + VARB_WORKAROUND_VOTER, en, 0); + if (rc < 0) { + pr_err("Couldn't vote hw aicl rerun rc= %d\n", rc); + return; + } + chip->aicl_deglitch_short = en; +} + +static void smbchg_aicl_deglitch_wa_check(struct smbchg_chip *chip) +{ + union power_supply_propval prop = {0,}; + int rc; + bool low_volt_chgr = true; + + if (!(chip->wa_flags & SMBCHG_AICL_DEGLITCH_WA)) + return; + + if (!is_usb_present(chip) && !is_dc_present(chip)) { + pr_smb(PR_STATUS, "Charger removed\n"); + smbchg_aicl_deglitch_wa_en(chip, false); + return; + } + + if (!chip->bms_psy) + return; + + if (is_usb_present(chip)) { + if (is_hvdcp_present(chip)) + low_volt_chgr = false; + } else if (is_dc_present(chip)) { + if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIPOWER) + low_volt_chgr = false; + else + low_volt_chgr = chip->low_volt_dcin; + } + + if (!low_volt_chgr) { + pr_smb(PR_STATUS, "High volt charger! Don't set deglitch\n"); + smbchg_aicl_deglitch_wa_en(chip, false); + return; + } + + /* It is possible that battery voltage went high above threshold + * when the charger is inserted and can go low because of system + * load. We shouldn't be reconfiguring AICL deglitch when this + * happens as it will lead to oscillation again which is being + * fixed here. Do it once when the battery voltage crosses the + * threshold (e.g. 4.2 V) and clear it only when the charger + * is removed. + */ + if (!chip->vbat_above_headroom) { + rc = chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_VOLTAGE_MIN, &prop); + if (rc < 0) { + pr_err("could not read voltage_min, rc=%d\n", rc); + return; + } + chip->vbat_above_headroom = !prop.intval; + } + smbchg_aicl_deglitch_wa_en(chip, chip->vbat_above_headroom); +} + +#define MISC_TEST_REG 0xE2 +#define BB_LOOP_DISABLE_ICL BIT(2) +static int smbchg_icl_loop_disable_check(struct smbchg_chip *chip) +{ + bool icl_disabled = !chip->chg_otg_enabled && chip->flash_triggered; + int rc = 0; + + if ((chip->wa_flags & SMBCHG_FLASH_ICL_DISABLE_WA) + && icl_disabled != chip->icl_disabled) { + rc = smbchg_sec_masked_write(chip, + chip->misc_base + MISC_TEST_REG, + BB_LOOP_DISABLE_ICL, + icl_disabled ? BB_LOOP_DISABLE_ICL : 0); + chip->icl_disabled = icl_disabled; + } + + return rc; +} + +#define UNKNOWN_BATT_TYPE "Unknown Battery" +#define LOADING_BATT_TYPE "Loading Battery Data" +static int smbchg_config_chg_battery_type(struct smbchg_chip *chip) +{ + int rc = 0, max_voltage_uv = 0, fastchg_ma = 0, ret = 0, iterm_ua = 0; + struct device_node *batt_node, *profile_node; + struct device_node *node = chip->spmi->dev.of_node; + union power_supply_propval prop = {0,}; + + rc = chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_BATTERY_TYPE, &prop); + if (rc) { + pr_smb(PR_STATUS, "Unable to read battery-type rc=%d\n", rc); + return 0; + } + if (!strcmp(prop.strval, UNKNOWN_BATT_TYPE) || + !strcmp(prop.strval, LOADING_BATT_TYPE)) { + pr_smb(PR_MISC, "Battery-type not identified\n"); + return 0; + } + /* quit if there is no change in the battery-type from previous */ + if (chip->battery_type && !strcmp(prop.strval, chip->battery_type)) + return 0; + + batt_node = of_parse_phandle(node, "qcom,battery-data", 0); + if (!batt_node) { + pr_smb(PR_MISC, "No batterydata available\n"); + return 0; + } + + profile_node = of_batterydata_get_best_profile(batt_node, + "bms", NULL); + if (!profile_node) { + pr_err("couldn't find profile handle\n"); + return -EINVAL; + } + chip->battery_type = prop.strval; + + /* change vfloat */ + rc = of_property_read_u32(profile_node, "qcom,max-voltage-uv", + &max_voltage_uv); + if (rc) { + pr_warn("couldn't find battery max voltage rc=%d\n", rc); + ret = rc; + } else { + if (chip->vfloat_mv != (max_voltage_uv / 1000)) { + pr_info("Vfloat changed from %dmV to %dmV for battery-type %s\n", + chip->vfloat_mv, (max_voltage_uv / 1000), + chip->battery_type); + rc = smbchg_float_voltage_set(chip, + (max_voltage_uv / 1000)); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set float voltage rc = %d\n", rc); + return rc; + } + } + } + + /* change chg term */ + rc = of_property_read_u32(profile_node, "qcom,chg-term-ua", + &iterm_ua); + if (rc && rc != -EINVAL) { + pr_warn("couldn't read battery term current=%d\n", rc); + ret = rc; + } else if (!rc) { + if (chip->iterm_ma != (iterm_ua / 1000) + && !chip->iterm_disabled) { + pr_info("Term current changed from %dmA to %dmA for battery-type %s\n", + chip->iterm_ma, (iterm_ua / 1000), + chip->battery_type); + rc = smbchg_iterm_set(chip, + (iterm_ua / 1000)); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set iterm rc = %d\n", rc); + return rc; + } + } + chip->iterm_ma = iterm_ua / 1000; + } + + /* + * Only configure from profile if fastchg-ma is not defined in the + * charger device node. + */ + if (!of_find_property(chip->spmi->dev.of_node, + "qcom,fastchg-current-ma", NULL)) { + rc = of_property_read_u32(profile_node, + "qcom,fastchg-current-ma", &fastchg_ma); + if (rc) { + ret = rc; + } else { + pr_smb(PR_MISC, + "fastchg-ma changed from to %dma for battery-type %s\n", + fastchg_ma, chip->battery_type); + rc = vote(chip->fcc_votable, BATT_TYPE_FCC_VOTER, true, + fastchg_ma); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't vote for fastchg current rc=%d\n", + rc); + return rc; + } + } + } + + return ret; +} + +#define MAX_INV_BATT_ID 7700 +#define MIN_INV_BATT_ID 7300 +static void check_battery_type(struct smbchg_chip *chip) +{ + union power_supply_propval prop = {0,}; + bool en; + + if (!chip->bms_psy && chip->bms_psy_name) + chip->bms_psy = + power_supply_get_by_name((char *)chip->bms_psy_name); + if (chip->bms_psy) { + chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_BATTERY_TYPE, &prop); + en = (strcmp(prop.strval, UNKNOWN_BATT_TYPE) != 0 + || chip->charge_unknown_battery) + && (strcmp(prop.strval, LOADING_BATT_TYPE) != 0); + vote(chip->battchg_suspend_votable, + BATTCHG_UNKNOWN_BATTERY_EN_VOTER, !en, 0); + + if (!chip->skip_usb_suspend_for_fake_battery) { + chip->bms_psy->get_property(chip->bms_psy, + POWER_SUPPLY_PROP_RESISTANCE_ID, &prop); + /* suspend USB path for invalid battery-id */ + en = (prop.intval <= MAX_INV_BATT_ID && + prop.intval >= MIN_INV_BATT_ID) ? 1 : 0; + vote(chip->usb_suspend_votable, FAKE_BATTERY_EN_VOTER, + en, 0); + } + } +} + +static int smbchg_otg_regulator_enable(struct regulator_dev *rdev) +{ + int rc = 0; + struct smbchg_chip *chip = rdev_get_drvdata(rdev); + + chip->otg_retries = 0; + chip->chg_otg_enabled = true; + rc = configure_icl_control(chip, ICL_BUF_SS_DONE_VAL); + if (rc) { + dev_err(chip->dev, "Couldn't switch to soft start completion, rc=%d\n", + rc); + return rc; + } + smbchg_icl_loop_disable_check(chip); + smbchg_otg_pulse_skip_disable(chip, REASON_OTG_ENABLED, true); + + /* If pin control mode then return from here */ + if (chip->otg_pinctrl) + return rc; + + /* sleep to make sure the pulse skip is actually disabled */ + msleep(20); + rc = smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_REG, + OTG_EN_BIT, OTG_EN_BIT); + if (rc < 0) + dev_err(chip->dev, "Couldn't enable OTG mode rc=%d\n", rc); + else + chip->otg_enable_time = ktime_get(); + pr_smb(PR_STATUS, "Enabling OTG Boost\n"); + return rc; +} + +static int smbchg_otg_regulator_disable(struct regulator_dev *rdev) +{ + int rc = 0; + struct smbchg_chip *chip = rdev_get_drvdata(rdev); + + if (!chip->otg_pinctrl) { + rc = smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_REG, + OTG_EN_BIT, 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't disable OTG mode rc=%d\n", + rc); + } + + chip->chg_otg_enabled = false; + smbchg_otg_pulse_skip_disable(chip, REASON_OTG_ENABLED, false); + smbchg_icl_loop_disable_check(chip); + rc = configure_icl_control(chip, ICL_BUF_SYSON_LDO_VAL); + if (rc) { + dev_err(chip->dev, "Couldn't switch to Syson LDO, rc=%d\n", + rc); + rc = 0; + } + pr_smb(PR_STATUS, "Disabling OTG Boost\n"); + return rc; +} + +static int smbchg_otg_regulator_is_enable(struct regulator_dev *rdev) +{ + int rc = 0; + u8 reg = 0; + struct smbchg_chip *chip = rdev_get_drvdata(rdev); + + rc = smbchg_read(chip, ®, chip->bat_if_base + CMD_CHG_REG, 1); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't read OTG enable bit rc=%d\n", rc); + return rc; + } + + return (reg & OTG_EN_BIT) ? 1 : 0; +} + +struct regulator_ops smbchg_otg_reg_ops = { + .enable = smbchg_otg_regulator_enable, + .disable = smbchg_otg_regulator_disable, + .is_enabled = smbchg_otg_regulator_is_enable, +}; + +#define USBIN_CHGR_CFG 0xF1 +#define ADAPTER_ALLOWANCE_MASK 0x7 +#define USBIN_ADAPTER_9V 0x3 +#define USBIN_ADAPTER_5V_9V_CONT 0x2 +#define USBIN_ADAPTER_5V_UNREGULATED_9V 0x5 +static int smbchg_external_otg_regulator_enable(struct regulator_dev *rdev) +{ + int rc = 0; + struct smbchg_chip *chip = rdev_get_drvdata(rdev); + + rc = vote(chip->usb_suspend_votable, OTG_EN_VOTER, true, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't suspend charger rc=%d\n", rc); + return rc; + } + + rc = smbchg_read(chip, &chip->original_usbin_allowance, + chip->usb_chgpth_base + USBIN_CHGR_CFG, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb allowance rc=%d\n", rc); + return rc; + } + + /* + * To disallow source detect and usbin_uv interrupts, set the adapter + * allowance to 9V, so that the audio boost operating in reverse never + * gets detected as a valid input + */ + rc = vote(chip->hvdcp_enable_votable, HVDCP_OTG_VOTER, true, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't disable HVDCP rc=%d\n", rc); + return rc; + } + + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + 0xFF, USBIN_ADAPTER_9V); + if (rc < 0) { + dev_err(chip->dev, "Couldn't write usb allowance rc=%d\n", rc); + return rc; + } + + pr_smb(PR_STATUS, "Enabling OTG Boost\n"); + return rc; +} + +static int smbchg_external_otg_regulator_disable(struct regulator_dev *rdev) +{ + int rc = 0; + struct smbchg_chip *chip = rdev_get_drvdata(rdev); + + rc = vote(chip->usb_suspend_votable, OTG_EN_VOTER, false, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't unsuspend charger rc=%d\n", rc); + return rc; + } + + /* + * Reenable HVDCP and set the adapter allowance back to the original + * value in order to allow normal USBs to be recognized as a valid + * input. + */ + rc = vote(chip->hvdcp_enable_votable, HVDCP_OTG_VOTER, false, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't enable HVDCP rc=%d\n", rc); + return rc; + } + + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + 0xFF, chip->original_usbin_allowance); + if (rc < 0) { + dev_err(chip->dev, "Couldn't write usb allowance rc=%d\n", rc); + return rc; + } + + pr_smb(PR_STATUS, "Disabling OTG Boost\n"); + return rc; +} + +static int smbchg_external_otg_regulator_is_enable(struct regulator_dev *rdev) +{ + struct smbchg_chip *chip = rdev_get_drvdata(rdev); + + return get_client_vote(chip->usb_suspend_votable, OTG_EN_VOTER); +} + +struct regulator_ops smbchg_external_otg_reg_ops = { + .enable = smbchg_external_otg_regulator_enable, + .disable = smbchg_external_otg_regulator_disable, + .is_enabled = smbchg_external_otg_regulator_is_enable, +}; + +static int smbchg_regulator_init(struct smbchg_chip *chip) +{ + int rc = 0; + struct regulator_init_data *init_data; + struct regulator_config cfg = {}; + struct device_node *regulator_node; + + regulator_node = of_get_child_by_name(chip->dev->of_node, + "qcom,smbcharger-boost-otg"); + + init_data = of_get_regulator_init_data(chip->dev, regulator_node); + if (!init_data) { + dev_err(chip->dev, "Unable to allocate memory\n"); + return -ENOMEM; + } + + if (init_data->constraints.name) { + chip->otg_vreg.rdesc.owner = THIS_MODULE; + chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE; + chip->otg_vreg.rdesc.ops = &smbchg_otg_reg_ops; + chip->otg_vreg.rdesc.name = init_data->constraints.name; + + cfg.dev = chip->dev; + cfg.init_data = init_data; + cfg.driver_data = chip; + cfg.of_node = regulator_node; + + init_data->constraints.valid_ops_mask + |= REGULATOR_CHANGE_STATUS; + + chip->otg_vreg.rdev = devm_regulator_register(chip->dev, + &chip->otg_vreg.rdesc, &cfg); + if (IS_ERR(chip->otg_vreg.rdev)) { + rc = PTR_ERR(chip->otg_vreg.rdev); + chip->otg_vreg.rdev = NULL; + if (rc != -EPROBE_DEFER) + dev_err(chip->dev, + "OTG reg failed, rc=%d\n", rc); + } + } + + if (rc) + return rc; + + regulator_node = of_get_child_by_name(chip->dev->of_node, + "qcom,smbcharger-external-otg"); + if (!regulator_node) { + dev_dbg(chip->dev, "external-otg node absent\n"); + return 0; + } + init_data = of_get_regulator_init_data(chip->dev, regulator_node); + if (!init_data) { + dev_err(chip->dev, "Unable to allocate memory\n"); + return -ENOMEM; + } + + if (init_data->constraints.name) { + if (of_get_property(chip->dev->of_node, + "otg-parent-supply", NULL)) + init_data->supply_regulator = "otg-parent"; + chip->ext_otg_vreg.rdesc.owner = THIS_MODULE; + chip->ext_otg_vreg.rdesc.type = REGULATOR_VOLTAGE; + chip->ext_otg_vreg.rdesc.ops = &smbchg_external_otg_reg_ops; + chip->ext_otg_vreg.rdesc.name = init_data->constraints.name; + + cfg.dev = chip->dev; + cfg.init_data = init_data; + cfg.driver_data = chip; + cfg.of_node = regulator_node; + + init_data->constraints.valid_ops_mask + |= REGULATOR_CHANGE_STATUS; + + chip->ext_otg_vreg.rdev = devm_regulator_register(chip->dev, + &chip->ext_otg_vreg.rdesc, + &cfg); + if (IS_ERR(chip->ext_otg_vreg.rdev)) { + rc = PTR_ERR(chip->ext_otg_vreg.rdev); + chip->ext_otg_vreg.rdev = NULL; + if (rc != -EPROBE_DEFER) + dev_err(chip->dev, + "external OTG reg failed, rc=%d\n", rc); + } + } + + return rc; +} + +#define CMD_CHG_LED_REG 0x43 +#define CHG_LED_CTRL_BIT BIT(0) +#define LED_SW_CTRL_BIT 0x1 +#define LED_CHG_CTRL_BIT 0x0 +#define CHG_LED_ON 0x03 +#define CHG_LED_OFF 0x00 +#define LED_BLINKING_PATTERN1 0x01 +#define LED_BLINKING_PATTERN2 0x02 +#define LED_BLINKING_CFG_MASK SMB_MASK(2, 1) +#define CHG_LED_SHIFT 1 +static int smbchg_chg_led_controls(struct smbchg_chip *chip) +{ + u8 reg, mask; + int rc; + + if (chip->cfg_chg_led_sw_ctrl) { + /* turn-off LED by default for software control */ + mask = CHG_LED_CTRL_BIT | LED_BLINKING_CFG_MASK; + reg = LED_SW_CTRL_BIT; + } else { + mask = CHG_LED_CTRL_BIT; + reg = LED_CHG_CTRL_BIT; + } + + rc = smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_LED_REG, + mask, reg); + if (rc < 0) + dev_err(chip->dev, + "Couldn't write LED_CTRL_BIT rc=%d\n", rc); + return rc; +} + +static void smbchg_chg_led_brightness_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct smbchg_chip *chip = container_of(cdev, + struct smbchg_chip, led_cdev); + u8 reg; + int rc; + + reg = (value > LED_OFF) ? CHG_LED_ON << CHG_LED_SHIFT : + CHG_LED_OFF << CHG_LED_SHIFT; + + if (chip->bms_psy) { + if (value > LED_OFF) + power_supply_set_hi_power_state(chip->bms_psy, 1); + else + power_supply_set_hi_power_state(chip->bms_psy, 0); + } + + pr_smb(PR_STATUS, + "set the charger led brightness to value=%d\n", + value); + rc = smbchg_sec_masked_write(chip, + chip->bat_if_base + CMD_CHG_LED_REG, + LED_BLINKING_CFG_MASK, reg); + if (rc) + dev_err(chip->dev, "Couldn't write CHG_LED rc=%d\n", + rc); +} + +static enum +led_brightness smbchg_chg_led_brightness_get(struct led_classdev *cdev) +{ + struct smbchg_chip *chip = container_of(cdev, + struct smbchg_chip, led_cdev); + u8 reg_val, chg_led_sts; + int rc; + + rc = smbchg_read(chip, ®_val, chip->bat_if_base + CMD_CHG_LED_REG, + 1); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't read CHG_LED_REG sts rc=%d\n", + rc); + return rc; + } + + chg_led_sts = (reg_val & LED_BLINKING_CFG_MASK) >> CHG_LED_SHIFT; + + pr_smb(PR_STATUS, "chg_led_sts = %02x\n", chg_led_sts); + + return (chg_led_sts == CHG_LED_OFF) ? LED_OFF : LED_FULL; +} + +static void smbchg_chg_led_blink_set(struct smbchg_chip *chip, + unsigned long blinking) +{ + u8 reg; + int rc; + + if (chip->bms_psy) { + if (blinking == 0) + power_supply_set_hi_power_state(chip->bms_psy, 0); + else + power_supply_set_hi_power_state(chip->bms_psy, 1); + } + + if (blinking == 0) { + reg = CHG_LED_OFF << CHG_LED_SHIFT; + } else { + if (blinking == 1) + reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; + else if (blinking == 2) + reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT; + else + reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT; + } + + rc = smbchg_sec_masked_write(chip, + chip->bat_if_base + CMD_CHG_LED_REG, + LED_BLINKING_CFG_MASK, reg); + if (rc) + dev_err(chip->dev, "Couldn't write CHG_LED rc=%d\n", + rc); +} + +static ssize_t smbchg_chg_led_blink_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct smbchg_chip *chip = container_of(cdev, struct smbchg_chip, + led_cdev); + unsigned long blinking; + ssize_t rc = -EINVAL; + + rc = kstrtoul(buf, 10, &blinking); + if (rc) + return rc; + + smbchg_chg_led_blink_set(chip, blinking); + + return len; +} + +static DEVICE_ATTR(blink, 0664, NULL, smbchg_chg_led_blink_store); + +static struct attribute *led_blink_attributes[] = { + &dev_attr_blink.attr, + NULL, +}; + +static struct attribute_group smbchg_led_attr_group = { + .attrs = led_blink_attributes +}; + +static int smbchg_register_chg_led(struct smbchg_chip *chip) +{ + int rc; + + chip->led_cdev.name = "red"; + chip->led_cdev.brightness_set = smbchg_chg_led_brightness_set; + chip->led_cdev.brightness_get = smbchg_chg_led_brightness_get; + + rc = led_classdev_register(chip->dev, &chip->led_cdev); + if (rc) { + dev_err(chip->dev, "unable to register charger led, rc=%d\n", + rc); + return rc; + } + + rc = sysfs_create_group(&chip->led_cdev.dev->kobj, + &smbchg_led_attr_group); + if (rc) { + dev_err(chip->dev, "led sysfs rc: %d\n", rc); + return rc; + } + + return rc; +} + +static int vf_adjust_low_threshold = 5; +module_param(vf_adjust_low_threshold, int, 0644); + +static int vf_adjust_high_threshold = 7; +module_param(vf_adjust_high_threshold, int, 0644); + +static int vf_adjust_n_samples = 10; +module_param(vf_adjust_n_samples, int, 0644); + +static int vf_adjust_max_delta_mv = 40; +module_param(vf_adjust_max_delta_mv, int, 0644); + +static int vf_adjust_trim_steps_per_adjust = 1; +module_param(vf_adjust_trim_steps_per_adjust, int, 0644); + +#define CENTER_TRIM_CODE 7 +#define MAX_LIN_CODE 14 +#define MAX_TRIM_CODE 15 +#define SCALE_SHIFT 4 +#define VF_TRIM_OFFSET_MASK SMB_MASK(3, 0) +#define VF_STEP_SIZE_MV 10 +#define SCALE_LSB_MV 17 +static int smbchg_trim_add_steps(int prev_trim, int delta_steps) +{ + int scale_steps; + int linear_offset, linear_scale; + int offset_code = prev_trim & VF_TRIM_OFFSET_MASK; + int scale_code = (prev_trim & ~VF_TRIM_OFFSET_MASK) >> SCALE_SHIFT; + + if (abs(delta_steps) > 1) { + pr_smb(PR_STATUS, + "Cant trim multiple steps delta_steps = %d\n", + delta_steps); + return prev_trim; + } + if (offset_code <= CENTER_TRIM_CODE) + linear_offset = offset_code + CENTER_TRIM_CODE; + else if (offset_code > CENTER_TRIM_CODE) + linear_offset = MAX_TRIM_CODE - offset_code; + + if (scale_code <= CENTER_TRIM_CODE) + linear_scale = scale_code + CENTER_TRIM_CODE; + else if (scale_code > CENTER_TRIM_CODE) + linear_scale = scale_code - (CENTER_TRIM_CODE + 1); + + /* check if we can accomodate delta steps with just the offset */ + if (linear_offset + delta_steps >= 0 + && linear_offset + delta_steps <= MAX_LIN_CODE) { + linear_offset += delta_steps; + + if (linear_offset > CENTER_TRIM_CODE) + offset_code = linear_offset - CENTER_TRIM_CODE; + else + offset_code = MAX_TRIM_CODE - linear_offset; + + return (prev_trim & ~VF_TRIM_OFFSET_MASK) | offset_code; + } + + /* changing offset cannot satisfy delta steps, change the scale bits */ + scale_steps = delta_steps > 0 ? 1 : -1; + + if (linear_scale + scale_steps < 0 + || linear_scale + scale_steps > MAX_LIN_CODE) { + pr_smb(PR_STATUS, + "Cant trim scale_steps = %d delta_steps = %d\n", + scale_steps, delta_steps); + return prev_trim; + } + + linear_scale += scale_steps; + + if (linear_scale > CENTER_TRIM_CODE) + scale_code = linear_scale - CENTER_TRIM_CODE; + else + scale_code = linear_scale + (CENTER_TRIM_CODE + 1); + prev_trim = (prev_trim & VF_TRIM_OFFSET_MASK) + | scale_code << SCALE_SHIFT; + + /* + * now that we have changed scale which is a 17mV jump, change the + * offset bits (10mV) too so the effective change is just 7mV + */ + delta_steps = -1 * delta_steps; + + linear_offset = clamp(linear_offset + delta_steps, 0, MAX_LIN_CODE); + if (linear_offset > CENTER_TRIM_CODE) + offset_code = linear_offset - CENTER_TRIM_CODE; + else + offset_code = MAX_TRIM_CODE - linear_offset; + + return (prev_trim & ~VF_TRIM_OFFSET_MASK) | offset_code; +} + +#define TRIM_14 0xFE +#define VF_TRIM_MASK 0xFF +static int smbchg_adjust_vfloat_mv_trim(struct smbchg_chip *chip, + int delta_mv) +{ + int sign, delta_steps, rc = 0; + u8 prev_trim, new_trim; + int i; + + sign = delta_mv > 0 ? 1 : -1; + delta_steps = (delta_mv + sign * VF_STEP_SIZE_MV / 2) + / VF_STEP_SIZE_MV; + + rc = smbchg_read(chip, &prev_trim, chip->misc_base + TRIM_14, 1); + if (rc) { + dev_err(chip->dev, "Unable to read trim 14: %d\n", rc); + return rc; + } + + for (i = 1; i <= abs(delta_steps) + && i <= vf_adjust_trim_steps_per_adjust; i++) { + new_trim = (u8)smbchg_trim_add_steps(prev_trim, + delta_steps > 0 ? 1 : -1); + if (new_trim == prev_trim) { + pr_smb(PR_STATUS, + "VFloat trim unchanged from %02x\n", prev_trim); + /* treat no trim change as an error */ + return -EINVAL; + } + + rc = smbchg_sec_masked_write(chip, chip->misc_base + TRIM_14, + VF_TRIM_MASK, new_trim); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't change vfloat trim rc=%d\n", rc); + } + pr_smb(PR_STATUS, + "VFlt trim %02x to %02x, delta steps: %d\n", + prev_trim, new_trim, delta_steps); + prev_trim = new_trim; + } + + return rc; +} + +#define SMBCHG_UPDATE_MS 1000 +static void smbchg_cool_limit_work(struct work_struct *work) +{ + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + cool_limit_work.work); + + int temp, rc; + + temp = get_prop_batt_temp(chip); + + if (temp > 0 && temp <= 50){ + mutex_lock(&chip->cool_current); + rc = smbchg_fastchg_current_comp_set(chip, 250); + mutex_unlock(&chip->cool_current); + } + if (temp > 50 && temp < 150){ + mutex_lock(&chip->cool_current); + rc = smbchg_fastchg_current_comp_set(chip, 1200); + mutex_unlock(&chip->cool_current); + } + + schedule_delayed_work(&chip->cool_limit_work, msecs_to_jiffies(SMBCHG_UPDATE_MS)); + +} + +#define VFLOAT_RESAMPLE_DELAY_MS 10000 +static void smbchg_vfloat_adjust_work(struct work_struct *work) +{ + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + vfloat_adjust_work.work); + int vbat_uv, vbat_mv, ibat_ua, rc, delta_vfloat_mv; + bool taper, enable; + + smbchg_stay_awake(chip, PM_REASON_VFLOAT_ADJUST); + taper = (get_prop_charge_type(chip) + == POWER_SUPPLY_CHARGE_TYPE_TAPER); + enable = taper && (chip->parallel.current_max_ma == 0); + + if (!enable) { + pr_smb(PR_MISC, + "Stopping vfloat adj taper=%d parallel_ma = %d\n", + taper, chip->parallel.current_max_ma); + goto stop; + } + + if (get_prop_batt_health(chip) != POWER_SUPPLY_HEALTH_GOOD) { + pr_smb(PR_STATUS, "JEITA active, skipping\n"); + goto stop; + } + + set_property_on_fg(chip, POWER_SUPPLY_PROP_UPDATE_NOW, 1); + rc = get_property_from_fg(chip, + POWER_SUPPLY_PROP_VOLTAGE_NOW, &vbat_uv); + if (rc) { + pr_smb(PR_STATUS, + "bms psy does not support voltage rc = %d\n", rc); + goto stop; + } + vbat_mv = vbat_uv / 1000; + + if ((vbat_mv - chip->vfloat_mv) < -1 * vf_adjust_max_delta_mv) { + pr_smb(PR_STATUS, "Skip vbat out of range: %d\n", vbat_mv); + goto reschedule; + } + + rc = get_property_from_fg(chip, + POWER_SUPPLY_PROP_CURRENT_NOW, &ibat_ua); + if (rc) { + pr_smb(PR_STATUS, + "bms psy does not support current_now rc = %d\n", rc); + goto stop; + } + + if (ibat_ua / 1000 > -chip->iterm_ma) { + pr_smb(PR_STATUS, "Skip ibat too high: %d\n", ibat_ua); + goto reschedule; + } + + pr_smb(PR_STATUS, "sample number = %d vbat_mv = %d ibat_ua = %d\n", + chip->n_vbat_samples, + vbat_mv, + ibat_ua); + + chip->max_vbat_sample = max(chip->max_vbat_sample, vbat_mv); + chip->n_vbat_samples += 1; + if (chip->n_vbat_samples < vf_adjust_n_samples) { + pr_smb(PR_STATUS, "Skip %d samples; max = %d\n", + chip->n_vbat_samples, chip->max_vbat_sample); + goto reschedule; + } + /* if max vbat > target vfloat, delta_vfloat_mv could be negative */ + delta_vfloat_mv = chip->vfloat_mv - chip->max_vbat_sample; + pr_smb(PR_STATUS, "delta_vfloat_mv = %d, samples = %d, mvbat = %d\n", + delta_vfloat_mv, chip->n_vbat_samples, chip->max_vbat_sample); + /* + * enough valid samples has been collected, adjust trim codes + * based on maximum of collected vbat samples if necessary + */ + if (delta_vfloat_mv > vf_adjust_high_threshold + || delta_vfloat_mv < -1 * vf_adjust_low_threshold) { + rc = smbchg_adjust_vfloat_mv_trim(chip, delta_vfloat_mv); + if (rc) { + pr_smb(PR_STATUS, + "Stopping vfloat adj after trim adj rc = %d\n", + rc); + goto stop; + } + chip->max_vbat_sample = 0; + chip->n_vbat_samples = 0; + goto reschedule; + } + +stop: + chip->max_vbat_sample = 0; + chip->n_vbat_samples = 0; + smbchg_relax(chip, PM_REASON_VFLOAT_ADJUST); + return; + +reschedule: + schedule_delayed_work(&chip->vfloat_adjust_work, + msecs_to_jiffies(VFLOAT_RESAMPLE_DELAY_MS)); + return; +} + +static int smbchg_charging_status_change(struct smbchg_chip *chip) +{ + smbchg_vfloat_adjust_check(chip); + set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS, + get_prop_batt_status(chip)); + return 0; +} + +#define BB_CLMP_SEL 0xF8 +#define BB_CLMP_MASK SMB_MASK(1, 0) +#define BB_CLMP_VFIX_3338MV 0x1 +#define BB_CLMP_VFIX_3512MV 0x2 +static int smbchg_set_optimal_charging_mode(struct smbchg_chip *chip, int type) +{ + int rc; + bool hvdcp2 = (type == POWER_SUPPLY_TYPE_USB_HVDCP + && smbchg_is_usbin_active_pwr_src(chip)); + + /* + * Set the charger switching freq to 1MHZ if HVDCP 2.0, + * or 750KHZ otherwise + */ + rc = smbchg_sec_masked_write(chip, + chip->bat_if_base + BAT_IF_TRIM7_REG, + CFG_750KHZ_BIT, hvdcp2 ? 0 : CFG_750KHZ_BIT); + if (rc) { + dev_err(chip->dev, "Cannot set switching freq: %d\n", rc); + return rc; + } + + /* + * Set the charger switch frequency clamp voltage threshold to 3.338V + * if HVDCP 2.0, or 3.512V otherwise. + */ + rc = smbchg_sec_masked_write(chip, chip->bat_if_base + BB_CLMP_SEL, + BB_CLMP_MASK, + hvdcp2 ? BB_CLMP_VFIX_3338MV : BB_CLMP_VFIX_3512MV); + if (rc) { + dev_err(chip->dev, "Cannot set switching freq: %d\n", rc); + return rc; + } + + return 0; +} + +#define DEFAULT_SDP_MA 100 +#define DEFAULT_CDP_MA 1500 +enum power_supply_type hvdcp_flag = 0; +static int smbchg_change_usb_supply_type(struct smbchg_chip *chip, + enum power_supply_type type) +{ + int rc, current_limit_ma; + union power_supply_propval propval; + + /* + * if the type is not unknown, set the type before changing ICL vote + * in order to ensure that the correct current limit registers are + * used + */ + if (type != POWER_SUPPLY_TYPE_UNKNOWN) + chip->usb_supply_type = type; + + /* + * Type-C only supports STD(900), MEDIUM(1500) and HIGH(3000) current + * modes, skip all BC 1.2 current if external typec is supported. + * Note: for SDP supporting current based on USB notifications. + */ + hvdcp_type = type; + if (chip->typec_psy && (type != POWER_SUPPLY_TYPE_USB)) + current_limit_ma = chip->typec_current_ma; + else if (type == POWER_SUPPLY_TYPE_USB) + current_limit_ma = DEFAULT_SDP_MA; + else if (type == POWER_SUPPLY_TYPE_USB) + current_limit_ma = DEFAULT_SDP_MA; + else if (type == POWER_SUPPLY_TYPE_USB_CDP) + current_limit_ma = DEFAULT_CDP_MA; + else if (type == POWER_SUPPLY_TYPE_USB_HVDCP) + current_limit_ma = smbchg_default_hvdcp_icl_ma; + else if (type == POWER_SUPPLY_TYPE_USB_HVDCP_3) + current_limit_ma = smbchg_default_hvdcp3_icl_ma; + else + current_limit_ma = smbchg_default_dcp_icl_ma; + hvdcp_flag = type; + pr_smb(PR_STATUS, "Type %d: setting mA = %d\n", + type, current_limit_ma); + + rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, + current_limit_ma); + if (rc < 0) { + pr_err("Couldn't vote for new USB ICL rc=%d\n", rc); + goto out; + } + + if (!chip->skip_usb_notification) { + propval.intval = type; + chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_REAL_TYPE, + &propval); + } + + /* + * otherwise if it is unknown, remove vote + * and set type after the vote + */ + if (type == POWER_SUPPLY_TYPE_UNKNOWN) { + rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, 0); + if (rc < 0) + pr_err("Couldn't remove ICL vote rc=%d\n", rc); + + chip->usb_supply_type = type; + } + + /* set the correct buck switching frequency */ + rc = smbchg_set_optimal_charging_mode(chip, type); + if (rc < 0) + pr_err("Couldn't set charger optimal mode rc=%d\n", rc); + +out: + return rc; +} + +#define HVDCP_ADAPTER_SEL_MASK SMB_MASK(5, 4) +#define HVDCP_5V 0x00 +#define HVDCP_9V 0x10 +#define USB_CMD_HVDCP_1 0x42 +#define FORCE_HVDCP_2p0 BIT(3) + +static int force_9v_hvdcp(struct smbchg_chip *chip) +{ + int rc; + + /* Force 5V HVDCP */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_5V); + if (rc) { + pr_err("Couldn't set hvdcp config in chgpath_chg rc=%d\n", rc); + return rc; + } + + /* Force QC2.0 */ + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + USB_CMD_HVDCP_1, + FORCE_HVDCP_2p0, FORCE_HVDCP_2p0); + rc |= smbchg_masked_write(chip, + chip->usb_chgpth_base + USB_CMD_HVDCP_1, + FORCE_HVDCP_2p0, 0); + if (rc < 0) { + pr_err("Couldn't force QC2.0 rc=%d\n", rc); + return rc; + } + + /* Delay to switch into HVDCP 2.0 and avoid UV */ + msleep(500); + + /* Force 9V HVDCP */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_9V); + if (rc) + pr_err("Couldn't set hvdcp config in chgpath_chg rc=%d\n", rc); + + return rc; +} + +static void smbchg_hvdcp_det_work(struct work_struct *work) +{ + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + hvdcp_det_work.work); + int rc; + + if (chip->parallel.use_parallel_aicl) { + if (!chip->hvdcp3_supported || !is_hvdcp_present(chip)) { + complete_all(&chip->hvdcp_det_done); + pr_smb(PR_MISC, "hvdcp_det_done complete\n"); + } + } + + if (is_hvdcp_present(chip)) { + if (!chip->hvdcp3_supported && + (chip->wa_flags & SMBCHG_HVDCP_9V_EN_WA)) { + /* force HVDCP 2.0 */ + rc = force_9v_hvdcp(chip); + if (rc) + pr_err("could not force 9V HVDCP continuing rc=%d\n", + rc); + } + smbchg_change_usb_supply_type(chip, + POWER_SUPPLY_TYPE_USB_HVDCP); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_aicl_deglitch_wa_check(chip); + } + smbchg_relax(chip, PM_DETECT_HVDCP); +} + +static int set_usb_psy_dp_dm(struct smbchg_chip *chip, int state) +{ + int rc; + u8 reg; + + /* + * ensure that we are not in the middle of an insertion where usbin_uv + * is low and src_detect hasnt gone high. If so force dp=F dm=F + * which guarantees proper type detection + */ + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1); + if (!rc && !(reg & USBIN_UV_BIT) && !(reg & USBIN_SRC_DET_BIT)) { + pr_smb(PR_MISC, "overwriting state = %d with %d\n", + state, POWER_SUPPLY_DP_DM_DPF_DMF); + state = POWER_SUPPLY_DP_DM_DPF_DMF; + } + pr_smb(PR_MISC, "setting usb psy dp dm = %d\n", state); + return power_supply_set_dp_dm(chip->usb_psy, state); +} + +#define APSD_CFG 0xF5 +#define AUTO_SRC_DETECT_EN_BIT BIT(0) +#define APSD_TIMEOUT_MS 1500 +static void restore_from_hvdcp_detection(struct smbchg_chip *chip) +{ + int rc; + + /* switch to 9V HVDCP */ + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_9V); + if (rc < 0) + pr_err("Couldn't configure HVDCP 9V rc=%d\n", rc); + + /* enable HVDCP */ + rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, false, 1); + if (rc < 0) + pr_err("Couldn't enable HVDCP rc=%d\n", rc); + + /* enable APSD */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + APSD_CFG, + AUTO_SRC_DETECT_EN_BIT, AUTO_SRC_DETECT_EN_BIT); + if (rc < 0) + pr_err("Couldn't enable APSD rc=%d\n", rc); + + /* Reset back to 5V unregulated */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + ADAPTER_ALLOWANCE_MASK, USBIN_ADAPTER_5V_UNREGULATED_9V); + if (rc < 0) + pr_err("Couldn't write usb allowance rc=%d\n", rc); + + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, AICL_EN_BIT); + if (rc < 0) + pr_err("Couldn't enable AICL rc=%d\n", rc); + + chip->hvdcp_3_det_ignore_uv = false; + chip->pulse_cnt = 0; + + if ((chip->schg_version == QPNP_SCHG_LITE) + && is_hvdcp_present(chip)) { + pr_smb(PR_MISC, "Forcing 9V HVDCP 2.0\n"); + rc = force_9v_hvdcp(chip); + if (rc) + pr_err("Failed to force 9V HVDCP=%d\n", rc); + } + + pr_smb(PR_MISC, "Retracting HVDCP vote for ICL\n"); + rc = vote(chip->usb_icl_votable, HVDCP_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); +} + +#define RESTRICTED_CHG_FCC_PERCENT 50 +static int smbchg_restricted_charging(struct smbchg_chip *chip, bool enable) +{ + int current_table_index, fastchg_current; + int rc = 0; + + /* If enable, set the fcc to the set point closest + * to 50% of the configured fcc while remaining below it + */ + current_table_index = find_smaller_in_array( + chip->tables.usb_ilim_ma_table, + chip->cfg_fastchg_current_ma + * RESTRICTED_CHG_FCC_PERCENT / 100, + chip->tables.usb_ilim_ma_len); + fastchg_current = + chip->tables.usb_ilim_ma_table[current_table_index]; + rc = vote(chip->fcc_votable, RESTRICTED_CHG_FCC_VOTER, enable, + fastchg_current); + + pr_smb(PR_STATUS, "restricted_charging set to %d\n", enable); + chip->restricted_charging = enable; + + return rc; +} + +static void handle_usb_removal(struct smbchg_chip *chip) +{ + struct power_supply *parallel_psy = get_parallel_psy(chip); + int rc; + + pr_smb(PR_STATUS, "triggered\n"); + smbchg_aicl_deglitch_wa_check(chip); + /* Clear the OV detected status set before */ + if (chip->usb_ov_det) + chip->usb_ov_det = false; + /* Clear typec current status */ + if (chip->typec_psy) + chip->typec_current_ma = 0; + /* cancel/wait for hvdcp pending work if any */ + cancel_delayed_work_sync(&chip->hvdcp_det_work); + smbchg_relax(chip, PM_DETECT_HVDCP); + smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); + + if (chip->parallel.use_parallel_aicl) { + complete_all(&chip->hvdcp_det_done); + pr_smb(PR_MISC, "complete hvdcp_det_done\n"); + } + + if (!chip->skip_usb_notification) { + pr_smb(PR_MISC, "setting usb psy present = %d\n", + chip->usb_present); + power_supply_set_present(chip->usb_psy, chip->usb_present); + } + set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DPR_DMR); + schedule_work(&chip->usb_set_online_work); + pr_smb(PR_MISC, "setting usb psy health UNKNOWN\n"); + rc = power_supply_set_health_state(chip->usb_psy, + POWER_SUPPLY_HEALTH_UNKNOWN); + if (rc < 0) + pr_smb(PR_STATUS, + "usb psy does not allow updating prop %d rc = %d\n", + POWER_SUPPLY_HEALTH_UNKNOWN, rc); + + if (parallel_psy && chip->parallel_charger_detected) + power_supply_set_present(parallel_psy, false); + if (chip->parallel.avail && chip->aicl_done_irq + && chip->enable_aicl_wake) { + disable_irq_wake(chip->aicl_done_irq); + chip->enable_aicl_wake = false; + } + chip->parallel.enabled_once = false; + chip->vbat_above_headroom = false; + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + ICL_OVERRIDE_BIT, 0); + if (rc < 0) + pr_err("Couldn't set override rc = %d\n", rc); + + vote(chip->usb_icl_votable, WEAK_CHARGER_ICL_VOTER, false, 0); + chip->usb_icl_delta = 0; + vote(chip->usb_icl_votable, SW_AICL_ICL_VOTER, false, 0); + vote(chip->aicl_deglitch_short_votable, + HVDCP_SHORT_DEGLITCH_VOTER, false, 0); + if (!chip->hvdcp_not_supported) + restore_from_hvdcp_detection(chip); +} + +static bool is_usbin_uv_high(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb rt status rc = %d\n", rc); + return false; + } + return reg &= USBIN_UV_BIT; +} + +#define HVDCP_NOTIFY_MS 2500 +static void handle_usb_insertion(struct smbchg_chip *chip) +{ + enum power_supply_type usb_supply_type; + int rc; + char *usb_type_name = "null"; + + pr_smb(PR_STATUS, "triggered\n"); + /* usb inserted */ + read_usb_type(chip, &usb_type_name, &usb_supply_type); + pr_smb(PR_STATUS, + "inserted type = %d (%s)", usb_supply_type, usb_type_name); + + smbchg_aicl_deglitch_wa_check(chip); + if (chip->typec_psy) + update_typec_status(chip); + smbchg_change_usb_supply_type(chip, usb_supply_type); + if (!chip->skip_usb_notification) { + pr_smb(PR_MISC, "setting usb psy present = %d\n", + chip->usb_present); + power_supply_set_present(chip->usb_psy, chip->usb_present); + } + + /* Notify the USB psy if OV condition is not present */ + if (!chip->usb_ov_det) { + /* + * Note that this could still be a very weak charger + * if the handle_usb_insertion was triggered from + * the falling edge of an USBIN_OV interrupt + */ + pr_smb(PR_MISC, "setting usb psy health %s\n", + chip->very_weak_charger + ? "UNSPEC_FAILURE" : "GOOD"); + rc = power_supply_set_health_state(chip->usb_psy, + chip->very_weak_charger + ? POWER_SUPPLY_HEALTH_UNSPEC_FAILURE + : POWER_SUPPLY_HEALTH_GOOD); + if (rc < 0) + pr_smb(PR_STATUS, + "usb psy does not allow updating prop %d rc = %d\n", + POWER_SUPPLY_HEALTH_GOOD, rc); + } + schedule_work(&chip->usb_set_online_work); + + if (!chip->hvdcp_not_supported && + (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP)) { + cancel_delayed_work_sync(&chip->hvdcp_det_work); + smbchg_stay_awake(chip, PM_DETECT_HVDCP); + schedule_delayed_work(&chip->hvdcp_det_work, + msecs_to_jiffies(HVDCP_NOTIFY_MS)); + if (chip->parallel.use_parallel_aicl) { + reinit_completion(&chip->hvdcp_det_done); + pr_smb(PR_MISC, "init hvdcp_det_done\n"); + } + } + + smbchg_detect_parallel_charger(chip); + + if (chip->parallel.avail && chip->aicl_done_irq + && !chip->enable_aicl_wake) { + rc = enable_irq_wake(chip->aicl_done_irq); + chip->enable_aicl_wake = true; + } +} + +void update_usb_status(struct smbchg_chip *chip, bool usb_present, bool force) +{ + mutex_lock(&chip->usb_status_lock); + if (force) { + chip->usb_present = usb_present; + chip->usb_present ? handle_usb_insertion(chip) + : handle_usb_removal(chip); + goto unlock; + } + if (!chip->usb_present && usb_present) { + chip->usb_present = usb_present; + handle_usb_insertion(chip); + } else if (chip->usb_present && !usb_present) { + chip->usb_present = usb_present; + handle_usb_removal(chip); + } + + /* update FG */ + set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS, + get_prop_batt_status(chip)); +unlock: + mutex_unlock(&chip->usb_status_lock); +} + +static int otg_oc_reset(struct smbchg_chip *chip) +{ + int rc; + + rc = smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_REG, + OTG_EN_BIT, 0); + if (rc) + pr_err("Failed to disable OTG rc=%d\n", rc); + + msleep(20); + + /* + * There is a possibility that an USBID interrupt might have + * occurred notifying USB power supply to disable OTG. We + * should not enable OTG in such cases. + */ + if (!is_otg_present(chip)) { + pr_smb(PR_STATUS, + "OTG is not present, not enabling OTG_EN_BIT\n"); + goto out; + } + + rc = smbchg_masked_write(chip, chip->bat_if_base + CMD_CHG_REG, + OTG_EN_BIT, OTG_EN_BIT); + if (rc) + pr_err("Failed to re-enable OTG rc=%d\n", rc); + +out: + return rc; +} + +static int get_current_time(unsigned long *now_tm_sec) +{ + struct rtc_time tm; + struct rtc_device *rtc; + int rc; + + rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); + if (rtc == NULL) { + pr_err("%s: unable to open rtc device (%s)\n", + __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); + return -EINVAL; + } + + rc = rtc_read_time(rtc, &tm); + if (rc) { + pr_err("Error reading rtc device (%s) : %d\n", + CONFIG_RTC_HCTOSYS_DEVICE, rc); + goto close_time; + } + + rc = rtc_valid_tm(&tm); + if (rc) { + pr_err("Invalid RTC time (%s): %d\n", + CONFIG_RTC_HCTOSYS_DEVICE, rc); + goto close_time; + } + rtc_tm_to_time(&tm, now_tm_sec); + +close_time: + rtc_class_close(rtc); + return rc; +} + +#define AICL_IRQ_LIMIT_SECONDS 60 +#define AICL_IRQ_LIMIT_COUNT 25 +static void increment_aicl_count(struct smbchg_chip *chip) +{ + bool bad_charger = false; + int max_aicl_count, rc; + u8 reg; + long elapsed_seconds; + unsigned long now_seconds; + + pr_smb(PR_INTERRUPT, "aicl count c:%d dgltch:%d first:%ld\n", + chip->aicl_irq_count, chip->aicl_deglitch_short, + chip->first_aicl_seconds); + + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + ICL_STS_1_REG, 1); + if (!rc) + chip->aicl_complete = reg & AICL_STS_BIT; + else + chip->aicl_complete = false; + + if (chip->aicl_deglitch_short || chip->force_aicl_rerun) { + if (!chip->aicl_irq_count) + get_current_time(&chip->first_aicl_seconds); + get_current_time(&now_seconds); + elapsed_seconds = now_seconds + - chip->first_aicl_seconds; + + if (elapsed_seconds > AICL_IRQ_LIMIT_SECONDS) { + pr_smb(PR_INTERRUPT, + "resetting: elp:%ld first:%ld now:%ld c=%d\n", + elapsed_seconds, chip->first_aicl_seconds, + now_seconds, chip->aicl_irq_count); + chip->aicl_irq_count = 1; + get_current_time(&chip->first_aicl_seconds); + return; + } + /* + * Double the amount of AICLs allowed if parallel charging is + * enabled. + */ + max_aicl_count = AICL_IRQ_LIMIT_COUNT + * (chip->parallel.avail ? 2 : 1); + chip->aicl_irq_count++; + + if (chip->aicl_irq_count > max_aicl_count) { + pr_smb(PR_INTERRUPT, "elp:%ld first:%ld now:%ld c=%d\n", + elapsed_seconds, chip->first_aicl_seconds, + now_seconds, chip->aicl_irq_count); + pr_smb(PR_INTERRUPT, "Disable AICL rerun\n"); + chip->very_weak_charger = true; + bad_charger = true; + + /* + * Disable AICL rerun since many interrupts were + * triggered in a short time + */ + /* disable hw aicl */ + rc = vote(chip->hw_aicl_rerun_disable_votable, + WEAK_CHARGER_HW_AICL_VOTER, true, 0); + if (rc < 0) { + pr_err("Couldn't disable hw aicl rerun rc=%d\n", + rc); + return; + } + + /* Vote 100mA current limit */ + rc = vote(chip->usb_icl_votable, WEAK_CHARGER_ICL_VOTER, + true, CURRENT_100_MA); + if (rc < 0) { + pr_err("Can't vote %d current limit rc=%d\n", + CURRENT_100_MA, rc); + } + + chip->aicl_irq_count = 0; + } else if ((get_prop_charge_type(chip) == + POWER_SUPPLY_CHARGE_TYPE_FAST) && + (reg & AICL_SUSP_BIT)) { + /* + * If the AICL_SUSP_BIT is on, then AICL reruns have + * already been disabled. Set the very weak charger + * flag so that the driver reports a bad charger + * and does not reenable AICL reruns. + */ + chip->very_weak_charger = true; + bad_charger = true; + } + if (bad_charger) { + pr_smb(PR_MISC, + "setting usb psy health UNSPEC_FAILURE\n"); + rc = power_supply_set_health_state(chip->usb_psy, + POWER_SUPPLY_HEALTH_UNSPEC_FAILURE); + if (rc) + pr_err("Couldn't set health on usb psy rc:%d\n", + rc); + schedule_work(&chip->usb_set_online_work); + } + } +} + +static int wait_for_usbin_uv(struct smbchg_chip *chip, bool high) +{ + int rc; + int tries = 3; + struct completion *completion = &chip->usbin_uv_lowered; + bool usbin_uv; + + if (high) + completion = &chip->usbin_uv_raised; + + while (tries--) { + rc = wait_for_completion_interruptible_timeout( + completion, + msecs_to_jiffies(APSD_TIMEOUT_MS)); + if (rc >= 0) + break; + } + + usbin_uv = is_usbin_uv_high(chip); + + if (high == usbin_uv) + return 0; + + pr_err("usbin uv didnt go to a %s state, still at %s, tries = %d, rc = %d\n", + high ? "risen" : "lowered", + usbin_uv ? "high" : "low", + tries, rc); + return -EINVAL; +} + +static int wait_for_src_detect(struct smbchg_chip *chip, bool high) +{ + int rc; + int tries = 3; + struct completion *completion = &chip->src_det_lowered; + bool src_detect; + + if (high) + completion = &chip->src_det_raised; + + while (tries--) { + rc = wait_for_completion_interruptible_timeout( + completion, + msecs_to_jiffies(APSD_TIMEOUT_MS)); + if (rc >= 0) + break; + } + + src_detect = is_src_detect_high(chip); + + if (high == src_detect) + return 0; + + pr_err("src detect didnt go to a %s state, still at %s, tries = %d, rc = %d\n", + high ? "risen" : "lowered", + src_detect ? "high" : "low", + tries, rc); + return -EINVAL; +} + +static int fake_insertion_removal(struct smbchg_chip *chip, bool insertion) +{ + int rc; + bool src_detect; + bool usbin_uv; + + if (insertion) { + reinit_completion(&chip->src_det_raised); + reinit_completion(&chip->usbin_uv_lowered); + } else { + reinit_completion(&chip->src_det_lowered); + reinit_completion(&chip->usbin_uv_raised); + } + + /* ensure that usbin uv real time status is in the right state */ + usbin_uv = is_usbin_uv_high(chip); + if (usbin_uv != insertion) { + pr_err("Skip faking, usbin uv is already %d\n", usbin_uv); + return -EINVAL; + } + + /* ensure that src_detect real time status is in the right state */ + src_detect = is_src_detect_high(chip); + if (src_detect == insertion) { + pr_err("Skip faking, src detect is already %d\n", src_detect); + return -EINVAL; + } + + pr_smb(PR_MISC, "Allow only %s charger\n", + insertion ? "5-9V" : "9V only"); + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + ADAPTER_ALLOWANCE_MASK, + insertion ? + USBIN_ADAPTER_5V_9V_CONT : USBIN_ADAPTER_9V); + if (rc < 0) { + pr_err("Couldn't write usb allowance rc=%d\n", rc); + return rc; + } + + pr_smb(PR_MISC, "Waiting on %s usbin uv\n", + insertion ? "falling" : "rising"); + rc = wait_for_usbin_uv(chip, !insertion); + if (rc < 0) { + pr_err("wait for usbin uv failed rc = %d\n", rc); + return rc; + } + + pr_smb(PR_MISC, "Waiting on %s src det\n", + insertion ? "rising" : "falling"); + rc = wait_for_src_detect(chip, insertion); + if (rc < 0) { + pr_err("wait for src detect failed rc = %d\n", rc); + return rc; + } + + return 0; +} + +static void smbchg_handle_hvdcp3_disable(struct smbchg_chip *chip) +{ + enum power_supply_type usb_supply_type; + char *usb_type_name = "NULL"; + + if (chip->allow_hvdcp3_detection) + return; + + chip->pulse_cnt = 0; + + if (is_hvdcp_present(chip)) { + smbchg_change_usb_supply_type(chip, + POWER_SUPPLY_TYPE_USB_HVDCP); + } else if (is_usb_present(chip)) { + read_usb_type(chip, &usb_type_name, &usb_supply_type); + smbchg_change_usb_supply_type(chip, usb_supply_type); + if (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP) { + schedule_delayed_work(&chip->hvdcp_det_work, + msecs_to_jiffies(HVDCP_NOTIFY_MS)); + if (chip->parallel.use_parallel_aicl) { + reinit_completion(&chip->hvdcp_det_done); + pr_smb(PR_MISC, "init hvdcp_det_done\n"); + } + } + } else { + smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); + } +} + +static int smbchg_prepare_for_pulsing(struct smbchg_chip *chip) +{ + int rc = 0; + u8 reg; + + /* switch to 5V HVDCP */ + pr_smb(PR_MISC, "Switch to 5V HVDCP\n"); + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_5V); + if (rc < 0) { + pr_err("Couldn't configure HVDCP 5V rc=%d\n", rc); + goto out; + } + + /* wait for HVDCP to lower to 5V */ + msleep(500); + /* + * Check if the same hvdcp session is in progress. src_det should be + * high and that we are still in 5V hvdcp + */ + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "src det low after 500mS sleep\n"); + goto out; + } + + /* disable HVDCP */ + pr_smb(PR_MISC, "Disable HVDCP\n"); + rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, true, 0); + if (rc < 0) { + pr_err("Couldn't disable HVDCP rc=%d\n", rc); + goto out; + } + + pr_smb(PR_MISC, "HVDCP voting for 300mA ICL\n"); + rc = vote(chip->usb_icl_votable, HVDCP_ICL_VOTER, true, 300); + if (rc < 0) { + pr_err("Couldn't vote for 300mA HVDCP ICL rc=%d\n", rc); + goto out; + } + + pr_smb(PR_MISC, "Disable AICL\n"); + smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, 0); + + chip->hvdcp_3_det_ignore_uv = true; + /* fake a removal */ + pr_smb(PR_MISC, "Faking Removal\n"); + rc = fake_insertion_removal(chip, false); + if (rc < 0) { + pr_err("Couldn't fake removal HVDCP Removed rc=%d\n", rc); + goto handle_removal; + } + + set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DP0P6_DMF); + + /* disable APSD */ + pr_smb(PR_MISC, "Disabling APSD\n"); + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + APSD_CFG, + AUTO_SRC_DETECT_EN_BIT, 0); + if (rc < 0) { + pr_err("Couldn't disable APSD rc=%d\n", rc); + goto out; + } + + /* fake an insertion */ + pr_smb(PR_MISC, "Faking Insertion\n"); + rc = fake_insertion_removal(chip, true); + if (rc < 0) { + pr_err("Couldn't fake insertion rc=%d\n", rc); + goto handle_removal; + } + chip->hvdcp_3_det_ignore_uv = false; + + pr_smb(PR_MISC, "Enable AICL\n"); + smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, AICL_EN_BIT); + + /* + * DCP will switch to HVDCP in this time by removing the short + * between DP DM + */ + msleep(HVDCP_NOTIFY_MS); + /* + * Check if the same hvdcp session is in progress. src_det should be + * high and the usb type should be none since APSD was disabled + */ + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "src det low after 2s sleep\n"); + rc = -EINVAL; + goto out; + } + + smbchg_read(chip, ®, chip->misc_base + IDEV_STS, 1); + if ((reg >> TYPE_BITS_OFFSET) != 0) { + pr_smb(PR_MISC, "type bits set after 2s sleep - abort\n"); + rc = -EINVAL; + goto out; + } + + set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DP0P6_DM3P3); + /* Wait 60mS after entering continuous mode */ + msleep(60); + + return 0; +out: + chip->hvdcp_3_det_ignore_uv = false; + restore_from_hvdcp_detection(chip); + return rc; +handle_removal: + chip->hvdcp_3_det_ignore_uv = false; + update_usb_status(chip, 0, 0); + return rc; +} + +static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) +{ + int rc = 0; + + set_usb_psy_dp_dm(chip, POWER_SUPPLY_DP_DM_DPF_DMF); + + /* switch to 9V HVDCP */ + pr_smb(PR_MISC, "Switch to 9V HVDCP\n"); + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_9V); + if (rc < 0) { + pr_err("Couldn't configure HVDCP 9V rc=%d\n", rc); + return rc; + } + + /* enable HVDCP */ + pr_smb(PR_MISC, "Enable HVDCP\n"); + rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, false, 1); + if (rc < 0) { + pr_err("Couldn't enable HVDCP rc=%d\n", rc); + return rc; + } + + /* enable APSD */ + pr_smb(PR_MISC, "Enabling APSD\n"); + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + APSD_CFG, + AUTO_SRC_DETECT_EN_BIT, AUTO_SRC_DETECT_EN_BIT); + if (rc < 0) { + pr_err("Couldn't enable APSD rc=%d\n", rc); + return rc; + } + + /* Disable AICL */ + pr_smb(PR_MISC, "Disable AICL\n"); + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, 0); + if (rc < 0) { + pr_err("Couldn't disable AICL rc=%d\n", rc); + return rc; + } + + /* fake a removal */ + chip->hvdcp_3_det_ignore_uv = true; + pr_smb(PR_MISC, "Faking Removal\n"); + rc = fake_insertion_removal(chip, false); + if (rc < 0) { + pr_err("Couldn't fake removal rc=%d\n", rc); + goto out; + } + + /* + * reset the enabled once flag for parallel charging so + * parallel charging can immediately restart after the HVDCP pulsing + * is complete + */ + chip->parallel.enabled_once = false; + + /* Enable AICL */ + pr_smb(PR_MISC, "Enable AICL\n"); + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, AICL_EN_BIT); + if (rc < 0) { + pr_err("Couldn't enable AICL rc=%d\n", rc); + goto out; + } + + /* fake an insertion */ + pr_smb(PR_MISC, "Faking Insertion\n"); + rc = fake_insertion_removal(chip, true); + if (rc < 0) { + pr_err("Couldn't fake insertion rc=%d\n", rc); + goto out; + } + chip->hvdcp_3_det_ignore_uv = false; + +out: + /* + * There are many QC 2.0 chargers that collapse before the aicl deglitch + * timer can mitigate. Hence set the aicl deglitch time to a shorter + * period. + */ + + rc = vote(chip->aicl_deglitch_short_votable, + HVDCP_SHORT_DEGLITCH_VOTER, true, 0); + if (rc < 0) + pr_err("Couldn't reduce aicl deglitch rc=%d\n", rc); + + pr_smb(PR_MISC, "Retracting HVDCP vote for ICL\n"); + rc = vote(chip->usb_icl_votable, HVDCP_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); + + chip->hvdcp_3_det_ignore_uv = false; + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "HVDCP removed\n"); + update_usb_status(chip, 0, 0); + } + + smbchg_handle_hvdcp3_disable(chip); + + if (chip->parallel.use_parallel_aicl) { + pr_smb(PR_MISC, "complete hvdcp_det_done\n"); + complete_all(&chip->hvdcp_det_done); + } + + return rc; +} + +#define USB_CMD_APSD 0x41 +#define APSD_RERUN BIT(0) +static int rerun_apsd(struct smbchg_chip *chip) +{ + int rc = 0; + + chip->hvdcp_3_det_ignore_uv = true; + + if (chip->schg_version == QPNP_SCHG_LITE) { + pr_smb(PR_STATUS, "Re-running APSD\n"); + reinit_completion(&chip->src_det_raised); + reinit_completion(&chip->usbin_uv_lowered); + reinit_completion(&chip->src_det_lowered); + reinit_completion(&chip->usbin_uv_raised); + + /* re-run APSD */ + rc = smbchg_masked_write(chip, + chip->usb_chgpth_base + USB_CMD_APSD, + APSD_RERUN, APSD_RERUN); + if (rc) { + pr_err("Couldn't re-run APSD rc=%d\n", rc); + goto out; + } + + pr_smb(PR_MISC, "Waiting on rising usbin uv\n"); + rc = wait_for_usbin_uv(chip, true); + if (rc < 0) { + pr_err("wait for usbin uv failed rc = %d\n", rc); + goto out; + } + + pr_smb(PR_MISC, "Waiting on falling src det\n"); + rc = wait_for_src_detect(chip, false); + if (rc < 0) { + pr_err("wait for src detect failed rc = %d\n", rc); + goto out; + } + + pr_smb(PR_MISC, "Waiting on falling usbin uv\n"); + rc = wait_for_usbin_uv(chip, false); + if (rc < 0) { + pr_err("wait for usbin uv failed rc = %d\n", rc); + goto out; + } + + pr_smb(PR_MISC, "Waiting on rising src det\n"); + rc = wait_for_src_detect(chip, true); + if (rc < 0) { + pr_err("wait for src detect failed rc = %d\n", rc); + goto out; + } + } else { + pr_smb(PR_STATUS, "Faking Removal\n"); + rc = fake_insertion_removal(chip, false); + msleep(500); + pr_smb(PR_STATUS, "Faking Insertion\n"); + rc = fake_insertion_removal(chip, true); + } + +out: + chip->hvdcp_3_det_ignore_uv = false; + return rc; +} + +#define SCHG_LITE_USBIN_HVDCP_5_9V 0x8 +#define SCHG_LITE_USBIN_HVDCP_5_9V_SEL_MASK 0x38 +#define SCHG_LITE_USBIN_HVDCP_SEL_IDLE BIT(3) +static bool is_hvdcp_5v_cont_mode(struct smbchg_chip *chip) +{ + int rc; + u8 reg = 0; + + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + USBIN_HVDCP_STS, 1); + if (rc) { + pr_err("Unable to read HVDCP status rc=%d\n", rc); + return false; + } + + pr_smb(PR_STATUS, "HVDCP status = %x\n", reg); + + if (reg & SCHG_LITE_USBIN_HVDCP_SEL_IDLE) { + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + INPUT_STS, 1); + if (rc) { + pr_err("Unable to read INPUT status rc=%d\n", rc); + return false; + } + pr_smb(PR_STATUS, "INPUT status = %x\n", reg); + if ((reg & SCHG_LITE_USBIN_HVDCP_5_9V_SEL_MASK) == + SCHG_LITE_USBIN_HVDCP_5_9V) + return true; + } + return false; +} + +static int smbchg_prepare_for_pulsing_lite(struct smbchg_chip *chip) +{ + int rc = 0; + + pr_smb(PR_MISC, "HVDCP voting for 300mA ICL\n"); + rc = vote(chip->usb_icl_votable, HVDCP_ICL_VOTER, true, 300); + if (rc < 0) { + pr_err("Couldn't vote for 300mA HVDCP ICL rc=%d\n", rc); + return rc; + } + + /* check if HVDCP is already in 5V continuous mode */ + if (is_hvdcp_5v_cont_mode(chip)) { + pr_smb(PR_MISC, "HVDCP by default is in 5V continuous mode\n"); + return 0; + } + + /* switch to 5V HVDCP */ + pr_smb(PR_MISC, "Switch to 5V HVDCP\n"); + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_5V); + if (rc < 0) { + pr_err("Couldn't configure HVDCP 5V rc=%d\n", rc); + goto out; + } + + /* wait for HVDCP to lower to 5V */ + msleep(500); + /* + * Check if the same hvdcp session is in progress. src_det should be + * high and that we are still in 5V hvdcp + */ + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "src det low after 500mS sleep\n"); + goto out; + } + + pr_smb(PR_MISC, "Disable AICL\n"); + smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, 0); + + /* re-run APSD */ + rc = rerun_apsd(chip); + if (rc) { + pr_err("APSD rerun failed\n"); + goto out; + } + + pr_smb(PR_MISC, "Enable AICL\n"); + smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG, + AICL_EN_BIT, AICL_EN_BIT); + /* + * DCP will switch to HVDCP in this time by removing the short + * between DP DM + */ + msleep(HVDCP_NOTIFY_MS); + /* + * Check if the same hvdcp session is in progress. src_det should be + * high and the usb type should be none since APSD was disabled + */ + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "src det low after 2s sleep\n"); + rc = -EINVAL; + goto out; + } + + /* We are set if HVDCP in 5V continuous mode */ + if (!is_hvdcp_5v_cont_mode(chip)) { + pr_err("HVDCP could not be set in 5V continuous mode\n"); + goto out; + } + + return 0; +out: + chip->hvdcp_3_det_ignore_uv = false; + restore_from_hvdcp_detection(chip); + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "HVDCP removed - force removal\n"); + update_usb_status(chip, 0, true); + } + return rc; +} + +static int smbchg_unprepare_for_pulsing_lite(struct smbchg_chip *chip) +{ + int rc = 0; + + pr_smb(PR_MISC, "Forcing 9V HVDCP 2.0\n"); + rc = force_9v_hvdcp(chip); + if (rc) { + pr_err("Failed to force 9V HVDCP=%d\n", rc); + return rc; + } + + pr_smb(PR_MISC, "Retracting HVDCP vote for ICL\n"); + rc = vote(chip->usb_icl_votable, HVDCP_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); + + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "HVDCP removed\n"); + update_usb_status(chip, 0, 0); + } + smbchg_handle_hvdcp3_disable(chip); + + if (chip->parallel.use_parallel_aicl) { + pr_smb(PR_MISC, "complete hvdcp_det_done\n"); + complete_all(&chip->hvdcp_det_done); + } + + return rc; +} + +#define CMD_HVDCP_2 0x43 +#define SINGLE_INCREMENT BIT(0) +#define SINGLE_DECREMENT BIT(1) +static int smbchg_dp_pulse_lite(struct smbchg_chip *chip) +{ + int rc = 0; + + pr_smb(PR_MISC, "Increment DP\n"); + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_HVDCP_2, + SINGLE_INCREMENT, SINGLE_INCREMENT); + if (rc) + pr_err("Single-increment failed rc=%d\n", rc); + + return rc; +} + +static int smbchg_dm_pulse_lite(struct smbchg_chip *chip) +{ + int rc = 0; + + pr_smb(PR_MISC, "Decrement DM\n"); + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_HVDCP_2, + SINGLE_DECREMENT, SINGLE_DECREMENT); + if (rc) + pr_err("Single-decrement failed rc=%d\n", rc); + + return rc; +} + +static int smbchg_hvdcp3_confirmed(struct smbchg_chip *chip) +{ + int rc = 0; + + /* + * reset the enabled once flag for parallel charging because this is + * effectively a new insertion. + */ + chip->parallel.enabled_once = false; + + pr_smb(PR_MISC, "Retracting HVDCP vote for ICL\n"); + rc = vote(chip->usb_icl_votable, HVDCP_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc); + + smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_USB_HVDCP_3); + + if (chip->parallel.use_parallel_aicl) { + complete_all(&chip->hvdcp_det_done); + pr_smb(PR_MISC, "hvdcp_det_done complete\n"); + } + + return rc; +} + +static int smbchg_dp_dm(struct smbchg_chip *chip, int val) +{ + int rc = 0; + int target_icl_vote_ma; + + switch (val) { + case POWER_SUPPLY_DP_DM_PREPARE: + if (!is_hvdcp_present(chip)) { + pr_err("No pulsing unless HVDCP\n"); + return -ENODEV; + } + if (chip->schg_version == QPNP_SCHG_LITE) + rc = smbchg_prepare_for_pulsing_lite(chip); + else + rc = smbchg_prepare_for_pulsing(chip); + break; + case POWER_SUPPLY_DP_DM_UNPREPARE: + if (chip->schg_version == QPNP_SCHG_LITE) + rc = smbchg_unprepare_for_pulsing_lite(chip); + else + rc = smbchg_unprepare_for_pulsing(chip); + break; + case POWER_SUPPLY_DP_DM_CONFIRMED_HVDCP3: + rc = smbchg_hvdcp3_confirmed(chip); + break; + case POWER_SUPPLY_DP_DM_DP_PULSE: + if (chip->schg_version == QPNP_SCHG) + rc = set_usb_psy_dp_dm(chip, + POWER_SUPPLY_DP_DM_DP_PULSE); + else + rc = smbchg_dp_pulse_lite(chip); + if (!rc) + chip->pulse_cnt++; + pr_smb(PR_MISC, "pulse_cnt = %d\n", chip->pulse_cnt); + break; + case POWER_SUPPLY_DP_DM_DM_PULSE: + if (chip->schg_version == QPNP_SCHG) + rc = set_usb_psy_dp_dm(chip, + POWER_SUPPLY_DP_DM_DM_PULSE); + else + rc = smbchg_dm_pulse_lite(chip); + if (!rc && chip->pulse_cnt) + chip->pulse_cnt--; + pr_smb(PR_MISC, "pulse_cnt = %d\n", chip->pulse_cnt); + break; + case POWER_SUPPLY_DP_DM_HVDCP3_SUPPORTED: + chip->hvdcp3_supported = true; + pr_smb(PR_MISC, "HVDCP3 supported\n"); + break; + case POWER_SUPPLY_DP_DM_ICL_DOWN: + chip->usb_icl_delta -= 100; + target_icl_vote_ma = get_client_vote(chip->usb_icl_votable, + PSY_ICL_VOTER); + vote(chip->usb_icl_votable, SW_AICL_ICL_VOTER, true, + target_icl_vote_ma + chip->usb_icl_delta); + break; + case POWER_SUPPLY_DP_DM_ICL_UP: + chip->usb_icl_delta += 100; + target_icl_vote_ma = get_client_vote(chip->usb_icl_votable, + PSY_ICL_VOTER); + vote(chip->usb_icl_votable, SW_AICL_ICL_VOTER, true, + target_icl_vote_ma + chip->usb_icl_delta); + break; + default: + break; + } + + return rc; +} + +static int smbchg_get_prop_batt_charge_counter(struct smbchg_chip *chip) +{ + int rc; + union power_supply_propval val; + + if (!chip->bms_psy) + return -EINVAL; + + rc = power_supply_get_property(chip->bms_psy, + POWER_SUPPLY_PROP_CHARGE_COUNTER, &val); + if (rc < 0) { + pr_smb(PR_STATUS, "Couldn't get charge count rc = %d\n", rc); + return rc; + } + + return val.intval; +} + +static int smbchg_get_prop_batt_current_max(struct smbchg_chip *chip) +{ + int rc; + union power_supply_propval val; + + if (!chip->usb_psy) + return -EINVAL; + + rc = power_supply_get_property(chip->usb_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, &val); + if (rc < 0) { + pr_smb(PR_STATUS, "Couldn't get current max rc = %d\n", rc); + return rc; + } + + return val.intval; +} + +static void update_typec_capability_status(struct smbchg_chip *chip, + const union power_supply_propval *val) +{ + int rc; + + pr_smb(PR_TYPEC, "typec capability = %dma\n", val->intval); + + if (!chip->skip_usb_notification) { + rc = chip->usb_psy->set_property(chip->usb_psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, val); + if (rc) + pr_err("typec failed to set current max rc=%d\n", rc); + } + + pr_debug("changing ICL from %dma to %dma\n", chip->typec_current_ma, + val->intval); + chip->typec_current_ma = val->intval; + smbchg_change_usb_supply_type(chip, chip->usb_supply_type); +} + +static void update_typec_otg_status(struct smbchg_chip *chip, int mode, + bool force) +{ + pr_smb(PR_TYPEC, "typec mode = %d\n", mode); + + if (mode == POWER_SUPPLY_TYPE_DFP) { + chip->typec_dfp = true; + power_supply_set_usb_otg(chip->usb_psy, chip->typec_dfp); + /* update FG */ + set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS, + get_prop_batt_status(chip)); + } else if (force || chip->typec_dfp) { + chip->typec_dfp = false; + power_supply_set_usb_otg(chip->usb_psy, chip->typec_dfp); + /* update FG */ + set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS, + get_prop_batt_status(chip)); + } +} + +#define CHARGE_OUTPUT_VTG_RATIO 840 +static int smbchg_get_iusb(struct smbchg_chip *chip) +{ + int rc, iusb_ua = -EINVAL; + struct qpnp_vadc_result adc_result; + + if (!is_usb_present(chip) && !is_dc_present(chip)) + return 0; + + if (chip->vchg_vadc_dev && chip->vchg_adc_channel != -EINVAL) { + rc = qpnp_vadc_read(chip->vchg_vadc_dev, + chip->vchg_adc_channel, &adc_result); + if (rc) { + pr_smb(PR_STATUS, + "error in VCHG (channel-%d) read rc = %d\n", + chip->vchg_adc_channel, rc); + return 0; + } + iusb_ua = div_s64(adc_result.physical * 1000, + CHARGE_OUTPUT_VTG_RATIO); + } + + return iusb_ua; +} + +static void smbchg_external_power_changed(struct power_supply *psy) +{ + struct smbchg_chip *chip = container_of(psy, + struct smbchg_chip, batt_psy); + union power_supply_propval prop = {0,}; + int rc, current_limit = 0, soc; + enum power_supply_type usb_supply_type; + char *usb_type_name = "null"; + + if (chip->bms_psy_name) + chip->bms_psy = + power_supply_get_by_name((char *)chip->bms_psy_name); + + smbchg_aicl_deglitch_wa_check(chip); + if (chip->bms_psy) { + check_battery_type(chip); + soc = get_prop_batt_capacity(chip); + if (chip->previous_soc != soc) { + chip->previous_soc = soc; + smbchg_soc_changed(chip); + } + + rc = smbchg_config_chg_battery_type(chip); + if (rc) + pr_smb(PR_MISC, + "Couldn't update charger configuration rc=%d\n", + rc); + } + + rc = chip->usb_psy->get_property(chip->usb_psy, + POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop); + if (rc == 0) + vote(chip->usb_suspend_votable, POWER_SUPPLY_EN_VOTER, + !prop.intval, 0); + + rc = chip->usb_psy->get_property(chip->usb_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, &prop); + if (rc == 0) + current_limit = prop.intval / 1000; + + read_usb_type(chip, &usb_type_name, &usb_supply_type); + + pr_smb(PR_MISC, "usb type = %s current_limit = %d\n", + usb_type_name, current_limit); + + rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, + current_limit); + if (rc < 0) + pr_err("Couldn't update USB PSY ICL vote rc=%d\n", rc); + + + power_supply_changed(&chip->batt_psy); +} + +static enum power_supply_property smbchg_battery_properties[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED, + POWER_SUPPLY_PROP_CHARGING_ENABLED, + POWER_SUPPLY_PROP_CHARGE_TYPE, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_HEALTH, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL, + POWER_SUPPLY_PROP_FLASH_CURRENT_MAX, + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_RESISTANCE_ID, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE, + POWER_SUPPLY_PROP_INPUT_CURRENT_MAX, + POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, + POWER_SUPPLY_PROP_INPUT_CURRENT_NOW, + POWER_SUPPLY_PROP_FLASH_ACTIVE, + POWER_SUPPLY_PROP_FLASH_TRIGGER, + POWER_SUPPLY_PROP_DP_DM, + POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, + POWER_SUPPLY_PROP_RERUN_AICL, + POWER_SUPPLY_PROP_RESTRICTED_CHARGING, + POWER_SUPPLY_PROP_ALLOW_HVDCP3, + POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED, + POWER_SUPPLY_PROP_DUMP_SRAM, +}; + +static int smbchg_battery_set_property(struct power_supply *psy, + enum power_supply_property prop, + const union power_supply_propval *val) +{ + int rc = 0; + struct smbchg_chip *chip = container_of(psy, + struct smbchg_chip, batt_psy); + + switch (prop) { + case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED: + vote(chip->battchg_suspend_votable, BATTCHG_USER_EN_VOTER, + !val->intval, 0); + break; + case POWER_SUPPLY_PROP_CHARGING_ENABLED: + rc = vote(chip->usb_suspend_votable, USER_EN_VOTER, + !val->intval, 0); + rc = vote(chip->dc_suspend_votable, USER_EN_VOTER, + !val->intval, 0); + chip->chg_enabled = val->intval; + schedule_work(&chip->usb_set_online_work); + break; + case POWER_SUPPLY_PROP_CAPACITY: + chip->fake_battery_soc = val->intval; + power_supply_changed(&chip->batt_psy); + break; + case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: + smbchg_system_temp_level_set(chip, val->intval); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + rc = smbchg_set_fastchg_current_user(chip, val->intval / 1000); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + rc = smbchg_float_voltage_set(chip, val->intval); + break; + case POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE: + rc = smbchg_safety_timer_enable(chip, val->intval); + break; + case POWER_SUPPLY_PROP_FLASH_ACTIVE: + rc = smbchg_switch_buck_frequency(chip, val->intval); + if (rc) { + pr_err("Couldn't switch buck frequency, rc=%d\n", rc); + /* + * Trigger a panic if there is an error while switching + * buck frequency. This will prevent LS FET damage. + */ + BUG_ON(1); + } + + rc = smbchg_otg_pulse_skip_disable(chip, + REASON_FLASH_ENABLED, val->intval); + break; + case POWER_SUPPLY_PROP_FLASH_TRIGGER: + chip->flash_triggered = !!val->intval; + smbchg_icl_loop_disable_check(chip); + break; + case POWER_SUPPLY_PROP_FORCE_TLIM: + rc = smbchg_force_tlim_en(chip, val->intval); + break; + case POWER_SUPPLY_PROP_DP_DM: + rc = smbchg_dp_dm(chip, val->intval); + break; + case POWER_SUPPLY_PROP_RERUN_AICL: + smbchg_rerun_aicl(chip); + break; + case POWER_SUPPLY_PROP_RESTRICTED_CHARGING: + rc = smbchg_restricted_charging(chip, val->intval); + break; + case POWER_SUPPLY_PROP_CURRENT_CAPABILITY: + if (chip->typec_psy) + update_typec_capability_status(chip, val); + break; + case POWER_SUPPLY_PROP_TYPEC_MODE: + if (chip->typec_psy) + update_typec_otg_status(chip, val->intval, false); + break; + case POWER_SUPPLY_PROP_ALLOW_HVDCP3: + if (chip->allow_hvdcp3_detection != val->intval) { + chip->allow_hvdcp3_detection = !!val->intval; + power_supply_changed(&chip->batt_psy); + } + break; + case POWER_SUPPLY_PROP_DUMP_SRAM: + dump_debug(chip); + break; + default: + return -EINVAL; + } + + return rc; +} + +static int smbchg_battery_is_writeable(struct power_supply *psy, + enum power_supply_property prop) +{ + int rc; + + switch (prop) { + case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED: + case POWER_SUPPLY_PROP_CHARGING_ENABLED: + case POWER_SUPPLY_PROP_CAPACITY: + case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + case POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE: + case POWER_SUPPLY_PROP_DP_DM: + case POWER_SUPPLY_PROP_RERUN_AICL: + case POWER_SUPPLY_PROP_RESTRICTED_CHARGING: + case POWER_SUPPLY_PROP_DUMP_SRAM: + case POWER_SUPPLY_PROP_ALLOW_HVDCP3: + rc = 1; + break; + default: + rc = 0; + break; + } + return rc; +} + +static int smbchg_battery_get_property(struct power_supply *psy, + enum power_supply_property prop, + union power_supply_propval *val) +{ + struct smbchg_chip *chip = container_of(psy, + struct smbchg_chip, batt_psy); + + switch (prop) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = get_prop_batt_status(chip); + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = get_prop_batt_present(chip); + break; + case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED: + val->intval + = get_effective_result(chip->battchg_suspend_votable); + if (val->intval < 0) /* no votes */ + val->intval = 1; + else + val->intval = !val->intval; + break; + case POWER_SUPPLY_PROP_CHARGING_ENABLED: + val->intval = chip->chg_enabled; + break; + case POWER_SUPPLY_PROP_CHARGE_TYPE: + val->intval = get_prop_charge_type(chip); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + val->intval = smbchg_float_voltage_get(chip); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = smbchg_get_prop_batt_current_max(chip); + break; + case POWER_SUPPLY_PROP_HEALTH: + val->intval = get_prop_batt_health(chip); + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case POWER_SUPPLY_PROP_FLASH_CURRENT_MAX: + val->intval = smbchg_calc_max_flash_current(chip); + break; + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: + val->intval = chip->fastchg_current_ma * 1000; + break; + case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL: + val->intval = chip->therm_lvl_sel; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX: + val->intval = smbchg_get_aicl_level_ma(chip) * 1000; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED: + val->intval = (int)chip->aicl_complete; + break; + case POWER_SUPPLY_PROP_RESTRICTED_CHARGING: + val->intval = (int)chip->restricted_charging; + break; + /* properties from fg */ + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = get_prop_batt_capacity(chip); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + val->intval = get_prop_battery_charge_full_design(chip); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + val->intval = get_prop_battery_charge_full(chip); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = get_prop_batt_current_now(chip); + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = get_prop_batt_voltage_now(chip); + break; + case POWER_SUPPLY_PROP_RESISTANCE_ID: + val->intval = get_prop_batt_resistance_id(chip); + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = get_prop_batt_temp(chip); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = get_prop_batt_voltage_max_design(chip); + break; + case POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE: + val->intval = chip->safety_timer_en; + break; + case POWER_SUPPLY_PROP_FLASH_ACTIVE: + val->intval = chip->otg_pulse_skip_dis; + break; + case POWER_SUPPLY_PROP_FLASH_TRIGGER: + val->intval = chip->flash_triggered; + break; + case POWER_SUPPLY_PROP_DP_DM: + val->intval = chip->pulse_cnt; + break; + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + val->intval = smbchg_get_prop_batt_charge_counter(chip); + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: + val->intval = smbchg_is_input_current_limited(chip); + break; + case POWER_SUPPLY_PROP_RERUN_AICL: + val->intval = 0; + break; + case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW: + val->intval = smbchg_get_iusb(chip); + break; + case POWER_SUPPLY_PROP_ALLOW_HVDCP3: + val->intval = chip->allow_hvdcp3_detection; + break; + case POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED: + val->intval = chip->max_pulse_allowed; + break; + case POWER_SUPPLY_PROP_DUMP_SRAM: + val->strval = chip->debug_dump; + break; + default: + return -EINVAL; + } + return 0; +} + +static char *smbchg_dc_supplicants[] = { + "bms", +}; + +static enum power_supply_property smbchg_dc_properties[] = { + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CHARGING_ENABLED, + POWER_SUPPLY_PROP_CURRENT_MAX, +}; + +static int smbchg_dc_set_property(struct power_supply *psy, + enum power_supply_property prop, + const union power_supply_propval *val) +{ + int rc = 0; + struct smbchg_chip *chip = container_of(psy, + struct smbchg_chip, dc_psy); + + switch (prop) { + case POWER_SUPPLY_PROP_CHARGING_ENABLED: + rc = vote(chip->dc_suspend_votable, POWER_SUPPLY_EN_VOTER, + !val->intval, 0); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = vote(chip->dc_icl_votable, USER_ICL_VOTER, true, + val->intval / 1000); + break; + default: + return -EINVAL; + } + + return rc; +} + +static int smbchg_dc_get_property(struct power_supply *psy, + enum power_supply_property prop, + union power_supply_propval *val) +{ + struct smbchg_chip *chip = container_of(psy, + struct smbchg_chip, dc_psy); + + switch (prop) { + case POWER_SUPPLY_PROP_PRESENT: + val->intval = is_dc_present(chip); + break; + case POWER_SUPPLY_PROP_CHARGING_ENABLED: + val->intval = get_effective_result(chip->dc_suspend_votable); + if (val->intval < 0) /* no votes */ + val->intval = 1; + else + val->intval = !val->intval; + break; + case POWER_SUPPLY_PROP_ONLINE: + /* return if dc is charging the battery */ + val->intval = (smbchg_get_pwr_path(chip) == PWR_PATH_DC) + && (get_prop_batt_status(chip) + == POWER_SUPPLY_STATUS_CHARGING); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + val->intval = chip->dc_max_current_ma * 1000; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smbchg_dc_is_writeable(struct power_supply *psy, + enum power_supply_property prop) +{ + int rc; + + switch (prop) { + case POWER_SUPPLY_PROP_CHARGING_ENABLED: + case POWER_SUPPLY_PROP_CURRENT_MAX: + rc = 1; + break; + default: + rc = 0; + break; + } + return rc; +} + +#define HOT_BAT_HARD_BIT BIT(0) +#define HOT_BAT_SOFT_BIT BIT(1) +#define COLD_BAT_HARD_BIT BIT(2) +#define COLD_BAT_SOFT_BIT BIT(3) +#define BAT_OV_BIT BIT(4) +#define BAT_LOW_BIT BIT(5) +#define BAT_MISSING_BIT BIT(6) +#define BAT_TERM_MISSING_BIT BIT(7) +static irqreturn_t batt_hot_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_hot = !!(reg & HOT_BAT_HARD_BIT); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + smbchg_wipower_check(chip); + set_property_on_fg(chip, POWER_SUPPLY_PROP_HEALTH, + get_prop_batt_health(chip)); + return IRQ_HANDLED; +} + +static irqreturn_t batt_cold_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_cold = !!(reg & COLD_BAT_HARD_BIT); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + smbchg_wipower_check(chip); + set_property_on_fg(chip, POWER_SUPPLY_PROP_HEALTH, + get_prop_batt_health(chip)); + return IRQ_HANDLED; +} + +static irqreturn_t batt_warm_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + int rc; + /* set the warm float voltage compensation,set the warm float voltage to 4.1V */ + if (chip->float_voltage_comp != -EINVAL) { + rc = smbchg_float_voltage_comp_set(chip, chip->float_voltage_comp); + if (rc < 0) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", rc); + pr_smb(PR_STATUS, "set float voltage comp to %d\n", chip->float_voltage_comp); + } + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_warm = !!(reg & HOT_BAT_SOFT_BIT); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + set_property_on_fg(chip, POWER_SUPPLY_PROP_HEALTH, + get_prop_batt_health(chip)); + return IRQ_HANDLED; +} + +static irqreturn_t batt_cool_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + int rc; + /* set the cool float voltage compensation ,set the cool float voltage to 4.4V*/ + rc = smbchg_float_voltage_comp_set(chip, 0); + if (rc < 0) + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", rc); + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_cool = !!(reg & COLD_BAT_SOFT_BIT); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + set_property_on_fg(chip, POWER_SUPPLY_PROP_HEALTH, + get_prop_batt_health(chip)); + return IRQ_HANDLED; +} + +static irqreturn_t batt_pres_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_present = !(reg & BAT_MISSING_BIT); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + set_property_on_fg(chip, POWER_SUPPLY_PROP_HEALTH, + get_prop_batt_health(chip)); + return IRQ_HANDLED; +} + +static void smbchg_temp_check_work(struct work_struct *work) +{ + u8 reg = 0; + struct smbchg_chip *chip = container_of(work, + struct smbchg_chip, + temp_check_work.work); + + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + chip->batt_warm = !!(reg & HOT_BAT_SOFT_BIT); + chip->batt_cool = !!(reg & COLD_BAT_SOFT_BIT); + chip->batt_hot = !!(reg & HOT_BAT_HARD_BIT); + chip->batt_cold = !!(reg & COLD_BAT_HARD_BIT); + + pr_err("temp_check_work:chip->batt_warm:%d. chip->batt_cool:%d. chip->batt_hot:%d. chip->batt_cold:%d.\n", + chip->batt_warm, chip->batt_cool, chip->batt_hot, chip->batt_cold); + + if (chip->batt_warm && !chip->batt_hot) { + batt_warm_handler(0, chip); + pr_err("batt_warm_handler.\n"); + } + if (chip->batt_cool && !chip->batt_cold) { + batt_cool_handler(0, chip); + pr_err("batt_cool_handler.\n"); + } + if (chip->batt_hot) { + batt_hot_handler(0, chip); + pr_err("batt_hot_handler.\n"); + } + if (chip->batt_cold) { + batt_cold_handler(0, chip); + pr_err("batt_cold_handler.\n"); + } +} + +static irqreturn_t vbat_low_handler(int irq, void *_chip) +{ + pr_warn_ratelimited("vbat low\n"); + return IRQ_HANDLED; +} + +#define CHG_COMP_SFT_BIT BIT(3) +static irqreturn_t chg_error_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + int rc = 0; + u8 reg; + + pr_smb(PR_INTERRUPT, "chg-error triggered\n"); + + rc = smbchg_read(chip, ®, chip->chgr_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Unable to read RT_STS rc = %d\n", rc); + } else { + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + if (reg & CHG_COMP_SFT_BIT) + set_property_on_fg(chip, + POWER_SUPPLY_PROP_SAFETY_TIMER_EXPIRED, + 1); + } + + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + smbchg_wipower_check(chip); + return IRQ_HANDLED; +} + +static irqreturn_t fastchg_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + + pr_smb(PR_INTERRUPT, "p2f triggered\n"); + + if (is_usb_present(chip) || is_dc_present(chip)) { + smbchg_detect_parallel_charger(chip); + smbchg_parallel_usb_check_ok(chip); + } + + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + smbchg_wipower_check(chip); + return IRQ_HANDLED; +} + +static irqreturn_t chg_hot_handler(int irq, void *_chip) +{ + pr_warn_ratelimited("chg hot\n"); + smbchg_wipower_check(_chip); + return IRQ_HANDLED; +} + +static irqreturn_t chg_term_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + + pr_smb(PR_INTERRUPT, "tcc triggered\n"); + /* + * Charge termination is a pulse and not level triggered. That means, + * TCC bit in RT_STS can get cleared by the time this interrupt is + * handled. Instead of relying on that to determine whether the + * charge termination had happened, we've to simply notify the FG + * about this as long as the interrupt is handled. + */ + set_property_on_fg(chip, POWER_SUPPLY_PROP_CHARGE_DONE, 1); + + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + + return IRQ_HANDLED; +} + +static irqreturn_t taper_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + taper_irq_en(chip, false); + smbchg_read(chip, ®, chip->chgr_base + RT_STS, 1); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + smbchg_parallel_usb_taper(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + smbchg_wipower_check(chip); + return IRQ_HANDLED; +} + +static irqreturn_t recharge_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + smbchg_read(chip, ®, chip->chgr_base + RT_STS, 1); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + smbchg_parallel_usb_check_ok(chip); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + return IRQ_HANDLED; +} + +static irqreturn_t wdog_timeout_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + smbchg_read(chip, ®, chip->misc_base + RT_STS, 1); + pr_warn_ratelimited("wdog timeout rt_stat = 0x%02x\n", reg); + if (chip->psy_registered) + power_supply_changed(&chip->batt_psy); + smbchg_charging_status_change(chip); + return IRQ_HANDLED; +} + +/** + * power_ok_handler() - called when the switcher turns on or turns off + * @chip: pointer to smbchg_chip + * @rt_stat: the status bit indicating switcher turning on or off + */ +static irqreturn_t power_ok_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + u8 reg = 0; + + smbchg_read(chip, ®, chip->misc_base + RT_STS, 1); + pr_smb(PR_INTERRUPT, "triggered: 0x%02x\n", reg); + return IRQ_HANDLED; +} + +/** + * dcin_uv_handler() - called when the dc voltage crosses the uv threshold + * @chip: pointer to smbchg_chip + * @rt_stat: the status bit indicating whether dc voltage is uv + */ +#define DCIN_UNSUSPEND_DELAY_MS 1000 +static irqreturn_t dcin_uv_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + bool dc_present = is_dc_present(chip); + + pr_smb(PR_STATUS, "chip->dc_present = %d dc_present = %d\n", + chip->dc_present, dc_present); + + if (chip->dc_present != dc_present) { + /* dc changed */ + chip->dc_present = dc_present; + if (chip->dc_psy_type != -EINVAL && chip->psy_registered) + power_supply_changed(&chip->dc_psy); + smbchg_charging_status_change(chip); + smbchg_aicl_deglitch_wa_check(chip); + chip->vbat_above_headroom = false; + } + + smbchg_wipower_check(chip); + return IRQ_HANDLED; +} + +/** + * usbin_ov_handler() - this is called when an overvoltage condition occurs + * @chip: pointer to smbchg_chip chip + */ +static irqreturn_t usbin_ov_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + int rc; + u8 reg; + bool usb_present; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read usb rt status rc = %d\n", rc); + goto out; + } + + /* OV condition is detected. Notify it to USB psy */ + if (reg & USBIN_OV_BIT) { + chip->usb_ov_det = true; + if (chip->usb_psy) { + pr_smb(PR_MISC, "setting usb psy health OV\n"); + rc = power_supply_set_health_state(chip->usb_psy, + POWER_SUPPLY_HEALTH_OVERVOLTAGE); + if (rc) + pr_smb(PR_STATUS, + "usb psy does not allow updating prop %d rc = %d\n", + POWER_SUPPLY_HEALTH_OVERVOLTAGE, rc); + } + } else { + chip->usb_ov_det = false; + /* If USB is present, then handle the USB insertion */ + usb_present = is_usb_present(chip); + if (usb_present) + update_usb_status(chip, usb_present, false); + } +out: + return IRQ_HANDLED; +} + +/** + * usbin_uv_handler() - this is called when USB charger is removed + * @chip: pointer to smbchg_chip chip + * @rt_stat: the status bit indicating chg insertion/removal + */ +#define ICL_MODE_MASK SMB_MASK(5, 4) +#define ICL_MODE_HIGH_CURRENT 0 +static irqreturn_t usbin_uv_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + int aicl_level = smbchg_get_aicl_level_ma(chip); + int rc; + u8 reg; + + rc = smbchg_read(chip, ®, chip->usb_chgpth_base + RT_STS, 1); + if (rc) { + pr_err("could not read rt sts: %d", rc); + goto out; + } + + pr_smb(PR_STATUS, + "%s chip->usb_present = %d rt_sts = 0x%02x hvdcp_3_det_ignore_uv = %d aicl = %d\n", + chip->hvdcp_3_det_ignore_uv ? "Ignoring":"", + chip->usb_present, reg, chip->hvdcp_3_det_ignore_uv, + aicl_level); + + /* + * set usb_psy's dp=f dm=f if this is a new insertion, i.e. it is + * not already src_detected and usbin_uv is seen falling + */ + if (!(reg & USBIN_UV_BIT) && !(reg & USBIN_SRC_DET_BIT) && + !chip->hvdcp_3_det_ignore_uv) { + pr_smb(PR_MISC, "setting usb psy dp=f dm=f\n"); + power_supply_set_dp_dm(chip->usb_psy, + POWER_SUPPLY_DP_DM_DPF_DMF); + } + + if (reg & USBIN_UV_BIT) + complete_all(&chip->usbin_uv_raised); + else + complete_all(&chip->usbin_uv_lowered); + + if (chip->hvdcp_3_det_ignore_uv) + goto out; + + if ((reg & USBIN_UV_BIT) && (reg & USBIN_SRC_DET_BIT)) { + pr_smb(PR_STATUS, "Very weak charger detected\n"); + chip->very_weak_charger = true; + rc = smbchg_read(chip, ®, + chip->usb_chgpth_base + ICL_STS_2_REG, 1); + if (rc) { + dev_err(chip->dev, "Could not read usb icl sts 2: %d\n", + rc); + goto out; + } + if ((reg & ICL_MODE_MASK) != ICL_MODE_HIGH_CURRENT) { + /* + * If AICL is not even enabled, this is either an + * SDP or a grossly out of spec charger. Do not + * draw any current from it. + */ + rc = vote(chip->usb_suspend_votable, + WEAK_CHARGER_EN_VOTER, true, 0); + if (rc < 0) + pr_err("could not disable charger: %d", rc); + } else if (aicl_level == chip->tables.usb_ilim_ma_table[0]) { + /* + * we are in a situation where the adapter is not able + * to supply even 300mA. Disable hw aicl reruns else it + * is only a matter of time when we get back here again + */ + rc = vote(chip->hw_aicl_rerun_disable_votable, + WEAK_CHARGER_HW_AICL_VOTER, true, 0); + if (rc < 0) + pr_err("Couldn't disable hw aicl rerun rc=%d\n", + rc); + } + pr_smb(PR_MISC, "setting usb psy health UNSPEC_FAILURE\n"); + rc = power_supply_set_health_state(chip->usb_psy, + POWER_SUPPLY_HEALTH_UNSPEC_FAILURE); + if (rc) + pr_err("Couldn't set health on usb psy rc:%d\n", rc); + schedule_work(&chip->usb_set_online_work); + } + + smbchg_wipower_check(chip); +out: + return IRQ_HANDLED; +} + +/** + * src_detect_handler() - this is called on rising edge when USB charger type + * is detected and on falling edge when USB voltage falls + * below the coarse detect voltage(1V), use it for + * handling USB charger insertion and removal. + * @chip: pointer to smbchg_chip + * @rt_stat: the status bit indicating chg insertion/removal + */ +static irqreturn_t src_detect_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + bool usb_present = is_usb_present(chip); + bool src_detect = is_src_detect_high(chip); + int rc; + + pr_smb(PR_STATUS, + "%s chip->usb_present = %d usb_present = %d src_detect = %d hvdcp_3_det_ignore_uv=%d\n", + chip->hvdcp_3_det_ignore_uv ? "Ignoring":"", + chip->usb_present, usb_present, src_detect, + chip->hvdcp_3_det_ignore_uv); + + if (src_detect) + complete_all(&chip->src_det_raised); + else + complete_all(&chip->src_det_lowered); + + if (chip->hvdcp_3_det_ignore_uv) + goto out; + + /* + * When VBAT is above the AICL threshold (4.25V) - 180mV (4.07V), + * an input collapse due to AICL will actually cause an USBIN_UV + * interrupt to fire as well. + * + * Handle USB insertions and removals in the source detect handler + * instead of the USBIN_UV handler since the latter is untrustworthy + * when the battery voltage is high. + */ + chip->very_weak_charger = false; + /* + * a src detect marks a new insertion or a real removal, + * vote for enable aicl hw reruns + */ + rc = vote(chip->hw_aicl_rerun_disable_votable, + WEAK_CHARGER_HW_AICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't enable hw aicl rerun rc=%d\n", rc); + + rc = vote(chip->usb_suspend_votable, WEAK_CHARGER_EN_VOTER, false, 0); + if (rc < 0) + pr_err("could not enable charger: %d\n", rc); + + if (src_detect) { + update_usb_status(chip, usb_present, 0); + } else { + update_usb_status(chip, 0, false); + chip->aicl_irq_count = 0; + } +out: + return IRQ_HANDLED; +} + +/** + * otg_oc_handler() - called when the usb otg goes over current + */ +#define NUM_OTG_RETRIES 5 +#define OTG_OC_RETRY_DELAY_US 50000 +static irqreturn_t otg_oc_handler(int irq, void *_chip) +{ + int rc; + struct smbchg_chip *chip = _chip; + s64 elapsed_us = ktime_us_delta(ktime_get(), chip->otg_enable_time); + + pr_smb(PR_INTERRUPT, "triggered\n"); + + if (chip->schg_version == QPNP_SCHG_LITE) { + pr_warn("OTG OC triggered - OTG disabled\n"); + return IRQ_HANDLED; + } + + if (elapsed_us > OTG_OC_RETRY_DELAY_US) + chip->otg_retries = 0; + + /* + * Due to a HW bug in the PMI8994 charger, the current inrush that + * occurs when connecting certain OTG devices can cause the OTG + * overcurrent protection to trip. + * + * The work around is to try reenabling the OTG when getting an + * overcurrent interrupt once. + */ + if (chip->otg_retries < NUM_OTG_RETRIES) { + chip->otg_retries += 1; + pr_smb(PR_STATUS, + "Retrying OTG enable. Try #%d, elapsed_us %lld\n", + chip->otg_retries, elapsed_us); + rc = otg_oc_reset(chip); + if (rc) + pr_err("Failed to reset OTG OC state rc=%d\n", rc); + chip->otg_enable_time = ktime_get(); + } + return IRQ_HANDLED; +} + +/** + * otg_fail_handler() - called when the usb otg fails + * (when vbat < OTG UVLO threshold) + */ +static irqreturn_t otg_fail_handler(int irq, void *_chip) +{ + pr_smb(PR_INTERRUPT, "triggered\n"); + return IRQ_HANDLED; +} + +/** + * aicl_done_handler() - called when the usb AICL algorithm is finished + * and a current is set. + */ +static irqreturn_t aicl_done_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + bool usb_present = is_usb_present(chip); + int aicl_level = smbchg_get_aicl_level_ma(chip); + + pr_smb(PR_INTERRUPT, "triggered, aicl: %d\n", aicl_level); + + increment_aicl_count(chip); + + if (usb_present && !chip->parallel.use_parallel_aicl) + smbchg_parallel_usb_check_ok(chip); + + if (chip->aicl_complete) + power_supply_changed(&chip->batt_psy); + + return IRQ_HANDLED; +} + +/** + * usbid_change_handler() - called when the usb RID changes. + * This is used mostly for detecting OTG + */ +static irqreturn_t usbid_change_handler(int irq, void *_chip) +{ + struct smbchg_chip *chip = _chip; + bool otg_present; + + pr_smb(PR_INTERRUPT, "triggered\n"); + + otg_present = is_otg_present(chip); + if (chip->usb_psy) { + pr_smb(PR_MISC, "setting usb psy OTG = %d\n", + otg_present ? 1 : 0); + power_supply_set_usb_otg(chip->usb_psy, otg_present ? 1 : 0); + } + if (otg_present) + pr_smb(PR_STATUS, "OTG detected\n"); + + /* update FG */ + set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS, + get_prop_batt_status(chip)); + + return IRQ_HANDLED; +} + +static int determine_initial_status(struct smbchg_chip *chip) +{ + union power_supply_propval type = {0, }; + + /* + * It is okay to read the interrupt status here since + * interrupts aren't requested. reading interrupt status + * clears the interrupt so be careful to read interrupt + * status only in interrupt handling code + */ + + batt_pres_handler(0, chip); + if (chip->typec_psy) { + get_property_from_typec(chip, POWER_SUPPLY_PROP_TYPE, &type); + update_typec_otg_status(chip, type.intval, true); + } else { + usbid_change_handler(0, chip); + } + + chip->usb_present = is_usb_present(chip); + chip->dc_present = is_dc_present(chip); + + if (chip->usb_present) { + pr_smb(PR_MISC, "setting usb psy dp=f dm=f\n"); + power_supply_set_dp_dm(chip->usb_psy, + POWER_SUPPLY_DP_DM_DPF_DMF); + handle_usb_insertion(chip); + } else { + handle_usb_removal(chip); + } + + return 0; +} + +static int prechg_time[] = { + 24, + 48, + 96, + 192, +}; +static int chg_time[] = { + 192, + 384, + 768, + 1536, +}; + +enum bpd_type { + BPD_TYPE_BAT_NONE, + BPD_TYPE_BAT_ID, + BPD_TYPE_BAT_THM, + BPD_TYPE_BAT_THM_BAT_ID, + BPD_TYPE_DEFAULT, +}; + +static const char * const bpd_label[] = { + [BPD_TYPE_BAT_NONE] = "bpd_none", + [BPD_TYPE_BAT_ID] = "bpd_id", + [BPD_TYPE_BAT_THM] = "bpd_thm", + [BPD_TYPE_BAT_THM_BAT_ID] = "bpd_thm_id", +}; + +static inline int get_bpd(const char *name) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(bpd_label); i++) { + if (strcmp(bpd_label[i], name) == 0) + return i; + } + return -EINVAL; +} + +#define REVISION1_REG 0x0 +#define DIG_MINOR 0 +#define DIG_MAJOR 1 +#define ANA_MINOR 2 +#define ANA_MAJOR 3 +#define CHGR_CFG1 0xFB +#define RECHG_THRESHOLD_SRC_BIT BIT(1) +#define TERM_I_SRC_BIT BIT(2) +#define TERM_SRC_FG BIT(2) +#define CHG_INHIB_CFG_REG 0xF7 +#define CHG_INHIBIT_50MV_VAL 0x00 +#define CHG_INHIBIT_100MV_VAL 0x01 +#define CHG_INHIBIT_200MV_VAL 0x02 +#define CHG_INHIBIT_300MV_VAL 0x03 +#define CHG_INHIBIT_MASK 0x03 +#define USE_REGISTER_FOR_CURRENT BIT(2) +#define CHGR_CFG2 0xFC +#define CHG_EN_SRC_BIT BIT(7) +#define CHG_EN_POLARITY_BIT BIT(6) +#define P2F_CHG_TRAN BIT(5) +#define CHG_BAT_OV_ECC BIT(4) +#define I_TERM_BIT BIT(3) +#define AUTO_RECHG_BIT BIT(2) +#define CHARGER_INHIBIT_BIT BIT(0) +#define USB51_COMMAND_POL BIT(2) +#define USB51AC_CTRL BIT(1) +#define TR_8OR32B 0xFE +#define BUCK_8_16_FREQ_BIT BIT(0) +#define BM_CFG 0xF3 +#define BATT_MISSING_ALGO_BIT BIT(2) +#define BMD_PIN_SRC_MASK SMB_MASK(1, 0) +#define PIN_SRC_SHIFT 0 +#define CHGR_CFG 0xFF +#define RCHG_LVL_BIT BIT(0) +#define VCHG_EN_BIT BIT(1) +#define VCHG_INPUT_CURRENT_BIT BIT(3) +#define CFG_AFVC 0xF6 +#define VFLOAT_COMP_ENABLE_MASK SMB_MASK(2, 0) +#define TR_RID_REG 0xFA +#define FG_INPUT_FET_DELAY_BIT BIT(3) +#define TRIM_OPTIONS_7_0 0xF6 +#define INPUT_MISSING_POLLER_EN_BIT BIT(3) +#define CHGR_CCMP_CFG 0xFA +#define JEITA_TEMP_HARD_LIMIT_BIT BIT(5) +#define HVDCP_ADAPTER_SEL_MASK SMB_MASK(5, 4) +#define HVDCP_ADAPTER_SEL_9V_BIT BIT(4) +#define HVDCP_AUTH_ALG_EN_BIT BIT(6) +#define CMD_APSD 0x41 +#define APSD_RERUN_BIT BIT(0) +#define OTG_CFG 0xF1 +#define HICCUP_ENABLED_BIT BIT(6) +#define OTG_PIN_POLARITY_BIT BIT(4) +#define OTG_PIN_ACTIVE_LOW BIT(4) +#define OTG_EN_CTRL_MASK SMB_MASK(3, 2) +#define OTG_PIN_CTRL_RID_DIS 0x04 +#define OTG_CMD_CTRL_RID_EN 0x08 +#define AICL_ADC_BIT BIT(6) +static void batt_ov_wa_check(struct smbchg_chip *chip) +{ + int rc; + u8 reg; + + /* disable-'battery OV disables charging' feature */ + rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG2, + CHG_BAT_OV_ECC, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set chgr_cfg2 rc=%d\n", rc); + return; + } + + /* + * if battery OV is set: + * restart charging by disable/enable charging + */ + rc = smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't read Battery RT status rc = %d\n", rc); + return; + } + + if (reg & BAT_OV_BIT) { + rc = smbchg_charging_en(chip, false); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't disable charging: rc = %d\n", rc); + return; + } + + /* delay for charging-disable to take affect */ + msleep(200); + + rc = smbchg_charging_en(chip, true); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't enable charging: rc = %d\n", rc); + return; + } + } +} + +static int smbchg_hw_init(struct smbchg_chip *chip) +{ + int rc, i; + u8 reg, mask; + + rc = smbchg_read(chip, chip->revision, + chip->misc_base + REVISION1_REG, 4); + if (rc < 0) { + dev_err(chip->dev, "Couldn't read revision rc=%d\n", + rc); + return rc; + } + pr_smb(PR_STATUS, "Charger Revision DIG: %d.%d; ANA: %d.%d\n", + chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR], + chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR]); + + /* Setup 9V HVDCP */ + if (chip->hvdcp_not_supported) { + rc = vote(chip->hvdcp_enable_votable, HVDCP_PMIC_VOTER, + true, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't disable HVDCP rc=%d\n", + rc); + return rc; + } + } else { + rc = vote(chip->hvdcp_enable_votable, HVDCP_PMIC_VOTER, + true, 1); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't disable HVDCP vote rc=%d\n", rc); + return rc; + } + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_9V); + if (rc < 0) { + pr_err("Couldn't set hvdcp config in chgpath_chg rc=%d\n", + rc); + return rc; + } + } + + if (chip->aicl_rerun_period_s > 0) { + rc = smbchg_set_aicl_rerun_period_s(chip, + chip->aicl_rerun_period_s); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set AICL rerun timer rc=%d\n", + rc); + return rc; + } + } + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + 0xFF, 0x00); + if (rc < 0) + dev_err(chip->dev, "Couldn't set only 5v OVP 6.4V rc=%d\n", + rc); + + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + TR_RID_REG, + FG_INPUT_FET_DELAY_BIT, FG_INPUT_FET_DELAY_BIT); + if (rc < 0) { + dev_err(chip->dev, "Couldn't disable fg input fet delay rc=%d\n", + rc); + return rc; + } + + rc = smbchg_sec_masked_write(chip, chip->misc_base + TRIM_OPTIONS_7_0, + INPUT_MISSING_POLLER_EN_BIT, + INPUT_MISSING_POLLER_EN_BIT); + if (rc < 0) { + dev_err(chip->dev, "Couldn't enable input missing poller rc=%d\n", + rc); + return rc; + } + + /* + * Do not force using current from the register i.e. use auto + * power source detect (APSD) mA ratings for the initial current values. + * + * If this is set, AICL will not rerun at 9V for HVDCPs + */ + rc = smbchg_masked_write(chip, chip->usb_chgpth_base + CMD_IL, + USE_REGISTER_FOR_CURRENT, 0); + + if (rc < 0) { + dev_err(chip->dev, "Couldn't set input limit cmd rc=%d\n", rc); + return rc; + } + + /* + * set chg en by cmd register, set chg en by writing bit 1, + * enable auto pre to fast, enable auto recharge by default. + * enable current termination and charge inhibition based on + * the device tree configuration. + */ + rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG2, + CHG_EN_SRC_BIT | CHG_EN_POLARITY_BIT | P2F_CHG_TRAN + | I_TERM_BIT | AUTO_RECHG_BIT | CHARGER_INHIBIT_BIT, + CHG_EN_POLARITY_BIT + | (chip->chg_inhibit_en ? CHARGER_INHIBIT_BIT : 0) + | (chip->iterm_disabled ? I_TERM_BIT : 0)); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set chgr_cfg2 rc=%d\n", rc); + return rc; + } + + /* + * enable battery charging to make sure it hasn't been changed earlier + * by the bootloader. + */ + rc = smbchg_charging_en(chip, true); + if (rc < 0) { + dev_err(chip->dev, "Couldn't enable battery charging=%d\n", rc); + return rc; + } + + /* + * Based on the configuration, use the analog sensors or the fuelgauge + * adc for recharge threshold source. + */ + + if (chip->chg_inhibit_source_fg) + rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG1, + TERM_I_SRC_BIT | RECHG_THRESHOLD_SRC_BIT, + TERM_SRC_FG | RECHG_THRESHOLD_SRC_BIT); + else + rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG1, + TERM_I_SRC_BIT | RECHG_THRESHOLD_SRC_BIT, 0); + + if (rc < 0) { + dev_err(chip->dev, "Couldn't set chgr_cfg2 rc=%d\n", rc); + return rc; + } + + /* + * control USB suspend via command bits and set correct 100/500mA + * polarity on the usb current + */ + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, + USB51_COMMAND_POL | USB51AC_CTRL, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set usb_chgpth cfg rc=%d\n", rc); + return rc; + } + + check_battery_type(chip); + + /* set the float voltage */ + if (chip->vfloat_mv != -EINVAL) { + rc = smbchg_float_voltage_set(chip, chip->vfloat_mv); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set float voltage rc = %d\n", rc); + return rc; + } + pr_smb(PR_STATUS, "set vfloat to %d\n", chip->vfloat_mv); + } + + /* set the fast charge current compensation */ + if (chip->fastchg_current_comp != -EINVAL) { + rc = smbchg_fastchg_current_comp_set(chip, + chip->fastchg_current_comp); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set fastchg current comp rc = %d\n", + rc); + return rc; + } + pr_smb(PR_STATUS, "set fastchg current comp to %d\n", + chip->fastchg_current_comp); + } + + /* set the float voltage compensation */ + if (chip->float_voltage_comp != -EINVAL) { + rc = smbchg_float_voltage_comp_set(chip, + chip->float_voltage_comp); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set float voltage comp rc = %d\n", + rc); + return rc; + } + pr_smb(PR_STATUS, "set float voltage comp to %d\n", + chip->float_voltage_comp); + } + + /* set iterm */ + if (chip->iterm_ma != -EINVAL) { + if (chip->iterm_disabled) { + dev_err(chip->dev, "Error: Both iterm_disabled and iterm_ma set\n"); + return -EINVAL; + } else { + smbchg_iterm_set(chip, chip->iterm_ma); + } + } + + /* set the safety time voltage */ + if (chip->safety_time != -EINVAL) { + reg = (chip->safety_time > 0 ? 0 : SFT_TIMER_DISABLE_BIT) | + (chip->prechg_safety_time > 0 + ? 0 : PRECHG_SFT_TIMER_DISABLE_BIT); + + for (i = 0; i < ARRAY_SIZE(chg_time); i++) { + if (chip->safety_time <= chg_time[i]) { + reg |= i << SAFETY_TIME_MINUTES_SHIFT; + break; + } + } + for (i = 0; i < ARRAY_SIZE(prechg_time); i++) { + if (chip->prechg_safety_time <= prechg_time[i]) { + reg |= i; + break; + } + } + + rc = smbchg_sec_masked_write(chip, + chip->chgr_base + SFT_CFG, + SFT_EN_MASK | SFT_TO_MASK | + (chip->prechg_safety_time > 0 + ? PRECHG_SFT_TO_MASK : 0), reg); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set safety timer rc = %d\n", + rc); + return rc; + } + chip->safety_timer_en = true; + } else { + rc = smbchg_read(chip, ®, chip->chgr_base + SFT_CFG, 1); + if (rc < 0) + dev_err(chip->dev, "Unable to read SFT_CFG rc = %d\n", + rc); + else if (!(reg & SFT_EN_MASK)) + chip->safety_timer_en = true; + } + + /* configure jeita temperature hard limit */ + if (chip->jeita_temp_hard_limit >= 0) { + rc = smbchg_sec_masked_write(chip, + chip->chgr_base + CHGR_CCMP_CFG, + JEITA_TEMP_HARD_LIMIT_BIT, + chip->jeita_temp_hard_limit + ? 0 : JEITA_TEMP_HARD_LIMIT_BIT); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't set jeita temp hard limit rc = %d\n", + rc); + return rc; + } + } + + /* make the buck switch faster to prevent some vbus oscillation */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + TR_8OR32B, + BUCK_8_16_FREQ_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set buck frequency rc = %d\n", rc); + return rc; + } + + /* battery missing detection */ + mask = BATT_MISSING_ALGO_BIT; + reg = chip->bmd_algo_disabled ? 0 : BATT_MISSING_ALGO_BIT; + if (chip->bmd_pin_src < BPD_TYPE_DEFAULT) { + mask |= BMD_PIN_SRC_MASK; + reg |= chip->bmd_pin_src << PIN_SRC_SHIFT; + } + rc = smbchg_sec_masked_write(chip, + chip->bat_if_base + BM_CFG, mask, reg); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set batt_missing config = %d\n", + rc); + return rc; + } + + if (chip->vchg_adc_channel != -EINVAL) { + /* configure and enable VCHG */ + rc = smbchg_sec_masked_write(chip, chip->chgr_base + CHGR_CFG, + VCHG_INPUT_CURRENT_BIT | VCHG_EN_BIT, + VCHG_INPUT_CURRENT_BIT | VCHG_EN_BIT); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set recharge rc = %d\n", + rc); + return rc; + } + } + + smbchg_charging_status_change(chip); + + vote(chip->usb_suspend_votable, USER_EN_VOTER, !chip->chg_enabled, 0); + vote(chip->dc_suspend_votable, USER_EN_VOTER, !chip->chg_enabled, 0); + /* resume threshold */ + if (chip->resume_delta_mv != -EINVAL) { + + /* + * Configure only if the recharge threshold source is not + * fuel gauge ADC. + */ + if (!chip->chg_inhibit_source_fg) { + if (chip->resume_delta_mv < 100) + reg = CHG_INHIBIT_50MV_VAL; + else if (chip->resume_delta_mv < 200) + reg = CHG_INHIBIT_100MV_VAL; + else if (chip->resume_delta_mv < 300) + reg = CHG_INHIBIT_200MV_VAL; + else + reg = CHG_INHIBIT_300MV_VAL; + + rc = smbchg_sec_masked_write(chip, + chip->chgr_base + CHG_INHIB_CFG_REG, + CHG_INHIBIT_MASK, reg); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set inhibit val rc = %d\n", + rc); + return rc; + } + } + + rc = smbchg_sec_masked_write(chip, + chip->chgr_base + CHGR_CFG, + RCHG_LVL_BIT, + (chip->resume_delta_mv + < chip->tables.rchg_thr_mv) + ? 0 : RCHG_LVL_BIT); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set recharge rc = %d\n", + rc); + return rc; + } + } + + /* DC path current settings */ + if (chip->dc_psy_type != -EINVAL) { + rc = vote(chip->dc_icl_votable, PSY_ICL_VOTER, true, + chip->dc_target_current_ma); + if (rc < 0) { + dev_err(chip->dev, + "Couldn't vote for initial DC ICL rc=%d\n", rc); + return rc; + } + } + + + /* + * on some devices the battery is powered via external sources which + * could raise its voltage above the float voltage. smbchargers go + * in to reverse boost in such a situation and the workaround is to + * disable float voltage compensation (note that the battery will appear + * hot/cold when powered via external source). + */ + if (chip->soft_vfloat_comp_disabled) { + rc = smbchg_sec_masked_write(chip, chip->chgr_base + CFG_AFVC, + VFLOAT_COMP_ENABLE_MASK, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't disable soft vfloat rc = %d\n", + rc); + return rc; + } + } + + rc = vote(chip->fcc_votable, BATT_TYPE_FCC_VOTER, true, + chip->cfg_fastchg_current_ma); + if (rc < 0) { + dev_err(chip->dev, "Couldn't vote fastchg ma rc = %d\n", rc); + return rc; + } + + rc = smbchg_read(chip, &chip->original_usbin_allowance, + chip->usb_chgpth_base + USBIN_CHGR_CFG, 1); + if (rc < 0) + dev_err(chip->dev, "Couldn't read usb allowance rc=%d\n", rc); + + if (chip->wipower_dyn_icl_avail) { + rc = smbchg_wipower_ilim_config(chip, + &(chip->wipower_default.entries[0])); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set default wipower ilim = %d\n", + rc); + return rc; + } + } + /* unsuspend dc path, it could be suspended by the bootloader */ + rc = smbchg_dc_suspend(chip, 0); + if (rc < 0) { + dev_err(chip->dev, "Couldn't unsuspend dc path= %d\n", rc); + return rc; + } + + if (chip->force_aicl_rerun) { + /* vote to enable hw aicl */ + rc = vote(chip->hw_aicl_rerun_enable_indirect_votable, + DEFAULT_CONFIG_HW_AICL_VOTER, true, 0); + if (rc < 0) { + pr_err("Couldn't vote enable hw aicl rerun rc=%d\n", + rc); + return rc; + } + } + + if (chip->schg_version == QPNP_SCHG_LITE) { + /* enable OTG hiccup mode */ + rc = smbchg_sec_masked_write(chip, chip->otg_base + OTG_CFG, + HICCUP_ENABLED_BIT, HICCUP_ENABLED_BIT); + if (rc < 0) + dev_err(chip->dev, "Couldn't set OTG OC config rc = %d\n", + rc); + } + + if (chip->otg_pinctrl) { + /* configure OTG enable to pin control active low */ + rc = smbchg_sec_masked_write(chip, chip->otg_base + OTG_CFG, + OTG_PIN_POLARITY_BIT | OTG_EN_CTRL_MASK, + OTG_PIN_ACTIVE_LOW | OTG_PIN_CTRL_RID_DIS); + if (rc < 0) { + dev_err(chip->dev, "Couldn't set OTG EN config rc = %d\n", + rc); + return rc; + } + } + + if (chip->wa_flags & SMBCHG_BATT_OV_WA) + batt_ov_wa_check(chip); + + /* turn off AICL adc for improved accuracy */ + rc = smbchg_sec_masked_write(chip, + chip->misc_base + MISC_TRIM_OPT_15_8, AICL_ADC_BIT, 0); + if (rc) + pr_err("Couldn't write to MISC_TRIM_OPTIONS_15_8 rc=%d\n", + rc); + + rc = configure_icl_control(chip, ICL_BUF_SYSON_LDO_VAL); + if (rc) + dev_err(chip->dev, "Couldn't switch to Syson LDO, rc=%d\n", + rc); + return rc; +} + +static struct of_device_id smbchg_match_table[] = { + { + .compatible = "qcom,qpnp-smbcharger", + }, + { }, +}; + +#define DC_MA_MIN 300 +#define DC_MA_MAX 2000 +#define OF_PROP_READ(chip, prop, dt_property, retval, optional) \ +do { \ + if (retval) \ + break; \ + if (optional) \ + prop = -EINVAL; \ + \ + retval = of_property_read_u32(chip->spmi->dev.of_node, \ + "qcom," dt_property , \ + &prop); \ + \ + if ((retval == -EINVAL) && optional) \ + retval = 0; \ + else if (retval) \ + dev_err(chip->dev, "Error reading " #dt_property \ + " property rc = %d\n", rc); \ +} while (0) + +#define ILIM_ENTRIES 3 +#define VOLTAGE_RANGE_ENTRIES 2 +#define RANGE_ENTRY (ILIM_ENTRIES + VOLTAGE_RANGE_ENTRIES) +static int smb_parse_wipower_map_dt(struct smbchg_chip *chip, + struct ilim_map *map, char *property) +{ + struct device_node *node = chip->dev->of_node; + int total_elements, size; + struct property *prop; + const __be32 *data; + int num, i; + + prop = of_find_property(node, property, &size); + if (!prop) { + dev_err(chip->dev, "%s missing\n", property); + return -EINVAL; + } + + total_elements = size / sizeof(int); + if (total_elements % RANGE_ENTRY) { + dev_err(chip->dev, "%s table not in multiple of %d, total elements = %d\n", + property, RANGE_ENTRY, total_elements); + return -EINVAL; + } + + data = prop->value; + num = total_elements / RANGE_ENTRY; + map->entries = devm_kzalloc(chip->dev, + num * sizeof(struct ilim_entry), GFP_KERNEL); + if (!map->entries) { + dev_err(chip->dev, "kzalloc failed for default ilim\n"); + return -ENOMEM; + } + for (i = 0; i < num; i++) { + map->entries[i].vmin_uv = be32_to_cpup(data++); + map->entries[i].vmax_uv = be32_to_cpup(data++); + map->entries[i].icl_pt_ma = be32_to_cpup(data++); + map->entries[i].icl_lv_ma = be32_to_cpup(data++); + map->entries[i].icl_hv_ma = be32_to_cpup(data++); + } + map->num = num; + return 0; +} + +static int smb_parse_wipower_dt(struct smbchg_chip *chip) +{ + int rc = 0; + + chip->wipower_dyn_icl_avail = false; + + if (!chip->vadc_dev) + goto err; + + rc = smb_parse_wipower_map_dt(chip, &chip->wipower_default, + "qcom,wipower-default-ilim-map"); + if (rc) { + dev_err(chip->dev, "failed to parse wipower-pt-ilim-map rc = %d\n", + rc); + goto err; + } + + rc = smb_parse_wipower_map_dt(chip, &chip->wipower_pt, + "qcom,wipower-pt-ilim-map"); + if (rc) { + dev_err(chip->dev, "failed to parse wipower-pt-ilim-map rc = %d\n", + rc); + goto err; + } + + rc = smb_parse_wipower_map_dt(chip, &chip->wipower_div2, + "qcom,wipower-div2-ilim-map"); + if (rc) { + dev_err(chip->dev, "failed to parse wipower-div2-ilim-map rc = %d\n", + rc); + goto err; + } + chip->wipower_dyn_icl_avail = true; + return 0; +err: + chip->wipower_default.num = 0; + chip->wipower_pt.num = 0; + chip->wipower_default.num = 0; + if (chip->wipower_default.entries) + devm_kfree(chip->dev, chip->wipower_default.entries); + if (chip->wipower_pt.entries) + devm_kfree(chip->dev, chip->wipower_pt.entries); + if (chip->wipower_div2.entries) + devm_kfree(chip->dev, chip->wipower_div2.entries); + chip->wipower_default.entries = NULL; + chip->wipower_pt.entries = NULL; + chip->wipower_div2.entries = NULL; + chip->vadc_dev = NULL; + return rc; +} + +#define DEFAULT_VLED_MAX_UV 3500000 +#define DEFAULT_FCC_MA 2500 +static int smb_parse_dt(struct smbchg_chip *chip) +{ + int rc = 0, ocp_thresh = -EINVAL; + struct device_node *node = chip->dev->of_node; + const char *dc_psy_type, *bpd; + + if (!node) { + dev_err(chip->dev, "device tree info. missing\n"); + return -EINVAL; + } + + /* read optional u32 properties */ + OF_PROP_READ(chip, ocp_thresh, + "ibat-ocp-threshold-ua", rc, 1); + if (ocp_thresh >= 0) + smbchg_ibat_ocp_threshold_ua = ocp_thresh; + OF_PROP_READ(chip, chip->iterm_ma, "iterm-ma", rc, 1); + OF_PROP_READ(chip, chip->cfg_fastchg_current_ma, + "fastchg-current-ma", rc, 1); + if (chip->cfg_fastchg_current_ma == -EINVAL) + chip->cfg_fastchg_current_ma = DEFAULT_FCC_MA; + OF_PROP_READ(chip, chip->vfloat_mv, "float-voltage-mv", rc, 1); + OF_PROP_READ(chip, chip->safety_time, "charging-timeout-mins", rc, 1); + OF_PROP_READ(chip, chip->vled_max_uv, "vled-max-uv", rc, 1); + if (chip->vled_max_uv < 0) + chip->vled_max_uv = DEFAULT_VLED_MAX_UV; + OF_PROP_READ(chip, chip->rpara_uohm, "rparasitic-uohm", rc, 1); + if (chip->rpara_uohm < 0) + chip->rpara_uohm = 0; + OF_PROP_READ(chip, chip->prechg_safety_time, "precharging-timeout-mins", + rc, 1); + OF_PROP_READ(chip, chip->fastchg_current_comp, "fastchg-current-comp", + rc, 1); + OF_PROP_READ(chip, chip->float_voltage_comp, "float-voltage-comp", + rc, 1); + if (chip->safety_time != -EINVAL && + (chip->safety_time > chg_time[ARRAY_SIZE(chg_time) - 1])) { + dev_err(chip->dev, "Bad charging-timeout-mins %d\n", + chip->safety_time); + return -EINVAL; + } + if (chip->prechg_safety_time != -EINVAL && + (chip->prechg_safety_time > + prechg_time[ARRAY_SIZE(prechg_time) - 1])) { + dev_err(chip->dev, "Bad precharging-timeout-mins %d\n", + chip->prechg_safety_time); + return -EINVAL; + } + OF_PROP_READ(chip, chip->resume_delta_mv, "resume-delta-mv", rc, 1); + OF_PROP_READ(chip, chip->parallel.min_current_thr_ma, + "parallel-usb-min-current-ma", rc, 1); + OF_PROP_READ(chip, chip->parallel.min_9v_current_thr_ma, + "parallel-usb-9v-min-current-ma", rc, 1); + OF_PROP_READ(chip, chip->parallel.allowed_lowering_ma, + "parallel-allowed-lowering-ma", rc, 1); + if (chip->parallel.min_current_thr_ma != -EINVAL + && chip->parallel.min_9v_current_thr_ma != -EINVAL) + chip->parallel.avail = true; + + OF_PROP_READ(chip, chip->max_pulse_allowed, + "max-pulse-allowed", rc, 1); + chip->parallel.use_parallel_aicl = of_property_read_bool(node, + "qcom,use-parallel-aicl"); + OF_PROP_READ(chip, chip->parallel.min_main_icl_ma, + "parallel-min-main-icl-ma", rc, 1); + /* + * use the dt values if they exist, otherwise do not touch the params + */ + of_property_read_u32(chip->spmi->dev.of_node, + "qcom,parallel-main-chg-fcc-percent", + &smbchg_main_chg_fcc_percent); + of_property_read_u32(chip->spmi->dev.of_node, + "qcom,parallel-main-chg-icl-percent", + &smbchg_main_chg_icl_percent); + pr_smb(PR_STATUS, "parallel usb thr: %d, 9v thr: %d\n", + chip->parallel.min_current_thr_ma, + chip->parallel.min_9v_current_thr_ma); + OF_PROP_READ(chip, chip->jeita_temp_hard_limit, + "jeita-temp-hard-limit", rc, 1); + OF_PROP_READ(chip, chip->aicl_rerun_period_s, + "aicl-rerun-period-s", rc, 1); + OF_PROP_READ(chip, chip->vchg_adc_channel, + "vchg-adc-channel-id", rc, 1); + + /* read boolean configuration properties */ + chip->use_vfloat_adjustments = of_property_read_bool(node, + "qcom,autoadjust-vfloat"); + chip->bmd_algo_disabled = of_property_read_bool(node, + "qcom,bmd-algo-disabled"); + chip->iterm_disabled = of_property_read_bool(node, + "qcom,iterm-disabled"); + chip->soft_vfloat_comp_disabled = of_property_read_bool(node, + "qcom,soft-vfloat-comp-disabled"); + chip->chg_enabled = !(of_property_read_bool(node, + "qcom,charging-disabled")); + chip->charge_unknown_battery = of_property_read_bool(node, + "qcom,charge-unknown-battery"); + chip->chg_inhibit_en = of_property_read_bool(node, + "qcom,chg-inhibit-en"); + chip->chg_inhibit_source_fg = of_property_read_bool(node, + "qcom,chg-inhibit-fg"); + chip->low_volt_dcin = of_property_read_bool(node, + "qcom,low-volt-dcin"); + chip->force_aicl_rerun = of_property_read_bool(node, + "qcom,force-aicl-rerun"); + chip->skip_usb_suspend_for_fake_battery = of_property_read_bool(node, + "qcom,skip-usb-suspend-for-fake-battery"); + + /* parse the battery missing detection pin source */ + rc = of_property_read_string(chip->spmi->dev.of_node, + "qcom,bmd-pin-src", &bpd); + if (rc) { + /* Select BAT_THM as default BPD scheme */ + chip->bmd_pin_src = BPD_TYPE_DEFAULT; + rc = 0; + } else { + chip->bmd_pin_src = get_bpd(bpd); + if (chip->bmd_pin_src < 0) { + dev_err(chip->dev, + "failed to determine bpd schema %d\n", rc); + return rc; + } + } + + /* parse the dc power supply configuration */ + rc = of_property_read_string(node, "qcom,dc-psy-type", &dc_psy_type); + if (rc) { + chip->dc_psy_type = -EINVAL; + rc = 0; + } else { + if (strcmp(dc_psy_type, "Mains") == 0) + chip->dc_psy_type = POWER_SUPPLY_TYPE_MAINS; + else if (strcmp(dc_psy_type, "Wireless") == 0) + chip->dc_psy_type = POWER_SUPPLY_TYPE_WIRELESS; + else if (strcmp(dc_psy_type, "Wipower") == 0) + chip->dc_psy_type = POWER_SUPPLY_TYPE_WIPOWER; + } + if (chip->dc_psy_type != -EINVAL) { + OF_PROP_READ(chip, chip->dc_target_current_ma, + "dc-psy-ma", rc, 0); + if (rc) + return rc; + if (chip->dc_target_current_ma < DC_MA_MIN + || chip->dc_target_current_ma > DC_MA_MAX) { + dev_err(chip->dev, "Bad dc mA %d\n", + chip->dc_target_current_ma); + return -EINVAL; + } + } + + if (chip->dc_psy_type == POWER_SUPPLY_TYPE_WIPOWER) + smb_parse_wipower_dt(chip); + + /* read the bms power supply name */ + rc = of_property_read_string(node, "qcom,bms-psy-name", + &chip->bms_psy_name); + if (rc) + chip->bms_psy_name = NULL; + + /* read the battery power supply name */ + rc = of_property_read_string(node, "qcom,battery-psy-name", + &chip->battery_psy_name); + if (rc) + chip->battery_psy_name = "battery"; + + /* Get the charger led support property */ + chip->cfg_chg_led_sw_ctrl = + of_property_read_bool(node, "qcom,chg-led-sw-controls"); + chip->cfg_chg_led_support = + of_property_read_bool(node, "qcom,chg-led-support"); + + if (of_find_property(node, "qcom,thermal-mitigation", + &chip->thermal_levels)) { + chip->thermal_mitigation = devm_kzalloc(chip->dev, + chip->thermal_levels, + GFP_KERNEL); + + if (chip->thermal_mitigation == NULL) { + dev_err(chip->dev, "thermal mitigation kzalloc() failed.\n"); + return -ENOMEM; + } + + chip->thermal_levels /= sizeof(int); + rc = of_property_read_u32_array(node, + "qcom,thermal-mitigation", + chip->thermal_mitigation, chip->thermal_levels); + if (rc) { + dev_err(chip->dev, + "Couldn't read threm limits rc = %d\n", rc); + return rc; + } + } + + chip->skip_usb_notification + = of_property_read_bool(node, + "qcom,skip-usb-notification"); + + chip->otg_pinctrl = of_property_read_bool(node, "qcom,otg-pinctrl"); + + chip->cfg_override_usb_current = of_property_read_bool(node, + "qcom,override-usb-current"); + + return 0; +} + +#define SUBTYPE_REG 0x5 +#define SMBCHG_CHGR_SUBTYPE 0x1 +#define SMBCHG_OTG_SUBTYPE 0x8 +#define SMBCHG_BAT_IF_SUBTYPE 0x3 +#define SMBCHG_USB_CHGPTH_SUBTYPE 0x4 +#define SMBCHG_DC_CHGPTH_SUBTYPE 0x5 +#define SMBCHG_MISC_SUBTYPE 0x7 +#define SMBCHG_LITE_CHGR_SUBTYPE 0x51 +#define SMBCHG_LITE_OTG_SUBTYPE 0x58 +#define SMBCHG_LITE_BAT_IF_SUBTYPE 0x53 +#define SMBCHG_LITE_USB_CHGPTH_SUBTYPE 0x54 +#define SMBCHG_LITE_DC_CHGPTH_SUBTYPE 0x55 +#define SMBCHG_LITE_MISC_SUBTYPE 0x57 +#define REQUEST_IRQ(chip, resource, irq_num, irq_name, irq_handler, flags, rc)\ +do { \ + irq_num = spmi_get_irq_byname(chip->spmi, \ + resource, irq_name); \ + if (irq_num < 0) { \ + dev_err(chip->dev, "Unable to get " irq_name " irq\n"); \ + return -ENXIO; \ + } \ + rc = devm_request_threaded_irq(chip->dev, \ + irq_num, NULL, irq_handler, flags, irq_name, \ + chip); \ + if (rc < 0) { \ + dev_err(chip->dev, "Unable to request " irq_name " irq: %d\n",\ + rc); \ + return -ENXIO; \ + } \ +} while (0) + +static int smbchg_request_irqs(struct smbchg_chip *chip) +{ + int rc = 0; + struct resource *resource; + struct spmi_resource *spmi_resource; + u8 subtype; + struct spmi_device *spmi = chip->spmi; + unsigned long flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING + | IRQF_ONESHOT; + + spmi_for_each_container_dev(spmi_resource, chip->spmi) { + if (!spmi_resource) { + dev_err(chip->dev, "spmi resource absent\n"); + return rc; + } + + resource = spmi_get_resource(spmi, spmi_resource, + IORESOURCE_MEM, 0); + if (!(resource && resource->start)) { + dev_err(chip->dev, "node %s IO resource absent!\n", + spmi->dev.of_node->full_name); + return rc; + } + + rc = smbchg_read(chip, &subtype, + resource->start + SUBTYPE_REG, 1); + if (rc) { + dev_err(chip->dev, "Peripheral subtype read failed rc=%d\n", + rc); + return rc; + } + + switch (subtype) { + case SMBCHG_CHGR_SUBTYPE: + case SMBCHG_LITE_CHGR_SUBTYPE: + REQUEST_IRQ(chip, spmi_resource, chip->chg_error_irq, + "chg-error", chg_error_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->taper_irq, + "chg-taper-thr", taper_handler, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), rc); + disable_irq_nosync(chip->taper_irq); + REQUEST_IRQ(chip, spmi_resource, chip->chg_term_irq, + "chg-tcc-thr", chg_term_handler, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), rc); + REQUEST_IRQ(chip, spmi_resource, chip->recharge_irq, + "chg-rechg-thr", recharge_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->fastchg_irq, + "chg-p2f-thr", fastchg_handler, flags, rc); + enable_irq_wake(chip->chg_term_irq); + enable_irq_wake(chip->chg_error_irq); + enable_irq_wake(chip->fastchg_irq); + break; + case SMBCHG_BAT_IF_SUBTYPE: + case SMBCHG_LITE_BAT_IF_SUBTYPE: + REQUEST_IRQ(chip, spmi_resource, chip->batt_hot_irq, + "batt-hot", batt_hot_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->batt_warm_irq, + "batt-warm", batt_warm_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->batt_cool_irq, + "batt-cool", batt_cool_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->batt_cold_irq, + "batt-cold", batt_cold_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->batt_missing_irq, + "batt-missing", batt_pres_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->vbat_low_irq, + "batt-low", vbat_low_handler, flags, rc); + enable_irq_wake(chip->batt_hot_irq); + enable_irq_wake(chip->batt_warm_irq); + enable_irq_wake(chip->batt_cool_irq); + enable_irq_wake(chip->batt_cold_irq); + enable_irq_wake(chip->batt_missing_irq); + enable_irq_wake(chip->vbat_low_irq); + break; + case SMBCHG_USB_CHGPTH_SUBTYPE: + case SMBCHG_LITE_USB_CHGPTH_SUBTYPE: + REQUEST_IRQ(chip, spmi_resource, chip->usbin_uv_irq, + "usbin-uv", usbin_uv_handler, + flags | IRQF_EARLY_RESUME, rc); + REQUEST_IRQ(chip, spmi_resource, chip->usbin_ov_irq, + "usbin-ov", usbin_ov_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->src_detect_irq, + "usbin-src-det", + src_detect_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->aicl_done_irq, + "aicl-done", + aicl_done_handler, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), + rc); + if (chip->schg_version != QPNP_SCHG_LITE) { + REQUEST_IRQ(chip, spmi_resource, + chip->otg_fail_irq, "otg-fail", + otg_fail_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, + chip->otg_oc_irq, "otg-oc", + otg_oc_handler, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), + rc); + REQUEST_IRQ(chip, spmi_resource, + chip->usbid_change_irq, "usbid-change", + usbid_change_handler, + (IRQF_TRIGGER_FALLING | IRQF_ONESHOT), + rc); + enable_irq_wake(chip->otg_oc_irq); + enable_irq_wake(chip->usbid_change_irq); + enable_irq_wake(chip->otg_fail_irq); + } + enable_irq_wake(chip->usbin_uv_irq); + enable_irq_wake(chip->usbin_ov_irq); + enable_irq_wake(chip->src_detect_irq); + if (chip->parallel.avail && chip->usb_present) { + rc = enable_irq_wake(chip->aicl_done_irq); + chip->enable_aicl_wake = true; + } + break; + case SMBCHG_DC_CHGPTH_SUBTYPE: + case SMBCHG_LITE_DC_CHGPTH_SUBTYPE: + REQUEST_IRQ(chip, spmi_resource, chip->dcin_uv_irq, + "dcin-uv", dcin_uv_handler, flags, rc); + enable_irq_wake(chip->dcin_uv_irq); + break; + case SMBCHG_MISC_SUBTYPE: + case SMBCHG_LITE_MISC_SUBTYPE: + REQUEST_IRQ(chip, spmi_resource, chip->power_ok_irq, + "power-ok", power_ok_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, chip->chg_hot_irq, + "temp-shutdown", chg_hot_handler, flags, rc); + REQUEST_IRQ(chip, spmi_resource, + chip->wdog_timeout_irq, + "wdog-timeout", + wdog_timeout_handler, flags, rc); + enable_irq_wake(chip->chg_hot_irq); + enable_irq_wake(chip->wdog_timeout_irq); + break; + case SMBCHG_OTG_SUBTYPE: + break; + case SMBCHG_LITE_OTG_SUBTYPE: + REQUEST_IRQ(chip, spmi_resource, + chip->usbid_change_irq, "usbid-change", + usbid_change_handler, + (IRQF_TRIGGER_FALLING | IRQF_ONESHOT), + rc); + REQUEST_IRQ(chip, spmi_resource, + chip->otg_oc_irq, "otg-oc", + otg_oc_handler, + (IRQF_TRIGGER_RISING | IRQF_ONESHOT), rc); + REQUEST_IRQ(chip, spmi_resource, + chip->otg_fail_irq, "otg-fail", + otg_fail_handler, flags, rc); + enable_irq_wake(chip->usbid_change_irq); + enable_irq_wake(chip->otg_oc_irq); + enable_irq_wake(chip->otg_fail_irq); + break; + } + } + + return rc; +} + +#define REQUIRE_BASE(chip, base, rc) \ +do { \ + if (!rc && !chip->base) { \ + dev_err(chip->dev, "Missing " #base "\n"); \ + rc = -EINVAL; \ + } \ +} while (0) + +static int smbchg_parse_peripherals(struct smbchg_chip *chip) +{ + int rc = 0; + struct resource *resource; + struct spmi_resource *spmi_resource; + u8 subtype; + struct spmi_device *spmi = chip->spmi; + + spmi_for_each_container_dev(spmi_resource, chip->spmi) { + if (!spmi_resource) { + dev_err(chip->dev, "spmi resource absent\n"); + return rc; + } + + resource = spmi_get_resource(spmi, spmi_resource, + IORESOURCE_MEM, 0); + if (!(resource && resource->start)) { + dev_err(chip->dev, "node %s IO resource absent!\n", + spmi->dev.of_node->full_name); + return rc; + } + + rc = smbchg_read(chip, &subtype, + resource->start + SUBTYPE_REG, 1); + if (rc) { + dev_err(chip->dev, "Peripheral subtype read failed rc=%d\n", + rc); + return rc; + } + + switch (subtype) { + case SMBCHG_CHGR_SUBTYPE: + case SMBCHG_LITE_CHGR_SUBTYPE: + chip->chgr_base = resource->start; + break; + case SMBCHG_BAT_IF_SUBTYPE: + case SMBCHG_LITE_BAT_IF_SUBTYPE: + chip->bat_if_base = resource->start; + break; + case SMBCHG_USB_CHGPTH_SUBTYPE: + case SMBCHG_LITE_USB_CHGPTH_SUBTYPE: + chip->usb_chgpth_base = resource->start; + break; + case SMBCHG_DC_CHGPTH_SUBTYPE: + case SMBCHG_LITE_DC_CHGPTH_SUBTYPE: + chip->dc_chgpth_base = resource->start; + break; + case SMBCHG_MISC_SUBTYPE: + case SMBCHG_LITE_MISC_SUBTYPE: + chip->misc_base = resource->start; + break; + case SMBCHG_OTG_SUBTYPE: + case SMBCHG_LITE_OTG_SUBTYPE: + chip->otg_base = resource->start; + break; + } + } + + REQUIRE_BASE(chip, chgr_base, rc); + REQUIRE_BASE(chip, bat_if_base, rc); + REQUIRE_BASE(chip, usb_chgpth_base, rc); + REQUIRE_BASE(chip, dc_chgpth_base, rc); + REQUIRE_BASE(chip, misc_base, rc); + + return rc; +} + +static void dump_debug(struct smbchg_chip *chip) +{ + int pos = 1; + u8 reg; + u16 addr; + + /* charger peripheral */ + for (addr = 0xB; addr <= 0x10; addr++) + { + pos -= 1; + smbchg_read(chip, ®, chip->chgr_base + addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "CHGR Status", chip->chgr_base + addr, reg); + } + for (addr = 0xF0; addr <= 0xFF; addr++) + { + pos -= 1; + smbchg_read(chip, ®, chip->chgr_base + addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "CHGR Config", chip->chgr_base + addr, reg); + } + + /* battery interface peripheral */ + pos -= 1; + smbchg_read(chip, ®, chip->bat_if_base + RT_STS, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "BAT_IF Status", chip->bat_if_base + RT_STS, reg); + + pos-= 1; + smbchg_read(chip, ®, chip->bat_if_base + CMD_CHG_REG, 1); + pos += sprintf(chip->debug_dump + pos , "dump_reg:%s-%04X=%02X ", "BAT_IF Command", chip->bat_if_base + CMD_CHG_REG, reg); + + for (addr = 0xF0; addr <= 0xFB; addr++) + { + pos -= 1; + smbchg_read(chip, ®, chip->bat_if_base + addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "BAT_IF Config", chip->bat_if_base + addr, reg); + } + + /* usb charge path peripheral */ + for (addr = 0x7; addr <= 0x10; addr++) + { + pos -= 1; + smbchg_read(chip, ®, chip->usb_chgpth_base + addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "USB Status", chip->usb_chgpth_base + addr, reg); + } + + pos -= 1; + smbchg_read(chip, ®, chip->usb_chgpth_base + CMD_IL, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "USB Command", chip->usb_chgpth_base + CMD_IL, reg); + + for (addr = 0xF0; addr <= 0xF5; addr++) + { + pos -= 1; + smbchg_read(chip, ®, chip->usb_chgpth_base + addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "USB Config", chip->usb_chgpth_base + addr, reg); + } + + /* dc charge path peripheral */ + pos -= 1; + smbchg_read(chip, ®, chip->dc_chgpth_base + RT_STS, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "DC Status", chip->dc_chgpth_base + RT_STS, reg); + + for (addr = 0xF0; addr <= 0xF6; addr++) + { + pos -= 1; + smbchg_read(chip, ®, chip->dc_chgpth_base + addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "DC Config", chip->dc_chgpth_base + addr, reg); + } + + /* misc peripheral */ + pos -= 1; + smbchg_read(chip, ®, chip->misc_base + IDEV_STS, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "MISC Status", chip->misc_base + IDEV_STS, reg); + + pos -= 1; + smbchg_read(chip, ®, chip->misc_base + RT_STS, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "MISC Status", chip->misc_base + RT_STS, reg); + + for (addr = 0xF0; addr <= 0xF3; addr++) + { + pos -= 1; + smbchg_read(chip, ®, addr, 1); + pos += sprintf(chip->debug_dump + pos, "dump_reg:%s-%04X=%02X ", "MISC CFG", chip->misc_base + addr, reg); + } + + pr_err("%s\n", chip->debug_dump); +} + +static inline void dump_reg(struct smbchg_chip *chip, u16 addr, + const char *name) +{ + u8 reg; + + smbchg_read(chip, ®, addr, 1); + pr_smb(PR_DUMP, "%s - %04X = %02X\n", name, addr, reg); +} + +/* dumps useful registers for debug */ +static void dump_regs(struct smbchg_chip *chip) +{ + u16 addr; + + /* charger peripheral */ + for (addr = 0xB; addr <= 0x10; addr++) + dump_reg(chip, chip->chgr_base + addr, "CHGR Status"); + for (addr = 0xF0; addr <= 0xFF; addr++) + dump_reg(chip, chip->chgr_base + addr, "CHGR Config"); + /* battery interface peripheral */ + dump_reg(chip, chip->bat_if_base + RT_STS, "BAT_IF Status"); + dump_reg(chip, chip->bat_if_base + CMD_CHG_REG, "BAT_IF Command"); + for (addr = 0xF0; addr <= 0xFB; addr++) + dump_reg(chip, chip->bat_if_base + addr, "BAT_IF Config"); + /* usb charge path peripheral */ + for (addr = 0x7; addr <= 0x10; addr++) + dump_reg(chip, chip->usb_chgpth_base + addr, "USB Status"); + dump_reg(chip, chip->usb_chgpth_base + CMD_IL, "USB Command"); + for (addr = 0xF0; addr <= 0xF5; addr++) + dump_reg(chip, chip->usb_chgpth_base + addr, "USB Config"); + /* dc charge path peripheral */ + dump_reg(chip, chip->dc_chgpth_base + RT_STS, "DC Status"); + for (addr = 0xF0; addr <= 0xF6; addr++) + dump_reg(chip, chip->dc_chgpth_base + addr, "DC Config"); + /* misc peripheral */ + dump_reg(chip, chip->misc_base + IDEV_STS, "MISC Status"); + dump_reg(chip, chip->misc_base + RT_STS, "MISC Status"); + for (addr = 0xF0; addr <= 0xF3; addr++) + dump_reg(chip, chip->misc_base + addr, "MISC CFG"); +} + +static int create_debugfs_entries(struct smbchg_chip *chip) +{ + struct dentry *ent; + + chip->debug_root = debugfs_create_dir("qpnp-smbcharger", NULL); + if (!chip->debug_root) { + dev_err(chip->dev, "Couldn't create debug dir\n"); + return -EINVAL; + } + + ent = debugfs_create_file("force_dcin_icl_check", + S_IFREG | S_IWUSR | S_IRUGO, + chip->debug_root, chip, + &force_dcin_icl_ops); + if (!ent) { + dev_err(chip->dev, + "Couldn't create force dcin icl check file\n"); + return -EINVAL; + } + return 0; +} + +static int smbchg_check_chg_version(struct smbchg_chip *chip) +{ + struct pmic_revid_data *pmic_rev_id; + struct device_node *revid_dev_node; + int rc; + + revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node, + "qcom,pmic-revid", 0); + if (!revid_dev_node) { + pr_err("Missing qcom,pmic-revid property - driver failed\n"); + return -EINVAL; + } + + pmic_rev_id = get_revid_data(revid_dev_node); + if (IS_ERR(pmic_rev_id)) { + rc = PTR_ERR(revid_dev_node); + if (rc != -EPROBE_DEFER) + pr_err("Unable to get pmic_revid rc=%d\n", rc); + return rc; + } + + switch (pmic_rev_id->pmic_subtype) { + case PMI8994: + chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA + | SMBCHG_BATT_OV_WA + | SMBCHG_CC_ESR_WA + | SMBCHG_RESTART_WA + | SMBCHG_ICL_CONTROL_WA; + use_pmi8994_tables(chip); + chip->schg_version = QPNP_SCHG; + break; + case PMI8950: + chip->wa_flags |= SMBCHG_RESTART_WA; + case PMI8937: + /* fall through */ + case PMI8940: + chip->wa_flags |= SMBCHG_BATT_OV_WA; + if (pmic_rev_id->rev4 < 2) /* PMI8950 1.0 */ { + chip->wa_flags |= SMBCHG_AICL_DEGLITCH_WA; + } else { /* rev > PMI8950 v1.0 */ + chip->wa_flags |= SMBCHG_HVDCP_9V_EN_WA + | SMBCHG_USB100_WA; + } + use_pmi8994_tables(chip); + chip->tables.aicl_rerun_period_table = + aicl_rerun_period_schg_lite; + chip->tables.aicl_rerun_period_len = + ARRAY_SIZE(aicl_rerun_period_schg_lite); + + chip->schg_version = QPNP_SCHG_LITE; + /* PMI8937/PMI8940 doesn't support HVDCP */ + if ((pmic_rev_id->pmic_subtype == PMI8937) + || (pmic_rev_id->pmic_subtype == PMI8940)) + chip->hvdcp_not_supported = true; + break; + case PMI8996: + chip->wa_flags |= SMBCHG_CC_ESR_WA + | SMBCHG_FLASH_ICL_DISABLE_WA + | SMBCHG_RESTART_WA + | SMBCHG_FLASH_BUCK_SWITCH_FREQ_WA; + use_pmi8996_tables(chip); + chip->schg_version = QPNP_SCHG; + break; + default: + pr_err("PMIC subtype %d not supported, WA flags not set\n", + pmic_rev_id->pmic_subtype); + } + + pr_smb(PR_STATUS, "pmic=%s, wa_flags=0x%x, hvdcp_supported=%s\n", + pmic_rev_id->pmic_name, chip->wa_flags, + chip->hvdcp_not_supported ? "false" : "true"); + + return 0; +} + +static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip) +{ + enum power_supply_type usb_supply_type; + char *usb_type_name; + int rc; + + if (!(chip->wa_flags & SMBCHG_RESTART_WA)) + return; + + read_usb_type(chip, &usb_type_name, &usb_supply_type); + if (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP + && !is_hvdcp_present(chip)) { + pr_smb(PR_STATUS, "DCP found rerunning APSD\n"); + rc = vote(chip->usb_icl_votable, + CHG_SUSPEND_WORKAROUND_ICL_VOTER, true, 300); + if (rc < 0) + pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n", + rc); + + rc = rerun_apsd(chip); + if (rc) + pr_err("APSD rerun failed rc=%d\n", rc); + + read_usb_type(chip, &usb_type_name, &usb_supply_type); + if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) { + msleep(500); + pr_smb(PR_STATUS, "Rerun APSD as type !=DCP\n"); + + rc = rerun_apsd(chip); + if (rc) + pr_err("APSD rerun failed rc=%d\n", rc); + } + + rc = vote(chip->usb_icl_votable, + CHG_SUSPEND_WORKAROUND_ICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n", + rc); + + /* Schedule work for HVDCP detection */ + if (!chip->hvdcp_not_supported) { + cancel_delayed_work_sync(&chip->hvdcp_det_work); + smbchg_stay_awake(chip, PM_DETECT_HVDCP); + schedule_delayed_work(&chip->hvdcp_det_work, + msecs_to_jiffies(HVDCP_NOTIFY_MS)); + } + } +} + +static int smbchg_probe(struct spmi_device *spmi) +{ + int rc; + struct smbchg_chip *chip; + struct power_supply *usb_psy, *typec_psy = NULL; + struct qpnp_vadc_chip *vadc_dev = NULL, *vchg_vadc_dev = NULL; + const char *typec_psy_name; + + usb_psy = power_supply_get_by_name("usb"); + if (!usb_psy) { + pr_smb(PR_STATUS, "USB supply not found, deferring probe\n"); + return -EPROBE_DEFER; + } + + if (of_property_read_bool(spmi->dev.of_node, "qcom,external-typec")) { + /* read the type power supply name */ + rc = of_property_read_string(spmi->dev.of_node, + "qcom,typec-psy-name", &typec_psy_name); + if (rc) { + pr_err("failed to get prop typec-psy-name rc=%d\n", + rc); + return rc; + } + + typec_psy = power_supply_get_by_name(typec_psy_name); + if (!typec_psy) { + pr_smb(PR_STATUS, + "Type-C supply not found, deferring probe\n"); + return -EPROBE_DEFER; + } + } + + if (of_find_property(spmi->dev.of_node, "qcom,dcin-vadc", NULL)) { + vadc_dev = qpnp_get_vadc(&spmi->dev, "dcin"); + if (IS_ERR(vadc_dev)) { + rc = PTR_ERR(vadc_dev); + if (rc != -EPROBE_DEFER) + dev_err(&spmi->dev, "Couldn't get vadc rc=%d\n", + rc); + return rc; + } + } + + if (of_find_property(spmi->dev.of_node, "qcom,vchg_sns-vadc", NULL)) { + vchg_vadc_dev = qpnp_get_vadc(&spmi->dev, "vchg_sns"); + if (IS_ERR(vchg_vadc_dev)) { + rc = PTR_ERR(vchg_vadc_dev); + if (rc != -EPROBE_DEFER) + dev_err(&spmi->dev, "Couldn't get vadc 'vchg' rc=%d\n", + rc); + return rc; + } + } + + chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) { + dev_err(&spmi->dev, "Unable to allocate memory\n"); + return -ENOMEM; + } + + chip->fcc_votable = create_votable("BATT_FCC", + VOTE_MIN, + set_fastchg_current_vote_cb, chip); + if (IS_ERR(chip->fcc_votable)) { + rc = PTR_ERR(chip->fcc_votable); + goto votables_cleanup; + } + + chip->usb_icl_votable = create_votable("USB_ICL", + VOTE_MIN, + set_usb_current_limit_vote_cb, chip); + if (IS_ERR(chip->usb_icl_votable)) { + rc = PTR_ERR(chip->usb_icl_votable); + goto votables_cleanup; + } + + chip->dc_icl_votable = create_votable("DCIN_ICL", + VOTE_MIN, + set_dc_current_limit_vote_cb, chip); + if (IS_ERR(chip->dc_icl_votable)) { + rc = PTR_ERR(chip->dc_icl_votable); + goto votables_cleanup; + } + + chip->usb_suspend_votable = create_votable("USB_SUSPEND", + VOTE_SET_ANY, + usb_suspend_vote_cb, chip); + if (IS_ERR(chip->usb_suspend_votable)) { + rc = PTR_ERR(chip->usb_suspend_votable); + goto votables_cleanup; + } + + chip->dc_suspend_votable = create_votable("DC_SUSPEND", + VOTE_SET_ANY, + dc_suspend_vote_cb, chip); + if (IS_ERR(chip->dc_suspend_votable)) { + rc = PTR_ERR(chip->dc_suspend_votable); + goto votables_cleanup; + } + + chip->battchg_suspend_votable = create_votable("BATTCHG_SUSPEND", + VOTE_SET_ANY, + charging_suspend_vote_cb, chip); + if (IS_ERR(chip->battchg_suspend_votable)) { + rc = PTR_ERR(chip->battchg_suspend_votable); + goto votables_cleanup; + } + + chip->hw_aicl_rerun_disable_votable = create_votable("HWAICL_DISABLE", + VOTE_SET_ANY, + smbchg_hw_aicl_rerun_disable_cb, chip); + if (IS_ERR(chip->hw_aicl_rerun_disable_votable)) { + rc = PTR_ERR(chip->hw_aicl_rerun_disable_votable); + goto votables_cleanup; + } + + chip->hw_aicl_rerun_enable_indirect_votable = create_votable( + "HWAICL_ENABLE_INDIRECT", + VOTE_SET_ANY, + smbchg_hw_aicl_rerun_enable_indirect_cb, chip); + if (IS_ERR(chip->hw_aicl_rerun_enable_indirect_votable)) { + rc = PTR_ERR(chip->hw_aicl_rerun_enable_indirect_votable); + goto votables_cleanup; + } + + chip->aicl_deglitch_short_votable = create_votable( + "HWAICL_SHORT_DEGLITCH", + VOTE_SET_ANY, + smbchg_aicl_deglitch_config_cb, chip); + if (IS_ERR(chip->aicl_deglitch_short_votable)) { + rc = PTR_ERR(chip->aicl_deglitch_short_votable); + goto votables_cleanup; + } + + chip->hvdcp_enable_votable = create_votable( + "HVDCP_ENABLE", + VOTE_MIN, + smbchg_hvdcp_enable_cb, chip); + if (IS_ERR(chip->hvdcp_enable_votable)) { + rc = PTR_ERR(chip->hvdcp_enable_votable); + goto votables_cleanup; + } + + INIT_WORK(&chip->usb_set_online_work, smbchg_usb_update_online_work); + INIT_DELAYED_WORK(&chip->parallel_en_work, + smbchg_parallel_usb_en_work); + INIT_DELAYED_WORK(&chip->vfloat_adjust_work, smbchg_vfloat_adjust_work); + INIT_DELAYED_WORK(&chip->hvdcp_det_work, smbchg_hvdcp_det_work); + INIT_DELAYED_WORK(&chip->cool_limit_work, smbchg_cool_limit_work); + schedule_delayed_work(&chip->cool_limit_work, msecs_to_jiffies(SMBCHG_UPDATE_MS)); + init_completion(&chip->src_det_lowered); + init_completion(&chip->src_det_raised); + init_completion(&chip->usbin_uv_lowered); + init_completion(&chip->usbin_uv_raised); + init_completion(&chip->hvdcp_det_done); + chip->vadc_dev = vadc_dev; + chip->vchg_vadc_dev = vchg_vadc_dev; + chip->spmi = spmi; + chip->dev = &spmi->dev; + chip->usb_psy = usb_psy; + chip->typec_psy = typec_psy; + chip->fake_battery_soc = -EINVAL; + chip->usb_online = -EINVAL; + dev_set_drvdata(&spmi->dev, chip); + + spin_lock_init(&chip->sec_access_lock); + mutex_init(&chip->therm_lvl_lock); + mutex_init(&chip->usb_set_online_lock); + mutex_init(&chip->parallel.lock); + mutex_init(&chip->taper_irq_lock); + mutex_init(&chip->pm_lock); + mutex_init(&chip->wipower_config); + mutex_init(&chip->usb_status_lock); + mutex_init(&chip->cool_current); + device_init_wakeup(chip->dev, true); + chip->debug_dump = kmalloc(sizeof(char)*2048, GFP_KERNEL); + memset(chip->debug_dump, '\0', sizeof(char)*2048); + + rc = smbchg_parse_peripherals(chip); + if (rc) { + dev_err(chip->dev, "Error parsing DT peripherals: %d\n", rc); + goto votables_cleanup; + } + + printk("[SMBCHG]hvdcp enable\n"); + chip->hvdcp_not_supported = false; + + rc = smbchg_check_chg_version(chip); + if (rc) { + pr_err("Unable to check schg version rc=%d\n", rc); + goto votables_cleanup; + } + + rc = smb_parse_dt(chip); + if (rc < 0) { + dev_err(&spmi->dev, "Unable to parse DT nodes: %d\n", rc); + goto votables_cleanup; + } + + rc = smbchg_regulator_init(chip); + if (rc) { + dev_err(&spmi->dev, + "Couldn't initialize regulator rc=%d\n", rc); + goto votables_cleanup; + } + + rc = smbchg_hw_init(chip); + if (rc < 0) { + dev_err(&spmi->dev, + "Unable to intialize hardware rc = %d\n", rc); + goto out; + } + + INIT_DELAYED_WORK(&chip->temp_check_work, smbchg_temp_check_work); + schedule_delayed_work(&chip->temp_check_work, msecs_to_jiffies(SMBCHG_UPDATE_MS * 5)); + + rc = determine_initial_status(chip); + if (rc < 0) { + dev_err(&spmi->dev, + "Unable to determine init status rc = %d\n", rc); + goto out; + } + + chip->previous_soc = -EINVAL; + chip->batt_psy.name = chip->battery_psy_name; + chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY; + chip->batt_psy.get_property = smbchg_battery_get_property; + chip->batt_psy.set_property = smbchg_battery_set_property; + chip->batt_psy.properties = smbchg_battery_properties; + chip->batt_psy.num_properties = ARRAY_SIZE(smbchg_battery_properties); + chip->batt_psy.external_power_changed = smbchg_external_power_changed; + chip->batt_psy.property_is_writeable = smbchg_battery_is_writeable; + + rc = power_supply_register(chip->dev, &chip->batt_psy); + if (rc < 0) { + dev_err(&spmi->dev, + "Unable to register batt_psy rc = %d\n", rc); + goto out; + } + if (chip->dc_psy_type != -EINVAL) { + chip->dc_psy.name = "dc"; + chip->dc_psy.type = chip->dc_psy_type; + chip->dc_psy.get_property = smbchg_dc_get_property; + chip->dc_psy.set_property = smbchg_dc_set_property; + chip->dc_psy.property_is_writeable = smbchg_dc_is_writeable; + chip->dc_psy.properties = smbchg_dc_properties; + chip->dc_psy.num_properties = ARRAY_SIZE(smbchg_dc_properties); + chip->dc_psy.supplied_to = smbchg_dc_supplicants; + chip->dc_psy.num_supplicants + = ARRAY_SIZE(smbchg_dc_supplicants); + rc = power_supply_register(chip->dev, &chip->dc_psy); + if (rc < 0) { + dev_err(&spmi->dev, + "Unable to register dc_psy rc = %d\n", rc); + goto unregister_batt_psy; + } + } + chip->psy_registered = true; + chip->allow_hvdcp3_detection = true; + + if (chip->cfg_chg_led_support && + chip->schg_version == QPNP_SCHG_LITE) { + rc = smbchg_register_chg_led(chip); + if (rc) { + dev_err(chip->dev, + "Unable to register charger led: %d\n", + rc); + goto unregister_dc_psy; + } + + rc = smbchg_chg_led_controls(chip); + if (rc) { + dev_err(chip->dev, + "Failed to set charger led controld bit: %d\n", + rc); + goto unregister_led_class; + } + } + + rc = smbchg_request_irqs(chip); + if (rc < 0) { + dev_err(&spmi->dev, "Unable to request irqs rc = %d\n", rc); + goto unregister_led_class; + } + + if (!chip->skip_usb_notification) { + pr_smb(PR_MISC, "setting usb psy present = %d\n", + chip->usb_present); + power_supply_set_present(chip->usb_psy, chip->usb_present); + } + + rerun_hvdcp_det_if_necessary(chip); + + update_usb_status(chip, is_usb_present(chip), false); + dump_regs(chip); + create_debugfs_entries(chip); + dev_info(chip->dev, + "SMBCHG successfully probe Charger version=%s Revision DIG:%d.%d ANA:%d.%d batt=%d dc=%d usb=%d\n", + version_str[chip->schg_version], + chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR], + chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR], + get_prop_batt_present(chip), + chip->dc_present, chip->usb_present); + return 0; + +unregister_led_class: + if (chip->cfg_chg_led_support && chip->schg_version == QPNP_SCHG_LITE) + led_classdev_unregister(&chip->led_cdev); +unregister_dc_psy: + power_supply_unregister(&chip->dc_psy); +unregister_batt_psy: + power_supply_unregister(&chip->batt_psy); +out: + handle_usb_removal(chip); +votables_cleanup: + if (chip->aicl_deglitch_short_votable) + destroy_votable(chip->aicl_deglitch_short_votable); + if (chip->hw_aicl_rerun_enable_indirect_votable) + destroy_votable(chip->hw_aicl_rerun_enable_indirect_votable); + if (chip->hw_aicl_rerun_disable_votable) + destroy_votable(chip->hw_aicl_rerun_disable_votable); + if (chip->battchg_suspend_votable) + destroy_votable(chip->battchg_suspend_votable); + if (chip->dc_suspend_votable) + destroy_votable(chip->dc_suspend_votable); + if (chip->usb_suspend_votable) + destroy_votable(chip->usb_suspend_votable); + if (chip->dc_icl_votable) + destroy_votable(chip->dc_icl_votable); + if (chip->usb_icl_votable) + destroy_votable(chip->usb_icl_votable); + if (chip->fcc_votable) + destroy_votable(chip->fcc_votable); + return rc; +} + +static int smbchg_remove(struct spmi_device *spmi) +{ + struct smbchg_chip *chip = dev_get_drvdata(&spmi->dev); + + debugfs_remove_recursive(chip->debug_root); + + if (chip->dc_psy_type != -EINVAL) + power_supply_unregister(&chip->dc_psy); + + power_supply_unregister(&chip->batt_psy); + destroy_votable(chip->aicl_deglitch_short_votable); + destroy_votable(chip->hw_aicl_rerun_enable_indirect_votable); + destroy_votable(chip->hw_aicl_rerun_disable_votable); + destroy_votable(chip->battchg_suspend_votable); + destroy_votable(chip->dc_suspend_votable); + destroy_votable(chip->usb_suspend_votable); + destroy_votable(chip->dc_icl_votable); + destroy_votable(chip->usb_icl_votable); + destroy_votable(chip->fcc_votable); + + return 0; +} + +static void smbchg_shutdown(struct spmi_device *spmi) +{ + struct smbchg_chip *chip = dev_get_drvdata(&spmi->dev); + int rc; + + if (!(chip->wa_flags & SMBCHG_RESTART_WA)) + return; + + if (!is_hvdcp_present(chip)) + return; + + pr_smb(PR_MISC, "Reducing to 500mA\n"); + rc = vote(chip->usb_icl_votable, SHUTDOWN_WORKAROUND_ICL_VOTER, true, + 500); + if (rc < 0) + pr_err("Couldn't vote 500mA ICL\n"); + + pr_smb(PR_MISC, "Disable Parallel\n"); + mutex_lock(&chip->parallel.lock); + smbchg_parallel_en = 0; + smbchg_parallel_usb_disable(chip); + mutex_unlock(&chip->parallel.lock); + + pr_smb(PR_MISC, "Disable all interrupts\n"); + disable_irq(chip->aicl_done_irq); + disable_irq(chip->batt_cold_irq); + disable_irq(chip->batt_cool_irq); + disable_irq(chip->batt_hot_irq); + disable_irq(chip->batt_missing_irq); + disable_irq(chip->batt_warm_irq); + disable_irq(chip->chg_error_irq); + disable_irq(chip->chg_hot_irq); + disable_irq(chip->chg_term_irq); + disable_irq(chip->dcin_uv_irq); + disable_irq(chip->fastchg_irq); + disable_irq(chip->otg_fail_irq); + disable_irq(chip->otg_oc_irq); + disable_irq(chip->power_ok_irq); + disable_irq(chip->recharge_irq); + disable_irq(chip->taper_irq); + disable_irq(chip->usbid_change_irq); + disable_irq(chip->usbin_ov_irq); + disable_irq(chip->vbat_low_irq); + disable_irq(chip->wdog_timeout_irq); + + /* remove all votes for short deglitch */ + vote(chip->aicl_deglitch_short_votable, + VARB_WORKAROUND_SHORT_DEGLITCH_VOTER, false, 0); + vote(chip->aicl_deglitch_short_votable, + VARB_WORKAROUND_VOTER, false, 0); + vote(chip->aicl_deglitch_short_votable, + HVDCP_SHORT_DEGLITCH_VOTER, false, 0); + + /* vote to ensure AICL rerun is enabled */ + rc = vote(chip->hw_aicl_rerun_enable_indirect_votable, + SHUTDOWN_WORKAROUND_VOTER, true, 0); + if (rc < 0) + pr_err("Couldn't vote to enable indirect AICL rerun\n"); + rc = vote(chip->hw_aicl_rerun_disable_votable, + WEAK_CHARGER_HW_AICL_VOTER, false, 0); + if (rc < 0) + pr_err("Couldn't vote to enable AICL rerun\n"); + + /* switch to 5V HVDCP */ + pr_smb(PR_MISC, "Switch to 5V HVDCP\n"); + rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_ADAPTER_SEL_MASK, HVDCP_5V); + if (rc < 0) { + pr_err("Couldn't configure HVDCP 5V rc=%d\n", rc); + return; + } + + pr_smb(PR_MISC, "Wait 500mS to lower to 5V\n"); + /* wait for HVDCP to lower to 5V */ + msleep(500); + /* + * Check if the same hvdcp session is in progress. src_det should be + * high and that we are still in 5V hvdcp + */ + if (!is_src_detect_high(chip)) { + pr_smb(PR_MISC, "src det low after 500mS sleep\n"); + return; + } + + /* disable HVDCP */ + pr_smb(PR_MISC, "Disable HVDCP\n"); + rc = vote(chip->hvdcp_enable_votable, HVDCP_PMIC_VOTER, true, 0); + if (rc < 0) + pr_err("Couldn't disable HVDCP rc=%d\n", rc); + + chip->hvdcp_3_det_ignore_uv = true; + /* fake a removal */ + pr_smb(PR_MISC, "Faking Removal\n"); + rc = fake_insertion_removal(chip, false); + if (rc < 0) + pr_err("Couldn't fake removal HVDCP Removed rc=%d\n", rc); + + /* fake an insertion */ + pr_smb(PR_MISC, "Faking Insertion\n"); + rc = fake_insertion_removal(chip, true); + if (rc < 0) + pr_err("Couldn't fake insertion rc=%d\n", rc); + + disable_irq(chip->src_detect_irq); + disable_irq(chip->usbin_uv_irq); + + pr_smb(PR_MISC, "Wait 1S to settle\n"); + msleep(1000); + chip->hvdcp_3_det_ignore_uv = false; + + pr_smb(PR_STATUS, "wrote power off configurations\n"); +} + +static const struct dev_pm_ops smbchg_pm_ops = { +}; + +MODULE_DEVICE_TABLE(spmi, smbchg_id); + +static struct spmi_driver smbchg_driver = { + .driver = { + .name = "qpnp-smbcharger", + .owner = THIS_MODULE, + .of_match_table = smbchg_match_table, + .pm = &smbchg_pm_ops, + }, + .probe = smbchg_probe, + .remove = smbchg_remove, + .shutdown = smbchg_shutdown, +}; + +static int __init smbchg_init(void) +{ + return spmi_driver_register(&smbchg_driver); +} + +static void __exit smbchg_exit(void) +{ + return spmi_driver_unregister(&smbchg_driver); +} + +module_init(smbchg_init); +module_exit(smbchg_exit); + +MODULE_DESCRIPTION("QPNP SMB Charger"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:qpnp-smbcharger"); diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index cb66ee5e3a9cf..b5a7229cce803 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -60,7 +61,11 @@ static void scm_disable_sdi(void); * There is no API from TZ to re-enable the registers. * So the SDI cannot be re-enabled when it already by-passed. */ -static int download_mode = 1; + #ifdef FACTORY_VERSION_ENABLE + static int download_mode = 1; + #else + static int download_mode; + #endif #else static const int download_mode; #endif @@ -77,6 +82,13 @@ static bool scm_dload_supported; static struct kobject dload_kobj; static void *dload_type_addr; +/*lancelot add for reboot dl*/ +static int hq_reboot_dl; + +module_param_named(reboot_dl_set, hq_reboot_dl, int, 0644); +MODULE_PARM_DESC(reboot_dl_set, "for hq reboot enter dl mode"); +/*lancelot add end*/ + static int dload_set(const char *val, struct kernel_param *kp); /* interface for exporting attributes */ struct reset_attribute { @@ -151,7 +163,7 @@ static bool get_dload_mode(void) { return dload_mode_enabled; } - +#ifdef FACTORY_VERSION_ENABLE static void enable_emergency_dload_mode(void) { int ret; @@ -176,6 +188,7 @@ static void enable_emergency_dload_mode(void) if (ret) pr_err("Failed to set secure EDLOAD mode: %d\n", ret); } +#endif static int dload_set(const char *val, struct kernel_param *kp) { @@ -203,10 +216,12 @@ static void set_dload_mode(int on) return; } +#ifdef FACTORY_VERSION_ENABLE static void enable_emergency_dload_mode(void) { pr_err("dload mode is not enabled on target\n"); } +#endif static bool get_dload_mode(void) { @@ -275,8 +290,10 @@ static void msm_restart_prepare(const char *cmd) * Kill download mode if master-kill switch is set */ + + set_dload_mode(download_mode && - (in_panic || restart_mode == RESTART_DLOAD)); + (in_panic || restart_mode == RESTART_DLOAD || hq_reboot_dl)); #endif if (qpnp_pon_check_hard_reset_stored()) { @@ -298,7 +315,12 @@ static void msm_restart_prepare(const char *cmd) qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET); } - if (cmd != NULL) { + if (in_panic) { + qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET); + qpnp_pon_set_restart_reason( + PON_RESTART_REASON_PANIC); + __raw_writel(0x77665508, restart_reason); + } else if (cmd != NULL) { if (!strncmp(cmd, "bootloader", 10)) { qpnp_pon_set_restart_reason( PON_RESTART_REASON_BOOTLOADER); @@ -331,10 +353,24 @@ static void msm_restart_prepare(const char *cmd) __raw_writel(0x6f656d00 | (code & 0xff), restart_reason); } else if (!strncmp(cmd, "edl", 3)) { + #ifdef FACTORY_VERSION_ENABLE enable_emergency_dload_mode(); + #else + pr_crit("not factory version , no edl\n"); + #endif + } else if (!strcmp(cmd, "other")) { + qpnp_pon_set_restart_reason( + PON_RESTART_REASON_OTHER); + __raw_writel(0x77665501, restart_reason); } else { + qpnp_pon_set_restart_reason( + PON_RESTART_REASON_NORMAL); __raw_writel(0x77665501, restart_reason); } + } else { + qpnp_pon_set_restart_reason( + PON_RESTART_REASON_NORMAL); + __raw_writel(0x77665501, restart_reason); } flush_cache_all(); @@ -400,6 +436,8 @@ static void do_msm_poweroff(void) set_dload_mode(0); scm_disable_sdi(); qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN); + qpnp_pon_set_restart_reason(PON_RESTART_REASON_UNKNOWN); + __raw_writel(0x0, restart_reason); halt_spmi_pmic_arbiter(); deassert_ps_hold(); @@ -570,6 +608,10 @@ static int msm_restart_probe(struct platform_device *pdev) if (mem) tcsr_boot_misc_detect = mem->start; + qpnp_pon_set_restart_reason( + PON_RESTART_REASON_UNKNOWN); + __raw_writel(0x77665510, restart_reason); + pm_power_off = do_msm_poweroff; arm_pm_restart = do_msm_restart; diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c index c028d745d11ed..4b738d6b7455c 100644 --- a/drivers/regulator/qpnp-labibb-regulator.c +++ b/drivers/regulator/qpnp-labibb-regulator.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1851,7 +1852,12 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, return rc; } - if (!(val & (IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN))) { +#ifdef CONFIG_PROJECT_VINCE + if (1) +#else + if (!(val & (IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN))) +#endif + { /* SWIRE_RDY and IBB_MODULE_EN not enabled */ rc = qpnp_lab_dt_init(labibb, of_node); if (rc) { @@ -2492,8 +2498,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb, return rc; } +#ifdef CONFIG_PROJECT_VINCE + if (0) +#else if (ibb_enable_ctl & - (IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN)) { + (IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN)) +#endif + { /* SWIRE_RDY or IBB_MODULE_EN enabled */ rc = qpnp_labibb_read(labibb, &val, labibb->ibb_base + REG_IBB_LCD_AMOLED_SEL, 1); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3040c546f132c..2e161ed4d02bf 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1436,5 +1436,9 @@ config RTC_DRV_HID_SENSOR_TIME If this driver is compiled as a module, it will be named rtc-hid-sensor-time. +config PROJECT_SAKURA_CN + bool "XIAOMI D1S use" + help + diff rtc in D1S project. endif # RTC_CLASS diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c index e49d87e556782..636c4419449ab 100644 --- a/drivers/rtc/qpnp-rtc.c +++ b/drivers/rtc/qpnp-rtc.c @@ -593,7 +593,6 @@ static int qpnp_rtc_probe(struct spmi_device *spmi) qpnp_rtc_ops.set_time = qpnp_rtc_set_time; dev_set_drvdata(&spmi->dev, rtc_dd); - device_init_wakeup(&spmi->dev, 1); /* Register the RTC device */ rtc_dd->rtc = rtc_device_register("qpnp_rtc", &spmi->dev, &qpnp_rtc_ops, THIS_MODULE); @@ -613,6 +612,7 @@ static int qpnp_rtc_probe(struct spmi_device *spmi) goto fail_req_irq; } + device_init_wakeup(&spmi->dev, 1); enable_irq_wake(rtc_dd->rtc_alarm_irq); dev_dbg(&spmi->dev, "Probe success !!\n"); @@ -622,7 +622,6 @@ static int qpnp_rtc_probe(struct spmi_device *spmi) fail_req_irq: rtc_device_unregister(rtc_dd->rtc); fail_rtc_enable: - device_init_wakeup(&spmi->dev, 0); dev_set_drvdata(&spmi->dev, NULL); return rc; diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 40ef902f1ba5b..3a4b762ad9075 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -912,6 +912,11 @@ config QCOM_SMCINVOKE Enable SMCInvoke driver which supports capability based secure communication between QSEE and HLOS. +config SERIAL_NUM + bool "Enable Serial Number Proc Interface" + help + Provide a interface for reading CPU serial number + config QCOM_EARLY_RANDOM bool "Initialize random pool very early" help diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 88e87e339e652..0c6f9bdae6e06 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -112,3 +112,5 @@ obj-$(CONFIG_QCOM_SMCINVOKE) += smcinvoke.o obj-$(CONFIG_QCOM_EARLY_RANDOM) += early_random.o obj-$(CONFIG_MSM_HAB) += hab/ obj-$(CONFIG_QCOM_QDSS_BRIDGE) += qdss_bridge.o +obj-$(CONFIG_SERIAL_NUM) += serial_num.o + diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c index 4cf54aa8b2b97..8c360fd836098 100644 --- a/drivers/soc/qcom/pil-q6v5-mss.c +++ b/drivers/soc/qcom/pil-q6v5-mss.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -42,8 +45,82 @@ #define MAX_SSR_REASON_LEN 130U #define STOP_ACK_TIMEOUT_MS 1000 +#define STR_NV_SIGNATURE_DESTROYED "CRITICAL_DATA_CHECK_FAILED" + +static char last_modem_sfr_reason[MAX_SSR_REASON_LEN] = "none"; + #define subsys_to_drv(d) container_of(d, struct modem_data, subsys_desc) +static struct kobject *checknv_kobj; +static struct kset *checknv_kset; +static bool errimei_flag; + +static const struct sysfs_ops checknv_sysfs_ops = { +}; + +static void kobj_release(struct kobject *kobj) +{ + kfree(kobj); +} + +static struct kobj_type checknv_ktype = { + .sysfs_ops = &checknv_sysfs_ops, + .release = kobj_release, +}; + +static void checknv_kobj_clean(struct work_struct *work) +{ + kobject_uevent(checknv_kobj, KOBJ_REMOVE); + kobject_put(checknv_kobj); + kset_unregister(checknv_kset); +} + +static void checknv_kobj_create(struct work_struct *work) +{ + int ret; + + if (checknv_kset != NULL) { + pr_err("checknv_kset is not NULL, should clean up."); + kobject_uevent(checknv_kobj, KOBJ_REMOVE); + kobject_put(checknv_kobj); + } + + checknv_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); + if (!checknv_kobj) { + pr_err("kobject alloc failed."); + return; + } + + if (checknv_kset == NULL) { + checknv_kset = kset_create_and_add("checknv_errimei", NULL, NULL); + if (!checknv_kset) { + pr_err("kset creation failed."); + goto free_kobj; + } + } + + checknv_kobj->kset = checknv_kset; + + ret = kobject_init_and_add(checknv_kobj, &checknv_ktype, NULL, "%s", "errimei"); + if (ret) { + pr_err("%s: Error in creation kobject", __func__); + goto del_kobj; + } + + kobject_uevent(checknv_kobj, KOBJ_ADD); + return; + +del_kobj: + kobject_put(checknv_kobj); + kset_unregister(checknv_kset); + +free_kobj: + kfree(checknv_kobj); +} + +static DECLARE_DELAYED_WORK(create_kobj_work, checknv_kobj_create); +static DECLARE_WORK(clean_kobj_work, checknv_kobj_clean); + static void log_modem_sfr(void) { u32 size; @@ -61,6 +138,7 @@ static void log_modem_sfr(void) } strlcpy(reason, smem_reason, min(size, MAX_SSR_REASON_LEN)); + strlcpy(last_modem_sfr_reason, smem_reason, min(size, MAX_SSR_REASON_LEN)); pr_err("modem subsystem failure reason: %s.\n", reason); smem_reason[0] = '\0'; @@ -71,9 +149,15 @@ static void restart_modem(struct modem_data *drv) { log_modem_sfr(); drv->ignore_errors = true; - subsystem_restart_dev(drv->subsys); + if (strnstr(last_modem_sfr_reason, STR_NV_SIGNATURE_DESTROYED, strlen(last_modem_sfr_reason))) { + pr_err("errimei_dev: the NV has been destroyed, should restart to recovery\n"); + errimei_flag = true; + } else { + subsystem_restart_dev(drv->subsys); + } } + static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id) { struct modem_data *drv = subsys_to_drv(dev_id); @@ -356,6 +440,16 @@ static int pil_mss_loadable_init(struct modem_data *drv, return ret; } +static ssize_t pil_mss_errimei_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + + ret = snprintf(buf, 5, "%d", errimei_flag); + return ret; +} +static DEVICE_ATTR(errimei, 0444, pil_mss_errimei_show, NULL); + static int pil_mss_driver_probe(struct platform_device *pdev) { struct modem_data *drv; @@ -382,6 +476,9 @@ static int pil_mss_driver_probe(struct platform_device *pdev) if (ret) return ret; + if (device_create_file(&(pdev->dev), &dev_attr_errimei) < 0) + pr_err("device_create_file errimei failed.\n"); + return pil_subsys_init(drv, pdev); } @@ -389,6 +486,7 @@ static int pil_mss_driver_exit(struct platform_device *pdev) { struct modem_data *drv = platform_get_drvdata(pdev); + device_remove_file(&pdev->dev, &dev_attr_errimei); subsys_unregister(drv->subsys); destroy_ramdump_device(drv->ramdump_dev); pil_desc_release(&drv->q6->desc); diff --git a/drivers/soc/qcom/serial_num.c b/drivers/soc/qcom/serial_num.c new file mode 100644 index 0000000000000..ce2196e60cdee --- /dev/null +++ b/drivers/soc/qcom/serial_num.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define sn_readl(drvdata, off) __raw_readl(drvdata->base + off) + +#define SERIAL_NUM (0x000) + +static uint32_t sn; + +struct sn_drvdata { + void __iomem *base; + struct device *dev; +}; + +static struct sn_drvdata *sndrvdata; + +static int sn_read(struct seq_file *m, void *v) +{ + struct sn_drvdata *drvdata = sndrvdata; + + if (!drvdata) + return false; + + if (sn == 0) + sn = sn_readl(drvdata, SERIAL_NUM); + + dev_dbg(drvdata->dev, "serial num: %x\n", sn); + + seq_printf(m, "0x%x\n", sn); + + return 0; + +} + +static int sn_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, sn_read, NULL); +} + +static const struct file_operations sn_fops = { + .open = sn_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void sn_create_proc(void) +{ + struct proc_dir_entry *entry; + entry = proc_create("serial_num", 0 /* default mode */, + NULL /* parent dir */, &sn_fops); +} + +static int sn_fuse_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sn_drvdata *drvdata; + struct resource *res; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + /* Store the driver data pointer for use in exported functions */ + sndrvdata = drvdata; + drvdata->dev = &pdev->dev; + platform_set_drvdata(pdev, drvdata); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sn-base"); + if (!res) + return -ENODEV; + + drvdata->base = devm_ioremap(dev, res->start, resource_size(res)); + if (!drvdata->base) + return -ENOMEM; + + sn_create_proc(); + dev_info(dev, "SN interface initialized\n"); + return 0; +} + +static int sn_fuse_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct of_device_id sn_fuse_match[] = { + {.compatible = "qcom,sn-fuse"}, + {} +}; + +static struct platform_driver sn_fuse_driver = { + .probe = sn_fuse_probe, + .remove = sn_fuse_remove, + .driver = { + .name = "msm-sn-fuse", + .owner = THIS_MODULE, + .of_match_table = sn_fuse_match, + }, +}; + +static int __init sn_fuse_init(void) +{ + return platform_driver_register(&sn_fuse_driver); +} +arch_initcall(sn_fuse_init); + +static void __exit sn_fuse_exit(void) +{ + platform_driver_unregister(&sn_fuse_driver); +} +module_exit(sn_fuse_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("JTag Fuse driver"); + diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 4dc5ab23ab973..edbfd6457baae 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -3,6 +3,7 @@ * Android IPC Subsystem * * Copyright (C) 2007-2008 Google, Inc. + * Copyright (C) 2019 XiaoMi, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -3134,7 +3135,6 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = NULL; goto err_binder_alloc_buf_failed; } - t->buffer->allow_user_free = 0; t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; @@ -3630,14 +3630,18 @@ static int binder_thread_write(struct binder_proc *proc, buffer = binder_alloc_prepare_to_free(&proc->alloc, data_ptr); - if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", - proc->pid, thread->pid, (u64)data_ptr); - break; - } - if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", - proc->pid, thread->pid, (u64)data_ptr); + if (IS_ERR_OR_NULL(buffer)) { + if (PTR_ERR(buffer) == -EPERM) { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n", + proc->pid, thread->pid, + (u64)data_ptr); + } else { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx no match\n", + proc->pid, thread->pid, + (u64)data_ptr); + } break; } binder_debug(BINDER_DEBUG_FREE_BUFFER, diff --git a/drivers/staging/android/binder_alloc.c b/drivers/staging/android/binder_alloc.c index b900b0722b8bd..49536d237cb54 100644 --- a/drivers/staging/android/binder_alloc.c +++ b/drivers/staging/android/binder_alloc.c @@ -3,6 +3,7 @@ * Android IPC Subsystem * * Copyright (C) 2007-2017 Google, Inc. + * Copyright (C) 2019 XiaoMi, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -149,14 +150,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( else { /* * Guard against user threads attempting to - * free the buffer twice + * free the buffer when in use by kernel or + * after it's already been freed. */ - if (buffer->free_in_progress) { - pr_err("%d:%d FREE_BUFFER u%016llx user freed buffer twice\n", - alloc->pid, current->pid, (u64)user_ptr); - return NULL; - } - buffer->free_in_progress = 1; + if (!buffer->allow_user_free) + return ERR_PTR(-EPERM); + buffer->allow_user_free = 0; return buffer; } } @@ -462,7 +461,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; - buffer->free_in_progress = 0; + buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %pK\n", @@ -924,15 +923,13 @@ enum lru_status binder_alloc_free_page(struct list_head *item, index = page - alloc->pages; page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; + + mm = alloc->vma_vm_mm; + if (!atomic_inc_not_zero(&mm->mm_users)) + goto err_mmget; + if (!down_write_trylock(&mm->mmap_sem)) + goto err_down_write_mmap_sem_failed; vma = alloc->vma; - if (vma) { - /* Same as mmget_not_zero() in later kernel versions */ - if (!atomic_inc_not_zero(&alloc->vma_vm_mm->mm_users)) - goto err_mmget; - mm = alloc->vma_vm_mm; - if (!down_write_trylock(&mm->mmap_sem)) - goto err_down_write_mmap_sem_failed; - } list_del_init(item); spin_unlock(lock); @@ -946,10 +943,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item, PAGE_SIZE, NULL); trace_binder_unmap_user_end(alloc, index); - - up_write(&mm->mmap_sem); - mmput(mm); } + up_write(&mm->mmap_sem); + mmput(mm); trace_binder_unmap_kernel_start(alloc, index); diff --git a/drivers/staging/android/binder_alloc.h b/drivers/staging/android/binder_alloc.h index 36b38558513c4..b7fcccf75c8bb 100644 --- a/drivers/staging/android/binder_alloc.h +++ b/drivers/staging/android/binder_alloc.h @@ -50,8 +50,7 @@ struct binder_buffer { unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; - unsigned free_in_progress:1; - unsigned debug_id:28; + unsigned debug_id:29; struct binder_transaction *transaction; diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 735f5f24a5f0b..4d158a7134c1a 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -37,7 +37,7 @@ static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_NOWARN | static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_NOWARN); #ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS -static const unsigned int orders[] = {9, 8, 4, 0}; +static const unsigned int orders[] = {4, 0}; #else static const unsigned int orders[] = {0}; #endif diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index e112a4fe66829..cd7cc8923b6d5 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -717,7 +717,7 @@ long msm_ion_custom_ioctl(struct ion_client *client, data.flush_data.offset; end = start + data.flush_data.length; - if (check_vaddr_bounds(start, end)) { + if (start && check_vaddr_bounds(start, end)) { pr_err("%s: virtual address %pK is out of bounds\n", __func__, data.flush_data.vaddr); ret = -EINVAL; diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 514932eaddde1..6d3184003aa3d 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -45,3 +45,7 @@ obj-$(CONFIG_THERMAL_QPNP_ADC_TM) += qpnp-adc-tm.o obj-$(CONFIG_THERMAL_MONITOR) += msm_thermal.o msm_thermal-dev.o obj-$(CONFIG_LIMITS_MONITOR) += lmh_interface.o obj-$(CONFIG_LIMITS_LITE_HW) += lmh_lite.o +#thermal switch +ifeq ($(RAINBOW_FEATURE_THERMAL_SWITCH),true) +ccflags-$(CONFIG_THERMAL) := -DRAINBOW_FEATURE_THERMAL_SWITCH +endif diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 50595544eca26..9eaa8bb2a5e71 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -52,6 +52,9 @@ MODULE_AUTHOR("Zhang Rui"); MODULE_DESCRIPTION("Generic thermal management sysfs support"); MODULE_LICENSE("GPL v2"); + +static int g_mtktsAP; + static DEFINE_IDR(thermal_tz_idr); static DEFINE_IDR(thermal_cdev_idr); static DEFINE_MUTEX(thermal_idr_lock); @@ -1504,9 +1507,32 @@ int power_actor_set_power(struct thermal_cooling_device *cdev, return 0; } + +static ssize_t +ccc_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", g_mtktsAP); +} + +static ssize_t +ccc_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int index; + + if (kstrtoint(buf, 10, &index)) + return -EINVAL; + + g_mtktsAP = index; + return count; +} + + + static DEVICE_ATTR(type, 0444, type_show, NULL); static DEVICE_ATTR(temp, 0444, temp_show, NULL); static DEVICE_ATTR(mode, 0644, mode_show, mode_store); +static DEVICE_ATTR(temp_state, 0664, ccc_show, ccc_store); static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); @@ -2596,6 +2622,75 @@ static void thermal_unregister_governors(void) thermal_gov_power_allocator_unregister(); } + +unsigned int sconfig; + +#define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) + static ssize_t sconfig_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + + + + + pr_err("sconfig_show sconfig = %d\n", sconfig); + + return sprintf(buf, "%d\n", sconfig); +} + + +static ssize_t sconfig_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + + int ret; + + + sysfs_notify(&dev->kobj, NULL, "sconfig"); + + ret = kstrtoint(buf, 0, &sconfig); + if (ret) + return ret; + + pr_err("sconfig_store sconfig = %d\n", sconfig); + + return size; +} + + +static struct device_attribute dev_attr_thermal_config = { + .attr = { + .name = "sconfig", + .mode = 0666, + }, + .show = sconfig_show, + .store = sconfig_store, +}; + + +void thermalsconfig_init(void) +{ + static struct device *dev; + + int result; + + dev = device_create(&thermal_class, NULL, MKDEV(0, 0), NULL, "thermal_message"); + if (IS_ERR(dev)) { + result = PTR_ERR(dev); + printk(KERN_ALERT "Failed to create device.\n"); + } + #if 1 + result = device_create_file(dev, &dev_attr_thermal_config); + if (result < 0) { + printk(KERN_ALERT"Failed to create attribute file."); + } + #endif + result = device_create_file(dev, &dev_attr_temp_state); + if (result < 0) { + printk(KERN_ALERT"Failed to create attribute file."); + } +} + + static int __init thermal_init(void) { int result; @@ -2616,6 +2711,10 @@ static int __init thermal_init(void) if (result) goto exit_netlink; + + thermalsconfig_init(); + + return 0; exit_netlink: diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 66ff207f14539..8f53b186bbe8e 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -44,6 +45,10 @@ #include #include #include +#include + +#include + #include "power.h" #include "core.h" @@ -52,8 +57,9 @@ #include "debug.h" #include "xhci.h" -#define DWC3_IDEV_CHG_MAX 1500 -#define DWC3_HVDCP_CHG_MAX 1800 +#define DWC3_IDEV_CHG_MAX 2000 +#define DWC3_IDEV_PROPRIETARY_CHG_MAX 1000 +#define DWC3_HVDCP_CHG_MAX 2000 #define DWC3_WAKEUP_SRC_TIMEOUT 5000 #define MICRO_5V 5000000 @@ -88,6 +94,11 @@ int dcp_max_current = DWC3_IDEV_CHG_MAX; module_param(dcp_max_current, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(dcp_max_current, "max current drawn for DCP charger"); +/* delay in msec before running DCD */ +int dcd_delay_ms = 500; +module_param(dcd_delay_ms, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(dcd_delay_ms, "delay in msec before running DCD"); + /* XHCI registers */ #define USB3_HCSPARAMS1 (0x4) #define USB3_HCCPARAMS2 (0x1c) @@ -206,6 +217,7 @@ struct dwc3_msm { struct clk *utmi_clk_src; struct clk *bus_aggr_clk; struct clk *cfg_ahb_clk; + struct qpnp_vadc_chip *vadc_dev; struct regulator *dwc3_gdsc; struct usb_phy *hs_phy, *ss_phy; @@ -270,6 +282,7 @@ struct dwc3_msm { atomic_t in_p3; unsigned int lpm_to_suspend_delay; bool init; + struct hrtimer chg_hrtimer; u32 pm_qos_latency; struct pm_qos_request pm_qos_req_dma; @@ -1856,9 +1869,13 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event, PWR_EVNT_LPM_OUT_L1_MASK, 1); atomic_set(&dwc->in_lpm, 0); + pr_debug("%s():cancel HRTIMER\n", __func__); + hrtimer_cancel(&mdwc->chg_hrtimer); break; case DWC3_CONTROLLER_NOTIFY_OTG_EVENT: dev_dbg(mdwc->dev, "DWC3_CONTROLLER_NOTIFY_OTG_EVENT received\n"); + pr_debug("%s():cancel HRTIMER\n", __func__); + hrtimer_cancel(&mdwc->chg_hrtimer); if (dwc->enable_bus_suspend) { mdwc->suspend = dwc->b_suspend; queue_delayed_work(mdwc->dwc3_resume_wq, @@ -1956,8 +1973,11 @@ static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); if ((mdwc->in_host_mode || (mdwc->vbus_active - && mdwc->otg_state == OTG_STATE_B_SUSPEND)) - && dwc3_msm_is_superspeed(mdwc) && !mdwc->in_restart) { + && mdwc->otg_state == OTG_STATE_B_SUSPEND) + || (mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_PERIPHERAL)) + && dwc3_msm_is_superspeed(mdwc) && !mdwc->in_restart) { + pr_err("HQ----in dwce_msm 1907 host = %d vbus = %d otg = %d\n", mdwc->in_host_mode, mdwc->vbus_active, mdwc->otg_state); + if (!atomic_read(&mdwc->in_p3)) { dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); return -EBUSY; @@ -2182,7 +2202,9 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) * case of host bus suspend and device bus suspend. */ if ((mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_SUSPEND) + || (mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_PERIPHERAL) || mdwc->in_host_mode) { + pr_err("HQ----in dwce_msm 2118 vbus = %d otg = %d in_host_mode = %d\n", mdwc->vbus_active, mdwc-> otg_state, mdwc->in_host_mode); enable_irq_wake(mdwc->hs_phy_irq); enable_irq(mdwc->hs_phy_irq); if (mdwc->ss_phy_irq) { @@ -2343,6 +2365,8 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc) } else { dbg_event(0xFF, "BSV clear", 0); clear_bit(B_SESS_VLD, &mdwc->inputs); + pr_debug("%s(): cancel HRTIMER\n", __func__); + hrtimer_cancel(&mdwc->chg_hrtimer); } if (mdwc->suspend) { @@ -2496,6 +2520,23 @@ static irqreturn_t msm_dwc3_pwr_irq(int irq, void *data) return IRQ_HANDLED; } +static int dwc3_get_prop_usbin_voltage_now(struct dwc3_msm *mdwc) +{ + int rc = 0; + struct qpnp_vadc_result results; + if (IS_ERR_OR_NULL(mdwc->vadc_dev)) { + mdwc->vadc_dev = qpnp_get_vadc(mdwc->dev, "usbin"); + if (IS_ERR(mdwc->vadc_dev)) + return PTR_ERR(mdwc->vadc_dev); + } + rc = qpnp_vadc_read(mdwc->vadc_dev, USBIN, &results); + if (rc) { + pr_err("Unable to read usbin rc=%d\n", rc); + return 0; + } else { + return results.physical; + } +} static int dwc3_msm_power_get_property_usb(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -2530,6 +2571,9 @@ static int dwc3_msm_power_get_property_usb(struct power_supply *psy, case POWER_SUPPLY_PROP_USB_OTG: val->intval = !mdwc->id_state; break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = dwc3_get_prop_usbin_voltage_now(mdwc); + break; default: return -EINVAL; } @@ -2631,16 +2675,8 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, break; case POWER_SUPPLY_PROP_REAL_TYPE: mdwc->usb_supply_type = val->intval; - /* - * Update TYPE property to DCP for HVDCP/HVDCP3 charger types - * so that they can be recongized as AC chargers by healthd. - * Don't report UNKNOWN charger type to prevent healthd missing - * detecting this power_supply status change. - */ - if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3 - || mdwc->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP) - psy->type = POWER_SUPPLY_TYPE_USB_DCP; - else if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) + + if (mdwc->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN) psy->type = POWER_SUPPLY_TYPE_USB; else psy->type = mdwc->usb_supply_type; @@ -2648,6 +2684,8 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, case POWER_SUPPLY_TYPE_USB: mdwc->chg_type = DWC3_SDP_CHARGER; mdwc->voltage_max = MICRO_5V; + pr_debug("%s(): start hrtimer\n", __func__); + hrtimer_start(&mdwc->chg_hrtimer, ktime_set(1, 0), HRTIMER_MODE_REL); break; case POWER_SUPPLY_TYPE_USB_DCP: mdwc->chg_type = DWC3_DCP_CHARGER; @@ -2720,6 +2758,7 @@ static enum power_supply_property dwc3_msm_pm_power_props_usb[] = { POWER_SUPPLY_PROP_TYPE, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_USB_OTG, + POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_REAL_TYPE, }; @@ -2858,6 +2897,22 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) return 0; } +static enum hrtimer_restart chg_hrtimer_func(struct hrtimer *hrtimer) +{ + struct power_supply *usb_psy; + struct dwc3_msm *mdwc = container_of(hrtimer, struct dwc3_msm, chg_hrtimer); + pr_debug("%s(): Inside timer expired. DO floating charger update!\n", __func__); + usb_psy = power_supply_get_by_name("usb"); + if (!usb_psy) + pr_err("usb supply not found!\n"); + + if (mdwc->chg_type == DWC3_SDP_CHARGER) { + dwc3_msm_gadget_vbus_draw(mdwc, 500); + } + + return HRTIMER_NORESTART; +} + static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -3298,6 +3353,9 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (of_property_read_bool(node, "qcom,disable-dev-mode-pm")) pm_runtime_get_noresume(mdwc->dev); + hrtimer_init(&mdwc->chg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + mdwc->chg_hrtimer.function = chg_hrtimer_func; + /* Update initial ID state */ if (mdwc->pmic_id_irq) { enable_irq(mdwc->pmic_id_irq); @@ -3774,6 +3832,7 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) return 0; } +extern enum power_supply_type hvdcp_flag; static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) { enum power_supply_type power_supply_type; @@ -3786,12 +3845,17 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) dev_dbg(mdwc->dev, "SKIP setting power supply type again,chg_type = %d\n", mdwc->chg_type); - goto skip_psy_type; + } dev_dbg(mdwc->dev, "Requested curr from USB = %u, max-type-c:%u\n", mA, mdwc->typec_current_max); + if (hvdcp_flag == POWER_SUPPLY_TYPE_USB_HVDCP || hvdcp_flag == POWER_SUPPLY_TYPE_USB_HVDCP_3) { + pr_err("HVDCP!.\n"); + goto skip_psy_type; + } + if (mdwc->chg_type == DWC3_SDP_CHARGER) power_supply_type = POWER_SUPPLY_TYPE_USB; else if (mdwc->chg_type == DWC3_CDP_CHARGER) @@ -3811,6 +3875,8 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) if (mdwc->chg_type == DWC3_CDP_CHARGER) mA = DWC3_IDEV_CHG_MAX; + + /* Save bc1.2 max_curr if type-c charger later moves to diff mode */ mdwc->bc1p2_current_max = mA; @@ -3915,6 +3981,7 @@ static void dwc3_initialize(struct dwc3_msm *mdwc) PWR_EVNT_POWERDOWN_IN_P3_MASK, 1); } +static int proprietary_chg_flag; /** * dwc3_msm_otg_sm_work - workqueue function. * @@ -3927,6 +3994,7 @@ static void dwc3_msm_otg_sm_work(struct work_struct *w) struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, sm_work.work); struct dwc3 *dwc = NULL; bool work = 0; + u8 dcd = 0; int ret = 0; unsigned long delay = 0; const char *state; @@ -3981,10 +4049,22 @@ static void dwc3_msm_otg_sm_work(struct work_struct *w) dbg_event(0xFF, "undef_b_sess_vld", 0); switch (mdwc->chg_type) { case DWC3_DCP_CHARGER: + dev_dbg(mdwc->dev, "DCP charger\n"); + if (proprietary_chg_flag == 1) { + dwc3_msm_gadget_vbus_draw(mdwc, + DWC3_IDEV_PROPRIETARY_CHG_MAX); + } else { + dwc3_msm_gadget_vbus_draw(mdwc, + dcp_max_current); + } + atomic_set(&dwc->in_lpm, 1); + dbg_event(0xFF, "RelaxDCP", 0); + pm_relax(mdwc->dev); + break; case DWC3_PROPRIETARY_CHARGER: dev_dbg(mdwc->dev, "DCP charger\n"); dwc3_msm_gadget_vbus_draw(mdwc, - dcp_max_current); + DWC3_IDEV_PROPRIETARY_CHG_MAX); atomic_set(&dwc->in_lpm, 1); dbg_event(0xFF, "RelaxDCP", 0); pm_relax(mdwc->dev); @@ -3996,12 +4076,35 @@ static void dwc3_msm_otg_sm_work(struct work_struct *w) pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); + dwc3_msm_gadget_vbus_draw(mdwc, 0); + msleep(dcd_delay_ms); + + dcd = qusb_phy_run_dcd(mdwc->hs_phy); + pr_err("dwc3---dcd = %d\n", dcd); + if (dcd == 0x1) { + mdwc->chg_type = DWC3_PROPRIETARY_CHARGER; + pm_runtime_put_sync(mdwc->dev); + dbg_event(0xFF, "BDCD-Fpsync", + atomic_read(&mdwc->dev->power.usage_count)); + mdwc->otg_state = OTG_STATE_B_IDLE; + work = 1; + proprietary_chg_flag = 1; + break; + } else if (dcd == 0x5) { + mdwc->chg_type = DWC3_DCP_CHARGER; + pm_runtime_put_sync(mdwc->dev); + dbg_event(0xFF, "BDCD-Dpsync", atomic_read(&mdwc->dev->power.usage_count)); + mdwc->otg_state = OTG_STATE_B_IDLE; + work = 1; + proprietary_chg_flag = 0; + break; + } /* check dp/dm for SDP & runtime_put if !SDP */ if (mdwc->detect_dpdm_floating && mdwc->chg_type == DWC3_SDP_CHARGER) { dwc3_check_float_lines(mdwc); - if (mdwc->chg_type != DWC3_SDP_CHARGER) - break; + + } dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; @@ -4039,10 +4142,21 @@ static void dwc3_msm_otg_sm_work(struct work_struct *w) dbg_event(0xFF, "b_sess_vld", 0); switch (mdwc->chg_type) { case DWC3_DCP_CHARGER: + dbg_event(0xFF, "DCPCharger", 0); + if (proprietary_chg_flag == 1) { + dwc3_msm_gadget_vbus_draw(mdwc, + DWC3_IDEV_PROPRIETARY_CHG_MAX); + } else { + dwc3_msm_gadget_vbus_draw(mdwc, + dcp_max_current); + } + dbg_event(0xFF, "RelDCPBIDLE", 0); + pm_relax(mdwc->dev); + break; case DWC3_PROPRIETARY_CHARGER: dbg_event(0xFF, "DCPCharger", 0); dwc3_msm_gadget_vbus_draw(mdwc, - dcp_max_current); + DWC3_IDEV_PROPRIETARY_CHG_MAX); dbg_event(0xFF, "RelDCPBIDLE", 0); pm_relax(mdwc->dev); break; @@ -4063,6 +4177,29 @@ static void dwc3_msm_otg_sm_work(struct work_struct *w) dbg_event(0xFF, "CHG gsync", atomic_read( &mdwc->dev->power.usage_count)); + dwc3_msm_gadget_vbus_draw(mdwc, 0); + msleep(dcd_delay_ms); + pr_err("dwc3---mdwc = %d\n", mdwc->chg_type); + dcd = qusb_phy_run_dcd(mdwc->hs_phy); + pr_err("dwc3---dcd = %d\n", dcd); + if (dcd == 0x1) { + mdwc->chg_type = DWC3_PROPRIETARY_CHARGER; + pm_runtime_put_sync(mdwc->dev); + dbg_event(0xFF, "BDCD-Fpsync", + atomic_read(&mdwc->dev->power.usage_count)); + mdwc->otg_state = OTG_STATE_B_IDLE; + work = 1; + proprietary_chg_flag = 1; + break; + }else if (dcd == 0x5) { + mdwc->chg_type = DWC3_DCP_CHARGER; + pm_runtime_put_sync(mdwc->dev); + dbg_event(0xFF, "BDCD-Dpsync", atomic_read(&mdwc->dev->power.usage_count)); + mdwc->otg_state = OTG_STATE_B_IDLE; + work = 1; + proprietary_chg_flag = 0; + break; + } /* check dp/dm for SDP & runtime_put if !SDP */ if (mdwc->detect_dpdm_floating && mdwc->chg_type == DWC3_SDP_CHARGER) { @@ -4080,6 +4217,7 @@ static void dwc3_msm_otg_sm_work(struct work_struct *w) } } else { mdwc->typec_current_max = 0; + proprietary_chg_flag = 0; dwc3_msm_gadget_vbus_draw(mdwc, 0); dev_dbg(mdwc->dev, "No device, allowing suspend\n"); dbg_event(0xFF, "RelNodev", 0); diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 59ab62c92b666..a270640acce96 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -2,6 +2,7 @@ * f_hid.c -- USB HID function driver * * Copyright (C) 2010 Fabien Chouteau + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -197,6 +198,13 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, /* pick the first one */ list = list_first_entry(&hidg->completed_out_req, struct f_hidg_req_list, list); + + /* + * Remove this from list to protect it from beign free() + * while host disables our function + */ + list_del(&list->list); + req = list->req; count = min_t(unsigned int, count, req->actual - list->pos); spin_unlock_irqrestore(&hidg->spinlock, flags); @@ -212,15 +220,20 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer, * call, taking into account its current read position. */ if (list->pos == req->actual) { - spin_lock_irqsave(&hidg->spinlock, flags); - list_del(&list->list); kfree(list); - spin_unlock_irqrestore(&hidg->spinlock, flags); req->length = hidg->report_length; ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL); - if (ret < 0) + if (ret < 0) { + free_ep_req(hidg->out_ep, req); return ret; + } + } else { + spin_lock_irqsave(&hidg->spinlock, flags); + list_add(&list->list, &hidg->completed_out_req); + spin_unlock_irqrestore(&hidg->spinlock, flags); + + wake_up(&hidg->read_queue); } return count; @@ -455,6 +468,7 @@ static void hidg_disable(struct usb_function *f) { struct f_hidg *hidg = func_to_hidg(f); struct f_hidg_req_list *list, *next; + unsigned long flags; usb_ep_disable(hidg->in_ep); hidg->in_ep->driver_data = NULL; @@ -462,10 +476,13 @@ static void hidg_disable(struct usb_function *f) usb_ep_disable(hidg->out_ep); hidg->out_ep->driver_data = NULL; + spin_lock_irqsave(&hidg->spinlock, flags); list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) { + free_ep_req(hidg->out_ep, list->req); list_del(&list->list); kfree(list); } + spin_unlock_irqrestore(&hidg->spinlock, flags); } static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 8000d3a7d4621..1c98fccfd4dd7 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -198,6 +198,16 @@ config MSM_QUSB_PHY Synopsys DWC3 USB IPs on MSM SOCs. This driver expects to configure the PHY with a dedicated register I/O memory region. +config MSM_QUSB_PHY_E7 + tristate "MSM QUSB2 PHY Driver" + depends on ARCH_MSM + select USB_PHY + help + Enable this to support the QUSB2 PHY on MSM chips for E7O. This driver supports + the high-speed PHY which is usually paired with either the ChipIdea or + Synopsys DWC3 USB IPs on MSM SOCs. This driver expects to configure the + PHY with a dedicated register I/O memory region. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index a8ece39a9e673..4f15963185c64 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_USB_MSM_HSPHY) += phy-msm-hsusb.o obj-$(CONFIG_USB_MSM_SSPHY) += phy-msm-ssusb.o obj-$(CONFIG_USB_MSM_SSPHY_QMP) += phy-msm-ssusb-qmp.o obj-$(CONFIG_MSM_QUSB_PHY) += phy-msm-qusb.o phy-msm-qusb-v2.o +obj-$(CONFIG_MSM_QUSB_PHY_E7) += phy-msm-qusb_e7.o phy-msm-qusb-v2.o obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c index 59052aeda020c..3c1e7e0728e24 100644 --- a/drivers/usb/phy/phy-msm-qusb.c +++ b/drivers/usb/phy/phy-msm-qusb.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -116,7 +117,16 @@ #define QUSB2PHY_LVL_SHIFTER_CMD_ID 0x1B -unsigned int tune2; +#define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1C +#define QUSB2PHY_PLL_PWR_CTL 0x18 +#define REF_BUF_EN BIT(0) +#define REXT_EN BIT(1) +#define PLL_BYPASSNL BIT(2) +#define QUSB2PHY_PORT_QUICKCHARGE1 0x70 +#define QUSB2PHY_PORT_QUICKCHARGE2 0x74 +#define QUSB2PHY_PORT_INT_STATUS 0xF0 + +unsigned int tune2 = 0x5F; module_param(tune2, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2"); @@ -896,6 +906,60 @@ static void qusb_phy_shutdown(struct usb_phy *phy) qusb_phy_enable_clocks(qphy, false); } +int qusb_phy_dumpreg(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + pr_debug("%s:dump_phy_registers\n", __func__); + pr_debug("PORT_PWRDWN:%08x\n", readl_relaxed(qphy->base+ QUSB2PHY_PORT_POWERDOWN)); + pr_debug("UTMCTL1:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_UTMI_CTRL1)); + pr_debug("UTMCTL2:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_UTMI_CTRL2)); + pr_debug("AUTOPGM_CTL1:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1)); + pr_debug("PORT_PWRDWN:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PLL_PWR_CTL)); + pr_debug("linestate:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_UTMI_STATUS)); + pr_debug("!!\n!!INT_STATUS:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_INT_STATUS)); + return 0; +} + +int qusb_phy_run_dcd(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + u8 int_status; + + writel_relaxed(0x23, qphy->base + QUSB2PHY_PORT_POWERDOWN); + /*23*/ + writel_relaxed(0x35, qphy-> base + QUSB2PHY_PORT_UTMI_CTRL1); + writel_relaxed(0xC0, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + writel_relaxed(0x05, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); + writel_relaxed(0x22, qphy->base + QUSB2PHY_PORT_POWERDOWN); + /*22*/ + writel_relaxed(0x17, qphy->base+ QUSB2PHY_PLL_PWR_CTL); + usleep_range(5, 1000); + writel_relaxed(0x15, qphy->base+ QUSB2PHY_PLL_AUTOPGM_CTL1); + usleep_range(50, 1000); + writel_relaxed(0x09, + qphy->base+ QUSB2PHY_PORT_QUICKCHARGE2); + writel_relaxed(0x00, qphy->base+ QUSB2PHY_PORT_QUICKCHARGE1); + writel_relaxed(0x00, qphy->base+ QUSB2PHY_PORT_QUICKCHARGE2); + writel_relaxed(0x1F, qphy->base+ QUSB2PHY_PORT_INTR_CTRL); + writel_relaxed(0x08, qphy->base+ QUSB2PHY_PORT_QUICKCHARGE1); + usleep_range(1000, 2000); + int_status = readl_relaxed(qphy->base+ QUSB2PHY_PORT_INT_STATUS); + qusb_phy_dumpreg(phy); + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, qphy->base+ QUSB2PHY_PORT_POWERDOWN); + /*23*/ + writel_relaxed(0x95, qphy->base+ QUSB2PHY_PLL_AUTOPGM_CTL1); + writel_relaxed(0x80, qphy->base+ QUSB2PHY_PORT_UTMI_CTRL2); + writel_relaxed(0x10, qphy->base+ QUSB2PHY_PORT_UTMI_CTRL1); + writel_relaxed(CLAMP_N_EN |FREEZIO_N, qphy->base+ QUSB2PHY_PORT_POWERDOWN); + + int_status = int_status & 0x5; + pr_debug("%s: int_status:%x\n", __func__, int_status); + + return int_status; +} +EXPORT_SYMBOL(qusb_phy_run_dcd); + /** * Returns DP/DM linestate with Idp_src enabled to detect if lines are floating * diff --git a/drivers/usb/phy/phy-msm-qusb_e7.c b/drivers/usb/phy/phy-msm-qusb_e7.c new file mode 100644 index 0000000000000..0a62755ad8455 --- /dev/null +++ b/drivers/usb/phy/phy-msm-qusb_e7.c @@ -0,0 +1,1499 @@ +/* + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* TCSR_PHY_CLK_SCHEME_SEL bit mask */ +#define PHY_CLK_SCHEME_SEL BIT(0) + +#define QUSB2PHY_PLL_PWR_CTL 0x18 +#define REF_BUF_EN BIT(0) +#define REXT_EN BIT(1) +#define PLL_BYPASSNL BIT(2) +#define REXT_TRIM_0 BIT(4) + +#define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1C +#define PLL_RESET_N_CNT_5 0x5 +#define PLL_RESET_N BIT(4) +#define PLL_AUTOPGM_EN BIT(7) + +#define QUSB2PHY_PORT_QUICKCHARGE1 0x70 +#define IDP_SRC_EN BIT(3) + +#define QUSB2PHY_PORT_QUICKCHARGE2 0x74 +#define QUSB2PHY_PORT_INT_STATUS 0xF0 + +#define QUSB2PHY_PLL_STATUS 0x38 +#define QUSB2PHY_PLL_LOCK BIT(5) + +#define QUSB2PHY_PORT_QC1 0x70 +#define VDM_SRC_EN BIT(4) +#define VDP_SRC_EN BIT(2) + +#define QUSB2PHY_PORT_QC2 0x74 +#define RDM_UP_EN BIT(1) +#define RDP_UP_EN BIT(3) +#define RPUM_LOW_EN BIT(4) +#define RPUP_LOW_EN BIT(5) + +#define QUSB2PHY_PORT_POWERDOWN 0xB4 +#define CLAMP_N_EN BIT(5) +#define FREEZIO_N BIT(1) +#define POWER_DOWN BIT(0) + +#define QUSB2PHY_PORT_TEST_CTRL 0xB8 + +#define QUSB2PHY_PORT_UTMI_CTRL1 0xC0 +#define SUSPEND_N BIT(5) +#define TERM_SELECT BIT(4) +#define XCVR_SELECT_FS BIT(2) +#define OP_MODE_NON_DRIVE BIT(0) + +#define QUSB2PHY_PORT_UTMI_CTRL2 0xC4 +#define UTMI_ULPI_SEL BIT(7) +#define UTMI_TEST_MUX_SEL BIT(6) + +#define QUSB2PHY_PLL_TEST 0x04 +#define CLK_REF_SEL BIT(7) + +#define QUSB2PHY_PORT_TUNE1 0x80 +#define QUSB2PHY_PORT_TUNE2 0x84 +#define QUSB2PHY_PORT_TUNE3 0x88 +#define QUSB2PHY_PORT_TUNE4 0x8C + +/* In case Efuse register shows zero, use this value */ +#define TUNE2_DEFAULT_HIGH_NIBBLE 0xB +#define TUNE2_DEFAULT_LOW_NIBBLE 0x3 + +/* Get TUNE2's high nibble value read from efuse */ +#define TUNE2_HIGH_NIBBLE_VAL(val, pos, mask) ((val >> pos) & mask) + +#define QUSB2PHY_PORT_INTR_CTRL 0xBC +#define CHG_DET_INTR_EN BIT(4) +#define DMSE_INTR_HIGH_SEL BIT(3) +#define DMSE_INTR_EN BIT(2) +#define DPSE_INTR_HIGH_SEL BIT(1) +#define DPSE_INTR_EN BIT(0) + +#define QUSB2PHY_PORT_UTMI_STATUS 0xF4 +#define LINESTATE_DP BIT(0) +#define LINESTATE_DM BIT(1) + + +#define QUSB2PHY_1P8_VOL_MIN 1800000 /* uV */ +#define QUSB2PHY_1P8_VOL_MAX 1800000 /* uV */ +#define QUSB2PHY_1P8_HPM_LOAD 30000 /* uA */ + +#define QUSB2PHY_3P3_VOL_MIN 3075000 /* uV */ +#define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ +#define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ + +#define QUSB2PHY_REFCLK_ENABLE BIT(0) + +#define QUSB2PHY_LVL_SHIFTER_CMD_ID 0x1B + +#define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1C +#define QUSB2PHY_PLL_PWR_CTL 0x18 +#define REF_BUF_EN BIT(0) +#define REXT_EN BIT(1) +#define PLL_BYPASSNL BIT(2) +#define QUSB2PHY_PORT_QUICKCHARGE1 0x70 +#define QUSB2PHY_PORT_QUICKCHARGE2 0x74 +#define QUSB2PHY_PORT_INT_STATUS 0xF0 + +unsigned int tune2; +module_param(tune2, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2"); + +struct qusb_phy { + struct usb_phy phy; + void __iomem *base; + void __iomem *tune2_efuse_reg; + void __iomem *ref_clk_base; + void __iomem *tcsr_phy_clk_scheme_sel; + void __iomem *tcsr_phy_lvl_shift_keeper; + + struct clk *ref_clk_src; + struct clk *ref_clk; + struct clk *cfg_ahb_clk; + struct clk *phy_reset; + struct clk *iface_clk; + struct clk *core_clk; + + struct regulator *gdsc; + struct regulator *vdd; + struct regulator *vdda33; + struct regulator *vdda18; + int vdd_levels[3]; /* none, low, high */ + int init_seq_len; + int *qusb_phy_init_seq; + + u32 tune2_val; + int tune2_efuse_bit_pos; + int tune2_efuse_num_of_bits; + int tune2_efuse_correction; + + bool vdd_enabled; + bool power_enabled; + bool clocks_enabled; + bool cable_connected; + bool suspended; + bool ulpi_mode; + bool rm_pulldown; + bool dpdm_pulsing_enabled; + + /* emulation targets specific */ + void __iomem *emu_phy_base; + bool emulation; + int *emu_init_seq; + int emu_init_seq_len; + int *phy_pll_reset_seq; + int phy_pll_reset_seq_len; + int *emu_dcm_reset_seq; + int emu_dcm_reset_seq_len; + spinlock_t pulse_lock; + bool put_into_high_z_state; + bool scm_lvl_shifter_update; +}; + +static void qusb_phy_update_tcsr_level_shifter(struct qusb_phy *qphy, u32 val) +{ + int scm_ret, resp_ret = 0; + int dummy = 0; + + dev_dbg(qphy->phy.dev, "%s(): update tcsr lvl shift value:%d\n", + __func__, val); + if (qphy->tcsr_phy_lvl_shift_keeper) + writel_relaxed(val, qphy->tcsr_phy_lvl_shift_keeper); + + else if (qphy->scm_lvl_shifter_update) { + if (!is_scm_armv8()) { + scm_ret = scm_call(SCM_SVC_BOOT, + QUSB2PHY_LVL_SHIFTER_CMD_ID, &val, + sizeof(val), &resp_ret, + sizeof(resp_ret)); + } else { + struct scm_desc desc = {0}; + + desc.arginfo = SCM_ARGS(2); + desc.args[0] = val; + desc.args[1] = dummy; + + scm_ret = scm_call2(SCM_SIP_FNID(SCM_SVC_BOOT, + QUSB2PHY_LVL_SHIFTER_CMD_ID), + &desc); + } + dev_dbg(qphy->phy.dev, "%s(): scm_ret:%d resp_ret:%d\n", + __func__, scm_ret, resp_ret); + } +} + +static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) +{ + dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n", + __func__, qphy->clocks_enabled, on); + + if (!qphy->clocks_enabled && on) { + clk_prepare_enable(qphy->ref_clk_src); + clk_prepare_enable(qphy->ref_clk); + clk_prepare_enable(qphy->iface_clk); + clk_prepare_enable(qphy->core_clk); + clk_prepare_enable(qphy->cfg_ahb_clk); + qphy->clocks_enabled = true; + } + + if (qphy->clocks_enabled && !on) { + clk_disable_unprepare(qphy->cfg_ahb_clk); + /* + * FSM depedency beween iface_clk and core_clk. + * Hence turned off core_clk before iface_clk. + */ + clk_disable_unprepare(qphy->core_clk); + clk_disable_unprepare(qphy->iface_clk); + clk_disable_unprepare(qphy->ref_clk); + clk_disable_unprepare(qphy->ref_clk_src); + qphy->clocks_enabled = false; + } + + dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d\n", __func__, + qphy->clocks_enabled); +} + +static int qusb_phy_gdsc(struct qusb_phy *qphy, bool on) +{ + int ret; + + if (IS_ERR_OR_NULL(qphy->gdsc)) + return -EPERM; + + if (on) { + dev_dbg(qphy->phy.dev, "TURNING ON GDSC\n"); + ret = regulator_enable(qphy->gdsc); + if (ret) { + dev_err(qphy->phy.dev, "unable to enable gdsc\n"); + return ret; + } + } else { + dev_dbg(qphy->phy.dev, "TURNING OFF GDSC\n"); + ret = regulator_disable(qphy->gdsc); + if (ret) { + dev_err(qphy->phy.dev, "unable to disable gdsc\n"); + return ret; + } + } + + return ret; +} + +static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high) +{ + int min, ret; + + min = high ? 1 : 0; /* low or none? */ + ret = regulator_set_voltage(qphy->vdd, qphy->vdd_levels[min], + qphy->vdd_levels[2]); + if (ret) { + dev_err(qphy->phy.dev, "unable to set voltage for qusb vdd\n"); + return ret; + } + + dev_dbg(qphy->phy.dev, "min_vol:%d max_vol:%d\n", + qphy->vdd_levels[min], qphy->vdd_levels[2]); + return ret; +} + +static int qusb_phy_vdd(struct qusb_phy *qphy, bool on) +{ + int ret = 0; + + if (!qphy->vdd_enabled && on) { + dev_dbg(qphy->phy.dev, "TURNING ON VDD\n"); + ret = qusb_phy_config_vdd(qphy, true); + if (ret) { + dev_err(qphy->phy.dev, "Unable to config VDD:%d\n", + ret); + goto err; + } + + ret = regulator_enable(qphy->vdd); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable VDD\n"); + goto err; + } + qphy->vdd_enabled = true; + } + + if (qphy->vdd_enabled && !on) { + dev_dbg(qphy->phy.dev, "TURNING OFF VDD\n"); + ret = regulator_disable(qphy->vdd); + if (ret) { + dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n", + ret); + goto err; + } + + ret = qusb_phy_config_vdd(qphy, false); + if (ret) { + dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n", ret); + goto err; + } + qphy->vdd_enabled = false; + } +err: + return ret; +} + +static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on) +{ + int ret = 0; + + dev_dbg(qphy->phy.dev, "%s turn %s regulators. power_enabled:%d\n", + __func__, on ? "on" : "off", qphy->power_enabled); + + if (qphy->power_enabled == on) { + dev_dbg(qphy->phy.dev, "PHYs' regulators are already ON.\n"); + return 0; + } + + if (!on) + goto disable_vdda33; + + ret = qusb_phy_vdd(qphy, true); + if (ret < 0) + goto err_vdd; + + ret = regulator_set_optimum_mode(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of vdda18:%d\n", ret); + goto disable_vdd; + } + + ret = regulator_set_voltage(qphy->vdda18, QUSB2PHY_1P8_VOL_MIN, + QUSB2PHY_1P8_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for vdda18:%d\n", ret); + goto put_vdda18_lpm; + } + + ret = regulator_enable(qphy->vdda18); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable vdda18:%d\n", ret); + goto unset_vdda18; + } + + ret = regulator_set_optimum_mode(qphy->vdda33, QUSB2PHY_3P3_HPM_LOAD); + if (ret < 0) { + dev_err(qphy->phy.dev, "Unable to set HPM of vdda33:%d\n", ret); + goto disable_vdda18; + } + + ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN, + QUSB2PHY_3P3_VOL_MAX); + if (ret) { + dev_err(qphy->phy.dev, + "Unable to set voltage for vdda33:%d\n", ret); + goto put_vdda33_lpm; + } + + ret = regulator_enable(qphy->vdda33); + if (ret) { + dev_err(qphy->phy.dev, "Unable to enable vdda33:%d\n", ret); + goto unset_vdd33; + } + + qphy->power_enabled = true; + + pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__); + return ret; + +disable_vdda33: + ret = regulator_disable(qphy->vdda33); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret); + +unset_vdd33: + ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda33:%d\n", ret); + +put_vdda33_lpm: + ret = regulator_set_optimum_mode(qphy->vdda33, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set (0) HPM of vdda33\n"); + +disable_vdda18: + ret = regulator_disable(qphy->vdda18); + if (ret) + dev_err(qphy->phy.dev, "Unable to disable vdda18:%d\n", ret); + +unset_vdda18: + ret = regulator_set_voltage(qphy->vdda18, 0, QUSB2PHY_1P8_VOL_MAX); + if (ret) + dev_err(qphy->phy.dev, + "Unable to set (0) voltage for vdda18:%d\n", ret); + +put_vdda18_lpm: + ret = regulator_set_optimum_mode(qphy->vdda18, 0); + if (ret < 0) + dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n"); + +disable_vdd: + ret = qusb_phy_vdd(qphy, false); +err_vdd: + qphy->power_enabled = false; + dev_dbg(qphy->phy.dev, "QUSB PHY's regulators are turned OFF.\n"); + return ret; +} + +#define PHY_PULSE_TIME_USEC 250 +static int qusb_phy_update_dpdm(struct usb_phy *phy, int value) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + unsigned long flags; + int ret = 0; + u32 reg; + + dev_dbg(phy->dev, "%s value:%d rm_pulldown:%d pulsing enabled %d\n", + __func__, value, qphy->rm_pulldown, + qphy->dpdm_pulsing_enabled); + + switch (value) { + case POWER_SUPPLY_DP_DM_DPF_DMF: + dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DPF_DMF\n"); + if (!qphy->rm_pulldown) { + ret = qusb_phy_enable_power(qphy, true); + if (ret >= 0) { + qphy->rm_pulldown = true; + dev_dbg(phy->dev, "DP_DM_F: rm_pulldown:%d\n", + qphy->rm_pulldown); + } + + if (qphy->put_into_high_z_state) { + qusb_phy_update_tcsr_level_shifter(qphy, 0x1); + qusb_phy_gdsc(qphy, true); + qusb_phy_enable_clocks(qphy, true); + + dev_dbg(phy->dev, "RESET QUSB PHY\n"); + clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + usleep_range(100, 150); + clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + + /* + * Phy in non-driving mode leaves Dp and Dm + * lines in high-Z state. Controller power + * collapse is not switching phy to non-driving + * mode causing charger detection failure. Bring + * phy to non-driving mode by overriding + * controller output via UTMI interface. + */ + writel_relaxed(TERM_SELECT | XCVR_SELECT_FS | + OP_MODE_NON_DRIVE, + qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); + writel_relaxed(UTMI_ULPI_SEL | + UTMI_TEST_MUX_SEL, + qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + + /* Disable PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N | + POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + /* Make sure that above write is completed */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); + qusb_phy_gdsc(qphy, false); + } + } + + /* Clear QC1 and QC2 registers when rm_pulldown = 1 */ + if (qphy->dpdm_pulsing_enabled && qphy->rm_pulldown) { + dev_dbg(phy->dev, "clearing qc1 and qc2 registers.\n"); + ret = clk_prepare_enable(qphy->cfg_ahb_clk); + if (ret) + goto clk_error; + + /* Clear qc1 and qc2 registers */ + writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QC1); + writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QC2); + /* to make sure above write goes through */ + mb(); + clk_disable_unprepare(qphy->cfg_ahb_clk); + } + break; + + case POWER_SUPPLY_DP_DM_DPR_DMR: + dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DPR_DMR\n"); + if (qphy->rm_pulldown) { + dev_dbg(phy->dev, "clearing qc1 and qc2 registers.\n"); + if (qphy->dpdm_pulsing_enabled) { + ret = clk_prepare_enable(qphy->cfg_ahb_clk); + if (ret) + goto clk_error; + + /* Clear qc1 and qc2 registers */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_QC1); + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_QC2); + /* to make sure above write goes through */ + mb(); + clk_disable_unprepare(qphy->cfg_ahb_clk); + } + + if (!qphy->cable_connected) { + qusb_phy_update_tcsr_level_shifter(qphy, 0x0); + dev_dbg(phy->dev, "turn off for HVDCP case\n"); + ret = qusb_phy_enable_power(qphy, false); + } + if (ret >= 0) { + qphy->rm_pulldown = false; + dev_dbg(phy->dev, "DP_DM_R: rm_pulldown:%d\n", + qphy->rm_pulldown); + } + } + break; + + case POWER_SUPPLY_DP_DM_DP0P6_DMF: + if (!qphy->dpdm_pulsing_enabled) + break; + + dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DP0P6_DMF\n"); + ret = clk_prepare_enable(qphy->cfg_ahb_clk); + if (ret) + goto clk_error; + + /* Set DP to 0.6v and DM to High Z state */ + writel_relaxed(VDP_SRC_EN, qphy->base + QUSB2PHY_PORT_QC1); + /* complete above write */ + mb(); + clk_disable_unprepare(qphy->cfg_ahb_clk); + break; + + case POWER_SUPPLY_DP_DM_DP0P6_DM3P3: + if (!qphy->dpdm_pulsing_enabled) + break; + + dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DP0PHVDCP_36_DM3P3\n"); + ret = clk_prepare_enable(qphy->cfg_ahb_clk); + if (ret) + goto clk_error; + + /* Set DP to 0.6v */ + writel_relaxed(VDP_SRC_EN, qphy->base + QUSB2PHY_PORT_QC1); + /* Set DM to 3.075v */ + writel_relaxed(RPUM_LOW_EN | RDM_UP_EN, + qphy->base + QUSB2PHY_PORT_QC2); + /* complete above write */ + mb(); + clk_disable_unprepare(qphy->cfg_ahb_clk); + break; + + case POWER_SUPPLY_DP_DM_DP_PULSE: + if (!qphy->dpdm_pulsing_enabled) + break; + + dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DP_PULSE\n"); + ret = clk_prepare_enable(qphy->cfg_ahb_clk); + if (ret) + goto clk_error; + + spin_lock_irqsave(&qphy->pulse_lock, flags); + /*Set DP to 3.075v, sleep for .25 ms */ + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC2); + reg |= (RDP_UP_EN | RPUP_LOW_EN); + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC2); + + /* complete above write */ + mb(); + + /* + * It is recommended to wait here to get voltage change on + * DP/DM line. + */ + udelay(PHY_PULSE_TIME_USEC); + + /* Set DP to 0.6v, sleep 2-3ms */ + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC1); + reg |= VDP_SRC_EN; + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC1); + + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC2); + reg &= ~(RDP_UP_EN | RPUP_LOW_EN); + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC2); + /* complete above write */ + mb(); + spin_unlock_irqrestore(&qphy->pulse_lock, flags); + /* + * It is recommended to wait here to get voltage change on + * DP/DM line. + */ + usleep_range(2000, 3000); + clk_disable_unprepare(qphy->cfg_ahb_clk); + break; + + case POWER_SUPPLY_DP_DM_DM_PULSE: + if (!qphy->dpdm_pulsing_enabled) + break; + + dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DM_PULSE\n"); + ret = clk_prepare_enable(qphy->cfg_ahb_clk); + if (ret) + goto clk_error; + + spin_lock_irqsave(&qphy->pulse_lock, flags); + /* Set DM to 0.6v, sleep .25 ms */ + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC1); + reg |= VDM_SRC_EN; + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC1); + + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC2); + reg &= ~(RDM_UP_EN | RPUM_LOW_EN); + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC2); + + /* complete above write */ + mb(); + + /* + * It is recommended to wait here to get voltage change on + * DP/DM line. + */ + udelay(PHY_PULSE_TIME_USEC); + + /* DM to 3.075v, sleep 2-3ms */ + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC2); + reg |= (RPUM_LOW_EN | RDM_UP_EN); + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC2); + + reg = readl_relaxed(qphy->base + QUSB2PHY_PORT_QC1); + reg &= ~VDM_SRC_EN; + writel_relaxed(reg, qphy->base + QUSB2PHY_PORT_QC1); + + /* complete above write */ + mb(); + spin_unlock_irqrestore(&qphy->pulse_lock, flags); + + /* + * It is recommended to wait here to get voltage change on + * DP/DM line. + */ + usleep_range(2000, 3000); + clk_disable_unprepare(qphy->cfg_ahb_clk); + break; + default: + ret = -EINVAL; + dev_err(phy->dev, "Invalid power supply property(%d)\n", value); + break; + } + +clk_error: + return ret; +} + +static void qusb_phy_get_tune2_param(struct qusb_phy *qphy) +{ + u8 num_of_bits; + u32 bit_mask = 1; + + pr_debug("%s(): num_of_bits:%d bit_pos:%d\n", __func__, + qphy->tune2_efuse_num_of_bits, + qphy->tune2_efuse_bit_pos); + + /* get bit mask based on number of bits to use with efuse reg */ + if (qphy->tune2_efuse_num_of_bits) { + num_of_bits = qphy->tune2_efuse_num_of_bits; + bit_mask = (bit_mask << num_of_bits) - 1; + } + + /* + * Read EFUSE register having TUNE2 parameter's high nibble. + * If efuse register shows value as 0x0, then use default value + * as 0xB as high nibble. Otherwise use efuse register based + * value for this purpose. + */ + qphy->tune2_val = readl_relaxed(qphy->tune2_efuse_reg); + pr_debug("%s(): bit_mask:%d efuse based tune2 value:%d\n", + __func__, bit_mask, qphy->tune2_val); + + qphy->tune2_val = TUNE2_HIGH_NIBBLE_VAL(qphy->tune2_val, + qphy->tune2_efuse_bit_pos, bit_mask); + + /* Update higher nibble of TUNE2 value for better rise/fall times */ + if (qphy->tune2_efuse_correction) { + if (qphy->tune2_efuse_correction > 5 || + qphy->tune2_efuse_correction < -10) + pr_warn("Correction value is out of range : %d\n", + qphy->tune2_efuse_correction); + else + qphy->tune2_val = qphy->tune2_val + + qphy->tune2_efuse_correction; + } + + if (!qphy->tune2_val) + qphy->tune2_val = TUNE2_DEFAULT_HIGH_NIBBLE; + + /* Get TUNE2 byte value using high and low nibble value */ + qphy->tune2_val = ((qphy->tune2_val << 0x4) | + TUNE2_DEFAULT_LOW_NIBBLE); +} + +static void qusb_phy_write_seq(void __iomem *base, u32 *seq, int cnt, + unsigned long delay) +{ + int i; + + pr_debug("Seq count:%d\n", cnt); + for (i = 0; i < cnt; i = i+2) { + pr_debug("write 0x%02x to 0x%02x\n", seq[i], seq[i+1]); + writel_relaxed(seq[i], base + seq[i+1]); + if (delay) + usleep_range(delay, (delay + 2000)); + } +} + +static int qusb_phy_init(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + int ret, reset_val = 0; + bool is_se_clk = true; + + dev_dbg(phy->dev, "%s\n", __func__); + + ret = qusb_phy_enable_power(qphy, true); + if (ret) + return ret; + + qusb_phy_enable_clocks(qphy, true); + + /* + * ref clock is enabled by default after power on reset. Linux clock + * driver will disable this clock as part of late init if peripheral + * driver(s) does not explicitly votes for it. Linux clock driver also + * does not disable the clock until late init even if peripheral + * driver explicitly requests it and cannot defer the probe until late + * init. Hence, Explicitly disable the clock using register write to + * allow QUSB PHY PLL to lock properly. + */ + if (qphy->ref_clk_base) { + writel_relaxed((readl_relaxed(qphy->ref_clk_base) & + ~QUSB2PHY_REFCLK_ENABLE), + qphy->ref_clk_base); + /* Make sure that above write complete to get ref clk OFF */ + wmb(); + } + + /* Perform phy reset */ + clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + usleep_range(100, 150); + clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); + + if (qphy->emulation) { + if (qphy->emu_init_seq) + qusb_phy_write_seq(qphy->emu_phy_base, + qphy->emu_init_seq, qphy->emu_init_seq_len, 0); + + if (qphy->qusb_phy_init_seq) + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq, + qphy->init_seq_len, 0); + + /* Wait for 5ms as per QUSB2 RUMI sequence */ + usleep_range(5000, 7000); + + if (qphy->phy_pll_reset_seq) + qusb_phy_write_seq(qphy->base, qphy->phy_pll_reset_seq, + qphy->phy_pll_reset_seq_len, 10000); + + if (qphy->emu_dcm_reset_seq) + qusb_phy_write_seq(qphy->emu_phy_base, + qphy->emu_dcm_reset_seq, + qphy->emu_dcm_reset_seq_len, 10000); + + return 0; + } + + /* Disable the PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + + /* configure for ULPI mode if requested */ + if (qphy->ulpi_mode) + writel_relaxed(0x0, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + + /* save reset value to override based on clk scheme */ + reset_val = readl_relaxed(qphy->base + QUSB2PHY_PLL_TEST); + + if (qphy->qusb_phy_init_seq) + qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq, + qphy->init_seq_len, 0); + + /* + * Check for EFUSE value only if tune2_efuse_reg is available + * and try to read EFUSE value only once i.e. not every USB + * cable connect case. + */ + if (qphy->tune2_efuse_reg) { + if (!qphy->tune2_val) + qusb_phy_get_tune2_param(qphy); + + pr_debug("%s(): Programming TUNE2 parameter as:%x\n", __func__, + qphy->tune2_val); + writel_relaxed(qphy->tune2_val, + qphy->base + QUSB2PHY_PORT_TUNE2); + } + + /* If tune2 modparam set, override tune2 value */ + if (tune2) { + pr_debug("%s(): (modparam) TUNE2 val:0x%02x\n", + __func__, tune2); + writel_relaxed(tune2, + qphy->base + QUSB2PHY_PORT_TUNE2); + } + + /* ensure above writes are completed before re-enabling PHY */ + wmb(); + + /* Enable the PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + + /* Ensure above write is completed before turning ON ref clk */ + wmb(); + + /* Require to get phy pll lock successfully */ + usleep_range(150, 160); + + if (qphy->tcsr_phy_clk_scheme_sel) { + ret = readl_relaxed(qphy->tcsr_phy_clk_scheme_sel); + if (ret & PHY_CLK_SCHEME_SEL) { + pr_debug("%s:select single-ended clk src\n", + __func__); + is_se_clk = true; + } else { + pr_debug("%s:select differential clk src\n", + __func__); + is_se_clk = false; + } + } + + if (!is_se_clk) + reset_val &= ~CLK_REF_SEL; + else + reset_val |= CLK_REF_SEL; + + /* Turn on phy ref_clk if DIFF_CLK else select SE_CLK */ + if (!is_se_clk && qphy->ref_clk_base) + writel_relaxed((readl_relaxed(qphy->ref_clk_base) | + QUSB2PHY_REFCLK_ENABLE), + qphy->ref_clk_base); + else + writel_relaxed(reset_val, qphy->base + QUSB2PHY_PLL_TEST); + + /* Make sure that above write is completed to get PLL source clock */ + wmb(); + + /* Required to get PHY PLL lock successfully */ + usleep_range(100, 110); + + if (!(readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS) & + QUSB2PHY_PLL_LOCK)) { + dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", + readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS)); + WARN_ON(1); + } + + return 0; +} + +static void qusb_phy_shutdown(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + dev_dbg(phy->dev, "%s\n", __func__); + + qusb_phy_enable_clocks(qphy, true); + + /* Disable the PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + wmb(); + + qusb_phy_enable_clocks(qphy, false); +} + +int qusb_phy_dumpreg(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + pr_debug("%s:dump_phy_registers\n", __func__); + pr_debug("PORT_PWRDWN:%08x\n", readl_relaxed(qphy->base+ QUSB2PHY_PORT_POWERDOWN)); + pr_debug("UTMCTL1:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_UTMI_CTRL1)); + pr_debug("UTMCTL2:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_UTMI_CTRL2)); + pr_debug("AUTOPGM_CTL1:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1)); + pr_debug("PORT_PWRDWN:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PLL_PWR_CTL)); + pr_debug("linestate:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_UTMI_STATUS)); + pr_debug("!!\n!!INT_STATUS:%08x\n", readl_relaxed(qphy->base + QUSB2PHY_PORT_INT_STATUS)); + return 0; +} + +int qusb_phy_run_dcd(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + u8 int_status; + + writel_relaxed(0x23, qphy->base + QUSB2PHY_PORT_POWERDOWN); + /*23*/ + writel_relaxed(0x35, qphy-> base + QUSB2PHY_PORT_UTMI_CTRL1); + writel_relaxed(0xC0, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + writel_relaxed(0x05, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); + writel_relaxed(0x22, qphy->base + QUSB2PHY_PORT_POWERDOWN); + /*22*/ + writel_relaxed(0x17, qphy->base+ QUSB2PHY_PLL_PWR_CTL); + usleep_range(5, 1000); + writel_relaxed(0x15, qphy->base+ QUSB2PHY_PLL_AUTOPGM_CTL1); + usleep_range(50, 1000); + writel_relaxed(0x09, + qphy->base+ QUSB2PHY_PORT_QUICKCHARGE2); + writel_relaxed(0x00, qphy->base+ QUSB2PHY_PORT_QUICKCHARGE1); + writel_relaxed(0x00, qphy->base+ QUSB2PHY_PORT_QUICKCHARGE2); + writel_relaxed(0x1F, qphy->base+ QUSB2PHY_PORT_INTR_CTRL); + writel_relaxed(0x08, qphy->base+ QUSB2PHY_PORT_QUICKCHARGE1); + usleep_range(1000, 2000); + int_status = readl_relaxed(qphy->base+ QUSB2PHY_PORT_INT_STATUS); + qusb_phy_dumpreg(phy); + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, qphy->base+ QUSB2PHY_PORT_POWERDOWN); + /*23*/ + writel_relaxed(0x95, qphy->base+ QUSB2PHY_PLL_AUTOPGM_CTL1); + writel_relaxed(0x80, qphy->base+ QUSB2PHY_PORT_UTMI_CTRL2); + writel_relaxed(0x10, qphy->base+ QUSB2PHY_PORT_UTMI_CTRL1); + writel_relaxed(CLAMP_N_EN |FREEZIO_N, qphy->base+ QUSB2PHY_PORT_POWERDOWN); + + int_status = int_status & 0x5; + pr_debug("%s: int_status:%x\n", __func__, int_status); + + return int_status; +} +EXPORT_SYMBOL(qusb_phy_run_dcd); + +/** + * Returns DP/DM linestate with Idp_src enabled to detect if lines are floating + * + * @uphy - usb phy pointer. + * + */ +static int qusb_phy_linestate_with_idp_src(struct usb_phy *phy) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + u8 int_status, ret; + + /* Disable/powerdown the PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + + /* Put PHY in non-driving mode */ + writel_relaxed(TERM_SELECT | XCVR_SELECT_FS | OP_MODE_NON_DRIVE | + SUSPEND_N, qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); + + /* Switch PHY to utmi register mode */ + writel_relaxed(UTMI_ULPI_SEL | UTMI_TEST_MUX_SEL, + qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + + writel_relaxed(PLL_RESET_N_CNT_5, + qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); + + /* Enable PHY */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + + writel_relaxed(REF_BUF_EN | REXT_EN | PLL_BYPASSNL | REXT_TRIM_0, + qphy->base + QUSB2PHY_PLL_PWR_CTL); + + usleep_range(5, 1000); + + writel_relaxed(PLL_RESET_N | PLL_RESET_N_CNT_5, + qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); + usleep_range(50, 1000); + + writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QUICKCHARGE1); + writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QUICKCHARGE2); + + /* Enable all chg_det events from PHY */ + writel_relaxed(0x1F, qphy->base + QUSB2PHY_PORT_INTR_CTRL); + /* Enable Idp_src */ + writel_relaxed(IDP_SRC_EN, qphy->base + QUSB2PHY_PORT_QUICKCHARGE1); + + usleep_range(1000, 2000); + int_status = readl_relaxed(qphy->base + QUSB2PHY_PORT_INT_STATUS); + + /* Exit chg_det mode, set PHY regs to default values */ + writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, + qphy->base + QUSB2PHY_PORT_POWERDOWN); /* 23 */ + + writel_relaxed(PLL_AUTOPGM_EN | PLL_RESET_N | PLL_RESET_N_CNT_5, + qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); + + writel_relaxed(UTMI_ULPI_SEL, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); + + writel_relaxed(TERM_SELECT, qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); + + writel_relaxed(CLAMP_N_EN | FREEZIO_N, + qphy->base + QUSB2PHY_PORT_POWERDOWN); + + int_status = int_status & 0x5; + + /* + * int_status's Bit(0) is DP and Bit(2) is DM. + * Caller expects bit(1) as DP and bit(0) DM i.e. usual linestate format + */ + ret = (int_status >> 2) | ((int_status & 0x1) << 1); + pr_debug("%s: int_status:%x, dpdm:%x\n", __func__, int_status, ret); + + /* Re-initialize PHY */ + qusb_phy_init(phy); + + return ret; +} + +/** + * Performs QUSB2 PHY suspend/resume functionality. + * + * @uphy - usb phy pointer. + * @suspend - to enable suspend or not. 1 - suspend, 0 - resume + * + */ +static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + u32 linestate = 0, intr_mask = 0; + + if (qphy->suspended && suspend) { + dev_dbg(phy->dev, "%s: USB PHY is already suspended\n", + __func__); + return 0; + } + + if (suspend) { + /* Bus suspend case */ + if (qphy->cable_connected || + (qphy->phy.flags & PHY_HOST_MODE)) { + /* Clear all interrupts */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + + linestate = readl_relaxed(qphy->base + + QUSB2PHY_PORT_UTMI_STATUS); + + /* + * D+/D- interrupts are level-triggered, but we are + * only interested if the line state changes, so enable + * the high/low trigger based on current state. In + * other words, enable the triggers _opposite_ of what + * the current D+/D- levels are. + * e.g. if currently D+ high, D- low (HS 'J'/Suspend), + * configure the mask to trigger on D+ low OR D- high + */ + intr_mask = DPSE_INTR_EN | DMSE_INTR_EN; + if (!(linestate & LINESTATE_DP)) /* D+ low */ + intr_mask |= DPSE_INTR_HIGH_SEL; + if (!(linestate & LINESTATE_DM)) /* D- low */ + intr_mask |= DMSE_INTR_HIGH_SEL; + + writel_relaxed(intr_mask, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + + if (linestate & (LINESTATE_DP | LINESTATE_DM)) { + /* enable phy auto-resume */ + writel_relaxed(0x0C, + qphy->base + QUSB2PHY_PORT_TEST_CTRL); + /* flush the previous write before next write */ + wmb(); + writel_relaxed(0x04, + qphy->base + QUSB2PHY_PORT_TEST_CTRL); + } + + + dev_dbg(phy->dev, "%s: intr_mask = %x\n", + __func__, intr_mask); + + /* Makes sure that above write goes through */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); + } else { /* Disconnect case */ + /* Disable all interrupts */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + + /* Make sure that above write is completed */ + wmb(); + + qusb_phy_enable_clocks(qphy, false); + qusb_phy_update_tcsr_level_shifter(qphy, 0x0); + /* Do not disable power rails if there is vote for it */ + if (!qphy->rm_pulldown) + qusb_phy_enable_power(qphy, false); + else + dev_dbg(phy->dev, "race with rm_pulldown. Keep ldo ON\n"); + + /* + * Set put_into_high_z_state to true so next USB + * cable connect, DPF_DMF request performs PHY + * reset and put it into high-z state. For bootup + * with or without USB cable, it doesn't require + * to put QUSB PHY into high-z state. + */ + qphy->put_into_high_z_state = true; + } + qphy->suspended = true; + } else { + /* Bus suspend case */ + if (qphy->cable_connected || + (qphy->phy.flags & PHY_HOST_MODE)) { + qusb_phy_enable_clocks(qphy, true); + /* Clear all interrupts on resume */ + writel_relaxed(0x00, + qphy->base + QUSB2PHY_PORT_INTR_CTRL); + } else { + qusb_phy_enable_power(qphy, true); + qusb_phy_update_tcsr_level_shifter(qphy, 0x1); + qusb_phy_enable_clocks(qphy, true); + } + qphy->suspended = false; + } + + return 0; +} + +static int qusb_phy_notify_connect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + qphy->cable_connected = true; + + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); + return 0; +} + +static int qusb_phy_notify_disconnect(struct usb_phy *phy, + enum usb_device_speed speed) +{ + struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); + + qphy->cable_connected = false; + + dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n", + qphy->cable_connected); + return 0; +} + +static int qusb_phy_probe(struct platform_device *pdev) +{ + struct qusb_phy *qphy; + struct device *dev = &pdev->dev; + struct resource *res; + int ret = 0, size = 0; + const char *phy_type; + bool hold_phy_reset; + + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); + if (!qphy) + return -ENOMEM; + + qphy->phy.dev = dev; + spin_lock_init(&qphy->pulse_lock); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "qusb_phy_base"); + qphy->base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->base)) + return PTR_ERR(qphy->base); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "emu_phy_base"); + if (res) { + qphy->emu_phy_base = devm_ioremap_resource(dev, res); + if (IS_ERR(qphy->emu_phy_base)) { + dev_dbg(dev, "couldn't ioremap emu_phy_base\n"); + qphy->emu_phy_base = NULL; + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "tune2_efuse_addr"); + if (res) { + qphy->tune2_efuse_reg = devm_ioremap_nocache(dev, res->start, + resource_size(res)); + if (!IS_ERR_OR_NULL(qphy->tune2_efuse_reg)) { + ret = of_property_read_u32(dev->of_node, + "qcom,tune2-efuse-bit-pos", + &qphy->tune2_efuse_bit_pos); + if (!ret) { + ret = of_property_read_u32(dev->of_node, + "qcom,tune2-efuse-num-bits", + &qphy->tune2_efuse_num_of_bits); + } + of_property_read_u32(dev->of_node, + "qcom,tune2-efuse-correction", + &qphy->tune2_efuse_correction); + + if (ret) { + dev_err(dev, "DT Value for tune2 efuse is invalid.\n"); + return -EINVAL; + } + } + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "ref_clk_addr"); + if (res) { + qphy->ref_clk_base = devm_ioremap_nocache(dev, + res->start, resource_size(res)); + if (IS_ERR(qphy->ref_clk_base)) + dev_dbg(dev, "ref_clk_address is not available.\n"); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "tcsr_phy_clk_scheme_sel"); + if (res) { + qphy->tcsr_phy_clk_scheme_sel = devm_ioremap_nocache(dev, + res->start, resource_size(res)); + if (IS_ERR(qphy->tcsr_phy_clk_scheme_sel)) + dev_dbg(dev, "err reading tcsr_phy_clk_scheme_sel\n"); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "tcsr_phy_level_shift_keeper"); + if (res) { + qphy->tcsr_phy_lvl_shift_keeper = devm_ioremap_nocache(dev, + res->start, resource_size(res)); + if (IS_ERR(qphy->tcsr_phy_lvl_shift_keeper)) { + dev_err(dev, "err reading tcsr_phy_lvl_shift_keeper\n"); + qphy->tcsr_phy_lvl_shift_keeper = NULL; + } + } + + qphy->scm_lvl_shifter_update = of_property_read_bool(dev->of_node, + "qcom,secure-level-shifter-update"); + + qphy->dpdm_pulsing_enabled = of_property_read_bool(dev->of_node, + "qcom,enable-dpdm-pulsing"); + + qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src"); + if (IS_ERR(qphy->ref_clk_src)) + dev_dbg(dev, "clk get failed for ref_clk_src\n"); + + qphy->ref_clk = devm_clk_get(dev, "ref_clk"); + if (IS_ERR(qphy->ref_clk)) + dev_dbg(dev, "clk get failed for ref_clk\n"); + else + clk_set_rate(qphy->ref_clk, 19200000); + + qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb_clk"); + if (IS_ERR(qphy->cfg_ahb_clk)) + return PTR_ERR(qphy->cfg_ahb_clk); + + qphy->phy_reset = devm_clk_get(dev, "phy_reset"); + if (IS_ERR(qphy->phy_reset)) + return PTR_ERR(qphy->phy_reset); + + if (of_property_match_string(dev->of_node, + "clock-names", "iface_clk") >= 0) { + qphy->iface_clk = devm_clk_get(dev, "iface_clk"); + if (IS_ERR(qphy->iface_clk)) { + ret = PTR_ERR(qphy->iface_clk); + qphy->iface_clk = NULL; + if (ret == -EPROBE_DEFER) + return ret; + dev_err(dev, "couldn't get iface_clk(%d)\n", ret); + } + } + + if (of_property_match_string(dev->of_node, + "clock-names", "core_clk") >= 0) { + qphy->core_clk = devm_clk_get(dev, "core_clk"); + if (IS_ERR(qphy->core_clk)) { + ret = PTR_ERR(qphy->core_clk); + qphy->core_clk = NULL; + if (ret == -EPROBE_DEFER) + return ret; + dev_err(dev, "couldn't get core_clk(%d)\n", ret); + } + } + + qphy->gdsc = devm_regulator_get(dev, "USB3_GDSC"); + if (IS_ERR(qphy->gdsc)) + qphy->gdsc = NULL; + + qphy->emulation = of_property_read_bool(dev->of_node, + "qcom,emulation"); + + of_get_property(dev->of_node, "qcom,emu-init-seq", &size); + if (size) { + qphy->emu_init_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->emu_init_seq) { + qphy->emu_init_seq_len = + (size / sizeof(*qphy->emu_init_seq)); + if (qphy->emu_init_seq_len % 2) { + dev_err(dev, "invalid emu_init_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,emu-init-seq", + qphy->emu_init_seq, + qphy->emu_init_seq_len); + } else { + dev_dbg(dev, "error allocating memory for emu_init_seq\n"); + } + } + + of_get_property(dev->of_node, "qcom,phy-pll-reset-seq", &size); + if (size) { + qphy->phy_pll_reset_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->phy_pll_reset_seq) { + qphy->phy_pll_reset_seq_len = + (size / sizeof(*qphy->phy_pll_reset_seq)); + if (qphy->phy_pll_reset_seq_len % 2) { + dev_err(dev, "invalid phy_pll_reset_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,phy-pll-reset-seq", + qphy->phy_pll_reset_seq, + qphy->phy_pll_reset_seq_len); + } else { + dev_dbg(dev, "error allocating memory for phy_pll_reset_seq\n"); + } + } + + of_get_property(dev->of_node, "qcom,emu-dcm-reset-seq", &size); + if (size) { + qphy->emu_dcm_reset_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->emu_dcm_reset_seq) { + qphy->emu_dcm_reset_seq_len = + (size / sizeof(*qphy->emu_dcm_reset_seq)); + if (qphy->emu_dcm_reset_seq_len % 2) { + dev_err(dev, "invalid emu_dcm_reset_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,emu-dcm-reset-seq", + qphy->emu_dcm_reset_seq, + qphy->emu_dcm_reset_seq_len); + } else { + dev_dbg(dev, "error allocating memory for emu_dcm_reset_seq\n"); + } + } + + of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size); + if (size) { + qphy->qusb_phy_init_seq = devm_kzalloc(dev, + size, GFP_KERNEL); + if (qphy->qusb_phy_init_seq) { + qphy->init_seq_len = + (size / sizeof(*qphy->qusb_phy_init_seq)); + if (qphy->init_seq_len % 2) { + dev_err(dev, "invalid init_seq_len\n"); + return -EINVAL; + } + + of_property_read_u32_array(dev->of_node, + "qcom,qusb-phy-init-seq", + qphy->qusb_phy_init_seq, + qphy->init_seq_len); + } else { + dev_err(dev, "error allocating memory for phy_init_seq\n"); + } + } + + qphy->ulpi_mode = false; + ret = of_property_read_string(dev->of_node, "phy_type", &phy_type); + + if (!ret) { + if (!strcasecmp(phy_type, "ulpi")) + qphy->ulpi_mode = true; + } else { + dev_err(dev, "error reading phy_type property\n"); + return ret; + } + + hold_phy_reset = of_property_read_bool(dev->of_node, "qcom,hold-reset"); + ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level", + (u32 *) qphy->vdd_levels, + ARRAY_SIZE(qphy->vdd_levels)); + if (ret) { + dev_err(dev, "error reading qcom,vdd-voltage-level property\n"); + return ret; + } + + qphy->vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(qphy->vdd)) { + dev_err(dev, "unable to get vdd supply\n"); + return PTR_ERR(qphy->vdd); + } + + qphy->vdda33 = devm_regulator_get(dev, "vdda33"); + if (IS_ERR(qphy->vdda33)) { + dev_err(dev, "unable to get vdda33 supply\n"); + return PTR_ERR(qphy->vdda33); + } + + qphy->vdda18 = devm_regulator_get(dev, "vdda18"); + if (IS_ERR(qphy->vdda18)) { + dev_err(dev, "unable to get vdda18 supply\n"); + return PTR_ERR(qphy->vdda18); + } + + platform_set_drvdata(pdev, qphy); + + qphy->phy.label = "msm-qusb-phy"; + qphy->phy.init = qusb_phy_init; + qphy->phy.set_suspend = qusb_phy_set_suspend; + qphy->phy.shutdown = qusb_phy_shutdown; + qphy->phy.change_dpdm = qusb_phy_update_dpdm; + qphy->phy.type = USB_PHY_TYPE_USB2; + qphy->phy.dpdm_with_idp_src = qusb_phy_linestate_with_idp_src; + qphy->phy.notify_connect = qusb_phy_notify_connect; + qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; + + /* + * On some platforms multiple QUSB PHYs are available. If QUSB PHY is + * not used, there is leakage current seen with QUSB PHY related voltage + * rail. Hence keep QUSB PHY into reset state explicitly here. + */ + if (hold_phy_reset) + clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); + + ret = usb_add_phy_dev(&qphy->phy); + return ret; +} + +static int qusb_phy_remove(struct platform_device *pdev) +{ + struct qusb_phy *qphy = platform_get_drvdata(pdev); + + usb_remove_phy(&qphy->phy); + + if (qphy->clocks_enabled) { + clk_disable_unprepare(qphy->cfg_ahb_clk); + clk_disable_unprepare(qphy->ref_clk); + clk_disable_unprepare(qphy->ref_clk_src); + qphy->clocks_enabled = false; + } + + qusb_phy_enable_power(qphy, false); + + return 0; +} + +static const struct of_device_id qusb_phy_id_table[] = { + { .compatible = "qcom,qusb2phy", }, + { }, +}; +MODULE_DEVICE_TABLE(of, qusb_phy_id_table); + +static struct platform_driver qusb_phy_driver = { + .probe = qusb_phy_probe, + .remove = qusb_phy_remove, + .driver = { + .name = "msm-qusb-phy", + .of_match_table = of_match_ptr(qusb_phy_id_table), + }, +}; + +module_platform_driver(qusb_phy_driver); + +MODULE_DESCRIPTION("MSM QUSB2 PHY driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 926c1f2dc962c..0ff22578c9a33 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -81,7 +81,7 @@ static int usb_console_setup(struct console *co, char *options) if (*s) doflow = (*s++ == 'r'); } - + /* Sane default */ if (baud == 0) baud = 9600; @@ -303,4 +303,3 @@ void usb_serial_console_exit(void) usbcons_info.port = NULL; } } - diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2f5a97004a889..a8ab8195e708f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -15,6 +15,16 @@ config SH_MIPI_DSI config SH_LCD_MIPI_DSI bool +config PROJECT_VINCE + bool "XIAOMI E7 use" + ---help--- + diff touch and lcd in E7 project. + +config PROJECT_SAKURA + bool "XIAOMI D1S use" + ---help--- + diff touch and lcd in D1S project. + source "drivers/char/agp/Kconfig" source "drivers/gpu/vga/Kconfig" diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 2a708dd2eceed..36cb9f5624bdb 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -2,6 +2,7 @@ * linux/drivers/video/fbmem.c * * Copyright (C) 1994 Martin Schaller + * Copyright (C) 2019 XiaoMi, Inc. * * 2001 - Documented with DocBook * - Brad Douglas @@ -1054,20 +1055,36 @@ EXPORT_SYMBOL(fb_set_var); int fb_blank(struct fb_info *info, int blank) -{ +{ struct fb_event event; int ret = -EINVAL, early_ret; + printk("lcm enter %s fb_blank = %d\n", __func__, blank); if (blank > FB_BLANK_POWERDOWN) blank = FB_BLANK_POWERDOWN; + if (info->blank == blank) { + if (info->fbops->fb_blank) + ret = info->fbops->fb_blank(blank, info); + return ret; + } + event.info = info; event.data = ␣ + #ifdef CONFIG_PROJECT_SAKURA + /*fast tp suspend in LPWG*/ + if (blank == FB_BLANK_POWERDOWN){ + fb_notifier_call_chain(FB_EVENT_BLANK, &event); + } + #endif + early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event); + printk("lcm enter do fbops fb_blank = %d\n", blank); if (info->fbops->fb_blank) ret = info->fbops->fb_blank(blank, info); + printk("lcm enter do fbops fb_blank = %d\n", blank); if (!ret) fb_notifier_call_chain(FB_EVENT_BLANK, &event); @@ -1079,6 +1096,10 @@ fb_blank(struct fb_info *info, int blank) if (!early_ret) fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event); } + printk("lcm out %s fb_blank = %d\n", __func__, blank); + + if (!ret) + info->blank = blank; return ret; } @@ -1641,6 +1662,7 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) break; fb_info->node = i; + fb_info->blank = -1; atomic_set(&fb_info->count, 1); mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig index 048d9faf2111a..824e28c4208d7 100644 --- a/drivers/video/msm/Kconfig +++ b/drivers/video/msm/Kconfig @@ -54,6 +54,11 @@ config FB_MSM_QPIC_PANEL_DETECT ---help--- Support for Qpic panel auto detect +config ENABLE_PM_TP_SUSPEND_RESUME + bool "ENABLE PM TP SUSPEND/RESUME" + ---help--- + Say Y here if you want to know whether it is running in ffbm mode. + if FB_MSM_MDSS source "drivers/video/msm/mdss/Kconfig" endif diff --git a/drivers/video/msm/mdss/Kconfig b/drivers/video/msm/mdss/Kconfig index b44655e59ade6..e73e6395df6c4 100644 --- a/drivers/video/msm/mdss/Kconfig +++ b/drivers/video/msm/mdss/Kconfig @@ -82,3 +82,18 @@ config FB_MSM_MDSS_FRC_DEBUG frame rate control (FRC) debugging features to: Collect video frame statistics and check whether its output pattern matches expected cadence. + +config WPONIT_ADJUST_FUN + bool "XIAOMI whitepoint adjust" + ---help--- + Panel provides whitepoint x,y and r,g,b value. + +config PROJECT_SAKURA + bool "XIAOMI sakura project macro" + ---help--- + to distinguish diff project + +config PROJECT_DAISY + bool "XIAOMI daisy project macro" + ---help--- + to distinguish diff project diff --git a/drivers/video/msm/mdss/libmdss_get_rc.a b/drivers/video/msm/mdss/libmdss_get_rc.a new file mode 100644 index 0000000000000..68eb831d15bd7 Binary files /dev/null and b/drivers/video/msm/mdss/libmdss_get_rc.a differ diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c index b54ef434988b4..fe0e417a3ed45 100644 --- a/drivers/video/msm/mdss/mdss_compat_utils.c +++ b/drivers/video/msm/mdss/mdss_compat_utils.c @@ -4293,6 +4293,8 @@ int mdss_fb_compat_ioctl(struct fb_info *info, unsigned int cmd, if (!info || !info->par) return -EINVAL; + printk("linson run mdss_fb_compat_ioctl\n"); + cmd = __do_compat_ioctl_nr(cmd); switch (cmd) { case MSMFB_CURSOR: diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c index 0534d11b0a534..97dc4600bbef8 100644 --- a/drivers/video/msm/mdss/mdss_dsi.c +++ b/drivers/video/msm/mdss/mdss_dsi.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -33,6 +34,9 @@ #include "mdss_debug.h" #include "mdss_dsi_phy.h" #include "mdss_dba_utils.h" +#include +/*Add by HQ-zmc [Date: 2017-11-18 13:28:24]*/ +#include #define XO_CLK_RATE 19200000 #define CMDLINE_DSI_CTL_NUM_STRING_LEN 2 @@ -40,9 +44,31 @@ /* Master structure to hold all the information about the DSI/panel */ static struct mdss_dsi_data *mdss_dsi_res; +struct mdss_dsi_ctrl_pdata *change_par_ctrl ; + #define DSI_DISABLE_PC_LATENCY 100 #define DSI_ENABLE_PC_LATENCY PM_QOS_DEFAULT_VALUE +#ifdef CONFIG_ENABLE_PM_TP_SUSPEND_RESUME +/*A flag to indicate ffbm mode or not*/ +bool lcm_ffbm_mode = 0; +#endif + +/*Only used in D2*/ + +#ifdef CONFIG_PROJECT_VINCE +static struct NVT_CSOT_ESD nvt_csot_esd = { + .nova_csot_panel = false, + .ESD_TE_status = false +}; + +struct NVT_CSOT_ESD *get_nvt_csot_esd_status(void){ + return &nvt_csot_esd; +} + +bool vspn_power_state = false; /*only used in vince*/ +#endif + static struct pm_qos_request mdss_dsi_pm_qos_request; static void mdss_dsi_pm_qos_add_request(struct mdss_dsi_ctrl_pdata *ctrl_pdata) @@ -272,10 +298,99 @@ static int mdss_dsi_regulator_init(struct platform_device *pdev, return rc; } -static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) +#ifdef CONFIG_PROJECT_VINCE +/*Add by HQ-zmc [Date: 2017-12-21 16:50:07]*/ +static int nova_esd_2fingers_rst(struct mdss_panel_data *pdata){ + int ret = 0; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + ret = -EINVAL; + goto end; + } + + printk("[zmc] %s\n", __func__); + + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + + if (mdss_dsi_pinctrl_set_state(ctrl_pdata, true)) + pr_debug("reset enable: pinctrl not enabled\n"); + ret = mdss_dsi_panel_reset(pdata, 1); + if (ret) + pr_err("%s: Panel reset failed. rc=%d\n", + __func__, ret); + + ret = mdss_dsi_panel_reset(pdata, 0); + + msleep(30); + + if (mdss_dsi_pinctrl_set_state(ctrl_pdata, true)) + pr_debug("reset enable: pinctrl not enabled\n"); + ret = mdss_dsi_panel_reset(pdata, 1); + if (ret) + pr_err("%s: Panel reset failed. rc=%d\n", + __func__, ret); + + ret = mdss_dsi_panel_reset(pdata, 0); +end: + return ret; +} + +static int nova_esd_recovery(struct mdss_panel_data *pdata){ + int ret = 0; + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + /*Add by HQ-zmc [Date: 2017-12-18 11:16:00]*/ + struct NVT_CSOT_ESD *nvt_csot_esd_status = get_nvt_csot_esd_status(); + + if (nvt_csot_esd_status->ESD_TE_status){ + if (pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + ret = -EINVAL; + goto end; + } + + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, + panel_data); + + printk("[zmc] %s: vspn_power_state = %d\n", __func__, vspn_power_state); + + ret = msm_dss_enable_vreg( + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 0); + if (ret) + pr_err("%s: failed to disable vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + + vspn_power_state = false; + + printk("[zmc] nova_csot_panel delay 1000ms"); + + msleep(50); + ret = nova_esd_2fingers_rst(pdata); + + msleep(500); + + ret = nova_esd_2fingers_rst(pdata); + msleep(10); + + nvt_csot_esd_status->ESD_TE_status = false; + } + +end: + return ret; +} +#endif + + int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) { int ret = 0; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; +#ifdef CONFIG_PROJECT_VINCE + /*Add by HQ-zmc [Date: 2017-12-18 11:16:00]*/ + struct NVT_CSOT_ESD *nvt_csot_esd_status = get_nvt_csot_esd_status(); +#endif if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); @@ -292,15 +407,43 @@ static int mdss_dsi_panel_power_off(struct mdss_panel_data *pdata) ret = 0; } + usleep_range(1000, 1000); + if (mdss_dsi_pinctrl_set_state(ctrl_pdata, false)) pr_debug("reset disable: pinctrl not enabled\n"); - ret = msm_dss_enable_vreg( +#ifdef CONFIG_PROJECT_VINCE + /*changed by HQ-zmc 20170926*/ + if ((!synaptics_gesture_func_on) || (!synaptics_gesture_func_on_lansi) || (!NVT_gesture_func_on)){ + if (nvt_csot_esd_status->nova_csot_panel && nvt_csot_esd_status->ESD_TE_status){ + ret = nova_esd_recovery(pdata); + }else{ + printk("[zmc] %s: vspn_power_state = %d\n", __func__, vspn_power_state); + if (vspn_power_state){ + ret = msm_dss_enable_vreg( + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 0); + if (ret) + pr_err("%s: failed to disable vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + vspn_power_state = false; + } + } + }else if (nvt_csot_esd_status->nova_csot_panel && nvt_csot_esd_status->ESD_TE_status){ + ret = nova_esd_recovery(pdata); + } + else{ + printk("[zmc] %s: VSP/VSN keep high for gesture_wakeup\n", __func__); + } +#else + ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 0); - if (ret) - pr_err("%s: failed to disable vregs for %s\n", - __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + if (ret) + pr_err("%s: failed to disable vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + +#endif end: return ret; @@ -317,7 +460,22 @@ static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) } ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); - + printk("lcm %s msm_dss_enable_vreg enter\n", __func__); +#ifdef CONFIG_PROJECT_VINCE + printk("[zmc] %s: vspn_power_state = %d\n", __func__, vspn_power_state); + if (!vspn_power_state){ + printk("[zmc] mido/E7 lite msm_dss_enable_vreg \n "); + ret = msm_dss_enable_vreg( + ctrl_pdata->panel_power_data.vreg_config, + ctrl_pdata->panel_power_data.num_vreg, 1); + if (ret) { + pr_err("%s: failed to enable vregs for %s\n", + __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); + return ret; + } + vspn_power_state = true; + } +#else ret = msm_dss_enable_vreg( ctrl_pdata->panel_power_data.vreg_config, ctrl_pdata->panel_power_data.num_vreg, 1); @@ -326,6 +484,8 @@ static int mdss_dsi_panel_power_on(struct mdss_panel_data *pdata) __func__, __mdss_dsi_pm_name(DSI_PANEL_PM)); return ret; } +#endif + printk("lcm %s msm_dss_enable_vreg out\n", __func__); /* * If continuous splash screen feature is enabled, then we need to @@ -1632,6 +1792,8 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata) if ((pdata->panel_info.type == MIPI_CMD_PANEL) && mipi->vsync_enable && mipi->hw_vsync_mode) { mdss_dsi_set_tear_on(ctrl_pdata); + if (mdss_dsi_is_te_based_esd(ctrl_pdata)) + enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio)); } ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT; @@ -1701,6 +1863,11 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state) if ((pdata->panel_info.type == MIPI_CMD_PANEL) && mipi->vsync_enable && mipi->hw_vsync_mode) { + if (mdss_dsi_is_te_based_esd(ctrl_pdata)) { + disable_irq(gpio_to_irq( + ctrl_pdata->disp_te_gpio)); + atomic_dec(&ctrl_pdata->te_irq_ready); + } mdss_dsi_set_tear_off(ctrl_pdata); } @@ -2646,8 +2813,10 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, pdata); break; case MDSS_EVENT_UNBLANK: + pr_err("lcd-time event unblank begin\n"); if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE) rc = mdss_dsi_unblank(pdata); + pr_err("lcd-time event unblank end\n"); break; case MDSS_EVENT_POST_PANEL_ON: rc = mdss_dsi_post_panel_on(pdata); @@ -2659,9 +2828,11 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, pdata->panel_info.esd_rdy = true; break; case MDSS_EVENT_BLANK: + pr_err("lcd-time event blank begin\n"); power_state = (int) (unsigned long) arg; if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE) rc = mdss_dsi_blank(pdata, power_state); + pr_err("lcd-time event blank end\n"); break; case MDSS_EVENT_PANEL_OFF: power_state = (int) (unsigned long) arg; @@ -2824,18 +2995,39 @@ static struct device_node *mdss_dsi_pref_prim_panel( * * returns pointer to panel node on success, NULL on error. */ +char panel_name[MDSS_MAX_PANEL_LEN] = ""; +#ifdef CONFIG_WPONIT_ADJUST_FUN +u32 white_point_num_x = 0; +u32 white_point_num_y = 0; +u32 white_point_num_r = 0; +u32 white_point_num_g = 0; +u32 white_point_num_b = 0; +#endif +#ifdef CONFIG_PROJECT_VINCE +int white_point_num = 0; +extern uint32_t ESD_interval; /*ESD check period*/ +#endif static struct device_node *mdss_dsi_find_panel_of_node( struct platform_device *pdev, char *panel_cfg) { int len, i = 0; int ctrl_id = pdev->id - 1; - char panel_name[MDSS_MAX_PANEL_LEN] = ""; + +#ifdef CONFIG_PROJECT_VINCE + char *wponit_str; +#endif char ctrl_id_stream[3] = "0:"; char *str1 = NULL, *str2 = NULL, *override_cfg = NULL; char cfg_np_name[MDSS_MAX_PANEL_LEN] = ""; +#ifdef CONFIG_WPONIT_ADJUST_FUN + char *wponit_str; +#endif struct device_node *dsi_pan_node = NULL, *mdss_node = NULL; struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev); struct mdss_panel_info *pinfo = &ctrl_pdata->panel_data.panel_info; +#ifdef CONFIG_PROJECT_VINCE + struct NVT_CSOT_ESD *nvt_csot_esd_status = get_nvt_csot_esd_status(); +#endif len = strlen(panel_cfg); ctrl_pdata->panel_data.dsc_cfg_np_name[0] = '\0'; @@ -2845,6 +3037,36 @@ static struct device_node *mdss_dsi_find_panel_of_node( __func__, __LINE__); goto end; } else { +#ifdef CONFIG_ENABLE_PM_TP_SUSPEND_RESUME + lcm_ffbm_mode = strnstr(panel_cfg, "ffbm", len); + if (lcm_ffbm_mode){ + pr_info("[ffbm] we are in ffbm mode now!\n"); + } +#endif + +#ifdef CONFIG_PROJECT_VINCE + wponit_str = strnstr(panel_cfg, ":wpoint=", len); + if (!wponit_str) { + pr_err("%s:[white point calibration] white point is not present in %s\n", + __func__, panel_cfg); + }else{ + white_point_num = ((*(wponit_str + 8)) - '0') * 10 + ((*(wponit_str + 9) - '0')); + pr_err("[white point calibration] white_point_num = %d\n", white_point_num); + } +#endif + +#ifdef CONFIG_WPONIT_ADJUST_FUN + wponit_str = strnstr(panel_cfg, ":wpoint=", len); + if (!wponit_str) { + pr_err("%s:[white point calibration] white point is not present in %s\n", + __func__, panel_cfg); + }else{ + white_point_num_x = ((*(wponit_str + 8)) - '0') * 100 + ((*(wponit_str + 9) - '0'))*10 +(*(wponit_str + 10) - '0'); + white_point_num_y = ((*(wponit_str + 11)) - '0') * 100 + ((*(wponit_str + 12) - '0'))*10 +(*(wponit_str + 13) - '0'); + pr_err("[white point calibration] white_point_num_x = %d, white_point_num_y = %d\n", white_point_num_x, white_point_num_y); + } +#endif + /* check if any override parameters are set */ pinfo->sim_panel_mode = 0; override_cfg = strnstr(panel_cfg, "#" OVERRIDE_CFG, len); @@ -2888,10 +3110,42 @@ static struct device_node *mdss_dsi_find_panel_of_node( panel_name[i] = *(str1 + i); panel_name[i] = 0; } - pr_info("%s: cmdline:%s panel_name:%s\n", + pr_err("%s: cmdline:%s panel_name:%s\n", __func__, panel_cfg, panel_name); if (!strcmp(panel_name, NONE_PANEL)) goto exit; +#ifdef CONFIG_PROJECT_VINCE + if (!strcmp(panel_name, "qcom,mdss_dsi_td4310_fhdplus_video_e7")){ + hq_regiser_hw_info(HWID_LCM, "incell,vendor:Tianma,IC:TD4310(synaptics)"); + }else if (!strcmp(panel_name, "qcom,mdss_dsi_td4310_fhdplus_video_e7_g55")){ + hq_regiser_hw_info(HWID_LCM, "incell,vendor:Tianma_G55,IC:TD4310(synaptics)"); + }else if (!strcmp(panel_name, "qcom,mdss_dsi_td4310_ebbg_fhdplus_video_e7")){ + hq_regiser_hw_info(HWID_LCM, "incell,vendor:EBBG,IC:TD4310(synaptics)"); + }else if (!strcmp(panel_name, "qcom,mdss_dsi_nt36672_tianma_fhdplus_video_e7")){ + hq_regiser_hw_info(HWID_LCM, "incell,vendor:Tianma,IC:NT36672(novatek)"); + }else if (!strcmp(panel_name, "qcom,mdss_dsi_nt36672_csot_fhdplus_video_e7")){ + nvt_csot_esd_status->nova_csot_panel = true; + ESD_interval = 500; + hq_regiser_hw_info(HWID_LCM, "incell,vendor:CSOT,IC:NT36672(novatek)"); + } +#endif + if (!strcmp(panel_name, "qcom,mdss_dsi_otm1911_fhdplus_video")){ + hq_regiser_hw_info(HWID_LCM, "oncell, vendor:Skh, IC:atm007"); + }else if (!strcmp(panel_name, "qcom,mdss_dsi_ili7807_fhdplus_video")){ + hq_regiser_hw_info(HWID_LCM, "oncell, vendor:bird, IC:lol898"); +#ifdef CONFIG_WPONIT_ADJUST_FUN + white_point_num_r = 653332; + white_point_num_g = 291664; + white_point_num_b = 154054; +#endif + }else if (!strcmp(panel_name, "qcom,mdss_dsi_hx8399c_fhdplus_video")){ + hq_regiser_hw_info(HWID_LCM, "oncell, vendor:csot, IC:hx8399c"); +#ifdef CONFIG_WPONIT_ADJUST_FUN + white_point_num_r = 656333; + white_point_num_g = 288654; + white_point_num_b = 146057; +#endif + } mdss_node = of_parse_phandle(pdev->dev.of_node, "qcom,mdss-mdp", 0); @@ -3202,6 +3456,9 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev) pr_err("%s: Unable to get the ctrl_pdata\n", __func__); return -EINVAL; } + /*get ctrl_pdata earlyer*/ + change_par_ctrl = ctrl_pdata; + pr_info("%s : get change_par_ctrl = %p\n", __func__, change_par_ctrl); platform_set_drvdata(pdev, ctrl_pdata); @@ -3463,6 +3720,8 @@ static void mdss_dsi_res_deinit(struct platform_device *pdev) devm_kfree(&pdev->dev, dsi_res->ctrl_pdata[i]); } } + /*free change_par_ctrl*/ + change_par_ctrl = NULL; sdata = dsi_res->shared_data; if (!sdata) @@ -4079,6 +4338,49 @@ static int mdss_dsi_parse_ctrl_params(struct platform_device *ctrl_pdev, } +u32 te_count = 60; /*TE counter*/ + +static irqreturn_t te_interrupt(int irq, void *data) +{ + disable_irq_nosync(irq); + + te_count++; + + enable_irq(irq); + return IRQ_HANDLED; +} + +int init_te_irq(struct mdss_dsi_ctrl_pdata *ctrl_pdata) + { + int rc = -1; + int irq; + if (gpio_is_valid(ctrl_pdata->disp_te_gpio)) { + rc = gpio_request(ctrl_pdata->disp_te_gpio, "te-gpio"); + if (rc < 0) { + pr_err("%s: gpio_request fail rc=%d\n", __func__, rc); + return rc ; + } + rc = gpio_direction_input(ctrl_pdata->disp_te_gpio); + if (rc < 0) { + pr_err("%s: gpio_direction_input fail rc=%d\n", __func__, rc); + return rc ; + } + irq = gpio_to_irq(ctrl_pdata->disp_te_gpio); + pr_err("%s:liujia irq = %d\n", __func__, irq); + rc = request_threaded_irq(irq, te_interrupt, NULL, + IRQF_TRIGGER_RISING|IRQF_ONESHOT, + "te-irq", ctrl_pdata); + if (rc < 0) { + pr_err("%s: request_irq fail rc=%d\n", __func__, rc); + return rc ; + } + }else{ + pr_err("%s:liujia irq gpio not provided\n", __func__); + return rc ; + } + return 0; + } + static int mdss_dsi_parse_gpio_params(struct platform_device *ctrl_pdev, struct mdss_dsi_ctrl_pdata *ctrl_pdata) { @@ -4242,6 +4544,9 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev, if (ctrl_pdata->status_mode == ESD_REG || ctrl_pdata->status_mode == ESD_REG_NT35596) ctrl_pdata->check_status = mdss_dsi_reg_status_check; + else if (ctrl_pdata->status_mode == ESD_TE_NT35596) + {ctrl_pdata->check_status = mdss_dsi_TE_NT35596_check; + init_te_irq(ctrl_pdata); } else if (ctrl_pdata->status_mode == ESD_BTA) ctrl_pdata->check_status = mdss_dsi_bta_status_check; diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h index 6d6757ff592eb..e9802948cd52c 100644 --- a/drivers/video/msm/mdss/mdss_dsi.h +++ b/drivers/video/msm/mdss/mdss_dsi.h @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -107,6 +108,7 @@ enum dsi_panel_status_mode { ESD_BTA, ESD_REG, ESD_REG_NT35596, + ESD_TE_NT35596, ESD_TE, ESD_MAX, }; @@ -227,6 +229,12 @@ extern struct device dsi_dev; extern u32 dsi_irq; extern struct mdss_dsi_ctrl_pdata *ctrl_list[]; +#ifdef CONFIG_PROJECT_VINCE +extern bool synaptics_gesture_func_on; +extern bool synaptics_gesture_func_on_lansi; +extern bool NVT_gesture_func_on; +#endif + enum { DSI_CTRL_0, DSI_CTRL_1, @@ -466,6 +474,27 @@ struct mdss_dsi_ctrl_pdata { struct mdss_intf_recovery *recovery; struct mdss_intf_recovery *mdp_callback; + struct dsi_panel_cmds CABC_on_cmds; + struct dsi_panel_cmds CABC_off_cmds; + struct dsi_panel_cmds CE_on_cmds; + struct dsi_panel_cmds CE_off_cmds; + struct dsi_panel_cmds cold_gamma_cmds; + struct dsi_panel_cmds warm_gamma_cmds; + struct dsi_panel_cmds default_gamma_cmds; + struct dsi_panel_cmds white_gamma_cmds; +#ifdef CONFIG_PROJECT_VINCE + struct dsi_panel_cmds sRGB_on_cmds; + struct dsi_panel_cmds sRGB_off_cmds; +#endif + struct dsi_panel_cmds PM1_cmds; + struct dsi_panel_cmds PM2_cmds; + struct dsi_panel_cmds PM3_cmds; + struct dsi_panel_cmds PM4_cmds; + struct dsi_panel_cmds PM5_cmds; + struct dsi_panel_cmds PM6_cmds; + struct dsi_panel_cmds PM7_cmds; + struct dsi_panel_cmds PM8_cmds; + struct dsi_panel_cmds on_cmds; struct dsi_panel_cmds post_dms_on_cmds; struct dsi_panel_cmds post_panel_on_cmds; @@ -644,6 +673,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp); void mdss_dsi_cmdlist_kickoff(int intf); int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl); int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl); +int mdss_dsi_TE_NT35596_check(struct mdss_dsi_ctrl_pdata *ctrl); bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type); void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl); bool mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl, bool print_en); @@ -699,6 +729,19 @@ static inline const char *__mdss_dsi_pm_supply_node_name( } } +#ifdef CONFIG_PROJECT_VINCE +/*Add by HQ-zmc [Date: 2017-12-18 11:02:02]*/ +struct NVT_CSOT_ESD{ + bool nova_csot_panel; + bool ESD_TE_status; +}; + +struct NVT_CSOT_ESD *get_nvt_csot_esd_status(void); +#endif + +void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl, + struct dsi_panel_cmds *pcmds, u32 flags); + static inline u32 mdss_dsi_get_hw_config(struct dsi_shared_data *sdata) { return sdata->hw_config; diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c index 799a4e6ce3711..cf79597de1a1c 100644 --- a/drivers/video/msm/mdss/mdss_dsi_host.c +++ b/drivers/video/msm/mdss/mdss_dsi_host.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1155,6 +1156,78 @@ static int mdss_dsi_read_status(struct mdss_dsi_ctrl_pdata *ctrl) * Return: positive value if the panel is in good state, negative value or * zero otherwise. */ +#ifdef CONFIG_PROJECT_VINCE +int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + int ret = 0; + struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL; + /*Add by HQ-zmc [Date: 2017-12-18 11:16:00]*/ + struct NVT_CSOT_ESD *nvt_csot_esd_status = get_nvt_csot_esd_status(); + + if (nvt_csot_esd_status == NULL){ + pr_err("%s: Invalid nvt_csot_esd_status\n", __func__); + return 0; + } + + if (ctrl_pdata == NULL) { + pr_err("%s: Invalid input data\n", __func__); + return 0; + } + + pr_debug("%s: Checking Register status\n", __func__); + + mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, + MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON); + + sctrl_pdata = mdss_dsi_get_other_ctrl(ctrl_pdata); + if (!mdss_dsi_sync_wait_enable(ctrl_pdata)) { + ret = mdss_dsi_read_status(ctrl_pdata); + } else { + /* + * Read commands to check ESD status are usually sent at + * the same time to both the controllers. However, if + * sync_wait is enabled, we need to ensure that the + * dcs commands are first sent to the non-trigger + * controller so that when the commands are triggered, + * both controllers receive it at the same time. + */ + if (mdss_dsi_sync_wait_trigger(ctrl_pdata)) { + if (sctrl_pdata) + ret = mdss_dsi_read_status(sctrl_pdata); + ret = mdss_dsi_read_status(ctrl_pdata); + } else { + ret = mdss_dsi_read_status(ctrl_pdata); + if (sctrl_pdata) + ret = mdss_dsi_read_status(sctrl_pdata); + } + } + + /* + * mdss_dsi_read_status returns the number of bytes returned + * by the panel. Success value is greater than zero and failure + * case returns zero. + */ + if (ret > 0) { + if (!mdss_dsi_sync_wait_enable(ctrl_pdata) || + mdss_dsi_sync_wait_trigger(ctrl_pdata)) + ret = ctrl_pdata->check_read_status(ctrl_pdata); + else if (sctrl_pdata) + ret = ctrl_pdata->check_read_status(sctrl_pdata); + } else { + pr_err("%s: Read status register returned error\n", __func__); + } + + mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle, + MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF); + pr_debug("%s: Read register done with ret: %d\n", __func__, ret); + + /*Add by HQ-zmc [Date: 2017-12-19 18:39:41]*/ + if ((ret <= 0) && (!nvt_csot_esd_status->ESD_TE_status)) + nvt_csot_esd_status->ESD_TE_status = true; + + return ret; +} +#else int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int ret = 0; @@ -1214,6 +1287,51 @@ int mdss_dsi_reg_status_check(struct mdss_dsi_ctrl_pdata *ctrl_pdata) return ret; } +#endif + +extern u32 te_count; + +#ifdef CONFIG_PROJECT_VINCE +/*Add by HQ-zmc [Date: 2018-03-05 17:58:53] + TE_check per 1000ms, te_count < 48 +*/ +int mdss_dsi_TE_NT35596_check (struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + int ret = 1; + /*Add by HQ-zmc [Date: 2017-12-18 11:16:00]*/ + struct NVT_CSOT_ESD *nvt_csot_esd_status = get_nvt_csot_esd_status(); + + if (te_count < 48){ + ret = 0; + nvt_csot_esd_status->ESD_TE_status = true; + pr_err("liujia te_count doesnt add as time"); + } + + te_count = 0; + + return ret; +} +#else +static u32 te_count_old = 1; + +int mdss_dsi_TE_NT35596_check (struct mdss_dsi_ctrl_pdata *ctrl_pdata) +{ + int ret = 1; + + if (te_count_old != te_count){ + + te_count_old = te_count; + }else{ + ret = 0; + pr_err("liujia te_count doesnt add as time"); + } + if (te_count>=10000) + {te_count = 0; } + + return ret; + +} +#endif void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl, struct dsc_desc *dsc) { diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c index 6fad2fbd42fac..ff32bfb5eb5f0 100644 --- a/drivers/video/msm/mdss/mdss_dsi_panel.c +++ b/drivers/video/msm/mdss/mdss_dsi_panel.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -10,6 +11,7 @@ * GNU General Public License for more details. */ + #include #include #include @@ -34,6 +36,16 @@ #define VSYNC_DELAY msecs_to_jiffies(17) +/* test - start */ +extern char panel_name[MDSS_MAX_PANEL_LEN]; + +extern struct mdss_dsi_ctrl_pdata *change_par_ctrl ; +int change_par_buf; +#ifdef CONFIG_PROJECT_VINCE +int LCM_effect[4] = {0x2, 0xf0, 0xf00, 0xf000}; +#else +int LCM_effect[3] = {0x2, 0xf0, 0xf00}; +#endif DEFINE_LED_TRIGGER(bl_led_trigger); void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl) @@ -181,7 +193,7 @@ static void mdss_dsi_panel_apply_settings(struct mdss_dsi_ctrl_pdata *ctrl, mdss_dsi_cmdlist_put(ctrl, &cmdreq); } -static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl, +void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl, struct dsi_panel_cmds *pcmds, u32 flags) { struct dcs_cmd_req cmdreq; @@ -342,6 +354,9 @@ static int mdss_dsi_request_gpios(struct mdss_dsi_ctrl_pdata *ctrl_pdata) return rc; } +#ifdef CONFIG_PROJECT_VINCE +extern bool pullDownReset; +#endif int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) { struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; @@ -357,6 +372,10 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) panel_data); pinfo = &(ctrl_pdata->panel_data.panel_info); + if (enable) + printk("lcm %s enable enter\n", __func__); + else + printk("lcm %s disable enter\n", __func__); /* need to configure intf mux only for external interface */ if (pinfo->is_dba_panel) { @@ -470,6 +489,10 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) goto exit; } } + if (enable) + printk("lcm %s enable out\n", __func__); + else + printk("lcm %s disable out\n", __func__); if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) { pr_debug("%s: Panel Not properly turned OFF\n", __func__); @@ -486,7 +509,14 @@ int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable) usleep_range(100, 110); gpio_free(ctrl_pdata->disp_en_gpio); } + #ifdef CONFIG_PROJECT_VINCE + if (pullDownReset) { + pr_err("%s: pull down reset pin\n", __func__); + gpio_set_value((ctrl_pdata->rst_gpio), 0); + } + #else gpio_set_value((ctrl_pdata->rst_gpio), 0); + #endif gpio_free(ctrl_pdata->rst_gpio); if (gpio_is_valid(ctrl_pdata->mode_gpio)) gpio_free(ctrl_pdata->mode_gpio); @@ -862,6 +892,27 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) struct dsi_panel_cmds *on_cmds; int ret = 0; + struct dsi_panel_cmds *CABC_on_cmds_point; + struct dsi_panel_cmds *CABC_off_cmds_point; + struct dsi_panel_cmds *CE_on_cmds_point; + struct dsi_panel_cmds *CE_off_cmds_point; + struct dsi_panel_cmds *cold_gamma_cmds_point; + struct dsi_panel_cmds *warm_gamma_cmds_point; + struct dsi_panel_cmds *default_gamma_cmds_point; + struct dsi_panel_cmds *white_gamma_cmds_point; + struct dsi_panel_cmds *PM1_cmds_point; + struct dsi_panel_cmds *PM2_cmds_point; + struct dsi_panel_cmds *PM3_cmds_point; + struct dsi_panel_cmds *PM4_cmds_point; + struct dsi_panel_cmds *PM5_cmds_point; + struct dsi_panel_cmds *PM6_cmds_point; + struct dsi_panel_cmds *PM7_cmds_point; + struct dsi_panel_cmds *PM8_cmds_point; +#ifdef CONFIG_PROJECT_VINCE + struct dsi_panel_cmds *sRGB_on_cmds_point; + struct dsi_panel_cmds *sRGB_off_cmds_point; +#endif + if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; @@ -877,7 +928,6 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) if (ctrl->ndx != DSI_CTRL_LEFT) goto end; } - on_cmds = &ctrl->on_cmds; if ((pinfo->mipi.dms_mode == DYNAMIC_MODE_SWITCH_IMMEDIATE) && @@ -886,10 +936,135 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) pr_debug("%s: ndx=%d cmd_cnt=%d\n", __func__, ctrl->ndx, on_cmds->cmd_cnt); - + printk("lcm %s send init cmds\n", __func__); if (on_cmds->cmd_cnt) mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT); + if (!change_par_ctrl){ + pr_err("%s: change_par_ctrl is NULL, change lcm effect failed\n", __func__); + return 0; + } + + CABC_on_cmds_point = &change_par_ctrl->CABC_on_cmds; + CABC_off_cmds_point = &change_par_ctrl->CABC_off_cmds; + CE_on_cmds_point = &change_par_ctrl->CE_on_cmds; + CE_off_cmds_point = &change_par_ctrl->CE_off_cmds; + cold_gamma_cmds_point = &change_par_ctrl->cold_gamma_cmds; + warm_gamma_cmds_point = &change_par_ctrl->warm_gamma_cmds; + default_gamma_cmds_point = &change_par_ctrl->default_gamma_cmds; + white_gamma_cmds_point = &change_par_ctrl->white_gamma_cmds; + PM1_cmds_point = &change_par_ctrl->PM1_cmds; + PM2_cmds_point = &change_par_ctrl->PM2_cmds; + PM3_cmds_point = &change_par_ctrl->PM3_cmds; + PM4_cmds_point = &change_par_ctrl->PM4_cmds; + PM5_cmds_point = &change_par_ctrl->PM5_cmds; + PM6_cmds_point = &change_par_ctrl->PM6_cmds; + PM7_cmds_point = &change_par_ctrl->PM7_cmds; + PM8_cmds_point = &change_par_ctrl->PM8_cmds; +#ifdef CONFIG_PROJECT_VINCE + sRGB_on_cmds_point = &change_par_ctrl->sRGB_on_cmds; + sRGB_off_cmds_point = &change_par_ctrl->sRGB_off_cmds; +#endif + printk("lcm %s send effect cmds\n", __func__); + switch(LCM_effect[0]){ + case 0x0001: + mdss_dsi_panel_cmds_send(change_par_ctrl, warm_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0002: + mdss_dsi_panel_cmds_send(change_par_ctrl, default_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0003: + mdss_dsi_panel_cmds_send(change_par_ctrl, cold_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0004: + mdss_dsi_panel_cmds_send(change_par_ctrl, white_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0006: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM1_cmds_point, CMD_REQ_COMMIT); break; + case 0x0007: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM2_cmds_point, CMD_REQ_COMMIT); break; + case 0x0008: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM3_cmds_point, CMD_REQ_COMMIT); break; + case 0x0009: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM4_cmds_point, CMD_REQ_COMMIT); break; + case 0x000a: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM5_cmds_point, CMD_REQ_COMMIT); break; + case 0x000b: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM6_cmds_point, CMD_REQ_COMMIT); break; + case 0x000c: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM7_cmds_point, CMD_REQ_COMMIT); break; + case 0x0005: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM8_cmds_point, CMD_REQ_COMMIT); break; + } + if (LCM_effect[1] == 0x0010){ + #ifdef CONFIG_PROJECT_VINCE + switch(LCM_effect[3]){ + case 0x1000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_on_cmds_point, CMD_REQ_COMMIT); break; + case 0xf000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_off_cmds_point, CMD_REQ_COMMIT); break; + } + #endif + switch(LCM_effect[1]){ + case 0x0010: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x00f0: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_off_cmds_point, CMD_REQ_COMMIT); break; + } + switch(LCM_effect[2]){ + case 0x0100: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x0f00: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_off_cmds_point, CMD_REQ_COMMIT); break; + } + } + #ifdef CONFIG_PROJECT_VINCE + else if (LCM_effect[3] == 0x1000){ + switch(LCM_effect[1]){ + case 0x0010: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x00f0: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_off_cmds_point, CMD_REQ_COMMIT); break; + } + switch(LCM_effect[2]){ + case 0x0100: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x0f00: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_off_cmds_point, CMD_REQ_COMMIT); break; + } + + switch(LCM_effect[3]){ + case 0x1000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_on_cmds_point, CMD_REQ_COMMIT); break; + case 0xf000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_off_cmds_point, CMD_REQ_COMMIT); break; + } + } + #endif + else{ + switch(LCM_effect[1]){ + case 0x0010: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x00f0: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_off_cmds_point, CMD_REQ_COMMIT); break; + } + + switch(LCM_effect[2]){ + case 0x0100: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x0f00: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_off_cmds_point, CMD_REQ_COMMIT); break; + } + #ifdef CONFIG_PROJECT_VINCE + switch(LCM_effect[3]){ + case 0x1000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_on_cmds_point, CMD_REQ_COMMIT); break; + case 0xf000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_off_cmds_point, CMD_REQ_COMMIT); break; + } + #endif + } + printk("lcm %s send effect cmds out\n", __func__); if (pinfo->compression_mode == COMPRESSION_DSC) mdss_dsi_panel_dsc_pps_send(ctrl, pinfo); @@ -936,6 +1111,8 @@ static int mdss_dsi_post_panel_on(struct mdss_panel_data *pdata) ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); + change_par_ctrl = ctrl; + pr_debug("%s: ctrl=%pK ndx=%d\n", __func__, ctrl, ctrl->ndx); pinfo = &pdata->panel_info; @@ -978,6 +1155,7 @@ static int mdss_dsi_panel_off(struct mdss_panel_data *pdata) struct mdss_dsi_ctrl_pdata *ctrl = NULL; struct mdss_panel_info *pinfo; + if (pdata == NULL) { pr_err("%s: Invalid input data\n", __func__); return -EINVAL; @@ -1699,7 +1877,10 @@ static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl) for (i = 0; i < len; ++i) { if (ctrl->return_buf[i] != ctrl->status_value[group + i]) - break; + { + printk("%s: lcm esd error return_buf[%d] = %x, status_value[%d] = %x\n", __func__, i, ctrl->return_buf[i], i, ctrl->status_value[i]); + break; + } } if (i == len) @@ -1927,7 +2108,9 @@ static void mdss_dsi_parse_esd_params(struct device_node *np, ctrl->status_mode = ESD_REG; ctrl->check_read_status = mdss_dsi_gen_read_status; - } else if (!strcmp(string, "reg_read_nt35596")) { + } else if (!strcmp(string, "TE_check_NT35596")) { + ctrl->status_mode = ESD_TE_NT35596; + } else if (!strcmp(string, "reg_read_nt35596")) { ctrl->status_mode = ESD_REG_NT35596; ctrl->status_error_count = 0; ctrl->check_read_status = @@ -1948,11 +2131,9 @@ static void mdss_dsi_parse_esd_params(struct device_node *np, if ((ctrl->status_mode == ESD_BTA) || (ctrl->status_mode == ESD_TE) || (ctrl->status_mode == ESD_MAX)) return; - mdss_dsi_parse_dcs_cmds(np, &ctrl->status_cmds, "qcom,mdss-dsi-panel-status-command", "qcom,mdss-dsi-panel-status-command-state"); - rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-max-error-count", &tmp); ctrl->max_status_error_count = (!rc ? tmp : 0); @@ -2442,10 +2623,12 @@ static int mdss_dsi_panel_timing_from_dt(struct device_node *np, pr_info("%s: found new timing \"%s\" (%pK)\n", __func__, np->name, &pt->timing); } - return 0; } +#ifdef CONFIG_PROJECT_VINCE +extern int white_point_num; +#endif static int mdss_dsi_panel_config_res_properties(struct device_node *np, struct dsi_panel_timing *pt, struct mdss_panel_data *panel_data, @@ -2453,11 +2636,32 @@ static int mdss_dsi_panel_config_res_properties(struct device_node *np, { int rc = 0; +#ifdef CONFIG_PROJECT_VINCE + unsigned char dsi_on_num[3] = ""; + unsigned char dsi_on_str[27] = "qcom,mdss-dsi-on-command-"; +#endif + mdss_dsi_parse_roi_alignment(np, pt); +#ifdef CONFIG_PROJECT_VINCE + sprintf(dsi_on_num, "%02d", white_point_num); + strcat(dsi_on_str, dsi_on_num); + strcat(dsi_on_str, "\0"); + + if (white_point_num){ + pr_err("[white point calibration] dsi_on_command = %s", dsi_on_str); + mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds, + dsi_on_str, "qcom,mdss-dsi-on-command-state"); + }else{ + mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds, + "qcom,mdss-dsi-on-command", + "qcom,mdss-dsi-on-command-state"); + } +#else mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds, "qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state"); +#endif mdss_dsi_parse_dcs_cmds(np, &pt->post_panel_on_cmds, "qcom,mdss-dsi-post-panel-on-command", NULL); @@ -2599,6 +2803,10 @@ static int mdss_panel_parse_dt(struct device_node *np, static const char *pdest; struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info); +#ifdef CONFIG_PROJECT_VINCE + unsigned char dsi_white_num[3] = ""; + unsigned char dsi_white_str[26] = "qcom,mdss-white-command-"; +#endif if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) pinfo->is_split_display = true; @@ -2655,7 +2863,11 @@ static int mdss_panel_parse_dt(struct device_node *np, pinfo->panel_orientation = MDP_FLIP_UD; } +#ifdef CONFIG_PROJECT_DAISY + rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level-global", &tmp); +#else rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp); +#endif pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS); rc = of_property_read_u32(np, "qcom,mdss-dsi-bl-min-level", &tmp); pinfo->bl_min = (!rc ? tmp : 0); @@ -2799,6 +3011,67 @@ static int mdss_panel_parse_dt(struct device_node *np, mdss_dsi_parse_reset_seq(np, pinfo->rst_seq, &(pinfo->rst_seq_len), "qcom,mdss-dsi-reset-sequence"); + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->CABC_on_cmds, + "qcom,mdss-dsi-CABC_on-command", "qcom,mdss-dsi-CABC_on-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->CABC_off_cmds, + "qcom,mdss-dsi-CABC_off-command", "qcom,mdss-dsi-CABC_off-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->CE_on_cmds, + "qcom,mdss-dsi-CE_on-command", "qcom,mdss-dsi-CE_on-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->CE_off_cmds, + "qcom,mdss-dsi-CE_off-command", "qcom,mdss-dsi-CE_off-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->cold_gamma_cmds, + "qcom,mdss-dsi-cold_gamma-command", "qcom,mdss-dsi-cold_gamma-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->warm_gamma_cmds, + "qcom,mdss-dsi-warm_gamma-command", "qcom,mdss-dsi-warm_gamma-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->default_gamma_cmds, + "qcom,mdss-dsi-default_gamma-command", "qcom,mdss-dsi-default_gamma-command-state"); +#ifdef CONFIG_PROJECT_VINCE + sprintf(dsi_white_num, "%02d", white_point_num); + strcat(dsi_white_str, dsi_white_num); + strcat(dsi_white_str, "\0"); + printk("sxf white_point_num = %d\n", white_point_num); + printk("[white point calibration] sxf dsi_white_command = %s", dsi_white_str); + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->white_gamma_cmds, + dsi_white_str, "qcom,mdss-white-command-state"); + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->sRGB_on_cmds, + "qcom,mdss-dsi-sRGB_on-command", "qcom,mdss-dsi-sRGB_on-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->sRGB_off_cmds, + "qcom,mdss-dsi-sRGB_off-command", "qcom,mdss-dsi-sRGB_off-command-state"); +#endif + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM1_cmds, + "qcom,mdss-dsi-PM1-command", "qcom,mdss-dsi-PM1-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM2_cmds, + "qcom,mdss-dsi-PM2-command", "qcom,mdss-dsi-PM2-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM3_cmds, + "qcom,mdss-dsi-PM3-command", "qcom,mdss-dsi-PM3-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM4_cmds, + "qcom,mdss-dsi-PM4-command", "qcom,mdss-dsi-PM4-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM5_cmds, + "qcom,mdss-dsi-PM5-command", "qcom,mdss-dsi-PM5-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM6_cmds, + "qcom,mdss-dsi-PM6-command", "qcom,mdss-dsi-PM6-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM7_cmds, + "qcom,mdss-dsi-PM7-command", "qcom,mdss-dsi-PM7-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->PM8_cmds, + "qcom,mdss-dsi-PM8-command", "qcom,mdss-dsi-PM8-command-state"); + + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds, + "qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state"); + mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->off_cmds, "qcom,mdss-dsi-off-command", "qcom,mdss-dsi-off-command-state"); diff --git a/drivers/video/msm/mdss/mdss_dsi_status.c b/drivers/video/msm/mdss/mdss_dsi_status.c index 853c70a5e3e0e..009f3c9978916 100644 --- a/drivers/video/msm/mdss/mdss_dsi_status.c +++ b/drivers/video/msm/mdss/mdss_dsi_status.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -31,12 +32,17 @@ #include "mdss_panel.h" #include "mdss_mdp.h" +#ifdef CONFIG_PROJECT_VINCE +#define STATUS_CHECK_INTERVAL_MS 1000 +#else #define STATUS_CHECK_INTERVAL_MS 5000 +#endif #define STATUS_CHECK_INTERVAL_MIN_MS 50 #define DSI_STATUS_CHECK_INIT -1 #define DSI_STATUS_CHECK_DISABLE 1 -static uint32_t interval = STATUS_CHECK_INTERVAL_MS; +uint32_t ESD_interval = STATUS_CHECK_INTERVAL_MS; + static int32_t dsi_status_disable = DSI_STATUS_CHECK_INIT; struct dsi_status_data *pstatus_data; @@ -68,7 +74,7 @@ static void check_dsi_ctrl_status(struct work_struct *work) return; } - pdsi_status->mfd->mdp.check_dsi_status(work, interval); + pdsi_status->mfd->mdp.check_dsi_status(work, ESD_interval); } /* @@ -91,7 +97,7 @@ irqreturn_t hw_vsync_handler(int irq, void *data) if (pstatus_data) mod_delayed_work(system_wq, &pstatus_data->check_status, - msecs_to_jiffies(interval)); + msecs_to_jiffies(ESD_interval)); else pr_err("Pstatus data is NULL\n"); @@ -175,7 +181,7 @@ static int fb_event_callback(struct notifier_block *self, switch (*blank) { case FB_BLANK_UNBLANK: schedule_delayed_work(&pdata->check_status, - msecs_to_jiffies(interval)); + msecs_to_jiffies(ESD_interval)); break; case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_NORMAL: @@ -259,7 +265,7 @@ int __init mdss_dsi_status_init(void) return -EPERM; } - pr_info("%s: DSI status check interval:%d\n", __func__, interval); + pr_info("%s: DSI status check interval:%d\n", __func__, ESD_interval); INIT_DELAYED_WORK(&pstatus_data->check_status, check_dsi_ctrl_status); @@ -276,9 +282,9 @@ void __exit mdss_dsi_status_exit(void) pr_debug("%s: DSI ctrl status work queue removed\n", __func__); } -module_param_call(interval, param_set_interval, param_get_uint, - &interval, 0644); -MODULE_PARM_DESC(interval, +module_param_call(ESD_interval, param_set_interval, param_get_uint, + &ESD_interval, 0644); +MODULE_PARM_DESC(ESD_interval, "Duration in milliseconds to send BTA command for checking" "DSI status periodically"); diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index bb80af8fbdf8b..d6e2b541e9639 100644 --- a/drivers/video/msm/mdss/mdss_fb.c +++ b/drivers/video/msm/mdss/mdss_fb.c @@ -14,7 +14,8 @@ * GNU General Public License for more details. */ -#define pr_fmt(fmt) "%s: " fmt, __func__ + + #include #include @@ -24,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -54,8 +57,26 @@ #include "mdss_debug.h" #include "mdss_smmu.h" #include "mdss_mdp.h" +#include "mdss_dsi.h" #include "mdp3_ctrl.h" +extern struct mdss_dsi_ctrl_pdata *change_par_ctrl ; +extern int change_par_buf; +#ifdef CONFIG_PROJECT_VINCE +extern int LCM_effect[4]; +#else +extern int LCM_effect[3]; +#endif + + +#if defined(CONFIG_WPONIT_ADJUST_FUN) +extern uint32_t white_point_num_x; +extern uint32_t white_point_num_y; +extern uint32_t white_point_num_r; +extern uint32_t white_point_num_g; +extern uint32_t white_point_num_b; +#endif + #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER #define MDSS_FB_NUM 3 #else @@ -122,6 +143,39 @@ static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd, int event, void *arg); static void mdss_fb_set_mdp_sync_pt_threshold(struct msm_fb_data_type *mfd, int type); + + +#define WAIT_RESUME_TIMEOUT 200 +struct fb_info *prim_fbi; +static struct delayed_work prim_panel_work; +static atomic_t prim_panel_is_on; +static struct wake_lock prim_panel_wakelock; +static void prim_panel_off_delayed_work(struct work_struct *work) +{ +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_lock(); +#endif + if (!lock_fb_info(prim_fbi)) { +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + return; + } + printk("linson prim_panel_off_delayed_work close FB\n"); + if (atomic_read(&prim_panel_is_on)) { + printk("linson2 prim_panel_is_on = %d \n", atomic_read(&prim_panel_is_on)); + fb_blank(prim_fbi, FB_BLANK_POWERDOWN); + atomic_set(&prim_panel_is_on, false); + wake_unlock(&prim_panel_wakelock); + } + + unlock_fb_info(prim_fbi); +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif +} + + void mdss_fb_no_update_notify_timer_cb(unsigned long data) { struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; @@ -752,6 +806,205 @@ static int mdss_fb_blanking_mode_switch(struct msm_fb_data_type *mfd, int mode) return 0; } +static ssize_t mdss_fb_change_dispparam(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + + struct dsi_panel_cmds *CABC_on_cmds_point; + struct dsi_panel_cmds *CABC_off_cmds_point; + struct dsi_panel_cmds *CE_on_cmds_point; + struct dsi_panel_cmds *CE_off_cmds_point; + struct dsi_panel_cmds *cold_gamma_cmds_point; + struct dsi_panel_cmds *warm_gamma_cmds_point; + struct dsi_panel_cmds *default_gamma_cmds_point; + struct dsi_panel_cmds *white_gamma_cmds_point; + struct dsi_panel_cmds *PM1_cmds_point; + struct dsi_panel_cmds *PM2_cmds_point; + struct dsi_panel_cmds *PM3_cmds_point; + struct dsi_panel_cmds *PM4_cmds_point; + struct dsi_panel_cmds *PM5_cmds_point; + struct dsi_panel_cmds *PM6_cmds_point; + struct dsi_panel_cmds *PM7_cmds_point; + struct dsi_panel_cmds *PM8_cmds_point; +#ifdef CONFIG_PROJECT_VINCE + struct dsi_panel_cmds *sRGB_on_cmds_point; + struct dsi_panel_cmds *sRGB_off_cmds_point; +#endif + + sscanf(buf, "%x", &change_par_buf) ; + + if (!change_par_ctrl){ + pr_err("%s: change_par_ctrl is NULL, change lcm effect failed\n", __func__); + return 0; + } + + CABC_on_cmds_point = &change_par_ctrl->CABC_on_cmds; + CABC_off_cmds_point = &change_par_ctrl->CABC_off_cmds; + CE_on_cmds_point = &change_par_ctrl->CE_on_cmds; + CE_off_cmds_point = &change_par_ctrl->CE_off_cmds; + cold_gamma_cmds_point = &change_par_ctrl->cold_gamma_cmds; + warm_gamma_cmds_point = &change_par_ctrl->warm_gamma_cmds; + default_gamma_cmds_point = &change_par_ctrl->default_gamma_cmds; + white_gamma_cmds_point = &change_par_ctrl->white_gamma_cmds; + PM1_cmds_point = &change_par_ctrl->PM1_cmds; + PM2_cmds_point = &change_par_ctrl->PM2_cmds; + PM3_cmds_point = &change_par_ctrl->PM3_cmds; + PM4_cmds_point = &change_par_ctrl->PM4_cmds; + PM5_cmds_point = &change_par_ctrl->PM5_cmds; + PM6_cmds_point = &change_par_ctrl->PM6_cmds; + PM7_cmds_point = &change_par_ctrl->PM7_cmds; + PM8_cmds_point = &change_par_ctrl->PM8_cmds; +#ifdef CONFIG_PROJECT_VINCE + sRGB_on_cmds_point = &change_par_ctrl->sRGB_on_cmds; + sRGB_off_cmds_point = &change_par_ctrl->sRGB_off_cmds; +#endif + + if ((change_par_buf >= 0x01) && (change_par_buf <= 0x0c)) { + LCM_effect[0] = change_par_buf; + } else if ((change_par_buf == 0x10) || (change_par_buf == 0xf0)) { + LCM_effect[1] = change_par_buf; + } else if ((change_par_buf == 0x100) || (change_par_buf == 0xf00)) { + LCM_effect[2] = change_par_buf; + } + #ifdef CONFIG_PROJECT_VINCE + else if ((change_par_buf == 0x1000) || (change_par_buf == 0xf000)) { + LCM_effect[3] = change_par_buf; + } + #endif + + printk("mdss_fb_change_dispparam: mode=%x\n", change_par_buf); + switch(change_par_buf){ + case 0x0001: + mdss_dsi_panel_cmds_send(change_par_ctrl, warm_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0002: + mdss_dsi_panel_cmds_send(change_par_ctrl, default_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0003: + mdss_dsi_panel_cmds_send(change_par_ctrl, cold_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0004: + mdss_dsi_panel_cmds_send(change_par_ctrl, white_gamma_cmds_point, CMD_REQ_COMMIT); + break; + case 0x0006: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM1_cmds_point, CMD_REQ_COMMIT); break; + case 0x0007: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM2_cmds_point, CMD_REQ_COMMIT); break; + case 0x0008: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM3_cmds_point, CMD_REQ_COMMIT); break; + case 0x0009: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM4_cmds_point, CMD_REQ_COMMIT); break; + case 0x000a: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM5_cmds_point, CMD_REQ_COMMIT); break; + case 0x000b: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM6_cmds_point, CMD_REQ_COMMIT); break; + case 0x000c: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM7_cmds_point, CMD_REQ_COMMIT); break; + case 0x0005: + mdss_dsi_panel_cmds_send(change_par_ctrl, PM8_cmds_point, CMD_REQ_COMMIT); break; + case 0x0010: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x00f0: + mdss_dsi_panel_cmds_send(change_par_ctrl, CE_off_cmds_point, CMD_REQ_COMMIT); break; + case 0x0100: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_on_cmds_point, CMD_REQ_COMMIT); break; + case 0x0f00: + mdss_dsi_panel_cmds_send(change_par_ctrl, CABC_off_cmds_point, CMD_REQ_COMMIT); break; + #ifdef CONFIG_PROJECT_VINCE + case 0x1000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_on_cmds_point, CMD_REQ_COMMIT); break; + case 0xf000: + mdss_dsi_panel_cmds_send(change_par_ctrl, sRGB_off_cmds_point, CMD_REQ_COMMIT); break; + #endif + } + + return len; +} + +static ssize_t mdss_fb_get_dispparam(struct device *dev, + struct device_attribute *attr, char *buf) +{ + + int ret; + #ifdef CONFIG_PROJECT_VINCE + ret = scnprintf(buf, PAGE_SIZE, "%x%x%x%x\n", + LCM_effect[0] , LCM_effect[1] , LCM_effect[2] , LCM_effect[3]); + #else + ret = scnprintf(buf, PAGE_SIZE, "%x%x%x\n", + LCM_effect[0] , LCM_effect[1] , LCM_effect[2]); + #endif + return ret; +} + +#if defined(CONFIG_WPONIT_ADJUST_FUN) +bool set_white_point_x = true; +static ssize_t mdss_fb_set_wpoint(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + if (set_white_point_x) + { + sscanf(buf, "%3d", &white_point_num_x) ; + set_white_point_x = false; + } + else + { + sscanf(buf, "%3d", &white_point_num_y) ; + set_white_point_x = true; + } + return len; +} +static ssize_t mdss_fb_get_wpoint(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + ret = scnprintf(buf, PAGE_SIZE, "%3d%3d\n", + white_point_num_x, white_point_num_y); + return ret; +} +static ssize_t mdss_fb_set_rpoint(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + sscanf(buf, "%6d", &white_point_num_r) ; + return len; +} +static ssize_t mdss_fb_get_rpoint(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + ret = scnprintf(buf, PAGE_SIZE, "%6d\n", + white_point_num_r); + return ret; +} +static ssize_t mdss_fb_set_gpoint(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + sscanf(buf, "%6d", &white_point_num_g) ; + return len; +} +static ssize_t mdss_fb_get_gpoint(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + ret = scnprintf(buf, PAGE_SIZE, "%6d\n", + white_point_num_g); + return ret; +} +static ssize_t mdss_fb_set_bpoint(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + sscanf(buf, "%6d", &white_point_num_b) ; + return len; +} +static ssize_t mdss_fb_get_bpoint(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + ret = scnprintf(buf, PAGE_SIZE, "%6d\n", + white_point_num_b); + return ret; +} +#endif + static ssize_t mdss_fb_change_dfps_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -906,6 +1159,18 @@ static DEVICE_ATTR(measured_fps, S_IRUGO | S_IWUSR | S_IWGRP, mdss_fb_get_fps_info, NULL); static DEVICE_ATTR(msm_fb_persist_mode, S_IRUGO | S_IWUSR, mdss_fb_get_persist_mode, mdss_fb_change_persist_mode); +static DEVICE_ATTR(msm_fb_dispparam, S_IRUGO | S_IWUSR, + mdss_fb_get_dispparam, mdss_fb_change_dispparam); +#if defined(CONFIG_WPONIT_ADJUST_FUN) +static DEVICE_ATTR(msm_fb_wpoint, S_IRUGO | S_IWUSR, + mdss_fb_get_wpoint, mdss_fb_set_wpoint); +static DEVICE_ATTR(msm_fb_rpoint, S_IRUGO | S_IWUSR, + mdss_fb_get_rpoint, mdss_fb_set_rpoint); +static DEVICE_ATTR(msm_fb_gpoint, S_IRUGO | S_IWUSR, + mdss_fb_get_gpoint, mdss_fb_set_gpoint); +static DEVICE_ATTR(msm_fb_bpoint, S_IRUGO | S_IWUSR, + mdss_fb_get_bpoint, mdss_fb_set_bpoint); +#endif static struct attribute *mdss_fb_attrs[] = { &dev_attr_msm_fb_type.attr, &dev_attr_msm_fb_split.attr, @@ -919,6 +1184,13 @@ static struct attribute *mdss_fb_attrs[] = { &dev_attr_msm_fb_dfps_mode.attr, &dev_attr_measured_fps.attr, &dev_attr_msm_fb_persist_mode.attr, + &dev_attr_msm_fb_dispparam.attr, +#if defined(CONFIG_WPONIT_ADJUST_FUN) + &dev_attr_msm_fb_wpoint.attr, + &dev_attr_msm_fb_rpoint.attr, + &dev_attr_msm_fb_gpoint.attr, + &dev_attr_msm_fb_bpoint.attr, +#endif NULL, }; @@ -1199,6 +1471,7 @@ static int mdss_fb_init_panel_modes(struct msm_fb_data_type *mfd, return 0; } +static int ffbm_first_close_bl; static int mdss_fb_probe(struct platform_device *pdev) { struct msm_fb_data_type *mfd = NULL; @@ -1295,6 +1568,12 @@ static int mdss_fb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mfd); + if (strnstr(saved_command_line, "androidboot.mode=ffbm-01", + strlen(saved_command_line))){ + ffbm_first_close_bl = true; + pr_err("We are in ffbm-01 mode!\n"); + } + rc = mdss_fb_register(mfd); if (rc) return rc; @@ -1402,6 +1681,14 @@ static int mdss_fb_remove(struct platform_device *pdev) mdss_fb_remove_sysfs(mfd); + + if (mfd->panel_info && mfd->panel_info->is_prim_panel) { + atomic_set(&prim_panel_is_on, false); + cancel_delayed_work_sync(&prim_panel_work); + wake_lock_destroy(&prim_panel_wakelock); + } + + pm_runtime_disable(mfd->fbi->dev); if (mfd->key != MFD_KEY) @@ -1575,6 +1862,32 @@ static int mdss_fb_resume(struct platform_device *pdev) #endif #ifdef CONFIG_PM_SLEEP + +static int mdss_fb_pm_prepare(struct device *dev) +{ + struct msm_fb_data_type *mfd = dev_get_drvdata(dev); + + if (!mfd) + return -ENODEV; + if (mfd->panel_info->is_prim_panel) + atomic_inc(&mfd->resume_pending); + return 0; +} + +static void mdss_fb_pm_complete(struct device *dev) +{ + struct msm_fb_data_type *mfd = dev_get_drvdata(dev); + + if (!mfd) + return; + if (mfd->panel_info->is_prim_panel) { + atomic_set(&mfd->resume_pending, 0); + wake_up_all(&mfd->resume_wait_q); + } + return; +} + + static int mdss_fb_pm_suspend(struct device *dev) { struct msm_fb_data_type *mfd = dev_get_drvdata(dev); @@ -1609,6 +1922,10 @@ static int mdss_fb_pm_resume(struct device *dev) #endif static const struct dev_pm_ops mdss_fb_pm_ops = { + + .prepare = mdss_fb_pm_prepare, + .complete = mdss_fb_pm_complete, + SET_SYSTEM_SLEEP_PM_OPS(mdss_fb_pm_suspend, mdss_fb_pm_resume) }; @@ -1700,6 +2017,10 @@ void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl) */ if (mfd->bl_level_scaled == temp) { mfd->bl_level = bkl_lvl; + if ((0 == temp) && (ffbm_first_close_bl == true)){ + pdata->set_backlight(pdata, temp); + ffbm_first_close_bl = false; + } } else { if (mfd->bl_level != bkl_lvl) bl_notify_needed = true; @@ -2066,6 +2387,18 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info) struct mdss_panel_data *pdata; struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; + + + if ((info == prim_fbi) && (blank_mode == FB_BLANK_UNBLANK) && + atomic_read(&prim_panel_is_on)) { + atomic_set(&prim_panel_is_on, false); + wake_unlock(&prim_panel_wakelock); + cancel_delayed_work_sync(&prim_panel_work); + + return 0; + } + + ret = mdss_fb_pan_idle(mfd); if (ret) { pr_warn("mdss_fb_pan_idle for fb%d failed. ret=%d\n", @@ -2694,6 +3027,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) atomic_set(&mfd->commits_pending, 0); atomic_set(&mfd->ioctl_ref_cnt, 0); atomic_set(&mfd->kickoff_pending, 0); + atomic_set(&mfd->resume_pending, 0); init_timer(&mfd->no_update.timer); mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb; @@ -2709,6 +3043,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) init_waitqueue_head(&mfd->idle_wait_q); init_waitqueue_head(&mfd->ioctl_q); init_waitqueue_head(&mfd->kickoff_wait_q); + init_waitqueue_head(&mfd->resume_wait_q); ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret) @@ -2727,6 +3062,15 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd) pr_info("FrameBuffer[%d] %dx%d registered successfully!\n", mfd->index, fbi->var.xres, fbi->var.yres); + + if (panel_info->is_prim_panel) { + prim_fbi = fbi; + atomic_set(&prim_panel_is_on, false); + INIT_DELAYED_WORK(&prim_panel_work, prim_panel_off_delayed_work); + wake_lock_init(&prim_panel_wakelock, WAKE_LOCK_SUSPEND, "prim_panel_wakelock"); + } + + return 0; } @@ -3362,6 +3706,8 @@ int mdss_fb_atomic_commit(struct fb_info *info, int ret = -EPERM; u32 old_xres, old_yres, old_format; + + if (!mfd || (!mfd->op_enable)) { pr_err("mfd is NULL or operation not permitted\n"); return -EPERM; @@ -4927,6 +5273,7 @@ static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd, if (!info || !info->par) return -EINVAL; + return mdss_fb_do_ioctl(info, cmd, arg, file); } @@ -5120,6 +5467,70 @@ void mdss_fb_report_panel_dead(struct msm_fb_data_type *mfd) } + + /* + * mdss_prim_panel_fb_unblank() - Unblank primary panel FB + * @timeout : >0 blank primary panel FB after timeout (ms) + */ +int mdss_prim_panel_fb_unblank(int timeout) +{ + int ret = 0; + struct msm_fb_data_type *mfd = NULL; + + printk("SXF Enter %s\n", __func__); + if (prim_fbi) { + mfd = (struct msm_fb_data_type *)prim_fbi->par; + ret = wait_event_timeout(mfd->resume_wait_q, + !atomic_read(&mfd->resume_pending), + msecs_to_jiffies(WAIT_RESUME_TIMEOUT)); + if (!ret) { + printk("Primary fb resume timeout\n"); + return -ETIMEDOUT; + } +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_lock(); +#endif + if (!lock_fb_info(prim_fbi)) { +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + printk("SXF !lock_fb_info(prim_fbi) %s_%d\n", __func__, __LINE__); + return -ENODEV; + } + if (prim_fbi->blank == FB_BLANK_UNBLANK) { + unlock_fb_info(prim_fbi); +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + printk("SXF %s_%d\n", __func__, __LINE__); + return 0; + } + wake_lock(&prim_panel_wakelock); + ret = fb_blank(prim_fbi, FB_BLANK_UNBLANK); + printk("SXF fb_blank(prim_fbi, FB_BLANK_UNBLANK) %s , ret = %d\n", __func__, ret); + if (!ret) { + atomic_set(&prim_panel_is_on, true); + if (timeout > 0){ + printk("SXF %s , timeout = %d\n", __func__, timeout); + schedule_delayed_work(&prim_panel_work, msecs_to_jiffies(timeout)); + } + else + wake_unlock(&prim_panel_wakelock); + } else + wake_unlock(&prim_panel_wakelock); + unlock_fb_info(prim_fbi); +#ifdef CONFIG_FRAMEBUFFER_CONSOLE + console_unlock(); +#endif + printk("SXF Exit %s\n", __func__); + return ret; + } + + pr_err("primary panel is not existed\n"); + return -EINVAL; +} + + /* * mdss_fb_calc_fps() - Calculates fps value. * @mfd : frame buffer structure associated with fb device. diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h index 336a751d52b04..9ede5875fed87 100644 --- a/drivers/video/msm/mdss/mdss_fb.h +++ b/drivers/video/msm/mdss/mdss_fb.h @@ -333,6 +333,10 @@ struct msm_fb_data_type { struct task_struct *disp_thread; atomic_t commits_pending; atomic_t kickoff_pending; + + atomic_t resume_pending; + wait_queue_head_t resume_wait_q; + wait_queue_head_t commit_wait_q; wait_queue_head_t idle_wait_q; wait_queue_head_t kickoff_wait_q; diff --git a/firmware/GTP/goodix_firmware.bin b/firmware/GTP/goodix_firmware.bin new file mode 100644 index 0000000000000..8b8376e7d2296 Binary files /dev/null and b/firmware/GTP/goodix_firmware.bin differ diff --git a/firmware/Makefile b/firmware/Makefile index e297e1b52636d..e8b6460377cef 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -26,6 +26,8 @@ fw-shipped- += acenic/tg1.bin else acenic-objs := acenic/tg1.bin acenic/tg2.bin endif +fw-shipped-$(CONFIG_TOUCHSCREEN_TD4310_E7) += synaptics/startup_fw_update.img +fw-shipped-$(CONFIG_TOUCHSCREEN_TD4310_LANSI_E7) += synaptics/startup_fw_update_lansi.img fw-shipped-$(CONFIG_ACENIC) += $(acenic-objs) fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \ adaptec/starfire_tx.bin diff --git a/firmware/NVT_huaxing/novatek_ts_fw.bin b/firmware/NVT_huaxing/novatek_ts_fw.bin new file mode 100644 index 0000000000000..078da7b1481e5 Binary files /dev/null and b/firmware/NVT_huaxing/novatek_ts_fw.bin differ diff --git a/firmware/synaptics/startup_fw_update.img.ihex b/firmware/synaptics/startup_fw_update.img.ihex new file mode 100644 index 0000000000000..b0ed676e61d1c --- /dev/null +++ b/firmware/synaptics/startup_fw_update.img.ihex @@ -0,0 +1,8034 @@ +:10000000ABF6DBF80000030600B0010000100000B2 +:1000100045373030000000000000D610010000001D +:1000200000010000002000000021000000B00100DD +:10003000445335205231322E352E3200000000005C +:1000400000E6010000100000B00000000000000009 +:10005000816E2A0000000000000000000000000087 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000080 +:100080000000000000000000000000000000000070 +:10009000493243001D01FF000C0D2000000000004C +:1000A000493243001D01FF000C0D2000000000003C +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:100100003556E78E8BCCF8F9F717355ACF34CC60DB +:1001100064F91EAE3D758B7757577ADCA8D0A29054 +:1001200022BB43014C0436BD978616DC263B9BCA96 +:10013000CCFF44060C77D1B573312F084C336C6B70 +:100140006A363DE3F3F5D7C8B9254543874B94910B +:1001500097B9B43C3CA720020BB1AF7B0225C9384C +:10016000B3EA9984E0FA8142E620A0B494FEC7D9AC +:10017000B0E6B43F003218C1696166FA6FBF888289 +:10018000AB3EFFF7B592695014C55B7E5BB4457E0C +:10019000ABCDE85D52802A4D1B164417267939B73E +:1001A000E84F12216149C041E28F4F2B7D5C7D9960 +:1001B000BAF422877D2C130FCC11C90D180D37EB23 +:1001C0005DFB20B7DEDFE61CDA53593509114657CF +:1001D000C857E91EDB42DC33BDAD4070CF321C9600 +:1001E00087DDDB9BFD71174A7D91E6EF228C6D6CFC +:1001F00026C537EB72EFC150C59C6E0E4EB7842EEC +:1002000068FECC4780DBDB5F9FEF4D2E734FEA37F4 +:1002100038C4252699CA1D9C511A376EBE8A5AA524 +:10022000942413C80BBD81263F6C94814FFA990C1E +:10023000156E7857D0F589DAD8ACD50363EA52A3A6 +:100240006C0729717ED6D2A58E382E27DBF99E9FAA +:10025000619264A1E7F71DC42D3787489157921426 +:1002600032996E5F56C8016134D2E3929BE7283F12 +:10027000D92AFA6AF430E21CE31A3CE1EB003F08A9 +:100280008DB630F0AA91199B13574FC5641A8A771F +:10029000F92F1A5B9F61C84D6CDC8ED6977715CF0E +:1002A00076894A7049DE292E58ADA82272B9235D9D +:1002B00019556AAF0AC65B69665B8FBECDCA93BD2E +:1002C000B57B70E1DFA1947E363F1DAFFF3898DA31 +:1002D0008AE1329B2DD3878A4688F3C45CE82EB12D +:1002E000D719A3EB915BCD3C6639E4B14E43EEDD0B +:1002F000FE050713AB8CD5531F46B89078E6B6833E +:10030000ABAB165A5637443E54D4460158ACF64E61 +:10031000B27669E4DB64D92E56DA41DA465F91E3BE +:10032000B20184480EB68F9706D7BFD4A8962DE9A0 +:10033000E8957CC5E03794C24044DFF5801001CFDA +:10034000B6F89A8710600361BACFDC2E5A32517723 +:100350000591EC66EE85F935EA7DAE4CB84F4B5809 +:10036000B5E6DE8A866EB6047E0ADF449A35DA7414 +:10037000995C57319E2C18782F2860B2AA72D70248 +:10038000DC6F7B1952F84CA090AC4CCCA6365AEDE1 +:10039000DA65A69C4A05FE7EC0AFD731AB9798D1EF +:1003A00092772C3AF809FD510FB6E5E80FB3E93F13 +:1003B00011D00216EE1772AD22C3E96FD423C555D2 +:1003C0009EC21CB0D477D6293BDD1698044799CE3F +:1003D00091962686B7499E74CAFD6E7BA9D2664C5B +:1003E000468DF1B81C7F6222547252B6615EAA7CBF +:1003F000630EC4D39D637FDD71116432328F7FF44D +:100400003E73B6331370E438F74096973C29A152F7 +:10041000D9E9DCE3BC9A21699729DFF5B052482C71 +:1004200016908B0148C579357FB5DCBAD48F3E6A0A +:10043000D0D6D3E5C32DFADC70B357C01023FC9E91 +:10044000F5F40BE540CFDF460673CD1CFF1972654E +:100450003739C12E12F2F8F412233939F1D93C00A0 +:100460006F4A6078DFB4C145EEEAE4E5E6F459FE90 +:1004700096875F9D080974DF2C3EFA115788086241 +:100480009C483D25B005706EE88B502448E51A2B3A +:100490002414276F9E81F89F999DE76D644C8526F3 +:1004A0008D3756BAF251C701E6A980535C4CCF8212 +:1004B0003008A208F283A7A34DCB7D16AA82B92FDC +:1004C00012AD4B9C5E68E17F03CAE4FC19BEF79550 +:1004D000C57CF664C1A7C2760BB59329A469DABCC2 +:1004E0004000D96FE1BE540A2E16B5EF2F2954EA09 +:1004F0007923ED33DAE631E0BCA0B06EF2D274B904 +:100500007C90FB37E6E661DCAEA32B07C22BC6145A +:10051000F757190B2392FCF9BA8CD7F1AF5F1F2D57 +:10052000C0C59ADF2913AB5EA5BFD3E682D388ADE1 +:100530005C15FAA20863DF80D60647FB312BAB437C +:10054000806C9EEFCFBBEB8BB406FDE779FBF383AA +:100550002DEB73B7733265A973496372F603E4DC5C +:10056000D70C53F8377E0223345778AEE17FA24090 +:10057000588A0C3A26F558F824F17720914CC1F4AA +:10058000E4D60C4ADD16154E0763EDC13E2A8C2ACF +:10059000989F0714F4818CBF70FFE046136650EDFE +:1005A00098E6902C0498EB2D53DE53607B8DFCD4A1 +:1005B00031A3A62802825B3C9DDDB338D95F6DD0A4 +:1005C0003DEEA56975B19D796BD76C8BE8EA054363 +:1005D000357592332FA2C0798B1326938458E55B2F +:1005E0007DF5B35BC502E124A2C71504C96B63DEC8 +:1005F000AF51FB04E5B4E404ACA5CA5EFD23EBEF08 +:10060000E5C3E23BA0516E9F1BBA3FCD1D3BDC48CA +:100610006E723B8D43A9AEC95EDD3BD9D58C307D72 +:10062000B394A344AC88417BD388AC156A417E76F1 +:10063000CDD618CB8D529EB0865FF8D40B33CE9EAC +:100640003C8F7B0808FDF7CCB27F2740E7CB5E1CD0 +:10065000E5B0E2445515DBD1024DAC936BEF12933C +:10066000EB54086CCD2C3DFFC0B0C23C0BB2EC9DEE +:10067000DA5B77BC97D8BF38A3AFA51878398F025B +:100680002668360985DC6DD9D71C7D69B8498AFD95 +:1006900009BE6439D9F019C81857DBE91A73913CBF +:1006A0006C213CF089EE2842CC75EAE8676C546214 +:1006B000690BA0833AB81B3496521DC47BF3DB92BE +:1006C000B2294604988A871A989DE8C3CF5660528B +:1006D000AAED99ADCE21D7F8C6754DD3A69E690F68 +:1006E000983913107D60994A690B99C0930E4C1785 +:1006F000E78A83545E5834F23EA1D4F8D8B5F0CFDF +:100700001390821CA8DCF6492473309965D2C1FC91 +:1007100099BD5ED41AB312DBB385DA492CE3016DBF +:100720002CB9D8550BF2813EBF4F2233359C360D84 +:10073000A48C8C36D7E9FCE08FBA764D72FC317709 +:1007400067BB14F30AE8CD09A2E72F8E485BDAD421 +:1007500040D12D91BA64F4C03C21E9F504A1325096 +:1007600030AB379ED12437B449DE6EAFEE14132878 +:1007700072CA82F5167F63358C0B05D27C1B57A598 +:10078000EC8532D2695B6FA5C8B7078203736E84AC +:100790006C795F6B710CEB79FB04A5BA1FECB8891F +:1007A000BF3C85AE23CFC8009F8B2999E0131ECA9A +:1007B000A79CD7641223FE5573E1AFB9FB17B1753F +:1007C000E1415FBF328350619D76E200FA8C7C7C10 +:1007D0007132806B832686E0BB70FD627B1CE0D8A3 +:1007E000C5EADD59F70E8F157E2F5A6A64C018A628 +:1007F0001ECA622295C6FE848DEDD3411F6B49E966 +:10080000C9028C32CC59E241C5B881C4A732E85F35 +:10081000641BE4D1AAE694055C8B28671446DC5679 +:10082000C0360BC9B2E818B36BC56EBB9D2C9CCF0C +:100830006C6AEDFAEA1A29490B90DEDF777E1646DC +:10084000D21069A7E60555BC263A6AB6D332638949 +:10085000391A78BEDD642F90777D2FEC99BCEAC5FC +:10086000CB35B53EF9EB7C47732C6012B6B3E73657 +:10087000551E4B0E48D4082A3136E23728C55B4B4B +:10088000E943EA42976B62D0B4E75EDBFB01E0F537 +:1008900074233B1E63B674F62885CCDED351D7D0C3 +:1008A00026CECC60CDAF4486A919A16553E335A807 +:1008B000FADA3BE0D5551B5C547165E5DE5AF0E58C +:1008C000A63D1193C474616C60F00B28A54318CD4C +:1008D00032DBC31CEDAA5E93668F6F294036C2914E +:1008E000370D1C8414D550BD985F744975C6CD3F33 +:1008F00003A600C95703CC217B05CF126B75D7C562 +:10090000966E7374A3D518AD5350048BF907434EFC +:100910005EDEEF9533ACA5EA18F0EE0A2F57B995D5 +:100920003B2AFA6EBC530CD4E9D2E063FF0F49981E +:10093000676AF0DF988DBC28B6B2773F8C003EDB4B +:10094000664D323B89D547C01AF63E824388E01295 +:1009500089E72EDAADD4D6CFFB9162ABE9F5098DEC +:100960006EB371F4D4291165DFD48DBC6D55EEDA08 +:1009700061647894481BA7F7DAD09447CC9A5B79E6 +:10098000D5597B48F770C03C3119F3812418FFCE4C +:10099000A8E3F9DF5F7DFCD766BFED542DC6876401 +:1009A000C000F7276E11501D7C8ECA8FA9CE1D5D29 +:1009B0009974758BD3E2E2C65F4F5CE1D24D72044D +:1009C00081C16D3DF79F5DB0A06DEBD2C6878709F1 +:1009D000B8C000028B43767009ACC1CAE6D2883A2F +:1009E00068DD129F07792580EB30C3DB778BC0551C +:1009F00013329020B600170AB1E5064230980A6417 +:100A00000E1BA16ABC36012919F603A82BAF20BD25 +:100A10001D5F5D404FC638F9B10135788ECC8D0928 +:100A20004395BA0075D798FC8684BEF66625E4CB5C +:100A30004186DD189950FD23E831F61AB025FF3FB5 +:100A4000941322DB2D66BADB37086E0E7991783E5F +:100A5000949216D98FBF76A5973CBEA70131FF7639 +:100A60006E7E52DCC650D81CEB564B0EBE9F8620C5 +:100A70009EF355009005BA7D8AC4E9AB242E20D29E +:100A8000E2DCFE8A8FEE7DA9E91F568E189A468415 +:100A90009F57DD639B356C724109E7CB6CB0D7F58E +:100AA000EBF962A6B9BDFE9E5315F738892C61ADEE +:100AB0003BC240690AE2BEBD7160804080A30B4426 +:100AC0009499A67A6CA44E92AD0A34642DCCBD7074 +:100AD000337427A7DAD45A02737C98A8647DBFCFF9 +:100AE000D5BCDFF41A9692D93B43357FF825445D97 +:100AF00036E084A92E009D0DAFB41666F4E52BCF29 +:100B0000FFE0E038664E3DDE78EB3EA62591CDC88D +:100B100061CFBFE8EEA9B86659E56B125ABA313316 +:100B2000F39F46E8D40B96212CC6B015EB5A8F8D57 +:100B3000A893578CB1FD44DA24497B7BE1BBE904DF +:100B40006C2602EE2DF44EFA1390BEC676247AFE81 +:100B5000EA1AFBFFB681C05A59701BD09DB972B416 +:100B60003277F364489DCCA6818E641A72B85040E7 +:100B7000C029F2F19FBF1F648B7E4FE0D76AED5111 +:100B80004F5B4C5283A6B8654B64B3A0F2FEEB807A +:100B900051A7A9BEA21399605C702E4D81611A3FC6 +:100BA000681DF17C534DF8FDC4C9B9652DB45D5382 +:100BB000314E0A13BFB3B9799F16E8B3FDA3298F4D +:100BC0003733E8A8A2E135B2FE0F4E43E3D1184F08 +:100BD000197E10EC7411E990C9F6B4623D72E238E6 +:100BE0008207FF9F7F401D133D10AD9515C8657DA1 +:100BF0007F1BFE11EEDF87F1445EA2DB7E91472B67 +:100C0000ED91705F3B14C2B3881CD6F361F85CD7DA +:100C1000BCCEAD7D420E9F52B119370770A33A1179 +:100C20005BE3DB041F95FF74641CBC57CE3C1130A2 +:100C3000726B01A670D476A0D5AB65DB3A6A39AA8F +:100C4000331338439EC51EF72982B94F3AEB7C5DBA +:100C5000ABA7E27141C3570E087F89DCC9090EAF0B +:100C60006718625D5DDC8506759377AF6271F42667 +:100C700038869D6587EA60D49C780BAF6BDD660291 +:100C80005611FD2908729AFD9A699E4DED8D06C296 +:100C900047A6C2A03A6791A009EDEB03B69B660593 +:100CA00028CE1BAA4BEC6B659E7D1F532187763C9B +:100CB0001245B5E9142F32C3675ACACED82939CEA6 +:100CC00019C460C0F6687B5359F8C126CEC5D6D585 +:100CD000DED34139536A9FD0F178424474383925C4 +:100CE00074B10F8386A54F366A8545A524B89C0844 +:100CF00018BADE385637F5CA159FDD3B8CAB2FCAC4 +:100D0000BF40796820E8324AA0E57840AE9EDB8794 +:100D10002F91C295CD409C80C1E07D37E53F97F48F +:100D2000891D7371136471D0BADA8FAC90AF6BAB5D +:100D30001A29A1F1A44042A00034D8DCE49463A6AF +:100D40002468C017D03E978E7CB19CCB5977721225 +:100D50006FA73DDE6CDE67D956647C7540C84F2BAB +:100D6000A2F2F4E20F68F87D631D3A8AEC9C867368 +:100D70009C68F89CE21F16FB4B98EBB776F3F68461 +:100D800052D101AA8E28773BC658EE1C399CAE0F73 +:100D9000ECA7F9AE643CE25CB1D37C70689D852B16 +:100DA0006E5530DE1B202AA6BAC16B4B6C964F9E47 +:100DB000987F9905A4807DEF516B9EF8179492C996 +:100DC00000B3CEADA24B9455F4F9F9503E57E0F67E +:100DD0007AF8919288625770E81984EE77CBF39590 +:100DE0000E23E2FDC5E3723763D7CCA98B082F81B0 +:100DF000B46AF6AAC19A2158214986D42D48FCA884 +:100E00008D6105CF63C70BC588DD5BF9FC8CC273B0 +:100E1000B37175BFA89FFCC17B4863C8A65F18C7A4 +:100E20008489708CFCBE07D4BD144BF23D32E1FDC9 +:100E300002DE50D9FA36A1DCDB9E1224B6BAB73FE7 +:100E400098D76E8A0B1FF4C8B2D37752DE07315A97 +:100E50008EBDAA7D06BD03892A45BFE45F3982BDE8 +:100E60005E40F9BAC559C23C9B7E8F8B4F08DF2F7D +:100E7000E23705E4196E65427B57325FFDE58191EB +:100E80002D6575573C47337FC872A154DC8336A368 +:100E90005CBEAC01F4A95E01567C5CC622C08776BC +:100EA0001FEB981A9A370AAD69D0E802A2C1F39BEA +:100EB0002EEF48D24FF50F22ABC4D32DB9087C34A6 +:100EC000AD73A915904BB46F11A220937E5C5F4C5B +:100ED0006DED153B061A47982C77C212016D6C9286 +:100EE0000B85BD936828F6086EEA10B5770DA497B8 +:100EF000033C839CA40A4402359F87E1A9F0554C2A +:100F0000A7DE7453ECFC9812CED807259A156A78A0 +:100F1000ADE0399E2AF5584BBD0D2E71C5AC17AA10 +:100F200046A244D7E12D3CCE32BF8E1ECCC29612D3 +:100F30002E88DB3D0BF3131348EB684580E7D4D1D3 +:100F4000729F510EA70A96AF385347C61A9C76DA9D +:100F5000B9A2CE9DAB8D2C3DE0958CF5F4A2DFC2FD +:100F6000E71BD1F0C9B1F6EF366A5B6801D9991277 +:100F7000A97940F7D5492D47B49792032FE9ABFFE4 +:100F8000C8F319875CB22947F1B7E9AC2B2D97312B +:100F9000A53F366280C18A1A02AEFA5864C2F7DEF3 +:100FA000AC6D65345AC53979CC4FC45846C42AD083 +:100FB000CD5E224F15E788A7731C8C82A86C543D28 +:100FC0007C76298D9B6A3859FB11499F3308F55E61 +:100FD00095BFC6EDD0A2AF1EABE86E6AFE96B6EF27 +:100FE000A5A906B242CA457E3AAA3B0E72B0B177B5 +:100FF00029536683C0F103C1D77ACAC97BB1951C56 +:1010000098B67B7175619DB2CF295C5A7B03EB1951 +:101010006A2328095CC0A3559251021FB13884BAD3 +:10102000627AD846AA93F970E67EAF09316999FFD2 +:10103000455FF8D57AB27348D5D5CC60032DBD9EF7 +:1010400072637F01F86C447ECF901B33BCC90DEFF7 +:10105000FAF9C5E18801369236C255265EAE7B8923 +:1010600092832DCD443BFEE00CB178BCA607EE1E6A +:101070000B13C5821052B75EF183C3472EE7953B31 +:10108000A0952450B7E77CA2426A2B18F8BA16D96B +:1010900030796F878203155EB4D5E8AD0F7D5FCCE4 +:1010A00097F3DFADFE5EE6ACF487465FD4B04289CD +:1010B00091901DC3355BA0C8215A876D4F76E28998 +:1010C000A4A4780210419EF7D360047E975025CDEA +:1010D0002BA6953CD5F8444084E4F5F307034C93E4 +:1010E000E39F60DEABB45AB177F3F231BEAB81ABB4 +:1010F00065CAC5E48EB7B3C5F6D1E30D13D403DAE0 +:101100006E45CF5A03B1AEEE3877221AA5C1F1452C +:101110007FBED61897B63E110078257A533E257FBC +:10112000A78C86B89D04CA466462C92ACCBA5CB949 +:101130001D23226AE3D30D0778D11716FCF431275B +:101140009A9636E5ED79D3CB7BC5B9F41BE7DA0681 +:101150000F33A1A9468F5169479DF1BC0C7A59A163 +:101160000FE7BB84AE7F1DF48A852CF23578D83426 +:101170001A05B3FA4E3A27EB26C8399C5F48042A71 +:10118000BE6AD05635BD1CA381348AE2CD3F65B31B +:101190005FC1607B7E5FF5CBC4FA799933A7B2ACAF +:1011A000D0BC7E1731D0010C193E319D68E6D37753 +:1011B00027F707E4324D99CD5861711502F987BDC3 +:1011C00048CBAA079212A9F45488B041F4F9F23539 +:1011D0006566F66330379F2E5087E1F42D6184B742 +:1011E000C91E5E87DEE09E0B2B03E68AFD6A8C5DDE +:1011F00004228DBA208146479A8991FE4EDC42FD39 +:101200003D67D914CB47ED12056DFCFE7DC3711708 +:10121000BE221059703A8A1760054911DD55DA501F +:10122000056C0D013D9F11F60746E7C499A5062AF6 +:1012300084B7926F5C054E019A8589F0AE4389DDD3 +:1012400086CC44586BFA0D5BAEA3D514C84EAD07DF +:10125000CFF5B61C8AE55568507D587A608E1FBF61 +:10126000351131982748F48B8A179BA9423C6A6E46 +:101270006764E9631CC314526C5B02218C521DC865 +:101280005456A7AA6FD921E8BDC649FF9D350BD694 +:1012900074827AF6DB9F0172FE44FDA06B52F22548 +:1012A0002434AB8A3806E8C3F5ACD1457AD114CEE4 +:1012B000F7E9900FE3A51BC4C49054C4B1CE3251DA +:1012C000949C558CAE39597F64E85BD7EB14E0628F +:1012D000AFCC5A82A7E8014623BBC33D9C9259DBA1 +:1012E0005B35961DAA67106216BAE008500393C7D3 +:1012F000CDFE3CF914BAF26F14C0A84AB2BA8A5CA7 +:1013000001D1715DA7F7D0511A5241C73E81A7554F +:1013100092542C2B1707930FF83015CECC941CDA6F +:101320006B0026C79094C22975FD831C8B1C7FC956 +:1013300077B3653D9D7369F550A750AB55B4632DE8 +:1013400017DD22A9B0E0495EE7ED2D8E81E5E24090 +:101350008B06C4DF983FE1B036EC5968E4E0F84210 +:10136000C40291856DD35DEE20DBDC09C3E86049E2 +:101370001EB6837A99F17F8EF6BB0FD8C5D4C90FFC +:1013800041EA8F97C41BEDB6305A2473B50F0A4D4E +:101390007FF30B1CF6DDE43B0545CBBD8CB0AE0EF8 +:1013A0006BE7F4D2811E6DE23945147B6F9279CAE6 +:1013B000A558BE25EC15D233EBF92281C21D34129B +:1013C000CE287044DD590122F5F74E38FA2B3E1530 +:1013D00063867CA7147BD7D90CE1E41E79246EC602 +:1013E0007C14EFF36643CA251086C199CDD5B002AF +:1013F000214B64C84E877F21A3E0BF6B4DD5847617 +:10140000D43601EB110C6AB7C48A2BBF8633850131 +:101410001AC864721BC1F22BBFEB99F198115020CE +:10142000D26590B2F839667603C323936C7B9FE252 +:10143000FC7082F8D86EECEAC4838A319850F1C807 +:101440008BE3F46F1D6043CF8BEA04952B950C4022 +:101450003964D9A4EDA184D48935432906433D706C +:101460004C64C5D33E0D2EF2ABE9CD9E69F3CA574D +:1014700097103FA738E8A536F8D8AC8599DE8521C6 +:101480003E466510E62560C8973DC2FBF07E7BF6C0 +:10149000F75C7C1058A3A429976CB5318C0BE1FE46 +:1014A000D87CE5BA43194A83E570A4915AD909D981 +:1014B0009A8B364B2FD23B5490EABA8825F8731595 +:1014C0006685F874A9E99CB0AEA6E70D503AAF94D2 +:1014D0001BC8CA9400659FD4AED39E53F8ACC542D6 +:1014E000FC897E32D240C3C62EF2D6E8354C4D057B +:1014F00042A423C9B06F6CD16FF862E999B2774208 +:1015000015873CF675B2E8B0FFBA540ECFA1128130 +:1015100063AB76B97D6977F24ACF7E5857EFAAE67A +:10152000340D968DD84AA2E8FFAFB8137E2FFE186F +:101530004C90E882D2234125B57CDF0DD192610E1B +:101540001592DDD7C7ACE8E0D8AE1F34C12A3444C9 +:10155000473AA1F38E8984C79CB648F5C28223908E +:10156000CD6B4E6DB10884C885D63C0E7B1BF31144 +:1015700066976E1EADB043885E01FD7BD76409C0DF +:101580009BF0CAA7C4CFDBF3993259DF755646B337 +:10159000F8C80D7C01A22BA8444CFDF3844BD0A4C9 +:1015A000DD51A284B0D4154C37239B8511A44C99EE +:1015B000959E2AC0D2107ED4AD00D386CF4E22D2C3 +:1015C0007082F9ACDD420675C89983CD22F34B15C4 +:1015D000BC63FE84BFAC39F2FD7306A29ECF2E0E13 +:1015E00043606C50B817DA29AD74BED8F6A88C7376 +:1015F00005FC1F0FE56A68DBFE774668AB966FA1B6 +:101600002294DC107319FAF639BF00CA4F3E7853A2 +:10161000A9A720399024F41C7CB9A76427CED476DE +:1016200081393F998C3EC493A46A35C1106F05651A +:101630005B1F56594F1B5F3D7C3F28A6B231019A74 +:10164000F1F5B6914DFA60390611DEFD7417286286 +:101650006F2AB2E297E6D839049DB55D58A2113AD7 +:101660009FDB5C9D7757898C70792F52D4712F0541 +:1016700048E0F9EA0F9A5A3A36A897371EC13F62F6 +:101680006A30A8E012997510FD4BE50639BCDB7293 +:10169000B926861412B0292A3FD3DCD7ECFC132FCD +:1016A000C3BB06A0BE8B8B85E9FC09BA7165A58911 +:1016B000D5DD65A5279A7CAD378C8FDE3DCED98BE5 +:1016C000921C8E92A297EDB79F506FC00C50910C58 +:1016D00014FCF76101866C5522BB4EADABD8DE63BE +:1016E00018155A69903FDA67060B4026513A735E27 +:1016F000CF03BD5A5AFB3B3CBDE6317A1907F4D003 +:10170000E4496A0693FB6B5ADF4A35F0352C386A98 +:10171000FCF95D91C2B2F50CB91C5B3213834B8F9F +:101720008A075EB2B2880BC1A334F5FA63D339E9F4 +:10173000696ED74C903A70E478C3FF4DF26869E166 +:101740001BA9FB2B5D4B4D01D72C3D4D5F81C6AED8 +:10175000CDD4A417FA337DFA5555C171B03226E8BD +:1017600038DAE43C9606A91CB53AB51D5192E5B0AD +:10177000ABF4D5165F81929C22DCD2C5D1AD7A370D +:101780000C5AD392C418FB7914B60D68E756155855 +:101790001F516AD35A9A53B92A492F808DE780FA8C +:1017A0008A62C46FE312CC9300481536E83CD9DF57 +:1017B00069951DC6BC4378FE04EF1F9C243F87BD7E +:1017C00008A92113F653E8862A11BEB94E1F9B0FB4 +:1017D00023CC653DF7DC8D81C08F72A78B631651DA +:1017E000EB0B046BE620C04C829621C0A0BF0929F8 +:1017F0009C7A81ED1328ACD88E6C38D532409DCCC4 +:101800002217D37CF7BD5F3201DD302515D39AD383 +:101810007BC12242293417CB66FE44A9816EF6DCD7 +:10182000FAAC18AD703212E832ADD2BEE4C52F0862 +:10183000834DAB7CEBB850031D87642717390277C3 +:1018400061136481414E0896992BB64F50A83F1101 +:10185000C44B8E07EBA52B52248607781AC6555920 +:10186000FD40C88E8021795F0C27217DEB15E0615A +:10187000ACF5BF59E1EA138288CBB728EA59EE8C60 +:1018800018B5F467D5ABE9347666E794AE6335876F +:101890009DE91C0F5030FEFA9B4F5A9DD0978F1137 +:1018A000DA50913972234DB3FA8A33DB34602867FA +:1018B0008AFBD2FB354FCFABBAD6C75B7B4A1ADA6D +:1018C000B372482A4249E1333CBF204FBD60D5A1E5 +:1018D000F70BECD858070FEA45F2A29B9228B324E5 +:1018E00025BEB332470897BB9AB7491A6552E11F24 +:1018F00060B36D343D499F0FCC8CC6B3B2C3376C17 +:101900001B628B2ABC2744AC087C54B994C443E8BE +:1019100043F124FC6BCE3CC4C1159314D6327483BE +:101920006967CC4C71DA2C99773B8AE12B9EE77C76 +:101930002383C22F4F9A35FE283CCC9CF63F91B5AD +:101940009109CA273B35FD66D78864BB62CD0E3E40 +:101950004A1AB9070B69933AA8872741F1CB312F6F +:10196000B754ED48912C1F08D5DC6B0D1808EA47D9 +:10197000900E1CAB3E5073F01E5833D626A5B957B7 +:10198000E999F2E3EC6D1B740FF587E70B9856C8E5 +:10199000B0BA3AE28674089C93E87E528841326677 +:1019A0005A2D0425E7B4F22374730AB106C500D991 +:1019B000D109875CD4CCBC846777CA0EA186A6FE09 +:1019C000AACCCA35944B7EA758F41031A588B689A5 +:1019D0000ACE641BE614BCF7638F695CB7118D00F7 +:1019E000FC45B63D0D9D2BC8C64F649E5CBBB2F650 +:1019F000BD337AAC279CEE28EE88DDF3704946298A +:101A00005BC2E33018DA27E2776DB260A55B503233 +:101A10002BF524165F46DB6B8F4DD1CE4AC4D148DF +:101A2000B35009A368910BCBFA68EF064F64B0403E +:101A3000383CB31913AC153704FD56045EA7B07DCE +:101A4000AB46215BE36CC24037CFDC61DBE630891B +:101A50003311491B58007C1E36306C96CE6583CA04 +:101A6000D25EA94EEEC900413AFD1BCAFB1EE8FE3C +:101A7000CFA537A4860B9D160DF706F441BA7E3824 +:101A800074B7DCC001904B0DE64F89D41CC72DC242 +:101A9000EE231939C28F4BABB5390BABF167E1D8E7 +:101AA00020CA1E221C8A4A51A89811F3FD24DC8604 +:101AB0006B5F397A6C9C995EFD2279B2D9F99DAF42 +:101AC000DC34AE3639B3245C71278DBCD037540674 +:101AD0009D73D17F7E01FB2F9B929414F2B7C38E2E +:101AE0004EE61617C7F992DFCFEE9471BD59120278 +:101AF000584FFE70CB804C1B7A3998F9B7477090DD +:101B00008EC43B1E28E7EFD360E48D99292FA7648C +:101B10004DD5FF8FA9C99A9DD5C937C375B5B6A351 +:101B2000245585951D2C222E6E66043A173D6B8236 +:101B30009E0597A7EAC0E868DB076FD566049A8020 +:101B40000FBF68632B88723C3884092D3D3B7BF3C3 +:101B5000A3668BEBEC0425D801E4F39460F37A7967 +:101B6000B33B6BAD83DFA0F4C76711675F40D5B4AB +:101B70005440555DC5DB2D1FB3CE55EB801E71FD66 +:101B8000766B3B68BF8FFBBC316E59C83D320D117F +:101B9000D9E57474149DE26BEAE000501EBEB5EB0B +:101BA000BCA9EE0F0E0B3EACACC58D3ABC638940B0 +:101BB000495D71340FADC9DEFEC37E8B805455BCC8 +:101BC000BB9630F728346DA0F6036576367A46CD9D +:101BD000178E857A113DCC1345CD7D7383B24A466D +:101BE00033B18FB041A4D13FD3FCDD8B4310B80C8F +:101BF0007216BA522645D03C9BE952F0F97DFF3B64 +:101C000087926C5D6519AA11DCF858B70727055053 +:101C10000677F08314586CB4CCB4E97AC1AEF5F50C +:101C200096D699764AB2C0060CE406B2B77A00ABF3 +:101C3000B499FFDD5225B0709A3BF3DD21C0D9B9CC +:101C4000D45C6F7D97177A12425FF283FF1DDEE24C +:101C5000B79ABFFA3DD91411CA0F80A5A98A781680 +:101C60002024EFAD43278DB2959DADF502E64C0BD8 +:101C700010BF9F5B23C0AC6E14329F3DA9B3F654D6 +:101C800062CB790220F4A98588175A8A8B10CF7A03 +:101C9000ECF9FCC221F095F53AB165F104DD194685 +:101CA00032F4521E0BEFD6C6F404B9AD2A5B4327BB +:101CB0000818DE23EE8A210B4C987CF662A4318A48 +:101CC000823B45DDD832DCE0FE850F33633927E106 +:101CD0007E077BE8C3DB28E8723738F330CB3EB6AB +:101CE000EE06BDFEA3E4EAD8F02553D7E311EA6C73 +:101CF0001357D69C2C3FD31BF6BFF0642C192967D1 +:101D0000065B4F03BE8C291131CDCB601F5F80373E +:101D1000EB0AA179CEDE0DFD2A106CD847D58C5F79 +:101D2000F430B791CE9B2F4C8044664CB357E5847A +:101D3000CB61C34936D3DAB2FB5CD5D1A4A28C23E4 +:101D4000BB68A6CC71946B156447252959C682B728 +:101D50008910B2BC6083DFB35B51D2896D325547C5 +:101D6000C9C620DB1DFF69F62A7AB14931F65E2C1F +:101D7000403826A5AD229E0EF70D0880941CA91FA1 +:101D8000177AA6CE18BCC7AEE02B1D72DFB55896E9 +:101D9000A0BAEDC5909CA91C0D902E3951866149C1 +:101DA00096743DD237133A65392C719AC1F4049474 +:101DB0000A752752605D893FFDC6BD59A7F1199884 +:101DC00023C756D0050B287BE087EC7F94A0C2F791 +:101DD000E87EA5642A4533A2708B312C2F87C1C2BF +:101DE000DCB01DF5D6B219A56889C5694317A9DE0F +:101DF000F835DDEE033E0F62B7BFAD1A721BE291FC +:101E0000229E60F0F7BB04B4E8738C0D79EADB2EF8 +:101E10005D484B1CB5C28A00D033792D42841341F2 +:101E20001607F0FE268A4F4335C588E7ACD650F535 +:101E3000756367150B39484C951AA3B29F7462D627 +:101E4000B3C4CB9A92597E50E572B0089D37C0A3B7 +:101E50005D23D05ECF0828DB66B9E9BC3159D9EDE6 +:101E6000EF689416FFFFE89A1596546B7A9B31053C +:101E70002E9F52924B0B1B9C5A2D09059E7539348F +:101E8000BA02F6A3B4ED9273BAE6D83A335DF5B16F +:101E9000C203383D3C5E6C9B8D660BA34BE0C81EB5 +:101EA000BA3385AA32B236EF74C95CEF13E6D04D6F +:101EB000102B598BB9AD8AF4C06A29D2744DBCFB82 +:101EC000E1AAC7835F098954F5A3DCB6E64233B8BB +:101ED000EE2897F751AA6CACE32F521F9F6584FA46 +:101EE000275B60F8296681C73DAC513FC92AB8E637 +:101EF000232B8922B46C6C3BE39D0406230533A994 +:101F0000A7E75685AAA5D934C84239550CE52AA9B0 +:101F10008ADCE9F6461A8624998324D3D13380E3F8 +:101F2000C37C0E3937F5A84035FED99F9088324FD3 +:101F3000EE50A3AE28D2E816E81B8A6DF94881025C +:101F40004ACED7DB12231F726B59728F03B20A0D70 +:101F5000C5940C1479D7289336556CE63AAB1E8895 +:101F60006EFBEB453061FE6B2BA249D5BEF01FFC2A +:101F7000DD1C12DE519B1A8823262DC26EAC00DEBA +:101F8000629CFA48B166B82684CDB7488FD9568C82 +:101F9000D7BE6A5461C3FE4808C15AB89BC554D91C +:101FA000C587A61151348EA4D400B742ED5D7EB52D +:101FB0008BD8EE049639C8BD3465F8FCC1630C7E3D +:101FC000D9E6EE220BB078FF831A1DE77CAA987041 +:101FD0008373903C318724CB7A7D44B0BA1EF6D609 +:101FE0000C17DB7465D42AC352B2435B18829E8BF4 +:101FF0003BCFB65AD7DF65AE80F0C61817F716E3A9 +:10200000B71FBF5415B5F78395B54274C52AC69D51 +:1020100003EF0A262351FED66A4652772F87024ADB +:102020009EED7F40FFAC44F1EABB5A3076A000A899 +:102030007D3B44E4075D6EB1F060E47164CF7EA245 +:10204000A904E8095F091E6437AB696FB9B078EB82 +:102050003CA1E150058224F87166A5743CD1929EA2 +:102060008F03A9594A37CEBDA35BB7361ACF246F69 +:10207000ABEAA4525608F916CAB84C6B39D84E07C9 +:10208000513CF459D6B2FA664B7B3357F0A716BBD6 +:102090005C4A19B46927C9C1ACF93B0FB3298AA2BC +:1020A0009BF3C8869F88E4CBFFBE37906C12025723 +:1020B00010222C5668DBB80BEA2F6A428457FE3692 +:1020C0004870DDEE81DD7E8185A07416E9DFCE16D5 +:1020D00095B6009D722547375512DE9350BBF8E642 +:1020E0005698CB4E8840299B49CC2569B067607EC5 +:1020F000C0B2DED9B4CF1A1285147E48B3F23519B6 +:10210000E752542579FD3F933DD9BB167E2C172EFF +:10211000000C7A7D0CFE72A58FA98FCBA35AB2DA80 +:102120006844DB0A6A2BB35592A69A830B89CAE3EB +:102130006E7ED55C52AF0F203356D8D2323CDCF8DD +:10214000C2B69A15062C654474EA965E3E9EC45E3D +:1021500024602FB8950AD6EB67D91D5331E4D535E5 +:10216000632FB60E5D425D0599EC532DC72AD5F25B +:10217000AB2AEBD4C9DE7389A03F701880DAFF86E2 +:102180001EE9833AF6D0D51B596187E376B288B948 +:1021900070478B30E9CA1FCCD9B676A30701FF4040 +:1021A00044D3E23174DE670B9586362E6EA7040D9C +:1021B0006B8304448580CBDF5CC1C464C785A848B9 +:1021C0000A4C083E6F5D5DE370C12BBB0383742D29 +:1021D000E185B877904815ED02E8E5716FDC7C4346 +:1021E000766A8362208596DD1F3D000AB49484CD13 +:1021F000524C8481E5BA57B6274951E4A0A2BB18D6 +:10220000887123DFA865307A0134FE9589D282F483 +:10221000C6897A0A60D765A0F1C385C0B56B148CF6 +:10222000354446837DA8465CA08A7AEA42469CB043 +:10223000BB6247730129453E63AEC49F3D51B0B9AF +:10224000AFE37BE471CAC16C978B80DC2157201C03 +:10225000912B9FF03D833799405CFAE6150C2DA435 +:102260003F15BF355EB263CA4FA996FFD3FD1DEA85 +:10227000EC1F8B51DCA6B65D849A27BC67A6D1FB08 +:10228000EEC46838CFFA6338C9028CC1B1360C1875 +:102290008B92EEABC5C6A776510E2A46D634BFEA5E +:1022A000D74FFE6CA3C78A25C57184008EDFD76D1A +:1022B00005107A719960C02FCAE842A89EF43B3697 +:1022C000C39CBFE691E88E8B8BEE5C70DEADD8A030 +:1022D0001FEE23FE0132E4A482837DE68E77B76F82 +:1022E00094E6FD44803E8C99E0AFFA09797B5AAAC6 +:1022F000C52EA1C50A5AABBB67E85A9A2C4E0104F9 +:10230000FC5084E08B39CD871787A8EA6666352FA5 +:102310004F149AB904B54E1B1146AC01C60B6ABDE9 +:10232000D79C2A5F2B316503AE4E5A202A8AA6FD20 +:10233000EF0F44CDEC40F1B5EEB565EF6A0564F8FA +:1023400007CA78D62962702BAE58811F9EE914BD4A +:102350002B964C1B4907E8A2DAFF98FA57415562C1 +:102360009E5670A60F79747AA5EA3DEF479CA1A608 +:10237000394814965F8062BEB7670AAE4B25BC44ED +:102380002B7725D53D0C1913CF6284A954D23AEB93 +:102390001F483BAB5986EBFC11A989CFB6B954A9AC +:1023A000464E60F53654D00BCAADCCE782EF35D837 +:1023B000BF7F6FDFD6BC47286332A8F9B71D24D092 +:1023C000B1359DF8699D145519782726E07C1F7D4D +:1023D000573CF92C6771781E7837A2269CA296B8D4 +:1023E000227FE294EA235144FB8C058D4C425F1816 +:1023F0003BF1E806BC007D863BF6E127802B3EC51D +:10240000286050DAF2CC429EFA4DE6BBF2813CBB2A +:10241000B8551085F56A7B96DEB4B3775CBC444A48 +:102420007E22FF9CF8F79C7F6A4612C505F6D136DE +:102430001EFBC5701E3416B000D3BDD00229283B48 +:10244000938F2AACB08E3E587FC7D71CDB3EFC4E24 +:10245000C55E6AC95A2951AB827281B9BC32D59224 +:10246000ABFF226613EF234C939FA7A1A3B4233D98 +:10247000A9A7C054886BFDEE7E3901670118101FB3 +:10248000CC0021B5CE5B443BE2E531851533189B8A +:10249000ADBEAD680C952D7214B091185AEDBD8C7F +:1024A0007500653F59ACCF282895B840223B161BD4 +:1024B0002BE9E990E5AE8EBE93E07E230C9B7AFB80 +:1024C000D84A0893824E2382DFDF579C0473D439A5 +:1024D000EFBA9EB4A5FECBC06CB4BEB606D5A3744D +:1024E000C455760B586D9A0FDA05E34EB4A8028EE8 +:1024F0002867F3E480960C9DB944EFC56CC1D3FB0B +:10250000B1D02796988CF4FF9AAD3444347BA0C2A6 +:1025100090058C846D30C2DD00F9FA53BDF1D79D72 +:10252000A27C26C90C62B62DB7C77D1142D71B7A93 +:10253000DE25FA775D319C42E0BDFC684A65409437 +:102540008B995B6E24AFD0764FD04875FAB4907AF1 +:1025500056E0E624D19E90F9A976D65452C1F323D1 +:10256000E89DB9EFCADBDB3B8B93E8274E2935DDCD +:102570000ADBDA853B062E204CD8D3DD4E311F31E5 +:102580002D3D5FC29AFB4D439EE90F9F9A668822BC +:1025900069AAD475BD152E5AFF6AF1CF421B342E9D +:1025A00041834726D6514AEF17D875EFBA4A4F45AF +:1025B00051961227BB371B1C2A26A2021D34076323 +:1025C000BD4D03BD9361E4CC3F3F987DD53DDDBA61 +:1025D0002A7AD4762AA8A0067C4DA88DA77BCEEABD +:1025E0003826E6C50A545B45FE39D7AED35B2F16B5 +:1025F0009368060EA2E4F41D0E90CD5FA382B4276B +:102600005FC4620E0414B9D17C06D79A2E5495D2B9 +:10261000597543BAB2E63031B3FA737815B593CA37 +:102620006EBBF454FE57C5778A76D199B97789E0A5 +:102630001F6B734FD54BDCBC1D3E9668E676EA6691 +:10264000E27BFBA8D2FA08611247DE99E8D363D097 +:10265000DD18417B904BF89CF2DC52E4B28616B94F +:10266000A2424379D990FCC96BEA31B77F84960BBB +:10267000235C6F9B2874EE4F54B209A2A052D22C57 +:102680005A3CF9675879577A3C755BBA70E8A113E0 +:10269000EBFD58EA01A3BBFC14DC05DC91BCC8616E +:1026A0005C5C45A5B071BF8120739A7687F3DC39F5 +:1026B000F7E7EA5CC4C548D184DA2420555158D4E0 +:1026C00025FEA6AC8A38D218E20083ECC96ACF6B2B +:1026D00055FC8F8B59D246C52526760C8DD0F0AA95 +:1026E000469792FD2158EFBE2D58555C08BB678177 +:1026F0006F21C683FD916BFBF88F345EEFA99B6A57 +:1027000099C6EE5B2F28C2CCF558DFCE605F91985A +:1027100099393687E48A406F02E79BB410ACE8DA57 +:10272000CA027CC73EAA7C3C23835D4F7FBFCE2A72 +:102730003EC32D03B0AF849BCB3D7A6F10D904C14B +:102740004B02FD4F9B3C6524194A150C8715EDF88B +:10275000EFE991FA11F6E19BBF2D4C5750F0352D62 +:10276000708C966EA67D8F083C3890EF5C10A52F7C +:10277000C19F0114AD51FDAE7046A15B00B8FDE6EE +:1027800074CA24ECC50C8A59599C92CAF67DC47C43 +:1027900038CF65C383698239D7FD0A1D2852D7DF38 +:1027A000304E66B6778BCCA38F51ECA07A85F33B85 +:1027B0009B3842658C72D8DA9CB7B74D34285D8758 +:1027C000E89AB51A3137050D447EB425511CC11B5A +:1027D00039661F4F97336A6DB4775AFD943AE279A0 +:1027E000D1387D739A9C78F02EC14DEF1CC6057BC5 +:1027F0008EBA51C2E597F5E95976F66EE14150CCB3 +:10280000B06EF9542EB7A049E5BD0B8CB7863D6379 +:102810004F4A611C8C238FF7CECE30AFEEA95626DF +:10282000BECC7D54A7963F83C4A4EE6AF59C2D9B35 +:10283000F87F68D9A787420C9B2B8A262290844573 +:10284000B6235989FBD42B465CC358FCDD4BF6E11B +:102850009864238EA3343464EDC2B9BD84E690EE4F +:10286000B4D70423808868845C8485C27D7969E557 +:102870005A9AD51C3CE440BABED76E87D2A4E34F27 +:102880004A9A1183EA92A7527B4D2FD33A22B7235B +:10289000D12FB21A0E8E798FFCF40C242519C71F84 +:1028A000B39E7B9C0D3ED14733E0429AF46072C6E2 +:1028B000E89FB53DD6A80C443030DB81B729E2094A +:1028C0002BE39FF14BBB9ED4799A7120605319760C +:1028D000B1828C30BE4C8D34B7A60B94B72B617F80 +:1028E0007F259B12926D6B9CCE2D15A7560C9405DF +:1028F0001EB03CDBFB511E9A7C4D917B63B8A7EC6C +:1029000051D5D52392B27DF0642ADADD4F6E2CA228 +:10291000DAA7A58D9C9EF51E5665ACB0C2CA1C00F8 +:10292000CDE58276765A8EA3ACEA333E6448B7147E +:1029300089AA119A2800D75EDCA1BAAFF79C01AA38 +:102940006E0D7D728CC79F79C65F1B082FE129B37E +:10295000D7E071CD73DC591C6DDBFB700C479A4AD4 +:1029600036FC833A1FD2E1F8D364F62E281C8A5A2B +:10297000DC73700E2A7092ACFD9E1EDD570EEC5F6C +:102980006D6F5113A5BFECC32F1646465938869C70 +:10299000DDD9E463946911D6EB4DBCFD1FD29204DE +:1029A000C636E9EF2EC7C4EC097728948B974DDF24 +:1029B0008D6219366476A250C0C11BCA0E529E1C8D +:1029C000650D6B69272B3C6B6506BFB5D047702C36 +:1029D000D8AFED8FBCB4B7C6E895EB8DDFBF63E22F +:1029E000C49041D0396C252C4143B48677FC32A386 +:1029F000CCF687F2C71BD49083229B98E382D33016 +:102A00004DC3CBD29AC2030B6DDF2367BB787C68C2 +:102A100031335656735AB8CADA443AA9C86A09E338 +:102A2000D96D64B194950A88FDEDEAE805D0A8A1B6 +:102A300059093B585D6A06201EE6947D3B25E98CCA +:102A4000022B773D461C4E11BFF3C5AA5BBA79CC69 +:102A5000417BAE61B18B25C0A896B09FB4F7635F90 +:102A600014CCAC5B660EC9F3360DDD8952654004AB +:102A7000E50E85B9B3F56C491E40552D3A52F5FB6C +:102A800007DE83FF7600E8642BA25FF157D9A733F6 +:102A90000D0D7228D504E1EDB4892FB0BFACB64B53 +:102AA00017C2ED5024E2318E127A057DC0B41F8426 +:102AB0006BAE3DB1096C6294AAF612D9F981AF08E8 +:102AC00023FC7F7961A54A6A85851417379874AA13 +:102AD0006AC77B30BDB962A500994EF7885B1A685A +:102AE00091BACED22BF21EDC09894C68616D4A2462 +:102AF00075C60D687041CBC6A5A66D1DE33E80FB73 +:102B0000909D0340F61094F1A95B30CD35C357205A +:102B100040C006EBFB4E21383BD43A861C9390FC18 +:102B200044059DC12035ACC2415ED5C258156098A0 +:102B3000031D8DD71C72177D1D5409FDB67F641FC0 +:102B4000ED761AA3138726B3C3FB148103E1B69174 +:102B5000C9A5D50E83D8DC8B5E84931A359537C60C +:102B6000238A7053FB483AE07131522DCFF711663A +:102B70007BBD1742E8DC05B48E93159358187CEDA5 +:102B8000D6CCD7DA6AE3218993645EDA9552A41B26 +:102B9000FCA03B407993AB17764D70F941CF41488B +:102BA000005B49E65B29CF78E9B52820051D402E5A +:102BB000604919D923BBCCFF653BBC9E0584F9C392 +:102BC000A80FF7B302CFA5C8C78DB52647310FAB05 +:102BD00013429A9934DDF94F66AC7D7AF05B9DEC37 +:102BE0001D55A225E22CE128980B0A0DA2E287BE12 +:102BF000D2F6F4536488F6178CF354618CB593497C +:102C0000DC192770D726154ABB2F577E11510EF6B7 +:102C100076ACC7D894062BB1C25D57AF96DAF2E115 +:102C2000756375142ECCDAA30043CC7A00CD44E74B +:102C3000521A3B5F508B51E42C389C891AA5D6D68A +:102C4000166333D470287CF3177D49072DFCD43EDE +:102C5000234100CFEB074A0708C0BEF14AF567F8E9 +:102C6000178FBE250D3CD049556799729B9A362A1D +:102C70006F78AFBC7F0A06BA564AD5DB49BBCB7327 +:102C8000A79FE6C142BDCB37188958D9EBFDB0C725 +:102C90000558490839D83EF54C2A74F765DC7F6E33 +:102CA000518B0866CBEF96C641DB22A6748042B6F4 +:102CB00070C5D55739F79C445C22C2A1287937C723 +:102CC00044C10B4FED8B39644134132E5AFF6BD73F +:102CD000993AECC8ADF73F9827318E9E4BF877DBD9 +:102CE00098BF835E3930303B2266C36ED2227C0DA2 +:102CF000B97C6CD027BAA2593474C8327BAEB660A6 +:102D00009FDE87869C485E86F61C94FB1D940F35DB +:102D1000DD1DF256B76DDF190A2DED1E3A015FB6C3 +:102D20002C2DC0A44CBC4512D02399E3A5415AC513 +:102D300046CA18D3CE55B3D8EA585754B99EF7208F +:102D400061589E347875B602E975201E675F7F0270 +:102D5000A7163FA6D0FCDB1ACAA314C65B7E4AFFA7 +:102D60004CBD0B6911F3D9466E61349B48394284DE +:102D70003C9B5E6869A45D22F88115DFB296EAE0AB +:102D800032793A2D55C900812ACAB74C95401A208C +:102D900051F2A0B074F3D4A8E62160940B6121DC59 +:102DA000AD0B219008BA380617F560FF5E39E813BD +:102DB0008D7B04EC7453EA94B5E5F1D23EC4204017 +:102DC00005D4B01A61D9EFF2FCD53B912DD67FB96D +:102DD000ED06EEE4D5B342287BEE2C9C720E7C0A05 +:102DE000BBC759D2BE94EE56F627E83D4BCB2E0515 +:102DF000118FAE8DAFFF7654E63F1CCD8C25CE28CB +:102E000077E1BD82CAE381C8B6766F950DCB0DE33D +:102E1000E855DC1C8FAF2D0033B30020E39130EB7D +:102E2000CD71DED1AC2DBBFEE7BDD3129A825FF02F +:102E30008E8CC39D8F5B27DBA6A90B5CA6CAE429F9 +:102E40006DE21BE0EA15F26D32FD1DD658CEC1C60B +:102E50006947BC60B234A0562D00E4B75BCDB0B773 +:102E60007160098056E854315C46B04FEB5C7B8062 +:102E7000E8645B80BD5804A5A0213102FBB70DBBFF +:102E80005346A60F1F94DAC56D788F85DAA842994C +:102E900033E925AFB35E73EC9E5BC2B386715974A0 +:102EA000A6E4F34B74CCD1F3D409A2584AFDBEA3D7 +:102EB00008E12020173D0E419706EA4F1787A5C568 +:102EC0007A84B8ACD66CED4E52E96322173D7A276E +:102ED0003F208910CAFA9CFACBDAFCE225F85B465F +:102EE000FE789D8681821E8F61D23FD4B4E821B6E0 +:102EF0009C9B12DDC34022CDE4DB951F81001B6447 +:102F000031395328C82F0BDEE65075E9926015B3AE +:102F1000B2B2ABB0C2D7D1DC6FFE7E8D7FEC2F4357 +:102F2000FD773BD8A2347FC051819D6263AEDB9BAD +:102F30002DF935287FB6D0D49C5139C4B77A42CB0D +:102F40004B3E573D775078B3EC8EBBB7DF8128E31B +:102F5000F6208F178CFEB62F136EBCB89D94B12D42 +:102F6000DAC79A8E255E2AFCF846AD012C79494BCA +:102F7000785FF28472ED5FD607CA5EF2897A45D433 +:102F800059E2E502D6D37F1CFB37801F29E43EFDC2 +:102F90000D70D39A40243E7E46678B280078A67D2C +:102FA000D7B4A9214C810C3B3F1A81C7CD68EB46B1 +:102FB00020F542797A1459516037F96ACBAAA76291 +:102FC0005F8596325B89363A9E82DDA7CCB3EAFDF7 +:102FD0002962FC8E42538D2053227BE4EDBBD2EC60 +:102FE00077B20A00E72A056EFF46BD09B6ABBC05FD +:102FF0004DB674A78FC6B3E72928A614BBDA4804D8 +:10300000C6ACC3D6318492F44F6C920F6FB2346267 +:1030100089F8C632F96DB4D75D0651453EDA70972E +:10302000FBF7B0EA1DA5E85C22B06729856A5A4320 +:10303000D68D8448D106411774FBB43DDF9D90794D +:10304000A4729122610502978032B1B07AF24C41AC +:10305000653A2E7E8C613DF1AB73064746A0506DFC +:103060008D14654F47D5C3694B5BB930FE8D770032 +:1030700096234DA3576E0D6EEA0D026650A8F428F4 +:10308000DA6F36BCFF16E3152BB79B4501E5AA8323 +:10309000121131140ECDA650A1B591F81FC9B67109 +:1030A000A0441F5D1369786CCE672C1277AE0F3188 +:1030B000B4D231F10B08E1E1F635756FCE4E94973D +:1030C0006346BC1E59AF8F757D8FD75EF495E904BA +:1030D000C52AA9DCE9B6E158FC05A8A1F0B5AED730 +:1030E000AB005A6DCE13298CEF1D82DDD23AAAD6E1 +:1030F00046AE5668ED79EB69DB031C128AA9A84A33 +:10310000CBFBA7D3BF71904B5E10C956C1040B75A2 +:103110009A8683344EC1570777795470E06AE8C3C2 +:1031200035DE86A84A99FDFA83272901011941A4B1 +:10313000BE1181380BC96BEA7295A6DA6CF6F259AA +:10314000EA214121E14A19061140398A23D34F343B +:10315000FDFA890799AABD357D7D5A8C6CABEC2EA2 +:1031600045EF6E18FAA03CBB8205F710BD71EED595 +:1031700098EF29CD896A32A395DCCBA19F5C1324FB +:10318000C17CB6815D1737D9305C5B3A6F29917C81 +:10319000726A50E437E24F2089B0B64ABD62B8A4E3 +:1031A000EA97E91998744CCD730D49795A8711DB68 +:1031B000F7357C8469B1FDE419EE9CE61FEA62D420 +:1031C000D832428EF38DC2281E175F86E0E2460297 +:1031D0002808BE802A479912C1FEADE7B13570B507 +:1031E00081A6A4210DDAFBC1F3B125D62E39408684 +:1031F0006A62627D74659B9896CEF06C966F57FC00 +:103200005AFE50BE3606B8DBC8C005DE8E65B5A9CD +:103210008182961CACBDDA2832BF60DA5F819C30B7 +:10322000FD424B5655240028A13317D08B3499B555 +:1032300027BD468A42AF122232078187BE4F40E93E +:10324000E4B65AD6FC0769F3358AB540916CDE893D +:1032500086818D771608E75C4EAB9731C62112E662 +:103260003A649FC043FB5C780F8ABF2783BF61B07D +:103270004CD7CADF65EACFA3707407CA715B9DB7EC +:10328000369410369D745FC292BCED02F72DC2DAFF +:103290001209CC0A4DA48C832929C06A5552E848EA +:1032A000188DBA4D99CEB37CB97FE2C80439ADEE22 +:1032B000DC4546F9B1F80291894A8669EF5167A663 +:1032C000774F22A0148DFD7C929921064BE0137F4D +:1032D000445863858767C59531AF358A73D2378186 +:1032E000B5F90228906B2349822EFC6CD9714F10DE +:1032F0002C758FD76AC70F5CB7633C2F96DDC375FB +:10330000428C9A101F1FC98104EC899250231BB76D +:103310001D2C519263CFB830D717C9F1B7FE19F7FA +:103320003E61539FB1DE46A96E52B9B51F5E865B02 +:103330002527F37EC2E7C73D3F8B5306D2ADA313CB +:103340005C92619B34106DB8D88A19493CC7C2BBE6 +:10335000CF72981121057DA9E943C0E44E82C033A4 +:10336000C9FE2626E7A8F89B711AD1BF63C96D92E2 +:10337000832685903BA08C750B37EAE745D9B98E3B +:10338000471B70E26EE4B622103F04B79117E08C41 +:10339000BACED28DCF9D1528765E0C78F6EDF4D995 +:1033A00043C7595E32C8C6DB6DDAC18132502F6F18 +:1033B000C366D148F8FEDBDCDC8DD2BD8FE7C86F79 +:1033C00097F8BF23749AEC08F8540570AF8C106F0F +:1033D000834FFF8020A44AA645C29F0A381A758DE4 +:1033E000CEAB14D72F2C8D91D9A19678928A09D67D +:1033F000C02A9F791BA852EF5AC424E63B575F5757 +:10340000C08934AECB452F388C7218D47AC1A01540 +:10341000A4D5D09D4A9DFD78701CA7DF74A1F84704 +:1034200019682D86B6E5964FEC53CB23A77A001F7B +:103430001BA99091B4357E2263B5A4DD79C94FDC18 +:10344000072BEBC97244E46C96A6409B1A7D65AFCE +:10345000DF67E3FDC0A1676E63C42AE9C7B75DB249 +:10346000A5C05C3CA8522A7A1A0388B99DBBC24405 +:10347000C43A6B14D84F16BE037C3836904F8CB1CB +:1034800063BEBA83E0F4D247AAEC31F5A52AC44B57 +:103490005287A9106D1FC1847266D55EBD67AFC625 +:1034A000D3548D79F10DB29950CF806DD65FF43C35 +:1034B000AE92132DD70929D80F99D82EC6B50BD2A5 +:1034C0008F49F048B39356808C73A89C2FD5F54E46 +:1034D0002B7B8D984F3F9711BEC17816D531558AF9 +:1034E00013E3C0454909241ED4C43983A51BF92818 +:1034F0005BF66F759CA74019B22D603ECEBB944A17 +:10350000EF9C2D512F94B1C971B0C05100905289D8 +:1035100060F04084031AF0266D3B3C184B25DDE338 +:10352000FFCA926B01A75888E4FBC94A0FDA4464CA +:103530007600F4B193D4062F53391B760BF8863CF2 +:1035400025231FFB12BCC3190BFBAE8998E832FA86 +:10355000BFB6811E49866C990784F9408653DE66A2 +:10356000C0966F8133B627C36E44B33B6B726A81DA +:10357000CFB9BBEC37D4C57FEC907E1134ECD55B72 +:10358000024F6BD4EE8376627DE67D6DAEE32AFF5B +:1035900021218F1A0FDCD2AD5D66B19B746CC6C958 +:1035A000A53BA577E2C82B4E7D413B4CE2492287E3 +:1035B000AA3D6C72E64224748720AC258264DF92B7 +:1035C000AEEDD12A30AF3BF4D02297159D359094C3 +:1035D000DAE45E55BA2BFF89169A88863C61E6D5F7 +:1035E000A76901BFBBDD6B7CE131187345917C0B92 +:1035F00044CB38B444173A744F1C5C1A5046340517 +:10360000FB3F3264AFDAE61A55B9CD550F240128D5 +:10361000C9A273C5685AFCED4C8F779DAEB822B035 +:1036200031F6246E059EEBDD67A2FFFDC67875417D +:103630000B61E73FF2344869F7D2F77973F8A1B428 +:10364000C57995C2A6983B86BA1F98FBAD4A77B557 +:103650004A0657429D476BC9C379ED14783BA4C411 +:10366000FF185249FA353F5B699DCDF3A30DB2B106 +:103670000966E2CAE5BDE6D46204427B3C661F0FE0 +:1036800057734072A251D04078E8C45DDF32417474 +:103690000B704F654EC5C328807A98B8119BD39E96 +:1036A000CDE4054DE4601B416F061B3EEE1D665DDB +:1036B00014969354D9B3A4F0C55770390F6C01CC4C +:1036C000136560D7B3D8441B890CA9675832E455F9 +:1036D000FFCC1FE6D41F2D8D92F5C4B05DACBA01AE +:1036E00032C72B4235338D8CCD14B72954214D6C04 +:1036F0002124D4683512BF72270AC96600E5ADE3FC +:10370000BD30F71232C38E428661A99537F6BC29C7 +:103710005837FE9EE6BE36D3EAE6F8CCE7E2CC7731 +:10372000C771AD77AAF5ABE36595D2456B7DAE4029 +:103730008C2256F5FC97953972BECC79346C36B331 +:103740003AF29DC5CA747DAC95B08EA999BD36D3A9 +:103750001C117574F69489E1622A80A9379B1B4677 +:1037600044DD2780E486DC87AEAB18CEF4F97EE733 +:10377000D324FCEEBFE00D1B8C19B66520F3B37C9F +:1037800006227B18F5016806284B50E9AE6921E94D +:103790008D46DF2444FB08BD71CAB28CBAE1F2C584 +:1037A000A1CA7D39E96791778D3B6F5788CA292077 +:1037B0006DEAB2280D6F27A988708275B9152406A5 +:1037C0003F939C295190965D0F734194B182EBFC1D +:1037D00005504E264DF3FB9F324B91150A939335BE +:1037E000610BAE99FABC78A13320F24C2A5AC83D3D +:1037F00086BCCBE19FBA91B1F44D2D6761ADC24655 +:103800001A86C37E486BEA9CF7D37C9E929BDEE0CF +:10381000CE3E3EE0D32D8147FA2B3FD14CE968974D +:10382000DAD709D47A5C6BBF7A558BCE2E77A23566 +:10383000DE2F2C8E46F3683D026F53BF84FBFFECF6 +:103840006A308DA09E73CAC9B06AC68D8F86F96230 +:1038500011EC527DEC3208B8B51C7AB47B4DFEF801 +:1038600074E0805F8C8C7B74AB3212764668F733E1 +:10387000BFC8E80CCD0774B3A9A9EAC58064029556 +:10388000751C7C360DF64A9F61E5900BACF36034F5 +:103890008A924228635D53274EB701DE87D6E5DA68 +:1038A000B38F405D9C773B131B8242BB0E0CA74637 +:1038B0002F13A6A469F4B467E74B88EA10C2136615 +:1038C0008893E530BD7E59867DA068AF9551B9A833 +:1038D000F877E7D7E9790C10A1230AE72437B5B2C6 +:1038E000D9FD4CF82A0E744EF2E3DF1B7DD360BC89 +:1038F00078E0E5AC898BBBF7527E18F145B34B2ECF +:10390000BFEDB3CCC3A733AEB0D196F4CEEE604DCD +:103910009AA59373011659E58D29EE6976255A59B2 +:1039200006CE64D8FCDA23D6C2C52CCDC17C7EA8D5 +:1039300025B4F352802782FFFF03DA48B9D047ACA1 +:103940006133F30C20D5F999D2D1EB17CAA30255F4 +:103950006805F3278F0948F8C6BFA1F2ACF27CE5F1 +:10396000F3C7D398FA7FEB2604A06902D5DE7778F7 +:10397000E890668F5100E4787B4DBDC38201DF7D06 +:1039800023EA1CFA2A8B78D6EF6E69EC3D788C22FC +:10399000764126F884BEBD2A7313769886485276FF +:1039A0009EFC6FBEAF367DA4346E47AE0A53D6750B +:1039B000F9F3D4AD37CCDBC6491AF003F24433C473 +:1039C000417F1F9BB1F3268322DB76748A3EC82B8E +:1039D000BD3F11852ED13F9C9B4EABC7C7A389FC31 +:1039E000E3F87A9311624AB1A7D3A1B59C66A8AD5A +:1039F000204458FD760E1F249379C197333519342E +:103A000063CCAF3A19A020002237725AAE19167A49 +:103A1000632DEEF49039ABE4F7AE71A025340A3E85 +:103A2000FB3A4FE708FC8597795410EB40D415CF4B +:103A30001107CAD1D7C580AE411BA228657838616D +:103A4000CCC910BEF5E60258843DD3A14426A8EEA9 +:103A5000A2538696383A312061B6E8819FDF51C87B +:103A6000ACFEE447B183487889E3B73B3707C4E548 +:103A700059A01C387AC772C3B13F78DC6896BB4343 +:103A80009F028476FA20879CCE580660111135E695 +:103A9000A96A8548AD2F4E07E6915C507344418A70 +:103AA0008AF466A000AC44378C7B2C98B2B7A07126 +:103AB000229B4F16EF5BD85D6274F4131AC6C08266 +:103AC00070CE389485A6FB228C3350A481883DF0BB +:103AD0007E996D0A91509F2CF066A506E5D5F27689 +:103AE000A4D358E2E1D54E1B803A998CF568B08298 +:103AF00004C9F89580AAFC241B9527F03605A33C41 +:103B0000297D20605619CB34A233B48DDE2461E2C6 +:103B100085F1E5392D05852FD6BEE8484E5A4CEC87 +:103B20006026640019007E3C8545F65B2F3B2E8B9A +:103B30002C4104728A9FF7256E4ED52760AD65290A +:103B4000F4A9526C9F19A2084942DE4F87BB2F5B34 +:103B50003A5D664F34C451C097A7C5B6E8F1951DCC +:103B600053FA3B72141AD73B9EE535705DB7EDED05 +:103B70003F2702D0B9AECF7606548BCDF0D9153E93 +:103B800076A181CC4F89D435EFFF70E92C8CBA5FD8 +:103B9000D1C52755B9C28CC32D3B6F9766D7262850 +:103BA000FE4DF65DBFBAFD8796F4A4F957F0B62432 +:103BB0001C861C584C984EF548F6F433E6F8CC8138 +:103BC00089B845615312C5F9F16BD1D4348D5E6269 +:103BD0001797B0D1111AB0A402A040A01BD666DB83 +:103BE000FD232BEC1EA27751B18180B650DAF69AF4 +:103BF0007B6E2F11A03979D1721F7F90550B07E092 +:103C0000A1E89DD9F0A9EAAC4B684D27181BFD49E6 +:103C1000EB7C0E8EC82DE150E4ED0151BAF0EB7A49 +:103C20002A450504BBEC59AA01F7B357FAB77E98A9 +:103C3000F39D8569908D25BB89D1B049FA3BC59923 +:103C40007714710C688DCE81B5034873F0779E822E +:103C50009184306669B0FAB07DBEA27261303A1EBE +:103C600034049FFC2A80342928AF9E7ECD69F8FC5D +:103C70003A85DD3E072DFFF8D65245E33944C96544 +:103C8000AFC4028BAE7962CAAA62A37CCAF0CBA78A +:103C90003CC0E9CCD1C39AA2ED5B846039A3BE8756 +:103CA0009D7D96A10E01593EE42D6E9667AC55C0E0 +:103CB00061288F6AD7BC0A838A288C6F772426A94B +:103CC00045BC6A158A3C0FE4AB26C7DA2563023E81 +:103CD00016876EAF32AA040A9C1AE51648E38E15C1 +:103CE000AADD0C856016BEB3C528927D6F29499D5B +:103CF000118D5DF8A77BBEF0AFDA2D6A034B31550D +:103D0000F03DF379A73EFD2B2CEED896265477CCC8 +:103D100020092FFAE96335C26F571CE2B4C5C4BE4F +:103D20000D8AE2554C495BB6A46BFFCAEA6DB5C07B +:103D30009D798E86BA1FB7B59A955F27650296570B +:103D4000CE13EE2D989642220B3A2CDBDC0449F37D +:103D50006C315E202F0A1027B71CFBBF0064FDE703 +:103D600084658D318A75F1F679099F86A21BC0782A +:103D70004594B8843706E24C7BD0B35F35E03861B8 +:103D80006E8B8DAA5C996834F5718371AC4B63714D +:103D90005A04B0E3408D9FFD73D5649BD95EC3D1B7 +:103DA0006067F783D780CE353340F27CCE5BA7CCFB +:103DB000D0515BB5B1DB0D1B373FE9FADA7FC8E7BD +:103DC000B496B83B482FD01CD39F1BC7116E8253AB +:103DD000EF2B0EA19AD4DF679633AE79D85ADB6DFC +:103DE00024CAF6B284FBAFB2B6566A220999E0CB78 +:103DF000F302DDF112F62A745A5364B96AF05A17C5 +:103E0000451A764E3CA9A0D66BDAC5B8CB6061B92D +:103E10008B8F921CB3B35499381E2B77A945D48B42 +:103E20000D955F55043D462A43942A0CAC510C5F16 +:103E30000FFD2247F83A1888B19C3EE8F024A548C7 +:103E4000C883B01CA684CFC2A5665AD96FAF348B85 +:103E50007F33F07C18F1DE89A34E178698D5EE23C8 +:103E6000BF724E90F16F9B5575FC7DC93DC514C75F +:103E7000A211371C86E837BE030CD36B10C1E08952 +:103E8000B5CA4108E85E04937D3D15864FBDAB1869 +:103E90000CEC08A086A96ABF66DE3E295E6F6E94B0 +:103EA000CAE11A3937FB0F77479B811343F58265C7 +:103EB000BA951A6115B693EDFAA947CEC81FC33655 +:103EC0002A43B2DE28021DEA6E61540F1255B579FD +:103ED000AC6BE1ADA7C72A245162FF5B615D04AE04 +:103EE000CBEA138179D12EB3AD9A32368B281FAF2E +:103EF00042B4DADA53C7FDA2C108D1ACD9F342C843 +:103F000025628E229B614A107757CF99832A2D8C88 +:103F10003121ADBD993E57C43251F358D530826D31 +:103F2000835FBC9C3870413D199F83FD0F5F7C54BB +:103F3000F266E1E2719EE2E03B5FDC7569CB6E8F79 +:103F400069759D1946C01EF37EB096CDB016960CCD +:103F5000ADD4EF7FBAE39CA106D08D0BF5CD123620 +:103F60008367190BB69ECC825B94177944C93C12C7 +:103F7000B761CDA882A84EEAE3120FB81531161F1B +:103F8000BFB128BA72F2ADE3E181652386AE8AB093 +:103F9000777DD383EE729A4D81346F850014474349 +:103FA0004A3E346C8B7585FB51BB2408536198DC09 +:103FB000F168F73135FFE14258FF5F71A42552895E +:103FC000F4EAE4A289E9C83E8C55310733D455E6BA +:103FD0009F101518E9BF0A0D8640748AC32C31C49E +:103FE0008902F4AFFF95C2FDD87E7EF8C4523E87A9 +:103FF000BB9CC9E62FAF55E674CA34D9240B905840 +:1040000063803FCE6A4CC514CF6DF47054C1A8EEE6 +:10401000603804A7B55DE0583886C0D11BE2C98F6F +:10402000B9E10653A8466E0C42BB0C116B02361068 +:10403000434C0307523C24625BF93C0A10F06CD2FB +:10404000DC6DBB63A8B26A3531C414580C4B46C84A +:104050001442677285EB7BAB5A26280E7777172BB5 +:104060007E487043324FCE141C9C483726359A4DFB +:1040700031C220AA63249060148079F8C20951AF3C +:104080007782EF72D0888A981D2B710D849CE5B4DD +:10409000E8C20FA4DF41AA88BC1CC5089A80F7F6C5 +:1040A0001CB1F643B2D77F96FDC805C83275CFEC78 +:1040B000DB4E3D9CB2F5130556622E5F86D86D59D6 +:1040C00032C59528531968F65A0F785C783177A075 +:1040D00060693283EDDE331EA0F030629DEEE7B8FA +:1040E000DA7DC1C6699A73FB663B7834FF2874ADEC +:1040F00085EFFB56738B29855B033ECDBE7930E49B +:10410000FE37ABA936F868916D78B9340A0F7D692E +:10411000F7034756CCC82E2D6A4FD44215C410075A +:10412000C83E046B494668285F1A5AEB82F03BF997 +:1041300029CD69C6B8E4F3E0446BB37B890D35E063 +:10414000180B3A0801EF72E9906706CD9C952A5644 +:1041500081AAE4FC9CA8F4A5A9A1B3A57B1E72A624 +:10416000029F04B0CFCE6015B0D3978D0F3D1D7F59 +:1041700063F0D4306E6D5229AE3703A02C0241FF9C +:1041800039F665D9D58DCD6D230E7AC996D3C5CCB8 +:104190003EDC7A76E24573C954D467C64D715473D8 +:1041A0005EC7495C3221A956D10F16DBACC39CAA6D +:1041B00054564A1F4C919EC854AF7EE1F97FD3FA02 +:1041C000717D981DCE7EDEAF3A257B730DD68016AD +:1041D00079353AA5917082E7C59996ECC2F7A1624C +:1041E0009FE66C1B52D67641E8B44F1D7910062F1E +:1041F000B52B75C36F643EFC0031F31EA03DE34C4C +:1042000022B7CA86221307B2F5B849D810D33A7E2E +:104210003615E303A926154F40050A31A82FCA35E4 +:10422000C61373890A61DACB4E7DA5C695CBE9B971 +:10423000D6C82BD1F614F54CB541AC9CCAC609EFD3 +:10424000DE7940144F48D3C63200538A97ECE8FE1B +:10425000023E98CD121F374D3E86A891D5E14BA363 +:10426000F427133622EFCA0AB0DC35E3CC58062B0C +:10427000DE1F1B9EE3E492D90897B01B369CBD8AD3 +:10428000C2E1F0808CB2C0E2A6145D3BC197DB773F +:10429000C49D3C62B10EF1D2B9446744BE2148804E +:1042A000721F47FAAB3B047859B673C7FCBC04369F +:1042B00046376C4B6A5E3359FACBB93480BD04B8CB +:1042C000C8C6B794F68BCBF4C65895F320DD77FBC0 +:1042D00085C0E0F0D0E8A194BA83731C0A5265A8A7 +:1042E000CD73DD779D7AF462B77CCF980BDA96B206 +:1042F000501E0DB7A5913504E692703FDB664191E3 +:1043000023BFF5175A9AF5824F4D1977E6B603DDAC +:10431000CB5CF638088E0097799423B5D042693784 +:1043200092A5BD025D7EE278F1E1EF2088D2893D61 +:10433000DCB2563677DB04A868E5A19272EEDF7A2C +:1043400060B80B9CF7E919CA77A8BAD64236A133F0 +:1043500012D915CFAF022F5F14144AD4673500A0CD +:1043600004DAE662627873CD8F8924BAB5EDF66C13 +:10437000C44E38F01923260D5E94E89921FDFB8187 +:104380008DDBABF26CF16B48761FC3DB32C2DA3DDA +:10439000AE82B1BF422A4D202D4A40158F59297E49 +:1043A000B710720DBAA80A181B5295793EC5216F35 +:1043B0001E066C0D1F59C3BC3195C28CB344B68622 +:1043C00086F5DD3B9D4D036B41A3970BF243E4481B +:1043D0007EFD37F46E5AF6C8675369917572221DD7 +:1043E00058C13FA2E2EE5339BBCEA80AF785E47369 +:1043F000384BB3186E470D71FBEB77D65F80358D68 +:104400009AF0D34406EEFE2B1D547DDAFB893FA1C2 +:104410009757474E2D45027B4156B5F6ED76BCD3F6 +:10442000A2FADD889C2A649301B49189BAD05EAA6D +:10443000FBDBB0FDB01C3B7FE028F0633C29D1CB17 +:1044400095C9D4C95B62EFA596B461765E28C85A57 +:104450003303A9DEA8EEF335D6486EE254E975AC15 +:104460008F48E8998943BBE7878CA553EC99B11A2B +:1044700092A0DCD187E8C34910B2854F7E46B81EB2 +:10448000954BA88DE24DDDDAEF82181465DAD24F34 +:10449000002B318C6DFD7E5055504690BC360F3749 +:1044A0006D2E67D77656AE01F3875C5E5F836DAD88 +:1044B000C40259E9F6ED35257DFC3F861A4BEA85A5 +:1044C00010E84B47670E76BE66161C7B1B6595B2DF +:1044D000830D1AEEF5745A8A63603B2C9555C01E05 +:1044E0001CFAB45791215598B0E933BB78F47F5941 +:1044F000B679FA37B0CEF9C065D34CFFF4E8B2C74D +:104500003A201C42AD43A4F403579DCE4D4755F5C8 +:10451000D69AFA191A212EDECF2EA681C72DFEF4C7 +:10452000E623D8B4B53CCA52054B13C12A721FE02A +:10453000295CF19BE11DCC871E29541CE7CB544F0D +:104540009E3CCAF0A751F3AF29D6D3DB9B5ECD8E3C +:104550005FC7D48889A640507F123D968F4AAFC46A +:10456000568347A11078CDE250924FD40C173B8769 +:10457000EA3B46EB19146F299214B665BFD145DFAB +:104580008947E3B0525FFE9E78F64B29727C7EF637 +:104590007860D38BF6AABBB226CC3200E6AEBC164E +:1045A000CEEE990C2B13C3EEA242F504F7B153BB28 +:1045B000F14B84B3E33113F18F267C6A0499B86C14 +:1045C000B52D90C7104ED2000C54086CE27F2BD250 +:1045D00093B74922CEBDF30325D36BA4AD3B0AF0BC +:1045E000989B4F4E2B02658D225CB2EA3C41E30D55 +:1045F000650E6FA1EA73E8AED134CA8A5ECC726AE6 +:10460000F363709417286570883F9D17C07F0CB7BF +:10461000BA2259C0A44B07EA77A2D99B51BD37BE35 +:10462000760DDB7946BB4350C4E403205E4B92FB1E +:10463000132F4D19A17F2F240DDDD9ED0ABC1CC706 +:10464000E05F97CD217AF31D62DBC2E649A3A29118 +:104650002023BB2A4500861C9368B8BCA9841F345C +:104660002D8059EA4DA5373BEF3CD8AE90A75D6C45 +:104670002A6AA5FD344A09C8C7AA90D28100E2621D +:10468000E75F395D44166262C4A9A4E7BA8B93312F +:1046900069CBB054F0B170B31E4F29DA1E44E1A0CB +:1046A000B3FD7FD3DFC72E153B8940FC68DC61F783 +:1046B0008345718F21BF8905393F41620E7ADB1531 +:1046C000AEEBE27B7C41663F3AEF71BE520FD36E98 +:1046D00048B705B6839B0B24E6D9418D6FD48A0871 +:1046E0005A46841809ADB8F68FDCD9D043C191B2CF +:1046F000BA74257644FBE7ED80B8439316D3A8D16E +:10470000DABE15AF036C3BF7099BBDF68DC5F1DE34 +:10471000613163452B45BFE2610DD53FEFB77AAEFE +:10472000714F79082FCC3B0766B17C69760C3865F0 +:10473000E6259B9A395114D373595DD9CB7DDB5E45 +:10474000170B24AF62AA598D03FC92AAB3C432821C +:104750003922D55CF0297CFE6592F16C4BB3460F93 +:10476000E4C639C8651C7EA8F4C818C4635F8EC04F +:10477000F9E2D284CF9DBA7C5D699B21C00CBF1D3C +:104780000C166F9CC0AC7CD3812D698601027956D2 +:1047900049FEF7808E313563E8EFE7A6ED31711AF7 +:1047A000C7B4EAE3993C4AA244DD14E9A96319734A +:1047B000E37B0E91E8C90E9BD752DADB1D710C0B1F +:1047C0001730D7AFD2EB646B1F391D569229723B5D +:1047D000365F5164A0B85C46543EFED3B70F845B8D +:1047E00013B3BC587611C9B47200074885790661C5 +:1047F0008AF5199EEFD374588366A3D0D6B80130DA +:10480000F1E852AE21784A8E3B7F9D07FF4591E645 +:10481000E624996C92674EA0E007AC0401A8EF591A +:10482000FA9598D25D0AEF65A079D2789CC4ED69BB +:104830004C6BC872E0D139DD56E6DFFF799DE32A83 +:10484000E04E379F16B169C56A1C3171676E7C1DD9 +:10485000278B821C52A75020EDBF550E9815D2AB66 +:1048600020369766536FE0140126A04CB8A9CB6C94 +:10487000E5AB5E056E049BA2879CBA0BBB76B009C4 +:10488000E2C6BDEA3D6CB8DED95484CFC6BA3A95CB +:10489000B013A97FC5BFF1CCFF1EB9179A38B4B2C7 +:1048A000A49BA99CD6E0AE9F8FAA5E9383C05BD7E2 +:1048B000A117E30B2932BDDE8776194D9C10FBAAA8 +:1048C0005A9476EABA0E87C5F27BB4B86F9838D29C +:1048D000A1B3C13B1CCD5CD7BB4145BCBC8FA3DAA7 +:1048E0004F1AF8B93750B7354BE3A641D0034F5CA8 +:1048F0009E8C7B66D231F478DF9F4A321E90ED4B5E +:10490000F99B3B532826A4B756F020AFD6EC1B30BA +:10491000DF60C4065884051094127F8B79902C4A6E +:10492000A92BE4064C9B9E5F35EE56AEDEFE30B200 +:10493000A17AC0EDF701F223F79B723B167A4E8EF7 +:10494000E6D9D3AE6650032F24BB68427CBD96AA3D +:10495000E1E3B604A0BDF9D983DDDD01BDD0F8499E +:10496000B61368070237CBE676C12FFC5ACE08CBC8 +:10497000DBDD769BD4949768B5263BD7746BFFF844 +:104980001E8A042F21E8A41C07C9005381894418FA +:1049900065D5E1B60B598AAB370C339F45BB700721 +:1049A000FB19050A6F0AB4ADA567605F369FA79330 +:1049B0005FF302B1036092A2344033ADF23AF827BC +:1049C0000B0666783AE36608052AC0EE52ECE80466 +:1049D0000906741AA3AE865BC78540E66DF1B30382 +:1049E00003A8C90C229356FD52280A34FA5D56C713 +:1049F0000D7C978CD50A0CFCB82BDFF249BCBF7735 +:104A00002BF09FF7EFC5F9338008A73ED628B97C75 +:104A1000E2C1901BC3902201C70CF184C7437DD72C +:104A2000A93478E4D09BC199DC8C29554D053BF61F +:104A300009524BA949E99052BD01AF80F3FA06D85B +:104A40002DEF38356B38C7D067CEBD3286B379923B +:104A5000B57DDC33E63A24D9FB45257CB09052E99C +:104A6000F5CA7D4CEF067CAC7E80B8A707E664B83B +:104A7000C7C1E41F5FD604DB2522041DD898B4D437 +:104A8000AFDDECB5DA503AF269017DEABC3A792C37 +:104A90004931FD34BA0C8D937FBB3A32D75F5852FF +:104AA00063CFC01668B73F1A764A0709565AE40220 +:104AB000030AC05FCD87C969D1625B507C86DD4E39 +:104AC000F586D6F6149211FD9A16B81704F224B2A0 +:104AD0000F3668110F6792962D19736A65A4C85432 +:104AE000873B8FAC0C5DD8D33C92E23CA30B146D9A +:104AF0003048E54ED684C16AE98FB97C780015FB51 +:104B000047937914BA7B201022D62F8B40589011EE +:104B100014B2180B5D9615062A76F5309C8A999C7E +:104B2000CCFFD7506BB4D913D4DD9F3C34B2D93607 +:104B30005AD705185C582600916AA83C01606A1291 +:104B4000AC22FB34E5DEF2773FEBD1FEB76BD2F55A +:104B5000C9F1E9610095AA23190CAAC103980C14A4 +:104B6000E51037A0B5E6BD19F28EA668200F2A120F +:104B7000C3CAE3E9FEC4FDEF13FD906F8D67932A6E +:104B8000A0DACAF0E60274EEC943089F075D1BDE97 +:104B900001934CE21449E45A02CF7F37943F62807C +:104BA000775A1CA1DFDD25120243C106ED665C1CAD +:104BB000CF4FC40DE4AD79DCC244F60928ACC42C57 +:104BC000BFD72933F7159FF18D551035DFEF0BB0A7 +:104BD000AB050F71B9918A6F07A238F067C2B48E26 +:104BE0006CD705165062DB8E1653E521B9D4DE284A +:104BF00005AA174560686CC0C0FF1972AFAA7A9BFE +:104C00001D3C770EBA85DB2ABE88E1FE67B40362DD +:104C10004EACC26D9B7B4CB3710B1E1B1A3D023513 +:104C20005CA7B57AD719A0BC1D827C72BB6460EE0C +:104C3000C36DDF033899C7A0720345317DF9682D34 +:104C4000AFE25B02EA4FE0A755B7FA6407E4DA95F2 +:104C5000717C4CCDEDDCE46AAFD8B9B84ADB938FF8 +:104C6000FA82EF16D71DA4E51A7FFEF17C42F32EDF +:104C7000CAEF91425189DD3EE9364747D3D6D91470 +:104C8000BBFC724B0563E5A6CEBD973C981D1E8FFD +:104C9000867F76CDE719720C8BF9408C62D0F75B7A +:104CA00018D161B1C2EBF97F3A8FE50C868DE89A95 +:104CB000D1B43357807011104B0E778E106FC5E74B +:104CC000E1231CBAEB7F33BB68207372C9C99F2DE7 +:104CD000E36D8F1C809E8A653AFA904D9A997467AD +:104CE0007F84B9F6BB6EFE854FF8BD68BD566E4831 +:104CF000AC3517F85DA4C4C7F260C3C0CD2B4AF62B +:104D00005A4F006E7BBC1059ABC345C3D657082120 +:104D1000307829D6238C1D28F9A50D3DCD3E2022C3 +:104D20003B9A302573EAA388E7CDABD85497FC5C57 +:104D3000590B0D650D7D78A9FC5A5908F7D2E03062 +:104D4000A6CDBBF4FE2DD83DD8468B932C894B8441 +:104D500025C6539224560AD5A88EEF1C62000C3E3D +:104D600018BB152413D42F350775E84D5144175936 +:104D70004E6C920E2928B5CC18CDBAAF58A5184A5A +:104D8000C2FCB9630CEEAB03D1548D5632C581C55C +:104D90004759249C21F5D665EC15F7DED13D4FF53A +:104DA0006C42408DA22559BFA02382E187E4078B86 +:104DB00022952B1301483A131FCFDAEB7809DCAFA9 +:104DC0005C611E59F94844C737EE5587C0D702BF0A +:104DD000FC86967ADABD6C124A3EFE2D8DBE21C845 +:104DE00028CF6108A99DB3D01947C98F10FCA64EE2 +:104DF00051D6E00B8D313274254821FBAAE51E9572 +:104E00007E86DACFE8AE4E2E9EC6A5FC4629799660 +:104E1000F849FF3C8ACE61F6E4BA70D1313C778D17 +:104E20004F86A6FDE5A390B9029D7DAB763F483342 +:104E3000FE838013B371FCE66962C20C6F54D0BE6E +:104E40005EA13913DCF3647B7FF61935E509C8B937 +:104E5000966F0956952BF782FD7BDD679C18F3CF83 +:104E600041473E5694D70BCECC811E24274050BBE1 +:104E7000421D044E92F78569CDBE97172306001494 +:104E800021DA47DB9B16BD2C3571362A372A0D8671 +:104E900033D2E3D34CC5F168EA97C6CA78808ED97D +:104EA0005916C4CF111E56F3D0A3300175324802F3 +:104EB0006C1A51D1DEFE0AF9B7470835E929F740E7 +:104EC000F017BFC000F0B0A38EE135A53278779619 +:104ED000C717D978918AF6A917C3C16835DA67A2CE +:104EE000D22956CDC13C96A06CF0472410618C8F1E +:104EF000446F4BA4E8F2E4FF32FE030ECC5C45366F +:104F00007D83C9C3D733FCF86B99F449C80F3C22A1 +:104F1000E75BD9C6A9E3CA4B260DE5D79FD4B58474 +:104F200029E6B8AE9A846BF00AB42339EA78AEB0B9 +:104F3000A44FBF6822218C45C176C70388543C1B0F +:104F400070EB4D17CFC933220E447B5D99CBC19ACC +:104F5000DE506970EC308123C8DF835EDE1EB51F32 +:104F6000DAB2FFBD096A6B84CEE757C71D19256801 +:104F700043BACEC9546665F781B88EDD24737CE9E7 +:104F8000A3093C96566E1242BCE545DDE36A79788A +:104F9000FDD7956123F08B5F358ECC1199403CA7EE +:104FA00086F0A71CBA4B12E53FE54EA550580AFA09 +:104FB00006172656D3F5022477603C5FA80F741BB2 +:104FC0007304FAEB201DB79D93A5C722ACE880AC13 +:104FD000BBF18063F64C75B8004B3747816373FDB6 +:104FE00086F89EC2B75FA9A4566A1CDA3D733604E0 +:104FF00059557F56F0C22609F6EBCF258648E69B29 +:105000008A7F721C879273A92855B7EA3F0D6DA657 +:1050100027398BC047F3FD90877EF2D452EC38736A +:10502000AE93E4D361C41D6EBBD40282ED091AF3C2 +:10503000E3D1BC19032CF31E6A897648C20179B00A +:10504000E169794BB1F6F37A09994B9C1D368D765F +:10505000FAAC994AE000AED8ED3F040A3D836E5C9D +:105060006A3F02BC4D1CF0D8ABC2472C291B9600EE +:10507000DC27900218CF7773F0B14A90A6F20C9417 +:10508000545F762AD83CC5BFBFDF249F4C0E04E195 +:105090001B58BD51056BE3DDC536B1EC912535BE1E +:1050A000BFB33E32A18CA56B4B07689C977326E477 +:1050B000FF8F8A0F8695FF5A13117E334D6F20ADF7 +:1050C0007E84DF204DD7EC0EC1075F8FA6B81C4948 +:1050D0009510260352E465626B4C83E84BCBFAA132 +:1050E00026FAE9A56769138C4735999E943C51A629 +:1050F000119AEAB99E8F638592D4B31E11D8BAF57E +:10510000260AF1F6D0F13DF440286DCAF95462A0A8 +:10511000CA0120785735CA3C367A63CF27313B9B8A +:1051200095F4C713497BBF40712F0E0D0B13B2A628 +:105130000D41ECEAE1CD9BEC521FB95D577C88DB59 +:10514000E7B808DEA6099B3842DF99A5B15A279C2B +:10515000E8CF71BF88CDABBF7DDB256A4923E3BAB9 +:105160004FA5A6314DA7BA61DE5E18704F1481734A +:105170004AE71855630156673B4A6A0694938A3892 +:10518000AB5F8BB05362003B143AE221B10630CDE5 +:10519000B16FA80E5954E709F2E1F202D95C455CFF +:1051A000AD45FA5B6D262641FB6FBD51E81D0350EE +:1051B00070889D795ACAEBE0B442EB099E32AEA1E9 +:1051C000F2D779D5A5B0F5ECF83C8AB89D6271EDBF +:1051D0007FED47E12D359A74A827FD8EC7625707EA +:1051E00080061692981A474F0D06395B4C08CA592B +:1051F0003B45C1097D593807254689C69494D52C6D +:10520000B55FD15522680C2CF6241E25F80CBD750F +:10521000551C2D173065C75ADCA638E1885CC7EFEE +:105220000915158DF4576282672432509557A9D815 +:1052300077C474E4447C9C8F19BF70EA34A1967CD7 +:10524000856D5CD61FDE6A2CCF4B094B9B137840D3 +:105250004C7CFB9A5C203916288CD012512B4024B0 +:1052600090DFF7BA172B5E475EED1057A5ACD9FF5C +:105270002CA7A7EF63AA4E0A11746584370EB2F00B +:105280001A23BBB80FB82F691BF38365B6EE95A23E +:10529000BDE2F3B5216D2CBE7A1086701CDAABB975 +:1052A000651F55A436CAFC0ED57B700A3C96D03FCC +:1052B00064D398785D64703D07F1EE22D2B67ACB64 +:1052C0007030EF842BB3A80098C0E8FD00981660FA +:1052D000C4FF00EAF12AE6A5BB7F569A41B36B16DC +:1052E0000BA6A6ADA4E67648B950C277DEFA02EB6B +:1052F00005044ACE1366535723034FD8574615BDAE +:10530000CB5D754B82B3DB4A2F485909483902C639 +:105310007E324D96D0F5BFBC45B8071217CC55FE6E +:10532000236882F949FEFE16B5DCEC793F647DD630 +:10533000805F8445E13264F2ADD6F35A30C9BD6373 +:1053400043EEA556E12B527E5BAFC9470810CAC396 +:10535000299B50BFDF7FC2B8333D14FB61BA4706BB +:10536000DA3D8A4A9D3D04A8612AD6D8D8AC3DD002 +:10537000C72EC1BEED3DA92F67771AC1789FABAB91 +:10538000809E763796502F64EB3F1F30BC2A6C917D +:10539000E2FB87F96E558CA853A469DE810B09A640 +:1053A0003D747D57B7FF2282A831A5CCC0377DF16F +:1053B00018834FB022B9DC8D23B4FB471F05C60FFD +:1053C00041F003BD7299C888828AB7A175C040CEEA +:1053D0002F9676B9E14BBC2DC91226D42587DB6701 +:1053E0002B3FFDBF3282BE3B908C39C4DA98CDBDD5 +:1053F000F7A3CEF34CC7B70691C213C9C53078D90D +:10540000BF2AE661DE69E5F2B362296BCA06259E12 +:10541000872E2B4F97BFC5BDA3F6B8678AF1241E10 +:1054200038AC3BE4B7E879781E71566B2D4A7B099E +:10543000F4DC463909E8BED670B73B8E9097DFD5CD +:105440002D0909D10368F6ACFE6E2CC81A76F1A1BD +:1054500098F3BD226EE6972E27398966B41D929384 +:10546000F2331A284F9C8AF38F13676A0CB6AFF495 +:10547000335BAC1B3D541EFE6BA906B0B8754AA148 +:10548000F2DD1FDA866A28EC75169F195E31A42FAB +:1054900097DBDA2D30DE6099ACC00F0E8EB4CEC92A +:1054A0000776E250B765E45B83C2DB9F2F87E53761 +:1054B0004E98EAEFBB0D9231B1FFD2925D8C6594AC +:1054C000D98258E8377922C4246A4DA69FE472B77E +:1054D00054ADF7564A199AC8C8CBE39E9F81A68B54 +:1054E000BF6DBE4692CB19884C8DD99B3048C6D330 +:1054F000152C50ED760D3386EEBBA45A66B25A6772 +:10550000311D327A2F1358732865C3A41DF5D53B7E +:10551000AEBFF61950AE9200965B001A0B8394BD95 +:105520005C65C2361740774AFE86E42EEEA980BC41 +:10553000E70E8816CB85031B40F0C46E091B30D7DD +:10554000EA6B033412DC2F9FDF53C86CEBFA1A109E +:105550003F812D2CA63BF4B41FD2B9EBA9C5503B1B +:10556000C5D02BA9A5531E0904F4BEEBA50BFD6401 +:10557000E95C1E7967836A5242515F6DF0E68BECFD +:1055800068024C924F18A3375C19F9E196EA4F5420 +:10559000BE19B74BA63589D30F1029700D1320D62D +:1055A0002A4B54C536E8BD3F732BBCE3A2091F64E8 +:1055B00091B8EEE1B3A0FB4BA20A52EC2462D31ED9 +:1055C000C1D40098650D9A86E6BD15C4F11508C9C9 +:1055D000B9CB465634105AD0A1053F359A1144B084 +:1055E000436637E53E4AC631B2236DB3BBC654C7E6 +:1055F000255C80BF1C2C7D7FEEF5D7427FDB84BE0F +:10560000107FF156AAE7B324EBC7DC1C7C35719FF1 +:10561000B80613D1F8EB2F2F9B325F9444DE9FCC5A +:10562000CB794CE41DD061985CF511621C004CC034 +:10563000187C2D96FB5ED894B053E1F77B67F9BDDB +:105640001591502B8ACF7DBBCFC0A468311F39B1D3 +:1056500082A5FECE1B6C40B11BCBF5CA053F964E12 +:10566000D774A13309AC439E55C5CEBCC43E386D3A +:1056700082960089E8BC8B9CAF0BFFAF541D179638 +:1056800018F5231267B9D835767BBE737E5371E463 +:10569000B11C379FE14E8AD3177AECA95C6F9782D1 +:1056A000142AF5DD8CF4B72B66F5C71DCF2298BE02 +:1056B0007D5A080A2F294EC8B30D371DB4F0FA8F52 +:1056C000525F01AD3230ED738CE5BE71E901225CB1 +:1056D00009074DE8C0BA4967EFB262C2BE67709F62 +:1056E0006F521F2A039981DEDF82E4A9F354E1F5AA +:1056F0006AA9860F38BFF4FE26FD6660730818A9F4 +:105700004BC6595889F70DC4FEAF8FC564F8C967F9 +:105710005BE6C454F32B938012C124F37A4A8CAF16 +:10572000EDACF01C5788F676AFCC3064FC65898F01 +:105730001026DA1387FACBB230304459B6AA7FD09C +:105740004841582E0741E04E438BA1EE46684CE895 +:10575000D4D6B5CDC1803BCAC0BCC3C5022E0FB1E3 +:10576000268277C69B17B8EE04BAB25011C83939F1 +:10577000D4DEF730A4480CDEA2EF4564A8CC7A0151 +:10578000A156AA0B40383C6A7AD45FB78DA32A355C +:10579000930863C112DFF8E92E81F4876AA4D7D099 +:1057A000C1057661996C8D781198FF2AE2D1D919DB +:1057B00019A07C6DD353AEBE894262B3BEA2C1FFB5 +:1057C0004096A78A3976BDFD9B463DF5586916C4BB +:1057D000445EC049C9C66BCEDE7C16090F8F3ADD28 +:1057E000366794591389B66D5CE28B4B9FB72E32A6 +:1057F000E9F81E31F5C310B6AF496045D29056891D +:10580000B3EFC835BE105C79B9586B740731D3B2A9 +:10581000B7254CB8F82F17994C6A8D08B6C0FEA46E +:1058200043F76AD45137CB656F411E64978057FCAC +:10583000B9E71E72853DB5C82EF4697D5A1F6F8683 +:105840005D7F763D0329A5435F2E5288CEC6A09288 +:1058500032EE5847568E80877D8022A079F862BF4D +:105860005F0BD4AB1BA0ACC35CA54DF2B91517B24E +:10587000441698A930D25D321E27D7D4A7709CE970 +:1058800003E1BFE2971B57BF56DBBB33E696BA0C6A +:105890002684577084B181313C7FADD2B9D7E6946C +:1058A00060AB371F60D49CCB5F06094E387E4646FE +:1058B0008AC4D7580597BF9EEAAA790DFC658A93DA +:1058C0009B91E693513022B37367FC87D25EA31697 +:1058D0002E139C2DF03A06698724CEDB1BC24DD2D5 +:1058E0000F1AD70BC3E7F3DC72BB52CB641DF6264D +:1058F00007A7563E12D65AB449A0C2C8B8009DFBAD +:10590000AB32D3EACB8FFA56D8F1699BD17ED565FD +:105910004D025221881B20817B476B0447F5868608 +:105920002FCDBDDBCD9CBC701D098092A74BF99794 +:105930000B97803BA5D58F52573E6F0C3CFF069FBF +:10594000CB38E4F8D1EF5588CAF9F032D8D340AD5E +:10595000134D741CD56F14FFE1F34C4FA266F32472 +:10596000E474DFBBC1EA24D90B1B3D179F48537772 +:105970003B7A419BE90E6EA7181F6EDF61B0572876 +:10598000F7B184F2CF4CE162C1D5476556825AB176 +:10599000ED8A2A040684BD65CF693E2CABA975BF8C +:1059A0008BD143379717750A3C0490925C8E50F167 +:1059B0003607D6289F28B359DC0B92C8F22122C2A1 +:1059C000DCA60D39328435EA7818803E07F88DCE92 +:1059D000C026B096EB8F2BE4F05118B15673944C5F +:1059E000150B57E96551474EC11A1A63395B1EB949 +:1059F0006ED9FD61867B3E7E8DEAAF5CE6392D0D6A +:105A000011B73C25A16CC491110346034A757AA0D5 +:105A1000DD7C0D829C21312919378799E50A694778 +:105A20001109DD91467D2B8C3930852310610BDA0D +:105A30004387001C68C9B194EDE115ED79BD4D2A8D +:105A4000F497EA923060D3B9A0E6C6AEB76FC54C02 +:105A5000021AF920D2104904F2DBC46E7A2FC4CEA8 +:105A6000D9344EC839CA667A818DC2DE3C56E02EE2 +:105A7000F30F2720C8558DD3134FDA43836000ED11 +:105A8000CE86A112CEE723181442F8A91DFFD8CF65 +:105A9000D72F3252C9BF64B5D46C987D530D00D056 +:105AA00012975982ADD0C3879AAA7F57DA41E70887 +:105AB000A802A5A88675F39F4404F7898330F6925F +:105AC000FA095487C08807E111DB328FC0C3304028 +:105AD0006D34C78DE433A0472D762AEB978CD04BDD +:105AE000FA1E9A993AD0B373C4356D2F6E9071BE79 +:105AF0002DD5D5675CC3118761063B4C17D4DB1CE1 +:105B00003425DCBE06290ADCAC03ABD081E43C358D +:105B1000B00C76384CD1BFFE301D79BA7CAE8B0804 +:105B2000B5164BBD07438664B3671DE7A37F34A159 +:105B3000675069176AD97D07A92D2FA74C5AD4033E +:105B400050FEBEAF6471C1A2A7CDA5254B5EB58D39 +:105B500003E91AC73613F5B65FD81E1332C5ECD663 +:105B6000282F0E1A70FEC2F859412B7E54C45CA631 +:105B70004F8583C5F4DB0D51F3DECA2C8108B5D601 +:105B80006B78CF606A8A4EF9B3890F2B5EF1ECBE59 +:105B90000AFB7D640F810D4EDBD0F97A645FF02E35 +:105BA0002B2E31A14856E809833895AA1554484C44 +:105BB00068F50E920EDF5CA8C13D4DE51B760257DD +:105BC000F104386740A93B530AB109EE6DFD6B44FF +:105BD0006A0A3653335071F85CAC650AC9F20AA4FC +:105BE000080D9582E3ACC680F5B4160ABD0663CCF9 +:105BF0001105273199904A746F6F15B2CD5919105C +:105C0000DE243E158EDD2CF9AE2098166982D76D04 +:105C1000AB9B7F4152F50A8F30C53AD7FBC5BFA475 +:105C2000F34A7365B86D0CB8FD3F0C1ED72ACC51F2 +:105C3000BDDE6AC47F8B384867B36D2478E1219A52 +:105C4000A071A09B17846B77B71775A9C0F4C29198 +:105C50006DBF33734579FAF3870C8688E4BF28F962 +:105C60002601C896B5531A2314FD87FF64AF5779F0 +:105C7000C1BD631B01751E6C5FEF92DE3D63455530 +:105C80001F0ABC647389C97C7BA1DC9D6E1C390C26 +:105C900019950EA7F8A6BCAA7B357B7D323F5E9A8C +:105CA000A3E1C1B699058DBDF6BD0A2F096BDBD7FF +:105CB000D04CB749CD66AEEA64847344A7BF05E211 +:105CC0000CF06E052E2CB7B0E23CBEFE3DE92293EF +:105CD0003E921056AA2A7CADFCFAF17591495BFC04 +:105CE000F484975356D73879BA47BCECF6686714F2 +:105CF000E12546E5143EE8165544C183C3CF46F777 +:105D0000237C42ECAE980C5897DA5A745B346D9B46 +:105D10000ACB56CB1CB9E38D25FB1ACD8B62824B87 +:105D20006444A92C0B924FF2A55B758FFF5AF83D86 +:105D3000166CB7C11B71FE9A2DEE4EFA32E55B7AF6 +:105D4000727D41219532E6DD58B239DF8A774D3CCC +:105D5000BFE53B4B2A5D0FAE43124A57E17CF0444E +:105D600002FE2AAA0F883CC516E670DAECEDE3E0E5 +:105D7000B28A45DFEB32F67FFB97D5D4AB9B39A4D3 +:105D8000F71FEED63725FF06160D2B566BE7927DD3 +:105D900099731667D07DE6D4E04F9CDE9C0C95D2BB +:105DA00026A84545C88B020C2D8F1096868C763C14 +:105DB0008D621FA2CFEBE453D616EA567CE9E68B40 +:105DC000D155ED39085FEDB7642ED93AF25F08D6A8 +:105DD0006A5E24175258FCE7F431E96855AC7C7CC4 +:105DE000720CBDCA30CD9F778C4545F79CDB0074A3 +:105DF0005A5123E0F7553D00EFD3B32A19F9FA5B66 +:105E0000585DA732C9A0B2CC4E423520B0CE201882 +:105E1000C22271E045F7F66833570400D66C8F2E26 +:105E20009CDBCFF9E4FD7803F0091C285304D89FCC +:105E3000F574DF9F934372D801152C3976AAEDDCF7 +:105E40000AE4018A431D288927E02A17FC605C5F69 +:105E5000C7D0A93DDCFCD172E0A9DE54DD294101A7 +:105E600065755F106F7002AFB4C2113A13025F9C88 +:105E70000C23DFDAB2B36DE112BA0F427B9B2BFD2C +:105E8000A104785392D424472EE7EA68566F7D9593 +:105E9000258FB30726625F0ED3A84BEB1F8C5E3CA9 +:105EA000263C0BFBD970DAD7E02DEC8F914928C93D +:105EB0005DB4114247050D876266B09D181DD70C71 +:105EC0005D8192AA471DE313ABB4692166806362CA +:105ED00005E7303B9C5740CF670B89BA464AF359D8 +:105EE000ACFA1B58A0314D65B5B13719E91EADF8B4 +:105EF0004B5BC54485A1E760700EB5476B80556468 +:105F000053FB84F777EB5B78EF035AB4065D5A5581 +:105F100005A1607D51516CBC8E1E3A0F7E314E7AC8 +:105F200028ADD2E1E3F4834370D13A8C51376D61EF +:105F300068FD370DECC0ED8D54CC896691C6851196 +:105F4000A2D3196442B1CF75390C2C091D2E889B40 +:105F50002CEC6A856DB4D59D68F4518A1EEF450618 +:105F60006E6CA542238DFA47DED9D2D5701AA03EB9 +:105F700024DB80263CA7A203D500925B2552169213 +:105F8000F59051B911C76E78FCE2326510528EA8B7 +:105F90006D4ED3A667DCBE8C22D872AB2B316DAEB2 +:105FA0001601E38C45B86ABF2E6C547620A689D1C1 +:105FB000B04A22F58B7F74C5E3DECA8E8480A55378 +:105FC00096179870A3EFFD30A8780F795AA820662D +:105FD0000D558ACE5F90C5F3B959B972AE8DD366AF +:105FE0004F0339AC671451E868C35431DFE1A3684B +:105FF000401CACB5AEAAD9D0CBC7192BB6B635DA92 +:1060000028D9939C9E4E25B5B0FE692A062EF6949B +:10601000F964C015230B3B73DF3C19B58D07C375BD +:10602000BB5BFE642506861F1609852E4E887FD22F +:10603000024382F75DEEB990FDB4A1A8E24CCE78A0 +:1060400017AE985F69A133F212CC3D672CCCAD67D7 +:10605000184FFA54AD45182525E3AF576E64E1C6D5 +:10606000F88DA4B871058E17E5D8FEB51A376D35D1 +:1060700060E69D680C63E307E41947F6130E6A8730 +:106080007A906F60E37037E8497DFD4EA8767F2AED +:10609000FAF08FB0EB111475CAD73B5CB492B0061E +:1060A0002F9169212AFCD7488D32BF29AC4474D383 +:1060B0006C21E56F108356A3AF2D91C7C1D487988B +:1060C0004F52CBECD82717524F41717B7462F904C1 +:1060D000D25BEF991069B231F7C633A854BEB691BE +:1060E000BEB7FE5421136D7BE8C84EAB7DE5F23898 +:1060F00080CAF88AA7E232F955B78214EC9E491695 +:10610000DDC129FA2FD7B150B2F15248B8694D5BC1 +:10611000BC1A4373D03CDBDBE317FDFA3D35E03CB2 +:10612000058FB3E154BB485003E2A41DE84F0BC0F8 +:106130003A60E89348238E79B4181EDD2BA361449E +:106140009C51CEC65D278ECC083AA20BA56E401D91 +:10615000DB28F35F875BF33B665FC3CC125FE3C36F +:106160006556120D3164DFE2155DE5BA76A1D8F50A +:106170003971BA0034760C86D08EA989185F1A1648 +:10618000CC83A5E3FDCEF92FB5F99C0426DA43B103 +:10619000FF0BEA03CF8088052052AA78B2985523D6 +:1061A00018E1729530ABC223B26B5A2819BF302D5B +:1061B00020D74176DB563A55231D8CA4AB69482B7A +:1061C00037659A18E7413455E0475DC55AE5868939 +:1061D000A8AD14A7A6A902D1636978EC8D64D77025 +:1061E000EFB3D4DB0C2841E3221E5AA744280A64EB +:1061F0002CF5F4E1B67FB35CB8FEE0D4F3C2F2FD57 +:1062000080268DE997855520E3F0840F2043C4F262 +:10621000F3714ED3DF1BCE8971262ED72F5E974F99 +:10622000792EBDEFC4CE3507E5F33B807997E66064 +:10623000D8F6056837FE405D22594E9C553D187CC6 +:10624000D922E62215A611EE5AB688914DF23ECE1D +:1062500070DA2A60E866F2AD43504781FC98EC039F +:1062600011916389B05AB569100C8F032811A4BF2E +:10627000F928B7BD011263C0C3087091B8F5BE44D8 +:10628000F120E25C849642C4A9D21ED215A93F39FE +:10629000D214E58D571DBEF41817F23D52646145C6 +:1062A0005EE12B80334392B57D1CB1A85CE763436C +:1062B0009489E3ADD6A0C9305906BD7C3FBF4124C7 +:1062C0003E472A7EBBA159A563B5CDCF14FDA65F7D +:1062D000A364F01DA12E8F8C5863215826F2A926A5 +:1062E000F41BDB7509898C71BF9A3D7E4258F94FCA +:1062F0009D62A20DE970B97C7CF281B35462114DAC +:10630000036C8EE8F29FB0842D4F4142F0F72FF7D7 +:1063100032844FD02AA5FA7F668D0757E896C3D1FD +:106320005B3CBA0E144C2BB2C4078A4A19B40B67F3 +:10633000D05545B8FDF16253EF93A62BA6217BED16 +:10634000245B04CD7C2C43C4D7C09EB3D93652F015 +:1063500084643655BA31B7AFBC15E0B7DB6B65B8AE +:10636000142D5D4809ECDD0F6EE7876C0F020CAC55 +:106370003207F3CE4A08476704B65C6F51AF029408 +:10638000DAE3792C17AF24081CE6D45FF05E502FB7 +:10639000C5FB2927904099FA6E89739C00CE648CC6 +:1063A00020CA8BE226DE152DA126A27535760A932A +:1063B00052F5073B9A47022761149A3A709880E990 +:1063C000F0987BF3C4B73A0B2A32684607A03FF334 +:1063D0009FA5CBDD163EAA9DA7331B7CF37237BB6E +:1063E000741A404308B33D680883725212A1CA5E12 +:1063F000351C4A0B6F2A82D5198B87CFDAE1913190 +:10640000D02A2166885704B8CB7A5467B7354C0731 +:106410005125195D57EC2355F23D360D1BB4FD9AFD +:1064200060AFDBFD6A560792257EA7908BFDB3B85F +:10643000C37EE98FF34441EEF73D9E1F92A03BDD02 +:1064400045B23A1794AC52541DA913988B63C5D624 +:106450000D8373B438A9E75F93194F565AA0A585E9 +:10646000E91F4F591C2BBCC49DA0ABD8652717CE84 +:10647000D1A6FB82E9F85A769226844479A1C849CC +:10648000DA4E42EBD8A09F610828DE63ABDB1A1F0F +:10649000B203EA1C4031B475C1A73B063EAE4DC500 +:1064A0007D04F298CB8676F245131FD0A5AE04B6D4 +:1064B0005FA149F44CEB41EC57B1963F3C9FBA21A8 +:1064C000F7660B90D3D777444C2DA91CB5E5DE5B5E +:1064D000753316A993FA606C9B9C0F595B96BC456B +:1064E0002B3BE7D6B81D63213DDD9A9ECFAFEF076A +:1064F000FB3852341342C4F917CF4E86189F1FB68B +:10650000CC3A35E3A895B488A99A118891E2DC5277 +:106510002799842DE0D1FFB3FCA43BDCD1CEAE5B48 +:106520009938B3563C2C10FEBC73C11042BE549E29 +:1065300011446DCB4838226BBB0DF20FAF19F386B7 +:10654000210D7AF69C27E22CC4CFB90A1110DA5833 +:10655000510861F8743111FE0872C28C8BBE045D63 +:10656000988FCAF44E0146D38CD74F34DCCFED065A +:106570000D25141F59A36744FB9FBBD993525AFAA8 +:10658000D6B060A07AF56FBD4685771A17D5FFCFD4 +:10659000EBF20A08808427AD504E33CE8F289887BF +:1065A00084BCBC36191342677A653D815D3CC49951 +:1065B000BBAB0B4FB19CCD17446DEAB539A8A528EC +:1065C000F71C645969876248D984591B92704C98AA +:1065D000C4C524A18AE9AB24AC056227E40778305E +:1065E000638106C761146C7BA0C6A917178792C088 +:1065F000DBC7E39BE610966A3139CE6436812EDC28 +:10660000CF85CE666274BA3CE0411A1F0D73E4C3B5 +:10661000B017EB5BA3994C2D3321B50B0D68F9B086 +:10662000A6D3A5A0E4DDCCCD99C51EBD96F90FAFCC +:10663000EA11B11617C089DAED75CC813690D527ED +:10664000DEE76B07CEF56F9FE14F1707BE9B9DBC42 +:106650008D7378CF5AB1EF8B47E5E5643F3D78768F +:10666000D1E152DEBB4A17C761DAAC87184B330F52 +:10667000824784CD0F4C818B351EABFE1A76B9C58F +:10668000BFDDB2DE94D352B3250B1AB372F09C195E +:1066900087E03233B0B26F2217344CD62A1EB73996 +:1066A00025A01BF901017A53381731D2E2064E9129 +:1066B0003B386A25E6F7990D21E87AFE3821B39D2B +:1066C000A161CC789D2EE32A221871FE4D012B602A +:1066D000CE0803C4DB43F22195DEE2157BD11A7F9D +:1066E000EE6A0541C9A3DBEB1DA442886CCC3E6772 +:1066F000CC90E79BDD9DE5312E4DF4479396DCCEA3 +:10670000DF04EF66FADF710EC92C0AC84B8E7A419E +:10671000699A7692C07125B00604C5D783283328BC +:10672000CF778BC70A79293FE866F2EF2E4D3AF210 +:10673000A5051F644F9C48F9EBE36BBB81197722D9 +:106740009C56F8F53338B0ED19530B443349043CEB +:106750002B7133A8EEFD44AAD0782F0AABDD573158 +:106760006E1F20F4B5C5CEEDE0840FEAAAB4C13D9A +:106770002F9F9A4374A713575BC110B69E2715F637 +:1067800014C363B39347EFAD672EE83E45488F18B7 +:10679000F75CF4296D60F388C67303A87A0DA83DF1 +:1067A000DC7BAF8B9FFA44B61F7B3B3B7F45643F4E +:1067B000647861821CE7303F9A13BB3EF69A9BE5F2 +:1067C000D52062FF71F10D4A939BFCE279A8130575 +:1067D000C22354D59D460A94F099FA6A61865EC92F +:1067E000E91EF5C44D57A2675B988ED2CFEA2AF80E +:1067F000192364A3EBA5BE918C160FC457CA30535E +:1068000001107DFC975DCFC9312082BFBE40DF5FA4 +:1068100014A32E3456B78F6F67BED49FF226DB25A4 +:10682000FF1681CDA59602B962CBB25B6EF6A45875 +:106830000CD0178A47211A4169D6A44F75BAB1EA1C +:106840000A67DAE27F39813AB930F0459B17697DF2 +:106850009EDFDD3787FBD01429D290FA2F9A9D2630 +:10686000FD96D4614DF392BEAEF7B3D73C51F154CF +:106870004E4F14D630C621C6411A745E51B25D9394 +:10688000127C5E681B1AC996D1D75F9BE43BA29924 +:10689000B0C71C7CF62E8E0E2EE2EDE8FBBEDB248C +:1068A000E93839DECEDDFC266343C36FE9EB515294 +:1068B000A035E75163EC13856FBEE39F3B20137A4D +:1068C0006B7A827CC1BDC503FD6C9889EA8DBD37AA +:1068D000528B175268E0FF5D08E33728A3C57A3072 +:1068E000FA5C629F2D0E1DBC50312E735CD9D959B4 +:1068F000FAFEC8A2CA09D6C499103D97E927B8CFB5 +:10690000FE3A4971C4E1CA027E21B60C1790E8A193 +:10691000B0DC1E4EED0CE89C6ADE469E739FF89B31 +:10692000BD0745F67EEC4760D63C96EBBADBF045FA +:10693000D97EECA76CE3EDD13032531461BF20F265 +:106940002DB25BCB176DA3F5005B6F2888DC10744C +:106950004F8F2A9535737D17C499B3C5159E32A6FE +:10696000CFBB4F319E957266E348BBBC0F170880C2 +:10697000A2E34457836E5D97FDBC4B47765DAFDF66 +:106980000AA2F83B8BBE944053B4DEE0EE054952B8 +:10699000B608EF54A36F7080842962DD9D336EE1E9 +:1069A000556978A17A0EB087D37144FD8F0DC771F8 +:1069B0000637CA6CB0DA3B13B1650ACDCE360C3C53 +:1069C00028FC7496B8F79D3DAF518E11592ECAC25E +:1069D000B8646877A50241DB1A2E2F030407E1EAA9 +:1069E0002A513DBCF247089092673FD85CD7275A9E +:1069F000340A2098B9A03D30716E9973881CBD4946 +:106A00006F5B072DAEE73A5A7A01783266B4E880B8 +:106A1000A01FD5B5B5ED0D5473F1473A514616FB9D +:106A2000DCAA9C1F2E703BE8B85174B21BD02A71AF +:106A3000D2AEB2312E753F8056B319F4ED621C828E +:106A4000B8BA236FDDABFBE80624B76E1FD3C77857 +:106A50005FF2732423624EAF8927A08D75763DAA1D +:106A600099763F4E199D0E499E0CE56DA356027D09 +:106A70006E2DEA54CB0BC407A2DF4818217946A635 +:106A80009F8E2AA2CA2817374F0D9DFB8BD076C840 +:106A9000637C6568B5F0200871A25C578D247DE4A5 +:106AA00062A7E0AD48DCB9EC699B477F6E6F690D6A +:106AB0009A12A9FDFCF3890DDDAE66332B1032B1BD +:106AC0009FE36EE57242C21D71C9EEB4E805435DF5 +:106AD0001E4C9BBB6B6C99120780CB86492D0281A3 +:106AE0008FBB68E9764D451CA80AC71A07AD22DDA1 +:106AF0005215EA444A3F4E80D818D50FD9B0511EDE +:106B00003FBFF1E8EBDBBA0F6E50D1A8C707F260C8 +:106B1000C22CC4416EDF173049C1B37FA7ACFDBCA6 +:106B2000CD0326921AA9B2B90A0BC3D3852C61D61C +:106B3000A05D3727BB28E0595C4F6D59B3458A1AD1 +:106B4000ECE2904F4EF3D35297A4FDA76647144949 +:106B50001F623D93A4B6268CD85906753632E8E0FC +:106B6000154FAD14AF6B1547143FB01EC48610838C +:106B7000CC65BADC9D58EF2CD1D18D0499168927AC +:106B8000720931646F97DCE77D1DF847A43EF46A13 +:106B9000562653A7FA17FCE1F6CBE7D84E02A0C35E +:106BA000B35C103803926F95B6277AD8212D5F8495 +:106BB00009E6153018A8DFE5E25BBF98A4B2975547 +:106BC0004D864A34CCACF66898C012D79CCEE0E42F +:106BD0004466F00E79606025637D339D201EF37856 +:106BE00062105B2D191C358D40222A9FFBB03100AD +:106BF000AB9C60D1F8ABE5F16F5D48F44CF5A6387D +:106C000059CBB6166BFAC3179C82CC3E8E88545F64 +:106C10001DF08CAE1407AE6F25384A8B7DC34597A7 +:106C2000858D27041ECB3E401E0F9FE161FD7BE753 +:106C3000DA17CDD9613BAD8829C78E544BEAA58AB6 +:106C4000F401DD85D53FA4D8DE369AC33A7064CD11 +:106C5000AA24315C9AE0BD6AB3D6FD209D47AA7490 +:106C6000940D01ED355FF7A23A15A5227D8A5318E0 +:106C7000B2A2619E4A05628911D2D18D5DDCE0B875 +:106C8000A36C989925518907946C7DE12F0548FCE8 +:106C9000BA3366A46C0730D888985BC31898281F4D +:106CA0007A93F856486ADBF19B72F4F6CD3D5CDED0 +:106CB000B30785335CD8BA4E7561801CF879A67726 +:106CC00039467BE6DC9E80D11B49E51AE206126A52 +:106CD00068D2E673799B8C712E9E490D38EB1E4A63 +:106CE00071D9D8699F98BE1CA4B5AC4EBF57BB0DD7 +:106CF000574721B87112D44ECF8E3D55F3707AB2FA +:106D0000548CBD0072E939290849236B3C536ABA97 +:106D100051850D10DD36C7EE204FB3033F99D86083 +:106D20007481DCE57DF96995681792DEF629E872D1 +:106D300087A18530FEF68C588022AD2289B7319626 +:106D40006516CD92D91FDB93F12769867A1877F300 +:106D50004449FA802DF6850B820A8D7066354CFE0B +:106D6000B61BB1104B5378752069F202642EB594AE +:106D70001F826FDCCAC713B22E1728743892986F1F +:106D8000DABC0384AD2E9A625858CC3B0AD4FB1669 +:106D900045BDDDE52B0B18E1E2FC189B4DCD26A986 +:106DA000388105CFA3720901141A794EDB1791AF10 +:106DB00012426BF3CCB94E967FF684D8F7C116EA2F +:106DC00055F0FE0C0CE5FB8333777F47576FA96DB9 +:106DD0009FA3D43F1866B0ABC0D3E984355ABCA09A +:106DE0008A3B7C3F51C0B9F62FD493974BB1F09DAD +:106DF000840DAE04F181966AC2E5D745FD7FBDC61C +:106E00008BD8555FF9F5CD98CFEABFDD0F4E5830DE +:106E1000293D69155D2E8C80B43A3AA94CAFF4989F +:106E20004E58C3865D9AD82919048E952A6C590745 +:106E30008EAC114913E62D5ACD4FAF8592515D7539 +:106E40003251624B12B4FAD02FA4077F62AC9DC7B7 +:106E5000D4E513BDDDF2D4A1D3DA664F4BAE9F9FCC +:106E6000CA1EFEFE17E1F60C077E6FC118CBA3EB1E +:106E70002998B039130AEDF0F4F838D6464B772448 +:106E80009D38C3534EDB35F9E13D17513B9E686C8D +:106E9000BF24CE0F6164741D41A23D2E3E8650BAC0 +:106EA00093E282DDC156742D09C21C60CA76F95E78 +:106EB000E2E3729394D5CA99B7E499FBED22258653 +:106EC00002393259FF02307873B6941266C6EB3934 +:106ED000AC0B47131289C578B1D4ADACAE927F6AC2 +:106EE0001EB118D464EE39574F471F11A4E464FB58 +:106EF000D2269F4639D395ECAF5BC4E7F0E25AAF98 +:106F00003EA8FA5DD9E868A1E78DF4378C08732FA5 +:106F100075A3A9152F87C5C8D689107A773179E767 +:106F2000404EF10A19DA4DD2A61149DEC35DB0EC2C +:106F3000306E541FC6333AFB61B48F647657CF0E60 +:106F40009A18490B3445696A435647EC9134E2D9A3 +:106F5000AE5D20CA3FFC45055C0068DC751028DF8B +:106F600012E9F9A6D83FD54615FE93529F94BD8FDE +:106F700093C27B346C00D8A8F37C7E339E367D6749 +:106F8000D3FEE9B7703A65EFC3400E14BC264594B2 +:106F90004557971825E48B440F6ECF5BD349B2A6B3 +:106FA000C5B018A71765CFB824CF5FF6F13676BB0A +:106FB00063E8B03A7D98B3A52558C50E171DFBC7E9 +:106FC000341F85E92A14599AEF796279F95393505D +:106FD000A915D690DF3A1E82A6188C7AFC951F75EB +:106FE0005CCCD700D2F6B9FEED55AC8F9C51BFF604 +:106FF0002D2D4BED99D5726ED82F0C88326FC7129C +:10700000B5BA972B73CA8FF856B817986C85A987AD +:10701000ABFDD95EB073F6B17E7FFC33CA4A074838 +:1070200000D9840E796E7B606ED68833230D66227C +:107030006A037028F8688F28DB68FF4D72CEED0672 +:10704000FACF54462F684A99FCF141D943119C5913 +:10705000AA08FE9707DD5A485532D2D2600E701C3E +:10706000418782E817C97197BE6FC96AF293C577E5 +:10707000649A9A5100DE1B1834D48EADECAE072F03 +:107080009CEB388FB5DB7BED662CDBA6D01290E84D +:1070900047A1D6459370FF18C8094C89ACD6B4DA1D +:1070A00023E2A6F03F37DF24FB89C724F6A8F6AA1F +:1070B0002C4D745E497A82454CE45488FD1EEC4D9B +:1070C000572165635B0A105956E71E65A5D0DECFD0 +:1070D000E0EF94B2BB0A8D684F789E257AB80D4ACE +:1070E000F4ADF52ACDDD7E2FC3374CD0C12647093C +:1070F0009E131894BC72FA7DEDFE17E53E27A97F1A +:1071000008DF733ADF3B4721D2EABF8274E5AFABB9 +:107110007C6C2CCA94691663001E9FA26103401DFB +:10712000ACD2DB6906D600D63C81F4D1E050E30650 +:10713000CB838BE9F67721F125C958A9C56F67ADD7 +:10714000A4389253D05BF981CC9596D41544ABFF0B +:10715000FD651A9184121B2631069C506A756724BE +:10716000BB4293824CF620E2852802D284327ED83C +:10717000F2A86D00FAA3B6E2D01C41FC50CDC5A325 +:1071800079E914FC4EA5EEFDF5CEAD1F40A2772D9A +:1071900026BD9922D4BA45999AFE7B29F9099936D8 +:1071A0000C82D6579745A85F636B3181B70BEFA070 +:1071B000ACD4AEC01F5F03E88DFD215437EAF3CC99 +:1071C000725E0FF8F609D48690A176A45FF9CCF828 +:1071D000A0D8E51DCB4E889C85530C0D1C64CE2990 +:1071E000454F6789D071549E97957E7B231F7F5AA8 +:1071F00059E492317AF0195F9026AB850D9E2A866C +:10720000F019717F4EE9F73E736F7C939DC38364E1 +:107210006E9401299FB74C16BEF237E9A8F97B0F8F +:10722000C6A83414DB7BF225B4FB2BFD2B82DBB824 +:10723000BD6201094A4ABEA8EA13C5EC014A695475 +:10724000990EEBC06668418C5B7FBEC48FBBE36B5D +:10725000589AB55612B34D679DC45C5DACD0D05200 +:1072600060BD6D44A07A7936DFB69ADF3258A31A32 +:10727000E72E58F51C21B25F2838822AFA04375BC2 +:1072800002041CFA70DFE9E557AAE626835755ADDC +:10729000F9BBEDBA5A55BFFAF3EF08BF25005BF012 +:1072A000682FF4789E111500AE2D88D6741B4EA65B +:1072B0000AE71044B596844EA5793093A4D21EE116 +:1072C0008BA26EF1C4830EDFCE470477B717FF2B76 +:1072D000630EC9D3F37A94344F8EDE7F16161E6781 +:1072E000A399AB55024795C3A1752DB85C77D99B7F +:1072F0008044F32847747AD214A5508663060D2083 +:107300007D206F6A0C7617AA8CF2A3204E94D94385 +:10731000CF7EDF588246324DA416D0CE2596D0902F +:1073200003DC755533D5E86A14CCF6B98E58D159BB +:1073300002046325A9D7D98A84F017759F84F43D88 +:10734000B560FD6646E48B9428E97F417F1F6307A3 +:10735000998551F5BA05FDA7700B9F970A57B80498 +:10736000E3F51013C9AA9FD127420769A86BE1B0C2 +:107370009FDCAE8BEC4D4181A33C7E09CD8A3ED68D +:10738000B54190B6BC775BD7CFF1F6C0068639C65B +:10739000ED55A01B7EB7213C7B0F5F8F9BC7C68C32 +:1073A000E8469D6A990FDB0C6EBF010E11C0937603 +:1073B000E264AA79700243DF41BF4DDE6A6640F69F +:1073C000855926638CDF810E1529C31AAF8E4BA217 +:1073D000138861E80005B73102DDC952CAA1DC2972 +:1073E0009C82750410CD3EB2B6ED8D77AC176D70F2 +:1073F0008F8ADB2EED56D36DE00EA49832AB465D3E +:107400004AC0386F5AE6B918A830D0EF01ACB63A86 +:107410004E31EC1CCFE17B3EE0E3E87A34EB26F919 +:10742000D97D3987770B78B5DE2D003243885C81B2 +:1074300042BA048EF7E58520028DF19F5144BBD3FB +:107440000BD494EBB558C07B61556157511AB62DDA +:107450005BCEDD3A17C83B7F69CBA252863DDDCCBF +:107460000B17A70E534E1CCDD35A0D274C27641F64 +:10747000EA4A148D571ADD678C8F3F4E06E36B2B5B +:10748000DBF6F6432CB74D57A07F3465F3D49778DD +:10749000A3B9B9C2EEBC9CF0EA6D9B1F95189B99ED +:1074A00050B9AD38A259701019301CA42E9C8B0E07 +:1074B0000134F2EFC500273F838A56C49F765CD023 +:1074C00020F89544EA35C5B65BFD38E86FAD6492A7 +:1074D0003632A467BA39E76B683BBC3C91EFE3E90D +:1074E0000A64DBD3F6D11E7EABCC4D354B99DA590D +:1074F000BCD2D8E861C61C16EE2D9AEA798ABD8600 +:107500002F38D542F8886600B3E19B4D36E2EE3065 +:10751000F16831150432E5FEAF021608A343C60731 +:107520004704D0BBFC134F0926FDA721540D52750B +:10753000BF388A4EA1F6CE3DF853A05034D25A132C +:1075400010E484150F0727A1671C6CD8EC6B9AE92F +:1075500057447A6797928A3940347DE6C156B6D946 +:1075600059C6CBEFE72B4D1F845151A3DEBDA8199F +:1075700034986770CDC4745FC33B10CEA35FEA9CA0 +:10758000FC9983DE076EC8A30F6A61F04B96D8B4EE +:10759000F3F67AFD78D8BB947FBC583DBCE5FDC6B8 +:1075A00090A90F10351029FE49F745161FE3F9FE83 +:1075B00039EA59028B61850EBF40328F1663908085 +:1075C000A01A379C93236B86F025A5DD7C99DE36C7 +:1075D000D2BD9E06DA46CBAED3D2004BA742971659 +:1075E000677F28981E855AE9FBAACCF0BA52844CD2 +:1075F00006647FAF133B516AE30939EBBA86D14881 +:107600000C4674B7F65BC8FCB2B870352B623A5CB6 +:10761000EAA971B8BB79806361EE67456C14951572 +:1076200087002EC643119E979F6596BD8920335DC6 +:10763000B8205816A7AFB02B7A886C2FB1126818F3 +:107640006DFEA4C7F23DBCEEE738EC2E43350CF9D5 +:10765000CF7288A3E7B67EECF7087FAA831B5B9006 +:10766000CF74F729981BCEB3D589A95B1071C218C6 +:1076700019BA4BF47B73DA35BF3F1F18C88B8E6A7B +:10768000650BEE6990554CAC823E5CABF1C23ED6C8 +:107690002FAFA8DCB2B4CE922806B70F76BA1D136E +:1076A000E44CC385181D4A49F68987AED411D8CE5B +:1076B000DEDE6F685233B812FFE0847B9D568CF299 +:1076C000A1EBE2B86343AD62BD6F7F8489AE3557ED +:1076D000E2850BC730F1A1762D4BB06A5794810536 +:1076E000ECAD8712C98B6FCE7543012FFF07816404 +:1076F000094092F90F36BA96BE91C01A6FD823F995 +:107700003339DB0F25CFF3A218053ACFCD209B5696 +:10771000753C65C264FFBF198B7788158E1AD89F98 +:10772000FEA862BDEF6CD4FE6035DD66BABA786D36 +:1077300027DF6AC4D27A4B77087A142553AE1ECD60 +:1077400033408E54ED6D56D301D3A452BC5E18EF76 +:107750008914A924AA2520DC999CE0BCFFC1E9A4D6 +:107760000AC13365106CD59924B44CC082C32E97DE +:10777000A662202D6DD495FE82715AE089C86441BD +:10778000666E05662C8413B53893FD545B2E1AD2B1 +:10779000086497132FC588E41BCAB557233FD4123A +:1077A000BE3A88BB937ED8ECD7B1557C3A5BE5BA3C +:1077B000212CC6DE13CFE434F0E1E3C40EA3FF3C7A +:1077C0006A5C99D2F427571D942AB15D9D6DE63FFE +:1077D0006895B99E9609F1E4826A26500F3A548F53 +:1077E0003BBA5967E4CA67B06E4B7DDC4092688D46 +:1077F000CD45BFD4FFDDAC7C0EEC0B1DD1DA00EC27 +:1078000076C1C0C8F0D8B7279EDCA688C970EF53F0 +:10781000A418FAC3698003F9B3A8D544F173C11061 +:10782000A58F8AE12F5E033F7A1E6F7D9A422E4C10 +:107830005BB0BAE13A6FADA1DDD03C3551097315AB +:10784000AC174D9F9FAF802C3039B863C693E8F8D2 +:10785000327EE38A0BE1C1652D83E82ADF1107E25E +:10786000A09FF37CC5A89F1A0BFA93F377F585BF09 +:107870007993AF0CC7917F7C854020F75971B61F73 +:107880008190A5319E035D4EF56C7BC313FCF680A1 +:10789000C2E3CAD3E6E57CFCC10A42432A1391C481 +:1078A000462CA32050C2B39F698E4AD1B19A7EBBA9 +:1078B0009AF6B3F97FC5C4E777F39532945952210C +:1078C0009663E129211E57AAC10DACAADE1BC32F66 +:1078D000FB3833D8478FD49F3947DFE2594A2351C9 +:1078E000392B93B735C0B5ED14F14072B40C532267 +:1078F0005D250D5A77A1C9D7BFB0B95FAE89945F36 +:10790000580BC63356A1E56D3A09D7EC7A5F58A7F4 +:1079100061CBF847663F4A1C643306E56811D9AF6E +:1079200044CB3385EE151EE4CA142103B18B2682A5 +:10793000B9CB294CAB65ACF9D0A25EDC0841FBA900 +:10794000798E7F3C9D3C009C76055DC64E45320994 +:107950002C72532C3DAA201E42C9AE1BECD1D9C1BA +:107960000FBB3C272E022F8B0E5CE5F879478DF775 +:1079700019597E55274C960D3D58C443166AE31F8E +:10798000A91B9AD88F3A88C2D07A4D24C0D07F7074 +:1079900028FC7FD559C4C9577A6C596A476607F4E1 +:1079A000B502EC1D5780FDD1E00383992F4D0BA448 +:1079B000C60D120D9D1B4C5BC5B8AF669BAFF61B89 +:1079C0008844A4EC6D4DDB16E70D57717B2F8F9724 +:1079D000A8806188FC06987253CF5342F286101833 +:1079E0006ED902AA458C036D497CEB6A0CA80CB9D0 +:1079F0002EEF199B301AA33F678D9E4B0F2E2260EE +:107A0000A00FDAD570B359C1A9816E0C7E6940F41C +:107A1000E9E3408F0918F5BB0548F00E731F2749AD +:107A200086CE9740A2516029F4A48ECE515AEAF630 +:107A3000BF35E78B3BC50E7BDA2D907E4965B330B1 +:107A4000F58F64645DA1DE3C023F4C8DA6F8AA8EE2 +:107A50000F78F48DF94E3D7DD4701D70EE3AA6B4CA +:107A60001BFF6210B8F9A88629E095F619A13284A7 +:107A7000A07D8E48136E37BFAA57E16AC670B64222 +:107A80000B91BAC83B32D974C981D3252C77C5393B +:107A90005C43B50EB751E9C4D5644C541035F65863 +:107AA000A927B418DE8739A427459AD6D47D6A94CD +:107AB000E7022A48B6B8E1A8489E08291F46295778 +:107AC000B8F78D09FF47362205BC46FC982C175F96 +:107AD000F29E38D9A65D47274BD8D92369290B6474 +:107AE00062751E2DB48971F71ED32D6E0E93B99950 +:107AF00007BCCC4DB9D037627CFBC1E2B0C2902745 +:107B0000BE74C86DD1BF6EE03168FDD669D7DC8C1C +:107B10003E9010A5EA5F59EACF78EF84854486C489 +:107B200052CD363970EFEAA416135F27D148687931 +:107B30009004C614DD6310D7440F65808A419BFB17 +:107B400070A3F315A2DB7E849760909885503C79F2 +:107B5000EC8648F5F1D983DA26D048781B74266183 +:107B60005803A64012C51076B88F58B51B3BF09746 +:107B70009A82972CC533F37EE8FC3D0F18D35D5FE6 +:107B800078EFAC3C1EDAD0C58545BFFF4F489780E3 +:107B90002161B2366A5884D18357BF49332A1C36D3 +:107BA00043970EC25C77651DC0A26906188C4A55C2 +:107BB000A096D54372D4F2A23CAAACDF9494B5D17E +:107BC000834804F98ED8B14C8B6D37CB5D90AC5D9A +:107BD000E3CB660BE9E60EC170CC496D16936E8F50 +:107BE0006EAAC9912843E74F0442C89CDAE0CE2E22 +:107BF0001959E2E0694A228400481B1770B57D14C8 +:107C0000BCA97CBF145F1A5E0D8821F085FCA51607 +:107C10007DA7CD7371623C8A36D6A380CBF6C1BCFA +:107C20002CAD2F1ED23566221A9234731393408BDB +:107C30006317DE9B9592C833E07CB49AA17B726D8A +:107C4000AFD062F69DCA3E245348231FF7025DB9A8 +:107C5000698001DA7AED12F2398F1CDB6229D15585 +:107C6000C8BBFA41E52530E8E8542AE517C352D9E4 +:107C7000F35A24FCD66D98FA38EC55EF55B20694B9 +:107C80001EB81F87CADEDE3F0AEED5322E33E8A9C2 +:107C9000EB97C89E61CBF3F63753135D8D7370B0CD +:107CA000B93ECDCAA41B0A4F276EBAA339D99F8DFE +:107CB000A40A1B7F695B19D4D04733C424A15B5C41 +:107CC0002222C3807B34E34BBA513BD5DC4DFCC44C +:107CD00052F2C59C9E1608DCCE51D9DF0AC3D17979 +:107CE000470C6B9EBD6BDC015776DC17BA5ADE5D24 +:107CF00032343CE2B6497479F8946F9CB3F2A779B8 +:107D0000702D922497D2104021B0BDAA5339019012 +:107D1000C8AB02DDD658AD63AF9E42BAFD9708C628 +:107D2000B19C5ACB8928EF569044B04822987B48A2 +:107D3000479E61100322E1537BF000729ED966EFEB +:107D400002B6F32373AA59E6CAFC84A7FB5ED4C526 +:107D500000C3D26145E877FB5C8967185019D632B9 +:107D6000A8DDCA3E310F1827848AB1525561CE5919 +:107D70007E0F3E1FF727B79A231606EDD37FD41543 +:107D80006A5CDCD6EA5D4419DA427F8B47459FC2C4 +:107D9000C40BCF34BC86E70921F1C1B4A8C16AE2A3 +:107DA00044463A8048622849E8AF1F28F75640E425 +:107DB000DA13F306AD500B9782EEA6E4B4792733BD +:107DC00026E57392412AFEE63D1F9474A8D126BB96 +:107DD000E07D276967AE1FE852F61F37FE5EA7D623 +:107DE0003E379E39E492E038FEE21393DBB00C6636 +:107DF000646CA2052CF029E64D0F697F409A723F12 +:107E0000D7FE5D1F1033303E1E499F94AD7640D2A1 +:107E1000809EFADD8F8B687E1C04779C63BC2DA34B +:107E2000C03621F8A7C7A3F9D9725F159517E6A93F +:107E30004DD7198CD96C6D31E7779F238502A380CC +:107E400050CF851C1E8DA5C52CC3D46EA9FC040C77 +:107E5000F5654E2CE509A260A897E53CBB0E0A0625 +:107E6000E3B2E16F580977D745EFA981DE63DAAB5A +:107E700094F3F3E0A182CF356577F6DF8FCEE28908 +:107E800029BF6FF6C0D75B3A346827BD69F28DE72A +:107E900075AAB09F20A2930DBAF47A34BD410C3973 +:107EA0008E1CA87F8B0A9EDEE3238F4AD521714E5C +:107EB00055F0A8C407429668290291E32CB67B6C62 +:107EC000D1255C943FABEC045C29D980D0AACEA626 +:107ED00014C8668D8F9FD41687C1D9E58F56433558 +:107EE000E39B06E21EDDCF31D4223E040C359AD747 +:107EF000A35A45946F41016D22AC2AE51644C65D34 +:107F000059B95AA62D1782197FD8DD2EEF644E95E8 +:107F100004A5D30F5B91D0162490A421A749FBFEA2 +:107F2000118702D08023AC2102904CFE58F86FECF0 +:107F300011993D88A30F5E603CAE2402A7C06D512D +:107F4000D78B3BFFF033BB2781437154FFEFF4D154 +:107F5000928BFF07D85DA8DD4370F103462F7D9A11 +:107F600070DF7CE528FF2DCAA7E885F429A976E50E +:107F70008782FC14E7366BBCDF3E9E1EE633009919 +:107F8000EBD1DF05467E66AB9E6ABE48D85CB56A1B +:107F90004F209FFF11E257161C66E6970DB9C55E8C +:107FA00007DD4F089667A396A8239740CCAAB9DAB5 +:107FB000D28617B08333B744A324C48C3D1D5C4BD9 +:107FC000E57576062E747EBD84A55D15BAA79EF173 +:107FD000A9BA49A069B6BA068B7BF682ABAEA7C335 +:107FE000E30CED41B7B0CE35729F1375743F68CD89 +:107FF000ACF638B90B515EEAC09E4A60E0CD4EC97E +:108000001A422D25F81D5AE6EE5E8EC667EDC93A76 +:10801000A9BAAFD0C0AD32076537F82428F2AE9ABE +:10802000B29CE5C97D55AE46FF91E8CB1E80134951 +:10803000AA715D695584418AFCC48E3F6DB30741C6 +:10804000EF516669EB6404FE8BDAB1E327E08F2D14 +:108050005F37ACE299A5E6B822C4048B670523EF2D +:1080600039C8AB5F4267751DF3A7CE8C14F604D1F7 +:108070003BB43EDEE472CB77C63608C445B01EC0C2 +:1080800035A30E360F3B6184607D5B04B65323102D +:10809000E345445F1996BC690D02D61E4D3AEBA626 +:1080A000537F055C1CB16C1166C4984D77388F5AAC +:1080B000636855A7CE708F3B89CA042C1331778330 +:1080C000014B8C71704088D29C48FFE3C6A7DB3D12 +:1080D000A981C81BA9519652B2544B84E6A696DBDF +:1080E000519F4A44FC4CC3056C66923C2A4110C225 +:1080F0004A915E483FC9221F4DB041F72612FBD975 +:108100006E9C36E426D8CA6B9B36AE89BC2892A8F2 +:10811000B02081B1EF92972908CA810F53D462F140 +:10812000FB94BE687B4C9311A9AB89FC503C7A1D33 +:108130003FBE30AD80FA32313E61EBC97AC2363E85 +:1081400024F79DA0908CC02D8A1D015414DD33C8E6 +:108150002E7C4FCC9BA5A98F5AADA6AB7F55A2F024 +:1081600060ECE1588A6642A6D90D9CB70AEC927879 +:10817000513920CCB27013D032DD2EFE9FA1E60320 +:10818000D95126EDC3D46E1072990D20977669529D +:108190001430D79192F0B0C81F4979A17DD4658A77 +:1081A0002C93FB8613A043FA08A6D880B271E05244 +:1081B000C4A892795C28A5BE5620E7176395BFE74F +:1081C000FCC92D8BC99BB8BD3B8AD5B3F9706E39FC +:1081D00096FDDB17E3CDC95676E35C0A1A054E71AE +:1081E000B355171A9A434720D44CAD9D5CC7DA0C9F +:1081F0000804A392A387FAFB04BCA87F34C9D15119 +:10820000E1C0136DF3035E24D22DF277D520233D18 +:1082100094096644DDBB41E3AEABCE1441B8EDED4D +:1082200083900FEEDF4EF60EE8BF25E5C658FB2C17 +:108230001E7D3A04A276187656341E7E54DB011554 +:10824000515ED5F5BC8DFD966CADC3AA4F4769FF55 +:1082500085BA137F5FA9DCB7D21D509B1B2777A778 +:10826000020F9A7D273DE2998393A96C6CE66A4FD1 +:108270008A98425D3F13BED218618D57D2FB5B597D +:10828000A25A66B98CB278072754E762A73F31A794 +:10829000BA855B379B485D833F39B10CD65C62E69B +:1082A0003CA934C949CD4F1267FFB094D9DBCDF05A +:1082B000E6B4D9699075421E044538CF8321808D7C +:1082C00009B3A0879B36906F731CC8A076457109CF +:1082D000EC9501789F1FFAB8F0FE093E3D43DDB9E9 +:1082E0005B87A7C8CBF109B29B5509FD6C296FCC00 +:1082F000775D6556F4DCCAD1346DB0046756D2346C +:10830000B3F2ECDEA4AF20D1DBC59130627F532BFA +:10831000931AAB4F732C7CB0C3646E1CA8416C9C49 +:1083200078DEBF63B7F98198F33B243F30EB83D904 +:108330009B46CE90CFC506F5E77E3A078B99606DD8 +:1083400021C834EA1BFFB305A7E6518E90229105A0 +:108350008861CDE6501D8F5CF3727F0D3E0AC937F0 +:10836000D2337CD7DF059CBED28AE37F258FA768F6 +:10837000046CFFC83AC34CFEBBC7D6E1B5F0C36579 +:1083800034E60840242D34124902C0963EE303E04F +:108390003FFC2C1A976D71F127C7A1B214BDC9BE5D +:1083A000E48E3C494CD258CCA2D394CE859FD54183 +:1083B000A1B25AB3CAB7B7451B304A6A7941782A85 +:1083C0005746D2D9CFDC68C347B9CDDC41591D2D02 +:1083D0008C82BEC026FC4845494BE8AD0838C21126 +:1083E00030BFFF453E2B00522678FEAE8EFC353C5A +:1083F0006F682A41B608DF7D11FA1EA6F1EF7400FE +:108400001D35C37209D80C213775A58879FAB7F4E0 +:10841000501B3DB0D147F5D3C062B2B11C9105A944 +:10842000C44626C382D74E07D7E4D03DFD09E2C635 +:108430005B3493FBED769219E5BF2A4DDBF22C9C61 +:1084400005CE92F9F2418C68DF5DCA5DAD281F440C +:1084500044FD42A40264F16DAEAA626AE341B31422 +:10846000430592A2CE355001BE7EA52D28FB782E65 +:1084700037ACC6EB9876F89421157AE6E3050368E5 +:10848000B2A73640C3DECD16DBE12F8DBACADDB20E +:108490004A93730187121273513B790DD3DDA2CE3B +:1084A000FD333CE605152469CEAECC7E7E2ADBEB9F +:1084B000DA7BF07E15D1549F1BCB9F18A7A0C07FFD +:1084C0003EF4EDD9F71DBD32F9E415231D0DDCB1E5 +:1084D000E041045334AD41A601BAC4ABC9D15A9DA1 +:1084E0001687F7F7E04C72DD77BFAD8387429FD8E0 +:1084F000CB12C0EF9BFDC8B1308A632AA02D047255 +:108500004DB5E1BDC635FAA12F1FFFCA76C447C8D5 +:108510004B5D65C0301B07AAB9AEDCF41837545E5A +:1085200073CFECBA1D4C73BFDA1234BAA1682800BD +:10853000A72330A99E45C346CC96F7B469E3417F93 +:1085400003CE6E66D1143DD3D91C831E66A4B08BB6 +:10855000B3CFF41A326023A16CB2107C46C1BA25A5 +:10856000E64A9855706DB9AB09A7D42B6683801C79 +:108570009B1B22136EF49A4053866059C8531151C5 +:10858000F79976A83989D4F22549F4F34634005690 +:10859000918CD986FBC0207D59C141FF96C920FF2F +:1085A0007FD57694A339C837C51A4E51CFD94153D8 +:1085B0005EB27DE97DD3715D7C93901D44B1472906 +:1085C000E59C90CAD8B37BBFF5C4DCCE4FFB47A86F +:1085D00044F8F2365CDC01C8B99A9261ECBD8C2794 +:1085E000E3F9817536238D2E4A9827EFDDC6F745CE +:1085F0007D39057D02B287D967664A67AA261B8F37 +:10860000456D814883C4228C86FC3D43E58FFADFAB +:10861000CF15C65D26C0964E285EC90571E7AC66CB +:10862000C7F736D1F046B0F5816D704A1E27EF646A +:108630003FEEA06959B12FAD36F6D6CAC2EA97EB24 +:10864000F8B17A04F307EBD88968AB987A9F80A5D4 +:10865000F24B8114E394185B0BAC209EBDE07ADFF3 +:108660007E1E50A2F21F4A68EB85AD7968F3F1BF18 +:108670008E55C6C9C1E202AE40AC62B049FFF86C8B +:10868000043C845F87169C0C1F0A2F64F96799339A +:1086900061A5E8659B52B43E119C8794227454B244 +:1086A000B1710470A656AA628D134D260C22A1B397 +:1086B000582625FCDDBA1D1EA54CFB167CA093B4E4 +:1086C0006061351EBE9A999C88ECE2F6FA794B9966 +:1086D00061F18FF450DC065D3F4BC61A552A998D27 +:1086E0000F6CC62BAD77C09A9D4B96BDAAE64D4246 +:1086F000EDEEC56CE2CB07A631A9BEC75C56B9D674 +:10870000CDC290886541D82FE11EE5D3789652C539 +:10871000736442B5E9CF839BD5E0CF33540862C080 +:1087200055CE9959E09AECFCFE240FAC005BD33790 +:10873000EF3151DDC1AE0F72CFDB978B1465D3EFF4 +:10874000F623ED0483FB4B4A3244EF7E95E333CCB2 +:1087500068749EBE072E103AC5984A23EA7B0582AC +:108760002B3ED02440C73B35BA788237FDCAA32EB2 +:10877000AF56F1D282C475B7D2A57AAC7B1857C573 +:108780004AB30487874A0B939E10A1DE2BAEC68D99 +:108790009937737E9A885FFDA7C0AF153DAF05A0DE +:1087A000B7C75A722497FEC00A8779323BD498A97A +:1087B000FE522C9F7F1924183C929C98C87006A5E5 +:1087C0009C29EC4499CAA72B9DCCB03CEAE295D4F5 +:1087D00046584C7EA14D7E8C1FD229189247D9D97C +:1087E000CEE90D97EA359217C8E5F23845F788FBD0 +:1087F0002A6431A1B67803A5B756D5C74BCB720909 +:108800001887F8B9CC41533237DA205F7D5193276E +:108810005DF31C7F3F4BF914A005FFB1A3D886FC84 +:108820002B2199E4BE5D2DF8E0D465B4FFE528194D +:10883000C03883788FEF0217EE285E0DA16CD9A7A0 +:10884000E7FEA89F22BEEC92096C89CA15FF3F562D +:10885000C890EFCFC50F90A30952B8702A508C77FB +:10886000D81E2B82E8F10F3F1145F6365C8427F2C3 +:10887000603FF567A948952E817831CEEDA03DEA9D +:108880003C01B8EB4D7BBF97E370B49187572866E6 +:108890005521B8B33D3DB71648D14C13A61AA026B2 +:1088A000B337F0C7262E2F5F44045D3FB0567CCB14 +:1088B000C53C6990EC957A0AA534D2F13494D6C0BF +:1088C00086D4DDC78E3AD7F023840E995C886FD3A7 +:1088D00008D1787BBC224D355FEAEB1F96B1A6121A +:1088E000BBA96D9336CC0FE7DB86188AADA0795B08 +:1088F0009BFD14B5A43786D2DA4C70F766A1436E9F +:108900000E19524EB7FD0D9A0D6044B13229ADC11A +:10891000420BC25DC9D6F25C81549FC8AD63A446C8 +:10892000A4715681C14DEC8AD4CD3465A063437DDA +:108930004FD89D592C3558C37164E9108920A8F689 +:10894000F9AF3C30EDCF1DE801C0AC0C68CD8139EA +:1089500055A8FD4B8537516B2E0311AD2D0F745C5F +:108960007FBB3CD44AA836D3C6F5C57FC4BC37F616 +:108970001D225A88B71C6C27AA8AD8D458A2A50CE5 +:108980005BE8FDD366536908F387F11DFD21607331 +:108990001B07348A86184E7FDCCC35207E1BF42AD8 +:1089A000C8580FCBAE5150EF3C401081365CF9D621 +:1089B00018A13D4CD6C8836C5C755802A92A539DFA +:1089C000ABC25F6E328E9DCB221CD415C8BC8A49C7 +:1089D000E7A2E762BD84E48B0A664F359B36086FD9 +:1089E0001C73F622262FB7BAB96B6FA8B8C4D80B80 +:1089F00098C8C45DD08B5724AA15E88FDF3DE75691 +:108A00006DC8C27060B42314D940439C095C1A5CE1 +:108A10002CEA01D779175E955A1A16324FDABF6BD6 +:108A200010616D0C5DBF21DA41E3CE0551A23B66BA +:108A300002C0D4E0E4796285AF1045933413C6E8F0 +:108A4000BC8467EEC56FAB0F28719638ECA5D92EA4 +:108A50000D5BE170AE31174F6112DBBB131F6596E2 +:108A600076163481E91A1018F1F9E8D354E6E7E5EF +:108A7000CFB4C701BF001E80F919C5A1D7E9CC55F5 +:108A8000718FDBC020ED29F400466804BDD6B75BCA +:108A90002231D37CE64C0C8F754C1A59F78C564416 +:108AA00019D0198CF70C43D019FDC8CB19AAF5368B +:108AB000D497ABFB4A0AFB36AC4CD877F50C1F2099 +:108AC0001AA1B09B21854769F0B67AD74B355C3740 +:108AD0004D814899534992CF9D3730032F0ADD17B6 +:108AE000EC0598E21CF44370F4D57672809C245C0B +:108AF000D1FB6D13E88552C2518DDDCF85D821D3CE +:108B00009DCF81A02795BFFEC3355D364F1B7BE708 +:108B100045C896E18BB012BA55315942914BA3EF3B +:108B2000746312382ABEA1F67E8A498BE9EC72562C +:108B3000BC170CCBD8760DD01C4A3C623B6EA13ED4 +:108B4000D5818CD296001EC39AB8F87F119E3ECA7A +:108B500097E13517482BDD9257F93A252FA5F234C6 +:108B6000B3EB43EEFFE53C7B6D8B6CE38ADFADE658 +:108B7000A646CF361DE2048E68DFB8EDCAE4B6D64D +:108B800016895E979BF9612CA96476B1D25A34118B +:108B9000E5415C2DAB7C4BD70337D90CDB6445201A +:108BA00055712511B604C8292F891BF21E93E7665B +:108BB0008EEACB36EAC10BEEB3C609DA085EA8F737 +:108BC00036CF1E0AE7628412E679E3E9CD59162E04 +:108BD000FDB253D33D3EBD386244BEB864AB653090 +:108BE0005AD280110B6F64FF70BB5356002FFFE504 +:108BF0003552F210F504C2567C7B1556D645F4FA70 +:108C0000E87F1D7F3A4AB9D2A3AB59F38FBB886086 +:108C1000B6E6D11EDB6742CA97FF6B3CCF2DF9FB4E +:108C200012333B44B9F6FBE2E5E9C62D3A86091258 +:108C3000CA63F7B9F4F80F40279B7298A845AD7046 +:108C4000E75BE5E20A35DA886F564354904D163BF0 +:108C5000C526401F59214311B311DBE004C5DF34A1 +:108C600051865A5B4BDB8E1841DBE2BCB96B692A3B +:108C700084DF1CDAEF321397271594B3B8D01B4268 +:108C80005B1C182B7C1CAF31E8F67B85500B6E65A6 +:108C900095E72D1DE92936E97D560DBF1CF8144DC9 +:108CA000DAA281B75752DC388FFFADFE1A5CF3C4ED +:108CB000ABD19963628A31C1D429AC9B0A919BFDE7 +:108CC000323C8CB5C095E97179997F2DF6485222D6 +:108CD0002D090DF0F62B6CDBA433BE65B3DFCF148A +:108CE00082CFA99444739658B20135429017F03858 +:108CF0001C7620052A91568D9367D3A5075A4FD32A +:108D000053CA268E0A7610667ED523C2F3F7D2495F +:108D100099828F908A51DDEC07BCD3D3B2FEF4E781 +:108D200080EB4B104501A92B8701F405477E6FD6D8 +:108D300015694A49A1B19EEE983599456BD145B167 +:108D4000554B78671C2E90A40FD1EEED7E999E1A9C +:108D500055C0D6B1AEC96F55EF6AB33E36613A53CE +:108D600072C366D16F3DFF245E11F6264980324200 +:108D700069CCAEFBB9989A0049262C70809E7AC0C7 +:108D800050FDF0E0A0A50510A58BF2202B3C1C06A1 +:108D90008485BA6AA17746964F12D9BD2F87BCF158 +:108DA000F5FBC0B26FB28C36E2D21919CDF2DE5BA0 +:108DB0002BDA1A480DB0CEE95B160637F97050C2AF +:108DC000F97879AB57576C47DB995BAD47FA412B84 +:108DD000706955ACC886AA6D659AA78E8F8C770787 +:108DE000004E7724DAF06FB9DEFEF50C2FCA3FE5AE +:108DF000E32AA7ECA1AE0CD65B04C40C80C3A90186 +:108E000072A164663B9F2C846634E8D1669AED7546 +:108E10009F21615F9299F19CA9283C95423D404277 +:108E20005BDBB69AA33CD983DADA332245B66A21F2 +:108E3000E7FCBD6833424AA6B2E61E74DCADF1938E +:108E400051F0F7C63C31941A6882CF5A152B278E01 +:108E50009E3BB856067FCBAE96BE54C39BD84550BA +:108E60004E767E5BD4C6A9658381C474F1FF030F7F +:108E7000F2F64A68F6C467F4ED05ABC7C044D73DC7 +:108E80004C009FF53F3F1F2CC2278C5F68ADFBBD98 +:108E90009556755130BFC4E5E40C0F184F7A8F0E0C +:108EA000DF5E21B475C0A6FCA0B455702DAEFAB734 +:108EB00006735BAB52B541F7D57A897B7D928131E0 +:108EC0008A7905CB989B1C4C1BC74BF629A8548666 +:108ED000FEB8E93166D07D9FE47EE36993CF0E8AC8 +:108EE00007C37BAD3786F515446BA82D72787C934C +:108EF000FF7F750A368CDB8F831F677B65C875B86B +:108F000054A1EE89A2CBA7AA2ACE9945A6909C4946 +:108F1000D787727FDDD6AD01C9C9BEE6BEBC1B24B2 +:108F20002D9D22477A3E693BC66B67A60381EE46BC +:108F300004B872804C0FE2A823C7EB2EB5677B6E96 +:108F4000F8B5C1164FF0AC759738125D160E9180CA +:108F50001FD84B7925D768B7F3AD466B3FF0D336B2 +:108F6000A8774F7EBA859187A88709E39213CE9C94 +:108F70008D92A95503A3996A7FFAF7F8644C278468 +:108F8000939F12D6FEB9F52BA72ADA618982399E02 +:108F90005FBA02E7A872DE6F7A241F4C6551195B35 +:108FA000922D208BACB6451A45053B84BEFE167B40 +:108FB0009938BE20B2022765ABB04A1447ED5F4A2C +:108FC00024BD68BAFF2A58E2DAF9BCC852CFB055BE +:108FD000A529B62BAC810DE86DDA07880BF6D3D93D +:108FE00067F446F1AC005D700854F275744952B8EC +:108FF0000DE53ABE9B6A340564C0C689FFE4E6BD50 +:1090000020E0743ED9BE0CA660CED2EE06BCBEFFF8 +:10901000D409F04044D628851CFBC3A0307440D846 +:1090200054A4FFDB942986A98E1837E094ADA1F1F2 +:10903000A8B42C707B995B38662735C35FEB8DEF46 +:1090400052D7752CE5FBF3498A610052C835C852E6 +:109050001DE58D579AD12E115BB66B2DD88028BA9D +:10906000AF1F484499B41003DBD810E1B6264F690E +:10907000C94BC98BE3F244473505B25ABA94341947 +:109080008695BC3B243F5182E61440F3AD09F7C1FD +:10909000A3F0830F628CEE57ABA32418E9FEE0F433 +:1090A0009F905B4747A27367DEB9B5922B6FF6A31B +:1090B000696EF725100523F12ED30D5DA8F837A0B2 +:1090C000DBDB7D85351B7732A45995F33B30A1FE60 +:1090D0004E37149FA331FFAEE36CC1F421170A1978 +:1090E00024022F9D98DA56271E4A21586F8F39592E +:1090F00094E9C7D72FA2A44112F03B176DA14B21D1 +:109100002C98C2700F7D48882AA686438D009F0F39 +:109110005013E39E8FDD7D101F4087C0725CB3C586 +:10912000288CC7BD0E1FE0464525868A35D67AC6EF +:10913000353A32690471581F22167626DB0BF2E1AC +:1091400039EDF508BAF28DE8634D85F438D03F7CEF +:109150002A91C89EF97DC35ECE8B2FC98A1FA69126 +:109160005BAFBD9D7C6FC284D23DA577B44A01D868 +:1091700088C57F03F5F59C23ABD7B94BBE396AD7B9 +:109180009060A9C56AC136F6CEE3B8BE037CF72B62 +:10919000AEAFF0D09E6EE628CB6026279FC8F7E6DC +:1091A000113A8213FEEE19591E236DF4919149680C +:1091B000C9A50C0C7853D476EBA58453F614047E21 +:1091C000F3A3F09428DA57E0DD419DBAF50835E4C1 +:1091D00044F7EBA1ACAEE0C8CC1298AA2D6566F9B5 +:1091E000071F32A3817AE03573759B8A9EF2F8647B +:1091F000E7F1A3267389A5394F34E91107685A1D91 +:109200001BFC3FAAE9DDF7D088CA200990C4D11F12 +:109210007214342F8E293D6BB81E87C61DCAF7AD58 +:10922000892A0B7354BA18A12A891EFFD917A538A9 +:10923000C5251F2EFCB3FD5B896AFE657454E77774 +:109240004394AFA5BF22B1D6B1039947CBE818D25A +:109250008A5805E83F72CAEE4EDD1A1CE0B8779CCA +:10926000388667647EDDB64F29CDE8BF0ADB2C1651 +:10927000FC34D2BCE88A48440A66FEBE879A8A82D9 +:1092800098FA8C1008816E27F703B9873D45461C74 +:10929000F5AC1DD947A38A9249A1451304C58A603C +:1092A000E0D17D4549B48272CF4DF81D2A52935BBF +:1092B00017D77169C98469C23012C873407EEA5CED +:1092C0007B479C09FCA0FBCA3485F3F781A719BF33 +:1092D00022E935071CB7C187DF078D4A391632C12D +:1092E0001E15594C305036CB4EDF108B95FC2A6141 +:1092F00021C19D606B9E382DAF8AC71AD72FDC2AFB +:10930000F20387D8C81066F62C46D4108AEFB2173D +:109310007249C8A3802C2DFDC2E22133E8F8200C4D +:109320005EA3E1C44F10116C970F2CB5ACE0C1B136 +:109330003E295E44525F3A470C06DB52AB4202E5DF +:109340008DB27FAB44C01598A949043C83A692FA1C +:10935000AC66B05B3D869E4F47AC76A5188738FA61 +:1093600043B2BB5039B413AFF0A44F41F5591D942B +:10937000204F0AB72EEFD111750F69B2B46D2E567A +:10938000498607590E27195C4806E8CF31C6159A59 +:109390004C9F4A7B257B2A860C7063FDCE11F36CB3 +:1093A000B93D5F3106B3AEE30FAB4135FC0943C3B2 +:1093B000EC3B83C6D29CBC7AEFF6E537D0812456CD +:1093C000E7F761CCAB8A9F03547D21CBB1776EE484 +:1093D0004787CCF85F982AE3D5A0BEB255FCB34DC1 +:1093E000F10B7FF0069FAD3D28F7C8FA26F121FF6B +:1093F0006EF10D88AD576ADAEBF615A5C62686988C +:10940000AE2BC95A9D29A496E94A9C4F0223BF60FE +:10941000B12B308EB8D41367E2E6F6F13D6AAC2585 +:10942000361BCF228374889B5AA076A9C4876B15FC +:109430008F3C6C7D8D6B0108B57BE656D21F48E6EC +:109440008B690B7B6EF0BF50477514D0585E334A62 +:10945000B717DD81151B5116E2EE00889556CB5DDE +:109460006117C7E088F410B12DFA80D394AACEE832 +:10947000AD0ACD2AF7EEAC42227F508E5EDD980910 +:10948000301F526C76B6583591F48647DCBD766451 +:109490003DEB0FBFD5487C8076AABDB5F313C87FDE +:1094A000D1E59D7E1599EB3003BC1157985A47C002 +:1094B000E66FFFAA537616E306816306D4EA5E01DF +:1094C0009689E4E73BBD5F764C82931664AE0E87C7 +:1094D000DAADD6CB601D6897F8C8E459A95ECAC852 +:1094E0004D9F8A59C04DD8258BD5EA10A1BB08A63F +:1094F000EEC8BC660ABB8AD5E8549240F4A6D9F1FE +:10950000A586A7A712E4BD21F6C6EEE2B85FBB911F +:10951000BA01BAF2EBE0AEB77B2D898952454C9B7C +:109520007540EF82FD0D6B3B1A259B84705046AB56 +:109530006ABFA6FBEEA5C7FB9EF48E992AC35FD334 +:109540008667BA3A69007B1CE6085CDD1CB92EC050 +:10955000F9BC81AC1B170C600ADCF0FE9E6B4BC99A +:10956000E641340D5D03AC1C3727CAC58B8B5826EA +:10957000F5C181634E9AAADD116D582879102367D1 +:109580005F474DF7DB9D2F4E1BBF742B48470A1BCF +:10959000B8581E32CED53F232EC048B596D2068786 +:1095A000DF4D764D7F6F9CA96BB27EB9D9CB82CC53 +:1095B000BFE2B4FACF5980FE822DB973C404E8DA51 +:1095C0004D90F41FBE9B48328F16C4A2F652AC8059 +:1095D0001707146E2FEAFA627A16A7C5C397C81444 +:1095E00049868054CC1BCEBE922EEA91BEDC745BC1 +:1095F0003F7E13246D946ABA823BEA3A725DDD3194 +:109600004623986209AB387DC4521EB8BCBEE1C780 +:10961000D9BC49EE02F8DF76D8D4604B25245C6BC8 +:109620004ED86CD3F8D3CE696BAD1972CB877C540E +:10963000786EC35E89F615B36F65F0A3C450AD6C48 +:109640000883434C2092CE393AC8EB36808C5E15A5 +:1096500096843B7DC9B19026123FC4388B4C0F9B3A +:10966000E0A280076030B9C7F7351506BC89FC2D2C +:10967000E7AF7A668E26EB75485D565E24F9CFB467 +:10968000519C491705B45FD9E93ECFF8402018BF77 +:1096900041159E0131D20BFA7D3358B9B6DCD9445D +:1096A000D50312FAB05259174BAA04078DFA822437 +:1096B0008E3C298840D74DB083E8D060595B68EB79 +:1096C0000441733A57A1167414151D54DEE19883B2 +:1096D000142909C8F5C1F18BAFEC400816094DA754 +:1096E0000FAF3858D6DF9E5748F172652847A3045C +:1096F0001927D2191154092EE46C942C73C60FD07B +:109700005E5386AE2A09B9D1DB71C8EA39CE256F1E +:1097100069712968464F397B39E0892943AF972918 +:109720008B6CDD31D0F9A1EE7EF7217CA08CF04668 +:10973000A48FF71798365A76427B5F977E11BB3914 +:109740004E217E8B2BFF668AE7E8B06EDE0D9DB75B +:10975000CBD3AEEA36AC9CE4F2AAF7ABC27E620D84 +:10976000CE1EFCA9FBABD7DFA66D42A9559BEE37F9 +:10977000C164A23FE288DEB7D5FD5AC46C31EB90DC +:1097800096694D90A12114E72A71D03CCFE444CFD3 +:1097900096F7270434B2DBD1CED304BF3193F191D5 +:1097A0001E17E8245694CB1B784439464FD84BFB00 +:1097B000CEFB6BB4A0A1005D413FCBD9244D7EBC54 +:1097C000F8A6FF6C2E0B6B90C6067682440DC4C5BE +:1097D0002AFF277D54A9F4957655BD28710615D723 +:1097E0001E3B558DCB6C3C850AEDD5E9A3806D40C1 +:1097F000D0B823C00E94D7C2A674C02EDE32C1F6F4 +:10980000361E5E500BEBC6FA08D4A525C231834044 +:1098100030E014C43E0487A84085544EA343A5AE4F +:10982000583BA85A3F32B56C922E82F063ABDDC82C +:10983000243478D468FE086098ECF71711F49ABCC9 +:10984000F9EBC8090ABA74C6A87F97DDDC8D582BDE +:10985000B82352FC6F69C2EFA74A129A4C108C745D +:109860005B844F40D5A97994AA194922BADA299381 +:109870000666094FCA60277F3E008FC6580CC7D2C4 +:10988000610CD35A2A46944B4C4857638843DBD922 +:10989000A6DA26730F40D0FE133950B816979515E7 +:1098A0003BB90597F35ADD5313B458F1178C2CC20A +:1098B00000E39EF860E99E90119FB65AF552C4EB02 +:1098C0000B80B56EEA05AD928B99E59AE0BA4485B6 +:1098D00093C08963AA1E8BE3CBC7C4A8F2C79F9627 +:1098E000547EF69EDBA54C6713D9A50BE8AB903FE1 +:1098F0000868C783A46E6569CB2587D7186C69DAB9 +:1099000010C2F363EBC45BF43D75A3551F05A5F3CB +:109910006D795E4697E9ABC5DA01C29B6540E3BA53 +:10992000D62004397D671A215A41A472B0DD8966B8 +:1099300023E5072C9CDB229BC8E436A48F9EA24D16 +:109940000353157F7F4C24577AE37B888CD55C8347 +:10995000B3583C5BC61D1FA9308150858939ADA71E +:109960000EBCADC0BA406E58C1A454DF428CDA7848 +:109970005EA9792B2533B6218C4B5842AC131E7946 +:10998000DE8C25228BB5B15421F2F9784FD01A889C +:109990002DBDF9A501591BDD22626B62FC6339F014 +:1099A0000AC43268D33AD99DD36DFF36CD87BFD66E +:1099B00093213E231A94186432DA869969473DF858 +:1099C00074D1D1A5D5BEE4B23597A017751511761F +:1099D00080970C5539DD4E34D82269AC46F8A57114 +:1099E000D176765547A0239D0A7989CC946E15448B +:1099F00027C5C93E7BB52424AD394051ED4A97A710 +:109A00007CC6D506E4B5A05A2EF5E1A5A91F0ED255 +:109A10002719655F09A7618FDA6E922F5CAF4F9FA0 +:109A2000CD84D6083A2B107FCC9D11030DABEE9A56 +:109A3000B82C1392DED263F4EDF4865999D1C29515 +:109A40007BD3642F55BE766DC8655A6C0FE28810C3 +:109A5000C13EBC5131F030A420DB9C10D702222A39 +:109A6000454592E75B6EDC5A23847602F31DF67B54 +:109A70002852E2C312688177E06FB9375F895A3F95 +:109A8000280176A21FCCB401A03C70028DF15D7656 +:109A9000ACF578D83307C87EFC919CE3CD1D9BEFD5 +:109AA000CEEB8B2F433DA04D6F4D11FC9631EAABB1 +:109AB000F3E6F685EFE9432FEB49FE8A00C7B67A55 +:109AC000234C928CED554DCE5A803FFB97B5646286 +:109AD000C38CBFB80990CD5406729FE1156FA81FC3 +:109AE0002BC280DEDE5B9A8F7D5FBD780A2CB8C703 +:109AF000A23F8712377AE96BA950AB097998EFBC7E +:109B0000A761CAC48A32039ECD17F87F9590C3FC23 +:109B1000942DD87A03505C3B29D5949EB1ED68D33F +:109B200008858DF3E67DBFF184B51D60B4EA694513 +:109B300089255AD848BE37B39935173C75A5A8C6AC +:109B400010DD9092510059C3DD158D217707046A0D +:109B5000DE2F89963925E68DF03396EDD3EC16F499 +:109B6000BD113F6ACA9E151DE3415CE9068503B835 +:109B700064C01C10EBBDE8224AFD901CFB1F672946 +:109B8000A16F0E9530B7B113A9FD893CECBFDC8EF7 +:109B9000003D76EC5A6BE872452984B8B4E4572549 +:109BA0005BC88F8D3FF0AB4D4AE2DBD3A24C84857E +:109BB000BF8AEE55C3F846DB18BB7E982C61DBF2FA +:109BC0001CCBF767964905F154F4C4F38FC65E3099 +:109BD0009232B7A19156D58CF2EE507446D2EB0B6F +:109BE00024970F44AFEB941022B472EEB8F0C22762 +:109BF000F811EA49405BBAAEF48ED95A7E5B5B8EAF +:109C0000A06E30294C2EA03A17F3A57F5F46D0886E +:109C10008AE5B490790A885653A31CCEE99F784A06 +:109C20004A2BBDF4A0A8C947080F40D0556D296D37 +:109C300019A84A86CEE4E95175C502A798EAC82A50 +:109C4000FDB985FEB599BB4380A5714D0046C9524B +:109C5000A438DE1182F4FA7650BC25E07D9395138A +:109C6000A8456125878C69A7A36D92DE513D9106B9 +:109C7000BC17983D1D503DDEDDF7F2D874BBFED118 +:109C800095A6747D324AB84B0938178A603F92A670 +:109C9000C8D5C2DC6731B02F47ED68BC2657B03657 +:109CA00084A6B2C8ED8F67790E8B52B4784E3F28E8 +:109CB000C568CEC9C474B25FB851F4D9A004A8CFA6 +:109CC000417D112917E909E4A292DA12EC62285EBB +:109CD000DB81E6EAAACB2D8A0420E4B56996E83F49 +:109CE000DF813F46018B75260498AC2F24EB1EA123 +:109CF00015D8A4A3B30930709DCD4E10AD1E092612 +:109D000015FA757475084936CF36BDE56D9165A0B5 +:109D10002A36E77468A32E4059EB53B5781041BC3E +:109D2000BDF9212A54208DA2C612AC7EFC49E482E2 +:109D300060006A2723A4EC6F403539C12506961DC3 +:109D40005F7B323D55A69FE5BAD3F8D93868EF1747 +:109D50007FA4A29CAFFD1EC754EA36B14AC2E9F205 +:109D6000E0F4F5E07993C458C03A5627247BB50255 +:109D7000AED44EBD7C348F141639163D81B545984E +:109D80009274079F7EEEC1B8CD9EF83315B59688C4 +:109D9000161745029174942519EB6C53619C285653 +:109DA00087699B517241DCA8566F1E4D05065850BD +:109DB0002CBC4D449729CBEDA8DA027E13F4B5579D +:109DC000CEB4DC120AA326FD87CE2A4513B655B3BE +:109DD000852FB4DC1DF079AFD1485335F164890B80 +:109DE0005FFAA6218745E514E1C50521FD92A5F797 +:109DF000A5F42DEE388B27C44236555E850DA1B8EB +:109E0000945C4BC423F086CF3874AF05C210E2983F +:109E1000F37627FACC5CA3A61471CFF320BE66605C +:109E2000546C8D67B0758358DB6C2061D1C5E469D3 +:109E300002827C88C0E1ECC6A9FECA62ED1FC5148F +:109E40008A77A08E76836EDB883D90A467AE431739 +:109E5000E22CA3657F900DA64F888B20C8C6C51441 +:109E60001C19D1E815C5F24D3C5C695333B8283E46 +:109E7000613F6C340B1C8A25F0D4DAE1D9E9F4890E +:109E800017C0F87D34F9779467D4150960E35A5206 +:109E9000978EA89C353CB292A188A63F965CB5E609 +:109EA000B3DCD3E72A04346D66A353FECE8DB15DD7 +:109EB00065B891A80E5CAF185334407300DD59FFAC +:109EC000FCC3EBBA1C2F19E17BDCF3A038F0A939F5 +:109ED000BB1F2AB463CF248401D43BCC61200E493C +:109EE0003CF11D97D89E9D2BCE45D78B6BE870A774 +:109EF0003D2A8E0A06606218A4A2DE25587748DE45 +:109F00009428998C9CC7489223DAD7BE745EFFFFD1 +:109F1000BC72610E2DD6778B8E08CBD61C8D55E783 +:109F20003F14E4A9D18B8DB8D3DB08AE638535DB54 +:109F3000A21AA8FE267B4D4F2346FC9BD850E2294F +:109F40002DA95D19641548236C06F8E3818E2B3723 +:109F5000896162AADDF7B3B05AD701B8A45A2BD9E8 +:109F6000A18A88F88992A5C8D0DE4C03F1A2964C4C +:109F700052685526AB301DDCA388731EE919A23642 +:109F8000AABAD86DFBF77F6E16F8D3779333AB9FE1 +:109F900049B91CBE943F9CF3895766091B7E85E72F +:109FA000ED820028F01220E333CD0DF2F688204137 +:109FB0000735356351EB034A29D9282FB0121D4EBE +:109FC000E909EB9FE5006A8033A0D0CD01BA891C76 +:109FD00074F17E950202E80A7481E2FAF23B4A1AB1 +:109FE00032C30EE268B85C514241FBA9D93C9E06DF +:109FF0000DAAD3EB681F09D91E0D86FCD8F7DC49E2 +:10A000009D0A67B95CC34E3AEB2C497B8A2D5E9D55 +:10A01000202AD3CA4B30B31DF59CE2B6EFBD873979 +:10A0200053527263FB0D3C6E34F6DD777816FC6D8F +:10A03000407012F30BDFA9255C01C15A9A65D4A9BF +:10A0400021C774123FD283E451CC4D76580CA9E756 +:10A05000790E61077CEB6DDA9C33387F3BF0302260 +:10A06000AF6BDE201CC79485A8517140A4F88B8685 +:10A07000BDC873B89A0BE32EDAE258C089740BA3FB +:10A080004C8B3CB653FE7AB06905FCB976FFF043C1 +:10A09000E7F990E5C937B6E56CFA01390846046579 +:10A0A0003AB74EA915592FED11A49F73C4186A4CE5 +:10A0B000D50D7255F8D53445C966647A0FB14B9EFB +:10A0C0001884D5EC00A8D4673B0345B5D53F035AA7 +:10A0D000A302A91E91460878EA68CD31B5B6AFC98A +:10A0E00028A6F6B254640624C09A0AAFA782E47D7B +:10A0F000210AA4EE183159CB59F8967CDE2D16F2C0 +:10A10000B12B07D918D48764D1C6150B345B311F26 +:10A11000E724995FCFE2A1E4D2C8A2E9E98B62F516 +:10A1200092445445277987FC90F3BF17B5FCC49B34 +:10A130007CD39B6BE264D5584131E25A4666C59B9D +:10A14000FD57954C7C69FEAC9870018ABDE57F0097 +:10A15000F43432BD6E8FF3775830E0727D3CF08579 +:10A1600052C850EAF8E8D77A8A5507F3E11A66BE72 +:10A170005E12F2080E8B3D8DD0F631A6F07AEF3BE1 +:10A18000F814AEEDE3585C527FC20889D038F2AAC9 +:10A190005EFCD38474D3F458443BDAAB2AAA11286A +:10A1A000EC23E55DA13C9F472C6E94F2ED3FFD054D +:10A1B000D9C8CE05560D5E3731D293AC3AA5EF71B2 +:10A1C0001DA8A80EF8D0134249C63214AFC2A12B65 +:10A1D00091F3365F88658588170567542035AFD4BD +:10A1E0007EE791F025EAE885768DD30292EC371769 +:10A1F0008EF4CA586A5C3EE29AE0F26063714635BA +:10A20000CB11EF7099FE5B68F7F6181CC2527FB352 +:10A21000533DADCB8BCC936E7C141427DCB9043B3F +:10A2200043C709E51847D986EFA45CE3084BA1F7BB +:10A230005355F08D296711D70E0DA296FF09FF41E6 +:10A24000128D11ADC6F82B294564A1C6E2869B7715 +:10A25000E09776A41AAFEBACEE1B629BAE3FF22701 +:10A260006191D205F23BE260E80CF11E7D11C93329 +:10A27000F3F4F08B515687450F0AADA636DD17C1B2 +:10A28000AF6BED78B2B6EF5BD148B389DAB20F6C41 +:10A29000F29B0E763C96800942131FE8A59C629DB6 +:10A2A0000923356C0EB61B4A07B4979B2D375373A1 +:10A2B0009FC28FD014AF436B91288AAD787EF6FE93 +:10A2C0006BEBBF8729D7691B72C328D249AD4CF30A +:10A2D0004AE76EBAE70963324607C71A6E7103761A +:10A2E0007DE87660CC1B2EE6FF09C7B056B71D157A +:10A2F0009B39358F7D58CD43A8E7021322E5AAC6C6 +:10A300007CD8599C6E4B484B6B6FCDD6255F71A0A6 +:10A31000CC262611EAB82B40DCB81FF4E5E7F67529 +:10A32000B0B6FAAFDB75D0F61673995CEA73B5FE7A +:10A330002A6F6356CC94A085A00036E677C9A4198D +:10A340000D0AEEC0798A65AD1419A62195205E2DFF +:10A3500049C04BF1CE0A90686E5FCD3FC08DF6E4E8 +:10A360001541895BEE9373ED598B031798ADEA8520 +:10A37000882395FE8E5F4F9C34ED9B3A1F596635BE +:10A3800071BA02371420CB15988A8FF7B98090E103 +:10A39000131F815D6C141B3DB24DCBA8F55C597148 +:10A3A000462D5FD2C3C826A2A7FDB20E148EEF0EB3 +:10A3B000EE136A723AB5099BE2EB19031054420599 +:10A3C00064437A52A17236288B07D739E119F09588 +:10A3D000CA133BC6D8E9BF60FCE45352B3D1B626DA +:10A3E000C352F21D3F38941A02F20527FBB3ED73F6 +:10A3F000F063AEAF28B17EBC1AC000F20ABF309045 +:10A4000091A3E7A16F4E010FF0A3024BA17E0D3186 +:10A41000798E604905B7993FCA9643FCFC88DDD622 +:10A42000212E1282B0EE3B158A79EC9AF5E8327053 +:10A4300068388780111395EFC8844985DB725149CC +:10A440002E7B31C41FB2BE9A68D0E07B556C853537 +:10A45000EF39E18CF6F17693CD15E318A9D3DBDD66 +:10A460008890FF60D26E870547608A7104563FE48A +:10A47000C964AEE7B73CDAE9BCC7AC0A5765591006 +:10A48000DF45D53452CAFA0A56CAFBB71A02768596 +:10A49000D3F65B63DD37137D792CBC39BF49565B3E +:10A4A0004A6F85FD14613B9A938C4842F54A520CE1 +:10A4B000C9F9084C848241521F5EC13AE79B9ED085 +:10A4C00011C862A5B7E6015EFBA26660F17D268F2A +:10A4D000A3C14ACA9CF5A5871603167201C599FB4C +:10A4E000C7B187CC390F35E9C22D42FDEC65A3B960 +:10A4F0006F077D436C20C6B64AE990176067045A1F +:10A500009A4A563540B848993EEF2FC48B6BB3BA80 +:10A510005A7A27776F4F675962460924F75D714D64 +:10A520001F68F9B2E034F56F33E8B667FA330C6DA3 +:10A530001B57F535D9A9345ADB6B3B9073EA0E06ED +:10A54000C810CCDE62CD5B73E4B7D2B0929ED4E289 +:10A55000CF8327BE871BD789D9D7A5F00B1D266CC3 +:10A5600045BE8BA52298739A59BB2635471EFFDB43 +:10A57000E8385CAE894EB8BE8090CFB50FC629E0F2 +:10A58000F7AB1CCAE5B28A3A4C6775FA1C0024EA9C +:10A590008CFEDFEB6B2D4019AFC20AABFFDFE0CFC3 +:10A5A000F2C5374AD8022DAFABF76DAFDE9A376EE2 +:10A5B000DD28BD34D637304FCCAA433A20A3ED2353 +:10A5C0000CF6497DC92BFCD6FACA2CE12B5D5759F4 +:10A5D0004D87F6EBB2F6E13A9AE7961B9B23957509 +:10A5E00037191EE04A537104A9F9EE286363705CC1 +:10A5F000EFE41C740DC1938EEF66781A3A07854913 +:10A60000A20867D890760A502CDF96CA7BC097BE06 +:10A610006A38B46FC9F6759507698F293479562D54 +:10A62000E4EF104CB79A969E4076F31C71C27DCE33 +:10A630001C411968466B1A4046E14E328C19229330 +:10A640002ECAF4A9DD694995F89EAA89274F3C5482 +:10A65000821984A5B918AC69B3956960B30986B944 +:10A66000C238C01749478E99DC9DA91B9AFE6477B2 +:10A670001BD72152ACE68161A75F88123AB9914A93 +:10A680007F10786E9E48EF1870566473342572E818 +:10A69000552E87F9BD679BA303BB052929C6AB0AC5 +:10A6A000E4E92202E44566FC79C46EF2A69FC71D68 +:10A6B00029B18ED420800B3EE3A06C145CFACD8AC5 +:10A6C0009BA080C0628750A9BB0E7A1E351931004D +:10A6D0002FC436718C1A8A013A9508834AF872574A +:10A6E000F91FF050C751E4277D172728AC6EB72714 +:10A6F000E02201504AD7CDD177DBE256DE8EE4DE90 +:10A7000045B633ACD7CC0E3C49E7C5967AA1CE937B +:10A71000E1FD60DDC4928F08716C85DCF50345CEE8 +:10A72000F9F3CEAFC5FF70F9FA2FA5B20B85CE5B5A +:10A73000CCC88DD911E8CFC85CB0D66B658D57B841 +:10A74000E8387EDE66FF83EF32F4FCFA382FE3F35D +:10A750009C0D3CFCF0B37C99122B55ECD1C778666C +:10A760006BB487305840B09C0100875F2BC5F4B5AF +:10A770003E32D795645C7D3BCF04902FB2F94A2CD2 +:10A7800033D7336E13C0A9D9BB043E4605428FCAE6 +:10A79000B1BFED3A98AD2E9AA69F403DA4F4C4AF48 +:10A7A000BF1644C59FB9DCFCA3898E3A2AE72DDC8D +:10A7B00065C7AFC234529D8C72914049DFC93D7468 +:10A7C000EE375B42419139D16386480FE908DDAB32 +:10A7D0008EFD073C63F5F1297D31B356AB27D7C217 +:10A7E000AC22DACE4CF97C93D6C4FCD5C97B61FE91 +:10A7F0003971098E038E0A7D10E2DBD6D9948EA7BB +:10A8000032A9F6F6391D6135DD48FF0FF3927B6101 +:10A81000256B38C3D3A08E9DB0732724E3F451BEBB +:10A8200048885422995613837FCAE78DA6EC77B1E6 +:10A83000E5E9B5A75AEF72CFFE718C9B381B78877C +:10A84000D001FA7443EAEC8DB65FAA6F9F9E8552E1 +:10A8500004F755AD6E6833F6FE8118B2B0C73FB14C +:10A860006F7FCFBEF8E01DC258D47FFB544AFFC2B1 +:10A870005FD1AF5FE8F29FD73E579359FF5E09A2C1 +:10A88000E86381C47A896D63F67349DFB3D12881A7 +:10A89000016758E71393F6B0CBDFA3DBBD022D3C75 +:10A8A000EBD4D7357A81326BE1E2693BD3A85A29E0 +:10A8B000EA6629DFC1709E981D032EBE4C881DFDDF +:10A8C000F4285EF0BF6751EBCFF0A00176524C55F3 +:10A8D000EB590D5D4A3B699A4A1B3D3F8AD880AAD5 +:10A8E00010813AC33D81998FAD09A44DE0BE4E2839 +:10A8F0008746B5068D53266E9539137245D88B025F +:10A90000294254AFA4A30E0569AE3BD1D7102868E5 +:10A910007C45785B8E0DAB2001722E39BFECEDA625 +:10A920000697BE173796B904CA0D5FF41CAE80298E +:10A93000871BF0E8856D0BA5DFE910B054E158F1F5 +:10A94000D5823504C741AFBC91684EF4C631808AC8 +:10A950003ACEBA20637528A88BFF72C3F2F2071EA5 +:10A960001A15827D610A72C13BFC8BE624285FDAEE +:10A9700074CAAAC45DFDA7D1A057E7F141DE6914EE +:10A98000978501CA94882C869C2A621E2C95FC22ED +:10A9900051BFF17F02ABC269C80E43396CF242214C +:10A9A00067E0B668B620C2C04425B21DEF87230613 +:10A9B00048090D35B0E79373C2D33CB68B5CD32501 +:10A9C000D6678427B2EBDA1DCA7D82BF37BD485FE8 +:10A9D000B322D03D4CDCCC7DC30070E8668DD676CA +:10A9E000D1F3C8CDC8A6B14AC7630FFB8C40E7912D +:10A9F000D8D5CC7DA4170985D9338795F9208A3A13 +:10AA0000E686A879624C7F024A4054F621698B1A87 +:10AA10008B13624983A986620DC4AD04F005729957 +:10AA200073EFA3534FB68EA817046CBBACCD2ECFDB +:10AA300088965913965F08709533C1EF724BF837BB +:10AA4000C5ABC6D5EE42479BDD10224F3847E68E98 +:10AA5000118028F8D1A73AA425ABCC94019F8EB6DB +:10AA60009A1C426709F6EDC468F23C167DB66B800D +:10AA700022F68B50717DD5C856B8DBC47C83FBCDE4 +:10AA8000D360BA9F72FBA65855690AB5339751CF68 +:10AA900011822F6B26B883EAAC9F38708A9657D202 +:10AAA000B9B2E4076AE5CBAA44213BB98112A8A553 +:10AAB000BB6DBD12312F6E45F69610D4D70E52677E +:10AAC000057476776A9C4EBAE71ED8351EAB4DEDFD +:10AAD000CB27689A9E8E5A809CC5D3B60210AA8254 +:10AAE000741ED9B7F7D5BC5580DABF3D1DDB90CEBB +:10AAF000F7F0C5F3321569B8B3A371623D0C570680 +:10AB0000A65F845EEC76ED1807FE41A33FD0C2E35A +:10AB100028D876041F7A3726DAF1ACA109D3571E5C +:10AB2000708D884F80B1C1C61EFF984442D0B406D4 +:10AB30004584DF782C57C7B36604854FC907D850C2 +:10AB4000DA9CF776B3EAAC946A3DC129F33E3EC87D +:10AB50001A1EEA5F77D873679DD9DD7065E59305A6 +:10AB6000395C11C5F62ABCC472B062A73A16F5CD9D +:10AB70008795F4F835699F0CCDE4E5903D9E3C90B7 +:10AB8000F8A2066DA2FDE7C1DB62813D765A27C6B9 +:10AB900053936762AD64199656665B0DCD3A65A412 +:10ABA0002F9ABCD5BE4A26DD7EA83E98270757C3FC +:10ABB000E6B11394EFF5BE53CBFA34128183A80BA0 +:10ABC0003F3BEB3C8BECE45C5334E03D32F0160B46 +:10ABD0003E63FAE61E92745D948FC7491F25C6B284 +:10ABE00087DF50FB83D94AE0FFF84127DC9E6C30B9 +:10ABF0002F7DE45BAFE3C6B68AAABA63CC89AF8A7D +:10AC000094DEB7B96F4EDA528D2D9FC8337B74290D +:10AC1000E1D8D331E9412B9089BACFEFCE4ED90E8E +:10AC2000FC30D76811649B0A7BBF0739F809E04DF7 +:10AC3000035917E2DD2BBF699D3F41251E0EFA55D2 +:10AC4000DFDC7D21D54D11A34D0B767429631C9952 +:10AC5000E0B5A3259FC749F1F85A8AF95EA62E5799 +:10AC600037074F76838BF3B6E72C4D11BE8E01C2AA +:10AC7000F6E0FBB8D4A6699709782BE189A1AA4B25 +:10AC8000613DFDDB60DB691B9A32C74BC4D00F8589 +:10AC9000AC7819773C0B63FE1F6FB0EDEC6DBF8D88 +:10ACA000A239A3A5538C234D59346E129D5DD15109 +:10ACB00072DE88FE98741D749E731A41DCCF0849B9 +:10ACC00009675023EA63D148D3273C72774BEC479E +:10ACD00094F5466CD6EE27031B36736B98B75DCBA5 +:10ACE0002B6F8D0E20E39A19F32EA9C6CD93180D64 +:10ACF00057E044B084F11098C01EB13D8712FA1C91 +:10AD0000877B0AA91F0AA0FCE48A1F83882A526154 +:10AD1000119231FE3C80BBB43E534FADBFA494981A +:10AD20003DD6ECD7239CB9ADE74FC712570BDD2BAF +:10AD30002E65BF8D9757B95135E69E0F124EABDC8D +:10AD4000CB60FC594DCDDA26F5F8A267B4573BCA63 +:10AD500079CF5E20B639F124E6132ED3765CDA5132 +:10AD6000BF34F4C49A6689704C85D3C7A4D1E2FC81 +:10AD7000D677C8D1A41152AC8E3CBE970936716803 +:10AD8000F975640751F69630155B21DEF163FC24FA +:10AD9000F847FBA9395E05CC090650043B0E6A98BA +:10ADA000AD43F2EA6B4C8D24C92297523E691B7D5C +:10ADB0002B5EB3F8880DCA2A5079F2383CADCA230D +:10ADC000A1AFFCF4C6EDC0C352F908DA951F99355E +:10ADD000E001B409E799A8A8C31CF8FBC19D0EF6D1 +:10ADE0009E7551BD53E7F7AC07D085AF01908899A8 +:10ADF000200A292D2AE4CA0B48520EEFB62F66F618 +:10AE000001D9C3B2E862319A9BD4927D22DBC0D8CB +:10AE1000162356768308B8007BBA016A50EEAAADB5 +:10AE2000B6D5CAAC39E4324B8CB29A966803705DE1 +:10AE30001D20745FAFEBC805BFA71F15BC21B99DCE +:10AE40009080B2573B46D12D2DCAE54869B7E6A69A +:10AE500043E5243E1DE5D29123FF3EBB46496000F9 +:10AE60005A2270C1381CCFE186C6B8283EF705B615 +:10AE7000149C338CD874093B3EA07D279F6A8FA613 +:10AE8000A7D1C326DFC70BD7B6835E7ECBC1C42B49 +:10AE9000E6504E1D35E50B2D4C1CE47E9336D684D2 +:10AEA000EE730525DF759780C272B529538B240197 +:10AEB000A8A3068EEB3F605A21CDCCB5A9A8824746 +:10AEC0006FD0E7690C6142EB370C093292D0412612 +:10AED00074318BFD88750BA7D1494ECF7865EF246F +:10AEE000AED093A40434FEA834D042F307E75E5DED +:10AEF000D4498E0DEC664477868478E03FB3964E55 +:10AF0000B60B794BA4FE39B63DE0DFE1365911A30B +:10AF1000AB25EE28DDC0B9FCB346C8D879E45F772D +:10AF2000656A5EE40AA3904E1886230E450668EE15 +:10AF300085E94B8CED4D4DDFC7A2219E4A6FF53C54 +:10AF40007213B473D6F9A437C202F0706F2849B8EF +:10AF5000BCBE7E6F8BECBC5C55624AF2F7788EC843 +:10AF60006912EABCCB8CFB283FD3C3E975D84809EA +:10AF7000418C2A159CF08C693BD4D2CEB6C5DF42F9 +:10AF8000B8A27A8EE160686C23BB6B70C26ED60E7D +:10AF9000BB156457F34987ED150AFEE44C31A04A0E +:10AFA000C4BA1FD455C07100AD488A3027B99C512E +:10AFB0005CB3619BF5F4DFA1E3E537812C14598D77 +:10AFC0006AF929B098C01438AFCC9B6342F7019C52 +:10AFD0001758F1071A252E0D7947CDB687BFA09FC8 +:10AFE0005726DAFBD0CF566AA550276F268A776896 +:10AFF000137D3E20CCAB498EAAE1D2165833B274F1 +:10B00000E4328669B871989580A37368F38A8121C8 +:10B0100029724B4EEDDABA32140E840C2A66E7C15F +:10B020006C8EE4EC602979827C0BB5DC1E038A3FD0 +:10B030000B22253F1AD07AF9627C2E02EDD67434A9 +:10B0400079AA277AD020D28A9DA66AF2E2004455D6 +:10B0500079B2D68D34CA044FD36C1C1ADE6E5CB143 +:10B06000D444643E9158522EAC4FD0FE8DA8E85285 +:10B070002E96F3C145BEF8779F228282CC07F6B7A1 +:10B08000EEF59164BEAC47C8F240C8CFCC1DCA6291 +:10B09000E8534FD27C52BE665A128902046FA570E3 +:10B0A0000B83001E823FC2CE379D71C336950D5F64 +:10B0B0000897401E930D2442FC086EEF4AC8EF1417 +:10B0C0004DE6D8360DB1E8FB2D3E9F6FFA72EA4986 +:10B0D000A659A3AB8706738A5BB0AF25490F8338A7 +:10B0E000FB162B7C7A8B6CAB0A3790F8CD82158BD4 +:10B0F00018D8F562BF92944AA316FF76B69DC6B0E3 +:10B10000093A97FF095566D80BBF46CB1821D70BD4 +:10B11000386CB09CA6044077469B5FA48ABC4B3138 +:10B1200030EB18FD5D5794C20B94BB3231C544EC33 +:10B130007CE56DB4B02D72643BC38746D049B6211F +:10B14000DCE3269BD33C96498D607C21D3790D7638 +:10B15000DA24A50C3638DBF081B3162A3926946E32 +:10B160001385028ADFBC3A5250EF262906029C4D15 +:10B170004BAEB79A3789E0305CE47A385F8C288828 +:10B18000F4CF90180C3BB3DB40D87643C51E9C9D92 +:10B19000CF7B6FA3BD4C4D4CD4FCD5536D12AF7C0F +:10B1A0009C8035B2B8A30547C15C9CB5D3D696C781 +:10B1B000FC30E2978034DBF42C7B890B948161A80E +:10B1C0005257400A3C6C9A9FA37E8CFD0AAF4B1AE3 +:10B1D000829D0AB20F7DFFAF88CAAE6E606E36499F +:10B1E000F0C5AE5621F2DE338A28005885AF444FB1 +:10B1F000F5B16CE36952D95E7C650461C80DB62A6D +:10B2000008D608B168979C8682CC1B48FA001A3988 +:10B21000119DEB6F5D140CF6882F8B09559C8E5099 +:10B22000BDF5BF942269AC3C41E83025F5DE66945B +:10B2300095D2D4458DD01917A7CFD02FFAC386A1A8 +:10B24000B30E6D9CD1C09EB992F770301F84D97B2C +:10B25000582F5648F4443EC6CA0649CCF2DD302B7E +:10B260004AB24652AC74DEDF59C88D105AD6260356 +:10B27000D3275B0E1E1BB7FF9CDCD8783435E66BFA +:10B280004296F2137584FEC1F6243D528A7E468BA7 +:10B2900003412268FF5C85E2E10424B6C45BBB6025 +:10B2A00043474206EE6E15E7E72D052CBCD0A2F40D +:10B2B00022015680CA19BE601CDD3E23BC87C0F740 +:10B2C0004FA7F7F3512CBA1EC5DFD1821D14F84BDE +:10B2D000134A2484EBEA1E5B905B923F08D5F6E3A9 +:10B2E000B698FBB7526AF2E207C3EECC80D26F5633 +:10B2F000D11E7309A85BE2B8BB48032DC4EBF23B37 +:10B30000219815C4D1F623078A6750E1E3D9229921 +:10B310009FBBA42AEE3F8A09DD498C992DB9E9B972 +:10B32000E91DB98ED546FCFAA1EE365EFC07908881 +:10B330009A04DEDD4B6AD2418754B4ED967DD26625 +:10B3400069DC4976B3749AD2C59B9C2A37F1166B97 +:10B350004D6346A0FAAF690ADEC6508F46DEF3D8C9 +:10B360007B9ADD0E37460F5E56E78F20250F22357C +:10B370003B8D711DD471D82D8D908F48F50A64D204 +:10B38000C126BEEEC3BD9A42D8EB33EA0EB993D5BF +:10B39000CB58684E9EEE199FB7E09AF25E231E23AB +:10B3A0008EBC3F6DFB91959244B8EDCE0C41244884 +:10B3B000EA978DB1E8DD5070058A68FD69192AF5B4 +:10B3C000F8C38C7277D8A96D384233A5402DCDDEF5 +:10B3D00019DA75683A4D9C7F273BEDEF2A1C2FCE7A +:10B3E0003702DDEE6D4C3F42E05EBE754656644569 +:10B3F000B98E7B417A00A015D991A79A1A1D0EE249 +:10B4000032044C8CA6E2FBCA7EEEBB80F9A7C65B79 +:10B41000F54DDC1C9AC16C6C09E1A59E6E2033A52C +:10B420003ECEFC0E1CF14C231FB9FAB94E3719E67B +:10B4300062FC7379FABE21CFB1EE38DE7E6E7BC737 +:10B4400036B1A79557E0B6065D000EC05A564AC6FB +:10B450006DB3AC2A6C7617ABF8CA7FFBB5AF3AB6C2 +:10B460007D015FD1C4E0E8ABB9DF1A0586733B0309 +:10B470000D5D9CC2AFFE5F768BE2F513BE7C594C2E +:10B48000D73A0BE266B2D14F14B2A43805E0664653 +:10B4900081F38D66064A2C577B85F3D7E28B7BE7D9 +:10B4A000879A60281E9079AF4D0B7CFFC775F8799D +:10B4B000CA23696E0A93A388F297851FAF22CA4CEC +:10B4C000039FF06E7503D56DF009536239B466FDC4 +:10B4D0009750A2FEFB2FE87688E7ABC2BFF9196A46 +:10B4E000684A2283D45BF4086E4C07EA215FFFBAF6 +:10B4F0009A9CC6FD566381C7D539B954B3DB13C2D4 +:10B500007E3FC1556C84F85D6CBDD8E23C1808984C +:10B51000B73930FE95C782C65B761B14DE4783C100 +:10B520004285387577F3431D658B1BBB6D2D8ED41B +:10B5300028362BD1DB3B33BE225E307055EE4A17E6 +:10B54000C1BFAE4B77253DAB9AFC9DDD8851DC1F1A +:10B55000B649174FAF3AEB14FF3A09F0E91C26FE43 +:10B5600004852EE1105D702960F2409A1D336B8BCB +:10B570007095C8A7E478E8C1DDD36BCC073ACECE8E +:10B58000802204B297BCD378A8B49D15633A9E98E4 +:10B590005EDE7B64EA81852A63602F50B10D24C88A +:10B5A0006005A0A629F01DDD0E185C6DD6592FCFC1 +:10B5B00097DD51070957D4A9AA9E8C9F02E0BBFAD8 +:10B5C0002118A3EDA8407E67002C412365ADAA7A1F +:10B5D000109691C58DB385BCE6D3360BD6EFEE360B +:10B5E000EBCA6408D0E2366774AE5DDE87DDB22F49 +:10B5F000382F836F90F95BE396751D7C1809407AAC +:10B60000F40EB5ED6970351BE1E27E2A834FC3422B +:10B610000612CC7B4E70F14675B1C2386130C9B4A8 +:10B6200040D11242D6DD6975CD6C8CF7F3640E996A +:10B630001B2FBE810F79ABD43597C30DB2A5F598FA +:10B64000A6AE8544D1AC8892CE0F855B0D10B36B4E +:10B65000297CE38D1EDB67C8E6D0C4923977675238 +:10B6600086ED4DDFCA3CD5069956367FF1FFF4B51D +:10B670002FACE106F1D082C6E85FD77707FED31D75 +:10B68000C85995A6AE29552323650E79FC7D82887D +:10B69000B1DC3EFF7A72CC231AD33002E640226A34 +:10B6A0008CECBB2C6838B1676F100DC727FD5FEFBE +:10B6B000BF701F84AEEE0D0FACAC6720A678AC9BBC +:10B6C000A2FA8F11293C8271B52EA7CACD1C998F81 +:10B6D0008B902FA8A7C2D04409C1A6E511F7DA5074 +:10B6E000CC62E2C31A5DF77F2F027BCF5F8772CDFA +:10B6F000CEB49FDC8D8A32494F5A273FBC3B521F44 +:10B700002EC118E86D05150A6E06BBCC9BBAA2A621 +:10B71000CDF87DB7C4756EBD6855D3C117AF85949C +:10B7200097DFA049BFC9E5D6B7BC6513EC0E9B1CDB +:10B73000B5F2DD231F428B0BA0CBB267DD6C721A12 +:10B74000101B0A0D29F84F36DCD440FC6190B64A34 +:10B750005FCDB6682926C3098F16FEA0A0C0BE31F2 +:10B76000C52B3DF0E800A8013AA653318AF7AC4555 +:10B770009C5999A29C04F02FB8667320213D16189D +:10B780006BEAAB8ED79B6FD9D9ADAE0E57A43AC733 +:10B7900031CE84D917D52C0F46676F4EC5CD88267C +:10B7A00085DB8C2FB05C7FD4AC19EF3321FC100308 +:10B7B00089B0477D1E0D2D4552185ED328C2BA3D73 +:10B7C0006BF8DA84EA15D867CF9AC985A9AFF4B5C2 +:10B7D00044CDC28DBBCDAACABBBE48E164E3D686C8 +:10B7E0006923D864B3B7FF6F585C06737D15126682 +:10B7F000887A773048EDF9D3F8380817538F89875E +:10B800003C5A5F04E72739A04410065AD882BC0886 +:10B81000D9958426C7163FDC0FE4CEF6DEFA6CAB72 +:10B820007C33F310D383A3A7571E2A612BD2FD7557 +:10B8300055325DFDB916659450DBEE0BA8E574F842 +:10B84000A66A2032C810E33B6705C2624B527E6B8A +:10B85000E97B24A2C13356E642A6BF89D59D2D1BA4 +:10B86000F591E41901B6421691838D75BB8AA375D3 +:10B870004F123135630A72DD54F4C1393875078EC1 +:10B88000257EC01DFE3A14EC65CB3226EDB59B76C5 +:10B89000A00D2032B087BA646EF3AF494F5B2F39E9 +:10B8A0003EA61CDF34E7C19DB5724C9631F1CACC7F +:10B8B000BB1884B0A09456356ACE7C1162A977B5C6 +:10B8C000742A1B9BC4243EDA1566AF359E8C2F2943 +:10B8D0004F8F6C7214546E0F32B82DFFD9230CECBD +:10B8E000BA3F5351B9C443B478448BB5161924DB1D +:10B8F00016E0A9D634EBCB41FEFBC4CD39D72BE201 +:10B900000A035265E13A025B332E0A652448469ADF +:10B9100073B7E063AA25A9B65C7FE719FBDD4E315A +:10B9200081AC544A94F42C099094D4C8259435A938 +:10B93000C70D922FDAE40AC8E0F912B0B0A9A9CB7A +:10B940007E1745C07A521AF1A1F14CC77EC3CD19BA +:10B950001555AE077D9469185543F115CA7B093A10 +:10B96000EDFADA07A0605D6192FE013C1A6697BBB2 +:10B9700036D997A220E8C0BAEA2A66882D4CCB9720 +:10B9800045725BC33D66C386EF53BC0561A33EA30E +:10B990006381BE99263DEECF7ABEB2D75F119C5926 +:10B9A0004E1FF5B4233ED1F3E45FA7B3D2A6E21055 +:10B9B000EB4D45458643DD2B566EE0DD21C570928B +:10B9C0008FE4E9412845028CADA29BAE88890436FC +:10B9D000E1F053CFCFFBB57E44AA1C317510A5D042 +:10B9E000C41D5368EAA7B01E9AF9616D7064A9D2AC +:10B9F0003ECD61FAC9AF5F11B80EC12A5169E7A601 +:10BA000043FFC63214A473C9FF65CD8B5EA11453E6 +:10BA100026F4B23CAED15F1679A78FB40686F43D0A +:10BA200029FD30B1C22867FB7B4DAE74986E1E9F16 +:10BA30009ED8FD575FB09A81F077DCF35601EA7A21 +:10BA400055CE4C867F8D1EB0104354B28B20265AA3 +:10BA500001C02EA266CB3D9E34075F4375E2EF4CDA +:10BA6000BCC2DB83C3128FA8B04CE3C1E094E18871 +:10BA7000E24D52ECF27D7CA157A7F7048C8F9B7DA1 +:10BA8000F46022D4DB904938C101EA2504CDE0E816 +:10BA900016BB9174D8373D7D4F1640130E63BD32EF +:10BAA0009CBDCB9247059F09F6711B2B62DBA3500F +:10BAB00071C512DD3D1D32E762A39B079132670914 +:10BAC000653209CD28DB55CC519EE4C951BD20D942 +:10BAD0004AF942F0FEDE11D07345E0EA21D2EC9241 +:10BAE000F027CD9EE83F41751FE278EF3547E836F5 +:10BAF0001B5026281D27C260058BB684BD86739B0C +:10BB0000E8D674CBF293D7BB53F05F44374A8E1418 +:10BB1000B3DF96C0931A5DC6EE87E6F7F5A5906091 +:10BB2000B32FA2EE16386AD7E60D98F8CCB083D1C1 +:10BB3000C2B7388ECDA6610AF7A82D22A66028D7F5 +:10BB4000F3DB713FDDE4E96ADCC275E957BA9B2E8D +:10BB500071F7C655DF059EB74326E895CBA7B4908D +:10BB6000143EEA2D6DBF0601F6A48869E7A2B3333F +:10BB700008FBA4209878DB05CC2EC0AA41B395C160 +:10BB80003B5796A0FA9C3C439B854014C846A8D2DC +:10BB900006439AFF8EA0B76A5FE927CC7B30AFC916 +:10BBA0002DE55A26BB0C9D32AB97A96E5920A5FCFA +:10BBB000ECA0A2473FEEC8E296A5311D605001B14E +:10BBC000C00FDE97C028E724A292562CFA7D54C3FA +:10BBD000DD9A5039E059A4AD5C8751D65F41B6B3C8 +:10BBE00024257CA7BDD4A4D7BB74A47B4BCEC7A20D +:10BBF0009EA1001712D5ACF9A71137EB06DC63E95B +:10BC0000C4A91CA382843667810EF041E5CFE7F713 +:10BC1000BA03ABDC6444C5D77E237C86E8CDC8E19B +:10BC20006772C19AE17B264C6BC358AE5508648E8F +:10BC3000AA5C3F566D748CE8997B101AAC12C44D07 +:10BC4000FACC120ECB9D4D2EE9E295497DF5F9B166 +:10BC5000D0F185888F08904D0CED462F81988F8DFF +:10BC60001085FFA2E19CA556155133A3F785139DBE +:10BC700093897EEBD8FC355C83A75039F403A1612E +:10BC80004524E2837BCB6D9307B007DF5B632B1208 +:10BC9000990002F33A94D4EC39450170728D75AC79 +:10BCA00064CED6F5443C04B38204E3CA394CA37194 +:10BCB000BC6F4C45C8B99D7FD21AE8306F42976E71 +:10BCC0007A63FCB7C94BFF672413C85F0986888075 +:10BCD0001B877A994FD164A87214238C1E0C45EBF4 +:10BCE000540606E0B5A94DAC0CA7430595956769C8 +:10BCF00031292E2F0A705447279F1ABAD95A2F5A22 +:10BD00007DB3316BF219C879C268060426095EFE5C +:10BD100013EB4DC903DFB01DE558C357E2077EFEA4 +:10BD2000E134C679375638644C77B597D0EB0DD1EE +:10BD30003D5CF1445B8267E97B256E0A19E256C7D8 +:10BD400094A26CDAE913EB9B392A5D7F11C84F3A54 +:10BD5000C29BF2430B73543B6C21951C842172D718 +:10BD6000453652C7F57A2D6D7760A107DAC4D9053B +:10BD700099D1E0A7338B62981F2183DDA3D1E99D80 +:10BD80007F3534D2E6557D3CE3CD22A4ECF2561A41 +:10BD900066E6AA172F175B4FA674B429D288E984E8 +:10BDA000858FBE7229466E24C6C1678594C534CB83 +:10BDB000700A9CFC729212AF52758CB54E89A44EDB +:10BDC0009CC99C5E1E85CC4868A5E8FB9035B4C92B +:10BDD000D9C001D300B4F966CB61702E50F3382876 +:10BDE0004C6A2F2B76B3D285089F47EC0E9A8EBEF5 +:10BDF00011D6978ED6363328C8756DBF6B91772EC6 +:10BE0000B0F55C333D23F4EB8FEE6003E68FF56213 +:10BE10001D14C0CE3EA538B7A0D3A2280AE0076300 +:10BE2000C49851240EDEF93E395EE1CF162F4BFB4C +:10BE3000BCE08212CBEECEFD0721688531C57020B3 +:10BE40009410539F1E9A230242A383133F38B47564 +:10BE5000775B4565AC1EB7547B08D443AA4A892555 +:10BE6000B62687CF9A9873E715A9C759CAC9E76854 +:10BE700039F42AEB905EFF714A4CA095DA8EC245E8 +:10BE8000992984364BDD921AA87DAF8046BDF7B064 +:10BE900043B7CD0D880CC0DF0510B60B13D88C034B +:10BEA000DD49D2968C4326959C4BAEE0B32544D415 +:10BEB0001D41FBBF5D3531E835305A6089D5A3A5FA +:10BEC000733DB4C403DDFE64CC37E3F3E937A51654 +:10BED0000D4C60D27F6FA97BC9C7D33EB45ED3FF40 +:10BEE0006D41D46A35C1D08D4AF52C901F6B0AE89C +:10BEF0008E715DCC0A0BE1A02FCD30794AC3981228 +:10BF0000DD13D3F88249D0C8AF04EB35322AAFAA8B +:10BF1000665EC1A542EB88C8667B73FC33ECE63AEB +:10BF2000F6EE02EC911D7AA07AB3F9CE6321C6F742 +:10BF30000F49DEEDDA48E9CBC88C96AC410F2737C4 +:10BF40003F49B862C251B64B73ECFAAEF61949CA12 +:10BF5000B7C010C8BFD730F6720BC1330700854F8A +:10BF60007620295259BAFE35D6ECF4A2CEE6547E9C +:10BF70000E9C4FA940579C75AFFF0A867468012E2E +:10BF8000D849F34EE84D245598EB0738ED6188F712 +:10BF90008FEE9CDF4C0FA2A7BC0857E87654BA6915 +:10BFA00032BAA204021047F288E709081ECA7CA729 +:10BFB0003803BFA5A3DD3BEC0ADC375BB23D0115BE +:10BFC000B3120A9F48F02B3E4B9CAA15E405CD12F4 +:10BFD0004485076F8261075CE39E02912210646DC5 +:10BFE00070F7A76C3E48A28DE10D2F0A0EA8BA6922 +:10BFF000AA3E6FACC4495D6B9422B71E16C3B40B46 +:10C00000B213CAB8907D1D9F454A8F483AE8896BA4 +:10C0100028618B0B598156B7DA76C523356EEE3120 +:10C02000E23C835B7E42CFBCF4329536E49B8717BB +:10C03000D8A03724F8E36108F5BFFD654AB5C3F31E +:10C04000CBF804FF808DE809BED793BAFEE96CBB3C +:10C05000263DCD32B4A1BFC364ADB2B7096273B29D +:10C06000D33CB2B161531F7731C195F836589180F6 +:10C070007456A20975EB067FE12ED3EC1E9BCA7F96 +:10C08000ABE4C4DB2A31D4AA9CA49DA5AF14E81567 +:10C09000497AD09509FC16C0C67D1A0769C7805732 +:10C0A000E62524487156A656DFD7AA350F4D896973 +:10C0B00062BB3547228B00292947AFE9F1B3EAAAD1 +:10C0C0004198C42D7E5A0530013ED0C4EFE772611D +:10C0D000C96F0E6AD2D2EC8FF6AD8A53B81FCDBDB0 +:10C0E00032A6715AB9C9158DA8A801EF28D7C9EB96 +:10C0F0008FEA084D6542CE9133F36BEE03E54A902B +:10C10000DF07CFD13E7F02D6A5292BFFBAA936D7AC +:10C11000753EF8C34A579A7A981D5812173E392F20 +:10C12000B1833DF10E7D9237BCE5ADC1D2ACD8CC28 +:10C130001F0763AB2253AEA9DBE824AB0AC8F79B09 +:10C14000B594C41F809B87D92E7E3EF87103FC7482 +:10C1500006D32ABD9C86EA479D404E0F39E2410432 +:10C16000B1C56594E2458B64622C992B13249EC063 +:10C17000B0515795319A69BCB7932A8E01817DEDF4 +:10C180000A464DE4E4601425A541DBE1E9256F365C +:10C1900093B8EC3762D2F035405133C75F9B3F3ED6 +:10C1A0003965A82EFAF6DA06BD2EE71F990A4AF07D +:10C1B000FDABCA135B1F6671B375C328BCF3A7AF91 +:10C1C000A5FD2BCC7CA0DBD539F87EFD2816DEAC96 +:10C1D000171809433B49D2A693617487F7A50BE072 +:10C1E00053CABAB5C31A31F306C90FD10F56A77790 +:10C1F00092F6344B517B10B4B328AF60DD670E0E5E +:10C20000B1A50FF5DD481417FC68235E7C0FF1D053 +:10C2100009FB7E02C749CBB42D76057CABD30F0258 +:10C220004876A56CFAFBD72D19C6C29A36B85AB60D +:10C230001CF4D768B40EA7F61AAFAF17E4CC76ADEE +:10C2400058BE2F1B21BFED3E87A9D8A82C23FE196D +:10C250007820833A2D758BA6A9FB1EFF8D46CEDF75 +:10C26000C4AAAB75FC5A9B4251FF6A33E7EB68E303 +:10C270001581D990A7631C3A79F5E7C5CE2E54D71E +:10C2800065796F5621BD28743682BEE5E0E9D74551 +:10C290008F98388B2190FD172DA124BB065617B619 +:10C2A000F814FA5BB05C4020E617F3C3DEF7396C94 +:10C2B000254B241BF17DF590344149326AB8A9968B +:10C2C000FC593C746630E9FDC9F54C252005E0A217 +:10C2D00078048059944496F843349B82B1D161EE3E +:10C2E000CE045B6F918974FE0747D6A0565C869A90 +:10C2F000D58DE68021C37E1E551BE7B2AF6ED2E31B +:10C3000020C549498F23E9BC2620F7243843D6337A +:10C310005E2132314089743140A00B5AED83AAC1AD +:10C32000C8FF1ECD28CDC6A465999117F548FBE23C +:10C330005B3C95C2FC54137C285D135F042275C1DD +:10C34000F45B2B94C463CFB07C729EA3C3DD34979F +:10C35000C4B754F30D3E8F7488056E18444740707F +:10C360004AC618F42705E3015FAD91F8D84F72B5BE +:10C37000B3EB98A7669D46AE5ACD45D2B5552ECBA8 +:10C38000D58CB6DBD9D1303421C25491A89F5A390B +:10C39000167DCE46F80FF2695524CF17A3780ADB35 +:10C3A000519EBF609B0504437ACA6B1E04DF401197 +:10C3B000EF9220ADB273FE674A3E598473970A9597 +:10C3C000DE771D23FE3BEF3DF788466EAD6E1716F8 +:10C3D00048BCFA1692633B5229A5B4BA81266C7602 +:10C3E000B7B441AB4A2BBA12094C03C73ECFAFF5E5 +:10C3F0001F531C2200FA9AD13268B5ACE30EC8353F +:10C40000535D8BDF39602948869BC1D3D1FC480D31 +:10C41000D115A1887CBC2B6F136F7D7CE3AF59E1F4 +:10C420006965B742EAAA713822D7DF7A9A544A1F5F +:10C43000748C6A1BABC469B1B429062B23153B8BE2 +:10C440005EC41BA57F8919CB571A27566928FEB6EB +:10C450000A8E9ACA0F24D2A369E293F50D8054C6BE +:10C46000B98839777F5401B7A6272483DEB1D77105 +:10C4700062D202C4E742ED9753A6B9E703D4005B4A +:10C4800094A52684A659C6469D0D64C50FE2726D1B +:10C49000986B73FD02575FB5AC0249DEF5B7A22B6E +:10C4A000AA975D5F635DC491DA93860EDD4DDA6015 +:10C4B0000C6F62F7DC9BBCFA2F9ADBD86273DDD974 +:10C4C00091A9EBA64964FE8F82F2F6DD4B1B1E514B +:10C4D000220B36D0719E7313FF5239D86442DEBAF4 +:10C4E000D07ECE3B89ED69A27D5C8515AE06955F59 +:10C4F00025A6918C68E86BD91A6C582E5B980E941F +:10C500009613D94C01F72677F46115F40C9AB23BD7 +:10C51000816D867F25CF7E13FCBE0B58182D0EEC47 +:10C520002539A0791229927031EAA0B53015A75BA0 +:10C530008B8D5470E76E15C29AFB66E225B314AD7D +:10C54000D88988E8FDEEE0D32D731C98C78BAB8BA0 +:10C55000BC1DA4246F30C45B72CFD4A1F66D1464EB +:10C5600087332C3C73AA00A3E8026D6F125C730939 +:10C570002542313A86471F75AD3BE57B00CCD82C70 +:10C58000F71A2F186955830641F5B2EA7E1BEA06B1 +:10C5900080ACA98ADBA04687C394D1025DE6DCD6D5 +:10C5A000A18196A3425943B77AE6B27AF5E8D0F969 +:10C5B000CB4C6A6AB89F3FF231825EE45315663411 +:10C5C0008DF27215D5A061092C5B94800CE037D1F7 +:10C5D000CF9AF6B5E9DD312DDA291AA140C51BDE67 +:10C5E000A98703F64773ACE6C8F89B6C3C8C93179D +:10C5F000C6EDB13C02544EDA8215D0A80322140DC8 +:10C60000638172DBCF7DF1654BC0CE5FA0EBF51689 +:10C61000E8B1B193E828F573B4169BBB2243CBA8CD +:10C620004384D80833B47C544299DDC1AEDFA86797 +:10C6300047A0EB35600E8947BAA7818B9D08A514EA +:10C6400042D7FC4D128863291EC9C7368137362F61 +:10C65000EDD2046A6A75AFED5134E24FAB31753DEE +:10C66000C83616B1FC86DC5B8B08521563EAD88BA2 +:10C67000EC889C04C11CE42F536880FBC6DCA5B881 +:10C680009F448E2BAE884A73D03E8CC507798B456C +:10C690008A616B23350172D1ED53FB778A1125CA6C +:10C6A0009924FF133F1EAC05D7DAE20C51C5B7C37E +:10C6B000B026407B5484CB07F9810DFEBDDF68AE08 +:10C6C0006DBA83E0E980DE3CA2BB3C578C8153BD50 +:10C6D000C44CB5D7105E1B2534B164B39F380991A3 +:10C6E000061C666E3AD9234D0CE5AC0DFD7842AAC6 +:10C6F0006E363B7788873670CF31965F13CD8317C0 +:10C70000DE0DA6FE932F32486A1528C9B9754B7203 +:10C7100009A871653B7843F59955C4F0E69C9F9C48 +:10C72000DA7B6B91B750050AA40D8EF0D59842AD17 +:10C730003CE0C0A66388E9E3CF4209A5CC58C423F6 +:10C74000AC2B268008A864D8B0940F6E0116138015 +:10C75000957D8213EB2B32598D659EBFDA15F784D8 +:10C760000A1E2177A4EA5FFEF8FF0D7BFF2250E648 +:10C77000430EF8ACB0B8BAF5BEB39A191C6DA46EEE +:10C780002145F7FCB2F2558818E1BFD53229FD2BBF +:10C79000EE7A63DE1D3498AA5F942D1042A533DF34 +:10C7A000144AC69B04C62CCE6DA5126232FE7410CC +:10C7B0008EDBBBDC7B5AF61D75B7EBB297203DBD17 +:10C7C000162B702411F806BA2CC360A913E055F893 +:10C7D000B18F8E8D9E552E9E48CD15358213F9CA88 +:10C7E000631D2F226C8F999041E0394C670F92A7FF +:10C7F000EA6D588C52BB21C8512E4AC58FDEB5F167 +:10C80000C3D3EEB13A7DD7624F1FE26AF5589879EB +:10C81000CA71C24A11A6C171B5B23052C414D9E866 +:10C8200082AC20AA56D9FF0A9D9AF8C5CD7D3B154A +:10C830009BEC43B71A22AF33764D5E6DAC36EE18E3 +:10C8400029B5C2346ECB9E0C60569B899C20C32EAA +:10C85000DEB8545816D273EFBC66422424A1BF0C34 +:10C860009661712F325FEAB06DB0980B72B1EBA494 +:10C8700062389812871970C84E950BD994999FD534 +:10C880009D2BA1F4E84E32402D6437BB8DFB2FC8A1 +:10C89000A31B3BA99F651F27DC4232832E1C2F7BE5 +:10C8A0008ED36B24E21383E000AE86C1765093A54D +:10C8B000D68C880E9570129A85A727C4DD7BF4115B +:10C8C0009338F2CCAD4F7026D1473E759B05F4816D +:10C8D0008BA652A19858729C8954D2E8E3F2E234B4 +:10C8E000812469017AE2623E152BA9CCC0489A14D2 +:10C8F00039A57165D5BDA91EEF80D9CE58CECC30F3 +:10C9000042B77C09AC1296ED3D6F90F19636757783 +:10C9100089020114996BF262AF00AD94E62C5A16AD +:10C9200059043E12CD1768B378A161B82BEC658924 +:10C930006F16D03BE5C803277B537A6613580391E3 +:10C94000776CAED4EAB77ACC41E7E60D4330404E7F +:10C950002565A20A8F0B3195E978F38F83FAD53FCD +:10C9600038C9232A8FCC66E2E4CD0B6E2B340CDA67 +:10C97000341FE1081F299EA92F145A15E6448A9BEB +:10C980001520F272FF15D5AC00A261E1F095DC1123 +:10C990002E293F30B7E6B9D3F35310BDC73ED5D2E9 +:10C9A000F8BB46A8EF58A8BE3F242126F14674FAEA +:10C9B000B4502144E04CA4E4EFE7323014B8E9B7B6 +:10C9C0001149532A1B3402416A9CE4D623DD34EC1E +:10C9D0002CB9F919B06B1B8FE16581CC1A6BB132A0 +:10C9E000A8ED228D9AED20EE12FE10591E55CA9721 +:10C9F000AB1F96D79A10376465BD2869B1E2C9A10B +:10CA0000E4C9A6A9BC50470599BD46066F291F4039 +:10CA100015DE89A7C462AB8C268499216D5D31D463 +:10CA200023B86A332BB789F8C04EF8DE1355F7BF29 +:10CA3000384143D5DE70853BB36467125550536B64 +:10CA40004537A2675FF9039124DC6E7AE7FCF02595 +:10CA5000A743E92FD318E92622D60267E5A39F064C +:10CA60000ADD6C0B44FDC54EFE7EDBF7162218ED89 +:10CA700070E7C2FAC15CA4F153AAAB8C5D27675C76 +:10CA800036C46D83C9D6D49C56447E93101DA6F13E +:10CA9000D6D0119A18EE124B5D07ED3900808566ED +:10CAA000A6DA497D55C11F936383ACC5DF7DE09253 +:10CAB000B8AC79F4203A05AE8F421ABEA18AD79D50 +:10CAC0000E71349236E47BE32F8DDDCE9125B2A733 +:10CAD000A62568BCDC7FBA6216AD941F8E339CA17C +:10CAE00041483F30F95EF1ED97FBE31228A17DC884 +:10CAF00067A50232A77BC90D021C96DC1F011A290B +:10CB0000C579942A166EB17C04C561F332D19C2993 +:10CB10007D0025934C7F7DD3DA22907AAD90779C6F +:10CB2000426CB82EA18D65EFC8476FFC64EC40EDF8 +:10CB30005E44F5A98F326D2FBEA74A3C4C92C07F50 +:10CB4000E0D75A06A6569308F3608BFA4C67CD09D6 +:10CB500005B4581ADA99DFA5DC237CCE894209D5C1 +:10CB60005265651F6182390206F5836DD6443E0326 +:10CB70002488E1A87920C092D9CA2CA2ED084148A6 +:10CB80003C56AFC4B66677A8FB5A82F29DD2379B5B +:10CB900057EF645DD6C9CFECFBF004D85276EF7442 +:10CBA0006AC2F87107C45521A240E8308757F801DE +:10CBB000754F7A06D8F137E157994BBD980078A1A7 +:10CBC000897BF870D587640A485A6E65F70D799CA1 +:10CBD000037A85BC1AEFF426B3AD16A92ECCD08407 +:10CBE000465763182B081E6C56F6DBA0C596B4B5E5 +:10CBF000FA5DAC24D8386B632A232FE8AB483502A2 +:10CC0000A67D2C35C418139B918FE5E8B2798BBDB6 +:10CC10007438D518D72B4B91A6A133F30895C6E3EA +:10CC200040C60AB19FE7502E9AE35D9018E254E99E +:10CC3000888F58F4B421823B039737AE28F9D07817 +:10CC40002183C031678406AE62FF4905B042A14C22 +:10CC50005C586F29193C735D8435818CB5657F42C2 +:10CC6000A5E80F1902C3B5D24A03808320808B0F39 +:10CC70006768107F8D5C0EE27CB942DE25874DB37C +:10CC8000F3996A3CA663EE894EDE025FA3FF3CA7E0 +:10CC900026DCBFB43DB19196B3B8A714FA84D5078A +:10CCA000A576089972B82ABF299D6DAEF4E6129454 +:10CCB0003A04D47720E90078690EDABC3F8F3B4212 +:10CCC00094BD083D17D1E5E1A5101A22990EEAC2DC +:10CCD000665742BD26A9F53530B7804ECD3E79FC6A +:10CCE0006B586CD8047135C5220443BF19F550DE6A +:10CCF000C66FCC7683367D473E83C4954590DFF47E +:10CD0000F414D6D99FE1DF99901BC8D68A96BB81CF +:10CD1000EDEDD4BD9CE37D6997088D3043C3961833 +:10CD2000D5F5C1B7F82D308B47069A7B35F1592ED2 +:10CD3000B8E31DA5D4CECDC5BE88E873EF7A14F054 +:10CD4000D970BDDDAC2DB293C3B0E39D8276B3BE86 +:10CD5000A16F0F13E4E62C0B7B27D971D034D7B227 +:10CD6000FCF6CC434AC82C85A24B28026D1AD3D0BE +:10CD70004BACAE738967E842468D505CDA8F4CAF9E +:10CD8000724D99F6F48DFE19BAED849C71ACDA4FB0 +:10CD90008ED86365A6DF36095E36F9BF13A9B8D50C +:10CDA000ED2CC75E64EC00F25B876344ACD6DE57C3 +:10CDB00092ACA203B6D258F388D2E1159FF15BE2A0 +:10CDC0004DDF33BDC956D72B12DDEDA6079FBF053A +:10CDD0009440D0572141C6EA3ABEA9BCEC09C7D15C +:10CDE000626857C20936172B58C372E1DA0510A2E0 +:10CDF000699BC030F00E5D6774441085FE81ACC93C +:10CE00006F2928121816CEB0C28B4767AE2C4CDDA6 +:10CE1000770FC43CB28C6E1C469AFFEFF720AE1F12 +:10CE20009805EC40287CF17B36FB5737DE61A49DEA +:10CE30005A8E1462568B4A9B09BEDF157BAEA0DB6F +:10CE4000DFC816CEA3788D3D4F3B2B176B4AB868D1 +:10CE500058E4648C96BE9C138EA42E5872505629AA +:10CE6000A4D7648A3F40F01A3F8AAD6CA35BA1301F +:10CE70005F2F9383B422871499AD90556978FD365E +:10CE8000C5909CD7532E09D5A83726922610799A9B +:10CE9000A39CFFB9A435C3E1EA78839280F955CD0C +:10CEA000BC359BCF1B1D73EA01416AF41030C2668A +:10CEB000301518D92191E6FEEFA336E415B6791E98 +:10CEC0004F4841B510C395B87A7743B7AC436FF17B +:10CED000141606ECC77C9E44ACD1D4F8F4378E63AC +:10CEE00041ACC64F4DBC15BA0237FC9C310F2648E9 +:10CEF000E8608088CBF8A696C09027462589935590 +:10CF0000EEA8FA95EA9F6424839589D44C18C80545 +:10CF10005CCEAE54ED0325133FA69C7C4CA4873712 +:10CF2000C60773DAA4FA331579F167C10F698E82E7 +:10CF3000CE62A62DAED0C906975ACAB1AE11CCF0BA +:10CF40007761D4B72CDFD4B1BA922B529B08D3A50A +:10CF500051D80BFBEFC27C6630104824A1AA0D0A01 +:10CF6000B96699AC28868ADB2D2039044CC6422F3D +:10CF7000BCFA6391B173498F3CBE2C1D509BA978BC +:10CF8000B7ABBE45A1163125C30B311F500B7597AA +:10CF9000590540A3E348ABFA6AC72A6AE273269AA6 +:10CFA0000918B9AE0CA7CFA8C92B87B07CFD738236 +:10CFB00073120FEF7ECB42BF4EB20AA224185F81DC +:10CFC0004281F618D407015B8E0197AC768FEBCFC8 +:10CFD00077EFBC58632EB768FC2AD67908D0EC8965 +:10CFE000B9D1CDCDC36B9D0763C226B4D171F3898E +:10CFF0004C08E0CD9BA1E048F2D3D2234B16176A30 +:10D00000FBEB36CB0FB88AC5A8246F16A803F844EB +:10D01000D815D390D185A9385C667DD93771466B18 +:10D0200089AB392B104ABB850134D94AF38C952E34 +:10D03000941FA102015226057AB353867F7F4FF9D0 +:10D04000B61583B0D7DC746C00D357E7A2CA6FEE75 +:10D0500059F56E2F74481364A9F2777A4ABAB6E08C +:10D060005CE8FAB19396F85991045C3FBE343BAB4F +:10D0700031AB6FE547E78E2D530986DAB123BBB19B +:10D08000F87392C904C8D6F178E9A931B0E6920ADA +:10D090004BE292EF43CA208C956858BFB27AD23ED9 +:10D0A0005674FBE996F1A982D6D12CD99C977E398A +:10D0B0006C7F55AAF0637EB1B80D2AD5C42AEDEC79 +:10D0C000E106A68B8232DF7EC1FAC9C31D48F86033 +:10D0D0004902ECC72B34EBD144978E857F824332D3 +:10D0E000A7B6B7E4F925F2C0B461510C9644B6680E +:10D0F000CB4746081E73E22F002BB43AA0B4A7F525 +:10D10000D0810918F88F8866D4D20F96995953099F +:10D11000C1BEE5F722DB2D710CCF1B8C5386085F57 +:10D120002F101874E421B7C9E80A5F0AE5E987B946 +:10D1300003B5268255BBBCEEC98A321455901C3407 +:10D140008336A27C74009CB84F519ACDBFE95D989C +:10D150001BE1D5E9E2172E064F5C09BC7EFCE47F9B +:10D16000831A51B0A071D28FF9B057848B58EC5507 +:10D17000F22BC7DD8BA4B3EA32805249FD771DE361 +:10D18000CEDCE74C636F11AF4969251D79943B7E76 +:10D1900026D499606ED0A178A9DD2053CF198D22B5 +:10D1A00011FB84E77C57BBC119EC3F7DD6A752EC3D +:10D1B000605201EB95100B60FB96A5CD1C2987886A +:10D1C000A7E88ECA1C5578340EF49A5A2D74C2FF03 +:10D1D000D1D82A2C617263ACBEE8A7141CACDB1B4F +:10D1E000DDFA6561922F956B6F1637DC57F5FB6C96 +:10D1F000770B3303F13A862E209F2A145AF2333AE2 +:10D200002AF62FAD7E2122C5D3BB46A10559F40CC9 +:10D210006276187C59C3613301CA85C6B7854EAEA4 +:10D22000B54EB8B9C07168A0C33E24019653D92F3A +:10D230009D08D312ADB303576862D4CCF777F1CF12 +:10D2400004C54C068894F08FD85CF7DFE1C74B2407 +:10D25000A86777555C4D44F9A218EAC8A0BC3C2DDC +:10D26000344377602D786CACA0D7FA8C78D2069DC9 +:10D27000231C87C83600ABE34CCCE690AD6E66BE8F +:10D28000149D871C3A5C7D3E1C6C062E644F208BDF +:10D29000F92A61BE1DBA241D87377D2935A71F9A3B +:10D2A0004082472F94AF29D6D26FA0ECDD50733B5C +:10D2B000C4F220491A463B3302B01ACD77F937EF52 +:10D2C000CB3C435E4D459B2EE5D9ABB3C9881718BF +:10D2D000694959C215A28F7AB89B6959FB862C1BE4 +:10D2E000FACD4F4D93C41E482E253C5EA657D21250 +:10D2F0000A82BA36085826DF8B25C253FBFA758A94 +:10D300000C22A6D9B163902B22566FD530D73D772A +:10D310000F4553FBE54B674C6E3CF9B09DF7FDEBB9 +:10D32000470ACDCDFD3DBB6D54BE7B42855AFFCB38 +:10D33000A3FE5813E8355562A90D587B082EB0ADF1 +:10D340008FEE1B01C6CBA9E65226CE1A2E03B3568A +:10D35000858B845854D46F1C665B5F9B55C0283006 +:10D3600019DA7F99D9E45709C2330BC3F8986D3C99 +:10D370008473EBC30B26287519C390CDDC25FB5AAB +:10D38000EBBA428863F2C0891E215C16F898F26CF1 +:10D390000C17D6B4C56EED0D098DCE14B286FD18EE +:10D3A000A713612DF4C9BF9D2ED56E91EB76F5EED6 +:10D3B000DFC8E763C8A428E1F6B4376D55C02A3248 +:10D3C000447403240DB3E95477B3B88A25CDC09EC5 +:10D3D000A3B826CCCA067C956EBB49F86ABA42DD72 +:10D3E00091E4A2C1EC8760D52C9ECD9E0BE5CFDBEE +:10D3F000BFC5F503D3EDA25119605F9E9B970E92B6 +:10D40000AB0D0126C676A04F3A006D897FA362124C +:10D410000B38BAC522D076EEF0DD68B566423A3EEA +:10D420008D6AE83A699307300D4C985771EA705548 +:10D43000490B5F11CA0391D3D4D16A77BD4D095905 +:10D440002227BCE00296E32DB7ECAD2091385EF8C0 +:10D45000C7AAD6405CA0B2CF734D1A378A6C8387B7 +:10D460008DB4E98EF427223CEF1F572A0A0E00A53F +:10D470002C2FC0C55D2573DE0588B2892AC5D5F37A +:10D480009A32DA2BA16A2F07ADEC6B51A31E0B1554 +:10D4900022409924673BC2185F38499436726B9FCB +:10D4A000A407C5155CDC8BE7F3B15F03CDD6FF6045 +:10D4B0005B210AEDD2D51B489C9B948957E85C6997 +:10D4C0005EFD4A564A79BF4F804ED2EF5C383CBF72 +:10D4D0004905420D72F4C1FEC3405322290CD930D4 +:10D4E000F46CDAC3A27EF3D6242386C4FF08E6A236 +:10D4F0000DAB522EC711D5990A0B3421B9B8743F20 +:10D5000089D6905B4753F404CAC5507C4152174BEF +:10D51000960B2BC0E04AE81C370FCBDCEFD71D0978 +:10D52000971F75471A37D7DCD2BF4DD9EB6E16025D +:10D5300095738DBF3A114541C30A7FB410407DB445 +:10D54000F16030BBD8D011677B86F507BFA560EFCF +:10D55000C7A1E166F266DCC1B2337D390D0EFFF280 +:10D560001E004968E9E60DCF6BC1EB1C16648F44C1 +:10D57000BAAAACCA06081EB2A1244EEC397E8E525D +:10D580002C26B62AE2F9E27D16016316582D967212 +:10D590004EA3045075301117277E5579AC4C7C286A +:10D5A000ECB0D7DFCEC4BEAE77B781ECA0332E8C03 +:10D5B000A89ED320FBBC5EBB98896CB972121E95E5 +:10D5C000C93A946DFC7D782E56C347FDBBD821C463 +:10D5D00079602EA5BD15C13226A7484B8119A40537 +:10D5E0000AA1B04D4C5528B8B07728D6EC83D79F08 +:10D5F000E605A35165858EA7A7E23172C33AE158CB +:10D60000C674589D3719F58B8462B8B5010AEA9A39 +:10D610005C739B9F4AE0EB18887C701048BCF0D785 +:10D6200002879862E0A5D6188F747EA9DD8CA3C40A +:10D630007EFD0EA450BA78A0DB23FB4AE3A2B2A77A +:10D640003F214F1E1E77FAF0E946EABBBEEB3937A1 +:10D6500003BDDF99B6FC26AC969B5177241D9EDD59 +:10D6600047D8C4655A9CA258B8570539EACA9F9B47 +:10D670007EEF7AE6A9BC3DF0209C3CD23AF9C50F7A +:10D680004D0E718D94D8B491094CD971409D3CF0E8 +:10D690001457F836CAD016EAD3844A991E8F7FA74A +:10D6A0004563E0D45F2228B2112AEF71AB8FAF3609 +:10D6B000F2B6A614FB27A0CF025CD7DBCA76CEA2B7 +:10D6C00069CE6B4E2EFFF3F2798C4C8D89BADAD18C +:10D6D000270B6172EFBAC29D3E7F052FBB7DF16EB5 +:10D6E00028540AFE40442A1A53A2451ED9B19A185A +:10D6F000F5142AFFBB562A2A3D06C0A3A0952B018C +:10D700005A8149CC020B2C376608AEBBC8FAB41F4D +:10D710001035B846B02F072D2137DB070D531E9D5E +:10D72000F766B2C8F3D0F8DE8FE9E1633C74C46DEC +:10D730008C5B27921A60A46BB9C3C33A5BFF48B4F1 +:10D7400022738A1C8DC5C1F5196135CE8F8B87A5D3 +:10D750009EB60884639F29960A042DF49F62B3EB5A +:10D76000B1DC3E839F98B8851D0BB20C960F86EBFB +:10D77000231FAB1B930CCCCCA1B20D6EC6F6038459 +:10D780004DA3B47ECCC1C45851F74EC732BF1C5212 +:10D7900021813DCACA9950CEB448BB05A961CF4C7E +:10D7A00060E38B2E8A36C3901D04FA320C27A084C6 +:10D7B000BD920CBF75EF9B9AEF2D0D78952B110044 +:10D7C000915C4F4E6FE77075195449C3EAAD846997 +:10D7D00072F6449A50814BB6619FF8D8F5BF7CE54C +:10D7E00062D1FDF714E48FB0E56992550AA6D367BC +:10D7F000AC27B6D215F239345C607571C6121A4E78 +:10D80000177C37F5B57CC3E32DC74C14685C5E9F6D +:10D81000A86238EBB31A02445D4E9E931B3300C2DC +:10D8200017DCD98A0E141C0E9B5525DB514D45FE85 +:10D8300026F8D3C311C2B076F0646B57A58C4DA601 +:10D84000964395398CC33365FA6806FD19C617618E +:10D850003715B5D095B60A5960C38320642C2CA324 +:10D860007D37E548AFBCF1A9ECD34E446E3B96E161 +:10D870001A29CE405F4CD1AEFAA3B639FA1E796CA4 +:10D880004B6ABADC03E905F290EE5D4EE7BA5A271F +:10D89000226EFC91A624A4B38C28D7A4F2235C4C5E +:10D8A000EB97E055659DFA81B62E69E7C882864CF4 +:10D8B0009EE7932756DD11AAF54B8170A5D72588E1 +:10D8C000B18545C04A9CFC6821A6B3C7EFD77EBA94 +:10D8D000CC4A3A2B57122B89EBA307747595225823 +:10D8E000FD31D394E32ADAFD637B6555E9FE7FF7CA +:10D8F0005BB8CBA1848F838DCC357B8E20BB4A3126 +:10D90000E7E24B117FEAF3A83331F3FDF537749B5F +:10D91000E5BC9B90A0A80797727A35293C60DEACE5 +:10D920003251FB0F531B1716CBC15BF5DE1EF5A161 +:10D930003AD0E88F5D7BC812F9D46F405DE540B402 +:10D94000FE02407FF5F53AF7423D1D44226EE33179 +:10D95000453BA4723011043FDA64F5ACF6071E13A0 +:10D96000A9B5ACC7CB92FCCF5EAA5BECFA07B44377 +:10D970003757E4DDB266E764A9FBAD448DDD827202 +:10D9800004A87D18D96B5F98C16B4F1F2180B31E0F +:10D99000F21F488924EBC13D0851764E05BCD2A147 +:10D9A0005655A2DA03D234BC6E3F9B428CCA37F87C +:10D9B000EC50915CD4218BE9E0B8C43551F8F8976C +:10D9C000974E7F1F23992D328FAD253E584EC3169B +:10D9D00015C1F1BF7EC62E45359470B3E91A93A3E5 +:10D9E000244CDBB144E57878479587A54043C3696B +:10D9F000C3FC79EED12CC183ECAB4618F975227CBF +:10DA0000C5608313DB236CC624B9B7B974A2370091 +:10DA100058D8B594B76873F8BFFD9EBC85FB8B5C86 +:10DA20002FD9059A8663204876C234327A27BE0AF7 +:10DA3000B782179F92207061C864867FB53335A77F +:10DA400022DE48F58099850E42BF88C9720421B84C +:10DA5000587A6593C713E8C19ADC62929B34C38DF0 +:10DA6000286B9D0225D75E2D3264FF52630DFD2089 +:10DA7000AC33EBCB391F828F5BB264A2D3D6AABA88 +:10DA80008928C713B8E0A46F687CDFED624B6E662F +:10DA9000A656A0FDAD7BF58EB3B3EBE3BBC0917191 +:10DAA0009CD01020780E0DEAB057545B01C2F7D419 +:10DAB000E025CF11BD1F3F5D76330862547142EE01 +:10DAC000BC7442F49287EFD565B8A27B667489383E +:10DAD000BDB18DC595A36F8A313F897F2BFC215B3A +:10DAE000D0F711BB6A7C29692770980AC8FE7BBCF5 +:10DAF000D36768F741CA85996302DC227ED419CFC7 +:10DB0000382A878EBDBF23B30F8BBA6872EBF73FFD +:10DB1000050650783BCC083977FBC09F405B5167C6 +:10DB200079ECDBE6EE5383BDE68A053CAD38D6C41E +:10DB3000FF900CEB9BDEEC7CFACD97FA7B64F1FB5B +:10DB40000ADDD597B4C520FE56E5665F1183289699 +:10DB5000DB2B4C44B36742D51162B7D67A496FBD0F +:10DB60002B4C55DC6109CF5AB63B6D83384B36D60A +:10DB7000AFBCD843FBEB976AB8FDF6BA9895FF1691 +:10DB80001446DF33BD09EC0FF161EA25A71F7ED6ED +:10DB9000AD1751DF26619938CFB1FD6E3B9A46BE75 +:10DBA000A3039C06A51A33F7FCFD96070BB1DCDA3C +:10DBB000B131999B59E39E126D799C6A9CF6426241 +:10DBC00040918BFE63972215F40FB9DEA8A51D3F87 +:10DBD000102FA8348E1A576FF20C7B8E494E2FF7F8 +:10DBE0005441B9C9A0D78EFCBA200E00D61EAA9601 +:10DBF0001CEF15EDED7217212A265698ABFA78F333 +:10DC0000DBB0AD33DCED170547FD7CF27098305882 +:10DC10009A0917CE5673F9CD50236D4C8B5CE5A84D +:10DC2000A3E0FA71227AC81D99EDEE85201D4A6F96 +:10DC30006963808FD857E549DAD3BC1CAD8833AE11 +:10DC4000E32E046CCB29AC460E46394BC93DA428C3 +:10DC5000C81250DFC85EB419A6AAB2E0FC95BD5345 +:10DC6000662EBF2EDF9EC099B6270C722BA2B0166F +:10DC70002A7BAAA996EC8CD015F4B1BE4A4EA654C4 +:10DC8000711143164EBB061EC6F7E350C32A9E44CD +:10DC9000C3D1D598409A0E36A90113FF0C94847B0A +:10DCA000CD9B1F9D172D907E3773CE3335407181EC +:10DCB00094E0BF3290EF46357054B95DFF1F8AAFD4 +:10DCC000560C8E79C63425EE0D390F25BD59CD7A07 +:10DCD00081C91819057407F4C3E89DB88D0650EB87 +:10DCE000EF6ED194641E4CA114186FB1900BDA87BB +:10DCF000549964D11C65EF894818C40998968F1C03 +:10DD0000CD9EFA2DCD9422A2BFD215A5A6FD688E78 +:10DD1000DBC6D8CB42998C5FEEADC95CD11093CCF9 +:10DD20003C20BA5951B70E7BD1D20E5AFDFBF1F609 +:10DD30000C4B1383723FC15A7C40E5D583B441AF8D +:10DD40003B4C403736035FD9AE41CB7514042B0AE8 +:10DD5000EB8EB8F7217D13A98108076BD3868D0C54 +:10DD6000312FFBB5D982953E98038F18098E27373E +:10DD700079E5981D408C8AF2664467DB5CD9D4480B +:10DD8000E950A440C049349501CF0BAF72CB4E4D42 +:10DD9000D421EE664AE8B790F293BD084C417A9CD4 +:10DDA000E4A4AF2A3B16D476A4700FCEE3CD1F8730 +:10DDB0005483F27D697E0406DE112C6A6951BEB37C +:10DDC00032B302EE702084B2D47ED68E9D62E373AD +:10DDD0000F4B4BB7E0976599E048FBB825FA1789D8 +:10DDE000D34AE0C0364DF8F27E61EE3E003BFAC603 +:10DDF0008E6F1154B55CB44E15DA5B4A0D02A784E0 +:10DE0000BFF7BF0254FBB1D7F296729A235A163C61 +:10DE10001C74841D8B50700EE1B284B52FBB04F7C7 +:10DE2000003D83B0C408DE1373830C82766B776B7E +:10DE3000B169150786A2A302F1A8A86607A2CE427F +:10DE400094E37090B197749848B8935CFD37ED9661 +:10DE5000E5AD9405C59ACBA0638C3E34C8F5270880 +:10DE600025C392643A61CD9443C959687B88C779C8 +:10DE700040307402BF21E938A1871D03222255EFEB +:10DE8000C2BFE7AB618DC27974FC82F13AA9011E71 +:10DE900065AF31C4154ADF60FC4522AF41E5CD28AE +:10DEA00065223453B1F4E472E15418D869FC95F159 +:10DEB00080347BEA26D664965670F463F083771834 +:10DEC0004BE598D4577FAC2FD9DA0D3F23CB49329D +:10DED0004F939456E3CE77086E07563A08477C284E +:10DEE000E663B4281BECDC977E471780F3ECDB1469 +:10DEF00023567F773EEDDDCF5F44EAC0B478CD0294 +:10DF0000C7B21E444D0DDE81FC228A54101F13BA85 +:10DF1000F4C8A520A9A8FE842557AD56EA5BACE756 +:10DF2000958EBADF927538823AFC3E55300A21E967 +:10DF3000AFAF347B05B9D0A5AD64D814C7FAD6E12C +:10DF4000D9F084834ABF1A655DE93B1E24DAE9B241 +:10DF5000EB89F682BD331B2818B88CAAF27D2135D7 +:10DF6000BA270236D60F5DD2601E3A11A48B1C1A56 +:10DF70009F808FB895094576835D9500EA5181862B +:10DF8000BE0EE645E944ECDA675ABC2B623394E6F0 +:10DF9000339DC6A1465E1ACC21306ECD6CECEF707D +:10DFA000B263552893129D747B1A0E5B4B12055079 +:10DFB000E3E19428CCBC03DD40739A029489647336 +:10DFC000E1FDC974378909FA707D1AAECD30004978 +:10DFD000524D959B6FDDF4C3E47675CC4CE127E0A0 +:10DFE000BC33B22FD4B27259D023864CFA3AA57EF4 +:10DFF000B72F64AF487604D176809F6C946FDE367D +:10E0000071DBB0F4EA8D834C149C0BE619286B3657 +:10E0100028F62CB196E679F3CC17515A9967889077 +:10E02000419F8058F9A9FBB0135BD6342546441FA5 +:10E03000548574ADCEB0B52D63EEF918484D99698D +:10E04000F6DAFBA90B0E5ADC547002AFFE97503A79 +:10E05000AFF7F69BAB444E3C82355D56DD96451CD2 +:10E0600022B0FB49075D04E3F880382AF5E6CBD2FD +:10E07000674B95DC67CDC7E3F7E6296EF9C3E19EF0 +:10E08000B0AC8DCF32670E9609E8D142C203777EDD +:10E09000BCE6F73B15A7BA4519F42621D7C2854837 +:10E0A0003BD8C91228195D08ACB3D5635E5F1BB6B7 +:10E0B000208462D4DBD2A1E157E6F7E4D7855F6D17 +:10E0C000DB7B8D0C3DBE048046C6AF1BC2522322B3 +:10E0D000D08BDC078A847C61EB44F61DA48A86F62B +:10E0E0001D7E4DBF6D5468230C429F1EA878C555F8 +:10E0F000291A9EB00DA8E1EED40F7371E293B80F08 +:10E10000BD6AE61315BD716C72705DE1861D037307 +:10E11000785E8F1B6690C3AD3D2AB8F89A267EF6CE +:10E12000A445F3377A9E23CE320036C054FC1785BF +:10E13000EF60901BD3C340C82C610BE2BF60573E19 +:10E14000ECAF759A75163894E4B1D8CF200C8A8755 +:10E1500019E063DB581954C4D6774C184CD8B40C6A +:10E1600099251353A9BB575AC17B7CD7792680A127 +:10E17000ADCF18E3A0EFD96886A77A96DC740C2F90 +:10E18000D1571C24E6D2D99F01AA5354569D8E1C08 +:10E1900086D4151D80031810FCC4E71401FBD017AA +:10E1A000D71A08B0DFED7FD049ADAB0454DC55FD84 +:10E1B0009EA61BC04FCFFB26FBB89B1030D886DA3B +:10E1C000E934B934098D64FB56E359735404A6DA73 +:10E1D000E30458970C0E9941351E28CE2C98869949 +:10E1E000FCC7852F8C9DF58E7B0F943D4DF681EFFE +:10E1F0003656911A572DC3F41D4F1FCB9E7707EC4F +:10E20000BACFA8CC29838260F433AF553EE5B8F588 +:10E2100023C313D3A3480FAF7C66600A8DFFC88465 +:10E22000DE0DA98BF20E2631B543E1C32EC608627E +:10E23000D5FD6989319F1EC1E54BA0407541E5DBE5 +:10E240005B5D045C52BF9242134D87F7F31DEB9A5E +:10E25000FF2B41B965CBC1464E739511596F2E20E6 +:10E2600028C5B44815F18CE47A956BA65BD10736C6 +:10E27000A8748A2405C7C2F5F33EC2134E8EF8BEB9 +:10E280002852A3E6527C2172287F4AA9FB98BB9AA8 +:10E29000314F5A3959F35DC6C380B7EE526EE6C0AE +:10E2A000913FE9588B784C49156AE039AB0D27E16D +:10E2B0005586E957B4921951D7D69460A41E8B762F +:10E2C00019E95AEB2CC261D3010CADA9B2C75D6E3E +:10E2D0002E5FC25B97C5AD604238A688A3A1684493 +:10E2E000CB9AF58D6D72C7F64C65EA225301082F63 +:10E2F00056A66F54300DFE07EDAF15948DD7BC5365 +:10E3000006363972CF6DB7A36B32B1739324A8EE82 +:10E310008C872EB0282AA585CFA90D7988F5443F92 +:10E32000EB0BA33B1835799CDFBA980BF15DA7DCAA +:10E33000F04E3CD7DE29CE0A7511661F9737419300 +:10E3400074520D97726AFA4255A75BEE50DFCC5EAD +:10E3500081186393D89EC9135072016EC7DCB22135 +:10E36000F9A8843B5FB627433236B68B50E3012EC3 +:10E37000E7DCF537686D421FBDE02A16E3A5A75E0E +:10E380002AC78E286D7E04F7E26DA56CD6DD2415B4 +:10E390006185DFB25BB88276118A93D472BEE013D6 +:10E3A0008EF595EA9B2B40F31A2E7773D4377DB107 +:10E3B0008387E32FA59BF0325BFF7D874CFCB89EE3 +:10E3C0005F105E16CD3B9CF667C0A269FEA0ACBB99 +:10E3D000177080971395DB211FC5FBA4BE3A262535 +:10E3E0000BBE99036CE15712566E0D7DA7FDA87CFC +:10E3F000446389017C4FB5F39D59C64713303F9A5A +:10E4000060B9A8DA93193ABF1FBD61246FEDC3B19B +:10E41000C23052910E4BD1FD1AF2A95942B9B9320C +:10E42000D86DA877D00A5B177E0E2A770DF61921D2 +:10E43000CCB4DAF317D0FD39AE3F3D8A5A1739DC38 +:10E44000F1FDE1F8A028862B97E01673D74BF6B1C3 +:10E45000C1A41B7DE3380B8A6BCE46F66BA425F571 +:10E460002C52A19882080D8477A738868942B6502D +:10E47000E61475E6825E130E577C2A9CA21CDD1DF5 +:10E48000515DBF8795AA65543B431AE0F6D10C6AEB +:10E4900037187C5D7064FC9156E65883DBAF1E4EE6 +:10E4A000B07206C9A6590D9D038FE21995BD157866 +:10E4B000CDA3DCF5920436FE5B5A01281CB63698D3 +:10E4C00056D90EE8A04E408F485667E9E92DC2A7FD +:10E4D0005B98B7524CC012EBB52ABC2F8AF37182FD +:10E4E000D3F9CFF05FD169D445DDE70FBE0BE0BBB8 +:10E4F000B1EB73F9E73F63EC8C1461071CF9114A27 +:10E5000025E4573D6F57DDE02318E744B1352C383B +:10E51000B55A75A91DB3F04450E9F3EFFA77109B93 +:10E520009167349C6993B9CD06D479DE79AAB50D8B +:10E53000F09BA7E8C4145B824964F9906CC8BA9058 +:10E540007FF3CCD66A48BC25BDEEA5BAE4B201BEC5 +:10E55000A650229C111C832B0B7117E2C6F662CECB +:10E560008BE6701D230AFD84F9C8D9DD1C43495789 +:10E570002DFBFFB40553D61D2D6F2B84E3279C5D27 +:10E58000EC27DA66A1ECC36472BA5F9C2BE30F1C24 +:10E590009C822F702A5BA6E73FFCB8D7A9EFF7E271 +:10E5A0001EE0B41496A9F250A2F2B7426AB1C0FBC1 +:10E5B0009CCE18EBEF82579364C464FF0D2B08A325 +:10E5C000A686BBAA553C606ABE8C9C6F52458838B3 +:10E5D0004213F7542D5A904090728D4A6FBD0D8DA5 +:10E5E00079EF85B20FED9ACB7C65C21506ACD110E0 +:10E5F0006282DB2A503011256329A6BFAF62200E4C +:10E600000CCB0E3670EF91F47FAAD786ED910160A6 +:10E610003DED2E71B58ACD10D228A8CCDE9F08F230 +:10E62000E9CBE4EE143B8750502275B2DA8580BC0A +:10E6300013A71E6FD66222E31FEC7936F25FB91181 +:10E640008DF09DDAB8E108F32666970D5218A3699C +:10E650009C63440B94EFF7E43E4F9E90DB851DF8DE +:10E660005D5230B6682841C3670FC03493EB3B5B03 +:10E67000293E45F2D2BA0CD3E52B75097EFE9A7E6F +:10E68000ACA812C9EFE267A91765A67B25F105A022 +:10E69000C51639A6B85BE3458B6B5A9F13BBC28F77 +:10E6A0008E0B26DD76114CDE85AED1868CA1D97F0E +:10E6B000F482ADB4D706C50CB696239C8D0AEBC682 +:10E6C00008C8760C7545E7CED02388E9B6AC3C3F48 +:10E6D0005A072F16C3C9E7942E516F8B349C6934A7 +:10E6E000AA87DAB2B882C43A68E0701A7A20A02BFE +:10E6F0006492607847825023AEF5542AB3BAE00999 +:10E700003F19C5A76E8A2E3A5BD6F43C95813EC16F +:10E71000D86F3CC6CCED4FFD46AAD30AE842596FEC +:10E72000C8D886E3B0A7D6159BDFF5B1CDDEB6011C +:10E73000B560A053E0F4C00ED2BBF4DB5D400A0B21 +:10E740005CCE85E917BC9F2A0F448B61712D97B46D +:10E75000A1A14A8657AEF214F6948F437DE93C5648 +:10E76000A3F556474A912A809964698AC40F50815B +:10E770008DB6922F0CCEB31524A2BD98F098934B72 +:10E78000CEE266B53323295C399C10924F0650F7D0 +:10E79000A27A8EBD072BB01CBB3625E422179E340F +:10E7A000904F9A72E80B183BF3504A31B5425576B8 +:10E7B000831E624E2446FABF62E7300C31ECF80348 +:10E7C00021A2351A039A4B14CF197CCD00839AB934 +:10E7D0005FED0808DF2F439B443229BDE9F2C68A6A +:10E7E0002D8672559B318722C9D2E5FF1C6136ED1B +:10E7F000A1D6A7F6C4E4FABBBD0AA213024D8BFE54 +:10E800009F94110EBDEA5C26C126BC381C86F4CC50 +:10E81000FB2643EA669F67C3B084B9F493B92EB16F +:10E820008C34E52A1E0C412376B5AF6AEBA97961D9 +:10E83000F675B6940BF2B88B3E3D5F5D42D8B76279 +:10E84000B5C873DA5A11AAEAFFE60E172E356535F8 +:10E8500056DEDF3167F558721D4DF8DA6CE777AC9C +:10E86000A412C4FC10F5BC15818FFB4192480D39F0 +:10E8700021475E20003EE41CB9A7C11C9D2C50D34B +:10E88000494452A8189D10739DBD8F8311DEA727A0 +:10E89000AAB723C39AE35F837CF7A08D3256FBC6E9 +:10E8A0007AFBEA1C19570EB90FC4E0D0282BFC667E +:10E8B000DCAC9ED7E9748CAD4E8B5414E33C3F86A0 +:10E8C000BA5A146F048AF40816614684E044E91CBD +:10E8D000362F5B980975A8F118477F4DD8F76AB2B3 +:10E8E0009E2491EF82FCC27EBE8FF530DA3FCC527F +:10E8F000BC1945CCCC8A142ECDCA839C33626A7E67 +:10E90000F0E5D60074FD76F51AF86CB5FB64FC7F73 +:10E91000612D53C95554044CA0DC204A98D2EE3ED8 +:10E92000ECC98A098A45BF219535C0EA29CF0CC8B0 +:10E93000199B0132006C4FD4F762C63B7C84701780 +:10E940008FB5E87C2B62B2FA435C33C89110723AFF +:10E95000E4887564BC9A8DFEC45F4B4630CE0B755F +:10E960000B8863EC994FF2D6B14B0E0A4ADD7477EF +:10E97000059AAB9F1597763C6C608FCB905A3E3FC3 +:10E980002F510CCE7BD9AD1AC625ABE7599C145339 +:10E99000F660930E497CB19C2C4C4EC942D5E7C31E +:10E9A0002DC8A30513C0B1FCBDFC4B78F4B878DDCD +:10E9B000BD7086FD581074DC7E04EE0B6B3C438BFF +:10E9C000760894558578C5CC496CE1FFAC230DEDF4 +:10E9D000011D2B4D1708102ED2AF881E74072AF97F +:10E9E000FF883815F0F1C17D3FFBC2C999279E0110 +:10E9F00036C594BBE25AEA92C4D2E34B1BFA43A851 +:10EA0000C91810058AC4A27E31DA15DD6F095CB918 +:10EA1000D17DBF53B7AE321CE0146C33F0793BC0EC +:10EA2000006FDC8F570E0699C7CF42974D458EDC9D +:10EA30008791BA5FE07E6723B7DBBC3AE3D907DC96 +:10EA400018C7A29D99A4C5EC58D591E83B56DD1492 +:10EA5000B6713749B6C51492A1D64521F60567406F +:10EA60005C7E7CAF5CCA810E764DBCE6195D65CCE0 +:10EA700079473B4F8A8B253249118F43CC7964A368 +:10EA80008900F4FBABBE383BD21268B2FB23EF60C7 +:10EA900091557E3C734853DB6FA1AF0168CF893E2F +:10EAA000F06D6C49C2057F6683C61AA5EEBEA5410E +:10EAB000CA5BF93D29B51FA1C32541309EEA06B9BD +:10EAC000A76C4AB34914C101C1AE2A5C7768345AB5 +:10EAD0007BC22F3E073A7C294573F4D5E7A6A75C95 +:10EAE000F4076378C29EE4EA5F5D81F88898CC9F62 +:10EAF000BBD9E50C2123C2228237FFB1418B822D85 +:10EB00006C75DB7589DA3693EDD97B07EA26A006AA +:10EB1000B619898CBADDB0CF95222EE9C7835D91F5 +:10EB2000C585B7EAF9E64ED42D3BB3921F8875C26E +:10EB300019E68CB25010344B4FF3552E57020E90FD +:10EB40008A88929E849EA5B00B49E2643FF50384B7 +:10EB50007D986150804041BF71104A0C6DF5D0D94D +:10EB600019B597525B71BD5DCB6C29E97984CD0EE7 +:10EB7000C2CD478E2037C44586116C87BB3EB9860F +:10EB8000FB3B9EC3E1FBA02191B34AA29FB6E107E4 +:10EB900047E14DAAEC282260CF3BF4E370C3DBD8F9 +:10EBA000F8AC6297D29AE5891873DE40ABC1D414F1 +:10EBB0007B48994DD52BAD85ADA7134AFF74D3F093 +:10EBC000B622A847C803685D2FBE96E48BE73BB822 +:10EBD0001966B346D69DD87E08702DEFCD6FE50837 +:10EBE00099BA6F4EADECB2D5041026BB2B73E0EC96 +:10EBF000DE3FA37A43B56438486EB29A7F5EC70C95 +:10EC000067FC4A49DF2661211E934C428608751134 +:10EC1000E3014CDE4CD855F5C9F76E88EA3AB41ECC +:10EC200084D2D862EA7B5945465D878526FCF1E6A9 +:10EC300001152F143C21BF19C86B1BA0DA4899ECB1 +:10EC4000D5737CD6F427D5B5236B5917DCAADACA5D +:10EC50004BCE5B898604F2FECB2E80CC238FFC71D9 +:10EC6000203326C8DFEEF59FEC90806CA3D2D8B697 +:10EC7000A381BF0F461FC84672AF28030835754BE6 +:10EC8000441649841E7491AE9DBACC57ED61BBD435 +:10EC90002DEFDAD4A38613D529B2A7D974BC1F0AE5 +:10ECA000E817B33C4CB34D4CB4F9719BDE097FF0CF +:10ECB000B489FD020A73F3360950DBB6D0C7E63FCC +:10ECC000C4BBA469CA1DCDE0E434A92B22CEC3A6DF +:10ECD00034BE642EAEE8BE22435E39FED871DEAD8E +:10ECE000A4C29A2799367B821EF7466081445D1B39 +:10ECF0004A851A15F5D866A3C34D283E6E5D11B935 +:10ED0000C27E5446F8622A97CB0E825630EA0AE653 +:10ED1000B8D7B9E55983E604FD0A1D52E9CDF6548A +:10ED200043ADA7D13AFAFF1F581FD7180F2E693AE3 +:10ED30009E0E7F08EAC7243893D334731A2D7A22A3 +:10ED4000F301946BF2763C7A8D31458EC489A96CBF +:10ED50004B30C528BBC98852320F6F004262C6CB08 +:10ED6000F23D195BDDD41FDB42E6D405C2B00E5480 +:10ED7000068331D24BD560EE9FFE3D5A28F45505EF +:10ED8000363EB12A36600CCC8CB5094DC3D250E06A +:10ED900057B0B6EC19F5B5EFFF81B08E088AFF14B5 +:10EDA000189067BB45BCB320B71DFDF2FB20B4151E +:10EDB000EF00C891F60297A6663E59F7B2BEC52885 +:10EDC0002535878CE125FF695DB02622FDBDAE109B +:10EDD000E680731E66B5A60D0A950E78B093AFF760 +:10EDE0005D7820E6EF81E6278CF06CADF93447685A +:10EDF0004676CB656E9280B8EE2B3087CFC3DA6B48 +:10EE0000F9DA626A7C193096CCCD2754EB7D98DC18 +:10EE1000D4CD883D41376A8F9C4C2565EF1558D479 +:10EE200006CA204E56C9DD6E915D5F2A41D5B57484 +:10EE3000FDB943B3261ED5F3CA4AE4DA6DF5FBA249 +:10EE4000C7FC6970570E249CEA99504C372768D04C +:10EE500081A177F5F1795E7BE40DB53B4F1AA216DF +:10EE6000DBE9703856F8DD7336DBD759FC343101F5 +:10EE7000C20CB14F3C10DE47D49906B5E7B500127D +:10EE800087CD5B598FEDA4CA6B303F276E838DCD44 +:10EE9000F70926734FB2A05B6A4681BE129D7EEAD7 +:10EEA000B5F669FA39B831FF374E765B9D8F8A56D1 +:10EEB000F76C9E2011FFCA9AAA633076FC83FD6925 +:10EEC000AEF56041DEF2F5831897C77F45663B32A9 +:10EED000F79964EF40B29549715F0459C383F8FF15 +:10EEE0005835C27C0AC4F0A25D49A54A04E6E6830F +:10EEF000CDE5E81243C7837396F4ACF0FFDCDC4445 +:10EF0000009D3213E96C0E9ED3AD9D2D5DFF124620 +:10EF10005D220189F8D956EB5AEDC2AF248144CD68 +:10EF20003D508982B650BEA46D2A3733F1CFBAD096 +:10EF300097BF789311474E1C9031D4F66B15F24D64 +:10EF4000AD8FE752F8522BFD17E6395BFC22633E8A +:10EF5000C545BB2C11E5DC296B9FC50124503FD072 +:10EF6000B56528837ADFD814D795CD2CA632FE0557 +:10EF7000798EDED4940D4A4E54637F7071D7386F0A +:10EF8000B27BB033E10E8D51F48825DAF459E76D88 +:10EF9000A6D05F440B7216AB62F5C0D9B5B2410F73 +:10EFA0005749F1D14A147AD45CEA99633E32518AC6 +:10EFB00039EBB700934829343E86530EF8F60639EC +:10EFC0009F3E9F981D245823D9461B585DFA83CB3A +:10EFD000E645C2135F02A03B274E7696DE7BD51036 +:10EFE00039480214132EF459CB61093497A6662AC6 +:10EFF00021FCDCEB2660B30EB967BC1C2030032675 +:10F000003D4A99DEF0BB969EE40FD09C1A3A397EB9 +:10F01000D12F28C55ECCF3AAD8EA5CB7F89AC50F01 +:10F02000069D186F80B76722D5E0AA414E50A5C053 +:10F0300033DCE57ED00792701A2C11BECC96CC64DE +:10F04000F231B07F3CC276CA2943853FC6EFD0CCAF +:10F05000D9B31CCA4E1438522E48AD0EC4193CC246 +:10F06000595946F2DB4A0D06AE206D58B1492101CF +:10F07000A53A378AF3DEC802FA5D7FAB0373E30576 +:10F0800060F6BEE351A65937FFE9FF433DCD8B2B18 +:10F09000A469E045E2F86C69F8EAC71E6D9DBB5CA7 +:10F0A0009531B5801EE37B14BA3E7973F6B5AEF5A3 +:10F0B000AD9FDBEDA51B6F75044013A3A5D6B1F37F +:10F0C000419DDA8F7C9050F027998B1580FB874407 +:10F0D000C324A2155498624557B491E249DE06DC78 +:10F0E000F134F2A35D8A12FF4DCF981E34A7BF12F0 +:10F0F000E7AC9F9DD72096E66365C1BC3F7AD5AC4F +:10F10000E9FC89FAA7904A32FCDEE2F4FC6A221C90 +:10F11000379E52C4E297E2775FA1F130EFBB41EE38 +:10F1200053BDB9D2FC549A0A41068E436A4B64EA35 +:10F130002323FB4097EBBB0C802F9EF5655D0144BC +:10F1400088D0283DE810439EB83C0BF1B71C6E22D6 +:10F15000A81E034AB8A2F6C651AD9E7CF3C4D8746B +:10F1600007EE9E497E61D119AECCA04267DE529770 +:10F17000B3A6C2F402679F45D5E97652F9296DB965 +:10F18000AE6EFA877AC79D23F0242AE66CF13CC75D +:10F19000DFA585AE5729FC15951E2DECC4BE41C4D4 +:10F1A000B95AA8AFA1A726797A4ADF7E3115253B47 +:10F1B000B92A86CFC64E8AC87EC8B0342237129785 +:10F1C000C3A3B6E22D53C1263D844A91F10BD71457 +:10F1D000211813DE669A4057C64F1AE047538FCD69 +:10F1E0001F22023BC8A2EA600B0C161EAE171824A1 +:10F1F000BE533A955D767007478AE60B2D2147E9A5 +:10F200002C8CFB9190E1227FFB4DDA4157E18DC9B7 +:10F21000B059BDCA51D00D50C979D5AA78FF04A400 +:10F220001D9AAC83CDA2913374139A958C56EF91AD +:10F2300008FBA118F591B7CB32996758029D7C382D +:10F240009782FD312F33117BADBFCB882383C64B13 +:10F250007418C83EFE700745D883E240B47BD6C818 +:10F26000F2ABED3452D6251A5775419D3A334B62B5 +:10F27000370C86A9D30FABB31722920F9DA48FA38F +:10F280003C823FB0502A8E2BFBFD7403AA21C94D4E +:10F290001AF855BA55EEC75B7308A7136D7CFB814E +:10F2A000E44C45B2890D6DDDF6178CCEBDEB3C0EFE +:10F2B000FA8F1C997755F27E6302AD1D86B18C677B +:10F2C0001661B1BFDA7BEAF2CE0A45E7F4ACF92069 +:10F2D0001A3713D53975C60D991C7620FD706A440E +:10F2E0006289E3C9E3FADFCC111FCF703E83AA7BAA +:10F2F000707F29DE512B6B1900409209E055AD2536 +:10F30000A9FD217710FBCDD1AD1836BC5118F86599 +:10F3100096DE0D6C9939B929FE542025A99ED36E2D +:10F320001E9B9161BBFEC62DCCB8001FCFE81760B5 +:10F33000673F8712858CA0CE76BCDB65C263336CD9 +:10F34000933F48F223F9FB5DE3BEFDAD944FCA7ACB +:10F350002831732AF5F17AD8F7F282C31D12FC9591 +:10F36000B9E5AFAEC9C71CE25E9123AA0F78863615 +:10F37000BBD5559EB2B8D5316D76A9A2DE075A65C8 +:10F38000619B9ED4471DE7441AB88A23A4870CDBEF +:10F39000BFDB16E2D57F654E2218114582770AE25F +:10F3A000D8A48E43F20A3E81C46BFB5F14A1F49C87 +:10F3B000998CACBD5921452ED26CDC9C38A42636E4 +:10F3C000E7C866637B8E7A601C533BB9E4C5BCB466 +:10F3D00027D72D06A2E247120DA2CB10D17A35E62F +:10F3E000E2DF53CD18F1961B4209444B4E9DD3B931 +:10F3F000415616AC30DA3ED421E6749B90881F1E2D +:10F400000874DB1CE7E47B78D843E1DC03BBEB89C1 +:10F410001DEAD33D96F360C810A473301936F66028 +:10F4200002BA335C86606E67A0F439D626BB842CA2 +:10F4300017903CA9B73EB6457BCDF4E620DF7CEAC9 +:10F44000BE6AD7689A90A5ABED73A9C7C429674E69 +:10F450007FA34E7A7A42EADEE298763D29B61D34E1 +:10F46000BD86CF2FE31C94D2AEACDC829212CE8547 +:10F47000D81555C3FB4E071FD83FC7AE311EB5CDBB +:10F48000E5A4FAD5AF5D1D5A253FA78477350B1645 +:10F49000684A48F2D5170EDF2127608D13ED91F5EC +:10F4A000CA7196F9F8FA1BCCB21820ACEF6C440A7A +:10F4B00044CDDD3CC72EF55752B29F23E76F18A607 +:10F4C00085A087CC52CEBCC2D45D0CF852C9C0B660 +:10F4D0006AAF98906088A3A0B7CE76960350469DF9 +:10F4E0001283931130967413A537A6130776510B28 +:10F4F000CE4A3F8376D6057F2C326DBDBC34097A67 +:10F50000C30BFAF6ADCF13FD0CDE3AA464CC504E1B +:10F51000D41DEC98836CB46103ECED5D9862F7EA5E +:10F52000CCD2A5A06084AE09C0BD33678C3000F199 +:10F53000CBB224BC2F490676EC4DD3AE60403E00E2 +:10F5400063A87F7E3E64679F1FCE69B9D0A2EAE5BB +:10F550006D46C68933450BAA3C68EFE029A1987433 +:10F560006F1C5222198470DEC3474066C4926852F1 +:10F570006CBDB799422CEB7EC819F481EA733977D8 +:10F580009F39933C825B240E0D766D77DC9DD66EA1 +:10F5900058E9C5628FF8F533EFB1233F558B136BF4 +:10F5A000ED658D1A00659BE99B29BB2D6B497E3962 +:10F5B000A19D1ECBB18D34FE3E66D7A8534994C899 +:10F5C0007CAFDFD928B2183429C087F428061F166B +:10F5D0006035E3BC75AB6D81E637E9AE7111FC387F +:10F5E000C6CA469603390FCF6139865B922E4BD33C +:10F5F0009E813F22C6DD37370CEBD30A2C6109848C +:10F6000094E78A12757997208DE7EB0D0EAF3E0FC8 +:10F61000E3F5F27CFF352191C29FA07D3E026C9202 +:10F62000F757FF533286F38CCF8FEFF8CF45394F22 +:10F630006D0A1181AA5826206DA7FCA044C5BA38CE +:10F6400000256FE892C59376F0D228B2751626DDB4 +:10F6500086244E33165A1CC2D2F8501E006CE96D37 +:10F660009142F24344A5A99E4D54441BDFA316B812 +:10F67000007936526EA731AFD0D78A192BA65ECD4E +:10F680006D85A44340BE54E1F539B4694D93229A87 +:10F69000D8B66EEA567E05AE72CDE5CB9714468F8E +:10F6A00042AC5167AABAB80BF41FF96ECC8022D7CE +:10F6B000DA1FDC8CF4176282E3CFA4FF956ADE8345 +:10F6C000E412D2690AD7DD0DBB4FD56AC38D920013 +:10F6D0006D1EE8516B33F7F477115055E8762B0E19 +:10F6E0006B807C304417CBAB9C4F5B6418F157C9DF +:10F6F000B2270FCCC9E75B4B29B6E70ABB87F620D8 +:10F70000700C83968618DC67218F201F574B50CCD6 +:10F71000C60A5C044C8735890BD4D7A1D049C621D1 +:10F72000CA3DF2380C38930878549B9280C9013056 +:10F73000A34C7EB38BA63B9D3BBD4E96582DD0A7C8 +:10F74000CDA1A46BA430E0C042998E34959D90CF9A +:10F75000B3EF8FF01AC603DD4ADB4029489A57CA37 +:10F760009AC826EF35033802A8C4E77166BEC325E0 +:10F770002370FBC0B43DD34D5BFE689F44B705D1F9 +:10F780004AF71150AED3DAF96B11A682634FB47702 +:10F79000893FCC259004EE97A45607D399946982AB +:10F7A0000C97ACF562BC8752F13F348F8515A2F1FE +:10F7B0002C75E176E1756F40257551E7A18B6E14CC +:10F7C000B1C91C654A09CA399048BD082CA50A4F21 +:10F7D0004E46E3FA411F68743CD7D80CF49253AC00 +:10F7E000FF31B46F6AD504A3330B64AE55F40985B9 +:10F7F0008D00BFF4FB6F486D713EB8D76CA7E4D0A5 +:10F8000051CDADECF981C6B66DF074B1A8B5382D07 +:10F81000DDEE7E638FD5E20BE8E1065F9B4C1A6755 +:10F82000500B9F9F541ACF542DACB1FEB40FBC5A4D +:10F8300039EA33525BE69317134FE2E13346A6FCF5 +:10F840003ABFCD515BC9E9CBEC43C95C5B1B647526 +:10F8500000D454EC7235C2E712A09D69098595BEAB +:10F860007CFAA7EEA3F194112FF30F972BDA4F83B5 +:10F87000C087FD61E4621B740FD0ECF44CD88D8618 +:10F880003814DDF32E145D6A614A779E14D0A13CD2 +:10F89000FC5B4D098937AECEF4EA6C21EE88841505 +:10F8A00050775DADF127D9D0D01B64715FAFE6B161 +:10F8B00059625B3E7748EE7CC880317653AD4D1679 +:10F8C00050DBDA0C2ADC5AB321F395B4DDFCA41921 +:10F8D000D008AAA5ADC19C0B193A402DD75E4703AD +:10F8E00079054D5676DB79589D19C3FC2913A46020 +:10F8F0009AE9CB3A906A3603D5CD753C6F22792DC3 +:10F90000468196E1AE7ABAD97E874B3BA1FDBE1700 +:10F91000651FBA144AC95E6A95804C4B3266DD9108 +:10F92000FCC7BCE55C8317C76484C1A9E21F718171 +:10F93000BF45975474C24E5BC7BBFB96375B16043A +:10F9400026B84A3EE586D1F77E11FE604268FBE9A3 +:10F950009DE7B9F68368701092E2C768600F82EE87 +:10F96000ABF503E182DEB9A6C714660BD6E2E2FC72 +:10F97000BC0378B56E434834FF0EA4076024943569 +:10F98000297DDB4BB86E0F51229696CFB96AF2AA49 +:10F990005BF526652400D38964D306B2EFE1B21883 +:10F9A00094DB943F3CD719AFA2D37CC1801686C1AB +:10F9B0005A65AB3F6F66777F10B0199CFCA713DBCD +:10F9C000B0FB7D407CDBA58D5D7714361E333B2C70 +:10F9D0008150CDE0FFD54DBD1A02E06EB81ACDA41E +:10F9E00050BC5829ECB6AF28D9ADCD20F871D35F03 +:10F9F0007DBF450E239EF61DF3AB6F39DBC7B9F112 +:10FA0000903CF7F03E665AA35DAE964A78032745D0 +:10FA1000C811635B5C979C66450B1EC0656DA63084 +:10FA2000E59B0FEA0AA15B36557C9EA63AB225F605 +:10FA300024C0D61A775A82E175E3D147DD80DED340 +:10FA400092BAA52E06F92045C1D12E38F72BEBA886 +:10FA500088581A4EF43E3430710F6D92B96D3225CC +:10FA6000DBF1090D323212A1CBEEA5DC86EF3B773C +:10FA7000CC148DDFC6A1E14E44F9BF6A5BB3F191AE +:10FA8000470A6E9692147C5CE2A2D6FD22DE2566C1 +:10FA90002D6092368CA7782299EC85F3AF608EA505 +:10FAA0004DE316082BBFC36892CF5D171217C8D558 +:10FAB00054FBC80550BF3FB4C4DBFD113D9AD611BD +:10FAC0000887B543E6FDEB41691CA736E6BF14E1A4 +:10FAD0000E9B2EA4E2F2B8AA1115F88E2D1EAA5480 +:10FAE000FE0839BC8D1704E64D1DA728CC0B043A3F +:10FAF000D6BD96E9AB7C092DABDF9241129ECA457B +:10FB0000748B033BC0DE1F821C37E4864BAADB6686 +:10FB1000A172B3162D389ABC6575598DCDB7C90E33 +:10FB2000C11974E7783D72B9FEECE8A9D9976DE583 +:10FB300074B382F545CB4AE0EAB54E3E09BC7EDFA0 +:10FB4000F5EEED3CB33DFE428A8506D9C54482718F +:10FB5000F88BFCD9F13CFF8BC9981736E523319817 +:10FB60007E22CB651258DFD793EA3CB72B6C483F17 +:10FB700047F7A00E66796EE9270AB68050971C8376 +:10FB800037812CCD1A83BBD11B5C975DFD6244335A +:10FB90008AD08A1B6C4FECC8D423401BB7F116D512 +:10FBA00013A83340CD0CBCCC943EEDB775798E7F55 +:10FBB000ECF633C4CBBEBEC0876A1E8AC118F855A6 +:10FBC000C61361A350D7BB8415590DD60C6FEA2319 +:10FBD000BC1C2781BCD0A16700A6B10A2F016B967F +:10FBE0004BE5899D4A37C470BB30123DEA9E0A4AF4 +:10FBF0003A81ED59D84B9F3BE3608834E71A96472A +:10FC000067126F5382BE438C384561478038817ECE +:10FC100027FD578D4073EB568501B4E6787340D7C6 +:10FC2000AAF00C1E1B8D7D0B0C4B790C0A5AE1952A +:10FC30009E362393C1A15D6F1218536CCE74596622 +:10FC4000457CB37965224615F8B8548F5D0C4E3F5C +:10FC500052162C37FEF94C3BE1479063E9B5A1A061 +:10FC60000DB07843D34D30060F844C3ABE2936662A +:10FC700032DA9183B8B8EC8D5EA9AB011621283534 +:10FC80000B5A9A2CD9AFEFCFB58169691AFFA83307 +:10FC9000DEDFE550B6CA4598B7DB85396C72EF6197 +:10FCA0004B3A6472FD7A0129D074F195F1342A94AB +:10FCB000C864FDCAF5050D58632EEC4C33B02443DF +:10FCC000AC615E7EC70E6BD2B7DEE2D923AF75C0E2 +:10FCD0003BE35D9250205BF649729AD63A037C87EB +:10FCE000AB7C598E59CD15B33CDF455DEDFADCFE9A +:10FCF000AC0B38AE726D53D9F58388931B78426292 +:10FD0000D30E477A10280E738849186529B873797D +:10FD10007FBA8186E1978EEB174A9B0BAFAC663AB0 +:10FD2000BC38D80734461F18746F6DAA42D0EC5CFB +:10FD3000F86B5685A43E64BAE53F44ADA5E7D95DAE +:10FD400035B48AE6EBB9A3D5256C6B86965FAF1206 +:10FD5000037C18CEAD3A1A593C1B8CD32CC248A454 +:10FD6000A417DB398B380F97DB6731B1C5FAC9F8B7 +:10FD7000259AB9D15BEC2EE15F0EC94DE87EB51D29 +:10FD80008901FC5DB00C5945F53A80267F13584E29 +:10FD9000B207E01331F057245F3B3B2DB2A7F4BD0F +:10FDA00029467D089B0B5A0482B8EDCC4FE06A15BA +:10FDB0009768CB04D8140C8D5F1AF226071B972680 +:10FDC0001168698A15EFAD98113BA129F984ECAB54 +:10FDD000C8E6BBCFDA1907809008858FF8EF4E246C +:10FDE000D4001F7834FBDDFF9D1485B560A7329FDA +:10FDF000CB0AA56CF9AF543F01AE9AC7F41800E5E1 +:10FE000022DD5D8D60CA8A0130BAAE7A22CC4A2AE0 +:10FE1000802638B5641FEBC5A967A071DA2801FBFD +:10FE20000D510F74E5E79B84D4242F0A5F845A3068 +:10FE300073B9D9FC5079784FE122397A687BBF3C9D +:10FE4000782ACBD0F25B88E46A56A7DA6B0A8385FE +:10FE50001BE219F3750134B0A87155D08E1431B27C +:10FE6000BE83D840CECCD26BC4BC0941F634131A41 +:10FE7000047E6C1A476863F7793D28D5F7176A3115 +:10FE8000DE120E4BAD801D206E32A4840E07E542BB +:10FE9000EEC06F689B7DDBFB815483C8646DC50930 +:10FEA00012C08A53743F87096151BEBE58245FD681 +:10FEB0008079C3880A71DA56F0458D5CFACA9810C9 +:10FEC000BC72BC2FBB28A096034D4B48C1132D72AA +:10FED000261954D60D6FD18EDF3A32359673C4C5CC +:10FEE000895C4996F26EA3207F1FA3A20BC891A93B +:10FEF000CFB371B9621D097F2A2AFD067CF02EBDA1 +:10FF0000B82FDA5C59B815F3BA536405E0551A886E +:10FF1000C92FF4764EC92D044D04A880302448F32F +:10FF200037D8EACAD37D2E3CC1A8A31AB649882384 +:10FF30009139EC9ADDF99B5FF8763ACA2B0AB8330F +:10FF4000B0219109F8CF06E50BDE81731789DD0931 +:10FF5000854B19CAB9952D28F7C9A90856E300F6AB +:10FF600049DBCCA0D94950EB33BC52EC91AC737A4D +:10FF7000C0D4DAE729FEB388FB0B7839397895517C +:10FF80003A401D6FA697D43473B92DE123568EA243 +:10FF900095620DC14889C5FE4B57F6DD7F6FD0864F +:10FFA000C58D6B4B19445489A8E8CB1BBCC0834E4C +:10FFB000639872A951F0BCE34D1D26E545AF6FF67D +:10FFC000D658A880F65F0CCF7531A68C96134EFAE2 +:10FFD000705A3AA73F2D084D0875EA413784564EAE +:10FFE000C2D363ED8384193A0C3017FD48573C2C7B +:10FFF000DEC7A4C2D4F2F40AFB84B7979609FCEEDC +:020000021000EC +:10000000F78E00ED3010EFDFC93E2DA537BAF67937 +:10001000AC5D51F4EDD75F22617F0728D789601668 +:10002000020E9EA187933D695A95297C2537357527 +:1000300022EE000DC6E63B0B3A3F4F1C1180010338 +:10004000ADBBE33674F417471ACF178ED81C462879 +:1000500001D12AC515A3E4C7742D41E49DCB0BCE75 +:100060005A26C3841FC2C0D00F8B44BE9FEAA4137C +:100070007981237B08F93D9060141AF96005CEF967 +:100080002476B17F1327AA9535E439E2DC1B8CC0B6 +:10009000B090D1A0EADDEF86E18F16D578AF55009C +:1000A0009552B69DA2EF6A6CA5AED2BBC887CC7A3A +:1000B00097E1E2EB4F47866D8A9F81005F29EA87CF +:1000C000E82ED6F1C837CC681D21BE6A212C89954F +:1000D000D0A3B85766A0C6EBA9D80FBDA905B9CA69 +:1000E000CE141647271F85816A9B0A43FEC5AEEFD3 +:1000F000B14F7FDF6AFC5AAA36DA1C6BBAA5606C76 +:10010000FF6148210B2A7469874346EBD6CD9FFBDC +:1001100010B3DCD506D5952F892DA94ADEC2645BC4 +:10012000D8B0D5215BA1E2C4A561CFE636A0817429 +:100130003927440DEDEAD2F0447CF2FE6AE045A393 +:10014000F7C0D43B673E1799D09AC5428F41409281 +:100150000C44B2D14E80BF27DA524295DAF3905E5A +:10016000E34F7526BDD4266298DA3AC52A079B1656 +:100170001488BE111D14DFB45BF72F0FFF6C8500D0 +:10018000862C3DBB963CF072407FF9F718B7B38BD5 +:10019000276DC16E49C49E5F3DFAD182A71F001230 +:1001A0002111B29A183B5E0597239FFCEA4F6A72B1 +:1001B00045070672E77B862A5BEFD46D114A392624 +:1001C000AED0AF4293595EB4052C4D891645FD93D0 +:1001D0000B82A12A97EFAECB5DF6A0B7E247387C41 +:1001E0003FC2B325E09EE1677CBDA76593D269C499 +:1001F000BACF121382206DE6F95EDC86AFBAFEC676 +:100200007623F96A0E7D721482C63A378CE2133176 +:1002100027551DA7C462E83648FEBD1412F77E1BA1 +:1002200053B6D5C7C65F21DDA93E96C1597D54C7D7 +:10023000F8B33F842B672EB721ACD49DAB6D03413F +:10024000C96F7ECDCB3FDABE1FB75E07C1A71B5B70 +:10025000AAABB49373B19116AE75C4D00576EAE437 +:10026000506912A80A94F04914916F92AEDE0113FE +:100270003FB3415049CD14E3FBDE542E1372DB0F24 +:10028000D0393E0F23A9A5771794A73745F57F836B +:1002900082C4EA16FCE1CEB2CFDEB699AD2CD87995 +:1002A000B82A427FE31C6B37385A8D59DFEE4C6316 +:1002B0005AECB6F213EE80AF81BCDBD455ACC4C9A6 +:1002C000BD4DB91DF600360233C5E67550AFA22FFD +:1002D00040801F85DA14A0EC962CD285093B1AC108 +:1002E0002634DD5E2631926F6CB4A448CEC0E9821C +:1002F000BF04F68996721EAFF90330E49E7331A1F4 +:100300005528C6866876C3C5E752FB9737B1F371A7 +:10031000F95BEC10A04D414FCA1CFB900333FFF674 +:1003200031A46CB66997A1CE2C0F9B9221D50E6398 +:10033000140710D7136E53FD72B1C7F14353867D76 +:10034000F66EDD20C3FF80C42BE29E4AF8A52E7C0A +:10035000FE1AB77842176FB8C542B7DDAB5EA91178 +:10036000EA108E2064426D4BE902874EB7177DBBC1 +:1003700035496B24934872ED77B4C5B9A83FB2A252 +:1003800001CBA963159FA95671F57C8E3067A641F4 +:100390005F8A0DF34DE632897D565893F4FD309D0A +:1003A000ED757B0C6A044160C8612FB373F5AF3003 +:1003B00090116B6E0742223437B9F57D31EBF6E0D0 +:1003C000738C0CA047C086F7DD82855E2773BC6CFA +:1003D0006941F976764FBA780E277A9E3A5E3138BF +:1003E00078D173D55C8D4C982ECA7A60E94BEAEAD5 +:1003F000EEF7A70533A94D024ADB92AE9290B809F9 +:1004000069BAAE7418E4F2532A43CF269451686A4D +:100410006513F0090FF21AF69C26CE593635731B78 +:100420009F8B857A91F5ED10BAEFA8720AEA965281 +:10043000BFD2A9358175F40EA7C2F5F614CAC4055A +:10044000C44485F597677B93A28E95C37A32642A5C +:100450006A1C3DC075E2AFC0424737D26E0E081924 +:1004600039CCFC4B605CDAA21941003E0034C43840 +:100470009BA6735A7F477BD99BC9B92EBAC5228ADE +:100480000D07EAFF19A622D397FD5FCF92D19D3FBA +:1004900023D85CA617801CCC895588C4083CD30699 +:1004A000FF68237710B1962D9F5083610BB0DC4914 +:1004B000D92A7CF1E9E05F41E5341483804F090AD1 +:1004C000B87E107D4348B3F0251B427FD096DC08F0 +:1004D000CFD03AEB55B9E79D091518D9D81FEF4B86 +:1004E0003F2DF3835573A4B328583DD40446D5C497 +:1004F000487F0E363BEF5156654CF52AFA6A9BCE83 +:10050000FA35AE7D3DC5CD66F1207729B256F105AD +:1005100033E297532405BFA2CAC2C77BE7CE33D7C5 +:100520008AE82FD8B4BF672F90097C6251E1A6EA10 +:10053000135AB353EA4D3E5D9E35DFBE75C383C08B +:10054000A7D12F7AEB0A13B732F572C29C55929657 +:1005500039415C66F23C26F2B4F0C36BC0466FF9D9 +:100560009C06F3442AEFA32963755CA69CFED53054 +:100570007C386C68D27DC2716FE063BDD9D3211D18 +:100580000B8BEBDEB87F9FD86D98CE12DF2BB2F0CD +:100590000C3F4842B14100B1DAC19E1FBE3A38E675 +:1005A0002AD74062E05B8EC7F90672983BF9D4A067 +:1005B0004D8F7F1111C7F7F434CDF4E8D9E607D099 +:1005C000A7C7CAD0DDBB1F5F7D75E7C786B7C07EF2 +:1005D000A0FDE8AD73AA412AEF2EAEF9D4A881C5DB +:1005E000C75F884082F6ECF8027BD4D3D8C6B1B09E +:1005F0002CD0A1A3F4029C294A075A67E1008A2162 +:1006000087E3C1840F48DDEF649D72B4A1051FDB51 +:1006100057DBBF44F9443C1C57EF29C26050544398 +:100620009514DC994C972267829425ED638749EFF6 +:10063000F1ACDDED51A008831C8F38AFAA6FD06FED +:10064000EB564773BBCD24EB1CF6FBAFD3798D7B08 +:10065000C1D80E3E7281BB78F952066F7C64BEBE73 +:10066000E64F54E9C3D80CFBA9C219E54605F63D8F +:100670005FF1F2BAA77C25333774B0FF4E1CCCE78C +:10068000C4BD9DD8868DDC65A8E68F6B300E4563B2 +:10069000A4BC29CF1B2DC37EC50A9BE47F3EC09E10 +:1006A000EC5A952654B2187176DE95FA56B557E194 +:1006B0000A00E81E14D5AE87A2BC27708017636AB3 +:1006C0003098886ABED04B087502F22A99E62863F2 +:1006D0000A35E2EC6891B7172E7B9C67A3BECB442A +:1006E0009F5AF25A8A4C0EBD0230377550EB04F611 +:1006F000DC1335731C7BADDF8A842ADCDE6A9BC386 +:10070000F8AEEE2313E2C60B611A907F5D0BCECCE0 +:10071000E33A6862DFEC2EB6F3DEEA8053D8715F0D +:1007200012837C37810527D91DD834B1CD1E21E72E +:100730007D46718A22FFEA81F01CE7F9BD15FF367C +:10074000C97C1E089C64A24988D63A6B8A0E743311 +:10075000354E96450794ABF4B86551A45E9A58B4EB +:100760008199F748B3F711B98A89FB364331E7ED30 +:10077000FDCD0CEA59433A804333A05F12DC9DEF74 +:1007800063E09D47E853B99A6F462EEDB5DE68FAEF +:100790003560A984423B85412CD56FC2517E82E6EB +:1007A000CF8803B272F4CADDC630D9FAB7B8F1CF38 +:1007B000C00791BBDC27EEFDF49D962FFA88C1FCA3 +:1007C0004C726ACD7620A4906B4695A24CE2BD8512 +:1007D000965C05CA5976A1EF647770AA277923B48D +:1007E0004A5DD4DB1D2DA8720EE118E2CF94FB26E2 +:1007F00025AC058C77077578E73E5817E04BC8EABB +:10080000AD89D261D941221FB495BC703EBD20266E +:100810006FB444AD93927EFE1349C0D630DA6013B4 +:1008200001471A15EBE44E3DBCB198D334C60DBB5D +:10083000DDB6C81ACA4DD2121172CEC800F9B9A2DB +:10084000F6203911A78C6C74FD4F474D16BFE1F1AE +:1008500056767FE2A1B48AD8A60E1AE6E231CE8699 +:100860002A17B1EF28DEFCE6E986DC0FE2675AFFC3 +:100870003B6E9F9071650B7B0221409D4E5916A9DE +:10088000D845DD6EB2A81527CEFFFCDB6283004899 +:100890002335FEBE2B0D9291B034101E9803372ED7 +:1008A000CB17576DB7FEB3C8A83F79781EF6166D03 +:1008B000394D3758AF4637AD0D66E9B4B5C5691542 +:1008C000780CD5631E2026B2EF94B0E67BF9217B2D +:1008D00037244CC10CB853DB2653D10C1CC9B96664 +:1008E000601E81885625F70B356BAF4E38567E69F2 +:1008F0003F4343F6C960349F262AD6B5F32C985A55 +:10090000F4AA1B47C1FA23F4AF0634892B24DA1367 +:10091000C70FFBC09DD387E9EC2D243C586B5F9536 +:10092000480B39E455618B84AC9D35381D3FE9ADEA +:1009300052AA18EC505342EAD35479D21C2631BD46 +:1009400020CA815FDE31ECEA3F4E9C1F3978A776E2 +:100950002073ABF97B3A3D422A6D85E4BEE5C99F21 +:100960004D43BE26E79B7CF243A0B52E47FFD1BD89 +:10097000120DEC2BB70E5220A80F3E6A344EDCDA73 +:10098000B87ADC020F1DC10EFD464A99C957F939E4 +:100990008CDBC15B5C507FBF26F1FFCF6D0BE72284 +:1009A0001F915FA950F53BDFDF708F7175DBE1D1DF +:1009B0007A9D68DF4D04580153F2867A19EA79BDB1 +:1009C0001214EFB551FAA309DE19F165381AA845DA +:1009D0009B2959C7D86DD0EFB13810BDD54B024017 +:1009E0008CEC88115EDD6B83BD0A37BF2785B19122 +:1009F0005B2D1E99335AA14AAD90CB1DED83E86C57 +:100A0000126788361BEA97B195DBDC4F1CABC073CD +:100A1000FD3009762EAA287ECAEF89F189318942F4 +:100A2000CFC71B0F76EF39B7F752076BF99F61F20B +:100A30007897950D7A587A4AB0D064B93418012263 +:100A40000D2B569AF9FE19CBA476340BC9823B398B +:100A5000ADE68DE113E4B410EE470E13D8417AC62B +:100A60002712E33C8EE83C1D14FA9C3C0265CCAC9A +:100A7000A0D4F59B893755173FBA2FF6950402C4C9 +:100A80004C094C9389D732EBDA61DD3DFBB4FA0BAC +:100A90003C5B6198AAC7DF7E7736674AFF758C3367 +:100AA000FD2CAA53A955291A8B14E29C80E2A5D5E6 +:100AB000CBC7F691F734914CCE111B5CF0604AB471 +:100AC000C5A3D77C7C0CA2372C0C0A4CD0C582F96C +:100AD000AE971E9E4DC9435B1DD7BB6EC6A3536721 +:100AE00014A0BD1738FE55C2EE2FE89BE9D915A01A +:100AF0006F0CA63481D1F53B051468EF967EFA633E +:100B0000FED6CD94E6C2A12A55E7F42AE4D1C9A3C2 +:100B1000656E5B6AABD6D5D281BD6E9F9EA6F3F89B +:100B20003E8418A275B7E6F2D0C73315458C3A89D2 +:100B30005CEFB38CBDF47E257A9BB856CD92EECE99 +:100B40007E1A36D3E4648EF7A5CE76F6EC7B893236 +:100B5000C45F93F2D760B7E6961ACFA560C9373C59 +:100B6000C1C29C92FF42A74D9EFDB99D74652CDDCC +:100B7000F520C5D780DE865346746DEC413C18865F +:100B8000134C08D4F649C52B78CA6453A4B25D440B +:100B9000F3185366B22090D17C69511D7DBCD5FC01 +:100BA000291B6CC8B789D4AE6C0001F84011750FD1 +:100BB000E9878EEA327CB61C6C3F6201DC04A2E05D +:100BC00088F3634C05DDE4DF7FB035537BED29E02E +:100BD000E39500AD3BA8CED8740A36DC676887641D +:100BE000F8CED0DD71D8BD478FC9D57AF652C6D0C0 +:100BF000C843E635985509601FC4FA9FD5525786F9 +:100C000068D92FBFF0E363A7B8E244383ACFCF1FCB +:100C10004D2F8731D8DDD6E80B762613E1AAAAA49A +:100C2000082483788DEA95F78086257D927F47F3A7 +:100C3000ED3F37154CC3AC74CFD14AEB8BE511A611 +:100C400011CFD942756206467EEC2E490CAD1F8E3F +:100C50003087582FF28B258E8144AE9A7C82BB441C +:100C6000FE06BFF97A64EE3770EE389CD70458CF91 +:100C70006AB3DCD350C6B26DFF5EE1D28DCAC377D2 +:100C8000DE0CF14C451272440DE00B206B64AC8716 +:100C9000A47C9A06AAB05257106128B2E04684DEBE +:100CA000C0A3B97BC7169806919CAD5100698E13FD +:100CB0003B8E41CF47ABE1A3A693265AF719760E98 +:100CC000547DB6C1C5D34CAA6DF23408AFF0C2FD55 +:100CD00032BD443D6B7A5C2EC167BEC968D595A70D +:100CE000CCC53637C61F2CB9B299CC17E275AA030A +:100CF000ACC54FA6C98F3C59B07D0149D2E1B53290 +:100D0000CA06FCF9B6FA8B8EFFAECDCDE33B72A5D9 +:100D1000F1FD13B8D64CCD5A710BF65418669607F0 +:100D2000B5FC673DFA760B1A637145CBFA8CFEB6BB +:100D3000342AF3F350A762851A39F3E9EEAC59F17E +:100D40009044D21369EAB6A3B08E0B410876FC4BEF +:100D500067E8C0B8A03F5B9C826CFDCF6BA99E0387 +:100D6000F85AAE03A91839FA7385A774DFC625B6F9 +:100D7000EB95D7E467DED0CF23D5CB8131FE61A9D7 +:100D80001C34A8B3587EC61CC7CC5CC0DF09F86E03 +:100D9000D89936438DF2D23A8A67CDF090BB4EC1D6 +:100DA000567FEDC29EC6698023F7893B01231A2F27 +:100DB000C1668AE5DDA9B525C7335BA5FAC5B721AC +:100DC0006685D3214A2F6BF20E520C15A605612BB6 +:100DD00095C5084863CDD144BA856A587F088DCE41 +:100DE000C7960E6747DF4F03E56EDC5772C0A194CC +:100DF0005F517D62EB8125776B18C5E2D142B670F9 +:100E0000B959BA1F32961C2B51024C7DF471BB6D3F +:100E1000C2DBCBFB022B3F9091D1D51220A6388CA0 +:100E20006E37FDD49AEA96214C75D203C98B329F56 +:100E3000A0E19685F2A290496DCA52A557E8459E59 +:100E4000B326220F24A4EED1AB35F86FA83956D1C2 +:100E5000E43662D9EC3DB0812C49E84079B05CA918 +:100E60007BCC3D285D792F251A94B7CEC80B7AEC40 +:100E7000FF786DEF2849681378E213AEA64932F780 +:100E800066EDEFA5BF9AA81AF41454365112E02764 +:100E9000CF72CB48ACACDE350EA194F1936786954A +:100EA000DC02550E12FCACA1D614445F040E694E50 +:100EB0004F3F2F70B6B813F1A3B4DAA02E6765BC0C +:100EC000483A49AD6E72F56094538F30BA5E704403 +:100ED00080A1C3A3BD4835FFDB22A717A843EF6657 +:100EE0003D7FBCD242C9DD984839591CBB34EECC99 +:100EF0004057D2064F14B447C8819C68AE33E89A75 +:100F00000D8138BA6AE6F67DE00C42C9BDDFC68DB8 +:100F100091E9E897AB7EEDC417143E28F9357AB510 +:100F2000A252E43E5539381CDC963777E933224724 +:100F3000396CDDDE341ECBBBEAD1E66ACDDEC0AD56 +:100F4000901ACC74656215B2834831E54BA9E70B62 +:100F50001060C39F8E25A7CFB6154C7898BAB1D72D +:100F6000CAAB7F9FB640D22BAD53947C8FB28944DD +:100F700052BED9B1DFA355B3DF74D3123B1A149715 +:100F8000D38565A7E157B9DE9EA7F3E80AAE1D2118 +:100F90007547922B0010D5BA08B72F46C145656337 +:100FA0009143F8E557D10D6D51235177B8A5EA0269 +:100FB000C8FBA37B144C94A567AF3DF07043BDE321 +:100FC000837E446845FF953C3617CDCFE4348DF1E0 +:100FD000D48E2C2935EC4C2EB5C2031C7505D3B527 +:100FE000E3110E41A011230AF6AF6C7B8A162CE8A0 +:100FF00007848A243FC2EABA30BE0523CE87FABAF4 +:10100000A88A6C3834F7385FFBBC520BD218821AAE +:101010003621F8E9945B33740F90E9B3102DDB8E21 +:10102000D5D171DDBBA71CF453619AF3C84A55B101 +:10103000D1BE9AA058369845CCB7FFC46E05026B56 +:101040004FDE88DB12B887738908D2362AB053CBBB +:1010500042CA7AF05CB7E71490B8D65B1096107469 +:1010600032C74F10960536B3EAD3485238290635B1 +:10107000C45D8F03F0A4C518B311DC03CF7CB66642 +:10108000551B9207035F49DDB608CECFE7ED172465 +:1010900072F8106163BF9E2AA343C7A8738187B902 +:1010A0003F8A8D2A70193DFBF35E222C4C67C7E8FE +:1010B00030CB6FEAE000E2B4D6265994983F0E098F +:1010C0002EA8C91FA5D5F4512E19845A69016FBEE7 +:1010D000104B210CC4C4355832C6C2D4DA695CBE88 +:1010E0009D30055BED1BC554240834293E859DDCED +:1010F000410EE05585088648B96F7E999DCE967F52 +:1011000041BB208A4AC11F8C2C08D78A5CCE4F9ADB +:10111000989FEBDEF03880BC761B00878FDFD88489 +:10112000AB3A5D5EE4DDA941EADBBAD78EBF595F19 +:10113000D90B83A3C7163CBE4BB2807F2E6C39F30C +:10114000542E311225A63BB30A93BB830AB9B68845 +:1011500071DA5A081C9091001D2350E8885490C3FE +:1011600092DB209C1F07F7153998D967481CCE09D8 +:1011700091C68BF8AEE69F9C9FEE58C50A5A491F50 +:1011800001B3F68586F299493F0EBD01276864FBDD +:10119000024A7B83B122FDC50D0A25A01A5E0639DD +:1011A000A103C6849CBF216875DBF03E6156949D07 +:1011B0003D24405A0E6AA26E0D0FE8AD3536FB7520 +:1011C00055EB59FEAB60D2347A0FF8A8B1AB9788D3 +:1011D000C83876ACDFA1862E522FAF8691D50B6131 +:1011E0003CF949AAA85F75F87E7B84FAA5FD5D5895 +:1011F0009F40062E18404605569A1EE866916ECD11 +:101200007D18E01B256C87A4BCEA490E9753F1D9E1 +:101210009E6253856DA19F869A8DF3874AE76E97EC +:1012200003E4D12B7AB7251247C0BEA55110CDF1EA +:1012300008334979F7C3ADC9BDC276AB46F005EDB9 +:10124000ECB6CC0F7D7AD272F3E3126AE4908D791A +:1012500058AACA748E0D48C1A87D4BAEF381256D86 +:10126000E1E13EEF48EF86DF82664FBCB034D2A9A1 +:10127000566EE165C94AC8A4ACA2CE89D6BDC503E5 +:101280007D0DAF39FB98A5D92DD04E8875B5342D7D +:10129000C29E971C1C53D9BF78130613C9E8EE6988 +:1012A00021488012B0B52C76C1F3093B5ACC9B7A09 +:1012B000850E1E5122883519F2B91AA7C668E58134 +:1012C0005FAAFAE099E3DA625F54723A49F65DC0C8 +:1012D00059267925A688EEFC2E1F00C026067BED38 +:1012E000896764AF3E1D2820D6890748A25F051E86 +:1012F000A41858F60E947E13E93332726E6707D93C +:101300004996C479A5905CA0FDD29F123C813CFF18 +:101310006812FB2A0E480073E6E2AE5818BBB4D43C +:101320008BC4B93DDF6AF2D9AB561F0B3569AF02EA +:10133000EBEF4BCC96ED80950AD52B99FF1D75D11F +:10134000034D1D56B33553EB7B09BB4C3A24457214 +:10135000A9251638F64690F598172139F550877269 +:101360002AE34FDD18AF840A1E012958696E9DD10A +:1013700027282AB15B8708A28494E4A0B96686E591 +:10138000EA3624B0ED4B4DA81FD1AEA950F6718FAF +:10139000FCE27695DE7BB94010DF2F82F1D7604EFC +:1013A0005FDCF7C8CE0C168DCCDAB8ADB1411D2884 +:1013B00009F7D8DA5B05F5A0CA96DA5ED12F43C3E8 +:1013C0005182F395BB681B7463E9CDBB86792DA56B +:1013D000EC7E734D86B70EED0063B12BB0EB181C9D +:1013E000FA87E557616CBA8699AF9B4565CEE4F103 +:1013F0007CAD6FFF10EA6088024D0B6B94E0F470D7 +:101400003B1D233C960D4E328F5E830D1CC269AF8F +:10141000691A5392887918CC3805C5BC184A43F923 +:10142000508BCFD975065416CFE1DE2C1119637E8F +:10143000BE73BC6AE31C52834F26B8AB8ACA854888 +:101440008D1AF1022507706CA03ED0B0E5A1F8819D +:101450003E8BB7B0274CF7F8DC11F5304CACEA6E98 +:1014600081DC45670FDF7F4E176A0B9510507DAC0E +:10147000D5C71F2D04EB6FE722806DB18C4842FC6D +:101480003803A389F947859B053FC18573E9DC3D96 +:10149000A5E0C1C5A7B2995DC4FBCDD267E3B99100 +:1014A000A55D967B507DE08177AFF30AE5806C0601 +:1014B00026C031EB083987F05E7D20585D6407391E +:1014C0000BF405DAC62BB5516CBED899330F618E7B +:1014D00047368ACC9136B027C1BEC553D9005104D6 +:1014E000BC0E485B37CF7F1EA00D9CF0290C3E2F11 +:1014F000D4BF8F66E12769717AB48F27EF74DBE779 +:10150000806BC050CDF0F4731EB6C5257A01AA4A8F +:10151000929B983EC3616A95FF67012BF38D9ECE27 +:10152000F32068D9588D9C13FF9E9E38009683291E +:101530003F180D0F20C94C7645F9D1872820119806 +:10154000E5BD9DBEE52A7CC70683409EAE1C21A654 +:101550009F6A63649684814796847F7FEAA6E73119 +:10156000A3C9ED407FC6DBCE323CB5CC5361EA7AED +:10157000D314AC2779C03C2A97BE1677E9C41FF272 +:1015800067029835C92D2F303A347211F77060E236 +:10159000B1FB4369D62C4C5568E855D624DFBDBB5A +:1015A00025CD796112AEA3E9CE1EEFFFFFC3C74080 +:1015B000D7E90F3BF95EA3C5E1BD38BDD1E9E10232 +:1015C000D9702ADF26462787B216A49498AADEDFB0 +:1015D00057BCC8981B794C1D10F27B905269F5BC22 +:1015E000FB2FF56FEC8AC493A1D741ABE502EA8FDC +:1015F00073D9CA45BF672F15D863DE2D6422F8481A +:10160000134964E18910B8E946C8837ACA3693A7BA +:1016100039DF92F64CCE8EF59914672358CA187E9E +:101620007A8484E05BF1C54D79702B11E75C38A9B1 +:10163000C1D9F52EE0687729C447AE309E4F4BB430 +:10164000A39B51B2D6FE12CBD7C508FDEA7358E969 +:10165000D08FA9CEE18E8B85BCA30538BE0A3FCAC8 +:101660001C34726F6C55C5B8F574BE3D6E7BBCFA08 +:1016700063195EBDBEAF4DD06FA4ECB008B05A5434 +:10168000BEF96EF10F79DD102F65585D0D63D8300E +:101690004AA8E821BB3A2A2167907BEF7E4003A34A +:1016A000A4881B07D3CC42E35F46A946D813DC8944 +:1016B000F46BD8CE256C2A89C50AFCFC6129BB8154 +:1016C000BFDAE4647912767C6142EC9D7531ED2DD0 +:1016D000F08B9302B3C4211A2D9EE3C203CA937FF9 +:1016E00068352A1DE082EF8A14DF8739ACE252D4D4 +:1016F0009B09C90CDC6B83DA398877C147DD14BCE0 +:1017000033EA26870FBD91561EBC1772A02A17C256 +:10171000ACB50F735A637A2059FF9ED3F7A74123C4 +:10172000B2792A31CC58A30EEEE96D01F86F5D2C29 +:101730004A5993E1A77AD5913425AFE58DD5156542 +:1017400006B09325275C64610AC9A09A87B59338CF +:10175000CA54249E5D738B09ADDBDB0A150E9FFE18 +:10176000AC08232D01BE7C3873FE2F534DBFDA53D6 +:10177000290F4293961355BA029F2681E1334DC03B +:1017800034D17D9943716A2B2A93AFC8CD8B54070E +:101790008D491CA92C5BD78BFF110A573D03F01E06 +:1017A000F1DC74DBD1A43D6E47A1A60EAE486821E2 +:1017B0004F6866D983CC0F92AB23D5190B89099753 +:1017C0001E43E3E757C4EB7A9557B22D774CBEFE24 +:1017D000ACE90FFE8367CA7A22EF2264F3864923BD +:1017E000EDF686B53E120ED211515D185A9ECE31DD +:1017F000EFACD8D7C49562F68E857E265F2CBCB937 +:1018000028D01C19936EDAE068D5A6A35B57A33BDA +:10181000A6229570825E96FBD29A518BE4E4BDC6F7 +:1018200062B6243419BDE762462239B4435999A6F9 +:101830009FF31790EDF6DEC0E7EC866A6B48D7E9B8 +:10184000BB2390D262914EF24D608C0AD509E5021D +:101850003286E1E085B5995C3D505A0A2D903732C9 +:10186000C9CE8B089D1B19C511D47905F6B857EF61 +:10187000EA4E636D149AF2093E3E2B32DF7AEC9009 +:1018800063618FD6BD74801BC6823E87B3FE9F8D79 +:1018900078ADC5EBF2E8F37E54392C7869E40BD7C8 +:1018A0006B9705025F93C2B4868BC9D5A25A0B43CE +:1018B000B86DB76FA0724AF0CF72AACE4B8FF268A4 +:1018C00088EC4997290D488D7F06A7E033F8732CE3 +:1018D000ACA1CBA73FE7FDF7BE0716110D145F477C +:1018E000592F2F5429FD47E48A7E29B7BE64D3C2FD +:1018F0009ABC3BEA77EEB9A0DA9A5350A9626D9A86 +:10190000A8B88DC0FA9B6AA891A6924B98C89F1060 +:1019100065AE6AE4D1CFB2EE302DEE6E94A8DEF360 +:10192000C51F7B9981DBFCD6615E065183732DBD9B +:10193000B211CAE451DB6A4A0A657D5A68DE650362 +:101940004036BD5F8C8CBB1BC884DC79D8D796959C +:10195000CFDF0EF5F751AA0C53771F4FF56E3E12ED +:10196000D778A497C13FAA8A5A233C72BAA2DECE86 +:10197000A98D5300720E3DDE68FB62B9F8A8A5A1DF +:1019800051DDF8911CAFA52B84463DB3502C316935 +:101990009EE051FEB1482429E1351472A778948263 +:1019A0009E567CB29FAF67A20BB4D216249D5FFEF9 +:1019B000C07318A284A2D3586CE2B163035E92E6AE +:1019C000AB91A478DF14F1426F7B2F56FBF8484CA3 +:1019D000ACE50701F86DD155173AF269D39E9F998E +:1019E000A34FD766941948150A6EDF19C01AED90F7 +:1019F000EFB05709A89C67441DE5A550051DD3E22B +:101A000090433FCA3B4E848610591C11840BE877E3 +:101A1000729A6CB8D2BE94FD0D055E7D2AB363D276 +:101A2000D50F33688E0E856400D257A8363B589583 +:101A300035ECC88E8947AE5847FBB96C9F775A6121 +:101A400034F28473229FE318A923F526B74BAB1E0B +:101A5000D965B20E38741CBDF8C1656D1EBDF8693C +:101A60005B31CA2D0E004066C5F372BCCE4B84318B +:101A70004B06B016ABC0270F828AF6689CD512EFD2 +:101A8000FA2468DB95C7D9BFBF84CFEB619170B7EB +:101A9000AF457D62133CC33C2005CBD7B102FEF3BA +:101AA0006AAAFD891E3F2A771573D65F1896DF87CD +:101AB000DEB0E89AB41841ED7CA22D99EA89DAFEED +:101AC000B6CBEBF255DB7A4924DE8CE4AAF1CEF4F6 +:101AD0009F0CE8752B35925846E70DA1646142D3FF +:101AE00031BC995B0C5CDDC0CD18AD56327F9F0ACE +:101AF00076B580C1D73CBBFCE3219343C5DADA5607 +:101B00007CCF725D8EA07CAD86D7D7F2BC5915858F +:101B1000C0B98E751B802E129A16E0B714EAB085F4 +:101B2000C2610CB25ED1EA256F61123D9C7ECCE9A8 +:101B3000BDE916FC0EADDAF545F510FFE233A7C39B +:101B400002A8C9F2B205C7707BF38ECC6ED519E638 +:101B5000573FB2555A31506091719BC2F6A671023F +:101B600019D3164359F6AA31FAAA8A6CCC4F803C95 +:101B700004C63EEEF217F75AC0E907BD564E72167C +:101B8000247926D525AB1AC7BC3733A42C926CA177 +:101B90007F505FDE54ABF070FDCFA8A770B7352241 +:101BA0006C05A3F53E31EB743C6853BA6878265F48 +:101BB000066C1A5CA6FCF307B13931B0D11DCE9684 +:101BC0007C402219AF43C845273BCC0CD0B7243901 +:101BD000DBF4E6D855905CA8A9B7018DC4AF328676 +:101BE0001A917615253BAABFFF242C86DEBD68110D +:101BF000B8BC60B4A18FED7EA5262C27E43B7DAD5B +:101C000060BE0C7F5AC379C1BBADE896EA8DE97519 +:101C1000F059C686A0FB400F576A4162821757F5FC +:101C2000A13E024EE397AB4E09096D9619436F50E2 +:101C3000802EB3027F4ED8B98DF035B597014B8118 +:101C400007621AD1B1D72C814B65168B2F89E5D845 +:101C5000CF2894E7ADBAB4ECC4194520994DFD5F87 +:101C600069384C9F13A5ECB90603D245D916F26228 +:101C7000D14F3FA1EF10ED7AF3123262316061541F +:101C8000D9C7533CB1658ABCE5B552457998CB4D6F +:101C90003E62BD595C87CB62C2846BA3D477F823C4 +:101CA000D7C833D316A1F87F5A6E3AC1C2264B93D8 +:101CB00044B8749630855031C5E2131B4795F6152C +:101CC000F9DC95C1DCCF30B3FBFFBA5E31BC1BA29F +:101CD0001EE1576B016994075096C4C765A82F474A +:101CE0003D06B930CC965CA11AB374B2C31864A196 +:101CF000E1B100EF0B6D764CE250E75AAA51F36F59 +:101D000033BF52B503989F3A26A8298D2652582CE6 +:101D100093C22EB935268DDFF6617D90CC365C8E70 +:101D2000D3108ECA2D6B3EBAB6678D55975D1440A1 +:101D3000BAA0BDFF17F51B8B10C0FEC2EDCB1E383D +:101D400012108F8D780E53E94CFC959BB1738D5C0E +:101D5000924F301DF30CABB4E05B178BAF8576EC84 +:101D6000AAF8F61D2C2EAD46D1FE7DF348C0FACE62 +:101D7000606CC580A828C586E71D72704A095C168C +:101D8000AF9950899D55943DA86AD6CC12B612974A +:101D9000EC58CD88A2D8D65ABCF000F439B0D79010 +:101DA000EC484C5F0D0A57D6D34005E04B37927B89 +:101DB000D6063C5F08652CE18A732465A1BC8D952D +:101DC0003B09F723049719AD4B587A16F3462BDFDE +:101DD000C44263953306A152730FF18FC083C6F7D7 +:101DE0007359E6B7D22132C8296D77609BDE5489DA +:101DF00065FD079DD5D430820F29A16512D30C8FC4 +:101E00007B7F977D44A862DA89877555A8280902E7 +:101E10007C04EBEBB2F3883A3E0A4D24D0AFE7F2F4 +:101E2000E50A514474EE8276EEE4F2A7BD2A9442AC +:101E3000EADFCF1BF7CC0453167DC24D6DF3485239 +:101E40003CC7250E1D458A9669AEEED29BE3041D64 +:101E5000285B747E0590386F3D3F8FED4B2159D73D +:101E60004719BD6D11A970DCCE6D3271CE7EE88C44 +:101E7000414CB37A64265201C313E58BE1DBD4896C +:101E8000068EF1F33A5210174315FE70E0D6DE1FAE +:101E9000421721E3A6D530A28ED16A75330B3501E6 +:101EA000EF3B508751FD92AA3771DDA158189E5122 +:101EB000C3C7A566BB7E3E8662B39762800A4AF4BA +:101EC000715504AE7122AACD35E8F6E9432C47CB13 +:101ED0007A340342C4487611131E54434B34D9F666 +:101EE0009BCE08BB797FCBB0D37EC5CD2613C382F2 +:101EF000849BB81F3E11E94F26C1A50929D1D5BE43 +:101F00003378D6EDBC4E80232034DD2D9536F9B3E1 +:101F10003621588B2564737209DBE299EBA0DF68E8 +:101F2000B2FDED80FB85F3A7955912C15B85DF807B +:101F30007B20129F23B8035307456F66FEE4C81D3C +:101F4000571D5FE30B0A461378D933810B2827030B +:101F50004E00A0D99924F762852F2275BE3106C4A0 +:101F60000635C47CD72DA42659E3C5D590CBD01215 +:101F7000FE1C5845E0A3FB61A2AD51EF22F67AA307 +:101F8000B7768258D0A35C3DD15506A7BEEF189214 +:101F9000131EE63B6ABC3F222D8465733AE57190BF +:101FA000609714E5CF2725B7B262A1BC8A8FCE6CAB +:101FB000E447715E8B9A106497767383C333CA04C7 +:101FC000329A676DB84DE25D648A208BD35F828759 +:101FD000BE5E068ED4594DFDB397D4B923CAACD991 +:101FE0002CB1F814C39580804D0DCFE589C871B729 +:101FF00096D5E845834228E6A9D64312C7215C144A +:102000006B673BCA8361EC676E26C98973CAD3DAF2 +:102010006A5693BBBA7448B0BD5A45DF9F0B692B13 +:102020004F6943D376E34B16F099AD4D856A6AC884 +:102030001A2714735363F1458139116EB4D4F5989E +:10204000F1136ED9290E97763E8BA74A838D36D829 +:10205000AA3FB783BE59894B4EB59E4F3D665988FE +:10206000AD59E8217C019DC14E4636665CC6FE2610 +:10207000241E0B0F9DCABC7FCA72BC389903E012A4 +:10208000AE1228973E7AE08DD0764E3E1A7CA5603F +:10209000CB8ADB5FEA3CCCC30FF774F5F27AA3C3BB +:1020A00071AC1E6B6E4F0A2C4A36192797C6AEC309 +:1020B00018CCB8B2C26A0D1220232424CC5BAFF135 +:1020C00057544D72844CB84513966DE0AD8349FC6E +:1020D0004EEEACC0811FBB1F464A32B610EE6B639A +:1020E000FF34A700C6EC641D3ACACCF55C8947F6FC +:1020F000608D735A4333977C13F7A0BAE602AF0B97 +:10210000F914D545329DE0BD638823A73ACEDD7D25 +:10211000DD014AAC14C2B562FD2827B3B7EB4E907F +:102120008C7A4FAA2FAB8A0CCB91D1838BFA34F9DE +:102130003B07701E38F79B64F3B244BD58BB32199D +:10214000235F765789C218323CCF1A4122C3507F91 +:10215000A2C49D482929A4DBDE606CC548AAB2A5AB +:1021600026DBBAAB50EDBFAD95CCF7C0AF32E92955 +:1021700009D60AB25B8AC8791B1BFD5634D92E4991 +:10218000B52C07AECDB7574535C5E1B273E649A0CA +:102190003308303A8FBE6EF85EA3E154888EFED4C9 +:1021A0004A392571153BF6D4AD7E1D2751620C1EB0 +:1021B000B61EE27FBF10C3334986DD45735BF5442D +:1021C0009475E73427452073365187126FED1CE074 +:1021D0009558C2EEB80C7FA68D56593BC2DA58DE30 +:1021E000143F2AE0338328A7D275F1DB2A7614F84E +:1021F00044A98C90F5BDE9DD6605A4047298C90E6A +:10220000CC036E3A1AFE7B3737A8DBCB50E731F1AF +:102210007455065C32311C7D74A894FF552AD4EAAB +:1022200019F1BE93E3030DF79CE84B5D607CA910A8 +:102230009C320E1919ACF25369E20C004E061B9445 +:1022400017E1640FA1CF0527F4028CDFE06300895A +:1022500028951C9713E1717DCFFA810CB24B89F65A +:1022600073813861F66A13062F1D750BB1B603C66C +:102270004C8B8C77AAD5904AE40E3E2E4ED4A30503 +:10228000192AF848D2330272ABDECFF161167C9D79 +:10229000EF21B2AC398E4CD1DE19A07A92BBB207D5 +:1022A000BF533D20B149C0C05EE81387C85F6EBD13 +:1022B0006B5A05BAA8067A8DD0D0DA81E3114B6249 +:1022C000F9A92714B0FF840D3CAA1B893E9770B36F +:1022D000A2CE1C32BA91549CAA78886CD421C8E250 +:1022E00078BF7E76ED88E65EA176CD068DF9278CE7 +:1022F0007894E9097F1CF843FD6F18FBB57CC82B67 +:1023000002936A351D950CC8B6143E3C86EEB0C7E4 +:10231000173E80E7123977C3C5B435A3BB8997BD93 +:1023200081A4AF32EF5BB7D5E85781762BC3B88471 +:102330004B148E0BDA56D19A290124CC046403760F +:102340000DD8D84EC4C3D89BE17951B016632BC0C9 +:1023500075735E694DA9F9C82F42155CD10EF9FD60 +:102360007708B8050F42D6E853C5ED8926259D4963 +:102370000CDDA08515E9F3BEAFDB49BD470A9171BD +:1023800084725C3D99F141130DD26BA85C354238E3 +:1023900092898912F41CC8B4C71351776BE05806B0 +:1023A000BA415B283FFD2541C2AFD18691AA4FC9F2 +:1023B0001E01992FA7462CABDD1B0C16F4F5E54E3C +:1023C000005045E94BDF77F58E77E4DFE6B150BD8D +:1023D00074BD67A0365A6F76712DE18330020AD83A +:1023E00087D9F0581EA41701B88EC87C5EBC40E1A6 +:1023F000B8DE38312E33A6D0700C1DB24A73B753F5 +:1024000037C8EB364F25A9AF92DF13AC3AF6CB3D78 +:102410009337387099FC4AB2A92B92C0A2964A9879 +:1024200094BB675A7BBB6B269FB690A6F1FBC66137 +:10243000A945BC59967317447A587A2CDA3204D2DB +:10244000B153D6735E4644F215C73E0145AF78548A +:102450002AE80253969417026E74C8E16661A5BC1F +:10246000C123DB8EF140B596712306BBD4F043B98E +:102470001204D0ECC21064081F89418EF9F9EA5B9E +:1024800055FE48E9DEE574E7B4AFA74FF48B60432F +:10249000F2BD81E4489A62B8D94342467F854093B1 +:1024A0007804A56080A14896510ECD89B76AB9B667 +:1024B0007EA22CB9CE5D7E9FF6B20B6497C706A6AE +:1024C0004A702AAEE5C0043C40E6EA9170850B00F4 +:1024D000E16C245FEAD94B6E6CE56AC9074AA0D764 +:1024E000AFEB65B7550F402E41D13C6253341223F8 +:1024F0006D343531B8833A72FC020F07F95910B6C2 +:10250000A990B6D5322398D9749291996EEC3BA8D4 +:1025100010C121CC69A9CC1A77F1B7D016450D842A +:10252000D82D6B3A86F762C6FC22175D51720EB445 +:102530008CF83B94ABB49106160FC08DB19839A5B9 +:10254000C7C0BCA39CFF9BB057FD58A6431C9B2E45 +:1025500022BDD86B268CA3C6FF3B583F8DF09B3E17 +:102560008081CCD789883DC6945E23BD1FDAE2B94D +:102570002F02ACB5D8F1A2EA20E2534072D468FE33 +:102580001C2EC8D046B363EAC3A7C9D9269DA03480 +:10259000FF17700B3E28FF751CE05745DED885F00D +:1025A0007465CC1CE5C1E07A88EF292921B2F8F2E4 +:1025B00059C37C27665B8D4017693DC360CE8EF49E +:1025C00018EA1AFCBAFF0F3B967B3F42826E33F14A +:1025D000914B45DDACCE15AB60DBF1F36B7820356C +:1025E0001AF7611D580CFF53C79E196FB46EC30ACA +:1025F000AB6CB1B4775D6CB58F1F59FFEA5022BE4A +:10260000FF64C3E8AFE3E316DA496B2DB35C3771BF +:1026100072D8D52B2EC9C4966424173850E2F4CA58 +:10262000740044BCB4029C3951EAA5338DBFC7F88D +:102630002E173AE072687C209AD1C5DE4E58990771 +:102640009236541CD25992AE2D7A6A7829A8F3F3A7 +:10265000B5EA9B990FFD2C75A672156B1FC6F2602B +:102660001AB906C102514990214172A2F32835726C +:102670001F2F1F755ED2839397C3C113FD34F96B6F +:10268000C84BCE9F38E3533AAF0C7FA53D67E7F8C0 +:10269000A18B8164FD94352E510CE0E62E09B5998D +:1026A0005B0949F682414C9EA3A6DE061459B9CFB8 +:1026B00048D0B5222CFA14B0E2C67AE130BA098BC0 +:1026C00095E89C74252515CBA23B3F6FCB3A31B6DC +:1026D0007A5238AA4A449020060D55CAEF3AD69647 +:1026E0002DAF80EB55C1960CA18B9B4F0A3D600B23 +:1026F00027CBC5623223A5341D76E4430E493B4FF8 +:10270000CEEF5830549A0DB86395CDBEB3197FB053 +:1027100025B5C51E494CB0FBD62FE7089342294981 +:10272000F1EAF0D29A8FC28225D02AAA0626D6A52F +:10273000FDC28E3934833AA981D7241C48AB8FCB94 +:10274000B2D5BF076C59BDCA7E865D32F29C640665 +:10275000997B126B773CCBE6AE58876DF196099D5D +:102760006769D7013C8E29BF3C926D5CC058996265 +:1027700056BC93755DC35F96803D929F6798E11943 +:1027800096C9C4DE8C32DC77EBE851EFF247329128 +:1027900047FE99C916728FAEBB3AD5AD95DD9C0D3B +:1027A000C75A2B65C0E2561CAE367B450D205DC274 +:1027B000F2859D1CF7207E7990CD1AE97D1CA5FC41 +:1027C000F260DDB02C1179A753E50E1069211C478A +:1027D0004549E3A06BF7AA3C2D18BC4811624D0790 +:1027E00089B95DF6042F134F14D603CD2F3F06BED3 +:1027F00022E49759D239D5B6A443DE93555180DFF0 +:10280000CC560DC37078DE3C7DF5F8C99387C915A9 +:102810000BAB071FD39E4AB0FC0C524FA529DBA679 +:1028200015A23A98143CAF3BEF78B2E70DFF430393 +:10283000FE777B0A0D323581F637F116DE2FDEF892 +:102840009159DA93C3E5B972F2628B98163638B2B1 +:1028500087A55FE8F57843F986771231826C463CAC +:1028600096360E1037C1C6801DD59D5CE2CD7A5CD0 +:1028700016D5726097F5BD19323E7A206C14304A35 +:10288000C1453F4E32CE3C708D312441874745A231 +:1028900061A40B5214A822141FE8AD0D1531639BDF +:1028A000A2DC8BC40224F40C3985000BEEA447CEC5 +:1028B000D488FF04F07D12B03EB04FB70D1987B732 +:1028C000CA408EFA58ED1F3CE914770D9BD411FADB +:1028D000523644F3DFC1811A690714BE5ECF8018F7 +:1028E00024D66ACC60128DC2B0808BB46064996CBF +:1028F00038E71C5F02BC1C1370FA880CA025F8FF97 +:102900006D214DD3C8588A82B286495DB0E4FFA1DB +:102910004F4576DE237F98188AC20C1A07191EB914 +:1029200087EC8E4F41EC60A6BDD0053C4C10941F47 +:10293000266A51B4BACA91B089248C489666C353AA +:10294000119CABC131CC156E06CA5C792BE0B60682 +:10295000A08905F2F5213897B8303AF07299F5550B +:10296000918F764BDDEE2C004FF3184F7857F82EF1 +:1029700013BF49A575363269EE1A69250B18389CC4 +:102980009E8E61C663FAC5EFDAA0A0CDFF34856CD8 +:102990005DA23FE6407F6274EB6454969D6C23F920 +:1029A000139DFADDF45FC41623CD2A395DC0854F2F +:1029B0008B47FF6A9EE53569DE3CFEDDABDC478E6A +:1029C00015DE309C35F998ECAFC58558AA3A6301FD +:1029D0000C9DEF763F2188C67FBD7C9AD401C0C98B +:1029E000F4F7244046CACC3F40146A42650EE17FAA +:1029F000A2C015E593FB87CDF3690270B219C075CB +:102A000031C3B2D5F341901FD80A867C502A3DC805 +:102A10009742BC61A287D6D0C41C7C23EDAC0BC905 +:102A2000D0D498B1F322CB2882F1819B14C21B270A +:102A30002B219AB9A910D8A27E525F4DED922BE3BB +:102A400033EA93E2F5D906663BB20C00D6A5E3B8AB +:102A500007A52A176FF52937CC458F983B517C275E +:102A600000B9984326576506522817222C37376A33 +:102A7000271F5EA12B228C680534387D16F614D2F0 +:102A80003A26C76894ADB180208F833BFEFE56691D +:102A90006DF838EE9C9D586DCF8599236AF446A455 +:102AA00045849B448E64C5437A2DCB39B458F110CC +:102AB000DA6AC77152F829B48FF3DB7B64DDCFCAC1 +:102AC0008215BCF0E8052E572E5638541EC46B12E2 +:102AD000E1D396EAA484E3AF09DBD4B8DB7137BA5B +:102AE0000E92019145B51C1EDB0DE132D6D2883B1A +:102AF00080E8FBB7F23C165A649BA7C0CF5C3877DE +:102B000059A3272CA1CAB0840A8F8556BE52863994 +:102B1000A092C8E333C002D430655FB237D5FF124C +:102B2000598E7D780E721D4068149E833597D43B74 +:102B300049E623ADA284180D62B4B7A9BD0430E301 +:102B40003A19C7563D87A99DB68352956B9DEA6198 +:102B50007ED5195B8C26318115F31212891C4466CF +:102B60001243C8B9DAEFCCCD9592F3E33BC7C7C7A0 +:102B7000DE2E22086D185B2D1F93A78F73ECAEF12C +:102B8000E5584417C400D34DA92FDE9405519B5638 +:102B90006A200E7F458C467DD87F03D7AB32932FBA +:102BA0009154F4CAC5EEF1F69437899AF556CCA043 +:102BB000010DF9E3DCE1D9C5EC43BAB03C790B3C3B +:102BC0002BE9E74319C3D950369D4B47460C57DBD9 +:102BD000380918A89304127F184C333F2EAE5ACCF4 +:102BE00006730561D47B33C679769FFCCF18B33B5F +:102BF00005E7F10A452CA0807475A21E5E88C6D632 +:102C000017EC8B3EAA8D42EF387D86D407B084172F +:102C1000E0DB948BD796A5CC6E6E4BD7115FFB2E65 +:102C20004DA707D9F6405B098C549B3777829043B8 +:102C30005C05B56DD2C2C9FBB74EB80AF258E7FDC4 +:102C40003B11BE0D7D0DDFC32D473B16E18210FD0C +:102C50000986E0ACFE20C123826DB88AC5CE5B4EEA +:102C60003C6622C4CADF989A0BBE1E8F620200F433 +:102C70001182210B9FFA063D4DD37EA4135D181ED1 +:102C80007295E01C90B78B53D0E08B786DD551D8FE +:102C900067CCA6FBF1378A9AECA9390A9FAD50DFC1 +:102CA000FF93B4CF8A6374E04068CF5D544FC5DDB5 +:102CB000FD920DA96EFE6A0761FD5A2FEFF712E82B +:102CC0009198F4801642005C7F42E0901320B3A2FA +:102CD0008E906D47D7245D6CBBBC1050795965440C +:102CE000B0816A85DEBE3C8F08D52630387F48E447 +:102CF000CB0B7CEA90E9035E01CED1CA9802A9838E +:102D000090A43DE74A0D8F4D87F4BBC032B0812EB1 +:102D100054AFA38D4FA79EF061A267DD859528FF74 +:102D2000D95990DB54158385E497C555830DB6D7E3 +:102D3000B6E6FEFD2919DA81153D6F32EBF09421DC +:102D40008CAB2622EA232EE9DD6542E54F6EFDE6D7 +:102D500095393E1D47CD3D5CF6B2987B71EE1887E4 +:102D6000A90751F7E30B874C9AE9FF2C4EB95A118A +:102D7000E1A82AF1E5769573B73EB8898764B1EF8B +:102D8000B8F638B044C97BD67B894064FA1C0AACDB +:102D9000CB38DF5EB0D15868A00F007474C5072926 +:102DA0006178603555055DB6D336A36C743B7DC242 +:102DB000AECDBE83A5FDD3A1143134DA54F7873DDF +:102DC00039200B40D6EA312E38C3A6FDBD1262F27F +:102DD0000A1F8E9F7076B0CA8597EE987F96C0FCCA +:102DE00009CE0FC1967E62F20B647F9DD813BD732E +:102DF00094F5F091262F71F6EB544DEB8B7E224B20 +:102E00001BB494726094012911DEC9CFF5AEBC7B6E +:102E10001E3B33333FF6CC7C07461949CAE52C18D4 +:102E2000BF6D3E0C23064B5A0FD217F17D975667A4 +:102E3000EE0A60A62E5DDE4278D9C6EBEA9702D58F +:102E4000E62C22BA715A93E0A49EB674D1591D02A1 +:102E5000AC7F549EE2269FC70A1D7DD6FDB422FAA0 +:102E6000CB600E9657750E966EA363C392E67819E3 +:102E7000BB7C9E102B1874D472FDDD7A8CC719565A +:102E80007DF5379BD01993F02570F3DDB41464857C +:102E9000DE52BF3721AF7C0B3C0A742490901ED0C9 +:102EA000ADB8C7496A9E60DE954D55A4A626DEA042 +:102EB000CC823D50F8E47D087545DBEEEF195D35B9 +:102EC0003C2CD02D7155D62B68BD010D754B2FB5FF +:102ED00008B0719B8907FF768FD1DA5501C8CE2ED5 +:102EE000944093DB99B5C47123EDEE33C5B3B7E9D4 +:102EF000FF0A1F175F03102B7B45715778CADE341A +:102F000074DA9BA7571B73F9D98A711C36954071E7 +:102F1000E9B31B5FD8F9E9AC8335211D3D49A8C44D +:102F20007A55E8FACC82882674320CB54DB1F18816 +:102F3000B28219455706026EFFD2DF0F88ACE4E873 +:102F40000489FF3C0E06DAE809DBE482838B521722 +:102F50007FE6D04F368AF12A7EC1F6694C9B5F7BB3 +:102F6000DE77D0FE80E8E531CF4994692C5F95E1AA +:102F7000F4A1BF852F0D96D054D2EB6823708258F0 +:102F800068C5FF64F317BCD0C095F596AA8D5607A7 +:102F900027B12E7F9F0BC0B5DFC17C95653B2547D0 +:102FA0004C8E1F9F9DC33A7C69DD878ECEF0F895CD +:102FB00076449B9911C0FA39AF084753C65FD310C6 +:102FC000405E1D1096F81C279A47AF70F3B5B6B94E +:102FD000ABD70570127A74C01697035C6D68D8CFB2 +:102FE000B6E4561BDD0ACDFC7B048E89E5326A5EB1 +:102FF000A502698D303AE61BA34CECB7EF2FDB53EB +:1030000050DCF65B8299DAE25CCD6648612D51F7BF +:103010009D55FBE272F69FF97AA146D967C957F52B +:10302000BED4D06015545ABCA055EA034A819374AB +:103030007319325EE7A24260AB94A2E36C58C15BA5 +:103040008C5A92A312DDCC12AF6EABD6A0EF10F269 +:103050000B64EF131717364572908AA48A611A76AB +:10306000951F5471292B55A07D38F8CA84FFEBEFCA +:10307000FB3B29B99A8A91486A9E872D93CFCF341A +:10308000B329688D65FDF2944266ED720A82BD6ACD +:10309000CBB3A90E6A203352E4168896F9304D332B +:1030A0007AC9FAAC5A4C39781C79E3A06830E38FBE +:1030B000D93515344CC6907225441D77D337FE6E32 +:1030C0001FA17A3C7816BAF2B5E423257D60D85268 +:1030D0002F0AD2333A8140B800B126B26850D741A6 +:1030E000794997067FAAEF9861AEEF7633035909C5 +:1030F0009E916CA6E8566116F9DC0DE63E40C7814C +:10310000BDC5E03A168EDDBE4DDC6EB9236A418343 +:10311000F3A6E45248893FD39F6A8B3A9272E37CCC +:10312000FD2F7FC7A34EAF9D485181D19CFE9832A1 +:1031300080CF10B22A7950BFD841B74FFF9EA2E18D +:103140009726ACFA0161B869D4D90EC3CE6863FE84 +:10315000C30DA9CEEF3652731A6E3446CC1DCBB3D5 +:103160007F0E0351F72D6B4A6317E0DB18A049501F +:10317000199FE5D413994344E07B61987C841BFC40 +:10318000D3462AEA4D6B1D73458A591258524E2B6D +:10319000C3584AA03AAF6EE6542382DD39381AB9D3 +:1031A0001A94319D017E242E6BD82CC05B56A85AF0 +:1031B000614B51EA70A236A8356AFE1A901859E69A +:1031C000C2A997E7180DE39AF0A3A7AA17EE8F8676 +:1031D0002214376C53B6C82C5B480E223484B56178 +:1031E0006130BFEFB22F0153ADCAE39E1A81A8B779 +:1031F000F53F0C271CEE5BE4933E4BE5C2CA93DC23 +:1032000017BAD6EA4C26963842D632E71DB5207555 +:10321000774456A7EC918045BC6C33C7D7F289C37D +:10322000F6A791A897D1044448E7DACCF7C9C4BB04 +:1032300058A792FCEBC2A42F03F161F2F3CAB6A91E +:10324000B963517B3C273D0A21B12DB2F8F2CDACD8 +:103250003C263433E4295BA8CDF040FDD18E9DAAF5 +:103260002043B9E49D6758C791B4923A4376B36A54 +:1032700083C3A98098292438F0915D4836417A02A9 +:10328000A701D54BB1BC0043B830027E6D9C7C10C9 +:10329000BDBA825B4F79B4DD62A3464F820037B777 +:1032A000FD990C36D8C0EBDCF271D93B6C16394E67 +:1032B000839EDBCC4770B54CD0D6BFF40EE6E5E17B +:1032C000964DA30C507B33EC4FBB1D39435480E526 +:1032D00094E6A20E334E4359B1C3D0519713D1D4C3 +:1032E00039D09C8A43D0F9D576A62CCF7A33A0C7A3 +:1032F000376A1D845B4FB17FC901E952FD6A6A726A +:10330000E87DC5F1F9D5D7BC919EC50F1366F2884B +:10331000D4D8CD6F494D3D3793B7A182D9BA1801A2 +:10332000E7B4D56F859C412FD77E38A8CBC72A65D7 +:10333000F5EEF93EFD634DC06B57AC8C27C577FFAA +:10334000906BDE6EDBE2F78C67A49376BEBBF20671 +:10335000E562F3AC70D14927AE0E8FE90C1E03BBBA +:103360002E7916A85320FE8F91BE194D040A447081 +:10337000BE6A93185C207924A2360F6D7EDFC44D9F +:103380009F8807C6D85519EA35C29B1F9E43E75947 +:10339000587D3D72D79662362873E9AB8336061A9C +:1033A0001D6F046549AFF928C929EB9EDF243091D0 +:1033B0007911D5945722D83F121F4CDFBC54785B4B +:1033C0000F24E7DBA4CC553F857A741439219B3355 +:1033D0004CC197A1AC51880A654BFA339494D244FE +:1033E000F02A9D8506D2DE297D8C78DAAF6C7E16B8 +:1033F000DE15D9B89C9C9B1CCFA83BDD48511B19FE +:10340000F532368C87DD65B473D64A9E759C7B7227 +:103410001C2B955141D3CD0EC75E4BF4448344A47D +:10342000C9FAAD651F8F528381E20555088356F5B1 +:10343000F36A2AFF9221F233FB831AEE0E255955C7 +:10344000FB509F074E0E2F43D79D6918C1BA55FFF9 +:103450005E119C0BAF95643AB55A3DE750879CE1ED +:1034600094A164A475815FDCD918C266EB49FB2086 +:10347000A790D24D7112B4AB5D3C5FFFB4C0E90AB6 +:103480003E7E93536A2079F140FD386C40AB8A95BB +:103490000CD1A3D99A4B02B24075F0E722BBB17EA2 +:1034A000E6D02818627E537264ABC287E641CBCE69 +:1034B000106BD5C7E822964C4D9F543292A95763A2 +:1034C00096AAD243BFB6E3E8543FEAAF9570D22044 +:1034D000D912F5BD851B8E3C3B2469D639C7CEC5B4 +:1034E000FDCAB90700BFB1160A73D016B05F4C9C75 +:1034F0006378A66971A597EEBDCC3EE0AAA9FC351C +:10350000670DBA95C6C383E2E353FBCC6B6DB57F01 +:1035100078CBE49D9E43085A2F556C74A523073839 +:10352000D4936C0D191891193AA292BEC51954582A +:103530002DB38F89BF03B38D7C1D7941F43FC67FC6 +:10354000BEF99E99F7C8DB4063A12F563BB492F2B7 +:103550004C8EE2507245A07DE1B7C90237BD15809F +:103560002E2BBF1B721E7C806E6321DB89F92C7BA6 +:103570000C3E4283FEE8702B0C5D330C306E978F4F +:10358000C1B4BC5BA1A6C357D7BCA7D7D9646E6131 +:10359000DCECAF50D3BE285A1BC99E185E6B2F4679 +:1035A0009E85027119643C149F789FCC20D7AB5B39 +:1035B000BA61C27ADC58C453A675501BAC2E6D306C +:1035C0004681D3E030455D4F68E86EC9B0F41FB95D +:1035D000313B7D2B953AAE569DDED3E2D710821952 +:1035E00056A5378F26CF5C70F072864E38D9330FD0 +:1035F0004D12630F27A96718004C68285287262BA5 +:10360000CCF80BD5293A121667249D8813FD11EAD0 +:10361000767424AF3DDDC7D2C5AE32FC13C6568DDD +:10362000B60F26A64911A3A62E84F4DF75510EDD30 +:10363000EF0D9B72D694EA21AEFA03332C5749EB77 +:10364000D92D4B96E427EA66734429B446D956D758 +:1036500055527D6FCB2BD720F9B466CA566438AC6F +:10366000A6AEA56BB62E63CFDA505B1443D2D086DC +:1036700043FF98B93307203D645F68CE261F10BE14 +:103680008EBD4D04B85E540464F2EA94B08888CECE +:10369000C0BFF59DBBC9C2A485550324385F9A4CB1 +:1036A000ED356815BD1CB8A7176B70F1127B7ED97C +:1036B000A4B77456AA95ACCD5DBF474CB8CFDF46D2 +:1036C00092F4B8F7A1FD603584F8868FCD35450DAD +:1036D00017B41F7C4E4E42B3C6610DAD1AA8A84C5C +:1036E000AC2FBF9A22D00A11AD7B349DF8AE890D64 +:1036F000752D02FD76FD3DA3B8F5B8A14777BBAEA9 +:10370000E7BED0646EB755BF132B0FC3185250E3FA +:10371000D01C12523A8C5A72365003313BE324705B +:103720006ABBA3FC0067DE75816670112A8D5EF1AD +:10373000D8DB2DEA0982B05E9970D36D5E32EE6FF0 +:10374000736064D39706B95857C4DA58BDC3855E11 +:10375000827FB928A650414FC5BC2A0CF991F50EBD +:103760004DE38A9194AA8DEA83FA50E8855528F3AF +:1037700019044D04A02DDDFD58B44B62F073518245 +:10378000F3D856C7E5C5FDE9D3FF8D085F7B605AC6 +:103790008AF07EB5D60234B591619D1332298C54DE +:1037A0006E3517526264622A136C03CD4D856D59D4 +:1037B0002D02CE4CD06AF475FF76D1EE2FBD7DFA86 +:1037C000BFBEAF033CE313F487136D67608F55C62C +:1037D0001A05A452D5850892F2E5AD4C44C77E6423 +:1037E000CF4254A4E63EDA0A283FB55485AA56F1E2 +:1037F0009E8BD519A8B516B698EE0672C45DEFFD7E +:10380000E544195B84754043D0C9CA1C1E7904DBAA +:103810003FCF4B784606FD48BC1194989618431646 +:10382000EF14DD133BD422B6C9E2BF0DF51342DC21 +:103830003F80F77E559D6CB9DBE239F9D2706EB5E9 +:1038400004A4F60FDFE81208DB7C6321121A528908 +:103850007AF4C6BBAE022D1B8245EBA921A95445C3 +:103860002F3A3F2C70C6D1E3619CAC4B19060FEE8A +:10387000B5347BFE665103F6A04610EAE9CF3589E0 +:10388000CABE85D9E01308E00EAF6423879D58E1D6 +:103890004C9F86220971053C8292113A0CEF1170FF +:1038A00059766802C62336C2F2E053C51BDBDFA59A +:1038B00024055A69A41591A344793008FBD6B02E8B +:1038C000C4E6BBB6ABED5786C2E7F49F5964A6E1E8 +:1038D0000CFE6AC1CA085AB42E9AC32A1334AF58D0 +:1038E0001657927BDA75ADC325F357B043BA7CDF28 +:1038F0005AAA39C38C54836341F6D224ECDC2D6B75 +:1039000041AEEA7F58BBED61024342370F71E523B8 +:103910007B492EF000A63EA35EDA4EB0C506A3801A +:10392000467B613F87646E1A7B2FD555B9D842CD4F +:10393000EF2DFEF00949D58BA2712721F1170E91C9 +:103940001A39BAB716349A1B240156C6F29E483A61 +:103950006438575ADF064C8A669CD2896656AF5344 +:10396000B530904769E35764CAEDCD5515CEEDB536 +:10397000A8AD1CE7E2413BF4E49389AC920113BB90 +:10398000F26F51EDD58054338710BE8DDDE697E59B +:10399000945D6A12D589759B719DDD88FAADE8E367 +:1039A000C67D327E06BED625922053035525171DAF +:1039B0001F77BD8396FE1D5E72BE45C289E95B041A +:1039C000174DF6D39D582765503423EDED598FF9E7 +:1039D000D7A33B7055FE652398C5C654922F41C5A9 +:1039E0007CC508139245AA601007D848C44CD27C05 +:1039F000C8A736A650B4254C6CDE06E598E07BAD32 +:103A0000C8D37AACE470917EF45B4FA0E43BFA1A21 +:103A1000D5A6A3987CBBBAA63A5374B9E8ACF21603 +:103A2000C083719C73BCDEBE83888E8F361561AFF8 +:103A300081A1762AEE507098114AC401EB29702DAD +:103A4000BABE91F70461F31306C68A076177A48EA4 +:103A50008FF9E6C7771E99A5F4BC35340CA7CC22A4 +:103A60001094DFF68AF643AFFF06765F5BD291785B +:103A70008CDD2EE8C8A381743F0C058456158F1089 +:103A8000CDF09034E998FB5EBEC95F75F42B74C726 +:103A900068FC1A90D1DFFFCAB8A4A3B6DF419C69C5 +:103AA000074E65FE49A30772EB01F839A12EE087A6 +:103AB00037B65A1409439607752251C874041DC6B7 +:103AC000F4F2C8311BA4CA18E0F19FC489892056BA +:103AD0009DA77CB0521DF41CD118A02BB46E6B8E28 +:103AE0004DC763D71A16500A4F55D853A53D7A5281 +:103AF000C13C316D6F7B76BCE05739FE3BE3751BF3 +:103B0000AA853903A472EA7E578D9193A7715FE06D +:103B100053FFBFF7B14F9764EBEDE8848D2F022B75 +:103B20005BE935BF47A98D83D2B9F404869BDB6777 +:103B3000B4363A3FFD01DDB793208F168EB3C435FE +:103B4000A2F7D8D01FDA25BC9B0E224786E8AAD65A +:103B5000E605808FDEA58519621976B98309878EFF +:103B6000E2C8E69CE1FD246EB57DA84001C4531572 +:103B70007A25DDDCAFFBAF448631B2C61CB28D576F +:103B8000DDB87C34A1873483020416AB12036A9833 +:103B90006A8F3CB6624564F657711D439E654E724E +:103BA000D5197DD7FF4A460B18E42948A8E2D23D33 +:103BB000C17D93CFD6374D3DB8CF49083362DA98EF +:103BC00012BC326A0146AB3D4C3CAFCD1EC3E20D88 +:103BD000426D11BB92961AA12A2CD136F2864DB6AF +:103BE000FAAFF4B59C3F9420F6C12FCD76B0D2EA5F +:103BF00010051CC2896B943F243EDF8046B170DB08 +:103C000056605943130F915A42C0E1899AF2709558 +:103C10000299747D45676440C39872091BC0F976A8 +:103C200078B5C8BBFC0DC5ACE0F6E97E8FD341A0EA +:103C30009D72E9A02F2C95C2604376481884D1CF9D +:103C4000566F3D36F8A316424E48605FBA43B0BC8B +:103C500095B8A3200B54EF514BB7DEDBEEA498E1EF +:103C6000504FC5BB2F939825E213674C53282F1E46 +:103C700055AF204DD9317D733BD6392A3BFA3A50A6 +:103C800049D76F1DC275BCE638140FAFD060346AD7 +:103C9000A95B0BD57936FBEA155E24B524BA24233B +:103CA000E4A4E7954CC430419733C8EBC9DC576FA7 +:103CB000AB4E62758A28B2058979990AC413E671F8 +:103CC000FB65CAF27704A3BAC5FB03D090C8AB5F0B +:103CD000584E38AF3FF91632C3896AC408D3DDA6FF +:103CE00054444789BA052329F6FFBBE65CD1308DE1 +:103CF0002D4EF903C06C9CAEE6438CE28A0D038D19 +:103D0000A0F18AF7D048EF10FC19FCA14869CCE17A +:103D100077442D1F063CB6A3257FD6719C15E4C7BA +:103D2000EEC72B1500BE8D2F8B7C6D685B09671F5E +:103D300009BEB78FE43C0C754E75435924D910E980 +:103D4000ADAEF6298333996684E92E3806851E3296 +:103D50009278ED2CE9CD28B34B47405059BDC305AF +:103D6000E5120A34C55BCB195AD5BF4F311AD21DA3 +:103D7000F233BE2414F039DE7C818E11B99348C32E +:103D80006B1CA16FC22AF1612DFDA0F3D41C94ED30 +:103D9000E5AD92BF5EEE874361A2F2A2795E604F0D +:103DA000FC17555A90A39A2F110B3180022A8108D3 +:103DB000E256CEC0381F981E704D1615DCC80D4750 +:103DC00026E928FC806F4DBE8C27CB4E4FB3BF9A9F +:103DD0006426F34BE583874263323F2A90750A2EAF +:103DE000DABB6D0766C0C83B12A87E7651F9E15F69 +:103DF00009F3569A2B54FEC7B6F86B045A8E212647 +:103E00008E079587164946359E56009F3AD69BD019 +:103E1000576D510DCFE8D6C54DAB12A1F8AEF1F0FC +:103E20001FAE6E8DB33039EF998F89B12F7A428FE3 +:103E30007736CA2B6554AE1A43C7942D405669CBCA +:103E4000E43CCBEAF244098DA0EA6A66BE3971C34C +:103E50008DF6BCE56BAED66A48B1431BB63212EEA6 +:103E6000D03DD0AA7EBCC7E2A2C2014C283FF838A0 +:103E7000CE233B8BD0DF6BE9C5DEFA5CA784B78825 +:103E800095719C8889B96BF38291B787E1049EE6AE +:103E9000EE861020766AB26A1E78AA7C9470AC789E +:103EA000EF2F52CC92904FEAF4E89DA28D4F02FE84 +:103EB00091A620DE235B275A5457F91DBFF5E199DF +:103EC000D3E8DAC76C7612411C84D70E6196D55AB6 +:103ED00050E7F6A228ABFDD214C8587EF78ED596CF +:103EE000CB768395FE77FD34C1BA5285AD82F67CE0 +:103EF0000D1C6B21BE8C82F4237F9BA228EA525AB0 +:103F000098F477D5AF906F3A34E286E0CBE82F7D16 +:103F1000F5E497881F1781D6E38E69AE9CFA0A5B99 +:103F200002711BDB29D263C9E37CDDBC4E9F108E7E +:103F3000FE539983F5A86DA319D0A4010D58E45F31 +:103F4000BCFFD6ECE896D53A88EA7C322D0A44A824 +:103F50003881C0E3889CF292EC584BADDE768D95AB +:103F6000C09238A4EB8C3B78D199F7E2D3A48B8A2A +:103F70009019DB38FF637BB36A38108411C5EAA758 +:103F8000B2496ACB9D4B1DF8F0C8FDD888FD2FDFE4 +:103F9000E77D4B66A0354033E06A1074C0271240BD +:103FA0005867604E85B205DD2F809DAACF7935AF69 +:103FB000C59A5542B50C0F4273D8F90BD74CCEE3D6 +:103FC000440616A283DA3710AE83D0F2674F5BBF88 +:103FD0003EDE99C6F9185CDD5D95F4BFDAB35D5637 +:103FE0005DC79EF8B3D9377CDFB84E938D2C5ECD7C +:103FF0001F1B5E9BE60F4D4ED417E916BD3AC3DF7B +:10400000AA6B8F3B0E43AEB33DC1BC0877CC5603C1 +:10401000CABC7E20589CFD17D4D77A17AE6C8D721F +:10402000CACBAF6EB8E85EB9F17D8992EB0A5C51FC +:10403000B3C9CA61BCB96B7FD475581BA9134BC2F5 +:10404000209D05634B951FBF72B24C24E56BDDD3F9 +:1040500091D5BAEE6592C1B150FF1FA98BEA9EE1DE +:10406000AFECD169C77B250E4D95E69AAD0F55D3C0 +:10407000E974667AB4B89104C6678EDF99DA0DAB3D +:104080001A191C413C23E93366BC675A66A1CDC9A5 +:104090009C3AF928FFBE02DF1CFFDE1181E4852D6A +:1040A0008DD421AA6BEB775D7CC82CDB5F24D96FA4 +:1040B000EDB10A274CD96BDBE2D1CEEDE66FDD40E6 +:1040C0001D03F3B26A0FDDE89A498B2E7C17EC9240 +:1040D0002D8F042358928A9D1C996A12A899D3E9BE +:1040E00024DF82C7BE833AEE1C636C12B876CE28FA +:1040F000C03D7B0DD373302FC405E49CE4B249CF9F +:104100005979B137E03490BD60C47BA3FED32DB4A0 +:1041100001CF0BFD49BDDD4126B6A16BE14FDE07A6 +:10412000DF6788BCF1998331B26F34B1EF6F6124DE +:10413000BDBBB986FD36D06ABC2BE1A90160A18662 +:104140003CB22C18BE565B0E7EAD1D0ACD12C74484 +:1041500034BF0E2D85F75512FDA198B625F47F6763 +:10416000E3859864C1E128473F4CD2700BBB433BC9 +:104170009A50FA2AD195978F1A513E71FAD706DCD8 +:104180000DE5A2FB2792096AA777B34451F02CAF43 +:104190005A8137145958ED4E61CF132D2ACB810027 +:1041A000CD3E0A23C479621F740507D943AD358C0F +:1041B0007F8BF5314D3BBDD7977B655B5D1F305FD6 +:1041C0005D5E98F6E244860289E9C4E178E0CFE3D7 +:1041D00040ECE67FD357E99C675698D56CE5639E23 +:1041E000B1D69B40B299E58570B56A4458C19C64CC +:1041F000B3FE08AE26BA2E091E6249E13CF954BD51 +:104200000169AB7E00B9DDBE572311A5E533C23D80 +:10421000B375DE8B8426A0080E20887924B05FF168 +:10422000FD1580E19B7083902B446C26A5788CBA99 +:10423000BC0106D4F0FAA63FCB5AB1C09A4E7CB36B +:10424000B2D6A2111E01D37C0AD5FF16339E24A13B +:1042500090A8B4E22A8459C744F2075677522E0335 +:10426000D704C52498AF2EC36CB62676C4BD02B061 +:10427000BA7A6D70328A69D3630DC9AFB33D2B6DC5 +:10428000D83619389FD426E5077B394E904A2EEF51 +:10429000AC08636F3F0BA545EF53802E011679F8EC +:1042A0000C98BDE2C1DCE351D1EA2EFBE61F27F9F1 +:1042B0002FBC4BB30826864CF882B8D5C19933D5AC +:1042C000A5DDA7EE9DAD91F11F959B6E9F7B978815 +:1042D000ABCABF4852F8F0D9251CA16ECED5E63244 +:1042E000CF2C4660E0143A6326157DF7C1381AEFEB +:1042F0009C854F14EB261A7D8DE6FCADEC3EA89C08 +:10430000B3054411C6B19D4DAB02045E110C6C2E79 +:104310007FE5AFC676F75CDC711FA2837C3E294C3B +:104320006A98E7741963D0B3E37E351ECC2846BC87 +:10433000D488E0F7AFE09E5709B07847C8C71C6340 +:10434000D3144925BDDAB877E705B7ABCBD99E9D25 +:10435000AF32D66E79EB70E6249CA47743C54A95BC +:10436000874F27F03BDD28AD7583B013E250372A25 +:10437000959D8E3115E7A460293D38BBE96846CF8D +:10438000D89314FB94AA24523EE89514E2F877439C +:10439000CC33A4004B292C420174037F92EB193CCF +:1043A000AA58A39F6E3F6247B4CDBF710029BB617D +:1043B0005367F31C289A4A4BAE4465F1E7796EE8DF +:1043C000B90E360989F5C9356BC81B78F1DB3CF5A8 +:1043D00021B6096E2DCE46C59DE45DFF92833B3725 +:1043E000810C8A1DDBCB1FC84550953F17C6EB12C9 +:1043F000880BBAD44299E5BD7F8721CCF017788B22 +:10440000DB1EDF5795062BF166B0DEB54DDF2C5A6B +:10441000520FEFDEAA2D492DF22CEEB3153AD77EBE +:10442000BF3FDAF9862B4D5AD00D95CB8CB6969BB3 +:10443000E930F59851F2FECE830BFAEF95D2592769 +:10444000F8594BDCEC0777DD593C55C7C1D6292D0F +:104450002041685A9283EB37F73740910B79B9299D +:10446000308933784EF94D95ECA7AA1F98B219F709 +:1044700090846B2F16ABC7680AC12047F6CA2E1965 +:104480008C3E3B41E3B2EDB715C46B2DD904AF6C44 +:104490001346DB8A87F4695B76F2696FCE9C3F92A4 +:1044A000608D475731F05F2A4DD70ABEA557434D5F +:1044B000451636964AD959EC0B2894121EDDDCFFBE +:1044C000C966F09C67D3A89CEAA8B82E45135D1175 +:1044D000D46BC64599668E4D51F98A1698B68A27CF +:1044E0008C71004F3CC0FA43731B12204938DA3FED +:1044F00012F16617549468CC2E44A759C8286B2C27 +:104500007A8F34188B34D24C029FAC8C2D0FF54629 +:104510009170F82820B9C2EE984C8EBE5CF2849B54 +:10452000203AE6EF8B24B12CC0BF7F7A6968B220B5 +:10453000469A5EB4D0014E10C9B8E01588BA76FC30 +:10454000ECEA006005AB72F66E3EAB210EA6126679 +:10455000B4A9C279B5625FD3293446362AE6ED762E +:1045600017563EDD8B308EC414B0FC9B20855987D6 +:1045700076928AA683346F0CA9DFDC4442FAEE54AB +:10458000521ED72826446665B30CC722FE7F109EB4 +:10459000F2CBDB4750A85F1AE148D0441655AB4F29 +:1045A000C2C8BEFFE3900C91B10D66C1A89E47A2A0 +:1045B000DF6076D69FD643A288C171B57AB4F0A6E3 +:1045C00096C6D138D8C5677EB9EE2CEA7F9D39A34F +:1045D000E14E31C4FF5D8F58FD5D4C10D4FC227458 +:1045E000693325AC9C8A1792A8E8C51CCB2133946B +:1045F000B26193AFF6ED3505FF93DBA768A3EE6AD2 +:10460000BF603E684EB871F11C05310066B9C2B09A +:1046100005BBCE1D04D2C627198F3D097872747F61 +:104620002EA2EDEC77CB16D3E86DA22D7971092976 +:104630005C0E6D78F00EBFED7161CF072A0CAFCA2A +:10464000901300295FB43FFCDD3BB302FB630B24F6 +:104650006DD161DB1D93D3D5E7C14961F8101438E2 +:1046600085E50928743FE6610C03D270DCD1321075 +:10467000522073C4460EFBE9FED26A6050354951A0 +:1046800042271ABC1035AFF10F41E414F0D5C15CDC +:104690004E5363FB75D2CA6DC75B00057E0533863A +:1046A000D009E41EB28B36EE87CC1D4C7F457014CA +:1046B000DC52F9E562E80A61939635B035AD5DC626 +:1046C0003AB4F91191D6D9B51A413D89D1F9367567 +:1046D000373411275B816FB2635F6034929B48D798 +:1046E0003A43ABCA60A37D1F8941D8015FE73145DA +:1046F0007929220AF90BD34D2A765292DEE9F7B8CE +:10470000A6CA6FAC69574EB32B9EA203D654C0CC39 +:10471000BF0AF480B7E751E70037D8ACFA5ED2831E +:104720002A559D1FDEF48AF1E2BAE5A5F8FBD20C0A +:104730005C83C39D351C8710D7A9ABADB9E23A0D98 +:10474000E633B0D5238DB0B5FAD4919CBF4E605AF4 +:1047500063BE4949348756571F83F7E18DF24A47B4 +:104760001F5B20CF00E427C3DA32B1C94048175499 +:10477000358509E75CC8F2AE2EAC8AF38002332B94 +:104780004FAB9240E7B19263C3E4D9FC26C0758A6F +:104790001884B8C928FA7E5ADC82F7CD579B32407C +:1047A000B83014A3DE79E03FC8F47C8C6917785EDA +:1047B000D4EB166CD9522307A559DA47AFB7FDA140 +:1047C000E0D7139CC4BF4EA5487FA54110BD07FB91 +:1047D000A56D3CC7D87379A2001D236E1FA3F2C933 +:1047E00033B844C0C1FE1F25DC82CF14F62290945A +:1047F0007438013A14BD0DC9793257D9164DD21407 +:10480000D98F6ADE4DDAF364F8532B3DB1AF60E522 +:10481000D31BED219D825FBEA0622E70D051F03778 +:104820002D89E3E850AE2FEAE25D08153D913BAAE1 +:10483000541A18AB150DC3E6FAC6C2655A3385DDA6 +:104840009597ED10BEEF66603B2EABE744F4253C38 +:104850005CBB6826BCC3105DDD5AF7DF9FD0883D86 +:10486000D86284327A6C90E24484DAA2E1724EE635 +:104870004E2D5CE1E7DF179A3126A7AA6161391452 +:104880007E21E57D8420074EAA8112AA42A5F12F40 +:10489000621C5315C6DDBFA6905DCCBBA184F6B6E5 +:1048A00000FD63627C20685B0E45975A61CB6FDF29 +:1048B000451814CCD4CC12BE508DAF11E80DA148D0 +:1048C00026D3BE050D4EB9059E8BE6E9DBD89F5C6D +:1048D000910194A0E10BD73F5C8E34A113EB95229C +:1048E0002FBB9E34449B70DE3ABCCE64DC4618FE7F +:1048F0002BE5337AC250D2BE25F37035C4CE505961 +:104900006204C3636085E9A88050F5AE644C829E62 +:10491000C2137150C3A8FD6F89FEBCFB4C06147F07 +:1049200058A706EAFA15A1933DB6016CD889040090 +:10493000B188C65A7536A27A28F202677F40B4E978 +:104940005A3F57172EC01A172BAAC06143F81EAB47 +:104950009C1FF7836657972FC3FF4E52837D673A9C +:10496000346536A941749A149D3540445161799457 +:104970007C348D96C1D9C1EE60A9E6077521E06E41 +:10498000703EA9F3583BBDE1D13CD0F77EEEC3A603 +:10499000625E6BDF83A56B6ED6F444007CF44091BD +:1049A000573254324B43E77639080F28ADEA468038 +:1049B0004CBBDDAFCD8BAE51900A1B67C46817F6B8 +:1049C0000EA3A231D653C08E89AF498045FFCFB622 +:1049D00081B877AB900C936ED10C588C5241A69C49 +:1049E00048F2545253A4F9CDFD7EAAC63143CB916F +:1049F00029FEE1FF49D64D7311F68C90AE68167B07 +:104A0000D1C6A550FA69C5E12CE826185F3BEAB982 +:104A10004EE037282E8F7F1DBDD08E6EEF5F14A61F +:104A2000762711EB7A43568700DAB5BE3321D8DCFE +:104A30009D9D5CF3D659321DC6E82725D0A0F0A76E +:104A40002EA37EF850C739C997B0192473E63DF9F3 +:104A5000F0FA52E7C5B3F186EC6A006D8A9AEBBCB6 +:104A60004D6E80021D0BC03BB54EF3DD3BDBF8BC49 +:104A7000C2592EE93022AFC7050B6FE41E9A3B489E +:104A800071DD7B453B132AC68CC67F4C766B49890A +:104A9000EDA2F2C3BD46D737976A38B2B287C6B027 +:104AA0000DD78C4F22E98A2DAA64485E7640EC9699 +:104AB00027B884E8702A9E15226483A01366B4E8A0 +:104AC000BAD0F6AEB917746CE5314827617127BAD0 +:104AD000AD8AE4D4089DB8284580E82915F6674CCE +:104AE000AAF5CDE3CA3C652D6CD95ADFA81BF82086 +:104AF000B28668362AF6666A3669FF57B25B4DD4CD +:104B00000A5EAEAEECC2BC0A32DE37582488BE293B +:104B100022EC69266577EAF299EE1A527F8E67BD1C +:104B2000104EAE007855D5DE77D909D960B5BA6D8B +:104B3000AF7BECAC8C7C450FFFD30D4A847DD80154 +:104B40008226E2DD94FF2EED0787CA2057239D04BD +:104B5000E4E8F1ADFEFC2E5CCF0A230F926ED90083 +:104B6000ABB3ECE5699B96292476E27F3F1B9EBFA1 +:104B7000EF57FB5029E0535BBAF1BBF3BFD0B75EF0 +:104B8000B94A9260D1E0F6D0CBDD33528316F0C340 +:104B9000DBB3F780EC0C0624281EE8C9B8EB2E40E6 +:104BA000A19D62798BDD46395D15B4AE7287CE74F6 +:104BB000D3728F05CBC51EFD153D8FC7E6DDA6D987 +:104BC00088A25BF820431E60E235B5AED21B4A785E +:104BD000593E126E8CD40BF521652904C8FA6AB1CE +:104BE0008F1F259CC0D24CD8FB23A02F37E855E35C +:104BF000E92AF2BF5E1991678B2B6C17B61708A8CC +:104C0000221DC53BF2A1A99277B78D216D2F783A6D +:104C10005E9FB8BBBF8A87EBB7FEEF41B907EED303 +:104C2000A26B4EECB2F233023F88C7FD0C681977D5 +:104C3000B4E7886F9D09C78D2AE3BFCD8DE7BB65BB +:104C4000D45BCAF3B69D5D25B2202B6CD586FC21C2 +:104C500004779B56C63B8964CCEBFFBF942EF86764 +:104C6000CF20B6B5A47761B85CBF869D7A1BC58D91 +:104C700051AB18E4C81BEA30175AE0CAD2573E3C81 +:104C80004752871A02E2C6E4EB46049CEEC3EB2CC3 +:104C90003B66322CC64DF3BC89DAB9972602B5EFD4 +:104CA000B3E9FA268B2BD67153F45BAD8ADAF16542 +:104CB0002BE2053D4C7DB193B6D5BC548072183BB8 +:104CC0006EEBCC038BBCFBBA93A48373094A68A335 +:104CD00006DB4EF48892E28DF181955BFF3E1B8DE1 +:104CE0003EFFF641FB1BFABCC5C61AA134FB833557 +:104CF000E932E77B35B5F0E97A13911283AB3916C7 +:104D00000470F3E0AE58605F2F31467E0D2D3A5CA3 +:104D10004831F2A37B80041DD7687F6BAB87597C39 +:104D20000E521B685F6F8C65028DA79F61CB8DA6AD +:104D3000712577F1B920A149E2AF0B932E735D493C +:104D40002AA7D45D108D90FB71B61EE259E643CEC2 +:104D500054DA4005528EB24690C7F5A4E2294B942E +:104D6000664A477AF4382D68CB96D2ED40EA05C5FD +:104D700010296FF07E285436B2B915E76F2D60B652 +:104D8000691B3BD68124BD9519CE92B1FB4EC264FE +:104D9000C6DE9C5C22D0E99222132E86BC01CE4056 +:104DA000F746F539ED3177D457EA48AEA439CAA1B0 +:104DB0003D22A9C43F2C37F14F7C4E3BDAA8AD2DE4 +:104DC00008B66A53B0A76E659E4D3288F5365A9282 +:104DD00061763D4B40FB81C034C3ED80FA89B8B3A6 +:104DE0009919D0BA6C9926FEF7CB29479014B2E0F6 +:104DF0004036A2105C93AA8C157823882C1FFA5E8B +:104E0000A898419735807C93E7D12040C34B2AA3D3 +:104E100084A8A02EDA7EC383E0699F8540F78D6C5D +:104E2000B3CD6D0D2CBA1F4C7587AF4D50804176B8 +:104E30007E7BFA76DC7062E5B9C64368A752F8DE7D +:104E40001F9C1821620D85F0E68915F6163B6DEA68 +:104E500060FA448FD46EE065D7DD2B4C47CD4D8191 +:104E60001E9B5BBBBD24CF7039C3F688623E978121 +:104E700062CCB66F402074699E02878FB7C2A5FCD2 +:104E8000D781034F3E564A6DBD23368BC276EBE287 +:104E9000C30ED5E9910A26344FC1A8831470F6BC1D +:104EA000A7CADF0A30B24D9A8DA09206F77B2E4436 +:104EB0004246B8E9377708B56A45F6F3A0C9BAA4FF +:104EC00008A05B3FF7BDCC70B321F9D91E478B44D6 +:104ED0007547F82DDD59E71912738B75D2ECDD6F2C +:104EE000A807DD35AFC471935FE6F2769319559943 +:104EF00014CA9DDF74DECFC6AEEA8F22A178C90343 +:104F00002462ED79E452E4A71CFED619878344029B +:104F1000A264E6FA5CD2367F0D45E0F438BE39A7CC +:104F2000B8406894579F3BADCC9C4870D59C9A5034 +:104F300064A3A120CE8E30CB9E018571D9A35DD70D +:104F40005409F7D442DB4F53D9EAC3FF64D0882514 +:104F5000245F4F9B59E41CCD340582A082CB63892A +:104F60003F1253E0885991C9659FFF9BDD4C0F1399 +:104F700024FA5DC0EEE536EFD161F33BE4F5E5835D +:104F800037D985DF534A857730A7AF22CF4C62E30C +:104F90002494E4B4464F0A3D041C52D146E5F42E55 +:104FA000504E2869944219E7BF8F20A8DCC6D595DA +:104FB000BCB855C8D3B084B971074DBB99C2B6D23D +:104FC0004B6E3DFB951BF89CFAD261E7C6896CB429 +:104FD000C1E49FD1D62E92B36C4EF95E60724F49F8 +:104FE00065831A78123EFCF06797A396B1A8AFCFFD +:104FF000719D59D0AE019CE092DA9D3DECBA8A7B5E +:105000001AFFF0E050EC81860265BFF5D95A0E71A7 +:10501000EDC7C98AA45EDA95D53C9CD1433D4FF7D4 +:10502000323E2009E0210E85994D991B4D0CF96700 +:10503000592C80CFE78463B16BCA500F83EA4CE8E8 +:10504000726E3E834B04252496C997A462C9DE4242 +:105050001F09AE657199705BB1744CFCC42BE60DF1 +:105060009008D031BE63C3BA4985FB88CD1CDD52A0 +:10507000B682978C40D42B63E6F790356C8A65B77F +:1050800059B09CB54B62C99E4990477C081EECAF55 +:1050900099A7374129D223D14C39355C5F57BC429F +:1050A000768443F0C27DB5FD30A0CFE309D35E34F2 +:1050B0003081A32B11F2A0374E0B554B069D3E2895 +:1050C0007F66D82CBAF0D37CBC3980C5ECC456A41A +:1050D000584EF30DCE93F9847F6D58F441351FBEC1 +:1050E0001FF6D94D81B450C6F57C99A9DD5023B97E +:1050F000905DB9234B53B12220D984CBEA5C48BFE1 +:105100006C50B8BF7CADD7FB6521C11AA2707E84FC +:10511000CF6F7206C187BBE3FD85F7D0C16862110E +:10512000507823A522A13AFEE56B6961F6BCB8F17F +:10513000924B8810256E75165D8AA61C2B6B87D83E +:10514000392F79EFB874A5809ED9A1D75EF168D2C6 +:1051500025E389585B60DC1B38DA86924E3246D9EB +:105160005AA8AF778D37B997F73CFC0B7875C88490 +:105170009B05263BA354B822E660BDA791AF779F5D +:10518000851FCE6DF06FA3BACED885D975560ABDEE +:105190004641D0165EB221BFE3B454CC91A551D3A1 +:1051A0002615F7A94E77C7D3FF0CA15A1DD8B644D0 +:1051B00059C9099016DD53838EF0EB822C87339CFE +:1051C0009A068EDD08C9A48940DD367BD6598194C4 +:1051D0003F28C765E4D164697E0D796FC4C842D2A7 +:1051E00068BF4BB61DB925EA20B2A4A1EFD05A95ED +:1051F0003097D529FD74EDB27C8F8268CB7FBB4D93 +:105200002487955546B383E850A44581EC592780FF +:105210007B0C0CBF4F14657A8706285B312E987182 +:105220005154DC241BE1429335048080EA1DE6E101 +:105230002BA0B8D9B75945F0FE43D0C654CD229B18 +:105240006E87DBAA8CA6DB76CFE7FD7C5A06967BC1 +:105250000BE7F78128839CDA08A589940DA0499B68 +:1052600030B24022EF6A3AE6484667169108F0F0FD +:105270009CA35F9DF4DFEC1C63426543A9D03123FE +:10528000622BDA60720FE80C04E3E5D487252699D7 +:10529000EAC71D05307DFF567CFA811136933174C3 +:1052A000E0DB00E30D03BE01124BD83029AECC91F8 +:1052B000E5360DCD12EFF1FCE9A7642161D46FB39F +:1052C000D0F3743870C754B7D3EF28624755C5453B +:1052D0009F952D2C49AC6097CF4EE29EE70F0CAA0C +:1052E000017FF646BB5E4436AC37755CA8553D443D +:1052F000571E1F322014487E76932DBF565636D93E +:1053000051F3BF85D387202B72263710B725078A24 +:10531000E7F17DE2492417364571977C04580084F3 +:10532000A71E1837241AFFEED4C5F28B0DAFA7883D +:105330001C5E56DC941F95058A67EFFF0A26C3069C +:1053400060A95240410B8C398747E1F04FEE7B3129 +:10535000504C1FBB651A572ADD195FA0913CE446EB +:10536000BB61752D0D9FC1C98E1534C0B026754126 +:10537000F87C21C2346E9A6AF70448BD11DEFEC083 +:10538000587E91BC5120439BD9A40A91041F6CE51F +:1053900083EBEFF4C7E8620D0A46D33B25530CB705 +:1053A0003F96F9AA89A80181ABF5E2CEFEB675CB8E +:1053B000EF4BE94020C356C5C5935EAD713109730B +:1053C000E842510193C427BEA87183EE010CA78E59 +:1053D0001BD933504470ABD7895198E00AAA8E1577 +:1053E0000E763917F8EB6CBD80B07020AD49F44DE6 +:1053F0005FEDA74BFED506B2258A61FEDD747B8387 +:105400002DB3BB9531CB744EFCB93722146BB1F27E +:105410001F9B41B4A809A34E5D29C186A876DB8AEB +:1054200040710E9D0CA84F35C211A32F965AC81873 +:105430000E3ECFD4B82D0EE66FE0F57A8758B779D7 +:1054400051092F51F169E8994277B1E6AD4A1F51F0 +:10545000391427138B71543F00F91CC535BE05E77D +:1054600045E707E7244F5B0B55A12B29069EC66D28 +:105470003645896138A69ACB7CCACA51B566D542F1 +:105480008602E3C57BCC6C99EC592A2001938E628D +:105490008CECD9E5538BC9D55A4560B002228B32CA +:1054A000E57AE982D8C5E46A7C46AD0F420DA38453 +:1054B000A246E4A4DB00AB206F8B12A2CFE8989E3B +:1054C000396F1B6579E854349FA12800B2871D9578 +:1054D0001F05232A506FEA197D88DFDD2E0A205030 +:1054E0000826BEE5EA2B05CF7C7A7399842ED8A4D2 +:1054F000BE21320FC311E1C87B019BA2118550AFC1 +:1055000082B22C9B788BD0D6AD56E052AD31A65DE1 +:105510002C221AA26D57FD1A9821D6864039A03642 +:10552000B692838591847A4A08F4C3106842117058 +:1055300007810756DFA0C05CB21ACD0F2ED5CA0670 +:10554000A03E4C1245E74D14D03CA7D104950E6205 +:105550003E324EF279C4C59C4120A6FC69A900C820 +:105560009E16009583BF6E54206FE20D5C3C0013C5 +:105570006A2DAAC3406E4FE84A0E80CEC0CA4F556E +:10558000311B30B9C16320989A77D3F5E11CE759F4 +:10559000F7986BCA91550387726BD77944111E84B3 +:1055A000050495862CCD88E7B353A9F59C55850352 +:1055B0009ACA61F54E3BB802CD1DBFC6F6D618603B +:1055C000AA1EE33AB5411C5FD42CCAC631F9D301F7 +:1055D000370AEF8CA9446F1F2771549CE3BAAC3D86 +:1055E000C9FF529D8E079C744C2BDDA34CEBDD1F35 +:1055F000F14D75BA991E308385CA46D972D98CE2AD +:10560000D72AC76E3E601181144D4DCB0FD0D1D833 +:1056100050E16D645BD79D4104D830264FB5B6A8E4 +:10562000F0FC91CF35D421E7B7CAA1FAEB621A9FFB +:10563000C9C4E8E5AE00E0D71BE1846F96524B7B0E +:10564000857B62FE5AD9E4D4B04EF3461E29C2824D +:10565000977689F32EA1BEA3252CAB218C46728BA5 +:10566000E4943FEB3F785B33B789DD987EB991CE08 +:105670001546A40C8C33E07B964395604CE039458D +:105680001F7650F9064162732D552F6A5F09433525 +:1056900021ED9E5C053633B48E2D8AC05E941AF9D6 +:1056A0007CE852C1B245C67AACA90EC6D414323DCC +:1056B00068AA7FCF7185848B062E3A9F9DF3A45DE7 +:1056C00081A5090E80571AE365E96D251B2C12345C +:1056D000BFE9D4D38E5DD0F5F6B00655A43DC11711 +:1056E0004B33C25546FBC088BAAAC2BD66056301EA +:1056F0009D7616C2B8459AA656F6AA70B874F1B04F +:10570000592CDAFDFB0EA4561BFB411E7F759AED4A +:1057100054F80780F860A5C60C41FB689792AA0F61 +:105720000728ED9425977133213E9698302025085F +:105730009BDB290EF73BA2CA6E172FC8C34E536DD1 +:10574000614C32610E6681F817FCF44EC3DB86B6FD +:105750001CA6EA4E107C2E04A0EE1F442AAB619CCE +:10576000E8B17C3ECB91EF5A30390AA281D7E7D01D +:10577000025584E8990AF4A57AE7021A51D117462E +:10578000A911F631A13ED85DEA95659DA0DB7E8228 +:1057900099B8531448FA5C28809D7B86EBCD7948F4 +:1057A000484F9E8414F7DB5F847087921C35BEC619 +:1057B00006C1052F7D2B053153057919290B1C8A4C +:1057C00040B2305F08BF5ABF9B11439D1E692B46F4 +:1057D000E09D6927BFCD112C187990E6A4F3C3434F +:1057E0003E6649E98D1B5A5629C89955A870B7706D +:1057F00091097115934A3E3CAF223B4BB0FA5C21B4 +:10580000F953082FC11B122EB0DCA96A8F58FAEF8A +:10581000B23513AB2B5308F0C2A0C51982253B1A31 +:10582000AA3364A1A31693D13971F3D24151C113A4 +:10583000797B878272511CB2BB28A8BBF117AECE10 +:105840007CB83D9B719BCF6D0714BBF8DF8077332D +:10585000B64C10BD525DB58862606182B7B7537EA9 +:105860007A693A5489FA73B091CB97A9CAE48FAA9E +:10587000069D32BB7AAD8C529ADD1ED24E80778F58 +:1058800080C4FD5A6C89013B338EC92045B62A2D50 +:105890007423B9FDD02E90BEB5055AD18F08D60518 +:1058A000CC5CBF3526F423E46D68D4CB851AF5268D +:1058B0003C31A96052284F53668BCCFB594CF252B5 +:1058C0009728473EBF5435A82F37AB996A1B974599 +:1058D000693A1D2581724ED44FD43857BC285232B4 +:1058E000F5A2629EB00C4A4E0CB9A9FD92333E91CE +:1058F00073FE0BF1D93B491875294BF838CB7C3234 +:105900009A5063E0D345727D0F0401C42681508113 +:10591000FA6A2F165AFFD0AF374882524062473F8B +:10592000CE3E00D4C472DFC72FCEEC03F8A17E595F +:1059300044F2F74EE0EB7983C1A64F9678670D2DC0 +:10594000E181FE3E998413CCBB0B16DF4676B6D3BD +:10595000CDEA2CA9CEB2C239179572E68A2B6F9286 +:10596000C9D55945060066678E9D0FDA7BE4622B28 +:10597000457E6B3F1B4D83A07CEFDCFF40A0BB1C32 +:10598000D5B2C22007BE2047DD1E56137BC632BCEF +:105990005DE63B4AF5D4BF0B1DE821F860A89223D1 +:1059A0003F523CE15BFEEC00927AFBB88127F72482 +:1059B000484B70D5F20F2782B6568AF3D3CDE60056 +:1059C000FD480055C970EB72F58972979222C44860 +:1059D000829790839B3064331991E7DEC8395AD897 +:1059E000D4E2746DD879069814ABE6E2EE0AE7DBF0 +:1059F000D3F211F9D4D59C9E7A828EDBE553E86010 +:105A000053734A4AEF69E8E6B885018625C3EB4639 +:105A1000AB50D1BCE611410793FFFF1A7F45931DA0 +:105A2000D83BD68F45B5872F90B023C783DCD95C90 +:105A30008EECD6C012080B9EBA6CDEB40AEB276F50 +:105A40007863D77F3C7ABCB736014BD03349F9C86D +:105A50009704CCF7B0B9FDC4ABB0EF62ABBA8FF42A +:105A6000560005A37FB473C9014B2CB9E8C1721667 +:105A700094CD24C74EB22626EEC01C2A0A98E49F75 +:105A8000AE7B72127374A5E5CB07DED1CB706FCA03 +:105A90002430FBD7CF12CA05302CF5EFD0D8DDCE9D +:105AA00059DFE018662273EA4312FDE6563F797427 +:105AB000B3EFEF92DE17D22DB486CC25BAE5862F50 +:105AC000D5F2A9B62FA772F6E0B38979E43BE17568 +:105AD00058638D1252B18EEBE50728F81FDD7E9DCD +:105AE000B193BED2675C163493E0DA34A622C22B9F +:105AF00044BAC3F35FBA7366B4616FDE5E1BA1B7CD +:105B00001E5574770AFF54E46850479DCD4E0951E5 +:105B1000CD13DBF48297B62B67A287A0BAEB8BA5D7 +:105B2000DBE51EE76B1E42E9FE0182F813D08648D2 +:105B3000266ACC8EEF2B8B47B5E650D7A29475E240 +:105B4000FD52FD8CC8C8121DC5CA00D1CE66D79AB9 +:105B50003E8CB9C06F92E000FB4AB693E3BEEE05FF +:105B60001779030F91BFCD19CE95534BBF711EF915 +:105B7000F350462209241F5D6CB48C774BEB6E34D6 +:105B80000732F277898BFCDAA21FCE28489B3D6151 +:105B9000E216910333A76F88F5A9633D5FF4A47102 +:105BA000EEBE65B9592121B068563EDF029846D64F +:105BB000773A2EA3FBCF3CF7EE053B6A18FECDE902 +:105BC000536B3586E9E882D7DEFC2749F44F42164D +:105BD0005CE403B98391A9EC843B56D701ECE06EF9 +:105BE000943CF3A4BF1AFB9045473D542E37028CDA +:105BF0005697631E8CA7ADA8E951B61196C055C83B +:105C000003D89F7B2E10E255F782898FC727AEB34A +:105C1000F0F334F0194648CCBDA505BA2B2BA0DC17 +:105C2000396CA0860AA90465B1E8B4192FEF8EA3D8 +:105C30007D147CA134DD5460A0AAE8B75ABA4EE9BD +:105C4000EB236D8C63A7EF3D6EEAB5C5D7ADD150A0 +:105C50007DD2AED1C4B20B4EBDAC5ECD1266D3EDDB +:105C6000C74B99FCC5A2D3933B7FFB2397235B8152 +:105C7000D23F9F4C27E5318F9F77C60119BC015B4E +:105C8000ADA982FAFF7EAB8B9925D399677C813CC5 +:105C9000DF323324CFCAB7F58BFBCA76D3CBD4DB44 +:105CA0002DEC03AF93D574610DC3C45D94EC96489D +:105CB0001E621A0D6A34DEBEFC0C48AC3C37DFF8BD +:105CC000F2A5D232CF2AC7B15BBFF60808FD753303 +:105CD0006F8003BEC650E5EA650EAB643A42F01F22 +:105CE0004165E1811147380BE460F9378D6D521B36 +:105CF0005BE7BCA0E9E6FF63B4443F7013585AA9C0 +:105D00006F30316A1294ED4629970D3C3859A73F00 +:105D10001F3B66EC5BBE43E62D5A7848B6D3DB1CCE +:105D2000BB6B961835A2B231E11390EB7F564C480D +:105D300073D8EF06EAC279BEFB5B00172C433F1A0B +:105D400055AB5C0F55F2AA523CB2506232CD8EEA8E +:105D50007F758090CC655729725E2225E6F794D82E +:105D60001AD8B5E053CE52CA182F8FB42AA674E3BE +:105D7000E397E8A0744F608CEDCD6D8549759AE48A +:105D80003A84F85094B130BCDF345709C6DCD19E58 +:105D900040DA3B3D171A53028C1EEC1AF369A45FDC +:105DA0005678AC8E003F09B916943CC8C68C71FF7A +:105DB000082E2893F227D731BED69EC2ED3E64A6A8 +:105DC000024F1D353E9169732CEBAA28ED9792384E +:105DD0001B005B13293F9C90027DF57D91F407CD5C +:105DE000CAC875F5061A87034EA119381B2E1D1C4B +:105DF0007249028312A6BADEF1E5B5BEF3FC4DECA2 +:105E00002457F99EDD96D9787B9FA78AF7AB43305C +:105E1000FD28E088FDAA9E6D7791D3084423F64DB6 +:105E20009ED3B79A9E589E037309F550B1BBF40AEE +:105E3000DC11638B33002C9F1C8E726B9E9B303267 +:105E40004FD08A2A8E6DA8ABEBA2A602FBF7C6A99B +:105E50004014B5902BE8AFA4E1785380066F7066CC +:105E6000516A773352EC0BCE2AB4D339770F6C08D2 +:105E7000C746E9B80787903A6A61956AC2D943BCB8 +:105E80007B530EC2858ED2E4B924830AEA0A3AB45F +:105E90000B7D7851D7727D76F423ACCF7829673AA1 +:105EA000E21CB02B9DD072CCE5EA8362C6B5B79FE9 +:105EB00098D041A7F3674D82CF0EFB3CB25A234BDB +:105EC0001374967CD966FA66C9395ED3C38AD796AD +:105ED0008168A8B76AABB3EF79E7EAC5C25BDDA01A +:105EE00037A51C3DB0E38D8377862C91A720A7DED4 +:105EF00011ADEF77A110C467CC297D9049E52CD274 +:105F0000F506DD4C0E797CC017106E07F026F70100 +:105F100095BE16615E230A1DDFEB53DFE648E149BB +:105F2000ED0E3CA7DB07428FEBB9DF1CC9C4017D36 +:105F3000AF34B11DC0CAF6A8B097B63BB9F69A44C3 +:105F400012A39F10BCE53136FF1C41287515E80DE2 +:105F5000BE64048F0604EBD3D56447D717AA5489CF +:105F6000235D363C3448DA482396438435D7CAE368 +:105F70007F23396A7D8AE65CA762098307904CC853 +:105F8000E2CC89395421D8C02DCB513CF41680E89D +:105F9000A62F69EAD4D3A2EC9C24F8C3A916B8377B +:105FA0008822DC9849AE89A5E3D0E86EF3BEC8909C +:105FB0006391F55F735BF084871FF743FAD037472F +:105FC000832D9452DBD1697B099707B62C14F30714 +:105FD000851540C03780C1BE77B9EA732A6D5281FA +:105FE000F0AFABF00C269A86F9B74C3CD8FAF685A0 +:105FF00001D373C87E0C7548DC9672BFC91CB05AB9 +:1060000000F6424908D9E3F9D2FA9384CC1DF85836 +:10601000F0184E3F181FFE92A38FF87F8E0D8F470A +:10602000B2462309FEF6DA8A26D62021690C21958C +:10603000A51E38827C9A66C4F5215DD3A99CDF8CAD +:10604000D78218920A88E4A391E234794371062B2F +:106050001B30D70997D05E2E14A62BE551107A0677 +:10606000B0C0208CDF1A185A8984A102A9C8E34362 +:1060700050679BE23356A319C6EE04225D8083BDB0 +:10608000D2F7D6056DFCD463BA40C1A4AF960346DF +:106090001BC9C5AEACAF2C20475636242969856C88 +:1060A000ACEE77CDD8603A6F1B8AAE6AB196379F57 +:1060B00035CD24D9BBF9B6E4DB3C7AFD2F3C9713F0 +:1060C000552B7D76CBF9261FB2F4E816159787FE7F +:1060D00096A89BA4676B17EBAFE5A0D85AE726CA32 +:1060E000B6834EAE7D27C46011FBB3D949AF944649 +:1060F0001779C63302C72A4E8D43FB396066375A7B +:10610000D8A3F22599652A68A3DFA73A4B536CB64A +:10611000CF9BBCDA2789C62A97F00831C5D512571C +:106120001F29C3FB1418DF60F0D164918C97894B51 +:1061300046DDA8CDD866F8F3D32157A084EBB29002 +:10614000EC9A3679FDDC3A55458639249D1AFF785C +:1061500002B6CCA5A2A232CD8CA3F2CE32CE3B7633 +:10616000EB6BF9CB69F2F6004FA344764A754177A1 +:10617000D1D4235780F0602D0A95F2B8B860FC7C2A +:106180003A9533FD12026DF529AD484B026C34820D +:106190006C6B52BF4E40847577DFF13389BEDCE70C +:1061A000517E622A25861E333D274F3D9ED149DA16 +:1061B000DD21B168F681B24858EA5FD5AC1C3BBD21 +:1061C0004E808EF0B05DBD8E1BC084EE8C2E1244CE +:1061D000B953F0BA70A70A945BCC0C52C11509BF31 +:1061E000630C1712152D13C18DB9A9E476D38280E3 +:1061F00058F80A939CD6A09300DE28103586801F9D +:10620000C201C66153AE9B3E6A612D19437DF18D7B +:106210004EE740A3CB770CAFA4B9F8866A0F2BD01A +:10622000E7CF96936E1ED97D3043754D170068BE3B +:1062300032F9D1E3944C6F316FC9CAEE97F421FA69 +:10624000D09CCD77F849DEB2147FB862C246152AD9 +:1062500015642CF2F3BAEA8FB6C1A457FA27A72423 +:1062600031FB2CD4DE288BF7DD56C50B14ACFB3488 +:106270007E2F945A4B82BD16C374E71424C5F85A76 +:1062800008E90367AFA7846843A1FD6C988E0E23CD +:10629000AC114E38D3A9ABDC66945FE372D1B8027F +:1062A0008C6775A69935A836D3EFA74C9583D96C22 +:1062B000A7C59EF23B851358535A10EBD5B6964AA4 +:1062C0006DEAA21195304BF80FE6A8BF7539DA7B5D +:1062D000E6A49FE74BF34AE554F0A53F608466A728 +:1062E0005B68A8C26DEE544791A63BCBDE9646DEB6 +:1062F0009A2296C07877B2449C16FECBBAA85E3339 +:10630000553EB7B0FC7FABA3E6AB1C09C07FD2F40F +:10631000ED266AD22912285A9250BAF98C4AA08DD9 +:106320000C2489807B2AE77C0D7C7D2B76CC007841 +:106330003DF7A3E71AF613C7BE48F5668C1CFEE0CE +:10634000B026B3613E4D7797AD9E712CBA7E0D6835 +:10635000FFAF5BAA541B231D2D64E714545DADAB46 +:10636000F9E9A7464DBE7BB495F7A6E9FCEB484C8E +:10637000B786DF9B18C7B52CDF43B786C8CEC60EDD +:10638000A09B77E04545A666358038C2D602661EDA +:10639000E2AFF8E9443CD2EDDB0C71C8158EBFEFDB +:1063A000D6E911850091EBB15983C98376D6DF5DBB +:1063B000EDF1BEF73CC86A0AEAFB896098D4C79E33 +:1063C000B95D863979DDFB5E65B0BB3B2B31BE8E96 +:1063D000F77A7087ECF8A468C94B3F48ECB4C7B4AF +:1063E0004B76536900C5CA8683245581D361003634 +:1063F000589FED3D251CC4559340DA83DF5FCA16D4 +:10640000F88CA0CCB01E2B9729D336EF7BC3ACCA37 +:106410004193E0CCCC73000B35724E4E0189B3FA38 +:106420002693728161F97CAF58C55F4EB957B2545B +:106430001520AD3A049A10ECDB254F000DE46650B0 +:106440009D45988E97054545517E46C020143C8653 +:1064500047A52E541FF4BB6225B76AB9C0F4DB21EF +:10646000DD2F4D36B2523700D8B5733E90D2B2838D +:106470003C95F794B5858C1D6F3BB91C60D89B6E1D +:10648000646EA36EF28B8B72120FBF1C1E536BB81F +:106490003A81B7FC6582AD5CFC9D2CE7F7D2344EA7 +:1064A000FC4D421FC9905079727520284F81913E52 +:1064B000B40E845735C8EB138ED7481C2B8DE4DB04 +:1064C00041AC45605FB4E52614A1912B05EBBAE61B +:1064D000CA0EB815CDFB245D870ECA1981652FE35E +:1064E000A85DF68A6E845E4C1039ADD2BEF430C71A +:1064F000A4F4DBBD3E9C5001D98E76348394B7FD65 +:10650000F18D199873A9B7E7C21EE81F5D24C11267 +:1065100013AB96F35BF70ECE5643E8CDDC9106F74E +:10652000EA1F5D3E99A5A848E606872AFBCF16B963 +:1065300060FE4B65D5946C6BE839C659930D9CEFA2 +:10654000ADAC536F5A0C6F3E12074A5C7BED71A9DC +:1065500032F56542EB1AA2EAF942C8F28A2B928E12 +:1065600063BB09E39647B32C0B3710FBFECB39F521 +:1065700084380EE1316C518038ECBF56D0EA1A9560 +:10658000808F23FC40C9614835E6183DFCB83CD0FB +:106590005A422B26056D9739490D78389C959DD523 +:1065A000F046DCB20D0B9E69CCC31D058FD7ED5CA8 +:1065B000F3F18519925E963168080589FE5F5FD711 +:1065C000CC46DF8F0343A349C0CEC76ECE6243E7FC +:1065D0009D90762FDE459F32613EADDD0461F06512 +:1065E00072A860EBC988FC8AA86472B6FD7FBCC73C +:1065F0000DCB002D8F59993E04B47C28252AAD5827 +:106600002FBDD4D52C91D66B8A0A310C7362C5008C +:1066100060BFE2D7168F621A10E2E9A7E1BE4D4DC6 +:106620001931126F667B8A763772A6C8057B128491 +:106630007F11955EDA724CB938D71A9DBBEA83C9CF +:10664000483261105940559C41187114128B0A4907 +:10665000774399141B96B21EBF2C01A807D5A359E6 +:1066600033E8BED53A1DBBE1382D67F198F9FA1031 +:106670001A2BE33BF21598BE4569D4888D76470FF7 +:1066800040263AB8A63BC152918DA288E1D587FB3E +:106690003DDE391F54742A0C7DE2D01E302532476E +:1066A00052398A4DF52F0DBB5C64211F2C8D47C3D9 +:1066B00032EE570A989C428DDBDFCEE0E9900E75F2 +:1066C000F9C7653E80C58A43EA9695592541EECBC8 +:1066D000AD51428A5824F7F4B4CEBA0F1C579F7EAE +:1066E00085FD83EDB2A53AB0EFC8F6FE52729EA9C1 +:1066F000985D8FC0851F2EFECF6DF066AAC0016227 +:10670000FA75332CFF75A8B25CF7DE089566325D2A +:106710006E3D6978C81604B0DB56D00D08FDEBA6B7 +:10672000F4A18C8079DBC7FDF382286D4F0FFECE7C +:106730005BBFB0CD02A8A04F626E1161A4EE12EA59 +:1067400009D844B36B03E31622D63D97FA3FCA57E4 +:1067500072B9EDD7A799285F5B6D8880903EF69956 +:1067600091AA9B07667B01675EF27459F33044ACD3 +:10677000B476CD1D601960E6FE19CD60A463742661 +:1067800035DF1A654A237D55F13EF1CF0861B5A684 +:10679000BBFBFA10F5C041128B9C2E77D8A50B3F9E +:1067A000BE004D9287972B0F446246483DD347F871 +:1067B000C78A57B19B2D06F30B869753E23E03D150 +:1067C0009C006A4D593B46BA9D939F08DE8D2E145E +:1067D000512AF06241C902770AB89A82AFD1C28EBB +:1067E0006EF5A13461D234A19C132860F43904C140 +:1067F000BC075BCE69B6D1D19079BB14B4C0FFE2BF +:106800008761D6FD8A07F7FB90BE6AD49D8B263739 +:106810005364BCEF771F6DFCF23D98FC94B3F821F4 +:10682000637E2B5A9CE75E20FEABB4314A98889D6C +:1068300009ED9B2015C0491A829179FADE2C1D437F +:106840008E5F8FED6BB46B8B9E60668C740ACEDFAF +:10685000F95528B95A38DD733B54B34BD0AA0B8A8B +:10686000F5EF3BF9DCAA6EFD64BA432731A28D49EE +:10687000639571A4082AA3B48798FB987ABECA507E +:10688000A9CF8483266609C645349EEACAC4D16569 +:10689000DB6F70602B205528F38933138932740E17 +:1068A00021D14D826BB32D47EB80E172373EC40A94 +:1068B00088A60DB91F308DF2702C25A822EF908884 +:1068C000F7196ACD7F8FC2D52BD4B8AF52ED52578E +:1068D000AF66C81BC46053E77B2A0EE1B819525952 +:1068E000539C28607AD4DFE05F6B1F432E434F68D0 +:1068F000AEFB2F0DC3AFA15D3FDFF6FF0CB09C6474 +:10690000C44DB72805AB0C5D552CF3CB2E4CB1D93B +:1069100070FB86A3230C1E578184530FF83F4D62F2 +:10692000D2971E3FEE0AAF7D79FDBD02DAD3ECE9C6 +:10693000FBC00BFEB3B06E0F917ECA4DDE89F9B37A +:1069400040A5C14B4CEF664458831834BE9D5BC7CD +:106950004FCA78CE4846BEBE101255A494BF1DC47F +:10696000DDBBF65E61744313BC8E3A58FCDCEF9DD0 +:10697000712067855F6FF024686A1557EA86C8A59D +:106980009A31D26C73C029D4312B9C043A0E84F412 +:106990005C2C1102C4BD899DC662D6B6470A214946 +:1069A0003A03275E704F37FBA39101551299EF57B9 +:1069B000FA3D9E1B9938B629C76C547A48BF94EDAE +:1069C000B889EBC0CD94F87DCB12E7EBD12DCEE4A6 +:1069D0009BA118CCDB58D7D19D297C7364555EB43C +:1069E0003739E4D5270E61087A0E47F61CD585792C +:1069F0003555EF3A2EA434ED37FF9B7CD0FE062BA5 +:106A00001CA0D311579CB90C12FBE8AFCC412E6CE3 +:106A1000DE2FF6C532C559AC0605EE2477D9F66BE4 +:106A2000FD782A93F6419685EB52E2F973173BAE57 +:106A30004A57357B5061A8019BB745F07CC7A2B28D +:106A40003DBDB611FD9B37CDADF803AFD1D514E7F1 +:106A500081AADAAE9200A4181FC7E7381EC00A66E2 +:106A600079AD82A7852875E64798F35D3161F747D0 +:106A7000D3982EE801A74FBE5BFE7FD67B9451636F +:106A8000424EC3294BA09CB2ADA9CDB2191590902E +:106A90000D857F9EF0043BE18C6896254C32D5E550 +:106AA0008B8766E269AACA12D29F9CAEAB09825C50 +:106AB0008A1FF6D1FA23943F3C08352BE8D36FE3C5 +:106AC00008A4BFF00466A67A48FC8E6E04C00B8250 +:106AD0007CB1AB6399B68E66DD80C3258014A90CAA +:106AE00069AABCC139BD578EEE317A62A75B549555 +:106AF000FD16F1CAC3600BC9010092801193DD8CB1 +:106B0000A22C9851819D077F2AB1438FF6215B20EB +:106B10000069A929CFAB643AFB08AB4EA4A87F66F5 +:106B200067E648FD0F7FE455F01FC36F0334E7D4D9 +:106B300085BE16B91F8B8CB56E94919F58A0D793C4 +:106B40006EEE6D7AE7A3853F7B7C20B95E7605AE5D +:106B5000DBCE1DB0F5E1959CFEA6AEDBDBA46DC9D6 +:106B6000DF08E195FA8D812752BAEF1B124BB6C6AA +:106B7000199B7A0B8C415EAEC5BC3CF9F3E0322028 +:106B800066DBBB6DCD3AFC4D167FB024A5CF22D776 +:106B9000D18BDA4245939FCBC628F57B698B97E072 +:106BA000AE95A206F8870B0B5160823A69DE53C19D +:106BB0008AF1F51E37608AFC9A03FDF70D3B91C7F9 +:106BC000D5263A72E199E7E385694156318BEFA802 +:106BD000226F61EDFEAC0F7066351C1057A940C6E0 +:106BE000B7C4314DEF5FC96B0E87D3D64FCAE9FDED +:106BF000829A510DE51A92E22282FDA8ADB6DEC05E +:106C0000E94E45FD028B999F92EA14BD69BD9164DE +:106C100022D737417D14DE8B49A70AA2E2E2F71A98 +:106C200083375F4C76970C5D7F9E9EE0C93B345264 +:106C30002088D5C9E16F649956033D0DA5C009B6FA +:106C4000377B2C0B971E04787C44B560BF6EC51D46 +:106C50003FDAB89BB32C0D36EEA8F2C5E20ECD5F3D +:106C6000BA77F8C50DE522FD14AD73F362E9C948A2 +:106C70008F2BBEB3F89251A109ECB7B454FE05C6F0 +:106C800036AFBB97A9091A2CE45AD805DD2ABB06F2 +:106C90003408DF5B34BEF2348F3D503394FDBDA623 +:106CA000EC399302BC2DD7BF5FDA6C89DEEA24C2CF +:106CB000AEAAD7099DAFF216ACEB322B2D3CFF6983 +:106CC000E4758F00DE787342CC5911D501F9555126 +:106CD000C66B708387D6FA0C9BA19A274BE5CAA690 +:106CE000C2ACF636FE8F0F2CBA1DA3BCE1DADE91E2 +:106CF00015FF20CCE58AAB9618E8677BFABA92516B +:106D000005F721DF485462F80E589C342B1540A437 +:106D1000D94EB0333F808509798901A502BBA5A270 +:106D20006141EC0C42C57FBB404532859D307FD729 +:106D30006CED9EF91A13FB9FE91044A54EA1B7F81C +:106D4000E3959F3764249D9A0E5C6C743BAEBA3C0D +:106D5000028C7BC9EE0F65A88C7A74BA1EF9ADE17E +:106D6000CF1245CE6F84DF51960BCB571D9D045338 +:106D70003E997BCA001E9488E3FE719701AD02958F +:106D8000512B52A32ABE7D4C2F4B5570C0EDA373DF +:106D900067AE764D763F53A067150C0B5A70A4F181 +:106DA0008C291D592F453088699C52099F6CDA4AFD +:106DB000717019D11AC2B43C38231B578EF56B7A07 +:106DC00011159A3AEFCA49621A2EACED19807F620A +:106DD00058E92368BE599502C3C83814852876EA55 +:106DE000084A33138EC74075D79E710615D39D860A +:106DF00035746AF5A29F0366B24F9B90367B117D76 +:106E00003B708431896F0182158663073623928730 +:106E10003491AB469905A4A4D08575020826386341 +:106E2000460BFC526428453D8C7467D82829FD0523 +:106E300041BA7A6CA066DB13120055DCC826ED0758 +:106E40002BDEC5C09B4390B4EA6EA32DD14876ECEF +:106E5000F8A7C7D75C587968F36BA74A25A06BCC15 +:106E60005FBD73D9B7CF8B5A5F87F5B02581D02A24 +:106E700054DF68BA67C9BE90BC53560120D1263290 +:106E80007D7273D1C6A407673830A126CB28149829 +:106E9000B6183E897DF19CFD189DAE0FA6D8A2853F +:106EA00051A5FCBEF488FDD6888FC77C44FB56D024 +:106EB00035BBE559E778AFE45BB32FF84AF3580FD9 +:106EC00074904A0C3C16BBAABBB0E0611EAAC92F45 +:106ED000B6043825AB326086F5140D76769FA995F9 +:106EE000EB610346BCB5DD6B7EC045D66FF50C98F3 +:106EF0007B8073D69ADC4277EDBEF79086C173A390 +:106F0000E6C077DFA927D7BC781CDF6B2C8AF9484D +:106F100058AD2FEB1790A7945367BA1615EDB2939F +:106F2000DAA6B4EB6AF0D847D21AA2EEB8AC304A6F +:106F30009DC39C4AF3E01A67F64D6314080F2F2F88 +:106F4000870300B29D560FD62A668B0C662B1F91C5 +:106F5000C63502715B29F640DDE8B4091E98B22DF2 +:106F6000567FE8BCD5900CB1A60361E6AF03BD1C0B +:106F7000013EBA218A6DA062E99BAF5BE4138B9856 +:106F800073C93C78B7B0C9CA084E14CEE2BA84B20D +:106F90007180F4C9376E361C1FE9653C179A0320CF +:106FA000E13A6A1F3E07948CA049F3AB90EA800B4C +:106FB0004D268BA976C49C05B859947B8EF547C3A2 +:106FC0007A2E8707114CFEB3C094788A5E761DC472 +:106FD000149156630B8BBE5D7F64544E3DFF1011C0 +:106FE0000D82BF688670D3E3EB9810FC5E90AC3ED8 +:106FF0007A53A4FFCA0048C8D8D71A2EA81102C4D1 +:10700000D3BEE7ECC7E9A55C9C4742A565FF2B58BA +:10701000DCDB7286691381C282B76D6D805B76EFAF +:10702000A6E63AE60D47E1BF4DBC344A8463283EEC +:10703000DED4DD1E17FD0F9DD30FEE977DCB33BF42 +:10704000C10266E120872C1DEF97D7B14E0B607D02 +:107050005B9937746E7321AF0BDD141C35E49766B2 +:107060008F4A53AEEE9223DA2AEAA95163A33C6118 +:10707000859B9B47E56173B28DE23B5DC6683097A7 +:10708000D73DBB98D4AEAD1C9DA86096E31A3F8B4C +:10709000BE45FE07377383DA2B9B492148E3B9BA13 +:1070A000CACDB545EB221741D7EB818503E38E3A74 +:1070B000B95D2E4C6ABD3F8DBE3C5C731B0A9E7E43 +:1070C0006F58FADAED4AD625D343ECE9322B3B7AF6 +:1070D000CDA5FFE8A4362522BD734607F03A98AE49 +:1070E0000E9B9EE143947BD52DB7B05590370D6232 +:1070F000668E0DF78032EC30FACC7B174BC03A64C9 +:1071000011FC746F97A14EF3F229B87458097924D1 +:10711000C5FFEA00A3872CDAF0EE076D13632E1685 +:10712000B16204007530299E6BD6A6921FE1AE189D +:1071300041EA5A88A6C7D874C486A336C9C901E9EA +:10714000D837439C8B18EA3247FEC1741A1CC028FA +:10715000F6CEFACE4489E66EC070314EC4242C3C83 +:107160001129770C7AD7F666F991956A651046F57C +:10717000439D76676DD438EBABD4262F57FF066658 +:107180001764015720247AC5407B4A6C94EB6BFF4F +:10719000C6546F507AFC84E19FDC61749B85C5689E +:1071A00025C494113055F0556409580054085963AA +:1071B000AA34198076699AEB397A514E9F9FDBEB9E +:1071C000144ECFAC765ACFE75C331126F18E816A2C +:1071D000FC25C99F546791744527BCECC6B540CCCB +:1071E00001CC71A9C186541DDD0E66C9930C036DD7 +:1071F00029F5DAB00F10CF21E9C68AF20992D295AB +:10720000B1D8083FFDF68444DBC99DB8771132E65A +:10721000C143832ED9F860EDED169A63058B49FDC5 +:10722000A8B894643DED9ED083D2E9E7BE42E66AF9 +:1072300070A207206083406630F4E06373A4902955 +:107240009900790AE51777C93212B2866A99600403 +:1072500049B2C6EA3C2085A388BAE634ADCD0B8896 +:10726000739405DA4818234C9BA09A2C33403BFDBD +:10727000D0AA06E923051413DA5236265E3DB4DBA4 +:107280008CE7FCE2CE1162AE9C140E26AD329A223F +:107290002147CC09AB78FF2229E383A5D53574E9D2 +:1072A0008CB7EF0EAC67CE8EC2E91BA9A52330C404 +:1072B00080D86D01165E4BAB5B6B8D4A2BA431E120 +:1072C00061075C2E1F2989C7BD32D08A9183AF1E0A +:1072D000C641CA41BBD58D5A6F04FE8932E5AA2F3B +:1072E000F2286637693EAA3098BC31898EDC6CA8DA +:1072F000F1EAB104EACF6270D452EE1CEA3C8FB5D9 +:10730000D4775BD9B31F0C27E37577D5D853263ACA +:107310009514ED8237C0B998D9251979B994FC8DA7 +:10732000688AB20931DCAB3E3C93F1FF17B7A5EB9D +:10733000EAF07942B3B768F11AB6BBF0E6BFD9C834 +:10734000AE9B563C72C9B932549D9C8894C2065972 +:10735000988BE2224C618FC19B67EAFFB92CCCE489 +:107360008D1C9C9AFA1FFCDBC5B7101E50D55DB969 +:1073700073DA996424B2C3744DB1B281ED84BC8DCB +:10738000E028A897FC4EF4802DBB899A9620A1B1E5 +:1073900009491ACE215F535B15C6608D3EED03E9A6 +:1073A000517DA79FE5465F6EEADB4D6C7A210113A4 +:1073B0001342DAFF94AEFC511C96281F996D508140 +:1073C000B34ACF13D0DE5EC7BE8095354D368AA94D +:1073D000BBD162CA5CE8890AADD0AD2D968390DE40 +:1073E000D5ECD499612109ED250A895C3ABF411792 +:1073F0000F9F7D6389541A7D7D1CE19B6E74EDBAED +:10740000808D15C7CD7995523D0CEB766EEC809C46 +:10741000F4FAE052364BFAA23A7DC98938CED11E31 +:10742000F1EA9420F28E12CF73225E6697E4A3589D +:10743000AEBD1B230B033AB75FBCB4F885EBE23457 +:1074400068F4B31E2D046163F116E11979AAB28BB9 +:107450001935EA24162D9496346405A479C00C5489 +:107460001A4B16831CF19478BF58F412F6EF992842 +:107470005950358EA936274E89EF708FCC11393887 +:10748000E8E95CC9AD8349BEE98717EC23F41A2CFF +:10749000142A7C4EC47EF1370E0F9E5FFDBAD9FCD4 +:1074A00039C78CD0B873BF48E6835E9DDF3FB3E138 +:1074B0006EC4827F5C9C8A36A62FA400ED8E276E58 +:1074C0006FADECA12F02DDC2B085B730AB82B9063B +:1074D0006ACB01705B74AFF3486CC16B0A0BA5718A +:1074E0000C9CECDFA36CE153FA03EB8957A42A66EA +:1074F0004BFAC3F4283DB279B73BAF908E86DE637A +:107500004951F80FE50CE8C7156D4632B89F2C1F9E +:107510001D4EA0A6F213088B89007823D6A66A48D0 +:10752000E2D79D14723C038E573D0F6C08B00FEAF2 +:107530005C788190AA4451F9FA550AAB560CCC7488 +:10754000349FE42B18B2F69826D73BA84A51AF4592 +:10755000830FB78EE5753D1531E87BE010F36A8F38 +:107560006E60AAA0C574D7AAB56863FDB30D961B5B +:10757000327F9BF030CAFE8F10C22B4307599351C4 +:10758000ECE9B0E6FFC2FDE55BFF058D3D8995673F +:10759000001B3B46C4A78859B6E0879B05DA122D2D +:1075A00078ED0F3A025C667CEE5E2E9133C5CD5DC0 +:1075B00070DAEEB5BB3123F7524A39B7FBA00DBAEA +:1075C0001B6520AD13182A2E9E9272CF19C6C4BC1B +:1075D0001FF1E7F9D0C957BD62E418B06E7A1229DD +:1075E000827A5A98DBA51A7DB0879A060D25BE19B6 +:1075F000CCBABA8BFD3844A166CF268E2D3190E8E7 +:1076000008E8663DFD22081BFC2DB34FD547139BB0 +:1076100069882B7124826030A74E6969065C7047C7 +:107620007ECED03CD15C1E89C7276F16B1DAF792A7 +:10763000F57E15BF9ED19B6121383C1F4585398D54 +:107640007FA982937E7E2D9A75DE1CCF38CC9E64F6 +:107650008B7BAB2127755397E3C9E1353F8377F9DE +:1076600048E66E1FCDD3E7169706095E6AD3E2A5FA +:10767000B03D51D7FED99326DBD51BEBB0F4B373E5 +:1076800022684CEB0CED8A671A71C6D0144E6AE47E +:1076900051E50CB9EAEB7E82BF67CAA1CC0E3BE88C +:1076A000ACAEF653ABADE538C6C35EA7B047654098 +:1076B000F3A0781FB47DFD32B7D526B967E37529ED +:1076C000FE178D90273BDD12DB861671B4C7E6F2FC +:1076D000EB60318E5DDA741DC873B5198BB45A5ED8 +:1076E000A4F506E45B17D1CE5A1AD2F6B631E4916E +:1076F0007C229EB344CD6CB843E531FD9BB5F73B8E +:107700000541C374682A40E068B8C68EA062A1EA49 +:10771000454873C00744787F476FC6C21BA36C06F9 +:107720001D410E8384233F60D15C0E369A1EB64500 +:10773000E62B2B4AE523AB7C7BCC1D4745B738B6FF +:107740004439F70DDFC303126B2731FB161B0FA162 +:10775000C5DEE1C986E563894C6132B10999D0CEB5 +:10776000939525F6C5DF83124D5D5C13B8BEC66BDD +:107770004CB3E2EB348D1EEAC80908980F2C0A6559 +:1077800041BA87E5F5EDFAE16A6CFC83E3F94C4F09 +:10779000DDF69743BB94EE7ADA2DA2FE69A0C3E72B +:1077A000478E848E69AD923F6E5CF3F00AA08278BA +:1077B0003BB36B2F3AAF8CC96F1D91494B60A19EB3 +:1077C000EB735EA262DD00E1B6E606181582F525D0 +:1077D000F9E5A99EB1F8A5FFEE8DE95B830ED3CE46 +:1077E0008F63E85B5B0C5C32F74BAB84A35B165D8D +:1077F0004F546C8C1F16333AFD8FA9642F5E45726F +:107800008D878CEC116D38FDC15D61CD4C721CF51E +:10781000D973A696F27F4567571E3F06A5B678A78F +:10782000763C2CDDED616DED670AAF72592C08874F +:107830004C6149159EED08F0A7DF859E747A777C30 +:107840002D8B0D9A5DEF5E1F1BB18B611CF1499A68 +:107850003A7263E5EBB0715D1B883172C4094C5616 +:10786000DC3127D3227DCC863AFF3C5245CE8DD5E4 +:10787000F3BA21C1C918773B7FC9245B02AAC2545D +:107880006BECF9BDDFD7AB2BDB6C4B7AAE7F2CBA40 +:107890004A4C0A3A7087EA5F860D040B7DE2382A6B +:1078A000F502AB0080A20D7509EE5136D536AE87D4 +:1078B000FE79360A1D6918BE0E21F9C302AF74AFF6 +:1078C00089ADF2ED6D7BACE3422A2A6B731AFBD8CB +:1078D000F8838FF1211A617BA917898E44D6806DB8 +:1078E00050902973032106DA0E2D2B72D96CA32F29 +:1078F0001D62E3D5F7DB6C89DE371B43623DC9AB04 +:1079000030E1A74B4D1935854CA7F915D87913A54A +:1079100046A0D9733AECFFF875388BDB1CBF2959A8 +:10792000BC3F7973903AFE4D8953663187A949DE91 +:107930003495C5CAF06B790C3EBEE76924633814F0 +:10794000C34AE388AF0CFFFBB49A6CBF965B51A6A9 +:10795000A5556449C2D403AC0AEDD823C72A05193A +:10796000F15796F63D853C86B2AC921349BA220F88 +:10797000B6AF4467637566D5E7F79F1E6993FE8AC5 +:107980004AEF7642D77A7D1CC8D56BDEDCE8C2B5FB +:1079900055008F6427BE17D5D9567E5DA7D1FF6AE3 +:1079A000B54B8343EFAF4DE3BF514C03526DFCB277 +:1079B0003DF034DB2F91A960166A94E51237E0AEF2 +:1079C000D9C5CE18769567E1A5D52C371A61A58C57 +:1079D000F379B9891B686093D39A4B7F603B329EE1 +:1079E000B97EDCED2386A9B1E8583D8C27ACBB30CD +:1079F0003FA29F7AEB695E59C134F48797B41FD1D7 +:107A00005DD871B0B58CA0284576D9976D75ECAF6F +:107A10001155CA166497FB6B69BEAD05E54EDA6475 +:107A200098180ED3BB0ECD61FEAE41EBAC5E0E0DD1 +:107A3000DD97B0BB5D1AB279B18EEF9C8B3F1E1201 +:107A40004EFB1AC4DB8A9F57A4B107AFB173C93B81 +:107A50000C6AA357A8EF7377E2FEE7D1F8FEBC915A +:107A600052554ED6EF9F1B6EAA1713611CF0716022 +:107A7000C07D1DDD14EFE76B7412021D97B826560A +:107A8000B741FAEC9B1D2EC2908927EFCFE2C113BC +:107A9000024FE4E7A89209C24E2DED219BF2FE03AE +:107AA000F4E49675688E319C4800B809CE0695843A +:107AB000BAF7F0BE9BC109C90CEDCE99D09AFFCCA4 +:107AC000A69D1064BC709C029E7009B4139EE701D1 +:107AD0009D164CDE2F3790FDDFEF2BD9F0859BEE06 +:107AE000B0E44D81E1F7836F08708CA38B66FB6770 +:107AF00095E13C6CF613C2C1549B35D28DF802A3BC +:107B0000DE04CDA327F558B7FFCF9C46F80A4C18E2 +:107B10005DBFC78AE1FE77C231BAB30CBBD4DAFECF +:107B20008C5B8889DC8AAB7B909C4A220E4687203E +:107B3000FB001F5EB828089D070B4363AEE2F24AC4 +:107B4000D0560AAE54B3861E58C225CE9AF2CE2C19 +:107B50005C7F8B540BE72811F770F7C318F554FAC4 +:107B6000941043742FA905D3BD82E19A00E5E4681F +:107B7000CD0482118EE11AFA166C255A5FB8E05EC8 +:107B80006CA17CC09F3AF9722D335C841C38E17D76 +:107B9000F667BC00EAE6536A74DFB6256E2032A7AA +:107BA000AD395F5EC7BA291C7AC50E1B9079CF38F4 +:107BB000A4305C9260B8D343CABFB5F8A9F96EA5EA +:107BC000CB7076163B72B7502FD589554BDEACA5DE +:107BD0000E5929AF53CF0EE66A4BFD58BFB5B069B9 +:107BE0009846F1B1FBF95BE31DDFB8A2E19C997106 +:107BF000582F48152A38C8EC542EABAB18FC49A8AE +:107C0000EB03074CD75595AED9A295A8ABFAC205A0 +:107C10005A32EB8DE38CE856F7F757F0A2356B57E5 +:107C20005EBD7C3211FC7A7891AC2B93AADF1E5694 +:107C3000C0A2B5B68393C4CD771251256C7AE455B2 +:107C4000114A5EAEE10D0C32B4AEFC99550F0082C4 +:107C5000F9B861A5B94D3ABF859FE946023F109F2B +:107C600006E16D3EC90CE2EBD497189AF325E3398F +:107C7000B43E752B9994C042AAE1ED907DD7D1C056 +:107C8000FB32F6192E2F583CD7511D1C9A0049156E +:107C9000AD2664B5BB591075D39AC80A06BC5851B5 +:107CA0003DFADF64185D7EBDA7891404D612BBA619 +:107CB000A464C7E7665B7C5FFC4343A0A8EF420A6D +:107CC0002BEB23147E7B2A5B8671611D8C7C693FC4 +:107CD000FAD0B52767B567A1D7B59E8FC5AEDB676C +:107CE00097B52D4868B207CEDB24BFD70D34F1A578 +:107CF0000E551D6B2C89C9543E968ACDC1C7F5D34C +:107D000065CB11D013D0431A23B5D18DE457A28D82 +:107D1000CEBD74E4A37BCE9F88BA286F33D8B37CE2 +:107D20001C467584410C2EF902B110D9BCDC171B1E +:107D30003C2891655523A2736A0B205B5E9B24B699 +:107D40007FB20325191FDFC4F9D9B6F427158FE9CF +:107D5000432EE853CFD92B9C1E49C8E0BA20CFD080 +:107D6000DCC373387A667BBAD2C088BCD49C7BEE05 +:107D70002E1FCE8A7469CF92BF14C9CDAD67F03083 +:107D80004421973EE1522DFF08B907AD4310E18E23 +:107D9000636E2BA05F2DDCAC00EAA45D2D93104236 +:107DA000AF85BB804C386DE7DF3D21B295725076D0 +:107DB000FF80D34E1860AE4207ADCFDF1FB47F8C7B +:107DC000C9C9AA8ED64584408265D4FC57749BC02D +:107DD000BB556B2C92B70548312460551BB8C56064 +:107DE000B5C4F9E17E5D71EE8DDD1D00B6326BE448 +:107DF000E9395A5320409AA843A725084196751B94 +:107E000017293810345929C084DFB8789263441E8A +:107E10005984E6CFFB94358C8FD9EEBAB03F34ACA1 +:107E2000060639144C51B2E5C2D2E91728FA687B2C +:107E3000679FF1978B7B273B646B58DBE9A893E145 +:107E40006EDD38BCD69096F5C7C6075290A8D6CB43 +:107E5000BA554F33C67FE80FC8F25F9D8E345B3F43 +:107E6000C9302FD8FBDA36F006EE1F79CA3BBCBF0B +:107E7000114B80931559A275ACC73DEE22E5A84D74 +:107E80008DBC1A42540E2CAB34A2FE716EB02FC4BE +:107E9000931967559C113B599A8821613042675567 +:107EA000A99B8C17270C135768C6ED66360E839C6A +:107EB00026A20278C43E136869E6AE7045C789AE53 +:107EC0005DD51894337FFB17110BABDBBF73340701 +:107ED0001188B7BC10F73C072A0A178E105230667B +:107EE0000A54B6E8FDF261371454D38DB9A378D3A0 +:107EF00066E265609CFA97DCDF59FCB25CA662948E +:107F00005BADCDC030B5022C460FF369D8996EA891 +:107F10005E8C1F670A35881216F058D4EE9A1767E0 +:107F2000869338A6E25E65582EECF8F12D436F9EDD +:107F3000BE857C75CDD0EFAED3D175EC59B758491D +:107F4000584B21E079217FFC45CD0BB9F32E001E63 +:107F50008CBC106EB11990A476D05BE5C5BF886E5D +:107F600094A92CC4A82ED15E9854D722136FED2467 +:107F70000FC7A88A3B007664BB81589368A7F65761 +:107F8000D28CF0B7D6820CD315185D25EC19BB7BCB +:107F9000A03DA51B52F1D3B2C433270862DE330FD4 +:107FA000F13C657F6F51F079ECA3DF968581EF821C +:107FB0002661F50D745387A2E2110EF63F731F0C74 +:107FC000AB70A2A100E8E86D38C5FDE0B7981D2BA5 +:107FD000053BF7803F2A3EC335C22A183E82AB8359 +:107FE0004870F68582A4688777C849B6849DE537CE +:107FF0003E5F482386FDE04339E1DA38BE675C30F6 +:10800000CDBB48C09D110007FAB0E78F36C5B16BF4 +:1080100075B63389829EE63A1BB8094D8DF2220669 +:108020009BC9643152C934E3671D42159314A154AE +:10803000D50154126F22EFCAF8DBCD004136FB7D2B +:1080400033C8167CD70709A56274022B6E448301DE +:10805000D53F85EAD0070C302A86E5FA971B15E64E +:10806000DBBB17AD0955F935D991C5A1986DF2E182 +:108070009DF6C863493CF7806AEE6B6AFB03CF2626 +:1080800080D4B7A44D72F692B7EFDA186398B6327F +:10809000C20A9FC419BBBA1EAD45CA8AAB7A1D94E9 +:1080A00023BA9AE244A2B3CD688B296E6748DF8E6B +:1080B0002886FEF0D01485FE40E9C8BA9A4D1BC64A +:1080C0004F69C52DA9737870B208E1A439B9C3F816 +:1080D00095F2C8356DB93C831FF8EBA11A2E233EEB +:1080E000CDE7BC5ED3201313F789479C7B6A94C409 +:1080F0000BC2A52FD6D2A3D284D1C4C63E9DC27CCA +:10810000D56C9C0F2B015FA14361A454E10734B3EC +:108110001C1C8FCC1E923A8E5FCE14FCDB2C77DDBC +:10812000911AB21D0181D07DA47674645C62FF282F +:1081300000567D396D6E5489867D7066D1232E532D +:10814000E5CDF97AE66CFAB5A28359BAD15FB30EE0 +:10815000537858449E0E2B072F991EBA1A848443D5 +:10816000A0FD259F2582FB7E71153586FD60273D8C +:108170003BCF39DB08638D6C3B210B549071AD050F +:10818000809C1E1F02E2CCB05A7A92B3531F460560 +:108190002CE5B7F95332C669B9A820A28505A7AC6A +:1081A0005C07E482FAC6312C8E7DB96DB274F2C6DA +:1081B0008823E76AFC8D5176FD49950543C2EF9708 +:1081C000768FBB3C2463D37D2E07892C5AF7F72A80 +:1081D000C3319AB4CBDD881777877EA3679C0A9E4C +:1081E00010C560655342BCB03CFF24A911058CD476 +:1081F00067ED4F167D9A812AE129A668E26BB2FEEF +:10820000A51DAC7CA007F80924FFCC9EF114227BAD +:10821000391F700160611D87E1D3894A112362B55E +:108220004FE4915FC5EFA2F28A38B3B7AD209876DC +:108230004ABA64247572EA4A4987EDAC09BE70D423 +:1082400011A78F4C4C6924BE1A992F85386B7299EF +:108250008CCF34A65391DBDE61C6238D0E077A8561 +:10826000551FF0E622D545F0D75E2E7FA5DD1CFF19 +:10827000ACF05B6CF8429A7EFC5C2CBB30A732A160 +:1082800053D76D2A91F7D028577D0FD1C1FE295AB7 +:10829000342DFDCB3E8C774FEC8703773F07BC2F07 +:1082A000A9336924F53E102E007A651D54D4077F4A +:1082B0003A56F520A24BDD36B55F1454E1B3A36006 +:1082C0007D662407275D85897E5273B13CB4FC8BA3 +:1082D00067950D30118F4A99AA2F83A1EBA1EF4327 +:1082E000EAFA77CF0F393963E265CECE763B4C346C +:1082F000739DB0278E98C8E3A4BE7F23F192F00847 +:10830000D18848ADE7F9735720BC2AEC9F25572147 +:10831000496D8234BAA6F77F593447A0A57F46F34A +:1083200046810120B19143723C2A6B3043629C4FDD +:10833000FCACB7E019A392ECF934083129A181FE15 +:10834000A3A4679A1EE994AF4F6DB9B4827F9A8057 +:108350007724E6756317E6D988B293886337239943 +:108360008ABE975943B0C9BAFEC6EE7E77355878B3 +:1083700083B982C9EEF07734299702893F0121A79A +:10838000EEA4A732C9E6B2F3E55A2BB228197AC790 +:10839000987B4990F617FC15975E29414D245D8422 +:1083A000946BEBF18AB9CD5918D4B525776982CA97 +:1083B0005F6FF2C78D71AEDE11D1AF3CA35DB4B774 +:1083C0002EFD961D8978974B9E3B234D31CF9743C9 +:1083D0003A3B88B9F3DB3310EECCDA36F4627F2C0B +:1083E00086EED68E5C6F6A0BD8A1AB186D83C3B7CF +:1083F0009696BD9A2CFA3833D96BE4B2C352F4A4E2 +:108400007F2A0846C19AC2ED2E63CBD37E46C9644B +:1084100078C28575693249DA454627897E8BCDF069 +:10842000F1473AD140269E804BD7E4F0E65EA5772F +:1084300071FF3814E9874026543A9C1EFE1C398A85 +:10844000B274D5DD0C3FB16F4F74DBEBAFF021EBB5 +:108450009177509086A9FFCF3C13C534C13D846D00 +:10846000D8F28B1A1803148E828D7F7C40AC48ADF5 +:10847000E1C6BF7944C823349AB6DCA8083CA544B9 +:1084800004EBE5FF4B07B738EEC3E5EE68F5893539 +:10849000DD6BFAFF7A789B7BA8AD2867988E6B78A6 +:1084A000877FED5844C937F54DBF473008B758E3CB +:1084B0006453652BFC486EC8D62F59D0C2FBAE3929 +:1084C000DD077D1D534F3CECEF3FB24D3A4A621938 +:1084D0005F3F40FB9228142AF73A09644B14FD8F42 +:1084E0000B4432E524F8D780751883FDA7BF7D2C97 +:1084F000786892B32FDA02EAD086D49F66312F9B38 +:1085000035B806ABD01AB9A3AA074E520FAA2260FB +:10851000C93220AE5812A1A8F0382CFDCCB2B9A2B5 +:108520004D47132AF344AB954DE3F3038E23BB422F +:10853000E0A846A25CDB651E5BEA9265ACFAED93AF +:108540004070B9FC766F268409BDC83481679A28CB +:108550007BD153BDC238BF2302CC715AFFF6D72F4F +:10856000C378051E4F6A695AA82E85C421CF61E5DC +:10857000E49D6B9C8DA3FE7DAC63EBCD3B793A9083 +:1085800013A04911CF32B1284DFF547A5468FBCB68 +:1085900090D68CAD7215AF70E64EC55ED9213F3EC8 +:1085A000F3DFFD92C006A857997685589C32C3E741 +:1085B0007826212876482EE68D12F30902E8A5993F +:1085C00034E12962BE629C2894A35475E341396367 +:1085D0000B194613411EF5FA4F88450324928E6706 +:1085E000C76C0A442962F047C332509A65E9A6A2D3 +:1085F00000E11193D6E9CF01FF013E59E051025B42 +:108600007255B311B1E5C9550E8423F5DD89708C1F +:10861000C1905B73A3258E4FF3A0FD98B604F1F0D3 +:10862000635BB1F05598B58A83947CB04F9D5748F1 +:10863000C1FB4E5EDBDF35B933AF95BFD5F632D81F +:10864000F4FA47A23B109C88E59580742DBAF88512 +:108650001944EFB96EA5BAC97F54CA3EAF6480C74A +:1086600097628A9816B1FA46ACD7BC2164277C5031 +:10867000FCDEB6FD16B33D34F4F91811351943FF8D +:108680003AAD3B5D645BD699530C48E8B0E1765453 +:1086900028775353578872AC26E069704D626E8C10 +:1086A000E63EA36F82AEB0CFBFCF63EDC7E3184FF6 +:1086B0003A5AAB7586A20ADA6D6E5F406E9D81E80C +:1086C0003280463908529EDDFE39EDAE67F45CF625 +:1086D000BA31818844282EEB2668B4D57EE5AAE31A +:1086E0004E6C620E7A8079563BA221FDEEB90715D9 +:1086F000BA324E7172A223EE95D33EFDED3A189434 +:108700000BBD3827617F7AB5A551EA9E132DA1DCF8 +:10871000D5D944047EF842A9FABCC36A22FF749BEF +:108720006DD02A2A29C51DA0769ED4B4AB1DE6853E +:10873000E12C699F00A8D69C8C208E91C266527253 +:1087400035DE3E62E49C9363E50CD4EBD8AC85281F +:10875000B66E596104BCCC2F6C66E17965C23CB23F +:108760004EED9162BE0DDFF6CADDD0028C9162291A +:108770006287EEAB815EB04244A1457E4275BB2369 +:10878000484A259F691832CC11D67721E796448054 +:108790001D617620AAF11DC205DED85D739BBF3B2B +:1087A000F0D3351AE0DB98EB485E00B7F6DB3545D1 +:1087B0005CFE69B3D4E892EDB603FCEE022780ECD0 +:1087C00005127B103A330770B43B73CF5D617C9523 +:1087D00054B45DE3060CFAB39C004F9EA63304EE3E +:1087E0009ACB258E5F336B2B59B6E1D51C9DA7CE56 +:1087F000946875ED55D304F9ADA46097A55AC933B3 +:10880000D57EA96BE04A45EA6AB7C42F4714F30E38 +:108810002EB35AC19C95F1245990AE7332C9BC89CC +:10882000C4E25945907C49B88366AA3CD31A3E03FA +:10883000B4F736D839B7E694138EC75BE5D8D915A7 +:108840002C86158B0DD6F86F98DC028E38C9691806 +:108850002E175DF20497E4E2A0BA06263BAF593327 +:10886000DD365CCFD04E56103AD869C98D040CB1B4 +:1088700082536A7A4C1F3440403EB7B2C909E1497D +:1088800007DDD0429678583795BE7481E1A9CD4076 +:10889000A14E2DDE99222AB7C64E13B93D92DD694D +:1088A00048B3629FBB42530797833774C9B83436C5 +:1088B000712EE4F0C2EADCE7EF3C75DF264E43821E +:1088C0003D5DCD83947FC2C163AD26F3BD9DFBF4B6 +:1088D0005779146E996CD80247FE30B03AF046F0E2 +:1088E000FF0FD9D8DF2964EEE21F95627E2F663232 +:1088F0006EADE03CDD01E47CE7304CAD48765B9B3F +:10890000BC0AF213ECAB353E1CFC49C24FEE42D61A +:10891000BBDDD45EEEBEF9A7F6A158CE12470949D9 +:108920004C6293DC0CF100EB534779C7C1F3FE7E38 +:108930004652B711D98FE2852061A886702D5198D3 +:10894000C41E1C90A9244215B81378B3C40BCE9949 +:10895000FA0A96D0D041BA6B51D85EA1740CCC7E85 +:1089600023BC2F99932CD2C8014EFAFF8EBE915F83 +:10897000CABF2DFCF6B0EA08C73A88B7EC6F9B1760 +:1089800005FB0BB8710DE408FC31BCE07425DF3D3C +:10899000E1A9EC394E5F21D18D054D70F034783569 +:1089A000B24500908D64223D73C15DB486391330A9 +:1089B000D3C1E6885CC3E56A30C9E74C916DF72CFA +:1089C0002BDF81738710D33718DBFFEB48DDC23113 +:1089D00021CD9564FD7556BC0D079626A53E9DCE0E +:1089E000958B65FAAE558E4F13764C87EFCBED6CB9 +:1089F000702B29630C20F5CB91817DF610D653A204 +:108A0000B3CA404B800102FE0097A1813C312FC1C7 +:108A1000AC2E65F880B12E06293D94902AE1A28AF9 +:108A200049E360C104721FA115D0B04B0FB082FCA6 +:108A30004DAC58BFFF5772B1B91B142B238D2EBC00 +:108A40000ED3F7057E620628B431659D52CC2CA06A +:108A50000629779194C21390B43CBF6431C7C774A0 +:108A60002E3B4F57AF92116ACDB49A4C44A1F0B34C +:108A70002E456CFF6318CA112BDE9E246A788BEAA0 +:108A800067B2DD88797C5D1DFE6A713EF53B12722E +:108A90001626182022EC6B0CE24BD44402402876B8 +:108AA0006104C4C5D8448BA062DCFE9CEFBD9C8BE6 +:108AB0003B6783360A0BCFDCD8B8F4822C27E09AC8 +:108AC0003C245B49E98EC55A5C33A82BEAD68176F3 +:108AD0009FCC0A9529D7D188BDC23548DA7227AD17 +:108AE000CD0814B4C8820D33A175990C8ACBF71D3B +:108AF00039BF764AB0803BE89CF54C521AC710A8A3 +:108B0000636FD00C0A84705AEAFCF2D5544DE5F537 +:108B100051D7EBC418616F4A2259EE933DE93C0FDF +:108B2000523A157896016FFD4A6025BC8AB192537E +:108B30005762E5B9D963AEA2548FF95B049C32B990 +:108B4000D948E2146B35F2BD70688880C6607781C1 +:108B5000A6A4404DB7DF8577A846B1F62EBB2CD032 +:108B60005E388893BE2EE89F7F54729BDA2479206A +:108B7000D76CC07E7B80C74764A3CC54CB93BE3FE9 +:108B800059712C147901877D8CA94263B6225ACB86 +:108B900008BEBEE45AADF9F7070150816A4808E7FC +:108BA000CA7FCE249C7137EB91D2CE8A4B6F04CC16 +:108BB000A5BB5CDA99A6F06543E3A32D8D43347120 +:108BC0002CC1DD9DEAF9254C8CB031236C7271B556 +:108BD000448907427601E537433A6C6CEF6D4D0AE4 +:108BE0007396826638FB36CFB30B7D6551D3989769 +:108BF00073B7A1E677E6940F21A44C3729265A33A0 +:108C00004C12835DFA622295D4DC234F2545CAA11C +:108C10000105D07E84AC5A4A4B8CE5C4C36F1C9CC2 +:108C2000D5229A168B0EA15C029F46762B65226692 +:108C30000995CBD197D99851CFABB874CA6A42A1E4 +:108C40004687310C412F1FE78E60525DA3AE5B2635 +:108C50002432669D0FF7EA7A50D8986E7644433BEB +:108C6000A239822C404AFB940E1B6B08063317FD79 +:108C7000AA582E8C71020324F454EFD9C4B5105CA9 +:108C8000C25CEB9A84D60F3ABC5DD434C552A2596B +:108C90001AF3EF65F2EA606B0CAF94C008010A406A +:108CA00039E9014ED81E31EC9FCA7405169A86F632 +:108CB000923E8010CA71BBCF934F982EEC11693A47 +:108CC000F0AE5F9B86C73B41101E847BD4033730D8 +:108CD0003AD57CBD60A03D38329D04480DB8D78898 +:108CE000A371032E5D5BE27F25DFEC02D8101B40F1 +:108CF000E615CD58BA1F8A4963729C52CFD4FA2B1D +:108D0000BBA90E31F73AAC2621180B7580DAE56362 +:108D100034157A5B5BFE80D844075FC35863774C99 +:108D20007A2EF6AB721519007BEF739573542FB042 +:108D3000F13259770402734936D9E9A68CDF3F1620 +:108D40000B43CEFF22DB321CD349343A9334F8ABC9 +:108D500014ADBBB25DEFC2FD16D758F286E649B03E +:108D60003EDF697383E4227C338DA5C359F4985A9E +:108D70006F51DCF1AA7D8DA28EBA16EB5DE637A7A6 +:108D800006811E14ABD2D6B1CC86B877E9CBB677C4 +:108D9000152E58CC0C84916C7E4F92C252474C35A4 +:108DA000451777F2F511AD40374C63ECB9B0F7F9E0 +:108DB00068C5D01170A4A142AE8B5573D0DE2B696B +:108DC000CD8237489406567F10437DAA0C083B316C +:108DD000DAFFF0899480780BC668496D7A2D1B35CF +:108DE00033821EF279013FEF6EB86BD53EC1A024ED +:108DF00043A5AC6D811BDE071BACB133A617828186 +:108E00003BB56B3E831CB33EC29EAD1D8BC956194C +:108E10007688743F8ED13B4281514A252AA7929889 +:108E20001D60756069E8C123879D71EFB49EC42EF3 +:108E30000AA50572198224E371D0279F06D194C335 +:108E400013EAF3C09853CC55D05441F64EC76B4348 +:108E5000D7A1B68C2D9B5FD2C2D240A2048D7AD905 +:108E6000679F17576507CE2C61A8D628BE58419337 +:108E70001685102D08447DDA22E8409EA03D379CDF +:108E800015CEAE10D9B9A27D9CB2CB8AE1DAAC8EF8 +:108E9000ADB3468E617DC75DDBAF14E38765E73E0A +:108EA000F59C54BC7F8E398B44CEAE9E875F25BC2B +:108EB0004C83E1FA4E495BDA9EB1785C4DA7B79CD2 +:108EC0005D86455DCDC129F94AB1E4304A8010B0D4 +:108ED000A23FC9E115A062E1108D2E890394A27210 +:108EE0001934E2AFB4DB7A1BA6FBE708D164F3EADE +:108EF0001CE90BA639C23F55FE35F4CAC161033BDC +:108F00001DCEB9E38C13FCB75CE862C50D86D5B6FF +:108F1000B687E9D6ADD4001BDDE74ACE8FD66F26E3 +:108F2000A8C862671A48C01C7B2360090FC2B1C47D +:108F3000030BD8B5EA0407D1768D09AF5A724D52AA +:108F4000C8B71E573ACC7886103FA9CE58715F1C1F +:108F5000F38CBC7B73139718E46698793FDA09F4B5 +:108F6000FD51034CA7ACC5B44B0BCE007B3BF0636B +:108F7000AB4073497BBEB4C3ABACC220EE6612AF4C +:108F8000220F473FA5A5120CD83231EFF51E1175FF +:108F90004EF0AEEC9793E9888F0636E6883778D4A2 +:108FA0005259DCD4FD6322A7429AE22D8E6C8C16B6 +:108FB000BDC1253C002AF7611921E211343FFC4D67 +:108FC0004C1E53F2721E8EEE606EE30F86432477C2 +:108FD00019A469AAFFDD7B6696952DC3A0747B95C5 +:108FE0009F60B8274DD216CA11E75A5DE71C479318 +:108FF000CF84B3BAEC60AF2B68C1B438A2228F63C0 +:10900000131C42412F5FC40D369E2F553198878225 +:1090100069F4D14F8C2B1D38E53D93992EE8DF9DE7 +:1090200011644F870A951C0F261310DBE7C61354F3 +:109030008725A8ADEA46545D4300A42FEC5B16A338 +:109040009229E7B619741204C9FE7A0BCC61924BCF +:109050000B8549D16C9D51E6A14BFD237AF4D3E4F5 +:109060000D5A5703AC800C886D17E67B112A82A934 +:109070006B97F442D6E3919D2F198349F68CBCA8D7 +:109080002FA1B430B1AE98EFCC9CC39FC6C5CE51D2 +:1090900013DAD56DD7960F512D9CD67536AE8C87C9 +:1090A00020F7E7B3D9275B479704C017B2E59B7E4B +:1090B00021CF3D2D7DA5E36E3C81992B306E4C2D4B +:1090C0007840BB458666893606B00602F2CF7BC47F +:1090D000009FF4E782CB2F38E33AA614874E6F0B3C +:1090E000A3965275A095B135C692352183F4972089 +:1090F000171C9E56B910EE39974218F0A9E04D6939 +:1091000092635E5369F32B20A2594E0113A3705949 +:10911000C8286A5C75C44F1A12264C13B967FF62DF +:10912000791F05E2BC03ADA5CFF3949B62A2721C2C +:109130009F236B33D2F07A0EAB7DB8C5674167D9F8 +:1091400011F2D2BF66985FE1D9FAC2AA018B6DD441 +:109150002B85CD1B618F1447621BD4B37A3781EA0C +:1091600026DF5D5855C533890019F9C8C0D198501C +:10917000662186685CF150D84B6D0216E226804A63 +:10918000B7C03E429E9651BE5625A322DE9F3F4366 +:10919000636D4EB9C1A90798EA1E3B186DA81DEB77 +:1091A00075AC68D6590031163B528D003CABB76D9B +:1091B00018C7076F94F21F7EC186775F90126DF813 +:1091C00023C4C8EBAAFB7BC9CC8B92C5B7456D3EC7 +:1091D0006CE3ECE1E8B93F33CC5587055CAF6B2E0F +:1091E000EC684678E2170A8C417CB1F9F1D6E7CEFB +:1091F0004AA727432334E9AFCED7460960DEB658E5 +:10920000CB7D3A1104867DCCA9B8B5BF909751F7B4 +:10921000608F619A14080A5A6DA58DF6CAEAEC3778 +:10922000836ED5B5D201BC70D8DE8A62DFE71E44FA +:1092300000C056B26F7204F5032A33F7EFFD125ADD +:10924000DE36494F39C8E15C03AE7927C1A65E6EB0 +:109250005B271F4E88E8C00C13C7E76A29C5F528AD +:1092600018AF8BEDBFFBD7DC4DBB77FAD9F4C3BB8E +:10927000A7E44BF5399EF7BB3BFABD31C8BAEEF512 +:10928000C5428608D9B5F211745A5EFDBD16DE9D41 +:1092900012209773C2B3A89C20B72DF76E2C172C01 +:1092A000AAEAF5EBE5F2DEFC2D3364E8B25F706705 +:1092B000B141EB5097CBA24249CE4A0E0CBA7A91FB +:1092C000F2C23E2893778B1C5EF108202395F21C96 +:1092D00089565AAC02B693D50733FF3E9560FF48D6 +:1092E000C908CB3EC2E0216C14850F47B514116844 +:1092F000B82FDD38A2A1ABD499C93B939FAC73B80A +:1093000090BD9616A01FBB4F3DE3EDFCE4FC99E831 +:1093100018633A415C1CD81E107FA83519FD6BE616 +:1093200048EC8B73B7AB49B756527904FF4DEE0644 +:10933000A57DD9FFADF7898210A7A5CD51F7BE87CE +:10934000F6A12ED8F164C12FB01873DBAD9F8486CF +:1093500071E3AAE66F3CEF46CEEA39551DC1098A92 +:109360005E13F671196BB7838A709DBB2BBC0D65BC +:10937000CB4F0920EE1101EB3A341726540704971E +:10938000A331265A7037C144C18F562F10E2E68CA4 +:10939000085E91CE9CAF54E45DCF1B1286F50E0E95 +:1093A000A2F827488AAEC3020CCF94D97D3DDEA037 +:1093B0000660C65F4D273331D775184D2FE045C87D +:1093C0007870ABAD30893087C3519389E9A3960299 +:1093D00015259D7DB8590CB2C75C0B0D5B9AC80C66 +:1093E00097A3785FC6FC7B936B28F596698EDB7339 +:1093F000B072D1EF818396AF49C78213832027A330 +:10940000F73D0B6A82224E1A214566267444039763 +:109410004D566B559852A20D40CA4D352553FD8DC2 +:1094200097854F2C7BD1053C77B46200B08BAD772C +:10943000828024F8E7656BB89B840BCAE559C34664 +:10944000C7853EEF942D34D13AA5F0F86EF460FF55 +:10945000D3164058E23C76E10F8C031066638161BD +:10946000B9C136390118ACC1BD085E7F1094152909 +:1094700002F1C0956073F8423AE1256F4F6690FDA6 +:10948000927649BD8858432BA760A58F267526E3A1 +:10949000995E8D5A1C11DF0D2FD4686774C3A934EF +:1094A0007BA8170EBC02220808B272FCE0AD466A27 +:1094B00003C76146DDECD6F316CF48BC49939E4DF9 +:1094C000B42F64ACD3B384CC2E180C067C8BF8BBC1 +:1094D00021F5BBEECA2A4E0208D12E40E6357E5C4D +:1094E000B07C217C5D6E84619C6710D8C41CECF05C +:1094F0007EE6898D7519B5A27FFC2CA6F38BE87FDB +:1095000009D259281D672B56B13ED27431060BCFB4 +:1095100095B1987DCF335AEFC5EEED780CC60CF8B7 +:10952000A7742E47B58FAAB406BA9316E603E1884E +:10953000556B73D4E470B80A756FB81CC7ADEB1BDC +:1095400077C4CC615589F2391B0E034F79701CA288 +:109550001CED4ADDC20EE72CCE1B4CE00AD0C4EA5B +:109560007C088784094FE5C09707F41F89FF61B124 +:1095700051D80C0725B433CC68A278993C284935DA +:109580003F7A02AD3B7ADFBCA4541D7E9BF8CEAA85 +:1095900015E6882F17A64B40A0C655F890AF1C1EA5 +:1095A00041EEA168B8DBDE0B221433BA1E97937329 +:1095B000D11DAE487099268A8B8F3323BFE2CAA48F +:1095C000D7CC8FC9D3C295AEDEA3C002069F8B1045 +:1095D00037518DC9B52C438DA5258185DF729984BE +:1095E000C0BA9C51C4EA8F4C5B6B3195990EC70B86 +:1095F0009DB294715764F08CCBD4F74833673AB17D +:10960000B96A2E90C18E5C84E3B6C5536D9837A9B4 +:109610006D0C86A1E762F8FB77FBB31AF3BAE6C7D5 +:10962000D00BD466E42FB954B944825B27C4228D91 +:109630008C4CDCAE45D39BBD9B5C33BCD5EFD5D108 +:10964000A10D914245E43DAD8D50D660090FDD235B +:1096500024FCBF7D6201BA10DACE8AB1C83A60B785 +:109660004546886F28079BD87A519041A4BE057A59 +:109670000A1E1D621E5B71879330C3793CA92C675B +:10968000CE906D6C5F0E96894F551B4C5825FF6C24 +:10969000D905D03E31B13FD506FBFE7F3E46FA05E7 +:1096A000063A78034B314556C619609A67A7522689 +:1096B00087EA64A39799AEF96AB5C055D1E6711FE0 +:1096C000714A52E0185439B481AC131998ABE6943E +:1096D0007A5AFA3B8F839F055B05D484C533DF40FC +:1096E000902FFDEABF8929469AE1E5365117F653D6 +:1096F000B968B7AA41942863D58016728C14406A61 +:109700004055DC5708394A6FC325E6712A0FA0E49B +:10971000F34BE1FC99EAE62E61BC214109A5895091 +:10972000356716B166E9853BEDCCBD8688351FCD22 +:10973000C2AF26D680635455AA99C5B533770AC7F8 +:109740003CA506CEE32C547BF46DE5D44A55623833 +:109750008F9AEFABC31647C89A06121BE4381665FA +:109760008D425C984D62E188CEDFA788DD11D2780A +:10977000040FC884D9192A54515185D53B4340C799 +:10978000E9C8AD66E3732A401CD41DC3D7CE7A1F47 +:10979000C1DCCA7774B0FC04255F01136618C33EB0 +:1097A00039CA825D8B943CEBA6E7027E190C57C048 +:1097B000175BA8DC41BF8C2D3A7FB75151452D1561 +:1097C000201B304E4B2EA3B0DC53E9454CFAC4BCF1 +:1097D000E82E1835E15528B22EAEC113CD5182ECDA +:1097E000AF0CD0ED6E0DDA0DAD29BACC3A666EE154 +:1097F000A17820E750A5FBAE2B69DA42B6ABE2BBFD +:10980000AC2F2751A89F87CDE2CC1229069D948BBF +:1098100064E567E10DA5F55C85C737F1AE41B6CECD +:109820005999D3C97C355723347C71D198D6FE051C +:10983000753B5CD356BC5B02E336F6163F35D97BED +:109840008B2FCABF6E932A62EE1E9139C0D630CFDD +:10985000C9092792F1754E2978F41A5110BFCFFB30 +:109860004282ACF7376A16FE1026B1C6E6509B99C5 +:1098700097B98CD05134A964B74BAD7EB628133A52 +:10988000FA0D1F7924304372F7FF6C879FF625D3BA +:109890000BAEABD261F17C7507712B4F9DF5E18862 +:1098A000E0BC3FBFECD3BA380080D22D5A4BB5870D +:1098B000411C32ADED97A050B33F3E944F33C6CD1F +:1098C0009B2B5872A58C82DF712445A2D1D09FD6E4 +:1098D000BADDB11DA2AC9E7C8C6794250BBAABCED1 +:1098E000C3F939175CFF3363D37A60AF979603AA45 +:1098F000944A5276BD46BC372A16C053D84775A144 +:10990000E808C333E77CE67EBF604A92A0FF80424E +:10991000FD751A1CF0D6E1D12BE4D55985AE53B1B3 +:109920003646C733D77FDA59918E358CCAA3089E45 +:109930004C7DDDD5EB4A63DD0BBD4EA0A64DC0C806 +:1099400090449BBA1B743476A4CF441207A632EA23 +:109950003DB0118F5D8F1702BE7B9E0DBF013D563E +:10996000004E1A46D87FF5A84D896A90031408A4C2 +:10997000BE923851A8731EA9365FA262F9A507A549 +:10998000931B1516054CDBA70BBA9B7B6E9FE9AFAB +:10999000C8F359EC5834F742E768074BB065D8B0C4 +:1099A000C8ACD53C56673CE1FAABD7DA2F44D67643 +:1099B00031219EFA6C9C8ED6B40B6ECF1A138FCBCE +:1099C0009314BCB1692B1C4C921F4A4FBFAC11F4CD +:1099D000C6498F3B0013B43BEB04D6CF8E1856ED2F +:1099E000F7475B4EFB170FCAB675506B3DE3C59644 +:1099F000222E64D1DF65A5FADA2BBB666E6561D6CF +:109A00007DFC048331B45A8E65AA98BAE71F306F83 +:109A10004535CB79C1EFBDA511935F99D97EF3810F +:109A20009AF19743822D6D254FE1B5B14C894208DB +:109A300098506E9348543FAAE121D7BDEFB6A07A63 +:109A4000F5AB4A2B2F9258244B308C384951A0EC5F +:109A5000977521BC93329308E97502D6BBA36F8832 +:109A60007C6F386EFA19DE1B5617755EC914D34227 +:109A700046F43CA6F25021DDAF169B6185579DCA86 +:109A80009BBE966EC168CA075401C435E39C3C6610 +:109A9000CDCEA93CC66F26AB5EE94C975518DE27A4 +:109AA0000FEF5A7B8ED3535C04EA88404423CD7178 +:109AB00003BDC7D9106554DFB0F38041613DF38623 +:109AC0003E3A4649F0B1C963638664D5EB1C22A6D1 +:109AD000896D4F5446B8452155730BD81742FE91F6 +:109AE00059F72FBF5339FDD3BF574319B55A6A925F +:109AF000DCFF5F71A2470D9ED2D2FCCE6071340DA7 +:109B00009139905B441F87BA3A4851AFAF832F9485 +:109B1000BF95EB927C19A9D739C7A0326D5A99A38A +:109B2000EEED1C60811FB5E0C7266A1B0A48F5549C +:109B300086A3B7136227008E59FAE2DCE64BE4F104 +:109B4000D80296425149AE170C3F567CD7F70B3DD1 +:109B500017F9166A5FF6F4FCACEA307D2E798F3681 +:109B6000E027D6BB1C1E549B8463EC3D75E000EAE5 +:109B70001CB7D1E700ABAF62A3AD6FD6C600DB4424 +:109B800017E8CA229BA45B6A9C7E0FC5D95E5AD196 +:109B90008C35EB81A7BD84293F1DD1806BD3E0B408 +:109BA0007D054AB02F3DCE54BD67D952C8B4DDE61D +:109BB000EEC21EE0AF773830B0B2FEE638E671573D +:109BC0006514E92B0090BBA2B80CDD039224ECDCF9 +:109BD00072F8AEC140C01972581B2E42B8933AF2C7 +:109BE0009099D562734A184936822177F02DE7643F +:109BF000952E0B01E0497FEC6442BF061B9254AFE7 +:109C000065AB26A0C70213EBEC105A961961CF186A +:109C10005CCE87E01E53376D66ED48FEF1EA95EEA7 +:109C2000F302BEB41E37C0EF19A59D4C813005B2BA +:109C300082CEBB68E0DC5A4D90F081396B8D653582 +:109C4000BD2890C3E573FCF92ADCE56243A9805185 +:109C5000611A168ED6A39CADAD7DAE6C61552E24D7 +:109C6000011CE6C8F9CC5238E8B8FDA6A28D8F5881 +:109C70001842C2E3E45756B425CED356CA5FA98D25 +:109C8000B2D7E1267C16211AE0BA78CF010F08B3CB +:109C900048FE91DE4CE7D5FA25C6A18865359F14AC +:109CA00004759D0714297713600304EBE9F5931FEE +:109CB0005BB3686EFC58E0F0C634A0C22FCCA8BFDE +:109CC000FDD21BA81013170A3D4CC140C8FD5721F7 +:109CD000260FE3D4B9D843C07919F59226A0C1A5BF +:109CE000967A862A12C8059A6FF0B758C3468C43F5 +:109CF0009ABD7BB83DE1BC9A9417D9A424FF3CE0FF +:109D000008ED865839C44844F3064C0F58E1CA930D +:109D1000A069F69FD487712C88D93A8D081ED72D5B +:109D200078A1D247936B284FED40CA5A505B0E433F +:109D3000A042298BE73D44EF2ED584E907A5CBCE81 +:109D400058F08B0BD7F1E00542E782E9DA6EBC628E +:109D5000FA202CBA363966CADAFC741BA4BF6265D5 +:109D6000CB6003F4AE989955F071FCC751459ABC8D +:109D7000422A9C2886D5F0A537B66F29C63941A757 +:109D8000235621BE67FEF40D4E59CB2DD9FD5E2E14 +:109D90007C78E05084739117B48C5A2277A4D2DB7C +:109DA0004D8D5E7CDA1E6CEE9F6A76F79E80A3383E +:109DB00069ED8F1E8D5F301F045836E58A442612E8 +:109DC000BE4CF78F2BFAFDE462DFCDEDB7599F3C17 +:109DD00069207BC2986DD2E542342D923636799057 +:109DE00069FD54E343BE239BC265EF5C0CF42590F0 +:109DF00011C5C7F8E1C76258925D02ED7D70957597 +:109E0000F3CEB2B70D41A74AB7C7C4A6B5690C9641 +:109E10007EE6C2572464DC4EB37001F8D08FFFCCCD +:109E2000A6A56B5E0EF724577DDF2F0D788E851E5D +:109E30002069C837C2E5FA300CDE85873B18D2C3EB +:109E4000F41F33818BCA014F487918F390F4D24242 +:109E50006442188CF84CDE933A4544A2F0EB4697E6 +:109E60001DB7AD863E8C0D0BC8BBDB3E12DF131C4D +:109E7000F9117EB4253DF6A6D4B7D611F2E5E82F48 +:109E80008A5DC7047360200FE26FEF57EED11A8D21 +:109E9000C98FB341539D26DC76E21925F9CA96A2F3 +:109EA0005CD186853EE22347A2649E31433B8638DF +:109EB000CCF7A6BB67F904AB9EE7F42763810C4D92 +:109EC000EF8E595B40BB50F30C287E226750F8435D +:109ED000DF48DD46D78AD6A2A4251428ABD1FE1EC2 +:109EE000A105D90AAA420E92684E1EBFBF0DEF739C +:109EF000ADF73FF75D14C58E478FF44C916655A7BB +:109F00001432BCA1357757712BBD63B03B8E01264F +:109F10001F9D40A6B3C8EAA6A7194CDE4A24DCF56B +:109F2000BC48A943F89B9DC6FAD52885AFEC3C7880 +:109F30006552D0D6DA4DE0F4AFAC1FD29949DEA716 +:109F400066C09E451B71DD08F2C3AC5975BEED7746 +:109F50000C09DBF1DB793224DF0C767380110EA162 +:109F6000DB4375E00EAE78865229D9C04108FCB7B4 +:109F70002907372DAFC236D28C8679325E96E7E458 +:109F80007BDBD3AA7FFE8B2B1CBAD8AB6D88A35783 +:109F9000B9C85BE992EEA726F5C6A3452342D22DA8 +:109FA000BC1FBF31EA6C98CD3E4E399F2B31EC1768 +:109FB00051F20DFFDA2D476827331B6EA0CC1F82AC +:109FC000071D1730EDF886A2CFEAC8A0D99463D355 +:109FD00009444331FD04F2CECC469D5803410E990D +:109FE0008F42E1D1E5FBE3592E0F2ED84F9FC98A4E +:109FF000ADBE133EB5FBFC076F2891926C9E460EDA +:10A00000ED2D6629E92DE14135FDCDDCBB37A0D131 +:10A010007E0CF8836D4A64FF5B24758E65E854F806 +:10A02000DC2EFE4874A5D8C02F97DBD700A454DCE3 +:10A0300099D4C12537C6F57F5BAAA0261DA185D17D +:10A0400099587C3E935EE1DF0942B694CB274941A3 +:10A05000A2797C605D6CB0DB66D0A280EC289D9D0F +:10A060005BC94D1350EB49B52848CC3B1B9E3AA920 +:10A070001924276C8C46DD4D1B4622A5BC33F47A8F +:10A08000863A983419F6192BB790CA44F3D75A4236 +:10A09000A832987CCDA5637D9CCD8E189780FCC896 +:10A0A00058FC571F70921AFA2D97C9FE24591E3D6D +:10A0B00007237D9C8C2FA3294274C9A3047BE84508 +:10A0C00054F02F5ACCA956C632E4D31BFD58FD04D8 +:10A0D000EFA6A5F3707B2395EFA0BB4752A6D30351 +:10A0E000BF12E29DE60B89DEF09E08D3128DDBD213 +:10A0F00027F4480B855870373C758C1DA52333AF6A +:10A1000009C75579F8BD476D60BF187748A0139708 +:10A110006931767E29B458B401A4666F1B3A8C9ECF +:10A120007E8E088120E96B8365E46019AB801ABAE2 +:10A1300022C1A8B00FBD6FF51111114B2AB11E132A +:10A140007EF8EA2B34EA77ED2736B50431B568CED0 +:10A1500047DE0083632847F6B3C833B530537494A1 +:10A16000AB579805511CC9B2BAF14F0C91B4E23902 +:10A170005CA0722AC2638412AD34363D55BB8E1E7C +:10A1800086FFF5D24485F03673E686B153FA7A64D9 +:10A19000B673ED64842A1227DF82E76D8FF1519840 +:10A1A000337CBAA51E16A5F2992CFEB1D0B540F2AB +:10A1B0008BA90A2B2344997E716B2281EB6EE6B446 +:10A1C00056FABC82E910425008284182E332B1E4D9 +:10A1D000A67C72C93B5005DC68E0AB70B312E0842A +:10A1E000C95A89779D4BDAED5CCC77D5BEB74DB5B2 +:10A1F00076F56A04784FDD0211C5BA130BD2C69FFB +:10A2000024BF0A98BE3A5F9F4C250754B410C5DBA3 +:10A21000AD0D6E1D7B077C1A162F294A46E07F0183 +:10A22000E03A28F0467C991A309CC5B926ADD85C36 +:10A230001514F0D9641866EA237A31F569C15675A8 +:10A24000D2E346909D1132B72EC8ECCB0458FFA242 +:10A25000C1EFDF94C4C705A2B70B3ED4FB58E40B93 +:10A2600063CDB8BA2E1740C86C9A2B39CFCECB43EA +:10A27000ECBB9974B1166DC2E564D2917A47891A24 +:10A28000021EC04D6D33CFE6CE7188EAC55280CE36 +:10A29000E51AAD0C1D2B15157F15E68A7763F907B6 +:10A2A00090EF743BBEB73E505A111A0DA9DA0F62F7 +:10A2B000CD8127AFEF9B464B68BD176CCD623F62E7 +:10A2C000E67A35F7403D7C9B73F24F846775EFACBF +:10A2D0009BD18B80950EE91E4DF612B3FF83E232BF +:10A2E000D74CA630B55C381FF6FCB116FE9694BF6D +:10A2F0005B8FDC99DA193030C366373AE7544AC6C7 +:10A3000033BF6BD057DE84071A03E0931F9408FC19 +:10A31000C9C479200604656DA79A45117847397735 +:10A320006B0CF421FCD71939E4049B8208909AA79E +:10A33000D7B52D53ED360142178832B2CE054BDB2F +:10A3400025A82CA4C07A42CBFFF0312E69AFA89487 +:10A3500019F8959FDE8EE10B203FB57757205CB949 +:10A3600049353A89F9CCBA38E60BE68CE98C149970 +:10A37000C33E0CF20A18E332C0A39D30359068F852 +:10A38000111563A610C5094EEBA58DC0F56BA02E67 +:10A39000F12DF64E503EBDF243985B7C2934642982 +:10A3A000CF586B21D202B86813FFA194A04E4BDBAB +:10A3B0000A665E344F7DFAE785B40ACAD31FB7C96F +:10A3C000198338B9D84BE692327A8AFA03DCF7B4AB +:10A3D00077C6B30B44B1E4FC87D0C1CE3952D283E7 +:10A3E0008A1B38E8C2BF3254FF6D19921EF2859461 +:10A3F0007E30F59BB060F6AE5D7F6F7093C07FBF1F +:10A40000F890650E2AA0F63DB9C949C95D8E631260 +:10A41000E2753612B1AD80A3762C06DFCD99EBE65E +:10A420009A361CA7C87E6CD3ECA6718DB94DD56940 +:10A4300043E42F4D4DCA1D7579CA45D78224FC7F50 +:10A440004D7AF7C569E7BAFA0F68EB7B594566A5FF +:10A45000EE3A81B52E9D71BFA9270604CF1EA1A596 +:10A46000687239165E0861B075CC75AD21A5178A82 +:10A47000AA9C6643C70F0464CC625C22C2D69A2CA5 +:10A48000F129413E944B6141E5BAF4ACB9013BBCC2 +:10A4900057C4DE572C376BEE6DC1C610E1DCA959ED +:10A4A000E9974A9E99F79810EA3116B21547248920 +:10A4B00086D398A64B57C66F4D5EDC29B8A91B9969 +:10A4C0009EE5C84ABC4B718AE27B5DB9EB01CAE1EB +:10A4D0008A47ABD4D8AA05D57DC83B1C926D29D23A +:10A4E00097D79D184A40326AD3D72C081AE788A913 +:10A4F0007C24458735EAFE4F30CD9ACABED593EC11 +:10A500005DE9479225443A854386CE912786A05936 +:10A51000CB358E02FA195B1397CB4F9B71A94BB7C2 +:10A52000786C4D6BD1DE34AA3D5EB182A5BB32B8EA +:10A5300061A234073B21A441B96835CC549DE004A5 +:10A540009F43AE93DBC32F127AE204F71E0A819772 +:10A550008EBB8FEDEF886D3E1FC972F9C27B0DD7A0 +:10A560005D6D6BFED37059FF615D86FAD553645EF5 +:10A57000880C9B608EE5C85871FCD5E59AE8918FF0 +:10A58000BAB6D6227695ACB18AA14B93D3914268E4 +:10A59000B2BA983499C3234C7958B53FC0A83459FE +:10A5A00018C54A9055C75E53469A85BE251BF1369D +:10A5B00076782AB326917AB8B1FAF8BF842D1CBBFD +:10A5C0008D66F2160CFF090C256D365275DD34CE02 +:10A5D00038CD76D3545BC5C315A5AB26DB41F0C996 +:10A5E000EB69DF66D210502B9628BFE9427A14B58A +:10A5F000682A20130A8D4D957A20527991A535202D +:10A60000A7063AC31B1D4826BE60B61998453ED51D +:10A610001F24880FB0ACA53313D7B38D80A96384F2 +:10A620006E54A2F73DAA44AEB13DC3D5983C42DD7D +:10A630001EC763F211972FF065E43A762A8F016501 +:10A6400097D9ED131F1361973FCF38A78306C5E451 +:10A65000F6EAA9882F13714B45842126C1B7E6FC81 +:10A66000F8E70EF874F47D0FBEFE358F9FE72405E2 +:10A67000A10C18953E921328D787641B7546254C6C +:10A68000323067C2EFB20730EC060855F242A2B58D +:10A690006D4BC3F3B320098DBA76531C83A7D6D074 +:10A6A0004CA35A47E2B551635B472F517FE3DA74FD +:10A6B0008F075B56E1E4E5AE0F3F82C627666C6903 +:10A6C000FDFD8464EEFB79E9395EDEC2217A9905ED +:10A6D0001F1E7BA0D2F2F615C7BCC17AAB6C9E865A +:10A6E0003CACBD6D7F9E8A6F3DB898CD512AB4FEBB +:10A6F000ADE8387504385F636A00607E77C8F1831F +:10A7000003EE2E5403979C638E5CE348870BDC803A +:10A71000B4DCAA16CCABAEF10BD8B46A48B5AE30F7 +:10A72000ED1D331014DA309B7C9C2EDB32611FB29E +:10A73000BE46D66766D0877B03406F763A564D4E4D +:10A740000B91D33F56E709766FF33CB6C4869F71F1 +:10A7500076808E0AC260EF770B51E49E3630D5EEDC +:10A760006839A94F582678DF3E0E1D42A89872EF2F +:10A77000DC75604D7017CE0CE13E97E09DE4172626 +:10A7800048C40028094FFD5DC6B5C763916367D60D +:10A790001DBE301B341BD197A1DA3227C0FBB7F4A2 +:10A7A000211EF4046C282ECCE3A96F4D20A6CD63A6 +:10A7B000AA6862BE2613970EB1D5AC44AD0E4454C0 +:10A7C000EA289B60E561FECF5BEA831B126E407D49 +:10A7D0003BDFA27E64849DB3589082D585655A2262 +:10A7E00049AED2342705D33363D800E1C7D2C81BA2 +:10A7F0001DB836F1E814CF4284CBBB301588FD5329 +:10A800009E646E2ADDB0B6AB008CC001814E7738F5 +:10A81000E66F117D40D1D6E4C89C9454A5E363E46F +:10A82000831CF166CFD9A287FC0C4DF58AD995CD52 +:10A830006AEB091A08E0376E0BB59E95F5E28BBA04 +:10A840000A59972E5500C388E94819699585191C3E +:10A85000392F519A8883239CB3505B24ADB4116681 +:10A8600029FCA4E57A061965ED5D068EB1D6DA6F8E +:10A87000ACE06AD7352D6CE61302ABBDFB2FBDD221 +:10A88000122B97EA0DAE3035A87E5A05D0908F3541 +:10A8900052F2CADBF269B237CA2E1574B5F822C873 +:10A8A00018CAFF31767D00E6361610A95261662C73 +:10A8B0005FC22D2EA7851B6DDCA6B7BA0D141DDF58 +:10A8C00014ADEBD1487775A2909E589A291F940732 +:10A8D000CB9AF465976383DB4DFE957DB91FFEB27D +:10A8E00065DF059B776710221F1F1F2D039480C70C +:10A8F0000DC879A1F305FC3391C5612DBEE1A90214 +:10A90000BCA045205A0468162D26E061EB43075C85 +:10A91000D50556C5502A8BE0E001F687687F657E35 +:10A92000B1FDD90CB3415D8D7289EFE912AB13C84B +:10A93000934A1F08D6938F7C2E0AFEACEACB62E8BE +:10A94000E580EB3FE4FC61500944312B82358C7586 +:10A9500074A1E8D08BABEEF1C9B59F957C19BCEB27 +:10A9600078D7B7CE358A0F600855467C220C10295F +:10A970009C44C9882D21944D19371D8D38958D948F +:10A9800066DED6C6705B3238F4B71C50DF59D91B6F +:10A990002C2724BF1F42F7A271FDE2087A396E6EA0 +:10A9A0008C7D23AF16B8CABFAB8FC28F21FD6C9AC6 +:10A9B0008F7224A1299E92D2E7665F7508C6116A3C +:10A9C0002EB2781DD12A522FAD7C61085AADD2F338 +:10A9D000D5CEA993F58FFF456F4B2C9434BCDE2860 +:10A9E0008A6FD77887BABD8EE9B2B8B1B745F5247A +:10A9F00094B0EEEE09C94BF52460633179580742F3 +:10AA0000E98949EF70D9AC8BCDD031DB551ADE9F87 +:10AA1000369BC241280CC936DFA9D6771C5379F280 +:10AA20008DAC632722E92AD146FAF1925A6635AEF7 +:10AA3000532F1E93F31273F45C037E4A56120ADC02 +:10AA4000E12EE08C2479AB313D1D8C77A1457A94C1 +:10AA5000FD1102AE1213228DE4891C66913D245E25 +:10AA60002AE6470AA432A7972F82662FB28370FE88 +:10AA70004B9651E680F3875B38B774FE3E92996639 +:10AA80008C10FED97F29C6478FDBE7B1998C574BD5 +:10AA900081E2BE4CD103519D5EA661AADAA6CB8CA1 +:10AAA00076D9E6AD4CF267A9812D661A6AE0C683B5 +:10AAB00096C1FEF9B0421ED79650664781795F78FD +:10AAC000ACD77325DB16EA253126872AD204CA368D +:10AAD0002A05FE1B6DF18292085C97FE2762626F69 +:10AAE000BBF6A71C73685FC03029EE8583C50FA431 +:10AAF000454F53B0EF65B8F6464FC50143F01DB35F +:10AB0000AA9394B979FD683A31EA8AB44B430D9E11 +:10AB1000BB0EBF706CD2407BB2CDF837E879315BA9 +:10AB20009DBA54E178315E29DB45AF0BA97313223E +:10AB30009A8032F9A6BE2D6A8FB4B5F88A071C2513 +:10AB4000B0761E23154B0B4797E93E4ACCE03EA258 +:10AB5000DF5BC2B8885721F6848BDEDDE783B50F53 +:10AB6000FB48539F823098BB3C58AEA651C6BF1FCE +:10AB700007A9439D9B1600A2998E3AF3640B2D5AA8 +:10AB8000232DDD4E6136D960D6AEA90097582FE44B +:10AB9000FFCBB3F0B9285945DC7476EBA022C1AFE6 +:10ABA000070DE85D6DEDC4CE8656B44315FDD07437 +:10ABB0006302386B69B86FE216C92D81D581CCDF8D +:10ABC0003181D84EA0E8BA92685E4C01A81ABBCD7C +:10ABD000DDC828DD9D33DF43F5B7D924CDF27C7283 +:10ABE000256AB73DD6869332C250CC595D1D85E6A5 +:10ABF0004C91878C75D393D2F33904870D68CB9C25 +:10AC0000437A61087CE411521B2F8E786AD6524039 +:10AC1000F4CE119D3C75EDED558F27C39D2AF4A40C +:10AC200055FDABA9CD052010EFCE9481B79A0B2A24 +:10AC30007A83526639EB8D3AEDBC4530BABDE1BC42 +:10AC40003E85373A927A6681C0ADCEC9624573645B +:10AC5000C25D00938321B1DCA69CC86C1443B5C6C9 +:10AC600049C5A057BEDA68D4E5CF9FC2E157A30417 +:10AC700053492ED22CF8C6041EBC1596093EF23557 +:10AC8000D1D8186CC496DD9BAB0CFA896C2617D111 +:10AC900086A244300E47AFEA0211A96A0079718199 +:10ACA000EAE6AA97146AE3E962B65F1AD2C1B1581C +:10ACB000CEB0D1F0814736508FC67A4DEEF3F49383 +:10ACC000DCCE5C4566B1644F454BAFC3B0EBB11110 +:10ACD000F58F9F5BE54AFABD83A964D0A04B931022 +:10ACE00038329410D2D212CDCA2C86B840A0091C9A +:10ACF000CF67BBE1E2C289D8E08CF47849703C426E +:10AD0000F842F1FA051CE5FFB0D0FF4B473E872E15 +:10AD100055E0180A29868696D63A0F97D5628A3961 +:10AD200036FC253B24E9C48378F17029BF9D58E2A5 +:10AD300059621A76B2A71314EB3249064859BF3646 +:10AD4000098211625BB2A67D9DB8F403BD8A5734B7 +:10AD500045B7CE2B03343B8C7045D7CA22BA9851E5 +:10AD6000F448E5324E0A9AB8D4CA008A7069FA1CCF +:10AD7000F92D82A10B70CC488D9B9CE244993271D5 +:10AD80007D9946184F8A89E5873A1270F455BE3A84 +:10AD900044D88AF08FD851A49DF94B97252C4CB0FC +:10ADA000328EC51CB486EDA7273738050E434752AF +:10ADB000D9EA31C75627831F38A1CE00680FD14F7B +:10ADC000A1326D7DD52D2EB844665E3C4E1E79E8CD +:10ADD000F6FE20CB6530EC0D508B479494CFE1C844 +:10ADE0004D76D4057845E41A4DAE38D063CC435B3C +:10ADF00074A63A39226A3F60BF9CE362BDBE3D7EC5 +:10AE0000F4A0E66F79F5BB4994A20769CA56F5FC30 +:10AE1000434D0E1CBD173E295E8FB9EED10F91B286 +:10AE2000F6EEF16AF78650A7511DCC708C5EFCD40B +:10AE3000C76FB24BAB96AFD2C68B48A66481D244E3 +:10AE400041D4B282C47B7E59E1BC681A5512C482D7 +:10AE5000FB5473265071580D76F3D0E6AE8C2CDC83 +:10AE600041EC81158467F511AA6E504C9090F6E87C +:10AE7000A45B6A6E493F1C8640B5A659CA1DE5AB66 +:10AE8000CA9E7C5CD6F1549ADB534A83E7317EF24A +:10AE9000BD6283759D4C0B85AA0C3FE8645AAD4298 +:10AEA000E57E22741F0C30CECB3C68B0BDECF4853F +:10AEB000F3A441161C59AB15B2E30840B981B6A002 +:10AEC000C4389F94418CD4EBAE38A20FA1B4C56BAB +:10AED00032BCBF0CEC72EB7C7BEEDC1677B042A18F +:10AEE000F592BD74BAC968A67D2ADCBDB22F2C0AC2 +:10AEF00032DE4953DF4BA8BAE38BD0AE6DD5B596A1 +:10AF0000E7F8362FC86EBF3E7E62D61BF4F83D6D63 +:10AF1000985CC8871579159883FA53B37419A5EB13 +:10AF200000DD5F6C42EDC40F9E540C60E026FAD742 +:10AF30006DA89C94628DB5B560D93FA8A78C3FFFE2 +:10AF4000D91025246BA6FD6540F61ABC774D1A80F2 +:10AF5000AB4C7D1EC440A56F6EFB04702F1DE8270F +:10AF60003F8DCBEE3B8241D9E72FD7CA45786F079B +:10AF7000512096C574FAF59CCBDF66FB228B542FCB +:10AF800042E9EB6EE82718BAC207643FC7E4529E55 +:10AF9000A98D1CCF23A9C86226911A7A35CE913982 +:10AFA000C38ED27425CECE49CA055E58B8075982E1 +:10AFB000FB0F80D0152CA9659906554AC6267A82C2 +:10AFC000995B6D84C04562824939BCF01FEA58180C +:10AFD000E1F3D1296629A6A0D273EB9FA00176FCEC +:10AFE000348C2FDDFA3A2CDF1E30E112F41098AFCA +:10AFF000886BE9E0A1F2D2421348F0AAA6D0926D84 +:10B00000FB973D3B16A3699E56369DAA3A5E573B79 +:10B010006FB2D342F1D974EE07A729F42C4FA8A53B +:10B020005B37067A55E51D0858CF30EEC9E7258015 +:10B030004EF1C62E302F51D37FF9EF222C3A949E39 +:10B040008FCD020C0851E30904E01725AF8A3E12A8 +:10B050001118A9E7B7BEB2B878496976A13409CE0C +:10B06000C57F753C0712656D57DA422AE5B678460A +:10B07000DE809609493010C342D151CD321C3ABF0F +:10B0800074FE171DAE764D100798371A5290D0C82F +:10B09000EC1992586182456FEA76F352A77548B26F +:10B0A000C0C3BB25D69CF1EEEA90FB2BDD864BA2FC +:10B0B000A1EA4F8720B127C837498ADCAD0281B8A1 +:10B0C000E494C6E4567F7A4730DA1FEF682BEA280B +:10B0D00027753547ED027029136BF1375C63AB863A +:10B0E000474E031A261E0E51711B17B9B352022781 +:10B0F000F41CDCF496C5BC61929A59A94F58F2EB46 +:10B10000B427279B321E08C9E458DC601BACCE6311 +:10B11000CAA0DD9DBA2E071FE2DEA60EDFC6986D1F +:10B120007674A18257E45634FBBD4B9E2E32627C6E +:10B130006030386CCF962A5DCB9715D6CC2B3C0867 +:10B14000BA0490E302CDB204E08B86F193F4C79485 +:10B15000D4B88E41382388707C16523F4D758DDBF4 +:10B16000EBA5F4109C7E65F6136D6DABBC1413E774 +:10B17000EF7CA63021CEFF0C6035C00985ECEDFDDB +:10B1800022B19EF1EE9634F74A65189465DE150AF1 +:10B190007277386D50FDD3447A1B016DD1370E3D67 +:10B1A000D421F3938144568B180205F928AB8F19EB +:10B1B00061BB3F01200A0E0C820BCB546F4D42E164 +:10B1C0005D78DD2F96DB2FDE678AA948CE3A82258F +:10B1D0007331676150F2B35A4B6E1C8979EE3E0CA5 +:10B1E0007A53E9D695B450BCA9209A49AD1A619614 +:10B1F00080F04C1991FED7453959153FD239E7EA0D +:10B20000E3B22A063BA6812FC5D14A43C4268EB796 +:10B21000FA6D728B13A9F076CD4CB78709F0527690 +:10B2200033393B384A4D65F709850E5B929ECEF85F +:10B2300008E6D7FDE3EAEB625F8A0F9E4CB7227AFD +:10B2400047F04198CA0DD405AAAAB4A4D91A6FCF61 +:10B250001827683AEBBE5E486DD58A4CB3BB04D65E +:10B26000042D119879928D2AA96484B14AB04EFEBA +:10B27000298F5DD4C08D7629AEE5B61BB2FF4FE6AF +:10B28000E36D78CCAD93C3859098A25FD68B54655F +:10B29000F1D4510982A6D0B3022826F1B2EBCE53E5 +:10B2A000F84D2A413F3B64FB6035ADCEF388ABEEF1 +:10B2B000F11CFE432F6F9D3C0D49C9CD497336D615 +:10B2C0002B7A14C6A74D222FB54827BEF456153247 +:10B2D0004FBE6ABB51A57DA57FEF4A179B035AE677 +:10B2E00020221793E6EF2E4D2E0A26491089348628 +:10B2F0009A7B8DBEA8A62A788D3C7BA73235DCB31D +:10B30000D86560A7D71AD18261916818C50159F92B +:10B310003B6B3927DAA0753134CE9D6CE24B8C2E15 +:10B32000605CF48E309AABE928A8E10D049CB2D0A1 +:10B33000EA32CD725F5B0F66449D73019AE8DCD7F9 +:10B34000D7BD98C40A002D291DB092EB6821D80101 +:10B350001ED3F0CBF72082CC12DE58BECC6ED6CEF8 +:10B36000E242BCF7090FD7408A55A3003E1034FDD6 +:10B37000874A91849F537ABAF3D8AB33229DE80A67 +:10B38000A80D4AA1231186485A075DFE3026865E25 +:10B3900048CFFA5A264C43A97A75A9645A4B72973A +:10B3A00045694BF6FD1119C5E746FF5F1B2C79393E +:10B3B000D739F361B98FC16F27AFABC441124A03CC +:10B3C0009B089B650B15429DCA84731D34D6D6FA23 +:10B3D0006A422CF2245D120FEB9813FCFF7816C41E +:10B3E00012B1D7D7DD06B7E63F3CE3B1CB59B18CFC +:10B3F0002697E16093C3F01B8BE274458954C23BEE +:10B400008815F42DB5FE6979DEA1104DA793E32FC1 +:10B4100079FB714AA3C3A1FED351204CAAA2A4F97F +:10B420005DD530E1DE706FEC96B45EDD9CFCD356EA +:10B4300006239F8A4F7A465B024B7BC673DCE70686 +:10B4400082D711F5E7D91F096CE358B67B45F39213 +:10B4500087911BF1F828C2632DC223A01B44233E11 +:10B460005C7085FAA27297DCAC7DC2C6520F0C6E7E +:10B4700058C2D29FB96B0F92928F2F3E668176C6CB +:10B480008A149C06A9199605FDF1BECC5D2039F001 +:10B4900049092017DAA5F6A7D46A5E6D59CC0E6E5D +:10B4A000F92E06A4CFC38D348EB30073ACFF10F910 +:10B4B000EE7FDAD44C644E6C4FEA159FF7A89F29B3 +:10B4C00034E976781BFF2DB48B36E0D18167D59BAC +:10B4D0002F6C6A81F43F5601510618D4FCEED092CD +:10B4E000413F5D9E0CCAA782688980F1E37282B3F6 +:10B4F0005A88938FD659CD83A975C0905CFFDEAC76 +:10B500000CE504D4A82BB31452FB8943A650B82CE5 +:10B510002CBB993B08304E7ABDB8A5A425E15C024E +:10B52000EF2C568C4F4DF8194C426D299E7F27EA1F +:10B5300074CFAFD1196B51647D4D02126BB4D36CD3 +:10B540002FC13A53664B0F2CBC62D10BF74A3C20FB +:10B550008A77611FEAB777D6B64E44B6F31A2960E8 +:10B560004E9944FA9F9D5F5231E80B21D545FC541A +:10B57000BACF75DA8B21595C6BC980AA04E2527F7D +:10B58000B27070954AE7A0465DD1A482DD7507DDF3 +:10B590003182F35F34C48458C717FC2C099B2ED624 +:10B5A0003D03660472E7B0356FBC4194E51222504A +:10B5B00008BED9906575B325848AF2681481DA6A69 +:10B5C0003C63C8F2986F4BC468C3252384732E4331 +:10B5D000810D666556FD761970DDFEE096091DB099 +:10B5E000A3224B34740CB1009462CA4EE9152CC7E7 +:10B5F00045829D7E1FC5798175FE2E762A247CBCEE +:10B600001A1121F017ED5125D2DA0B4E44FEED232D +:10B61000EF4C70F014E2C43B6DD379637FD82A9469 +:10B620003E0BA3D8B53D4942966EE30D85DFE56D2F +:10B63000B6B905496A2B3E7C3DE27A39BB1C11E65E +:10B64000A0B29E1004D34FBB01A4176FD2FCD48EBE +:10B6500018899F4A37999E5B26BBEFAEF28DC106D3 +:10B660000BA44745A69F48135EA2826A25266F65F4 +:10B6700004B429D8CF8812B7E34F100DE2DFECAB4A +:10B6800041A5A34811C22B1456559A7D564BBFBEF7 +:10B69000790B63257F969B7F6D93BEB9624713D26A +:10B6A0001C035D3EF8C10D59454C995AF6675B463F +:10B6B000372CCF46D922B7CF91FBE4461637E45654 +:10B6C0006711411D8B10A50B1E9EEEC8D1F8FC57CB +:10B6D0001E1C01C1480E054CF1CBDD9392E45AC407 +:10B6E000B2B16AC7659F22EA23C12307B44B4E5605 +:10B6F00081F6D2C34B0AEA3D8EA67BF7BDBBA7738A +:10B700001EEE245DC1EDBACB3F56D511CDE9678A57 +:10B71000C31496150F201A09F26DCD5C5FF34FA28A +:10B72000FBA6CEC113242FC7BA635A6DEF225E5415 +:10B730005F615B42F367533DE13EC47C645ED2DCF3 +:10B74000E1BFE582913C2A44B3CAC0635E220BBFCD +:10B750008A7E1FEA1F2B7C413DBE838E8D03CD9FC9 +:10B76000F21FD8303F27E805B3CC5816C64EE9D1B2 +:10B7700067972745217415F67C9BF65BFD74A3CE75 +:10B78000FD6EFFAC662A478E790E4021B019993CB8 +:10B790007F3BAD60D26CB4B629680B87E1F8624E8E +:10B7A000470021AFCD90E07444AD824EB0766A2F51 +:10B7B0001F03CBDD1ECD2A7199FD429ADD1B395D39 +:10B7C0003A6BA80297F560F736C20FEE869DBD3240 +:10B7D00001C73572F16F7042F0DF9616312925836B +:10B7E0001368254B39DBA258C95D2538FAEB0241B5 +:10B7F0008208CA436DE606A24C14A7A3AD3F127699 +:10B80000DB4920F4C3A06BB7002D26F8145409DAE5 +:10B81000BC6614402A4EF7F0159C485A63C9D553AC +:10B820007D33CFCF1DAC8CA4D391EC725925883ACF +:10B830008F4252EE0D7333ACD2105762A7917791BD +:10B84000C194A6E390487B3494C57CC6C1F5342FDF +:10B85000C207D956759527B0325F4CD1E3CD05EFBD +:10B860003B72B054312518A78AFBD5EC712934C33B +:10B87000C56EEBA9EB2D0B61292CEEB2A7C7716247 +:10B880002C4213F6B5EFB40F308A60C1D2BA7408F7 +:10B890008A89FD35A35062D0F702C36D18B63FAD5B +:10B8A000EF3F6C0B2E544959E7AC29D8AF9573DFA5 +:10B8B000F1410A4FFF919B6D4BCDAC1F1294DF8C71 +:10B8C000E99CE527C93B90BE2B965A98556DE7F148 +:10B8D000238C8CF060109284AE571C955EFCDFD7F1 +:10B8E000ADB66EFF39B0A29AA57D81D474783FFAC7 +:10B8F0002C4634A535C6DAC839FE5764802C30583A +:10B90000CD1B3BE549B2CE0C00E56E03BA3A2F9C45 +:10B9100079AB08015261287B94B6B6A29A9E13CEE9 +:10B92000ADC4A0A9CF048BCA106C45E647C5525DD3 +:10B93000163EAB07523F6FFA3A3FE84CBF339604CE +:10B94000A40187B43A4F333A32B193F2E7CF75D2BC +:10B95000F9BC556C41D16779FF628748C167B5BCB6 +:10B960000856F80C54AA7DDA79F7593226C6083EF3 +:10B9700002D4378D5D013F7DAA3B08BF30B618D198 +:10B98000A971360DDD0A5B9906DACB0029B551E0C5 +:10B99000F97CE545CC1321216DAA3F33BA7814D840 +:10B9A00093A7BFFCB264D51ADAC82B5E2BBE2E213A +:10B9B000070136894C410326BA4D50F7108ED34308 +:10B9C0006962857CFBB891D3C5310E126E3FCC08FD +:10B9D00015FBF39D52469BA80F3B1D63EB79308B03 +:10B9E000062B854CD6047D4B18FF65C20BDF683FE4 +:10B9F00075864E31DCD48D8660D94D277C44A350AA +:10BA0000E47AA5E5BD5818AC32CC76A5A78789762F +:10BA1000FD5AA9F9313DD5C86FBC0E1E58997B4B14 +:10BA20007A97C6E594D329E423BFDFFF6C9B893F57 +:10BA3000886FB148CEA2E4F39A41D98D3367CB73B6 +:10BA4000BD141043B76F6C76D436AC9E5E22D77FA0 +:10BA5000D349DF3198B0F03C444F909F4F440F16CC +:10BA60007BC6F461BA18339E71556C4C048A8518F4 +:10BA7000AED1B6770E8FF378B4C85496AA0EBBB386 +:10BA80006C3C67EA62D35230104D7C64177957AD35 +:10BA9000D8F064914066472267303C278BA25680DD +:10BAA000D4AF9E9C7DFD69CB7557637EADF40D7B55 +:10BAB000E8DE4AAFF5E61263CA77A92C12C33D79D6 +:10BAC00049A1D7E4AF3A9341BD9D42B2A95F4DB7BA +:10BAD000AAFC6A7645BD19BBE303136FFB3AFF2747 +:10BAE0005C298867F8D4A3F22837A64D206B47E27B +:10BAF0006D5A769F917248D9EBD4EFEAAA32BF16FD +:10BB0000F43E2699B23A7918F7C9C85793EEFCAEBD +:10BB10009F19A392A970F8DF109EDC920A4567DC9A +:10BB20006BC1D7E171C19FC289DF20EFA2D4830628 +:10BB3000683B386259956B2A765EE299ECB86C4E98 +:10BB40007A8C38CADC698FC1F05D8DF4811833CEF0 +:10BB5000C41801FF74D4E6A11574DA8628A40AC4B7 +:10BB60009A633C1C6B25D55B6873EFBE566D8F479F +:10BB7000AC97D7E734DBE3332EC4CE105B2BDBE985 +:10BB8000E4515A683278667F9BAE77D59E3F1DBBE5 +:10BB900052BF4B5064871ACA3CAD0ADA37E3EA5702 +:10BBA000B95B8239D286DE29917A29F92A1421B823 +:10BBB00048B5FA11B871DC222BC1335D1A5F4DC054 +:10BBC0006F6E9AAD4C1BDADB7A216469BFD14CD918 +:10BBD000668C581636283BE59B4828A8E48721A5A3 +:10BBE000FD6114CD9D9F6CB3F13910A5D3C436BE51 +:10BBF0004E970A772733EF3E89F867E71EF3C63979 +:10BC00005FADC35BE0252DFCCD4BE0CD51591EF857 +:10BC10001F8DB621820B9C432639E7EE06A4D11B6B +:10BC2000EF95C7BD5DB2D9B8C7C1554FFDE5DC1C66 +:10BC3000E3E9B7B728BB34BEFC5F3E78CBD2E8FC63 +:10BC4000D45D127CB0E185E1EE7166892009B52BE7 +:10BC5000AAD85925D8FD51A5520B2E4F661634503F +:10BC6000AD0FDD5021B7E773369337E2EF48E8B404 +:10BC70001F6646E3D29D233A59072A2ADF46F5D0AC +:10BC8000419CBC491E867E17732E0F5FBD2E2A076E +:10BC9000985A89BB3DE34AA70A52F663C219DDC828 +:10BCA000759D7E3F20DA6670BE3E24D5F345C33FC6 +:10BCB00069AE66BAE14291009462E8F8000BDC21BB +:10BCC000616A738B25DB8798051C669E3DFD13CB4F +:10BCD000D38F1A7BAA8AC6C09AA09F2EE1C6FF27DF +:10BCE00084A14BAA0F8E0BE702FCA2F47DD2802523 +:10BCF0005D18DF1421356A2589BB816D7750C60038 +:10BD0000DDD1F20E99942994B10FC4F53CD391E79B +:10BD1000D848539C833B7B24BD18D0BE08BFF18A12 +:10BD2000444409D46E3D504C85465306F4DDD36C33 +:10BD3000031F8C4F2DEBF2A9E9C1DFD28CC4A0EA1E +:10BD40006013CE96AE8165DFBB3572E355EC7BC2E6 +:10BD5000B0CEB0025AE7D23540502C765D9A842D91 +:10BD600025877377F605316E7887C16F6C490FFFB1 +:10BD7000CF99EE1BB01D86D2330C753A8BAB89B5CB +:10BD800080979B46FCAA4F59F3D43560DB7D961211 +:10BD90008E9C23149FC7E01275FDE80471F311DE39 +:10BDA00075F6EBF3BFDCE882CDBB0F522C63723823 +:10BDB000E42B825E2E547403F080688D3B83103533 +:10BDC0007BFC0F0C2E5CFE8A94BA35FDE516F52639 +:10BDD0004DDAA88506123B3B7818F56763F728DA39 +:10BDE000A842268F5D27A70102B11E49F2DDBFA937 +:10BDF0006E84F1F5A173E9D18358017B78F11BC5FD +:10BE0000CA95F1BC344A54981A62D9C726E21E4931 +:10BE1000FB43C0813E84591BEEE29B5B327F55B1F0 +:10BE200011791D3AB74F23056038DE5C0731FDA557 +:10BE3000D0D3281E451004CA664D0302F89940E786 +:10BE4000DD2845165BE9F6BF5EDB04446D0935DA93 +:10BE5000A45603C43A57B64C689FA11BFC2DEAC7F1 +:10BE600031CCACF3F8E4680778E3996C89017F96EC +:10BE7000D22F372ACCD5E31538077899869884E6EF +:10BE8000FA80DE6BAB09ADA196DD0A5413898FBA37 +:10BE900008F66986B3A68C86B0C675B0F551ADE6D6 +:10BEA00099DD6CC7D6C27FB226DBB6729D219F1585 +:10BEB00096F4A4B877AAAAB8D96F60B9F093CF5F07 +:10BEC0009A213E28E2D1CD41FE3D15167B91973354 +:10BED000AFC41489179607F5A897A8A0410FFB7A5D +:10BEE000BD0E6E345C88D574E120056809D5567B9B +:10BEF000A1353E85BAFEFBF2614A6B633E925471F6 +:10BF0000D4ED22D678698524B4019CF00D13E17C30 +:10BF100029E73F94DE81F733E9BE0272BED7B42130 +:10BF20001D8797C590E6576B8D0A3A5F085ED45B14 +:10BF30004FFA2CB9054BEF13324E63412656429A05 +:10BF400055793B639B2ECC040D606FC026E8E9D089 +:10BF5000983A798654E20C931966DCB2CD25774184 +:10BF6000ADD6033EE2628710DB301A688583ADA64A +:10BF70004DE36A1B749BAF837B10B8FA468C23E5B4 +:10BF800077DE0C77C1E302CA1710CF1F68FF3CB9F8 +:10BF9000E8A2B7E3DED0164DD5AF6EA2389CD90823 +:10BFA0004BA686D404D917427E5E4C89767FAFA01B +:10BFB000E6CAE37D02EEDF6C489A240CF2A5EA069D +:10BFC000877A219CC5A76D111C356E632F08DBCBCA +:10BFD000B84595261052E4C2358212F2652BCA226A +:10BFE00085C8910992826836533D5666AF6A2C4DDA +:10BFF0006C791F6F587B2531DBBA4E16006538C24D +:10C00000C7F0A7676AA3653FAF35FA3B95D8995D3E +:10C010001FE472EE547628AD5BB403E156FA20D2E9 +:10C02000EFFAFF0F69B7B22F2DCF02BB1FB430A0BC +:10C0300065028BD749EBC12286B136230514F63E43 +:10C0400030C95A2262BC2FD8990BBF15F87C696F92 +:10C0500089E4BC07B27F4EC0874833BC006C0FB385 +:10C060003AE79551CFD4678D982DA1D9869EFEBE13 +:10C0700051963CD3F94640280C11C356FA4C071C84 +:10C080000AE1C094901A7B34115155DBE264A7ACED +:10C090006848F14BCE48E637670FC99CA941367A0C +:10C0A00025073F532C05577D548BBDA48D4B34D5AC +:10C0B00011899FD4274BB861A0448CF79A33B850AC +:10C0C0003CBF9F0782BBDF9B42347D3B0F899E9420 +:10C0D00084B1A771C585434802C1665ABF930CF667 +:10C0E0003BB4E49BDDC243D20114CC63C02117638F +:10C0F00096107E3462F1BE15E50DF7352EFFC4F7BC +:10C100004B042AB7DA9D435F94091103D8BB6CF442 +:10C11000533ADF8002E25B881EDD0F00228583FE3A +:10C1200070928F19191090330A8BA3DDE2B92E9704 +:10C13000815DEB4A9F6114952E8C0517A560E07810 +:10C14000A4C6AC070CD95E8D0B3D984B602A058DBB +:10C150009D1506C0D3092F33BD38E9CBCE8A5D3D8E +:10C160000244291AAD6C65599241130A85B42741DE +:10C17000B00F4FA25F98FAE2B2773F87D11B11FE52 +:10C18000B8991CACB5BD65C4E5035A1A9001B56BEE +:10C190003A44382E4A3CC2C9DFA281D6167112AC8D +:10C1A00094E2DB1C50049DF4EC66BAED6832DB4D82 +:10C1B00015459B0750204105905100CA94CF0DBFF3 +:10C1C000A95F91B7D69E94833A583D89DEBDC58F4D +:10C1D00076DF1683481CD34FB5254994997F6EE5C9 +:10C1E000C5BF624FD0213F51BF9970707C761B2034 +:10C1F000A424AC7D2DD91B448960E02BA494C843B2 +:10C200003DF423712F3B4432A1E59FA7B7508336FD +:10C21000D14449EBA46327A40FA99877EDF5A2C2F6 +:10C2200041020EFACCA6BCFD54D688D80107CE2216 +:10C2300020E4B53C6F64EA94ED337C54511F03064F +:10C24000FE0B69ABB138CACC03D8877569B4E46317 +:10C25000D02E122F4B4C1B94D6CAC7436316F064E2 +:10C260001DEA66CE6425677081A2BAF606C3D20EB7 +:10C270009CDF6383B514E5500FA3D862B9852EF116 +:10C28000912E2C6EAD985B7992C722F725344F49D9 +:10C29000960277BFF0079AB3F20F1B49967AE85BD4 +:10C2A000E70425007FF67811032005CC9A9DB53967 +:10C2B00073680487B5BACDC6C82C0C26D843CF24E2 +:10C2C000D852519994E2FAE68FEC9FB6DBBAD202CB +:10C2D00091CBCC3B6B766663F99A974D8B70693A3C +:10C2E00014C4C00CB9F10557F4CFEC5C799232E577 +:10C2F00052AD9642EF6F4375EA09031CEF349C522E +:10C30000D1C8EFA58FBF4CC456FDBAA331500F0260 +:10C31000DDB146AF2871CEB32429C138DED3440F36 +:10C32000A76025C9B7B324AFCCB364CECC1EAC365E +:10C33000D476302490A763F881F8E039D95C1CB733 +:10C340009834B6009A40470A35E3298EDE56171115 +:10C350001C20D3742535C2D3A702C003948760B9CB +:10C3600022C8DB0232B8CBB080D10522FCF86426AB +:10C37000D3CEEA7BD45964F471506712B939D8D45A +:10C38000001D80A94BBC8C61711ECE79DF1871CB6A +:10C390001A675C93A07B3A8A082EBC500AC9A18A0E +:10C3A000AF5AA535DB55BB83DB0BF029751350E184 +:10C3B00005D8B09CEE4198747A634C49C353C2359A +:10C3C000B59C198DB090E1B84C73CED19695D8300C +:10C3D00071888E569190A2F1FDB08DE67541ED2ADF +:10C3E0003B21F319A71C463DA779F6793C38AB8C65 +:10C3F0000EA4A1D0489C2410F763B67C1B8C6BF272 +:10C4000055BFFD473CE64CC17A98FCD02B63F8DE63 +:10C41000043773B1D2743CEB75DFCE63115929FB3D +:10C42000D4E3362D92D73BDDA6E18ABC7460CC1EE6 +:10C430002E2E6C257CD56FF65EFA054FCC95FA2131 +:10C44000A58A54611E412F08415476AB5F92E3B434 +:10C4500053B761C530C32F8A158B7228680D1D86AE +:10C4600041213F818AB11DFE3C40056F8EFF1C902B +:10C4700051C11EF78CC4A135F24467D8BCC869838A +:10C48000D85EAF6C3DE20AD989E1A6361F8196F3EA +:10C49000464A9EF7CEE7C969680DCCFDE48A9D3413 +:10C4A000420B8DA65429F584FC44D4EF00748B3DD7 +:10C4B000085DD8D4A4D54A6DC20295A7D86ABAC37C +:10C4C000CE38972C994662FCDA302173BC498B2513 +:10C4D000BF5EED4042D0F69120940D6B8881234FD2 +:10C4E0004E040D921D4F3C012AFE6F4F6282ADFF3C +:10C4F0004501479FA39B81900A2D69260FBAD5AEAF +:10C5000069805E770BCDC6735C40390A20007DAA36 +:10C51000D009541EC124DA9C2A547653F92407EA20 +:10C52000D124C2D407BE65F0C8A4FAC98CA43BF5D7 +:10C530004A4BB1261291EA1196BC0E2B8E4CD61B9B +:10C5400028FBE03DFBA910D1B12BC43A9929D116A3 +:10C55000B744685F53459D5F645DAA047E5DBC116E +:10C560004F43D9CD2C123501924F2811E74A0FD7EE +:10C570008ACD40876B2288B67D289FED6A39F35DAE +:10C58000D5015C6A2589A4EC99E9E7E26816FD1DEE +:10C5900081739B710A15DF0EF3EAFEB9FFFA0D569F +:10C5A0001F0F076D9526A20FBE5D30F3B3D04394E5 +:10C5B000EEC34A28D6BEE53951AEA83261702B4B86 +:10C5C000F6774AB54D1D4F4EE5F839A29CAC25C310 +:10C5D000B47B07A3C9384571C6460BB74624A328C8 +:10C5E000A0433F2B4029CEFB2748CBD1E1793663CE +:10C5F00049B5FEEDEDFF9908645628702ED97E628C +:10C60000A6AD6A5E7E4691184F3692D4288B02D82A +:10C61000752DF0AC721247F5DE67A08C91C941CF41 +:10C6200035482B1D057DF8969C948AF77EC62B0114 +:10C630008F584C9F1D734A616DFA053A111FAFDA8E +:10C64000F7E21FB3C8845A548047438BC70F715514 +:10C65000AE3BC8F1A1F3190ED6AD6E3243C66FA43E +:10C66000A77EF868704EEBC18C93C2E8BE38DF72CB +:10C67000DEBF6F8FA1FFEFD1DA403C870B4A7EF718 +:10C680004A8A18657D82D5318AEE7D377BFB94F925 +:10C6900064FC2A22F6BEFABDF0314084571D85594C +:10C6A000C086FB7C539540C4DAFB394D1BC59C3DCD +:10C6B0001E6906DB5E9B4EC776477181DD093668D1 +:10C6C000C9640EBE63EE883E83820BD4610E707225 +:10C6D0000FF8E96D70E4C200730D2CA8C306DC44AA +:10C6E00063992ECE56F215D8F127F48D8E7774AC5F +:10C6F000D3C353222F94F8AC88D5B088D88BB473A9 +:10C7000089A95ED86BBC958AC4FD8317417D200D35 +:10C710003413B2440FE89DC00C7FCFE60039683374 +:10C720003743B6312628795C8E00874241F512A541 +:10C730005AFF6641C2071D538407768C419CB12B7A +:10C740002E1FA3002FFA9F8C8BE5D7241DD92FBA5B +:10C7500086D5CEE839769525A39E4BB48F1F1C2C29 +:10C76000C46C826560692C33063A715FEEE072FC3E +:10C77000BEF2FDC619CFA1FEBBB66EC095CF2F1578 +:10C78000659BF7B9F296D226AA3737411326CDE733 +:10C79000C81FBA28A85A6F3F5EA351D938840076C3 +:10C7A0002153998467EF8F3CB48281AE503EEC3ABE +:10C7B0005FC36ED11BCAF0FC9BB1BA5F9AF24F5CAB +:10C7C000B926AE4B40C9E22D0E19DF4B98803EB41E +:10C7D0007B04B17A0F92F68DADAE6EBB6C53B36A2B +:10C7E0009683F34FD68DC387EE5AFC734157E30708 +:10C7F0009761571C0AFECB4F9D05B0B4154D4744B9 +:10C80000E8D5580582C74CA50AC011268146EC9090 +:10C810003834D7B413E4C8ABE38F59A36DC2116D9C +:10C820005801FB527DB0604A6008FA7B0E527D626F +:10C83000123CB0CE23B4FA53F8D6851EEE72EA1538 +:10C84000D66094F2D2D45B2B5FACB0D35DB840EC31 +:10C8500076221830B4B8B654393CD513CCACF5F0C8 +:10C86000B483B8E9C70D167C14CA8FC68AD1403389 +:10C87000C3A0A59FC6C07E32FA67E7F81F4DA43556 +:10C88000CC9BBEDC4243F95FD56D44F62E58E55B88 +:10C89000CA5CFE3BB6B4AA21AE442562FE608F316D +:10C8A00091865F74C5BC4AF6A3EB7AFE0945D9A808 +:10C8B000D212540E79D9A5E395AD8B308DB07B346F +:10C8C000CE48A37EB289E4516FAFD77832BB97BA16 +:10C8D0004483E469FE22DD382F7C53C7695E75B955 +:10C8E000392BAF6E9D328741C3918F06FA38137F83 +:10C8F0000E80C218F654C8B4A7B8A1B7877F22B873 +:10C9000087D787071024C024C200AEA0F0984EE855 +:10C910009D0F8FB1B3D3AD3FAC26B642A0148D515D +:10C92000D3160FCDBE72C714798719EEC8D89B8570 +:10C93000A4E1096E2A90177CE4A0261A26D90B36AA +:10C9400063C370209A0238AE08B15EE3D80ACBFD0B +:10C950002D8F3C1854BFC689F7BC8E0A272CA435EE +:10C96000C1360DB8082C0469458F12E6C7F0CD0515 +:10C970004A55175199999219A7FEC8A7A5B9BB9B0B +:10C9800068DCF807BAF6452F58FB8463AFC4DA7742 +:10C99000DDDEA0FEB515DAC14458C8F682CEA5FA90 +:10C9A0009C9586EEB0F856EEBD198286F4C6E14D30 +:10C9B000E0F2DD86113AA386637957A239B813DB1A +:10C9C000F78316B11A1A95BDFE9AA2B87744AA8DBC +:10C9D000CBFC04738DA241EAA0484FA0D0F347C11D +:10C9E0002F347CD338435480954933D3B1CD996DDE +:10C9F000A18D7DFA9C99A2223EB5891C3FC32D686A +:10CA0000890834C0167C923AE40192986EF113249E +:10CA1000B7E02C5F1713C587CCCBF6159AFBCDF189 +:10CA2000B414FB4AE2C3405600AAEB272CFD6C3439 +:10CA300036129722EA67981A64F7FEFF4B03347C9C +:10CA400028D44AC6AAF72E3BA5C19B2CAE8A072440 +:10CA5000BFB0A6DA51A1C6A8249592C4FD3B1A83A3 +:10CA6000AC69C0244010AC236BBBC0BD5011504F0B +:10CA70006D129CD1EB7AA92F18A994FA6A4E8A45B7 +:10CA8000C01DD62CC8451CCB6B37BDC2364FE92A1A +:10CA90001EE60F44C8AEC0DDCDBC0DDCDE5F6268B3 +:10CAA0005C41584ED4115E120565365D4D1A9EFDEF +:10CAB000C5D29BA287342A0B228E9551F5AF06D59D +:10CAC0007F69C053FFB7F57AE1F24CF094D9D7A94A +:10CAD0004869888B401F49293380CCA202F8EDF0C9 +:10CAE000A4C9F75E5DCFB5D58024A0BAB760DF4B8F +:10CAF000A44619E2478983E40095CADEE2772F1540 +:10CB0000C2F41FBF0E5A9A96F09875219D35A4FA6B +:10CB1000997B787B34828675206D9FA612F45B1614 +:10CB2000D9E144931AF690F69A6ED85FC8C1041DF5 +:10CB30009C7466E168AD51D5EAA16526928B78A018 +:10CB400050766EBBB648C0B66C7F64D5FE7F61C3BD +:10CB50003AF86370C831276EB0B433BFDD0DDBC364 +:10CB6000E591FCE08E4629F3FD5DF016E8CB76A951 +:10CB70002E3EEC1C327DF6FCAC4AAD26F03E6BAB93 +:10CB8000746D44F3A6E5B1E8D86993B64BEE828C98 +:10CB900046B96E05A2E343D6DDDA6D19B9DD80270B +:10CBA0007346B557780D7DF7E283BD6E4CF785EB84 +:10CBB00063AD921030F435672BAD0F3CACB6BCF4CE +:10CBC000DA79A901BA1717272FFA27B3B2328A0BDD +:10CBD0003D18ED560ADA896065FB02C66F169A9118 +:10CBE000D576CD1BD433309173458FC88C15CF6C5F +:10CBF000E9C78728ECE9EADBFA1A8BF8647666E77E +:10CC000005D8D949FD8E36C163F5E9FBA88CA51A74 +:10CC10000D63226CAE31F4E90CE8D2D7115D1AF73E +:10CC20008763CE78AE89E921F3A53F8AA09B9188DE +:10CC30005646AD0E24ADE68A8C91DF3E6AE883E568 +:10CC400007F47A8047D1B8129D929EE3247B4E0C64 +:10CC5000C9BF9FD224505CF41868F709DA30CA695A +:10CC60006FD01067876626C611225ADC4E8631CCFB +:10CC700057DEF189C3EA21900D3C39CE3F4F516810 +:10CC800066B23E63E405E5121C12D45F03BE51C0D8 +:10CC9000368094947CB9E53AD9C4D864C7FC70ABAB +:10CCA00026E56317D1776F93D77067F96E9E58901A +:10CCB0007767E0842B47AD9943DB5D1196EC87BB2A +:10CCC000DBCDD05666E97ACF48BBC7144D6B10CA8E +:10CCD0009BB9A4D1DF3AAC609EC8AD63624FB26627 +:10CCE00070F89FC155E50DD7B61916963354B6C7DF +:10CCF000A11D692299BA9E2C98704146C0EAE49021 +:10CD000023B5CB9732E9CC3124AD7F758909DB8C13 +:10CD1000D6689A0AE5043D6F4788F4C022D22923D9 +:10CD2000A8D8DF5CCC14CEE47C6F5273E79C8C15E2 +:10CD300091AC9D446CA8C35760B482E39DE5D64C8A +:10CD400048F2418FA9F014633353EB6D7F6EE3F526 +:10CD5000E7AF4ECB9E6E920709E78C058F62782F66 +:10CD60007A34D351F28A7BE537203343C53F51DF14 +:10CD70002DB8EDB6577DF84C546A81C2A357D82A16 +:10CD80000F6AC954289FA47D68C9609D48B8FD9F5B +:10CD9000A6D0C638A3380BF3F714D8A504DD3BF7AB +:10CDA0007CCA9F7C01C0365DB0D96CBC681F9EFBFD +:10CDB000F920377643AF32BECD19620490A4073D07 +:10CDC000B3CB4142EFEB38492EEE53C48CB202286C +:10CDD000397642F90A5424D55F67A171E1C1095738 +:10CDE000C752639BAC4A7942F682806580B644F7AD +:10CDF000136FA96087ADA0C802E566A05816212B65 +:10CE000021D11623A2F777CEF3D91394FBD0966DD8 +:10CE100046CBBDBE67289FBB21F339903BE05CA5A4 +:10CE2000DE7F3F2B1549E8115D9F85E66603406B69 +:10CE3000A5E14B1EB397FB9CE97330A86D8ACD3BEF +:10CE4000762AD1C8487D2A58032FB98B686644B129 +:10CE50002BE015BE7F17B8C34BC63EE4A03B3A5546 +:10CE6000E8865BF476E5056025ED481D23CE8290CB +:10CE7000ED52D17753E50E28FF89BCC85D9DD7F3ED +:10CE800084FC069924221FB885478C20AA72B49B83 +:10CE900071D8E82BF31C57417408A476CD82C9C021 +:10CEA000F175762BCC2EC51D842BF1A4DCCEB3B747 +:10CEB000F0ABAAD369C2A1A40036244D89AE7F9EEF +:10CEC000F47E240858D1318DD7E5EA6E673A2F11E8 +:10CED0009369C5D21146258D475B2681DD19F5BBC7 +:10CEE0009E5830A4814CF8A0CB93DF291EBAF17A6A +:10CEF000C0D67D87D5A115BE1E672DEB1A13C6B30C +:10CF00000B2BBA267B4D29AA6097452A51988A0592 +:10CF1000EECDF6BBBB50E870C8D12B4CCC40FB8D9E +:10CF200006CFA610534B4D9F4C75017E04CE25278E +:10CF300034C3E826F14BBED9876C758F1C7AA8B430 +:10CF4000F14446982856BF7D61C7D6DF84CB5E602A +:10CF500071DA93CC005B544F3F26EAFB23845B4E8F +:10CF6000DF7B26DAD6B45355C127B62BD4C179BEA0 +:10CF7000D28BFC11101A4C8C91C456E6851C9EA4D1 +:10CF8000AE5B59DDB14941CE6526E5EFE86899B859 +:10CF900038B66CFC2510700506BA74FE0AABC2499F +:10CFA0009BF6BABC490378DDB9E220451342206BF9 +:10CFB00095AD7A7BD3AD6D2A2ED0C79DD9DF6FD6C4 +:10CFC000B22A156070E4DFF94E9E6B84E6DC62E203 +:10CFD000CC24E04D5F57A49372C70A0F45B7764340 +:10CFE000E5ABDD3AA54DFE0EFBB206996424D68C66 +:10CFF0007DE8BCBEA60631429F6E3EF20A85D9533B +:10D0000044EBBC8CE97E8EF46D2766C68E0D754FA1 +:10D01000DEB5BC41B1AAC75E676C3CB8E2E50F055E +:10D02000CDD97C66766BDE658057D45D6F447BED31 +:10D03000EF30222A2643160A6736AFC1571A5F051A +:10D0400071896429746C9D1B086879037FC34C6FD8 +:10D050002800169AEFB11EE868F89C22C535D9D68B +:10D06000A5569E4E52BFA522EA5FC9BF317F0D4B28 +:10D07000F42703581B3A8DF18B086CEB11863E1296 +:10D080008AEF98ABDA95258F1345F29EF9DAD357DC +:10D09000FD2D05B0444241CF19F96FD05B99198439 +:10D0A0001B500A5566A40596CA69EEAAD09683FC61 +:10D0B000F12DC86F59A2DF84BD157E240F2219C738 +:10D0C0005ACEC0A8516FFE323834B2CC7C7C0AA84C +:10D0D000D3862D2060E9AF5FA121D4E2DF23E94EA2 +:10D0E000F01DEEA4D88916E95F582B96F0D65A4861 +:10D0F000ECD00615597DF79AFF40A0A00BDCB27C5E +:10D10000F000005300070119C80E37046F087B3C7C +:10D110000A440000000020121E05BD0D3303263214 +:10D12000FE2CFFA8DEA8DE4616045A00301019387F +:10D13000140A1AAE07CC00CC4C46004C000080010B +:10D14000012626808000000466100010144028018B +:10D150001E6648FD00401C2D00C800C8006F03A7D4 +:10D160000764960001010001000000050A000000AC +:10D170006400DE0332002003F9000100FF032800F1 +:10D180000F042800470828000F0428004708282813 +:10D19000010A3C0105733C7801050303010001020B +:10D1A000005802011B0000FF91059001BFFF66D0EF +:10D1B0000700000000000E000000BCFF3535000035 +:10D1C0000000002001D007FFFF0C0C0F0F00D0075C +:10D1D0000101000E000E00000B00000000000E0018 +:10D1E00000000014000000008000000000000000AB +:10D1F000000000800000000000000000000080002F +:10D20000000000000000000000800000000000009E +:10D2100000000000831C001C00000B0000000082C6 +:10D2200019001900001C0000000081160016000003 +:10D230002F0000000080000000000000000000003F +:10D2400080000000000000000000008000000000DE +:10D2500000000000000000000000000000000000CE +:10D2600000000000000000000000000000000000BE +:10D2700000000000000000000000000000000000AE +:10D28000000000000000000000000000000000009E +:10D2900000000000000084000A023C00146405093C +:10D2A0000F0011004B0000800080001C1F40000098 +:10D2B00003000800080000001F1E1D1C1B1A19187F +:10D2C00017161514131211100F0E0D0C0B0A090866 +:10D2D0000706050403020100000102030405060716 +:10D2E00008001000100010001000100010001000C6 +:10D2F00010019908070605040302010002730030BB +:10D3000080730030813232191932761000000437F0 +:10D3100000000000043700000000086F001E00003D +:10D32000086F001E003C003E0019003200321E193A +:10D330008066CD0214CCA00178001B5A0AC8023CBA +:10D3400000000000000000000000000000000000DD +:10D3500000000000000000000000000000000000CD +:10D3600000000000000000000000000000000000BD +:10D3700000000000000000000000000000000000AD +:10D38000000000000000000000000000000000009D +:10D39000000000000000000000000000000000008D +:10D3A000000000000000000000000000000000007D +:10D3B000000000000000000000000000000000006D +:10D3C000000000000000000000000000000000005D +:10D3D000000000000000000000000000000000004D +:10D3E000000000000000000000000000000000003D +:10D3F000000000000000000000000000000000002D +:10D40000000000000000000000000000000000001C +:10D41000000000000000000000000000000000000C +:10D4200000000000000000000000000000000000FC +:10D4300000000000000000000000000000000000EC +:10D4400000000000000000000000000000000000DC +:10D4500000000000000000000000000000000000CC +:10D4600000000000000000000000000000000000BC +:10D4700000000000000000000000000000000000AC +:10D48000000000000000000000000000000000009C +:10D49000000000000000000000000000000000008C +:10D4A000000000000000000000000000000000007C +:10D4B000000000000000000000000000000000006C +:10D4C000000000000000000000000000000000005C +:10D4D000000000000000000000000000000000004C +:10D4E000000000000000000000000000000000003C +:10D4F000000000000000000000000000000000002C +:10D50000000000000000000000000000000000001B +:10D51000000000000000000000000000000000000B +:10D5200000000000000000000000000000000000FB +:10D5300000000000000000000000000000000000EB +:10D5400000000000000000000000000000000000DB +:10D5500000000000000000000000000000000000CB +:10D5600000000000000000000000000000000000BB +:10D5700000000000000000000000000000000000AB +:10D58000000000000000000000000000000000009B +:10D59000000000000000000000000000000000008B +:10D5A000000000000000000000000000000000007B +:10D5B000000000000000000000000000000000006B +:10D5C000000000000000000000000000000000005B +:10D5D000000000000000000000000000000000004B +:10D5E000000000000000000000000000000000003B +:10D5F000000000000000000000000000000000002B +:10D60000000000000000000000000000000000001A +:10D61000000000000000000000000000000000000A +:10D6200000000000000000000000000000000000FA +:10D6300000000000000000000000000000000000EA +:10D6400000000000000000000000000000000000DA +:10D6500000000000000000000000000000000000CA +:10D6600000000000000000000000000000000000BA +:10D6700000000000000000000000000000000000AA +:10D68000000000000000000000000000000000009A +:10D69000000000000000000000000000000000008A +:10D6A000000000000000000000000000000000007A +:10D6B000000000000000000000000000000000006A +:10D6C000000000000000000000000000000000005A +:10D6D000000000000000000000000000000000004A +:10D6E000000000000000000000000000000000003A +:10D6F000000000000000000000000000000000002A +:10D700000000000000000000000000000000000019 +:10D710000000000000000000000000000000000009 +:10D7200000000000000000000000000000000000F9 +:10D7300000000000000000000000000000000000E9 +:10D7400000000000000000000000000000000000D9 +:10D7500000000000000000000000000000000000C9 +:10D7600000000000000000000000000000000000B9 +:10D7700000000000000000000000000000000000A9 +:10D780000000000000000000000000000000000099 +:10D790000000000000000000000000000000000089 +:10D7A0000000000000000000000000000000000079 +:10D7B0000000000000000000000000000000000069 +:10D7C0000000000000000000000000000000000059 +:10D7D0000000000000000000000000000000000049 +:10D7E0000000000000000000000000000000000039 +:10D7F0000000000000000000000000000000000029 +:10D800000000000000000000000000000000000018 +:10D810000000000000000000000000000000000008 +:10D8200000000000000000000000000000000000F8 +:10D8300000000000000000000000000000000000E8 +:10D8400000000000000000000000000000000000D8 +:10D8500000000000000000000000000000000000C8 +:10D8600000000000000000000000000000000000B8 +:10D8700000000000000000000000000000000000A8 +:10D880000000000000000000000000000000000098 +:10D890000000000000000000000000000000000088 +:10D8A0000000000000000000000000000000000078 +:10D8B0000000000000000000000000000000000068 +:10D8C0000000000000000000000000000000000058 +:10D8D0000000000000000000000000000000000048 +:10D8E0000000000000000000000000000000000038 +:10D8F0000000000000000000000000000000000028 +:10D900000000000000000000000000000000000017 +:10D910000000000000000000000000000000000007 +:10D9200000000000000000000000000000000000F7 +:10D9300000000000000000000000000000000000E7 +:10D9400000000000000000000000000000000000D7 +:10D9500000000000000000000000000000000000C7 +:10D9600000000000000000000000000000000000B7 +:10D9700000000000000000000000000000000000A7 +:10D980000000000000000000000000000000000097 +:10D990000000000000000000000000000000000087 +:10D9A0000000000000000000000000000000000077 +:10D9B0000000000000000000000000000000000067 +:10D9C0000000000000000000000000000000000057 +:10D9D0000000000000000000000000000000000047 +:10D9E0000000000000000000000000000000000037 +:10D9F0000000000000000000000000000000000027 +:10DA00000000000000000000000000000000000016 +:10DA10000000000000000000000000000000000006 +:10DA200000000000000000000000000000000000F6 +:10DA300000000000000000000000000000000000E6 +:10DA400000000000000000000000000000000000D6 +:10DA500000000000000000000000000000000000C6 +:10DA600000000000000000000000000000000000B6 +:10DA700000000000000000000000000000000000A6 +:10DA80000000000000000000000000000000000096 +:10DA90000000000000000000000000000000000086 +:10DAA0000000000000000000000000000000000076 +:10DAB0000000000000000000000000000000000066 +:10DAC0000000000000000000000000000000000056 +:10DAD0000000000000000000000000000000000046 +:10DAE0000000000000000000000000000000000036 +:10DAF0000000000000000000000000000000000026 +:10DB00000000000000000000000000000000000015 +:10DB10000000000000000000000000000000000005 +:10DB200000000000000000000000000000000000F5 +:10DB300000000000000000000000000000000000E5 +:10DB400000000000000000000000000000000000D5 +:10DB500000000000000000000000000000000000C5 +:10DB600000000000000000000000000000000000B5 +:10DB700000000000000000000000000000000000A5 +:10DB80000000000000000000000000000000000095 +:10DB90000000000000000000000000000000000085 +:10DBA0000000000000000000000000000000000075 +:10DBB0000000000000000000000000000000000065 +:10DBC0000000000000000000000000000000000055 +:10DBD0000000000000000000000000000000000045 +:10DBE0000000000000000000000000000000000035 +:10DBF0000000000000000000000000000000000025 +:10DC00000000000000000000000000000000000014 +:10DC10000000000000000000000000000000000004 +:10DC200000000000000000000000000000000000F4 +:10DC300000000000000000000000000000000000E4 +:10DC400000000000000000000000000000000000D4 +:10DC500000000000000000000000000000000000C4 +:10DC600000000000000000000000000000000000B4 +:10DC700000000000000000000000000000000000A4 +:10DC80000000000000000000000000000000000094 +:10DC90000000000000000000000000000000000084 +:10DCA0000000000000000000000000000000000074 +:10DCB0000000000000000000000000000000000064 +:10DCC0000000000000000000000000000000000054 +:10DCD0000000000000000000000000000000000044 +:10DCE0000000000000000000000000000000000034 +:10DCF0000000000000000000000000000000000024 +:10DD00000000000000000000000000000000000013 +:10DD10000000000000000000000000000000000003 +:10DD200000000000000000000000000000000000F3 +:10DD300000000000000000000000000000000000E3 +:10DD400000000000000000000000000000000000D3 +:10DD500000000000000000000000000000000000C3 +:10DD600000000000000000000000000000000000B3 +:10DD700000000000000000000000000000000000A3 +:10DD80000000000000000000000000000000000093 +:10DD90000000000000000000000000000000000083 +:10DDA0000000000000000000000000000000000073 +:10DDB0000000000000000000000000000000000063 +:10DDC0000000000000000000000000000000000053 +:10DDD0000000000000000000000000000000000043 +:10DDE0000000000000000000000000000000000033 +:10DDF0000000000000000000000000000000000023 +:10DE00000000000000000000000000000000000012 +:10DE10000000000000000000000000000000000002 +:10DE200000000000000000000000000000000000F2 +:10DE300000000000000000000000000000000000E2 +:10DE400000000000000000000000000000000000D2 +:10DE500000000000000000000000000000000000C2 +:10DE600000000000000000000000000000000000B2 +:10DE700000000000000000000000000000000000A2 +:10DE80000000000000000000000000000000000092 +:10DE90000000000000000000000000000000000082 +:10DEA0000000000000000000000000000000000072 +:10DEB0000000000000000000000000000000000062 +:10DEC0000000000000000000000000000000000052 +:10DED0000000000000000000000000000000000042 +:10DEE0000000000000000000000000000000000032 +:10DEF0000000000000000000000000000000000022 +:10DF00000000000000000000000000000000000011 +:10DF10000000000000000000000000000000000001 +:10DF200000000000000000000000000000000000F1 +:10DF300000000000000000000000000000000000E1 +:10DF400000000000000000000000000000000000D1 +:10DF500000000000000000000000000000000000C1 +:10DF600000000000000000000000000000000000B1 +:10DF700000000000000000000000000000000000A1 +:10DF80000000000000000000000000000000000091 +:10DF90000000000000000000000000000000000081 +:10DFA0000000000000000000000000000000000071 +:10DFB0000000000000000000000000000000000061 +:10DFC0000000000000000000000000000000000051 +:10DFD0000000000000000000000000000000000041 +:10DFE0000000000000000000000000000000000031 +:10DFF0000000000000000000000000000000000021 +:10E000000000000000000000000000000000000010 +:10E010000000000000000000000000000000000000 +:10E0200000000000000000000000000000000000F0 +:10E0300000000000000000000000000000000000E0 +:10E0400000000000000000000000000000000000D0 +:10E0500000000000000000000000000000000000C0 +:10E0600000000000000000000000000000000000B0 +:10E0700000000000000000000000000000000000A0 +:10E080000000000000000000000000000000000090 +:10E090000000000000000000000000000000000080 +:10E0A0000000000000000000000000000000000070 +:10E0B0000000000000000000000000000000000060 +:10E0C0000000000000000000000000000000000050 +:10E0D0000000000000000000000000000000000040 +:10E0E0000000000000000000000000000000000030 +:10E0F00000000000000000000000000083314A938F +:10E10000010100010100000000000000000000000B +:10E1100000000000000000000000000000000000FF +:10E1200000000000000000000000000000000000EF +:10E1300000000000000000000000000000000000DF +:10E1400000000000000000000000000000000000CF +:10E1500000000000000000000000000000000000BF +:10E1600000000000000000000000000000000000AF +:10E17000000000000000000000000000000000009F +:10E18000000000000000000000000000000000008F +:10E19000000000000000000000000000000000007F +:10E1A000000000000000000000000000000000006F +:10E1B000000000000000000000000000000000005F +:10E1C000000000000000000000000000000000004F +:10E1D000000000000000000000000000000000003F +:10E1E000000000000000000000000000000000002F +:10E1F000000000000000000000000000000000001F +:10E20000000000000000000000FFFFFFFF001F01F2 +:10E210000A1E0E371E10015100010105640001FFA6 +:10E220000301730103020056A700B0700101010150 +:10E23000F001000000000000000045373030000011 +:10E240000000000029030F00030000000304270161 +:10E250000A290E05075025030000000000000000F9 +:10E2600000000000000000000000000000000000AE +:10E27000000000000000000000000000000000009E +:10E28000000000000000000000000000000000008E +:10E29000000000000000000000000000000000007E +:10E2A000000000000000000000000000000000006E +:10E2B000000000000000000000000000000000005E +:10E2C000000000000000000000000000000000004E +:10E2D000000000000000000000000000004C0013DF +:10E2E0000601122F260D0401012700090021340028 +:10E2F000000000000000000000000000000000001E +:10E3000000000000000000000000000000005802B3 +:10E31000011B0000FFAA059001BFFF66D0070000A7 +:10E320000000000E000000BCFF35350000000000BA +:10E3300020010CD00100008402A6094B801C1F00A4 +:10E340000300201244941102003A00064044C841E0 +:10E35000E8FB0C0C844C168007808088108080803D +:10E3600080808080868080828080808080818080A4 +:10E370008008000000000000000000000000000015 +:10E38000000000000000000000000000000000008D +:10E39000000000000000000000000000000000007D +:10E3A000000000000000000000000000000000006D +:10E3B000000000000000000000000000000000005D +:10E3C000000000000000000000000000000000004D +:10E3D000000000000000000000000000000000003D +:10E3E00000000000000000000042410D0001540048 +:10E3F000000000000000000000000000000000001D +:10E40000001F0000000108002009838180808080B7 +:10E41000C00100000000000000000000000000003B +:10E4200000000000000000000000000000000000EC +:10E4300000000000000000000000000000000000DC +:10E4400000000000000000000000000000000000CC +:10E4500000000000000000000000000000000000BC +:10E4600000000000000000000000000000000000AC +:10E47000000000000000000000000000000000009C +:10E48000000000000000000000000000000000008C +:10E49000000000000000000000000000000000007C +:10E4A000000000000000000000000000000000006C +:10E4B000000000000000000000000000000000005C +:10E4C000000000000000000000000000000000004C +:10E4D000000000000000000000000000000000003C +:10E4E00000000000000000000008070000015500C7 +:10E4F000000000000000000000000000000000001C +:10E50000027300308073003081282828283276106A +:10E510000000043700000000043700000000086F0E +:10E52000001E0000086F001E003C003E0019003273 +:10E5300000B432148066CD0214CCA0047800B46418 +:10E540001E9623A008004400000000000000000008 +:10E5500000000000000000000000000000000000BB +:10E5600000000000000000000000000000000000AB +:10E57000000000000000000000000000000000009B +:10E58000000000000000000000000000000000008B +:10E59000000000000000000000000000000000007B +:10E5A000000000000000000000000000000000006B +:10E5B000000000000000000000000000000000005B +:10E5C000000000000000000000000000000000004B +:10E5D000000000000000000000000000000000003B +:10E5E0000000000000000000004400000040510056 +:10E5F000000000000000000000000000000000001B +:10E6000087D8ACE500100000010101100000A60D44 +:10E6100000000000D2040204D20402040000000042 +:10E6200000000000000000000000000000000000EA +:10E6300000000000000000000000000000000000DA +:10E6400000000000000000000000000000000000CA +:10E6500000000000D20402040000000000000000DE +:10E6600000000000000000000000000000000000AA +:10E67000000000000000000000000000000000009A +:10E68000000000000000000000000000000000008A +:10E69000000000000000000000000000000000007A +:10E6A000000000000000000000000000000000006A +:10E6B000000000000000000000000000000000005A +:10E6C000000000000000000000000000000000004A +:10E6D000000000000000000000000000000000003A +:10E6E000000000000000000000000000000000002A +:10E6F000000000000000000000000000000000001A +:10E700000000000000000000000000000000000009 +:10E7100000000000000000000000000000000000F9 +:10E7200000000000000000000000000000000000E9 +:10E7300000000000000000000000000000000000D9 +:10E7400000000000000000000000000000000000C9 +:10E7500000000000000000000000000000000000B9 +:10E7600000000000000000000000000000000000A9 +:10E770000000000000000000000000000000000099 +:10E780000000000000000000000000000000000089 +:10E790000000000000000000000000000000000079 +:10E7A0000000000000000000000000000000000069 +:10E7B0000000000000000000000000000000000059 +:10E7C0000000000000000000000000000000000049 +:10E7D0000000000000000000000000000000000039 +:10E7E0000000000000000000000000000000000029 +:10E7F0000000000000000000000000000000000019 +:10E800000000000000000000000000000000000008 +:10E8100000000000000000000000000000000000F8 +:10E8200000000000000000000000000000000000E8 +:10E8300000000000000000000000000000000000D8 +:10E8400000000000000000000000000000000000C8 +:10E8500000000000000000000000000000000000B8 +:10E8600000000000000000000000000000000000A8 +:10E870000000000000000000000000000000000098 +:10E880000000000000000000000000000000000088 +:10E890000000000000000000000000000000000078 +:10E8A0000000000000000000000000000000000068 +:10E8B0000000000000000000000000000000000058 +:10E8C0000000000000000000000000000000000048 +:10E8D0000000000000000000000000000000000038 +:10E8E0000000000000000000000000000000000028 +:10E8F0000000000000000000000000000000000018 +:10E900000000000000000000000000000000000007 +:10E9100000000000000000000000000000000000F7 +:10E9200000000000000000000000000000000000E7 +:10E9300000000000000000000000000000000000D7 +:10E9400000000000000000000000000000000000C7 +:10E9500000000000000000000000000000000000B7 +:10E9600000000000000000000000000000000000A7 +:10E970000000000000000000000000000000000097 +:10E980000000000000000000000000000000000087 +:10E990000000000000000000000000000000000077 +:10E9A0000000000000000000000000000000000067 +:10E9B0000000000000000000000000000000000057 +:10E9C0000000000000000000000000000000000047 +:10E9D0000000000000000000000000000000000037 +:10E9E0000000000000000000000000000000000027 +:10E9F0000000000000000000000000000000000017 +:10EA00000000000000000000000000000000000006 +:10EA10000000EDE00000F7E03100F8E00000F9E070 +:10EA20000600FFE000000FE1330010E15B0011E1A0 +:10EA3000810012E1120013E1000018E1570019E112 +:10EA40003D001AE119001BE11E001CE10A001DE156 +:10EA500050001EE1500038E16F0039E13D003AE11D +:10EA600028003BE13C003CE114003DE1C8003EE1F0 +:10EA7000C80058E1B50059E133005AE141005BE1BB +:10EA800064005CE123005DE1A0005EE1A00078E1AC +:10EA9000140079E1140088E1370089E1320098E13F +:10EAA000640099E13200A8E10400F0E1000030E2E6 +:10EAB000840031E2400032E2100033E2FF0034E231 +:10EAC000860035E2A50036E2D80037E2280038E2B9 +:10EAD000F60039E2FF003AE25F003BE2E9003CE287 +:10EAE00094003DE211003EE2C2003FE2280040E215 +:10EAF000270041E2AD0042E2FF0043E27F0044E232 +:10EB00004B0045E2040046E2530047E20B0048E2B6 +:10EB1000DC0049E20F004AE210004BE210004CE238 +:10EB200010004DE210004EE210004FE2100050E2E3 +:10EB3000100051E2100052E2400053E2020054E2A1 +:10EB4000620055E2010056E2060057E2020058E278 +:10EB5000000059E200005AE201005BE200005CE2C2 +:10EB600001005DE200005EE200005FE2000070E292 +:10EB7000010071E2F80072E2700073E2080074E2D2 +:10EB8000640075E2040076E20C0077E2100078E29F +:10EB9000000079E208007AE230007BE200007CE2CB +:10EBA00000007DE200007EE200007FE2000080E2E3 +:10EBB000000081E2000082E2000083E2280084E29B +:10EBC000000085E2000086E2000087E20000B0E27B +:10EBD0008600B1E25800B2E26500B3E28600B4E21A +:10EBE0005000B5E20000B6E20000B7E20000B8E273 +:10EBF0000000B9E20000BAE24100BBE2B400BCE2AE +:10EC00001B00BDE20000BEE20000BFE24600C0E221 +:10EC10001400C1E26100C2E20000C3E20000C4E2ED +:10EC20000100C5E20100C6E20300C7E22800C8E215 +:10EC30000000C9E20100CAE20000CBE20100CCE220 +:10EC40000000CDE20000CEE21500CFE20000D0E2ED +:10EC50001500D1E20000D2E22C00D3E20100D4E2A0 +:10EC60000000D5E20000D6E20000D7E20000D8E2C2 +:10EC70000000D9E20000DAE20000DBE20000DCE2A2 +:10EC80000000DDE20000DEE20000DFE20000E0E282 +:10EC90002A00E1E20000E2E22A00E3E20000E4E20E +:10ECA0005A00E5E20200E6E20000E7E20000E8E2E6 +:10ECB0000000E9E20000EAE20000EBE20000ECE222 +:10ECC0000800EDE20000F0E27000F1E20000F2E284 +:10ECD0000000F3E20000F4E21100F5E21100F6E2B8 +:10ECE0000000F7E20000F8E20000F9E20200FAE2B8 +:10ECF0000400FBE23100FCE20100FDE20000FEE264 +:10ED00000000FFE2000000E3020001E3010002E373 +:10ED1000010003E3010030E3080031E3000032E3C7 +:10ED2000000033E3000034E3000035E3700036E315 +:10ED3000000037E3000070E3440071E3000072E379 +:10ED4000000073E3000074E33D0075E3010076E327 +:10ED50000E0077E3010078E3020079E301007AE333 +:10ED600002007BE301007CE302007DE300007EE320 +:10ED700000007FE3000080E3000081E3000082E305 +:10ED8000100083E3060084E3440085E3000086E38B +:10ED9000470087E35C0088E3000089E300008AE322 +:10EDA00000008BE300008CE300008DE300008EE3A5 +:10EDB00000008FE3000090E3000091E3000092E385 +:10EDC000000093E3000094E3000095E3000096E365 +:10EDD000000097E3000098E3000099E300009AE345 +:10EDE00000009BE300009CE300009DE300009EE325 +:10EDF00000009FE30000A0E30000A1E30000A2E305 +:10EE00000000A3E30000A4E30000A5E30000A6E3E4 +:10EE10000000A7E30000A8E30000A9E30000AAE3C4 +:10EE20000000ABE30000ACE30000ADE30000AEE3A4 +:10EE30000000B0E30000B1E31A00B2E32900B3E33D +:10EE40003C00B4E34B00B5E35700B6E36F00B7E313 +:10EE50007F00B8E38C00B9E39700BAE34900BBE355 +:10EE60005500BCE36300BDE37700BEE38000BFE371 +:10EE70008C00C0E39B00C1E3A600C2E3B200C3E381 +:10EE80000000C4E31A00C5E32900C6E33C00C7E361 +:10EE90004B00C8E35700C9E36F00CAE37F00CBE330 +:10EEA0008C00CCE39700CDE34900CEE35500CFE3DF +:10EEB0006300D0E37700D1E38000D2E38C00D3E39A +:10EEC0009B00D4E3A600D5E3B200F0E30300F1E336 +:10EED0000000F2E30100F3E30100F4E30200F5E3D4 +:10EEE000FE00F6E30000F7E30000F8E3FE00F9E3BC +:10EEF000FF00FAE30200FBE3F300FCE30000FDE3A4 +:10EF00000000FEE30100FFE3FD0000E4010001E476 +:10EF1000EE0002E4000003E4000004E4FF0005E466 +:10EF2000010006E4010007E4F60008E4000009E43B +:10EF300000000AE401000BE4FE000CE403000DE411 +:10EF4000EC000EE400000FE4000010E4010011E406 +:10EF5000FC0012E4FE0013E4FE0014E4000015E4DB +:10EF6000000016E4010017E4010018E4020019E4AF +:10EF7000FE001AE400001BE400001CE4FF001DE496 +:10EF8000FF001EE402001FE4E90020E4000021E489 +:10EF9000000022E4010023E4FE0024E4010025E453 +:10EFA000CD0026E4000030E4000031E4000032E44B +:10EFB000000033E4000034E4000035E4FC0036E4F3 +:10EFC000000037E4000038E4000039E400003AE4CF +:10EFD00000003BE4FC003CE400003DE400003EE4B3 +:10EFE00000003FE4000040E4000041E4FC0042E493 +:10EFF000000070E41C0071E4FC0072E4FC0073E4A7 +:10F00000FC0074E4000075E4000076E4000077E49E +:10F01000000078E4000079E400007AE400007BE47A +:10F0200000007CE400007DE400007EE400007FE45A +:10F03000000080E4000081E4000082E4000083E43A +:10F04000000084E4000085E4000086E4000087E41A +:10F05000000088E4000089E400008AE400008BE4FA +:10F0600000008CE400008DE400008EE400008FE4DA +:10F07000000090E4000091E4000092E4000093E4BA +:10F08000000094E4000095E4000096E4000097E49A +:10F09000000098E4000099E400009AE40000B0E465 +:10F0A000FE00B1E4F100B2E4FF00B3E4F800B4E420 +:10F0B0000700B5E42200B6E40000B7E40000B8E4BD +:10F0C0004000B9E40400BAE41100BBE43000BCE441 +:10F0D0000000BDE40D00BEE40000BFE40000C0E499 +:10F0E0000000C1E40000C2E40000C3E40000C4E486 +:10F0F0000000C5E40000C6E40000C7E40000C8E466 +:10F100000000C9E40000CAE40000F0E42200F1E4D9 +:10F11000000030E51D0031E5000032E5230033E555 +:10F12000000034E5230035E5000036E55C0037E5F6 +:10F13000020038E5BF0039E5BF003AE5E3003BE5F2 +:10F14000E3003CE5AF003DE5AF003EE5E2003FE512 +:10F15000E20040E5010041E5000042E5000043E532 +:10F16000000044E5000045E5000046E5000047E5F5 +:10F17000000048E5000049E500004AE500004BE5D5 +:10F1800000004CE500004DE500004EE500004FE5B5 +:10F19000000050E5000051E5000052E5000053E595 +:10F1A000000054E5000055E5A20070E55D0071E542 +:10F1B000400072E5490073E5530074E5590075E5B8 +:10F1C0005E0076E5630077E5680078E56E0079E536 +:10F1D00074007AE57E007BE58A007CE598007DE599 +:10F1E000A8007EE5BB007FE5D00080E5FF0081E55B +:10F1F000040082E5000083E5040084E5040085E561 +:10F20000420086E5000087E5690088E55A00B0E520 +:10F210004800B1E51D00F0E56600F1E55400F2E5B7 +:10F22000D900F3E53100F4E50100F5E51000F6E55D +:10F230001000F7E51000F8E51900F9E51900FAE506 +:10F240000000FBE50000FCE50000FDE50000FEE538 +:10F250000000FFE5000000E6000001E66D0002E6A8 +:10F26000650030E60000B0E61B00B1E63B00B2E608 +:10F27000BB00B3E67700B4E67700B5E67700B6E604 +:10F28000BB00B7E6B300B8E63300B9E60000BAE663 +:10F290000000BBE66E00BCE66F00BDE6D300BEE634 +:10F2A000D300BFE63300C0E6BB00C1E6F200C2E611 +:10F2B000FD00C3E6C600C4E60B0030E7030031E7FB +:10F2C000000032E7000037E7010038E7000039E7C7 +:10F2D000000070E7C100B0E70600B1E7FF00B2E749 +:10F2E0000300B3E70500B4E74100B5E72400B6E743 +:10F2F0008000B7E71F00B8E7C700B9E71F00BAE70B +:10F300001B00BBE70000BCE70C00BDE70700BEE741 +:10F310002000BFE70000C0E70000C1E70000C2E72F +:10F320000000C3E70000C4E70C00C5E7F000C6E733 +:10F330001F00C7E70000C8E70C00C9E70000CAE7E4 +:10F340000000CBE7AA00CCE76700CDE77E00CEE760 +:10F350001D00CFE70600D0E7000030E8000031E8EC +:10F360003E0032E8140033E83F0034E8070035E897 +:10F37000770036E8020073E8300074E8060075E8AC +:10F38000230076E8650093E8000094E8300095E8F3 +:10F39000F90096E8500073EB1F0073EC410074EC29 +:10F3A000510075EC000073EE000074EE000075EE85 +:10F3B0000000EDE00300000000000000000000007D +:10F3C000000000000000000000000000000000003D +:10F3D000000000000000000000000000000000002D +:10F3E000000000000000000000000000000000001D +:10F3F000000000000000000000000000000000000D +:10F4000000000000000000000000000000000000FC +:10F4100000000000000000000000000000000000EC +:10F4200000000000000000000000000000000000DC +:10F4300000000000000000000000000000000000CC +:10F4400000000000000000000000000000000000BC +:10F4500000000000000000000000000000000000AC +:10F46000000000000000000000000000000000009C +:10F47000000000000000000000000000000000008C +:10F48000000000000000000000000000000000007C +:10F49000000000000000000000000000000000006C +:10F4A000000000000000000000000000000000005C +:10F4B000000000000000000000000000000000004C +:10F4C000000000000000000000000000000000003C +:10F4D000000000000000000000000000000000002C +:10F4E000000000000000000000000000000000001C +:10F4F000000000000000000000000000000000000C +:10F5000000000000000000000000000000000000FB +:10F5100000000000000000000000000000000000EB +:10F5200000000000000000000000000000000000DB +:10F5300000000000000000000000000000000000CB +:10F5400000000000000000000000000000000000BB +:10F5500000000000000000000000000000000000AB +:10F56000000000000000000000000000000000009B +:10F57000000000000000000000000000000000008B +:10F58000000000000000000000000000000000007B +:10F59000000000000000000000000000000000006B +:10F5A000000000000000000000000000000000005B +:10F5B000000000000000000000000000000000004B +:10F5C000000000000000000000000000000000003B +:10F5D000000000000000000000000000000000002B +:10F5E000000000000000000000000000000000001B +:10F5F000000000000000000000000000000000000B +:00000001FF diff --git a/firmware/synaptics/startup_fw_update_lansi.img.ihex b/firmware/synaptics/startup_fw_update_lansi.img.ihex new file mode 100644 index 0000000000000..f44f0754dbfb7 --- /dev/null +++ b/firmware/synaptics/startup_fw_update_lansi.img.ihex @@ -0,0 +1,8034 @@ +:100000007A8FBF9E0000030600B0010000100000C0 +:1000100030584537303000000000D6100100000095 +:1000200000010000002000000021000000B00100DD +:10003000445335205231322E352E3200000000005C +:1000400000E6010000100000B00000000000000009 +:1000500034712A00000000000000000000000000D1 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000080 +:100080000000000000000000000000000000000070 +:10009000493243001D01FF000C0D700000000000FC +:1000A000493243001D01FF000C0D700000000000EC +:1000B0000000000000000000000000000000000040 +:1000C0000000000000000000000000000000000030 +:1000D0000000000000000000000000000000000020 +:1000E0000000000000000000000000000000000010 +:1000F0000000000000000000000000000000000000 +:100100003556E78E8BCCF8F9F717355ACF34CC60DB +:1001100064F91EAE3D758B7757577ADCA8D0A29054 +:1001200022BB43014C0436BD978616DC263B9BCA96 +:10013000CCFF44060C77D1B573312F084C336C6B70 +:100140006A363DE3F3F5D7C8B9254543874B94910B +:1001500097B9B43C3CA720020BB1AF7B0225C9384C +:10016000B3EA9984E0FA8142E620A0B494FEC7D9AC +:10017000B0E6B43F003218C1696166FA6FBF888289 +:10018000AB3EFFF7B592695014C55B7E5BB4457E0C +:10019000ABCDE85D52802A4D1B164417267939B73E +:1001A000E84F12216149C041E28F4F2B7D5C7D9960 +:1001B000BAF422877D2C130FCC11C90D180D37EB23 +:1001C0005DFB20B7DEDFE61CDA53593509114657CF +:1001D000C857E91EDB42DC33BDAD4070CF321C9600 +:1001E00087DDDB9BFD71174A7D91E6EF228C6D6CFC +:1001F00026C537EB72EFC150C59C6E0E4EB7842EEC +:1002000068FECC4780DBDB5F9FEF4D2E734FEA37F4 +:1002100038C4252699CA1D9C511A376EBE8A5AA524 +:10022000942413C80BBD81263F6C94814FFA990C1E +:10023000156E7857D0F589DAD8ACD50363EA52A3A6 +:100240006C0729717ED6D2A58E382E27DBF99E9FAA +:10025000619264A1E7F71DC42D3787489157921426 +:1002600032996E5F56C8016134D2E3929BE7283F12 +:10027000D92AFA6AF430E21CE31A3CE1EB003F08A9 +:100280008DB630F0AA91199B13574FC5641A8A771F +:10029000F92F1A5B9F61C84D6CDC8ED6977715CF0E +:1002A00076894A7049DE292E58ADA82272B9235D9D +:1002B00019556AAF0AC65B69665B8FBECDCA93BD2E +:1002C000B57B70E1DFA1947E363F1DAFFF3898DA31 +:1002D0008AE1329B2DD3878A4688F3C45CE82EB12D +:1002E000D719A3EB915BCD3C6639E4B14E43EEDD0B +:1002F000FE050713AB8CD5531F46B89078E6B6833E +:10030000ABAB165A5637443E54D4460158ACF64E61 +:10031000B27669E4DB64D92E56DA41DA465F91E3BE +:10032000B20184480EB68F9706D7BFD4A8962DE9A0 +:10033000E8957CC5E03794C24044DFF5801001CFDA +:10034000B6F89A8710600361BACFDC2E5A32517723 +:100350000591EC66EE85F935EA7DAE4CB84F4B5809 +:10036000B5E6DE8A866EB6047E0ADF449A35DA7414 +:10037000995C57319E2C18782F2860B2AA72D70248 +:10038000DC6F7B1952F84CA090AC4CCCA6365AEDE1 +:10039000DA65A69C4A05FE7EC0AFD731AB9798D1EF +:1003A00092772C3AF809FD510FB6E5E80FB3E93F13 +:1003B00011D00216EE1772AD22C3E96FD423C555D2 +:1003C0009EC21CB0D477D6293BDD1698044799CE3F +:1003D00091962686B7499E74CAFD6E7BA9D2664C5B +:1003E000468DF1B81C7F6222547252B6615EAA7CBF +:1003F000630EC4D39D637FDD71116432328F7FF44D +:100400003E73B6331370E438F74096973C29A152F7 +:10041000D9E9DCE3BC9A21699729DFF5B052482C71 +:1004200016908B0148C579357FB5DCBAD48F3E6A0A +:10043000D0D6D3E5C32DFADC70B357C01023FC9E91 +:10044000F5F40BE540CFDF460673CD1CFF1972654E +:100450003739C12E12F2F8F412233939F1D93C00A0 +:100460006F4A6078DFB4C145EEEAE4E5E6F459FE90 +:1004700096875F9D080974DF2C3EFA115788086241 +:100480009C483D25B005706EE88B502448E51A2B3A +:100490002414276F9E81F89F999DE76D644C8526F3 +:1004A0008D3756BAF251C701E6A980535C4CCF8212 +:1004B0003008A208F283A7A34DCB7D16AA82B92FDC +:1004C00012AD4B9C5E68E17F03CAE4FC19BEF79550 +:1004D000C57CF664C1A7C2760BB59329A469DABCC2 +:1004E0004000D96FE1BE540A2E16B5EF2F2954EA09 +:1004F00042DEAFADF45BCD3223CF6132A3DEDC1040 +:100500007C90FB37E6E661DCAEA32B07C22BC6145A +:10051000F757190B2392FCF9BA8CD7F1AF5F1F2D57 +:10052000C0C59ADF2913AB5EA5BFD3E682D388ADE1 +:100530005C15FAA20863DF80D60647FB312BAB437C +:10054000806C9EEFCFBBEB8BB406FDE779FBF383AA +:100550002DEB73B7733265A973496372F603E4DC5C +:10056000D70C53F8377E0223345778AEE17FA24090 +:10057000588A0C3A26F558F824F17720914CC1F4AA +:10058000E4D60C4ADD16154E0763EDC13E2A8C2ACF +:10059000989F0714F4818CBF70FFE046136650EDFE +:1005A00098E6902C0498EB2D53DE53607B8DFCD4A1 +:1005B00031A3A62802825B3C9DDDB338D95F6DD0A4 +:1005C0003DEEA56975B19D796BD76C8BE8EA054363 +:1005D000357592332FA2C0798B1326938458E55B2F +:1005E0007DF5B35BC502E124A2C71504C96B63DEC8 +:1005F000AF51FB04E5B4E404ACA5CA5EFD23EBEF08 +:10060000E5C3E23BA0516E9F1BBA3FCD1D3BDC48CA +:100610006E723B8D43A9AEC95EDD3BD9D58C307D72 +:10062000B394A344AC88417BD388AC156A417E76F1 +:10063000CDD618CB8D529EB0865FF8D40B33CE9EAC +:100640003C8F7B0808FDF7CCB27F2740E7CB5E1CD0 +:10065000E5B0E2445515DBD1024DAC936BEF12933C +:10066000EB54086CCD2C3DFFC0B0C23C0BB2EC9DEE +:10067000DA5B77BC97D8BF38A3AFA51878398F025B +:100680002668360985DC6DD9D71C7D69B8498AFD95 +:1006900009BE6439D9F019C81857DBE91A73913CBF +:1006A0006C213CF089EE2842CC75EAE8676C546214 +:1006B000690BA0833AB81B3496521DC47BF3DB92BE +:1006C000B2294604988A871A989DE8C3CF5660528B +:1006D000AAED99ADCE21D7F8C6754DD3A69E690F68 +:1006E000983913107D60994A690B99C0930E4C1785 +:1006F000E78A83545E5834F23EA1D4F8D8B5F0CFDF +:100700001390821CA8DCF6492473309965D2C1FC91 +:1007100099BD5ED41AB312DBB385DA492CE3016DBF +:100720002CB9D8550BF2813EBF4F2233359C360D84 +:10073000A48C8C36D7E9FCE08FBA764D72FC317709 +:1007400067BB14F30AE8CD09A2E72F8E485BDAD421 +:1007500040D12D91BA64F4C03C21E9F504A1325096 +:1007600030AB379ED12437B449DE6EAFEE14132878 +:1007700072CA82F5167F63358C0B05D27C1B57A598 +:10078000EC8532D2695B6FA5C8B7078203736E84AC +:100790006C795F6B710CEB79FB04A5BA1FECB8891F +:1007A000BF3C85AE23CFC8009F8B2999E0131ECA9A +:1007B000A79CD7641223FE5573E1AFB9FB17B1753F +:1007C000E1415FBF328350619D76E200FA8C7C7C10 +:1007D0007132806B832686E0BB70FD627B1CE0D8A3 +:1007E000C5EADD59F70E8F157E2F5A6A64C018A628 +:1007F0001ECA622295C6FE848DEDD3411F6B49E966 +:10080000C9028C32CC59E241C5B881C4A732E85F35 +:10081000641BE4D1AAE694055C8B28671446DC5679 +:10082000C0360BC9B2E818B36BC56EBB9D2C9CCF0C +:100830006C6AEDFAEA1A29490B90DEDF777E1646DC +:10084000D21069A7E60555BC263A6AB6D332638949 +:10085000391A78BEDD642F90777D2FEC99BCEAC5FC +:10086000CB35B53EF9EB7C47732C6012B6B3E73657 +:10087000551E4B0E48D4082A3136E23728C55B4B4B +:10088000E943EA42976B62D0B4E75EDBFB01E0F537 +:1008900074233B1E63B674F62885CCDED351D7D0C3 +:1008A00026CECC60CDAF4486A919A16553E335A807 +:1008B000FADA3BE0D5551B5C547165E5DE5AF0E58C +:1008C000A63D1193C474616C60F00B28A54318CD4C +:1008D00032DBC31CEDAA5E93668F6F294036C2914E +:1008E000370D1C8414D550BD985F744975C6CD3F33 +:1008F00003A600C95703CC217B05CF126B75D7C562 +:10090000966E7374A3D518AD5350048BF907434EFC +:100910005EDEEF9533ACA5EA18F0EE0A2F57B995D5 +:100920003B2AFA6EBC530CD4E9D2E063FF0F49981E +:10093000676AF0DF988DBC28B6B2773F8C003EDB4B +:10094000664D323B89D547C01AF63E824388E01295 +:1009500089E72EDAADD4D6CFFB9162ABE9F5098DEC +:100960006EB371F4D4291165DFD48DBC6D55EEDA08 +:1009700061647894481BA7F7DAD09447CC9A5B79E6 +:10098000D5597B48F770C03C3119F3812418FFCE4C +:10099000A8E3F9DF5F7DFCD766BFED542DC6876401 +:1009A000C000F7276E11501D7C8ECA8FA9CE1D5D29 +:1009B0009974758BD3E2E2C65F4F5CE1D24D72044D +:1009C00081C16D3DF79F5DB0A06DEBD2C6878709F1 +:1009D000B8C000028B43767009ACC1CAE6D2883A2F +:1009E00068DD129F07792580EB30C3DB778BC0551C +:1009F00013329020B600170AB1E5064230980A6417 +:100A00000E1BA16ABC36012919F603A82BAF20BD25 +:100A10001D5F5D404FC638F9B10135788ECC8D0928 +:100A20004395BA0075D798FC8684BEF66625E4CB5C +:100A30004186DD189950FD23E831F61AB025FF3FB5 +:100A4000941322DB2D66BADB37086E0E7991783E5F +:100A5000949216D98FBF76A5973CBEA70131FF7639 +:100A60006E7E52DCC650D81CEB564B0EBE9F8620C5 +:100A70009EF355009005BA7D8AC4E9AB242E20D29E +:100A8000E2DCFE8A8FEE7DA9E91F568E189A468415 +:100A90009F57DD639B356C724109E7CB6CB0D7F58E +:100AA000EBF962A6B9BDFE9E5315F738892C61ADEE +:100AB0003BC240690AE2BEBD7160804080A30B4426 +:100AC0009499A67A6CA44E92AD0A34642DCCBD7074 +:100AD000337427A7DAD45A02737C98A8647DBFCFF9 +:100AE000D5BCDFF41A9692D93B43357FF825445D97 +:100AF00036E084A92E009D0DAFB41666F4E52BCF29 +:100B0000FFE0E038664E3DDE78EB3EA62591CDC88D +:100B100061CFBFE8EEA9B86659E56B125ABA313316 +:100B2000F39F46E8D40B96212CC6B015EB5A8F8D57 +:100B3000A893578CB1FD44DA24497B7BE1BBE904DF +:100B40006C2602EE2DF44EFA1390BEC676247AFE81 +:100B5000EA1AFBFFB681C05A59701BD09DB972B416 +:100B60003277F364489DCCA6818E641A72B85040E7 +:100B7000C029F2F19FBF1F648B7E4FE0D76AED5111 +:100B80004F5B4C5283A6B8654B64B3A0F2FEEB807A +:100B900051A7A9BEA21399605C702E4D81611A3FC6 +:100BA000681DF17C534DF8FDC4C9B9652DB45D5382 +:100BB000314E0A13BFB3B9799F16E8B3FDA3298F4D +:100BC0003733E8A8A2E135B2FE0F4E43E3D1184F08 +:100BD000197E10EC7411E990C9F6B4623D72E238E6 +:100BE0008207FF9F7F401D133D10AD9515C8657DA1 +:100BF0007F1BFE11EEDF87F1445EA2DB7E91472B67 +:100C0000ED91705F3B14C2B3881CD6F361F85CD7DA +:100C1000BCCEAD7D420E9F52B119370770A33A1179 +:100C20005BE3DB041F95FF74641CBC57CE3C1130A2 +:100C3000726B01A670D476A0D5AB65DB3A6A39AA8F +:100C4000331338439EC51EF72982B94F3AEB7C5DBA +:100C5000ABA7E27141C3570E087F89DCC9090EAF0B +:100C60006718625D5DDC8506759377AF6271F42667 +:100C700038869D6587EA60D49C780BAF6BDD660291 +:100C80005611FD2908729AFD9A699E4DED8D06C296 +:100C900047A6C2A03A6791A009EDEB03B69B660593 +:100CA00028CE1BAA4BEC6B659E7D1F532187763C9B +:100CB0001245B5E9142F32C3675ACACED82939CEA6 +:100CC00019C460C0F6687B5359F8C126CEC5D6D585 +:100CD000DED34139536A9FD0F178424474383925C4 +:100CE00074B10F8386A54F366A8545A524B89C0844 +:100CF00018BADE385637F5CA159FDD3B8CAB2FCAC4 +:100D0000BF40796820E8324AA0E57840AE9EDB8794 +:100D10002F91C295CD409C80C1E07D37E53F97F48F +:100D2000891D7371136471D0BADA8FAC90AF6BAB5D +:100D30001A29A1F1A44042A00034D8DCE49463A6AF +:100D40002468C017D03E978E7CB19CCB5977721225 +:100D50006FA73DDE6CDE67D956647C7540C84F2BAB +:100D6000A2F2F4E20F68F87D631D3A8AEC9C867368 +:100D70009C68F89CE21F16FB4B98EBB776F3F68461 +:100D800052D101AA8E28773BC658EE1C399CAE0F73 +:100D9000ECA7F9AE643CE25CB1D37C70689D852B16 +:100DA0006E5530DE1B202AA6BAC16B4B6C964F9E47 +:100DB000987F9905A4807DEF516B9EF8179492C996 +:100DC00000B3CEADA24B9455F4F9F9503E57E0F67E +:100DD0007AF8919288625770E81984EE77CBF39590 +:100DE0000E23E2FDC5E3723763D7CCA98B082F81B0 +:100DF000B46AF6AAC19A2158214986D42D48FCA884 +:100E00008D6105CF63C70BC588DD5BF9FC8CC273B0 +:100E1000B37175BFA89FFCC17B4863C8A65F18C7A4 +:100E20008489708CFCBE07D4BD144BF23D32E1FDC9 +:100E300002DE50D9FA36A1DCDB9E1224B6BAB73FE7 +:100E400098D76E8A0B1FF4C8B2D37752DE07315A97 +:100E50008EBDAA7D06BD03892A45BFE45F3982BDE8 +:100E60005E40F9BAC559C23C9B7E8F8B4F08DF2F7D +:100E7000E23705E4196E65427B57325FFDE58191EB +:100E80002D6575573C47337FC872A154DC8336A368 +:100E90005CBEAC01F4A95E01567C5CC622C08776BC +:100EA0001FEB981A9A370AAD69D0E802A2C1F39BEA +:100EB0002EEF48D24FF50F22ABC4D32DB9087C34A6 +:100EC000AD73A915904BB46F11A220937E5C5F4C5B +:100ED0006DED153B061A47982C77C212016D6C9286 +:100EE0000B85BD936828F6086EEA10B5770DA497B8 +:100EF000033C839CA40A4402359F87E1A9F0554C2A +:100F0000A7DE7453ECFC9812CED807259A156A78A0 +:100F1000ADE0399E2AF5584BBD0D2E71C5AC17AA10 +:100F200046A244D7E12D3CCE32BF8E1ECCC29612D3 +:100F30002E88DB3D0BF3131348EB684580E7D4D1D3 +:100F4000729F510EA70A96AF385347C61A9C76DA9D +:100F5000B9A2CE9DAB8D2C3DE0958CF5F4A2DFC2FD +:100F6000E71BD1F0C9B1F6EF366A5B6801D9991277 +:100F7000A97940F7D5492D47B49792032FE9ABFFE4 +:100F8000C8F319875CB22947F1B7E9AC2B2D97312B +:100F9000A53F366280C18A1A02AEFA5864C2F7DEF3 +:100FA000AC6D65345AC53979CC4FC45846C42AD083 +:100FB000CD5E224F15E788A7731C8C82A86C543D28 +:100FC0007C76298D9B6A3859FB11499F3308F55E61 +:100FD00095BFC6EDD0A2AF1EABE86E6AFE96B6EF27 +:100FE000A5A906B242CA457E3AAA3B0E72B0B177B5 +:100FF00029536683C0F103C1D77ACAC97BB1951C56 +:1010000098B67B7175619DB2CF295C5A7B03EB1951 +:101010006A2328095CC0A3559251021FB13884BAD3 +:10102000627AD846AA93F970E67EAF09316999FFD2 +:10103000455FF8D57AB27348D5D5CC60032DBD9EF7 +:1010400072637F01F86C447ECF901B33BCC90DEFF7 +:10105000FAF9C5E18801369236C255265EAE7B8923 +:1010600092832DCD443BFEE00CB178BCA607EE1E6A +:101070000B13C5821052B75EF183C3472EE7953B31 +:10108000A0952450B7E77CA2426A2B18F8BA16D96B +:1010900030796F878203155EB4D5E8AD0F7D5FCCE4 +:1010A00097F3DFADFE5EE6ACF487465FD4B04289CD +:1010B00091901DC3355BA0C8215A876D4F76E28998 +:1010C000A4A4780210419EF7D360047E975025CDEA +:1010D0002BA6953CD5F8444084E4F5F307034C93E4 +:1010E000E39F60DEABB45AB177F3F231BEAB81ABB4 +:1010F00065CAC5E48EB7B3C5F6D1E30D13D403DAE0 +:101100006E45CF5A03B1AEEE3877221AA5C1F1452C +:101110007FBED61897B63E110078257A533E257FBC +:10112000A78C86B89D04CA466462C92ACCBA5CB949 +:101130001D23226AE3D30D0778D11716FCF431275B +:101140009A9636E5ED79D3CB7BC5B9F41BE7DA0681 +:101150000F33A1A9468F5169479DF1BC0C7A59A163 +:101160000FE7BB84AE7F1DF48A852CF23578D83426 +:101170001A05B3FA4E3A27EB26C8399C5F48042A71 +:10118000BE6AD05635BD1CA381348AE2CD3F65B31B +:101190005FC1607B7E5FF5CBC4FA799933A7B2ACAF +:1011A000D0BC7E1731D0010C193E319D68E6D37753 +:1011B00027F707E4324D99CD5861711502F987BDC3 +:1011C00048CBAA079212A9F45488B041F4F9F23539 +:1011D0006566F66330379F2E5087E1F42D6184B742 +:1011E000C91E5E87DEE09E0B2B03E68AFD6A8C5DDE +:1011F00004228DBA208146479A8991FE4EDC42FD39 +:101200003D67D914CB47ED12056DFCFE7DC3711708 +:10121000BE221059703A8A1760054911DD55DA501F +:10122000056C0D013D9F11F60746E7C499A5062AF6 +:1012300084B7926F5C054E019A8589F0AE4389DDD3 +:1012400086CC44586BFA0D5BAEA3D514C84EAD07DF +:10125000CFF5B61C8AE55568507D587A608E1FBF61 +:10126000351131982748F48B8A179BA9423C6A6E46 +:101270006764E9631CC314526C5B02218C521DC865 +:101280005456A7AA6FD921E8BDC649FF9D350BD694 +:1012900074827AF6DB9F0172FE44FDA06B52F22548 +:1012A0002434AB8A3806E8C3F5ACD1457AD114CEE4 +:1012B000F7E9900FE3A51BC4C49054C4B1CE3251DA +:1012C000949C558CAE39597F64E85BD7EB14E0628F +:1012D000AFCC5A82A7E8014623BBC33D9C9259DBA1 +:1012E0005B35961DAA67106216BAE008500393C7D3 +:1012F000CDFE3CF914BAF26F14C0A84AB2BA8A5CA7 +:1013000001D1715DA7F7D0511A5241C73E81A7554F +:1013100092542C2B1707930FF83015CECC941CDA6F +:101320006B0026C79094C22975FD831C8B1C7FC956 +:1013300077B3653D9D7369F550A750AB55B4632DE8 +:1013400017DD22A9B0E0495EE7ED2D8E81E5E24090 +:101350008B06C4DF983FE1B036EC5968E4E0F84210 +:10136000C40291856DD35DEE20DBDC09C3E86049E2 +:101370001EB6837A99F17F8EF6BB0FD8C5D4C90FFC +:1013800041EA8F97C41BEDB6305A2473B50F0A4D4E +:101390007FF30B1CF6DDE43B0545CBBD8CB0AE0EF8 +:1013A0006BE7F4D2811E6DE23945147B6F9279CAE6 +:1013B000A558BE25EC15D233EBF92281C21D34129B +:1013C000CE287044DD590122F5F74E38FA2B3E1530 +:1013D00063867CA7147BD7D90CE1E41E79246EC602 +:1013E0007C14EFF36643CA251086C199CDD5B002AF +:1013F000214B64C84E877F21A3E0BF6B4DD5847617 +:10140000D43601EB110C6AB7C48A2BBF8633850131 +:101410001AC864721BC1F22BBFEB99F198115020CE +:10142000D26590B2F839667603C323936C7B9FE252 +:10143000FC7082F8D86EECEAC4838A319850F1C807 +:101440008BE3F46F1D6043CF8BEA04952B950C4022 +:101450003964D9A4EDA184D48935432906433D706C +:101460004C64C5D33E0D2EF2ABE9CD9E69F3CA574D +:1014700097103FA738E8A536F8D8AC8599DE8521C6 +:101480003E466510E62560C8973DC2FBF07E7BF6C0 +:10149000F75C7C1058A3A429976CB5318C0BE1FE46 +:1014A000D87CE5BA43194A83E570A4915AD909D981 +:1014B0009A8B364B2FD23B5490EABA8825F8731595 +:1014C0006685F874A9E99CB0AEA6E70D503AAF94D2 +:1014D0001BC8CA9400659FD4AED39E53F8ACC542D6 +:1014E000FC897E32D240C3C62EF2D6E8354C4D057B +:1014F00042A423C9B06F6CD16FF862E999B2774208 +:1015000015873CF675B2E8B0FFBA540ECFA1128130 +:1015100063AB76B97D6977F24ACF7E5857EFAAE67A +:10152000340D968DD84AA2E8FFAFB8137E2FFE186F +:101530004C90E882D2234125B57CDF0DD192610E1B +:101540001592DDD7C7ACE8E0D8AE1F34C12A3444C9 +:10155000473AA1F38E8984C79CB648F5C28223908E +:10156000CD6B4E6DB10884C885D63C0E7B1BF31144 +:1015700066976E1EADB043885E01FD7BD76409C0DF +:101580009BF0CAA7C4CFDBF3993259DF755646B337 +:10159000F8C80D7C01A22BA8444CFDF3844BD0A4C9 +:1015A000DD51A284B0D4154C37239B8511A44C99EE +:1015B000959E2AC0D2107ED4AD00D386CF4E22D2C3 +:1015C0007082F9ACDD420675C89983CD22F34B15C4 +:1015D000BC63FE84BFAC39F2FD7306A29ECF2E0E13 +:1015E00043606C50B817DA29AD74BED8F6A88C7376 +:1015F00005FC1F0FE56A68DBFE774668AB966FA1B6 +:101600002294DC107319FAF639BF00CA4F3E7853A2 +:10161000A9A720399024F41C7CB9A76427CED476DE +:1016200081393F998C3EC493A46A35C1106F05651A +:101630005B1F56594F1B5F3D7C3F28A6B231019A74 +:10164000F1F5B6914DFA60390611DEFD7417286286 +:101650006F2AB2E297E6D839049DB55D58A2113AD7 +:101660009FDB5C9D7757898C70792F52D4712F0541 +:1016700048E0F9EA0F9A5A3A36A897371EC13F62F6 +:101680006A30A8E012997510FD4BE50639BCDB7293 +:10169000B926861412B0292A3FD3DCD7ECFC132FCD +:1016A000C3BB06A0BE8B8B85E9FC09BA7165A58911 +:1016B000D5DD65A5279A7CAD378C8FDE3DCED98BE5 +:1016C000921C8E92A297EDB79F506FC00C50910C58 +:1016D00014FCF76101866C5522BB4EADABD8DE63BE +:1016E00018155A69903FDA67060B4026513A735E27 +:1016F000CF03BD5A5AFB3B3CBDE6317A1907F4D003 +:10170000E4496A0693FB6B5ADF4A35F0352C386A98 +:10171000FCF95D91C2B2F50CB91C5B3213834B8F9F +:101720008A075EB2B2880BC1A334F5FA63D339E9F4 +:10173000696ED74C903A70E478C3FF4DF26869E166 +:101740001BA9FB2B5D4B4D01D72C3D4D5F81C6AED8 +:10175000CDD4A417FA337DFA5555C171B03226E8BD +:1017600038DAE43C9606A91CB53AB51D5192E5B0AD +:10177000ABF4D5165F81929C22DCD2C5D1AD7A370D +:101780000C5AD392C418FB7914B60D68E756155855 +:101790001F516AD35A9A53B92A492F808DE780FA8C +:1017A0008A62C46FE312CC9300481536E83CD9DF57 +:1017B00069951DC6BC4378FE04EF1F9C243F87BD7E +:1017C00008A92113F653E8862A11BEB94E1F9B0FB4 +:1017D00023CC653DF7DC8D81C08F72A78B631651DA +:1017E000EB0B046BE620C04C829621C0A0BF0929F8 +:1017F0009C7A81ED1328ACD88E6C38D532409DCCC4 +:101800002217D37CF7BD5F3201DD302515D39AD383 +:101810007BC12242293417CB66FE44A9816EF6DCD7 +:10182000FAAC18AD703212E832ADD2BEE4C52F0862 +:10183000834DAB7CEBB850031D87642717390277C3 +:1018400061136481414E0896992BB64F50A83F1101 +:10185000C44B8E07EBA52B52248607781AC6555920 +:10186000FD40C88E8021795F0C27217DEB15E0615A +:10187000ACF5BF59E1EA138288CBB728EA59EE8C60 +:1018800018B5F467D5ABE9347666E794AE6335876F +:101890009DE91C0F5030FEFA9B4F5A9DD0978F1137 +:1018A000DA50913972234DB3FA8A33DB34602867FA +:1018B0008AFBD2FB354FCFABBAD6C75B7B4A1ADA6D +:1018C000B372482A4249E1333CBF204FBD60D5A1E5 +:1018D000F70BECD858070FEA45F2A29B9228B324E5 +:1018E00025BEB332470897BB9AB7491A6552E11F24 +:1018F00060B36D343D499F0FCC8CC6B3B2C3376C17 +:101900001B628B2ABC2744AC087C54B994C443E8BE +:1019100043F124FC6BCE3CC4C1159314D6327483BE +:101920006967CC4C71DA2C99773B8AE12B9EE77C76 +:101930002383C22F4F9A35FE283CCC9CF63F91B5AD +:101940009109CA273B35FD66D78864BB62CD0E3E40 +:101950004A1AB9070B69933AA8872741F1CB312F6F +:10196000B754ED48912C1F08D5DC6B0D1808EA47D9 +:10197000900E1CAB3E5073F01E5833D626A5B957B7 +:10198000E999F2E3EC6D1B740FF587E70B9856C8E5 +:10199000B0BA3AE28674089C93E87E528841326677 +:1019A0005A2D0425E7B4F22374730AB106C500D991 +:1019B000D109875CD4CCBC846777CA0EA186A6FE09 +:1019C000AACCCA35944B7EA758F41031A588B689A5 +:1019D0000ACE641BE614BCF7638F695CB7118D00F7 +:1019E000FC45B63D0D9D2BC8C64F649E5CBBB2F650 +:1019F000BD337AAC279CEE28EE88DDF3704946298A +:101A00005BC2E33018DA27E2776DB260A55B503233 +:101A10002BF524165F46DB6B8F4DD1CE4AC4D148DF +:101A2000B35009A368910BCBFA68EF064F64B0403E +:101A3000383CB31913AC153704FD56045EA7B07DCE +:101A4000AB46215BE36CC24037CFDC61DBE630891B +:101A50003311491B58007C1E36306C96CE6583CA04 +:101A6000D25EA94EEEC900413AFD1BCAFB1EE8FE3C +:101A7000CFA537A4860B9D160DF706F441BA7E3824 +:101A800074B7DCC001904B0DE64F89D41CC72DC242 +:101A9000EE231939C28F4BABB5390BABF167E1D8E7 +:101AA00020CA1E221C8A4A51A89811F3FD24DC8604 +:101AB0006B5F397A6C9C995EFD2279B2D9F99DAF42 +:101AC000DD8D49A9CC6033CA5E61EFEF1A432D86E4 +:101AD0009D73D17F7E01FB2F9B929414F2B7C38E2E +:101AE0004EE61617C7F992DFCFEE9471BD59120278 +:101AF0008BD6D7E90C09C3667ECCEBFD858F95C9E3 +:101B00008C64133AEDA8FE4E07D7041757A30CCCEC +:101B10004DD5FF8FA9C99A9DD5C937C375B5B6A351 +:101B2000245585951D2C222E6E66043A173D6B8236 +:101B30009E0597A7EAC0E868DB076FD566049A8020 +:101B40000FBF68632B88723C3884092D3D3B7BF3C3 +:101B5000A3668BEBEC0425D801E4F39460F37A7967 +:101B6000B33B6BAD83DFA0F4C76711675F40D5B4AB +:101B70005440555DC5DB2D1FB3CE55EB801E71FD66 +:101B8000766B3B68BF8FFBBC316E59C83D320D117F +:101B9000D9E57474149DE26BEAE000501EBEB5EB0B +:101BA000BCA9EE0F0E0B3EACACC58D3ABC638940B0 +:101BB000495D71340FADC9DEFEC37E8B805455BCC8 +:101BC000BB9630F728346DA0F6036576367A46CD9D +:101BD000178E857A113DCC1345CD7D7383B24A466D +:101BE00033B18FB041A4D13FD3FCDD8B4310B80C8F +:101BF0007216BA522645D03C9BE952F0F97DFF3B64 +:101C000087926C5D6519AA11DCF858B70727055053 +:101C10000677F08314586CB4CCB4E97AC1AEF5F50C +:101C200096D699764AB2C0060CE406B2B77A00ABF3 +:101C3000B499FFDD5225B0709A3BF3DD21C0D9B9CC +:101C4000D45C6F7D97177A12425FF283FF1DDEE24C +:101C5000B79ABFFA3DD91411CA0F80A5A98A781680 +:101C60002024EFAD43278DB2959DADF502E64C0BD8 +:101C700010BF9F5B23C0AC6E14329F3DA9B3F654D6 +:101C800062CB790220F4A98588175A8A8B10CF7A03 +:101C9000ECF9FCC221F095F53AB165F104DD194685 +:101CA00032F4521E0BEFD6C6F404B9AD2A5B4327BB +:101CB0000818DE23EE8A210B4C987CF662A4318A48 +:101CC000823B45DDD832DCE0FE850F33633927E106 +:101CD0007E077BE8C3DB28E8723738F330CB3EB6AB +:101CE000EE06BDFEA3E4EAD8F02553D7E311EA6C73 +:101CF0001357D69C2C3FD31BF6BFF0642C192967D1 +:101D0000065B4F03BE8C291131CDCB601F5F80373E +:101D1000EB0AA179CEDE0DFD2A106CD847D58C5F79 +:101D2000F430B791CE9B2F4C8044664CB357E5847A +:101D3000CB61C34936D3DAB2FB5CD5D1A4A28C23E4 +:101D4000BB68A6CC71946B156447252959C682B728 +:101D50008910B2BC6083DFB35B51D2896D325547C5 +:101D6000C9C620DB1DFF69F62A7AB14931F65E2C1F +:101D7000403826A5AD229E0EF70D0880941CA91FA1 +:101D8000177AA6CE18BCC7AEE02B1D72DFB55896E9 +:101D9000A0BAEDC5909CA91C0D902E3951866149C1 +:101DA00096743DD237133A65392C719AC1F4049474 +:101DB0000A752752605D893FFDC6BD59A7F1199884 +:101DC00023C756D0050B287BE087EC7F94A0C2F791 +:101DD000E87EA5642A4533A2708B312C2F87C1C2BF +:101DE000DCB01DF5D6B219A56889C5694317A9DE0F +:101DF000F835DDEE033E0F62B7BFAD1A721BE291FC +:101E0000229E60F0F7BB04B4E8738C0D79EADB2EF8 +:101E10005D484B1CB5C28A00D033792D42841341F2 +:101E20001607F0FE268A4F4335C588E7ACD650F535 +:101E3000756367150B39484C951AA3B29F7462D627 +:101E4000B3C4CB9A92597E50E572B0089D37C0A3B7 +:101E50005D23D05ECF0828DB66B9E9BC3159D9EDE6 +:101E6000EF689416FFFFE89A1596546B7A9B31053C +:101E70002E9F52924B0B1B9C5A2D09059E7539348F +:101E8000BA02F6A3B4ED9273BAE6D83A335DF5B16F +:101E9000C203383D3C5E6C9B8D660BA34BE0C81EB5 +:101EA000BA3385AA32B236EF74C95CEF13E6D04D6F +:101EB000102B598BB9AD8AF4C06A29D2744DBCFB82 +:101EC000E1AAC7835F098954F5A3DCB6E64233B8BB +:101ED000EE2897F751AA6CACE32F521F9F6584FA46 +:101EE000275B60F8296681C73DAC513FC92AB8E637 +:101EF000232B8922B46C6C3BE39D0406230533A994 +:101F0000A7E75685AAA5D934C84239550CE52AA9B0 +:101F10008ADCE9F6461A8624998324D3D13380E3F8 +:101F2000C37C0E3937F5A84035FED99F9088324FD3 +:101F3000EE50A3AE28D2E816E81B8A6DF94881025C +:101F40004ACED7DB12231F726B59728F03B20A0D70 +:101F5000C5940C1479D7289336556CE63AAB1E8895 +:101F60006EFBEB453061FE6B2BA249D5BEF01FFC2A +:101F7000DD1C12DE519B1A8823262DC26EAC00DEBA +:101F8000629CFA48B166B82684CDB7488FD9568C82 +:101F9000D7BE6A5461C3FE4808C15AB89BC554D91C +:101FA000C587A61151348EA4D400B742ED5D7EB52D +:101FB0008BD8EE049639C8BD3465F8FCC1630C7E3D +:101FC000D9E6EE220BB078FF831A1DE77CAA987041 +:101FD0008373903C318724CB7A7D44B0BA1EF6D609 +:101FE0000C17DB7465D42AC352B2435B18829E8BF4 +:101FF0003BCFB65AD7DF65AE80F0C61817F716E3A9 +:10200000B71FBF5415B5F78395B54274C52AC69D51 +:1020100003EF0A262351FED66A4652772F87024ADB +:102020009EED7F40FFAC44F1EABB5A3076A000A899 +:102030007D3B44E4075D6EB1F060E47164CF7EA245 +:10204000A904E8095F091E6437AB696FB9B078EB82 +:102050003CA1E150058224F87166A5743CD1929EA2 +:102060008F03A9594A37CEBDA35BB7361ACF246F69 +:10207000ABEAA4525608F916CAB84C6B39D84E07C9 +:10208000513CF459D6B2FA664B7B3357F0A716BBD6 +:102090005C4A19B46927C9C1ACF93B0FB3298AA2BC +:1020A0009BF3C8869F88E4CBFFBE37906C12025723 +:1020B00010222C5668DBB80BEA2F6A428457FE3692 +:1020C0004870DDEE81DD7E8185A07416E9DFCE16D5 +:1020D00095B6009D722547375512DE9350BBF8E642 +:1020E000644ABF9CF9B6B07FB2C9E4A6E4D72AF32C +:1020F000C0B2DED9B4CF1A1285147E48B3F23519B6 +:1021000092E2851CBB68D5A12F63DDAAD751F611D9 +:102110004E37E83609EE5E99D82B9F73867B02E531 +:102120006844DB0A6A2BB35592A69A830B89CAE3EB +:102130006E7ED55C52AF0F203356D8D2323CDCF8DD +:10214000C2B69A15062C654474EA965E3E9EC45E3D +:1021500024602FB8950AD6EB67D91D5331E4D535E5 +:10216000632FB60E5D425D0599EC532DC72AD5F25B +:10217000AB2AEBD4C9DE7389A03F701880DAFF86E2 +:102180001EE9833AF6D0D51B596187E376B288B948 +:1021900070478B30E9CA1FCCD9B676A30701FF4040 +:1021A00044D3E23174DE670B9586362E6EA7040D9C +:1021B0006B8304448580CBDF5CC1C464C785A848B9 +:1021C0000A4C083E6F5D5DE370C12BBB0383742D29 +:1021D000E185B877904815ED02E8E5716FDC7C4346 +:1021E000766A8362208596DD1F3D000AB49484CD13 +:1021F000524C8481E5BA57B6274951E4A0A2BB18D6 +:10220000887123DFA865307A0134FE9589D282F483 +:10221000C6897A0A60D765A0F1C385C0B56B148CF6 +:10222000354446837DA8465CA08A7AEA42469CB043 +:10223000BB6247730129453E63AEC49F3D51B0B9AF +:10224000AFE37BE471CAC16C978B80DC2157201C03 +:10225000912B9FF03D833799405CFAE6150C2DA435 +:10226000EAC85806869561815E7E17ACCF00A3113F +:10227000EC1F8B51DCA6B65D849A27BC67A6D1FB08 +:102280000416C308D37BAAB7EC25257B2082B5E6CC +:102290008B92EEABC5C6A776510E2A46D634BFEA5E +:1022A000D74FFE6CA3C78A25C57184008EDFD76D1A +:1022B000437DCA44921F99B7D6E4BE26AA43A79588 +:1022C0009923FFB6C2E61BEB39E247E7D2628EA440 +:1022D000ADFED8C6E7D5C957EFB14DB69884DB64DB +:1022E000233AFEC09F85353A4C5B6488A4047A96F5 +:1022F000E603AEAB7A42CD2E1F736D6AC3385F9290 +:1023000037CD937331EAAF6E26D32736586535A3A0 +:10231000444660A3B11A06E5B4FEFED461A3805C16 +:10232000D79C2A5F2B316503AE4E5A202A8AA6FD20 +:10233000B6BAFF065D6E3BFB2F8543F0B7ECB305E5 +:1023400007CA78D62962702BAE58811F9EE914BD4A +:102350002B964C1B4907E8A2DAFF98FA57415562C1 +:10236000B1EBEC34D700D134F9E9548DF6896773B9 +:10237000271E37FB8259DB1036149DDA1F2D006FA4 +:10238000E943CCD59B6BB917D334C91518464F8494 +:10239000DEBD328B43D70479FA7AD1C029F20C051D +:1023A000809322842A5D7713E3168CF46E50CB3829 +:1023B00016EA238AB25E509C4E557FBAB9FC2FAB09 +:1023C0001979B914D3D566F947937D353407929DB1 +:1023D000B31A01A8D511273C849C106077CA30DD60 +:1023E000E7CD8CC26214882F5F7E85F87A8FDE4F2E +:1023F0008C67B1202973873C3847592BADAD7B5191 +:10240000B133D561C54BEC6858E6A17A5E23EB4148 +:10241000BE6DDAB4210845C684E1DF917BAAEED90E +:10242000851F2C359938A60378FB97C948F8984939 +:1024300080CAF85FAB1BA6CA3F6A4587EAC20DA4F3 +:1024400083CF0F5AFD989648CA393238E22D5C1D69 +:10245000AE4CD18944F437FF248E7E2603B73C6E00 +:10246000E86C6EA1B33D4F6D75F1077D1627A75E31 +:1024700005010CA481DC1BC2CD037C4F0FE4B12904 +:10248000CC0021B5CE5B443BE2E531851533189B8A +:10249000E1FC92157A21750E888D9D90540C08559B +:1024A0001544E2FE1D08DCB907979D4410BBD5BC5E +:1024B000725B9094ADB6881DC1B1E140EF053F4A13 +:1024C000F7224B360846120EA94137712271FF439D +:1024D000EFBA9EB4A5FECBC06CB4BEB606D5A3744D +:1024E0007B2281A8A376638AA06D53A05A5E1A9DB1 +:1024F000B369B754F21A307A5238AB65114A60B9F1 +:1025000053DE11CB424169B9A181AA7C4B4882EAD2 +:1025100081891D5C4AB1FC694547AF2510D19915E9 +:10252000A27C26C90C62B62DB7C77D1142D71B7A93 +:10253000AEBB35CFB6DFC541232C1555ED3EDBE1F3 +:10254000085EA476585DFDD970C088BA36DB8C026F +:10255000E175C9527B219E04B8E2B6CE47C9FFD5CA +:10256000F27768E73158EC9536E727268F164D69E4 +:10257000C4CC8CB1D5622B97D659D0CEC0FDA0A6C5 +:102580005B612A4CD9E32851795A6004FF8E04F12B +:102590007E7725EE4175BA66BA05048EFD85BA7858 +:1025A000D0786687D7452C96753528D93CE1DD373C +:1025B000EB1C33BB3E10ACFB6BD6C5523AF1C55099 +:1025C00012E26ACE355020D77BB5A29FC4DF97E3D5 +:1025D00061224167C85BBA6A047D7E66149A7756A9 +:1025E000E7A2E98718C890D47BF293D1CEC272CD0E +:1025F000F7EF5827E2B236FB1E9B6BA218B7EDCD62 +:10260000E1164961908ABD1FEA34333AF5A5588B2B +:10261000331ECBA84E05C11B7230187646E58BD011 +:102620000E6AC485F90872547A475FBD984B868F4D +:10263000322BBC9985829B3488E5F1F330314B24F1 +:1026400040232CB60CC295DA1ED90F12C4052512F0 +:10265000D422D3BE031B1B2277FF9121F329751BC4 +:10266000552D59D2DBDF26DF9E946D0BB114703CE3 +:102670001A5E54438AB676426915643BC1C729671E +:1026800037BA7007B14EC9FC85BCAE41C5EC2BB55D +:10269000303AF8B311CEDCADECC0D006795177DF1B +:1026A000DD6C5D5250B598AB189D568064B42EDD3C +:1026B000F7E7EA5CC4C548D184DA2420555158D4E0 +:1026C000E21B97E6C48F3261E091881C84BF4B49BE +:1026D00010EFA1DAA8E1AD55013BA363D328B4D72D +:1026E0002F2FD00AE95E8EADBA6EBA307887825449 +:1026F000EE5C9A34316243058E4457E867D8DF6058 +:10270000929CDD9CA14480FA818D6563413D4D988A +:102710007B2E4B066E083F2DC9497E4CB7B4F9B7E6 +:10272000CA027CC73EAA7C3C23835D4F7FBFCE2A72 +:102730003EC32D03B0AF849BCB3D7A6F10D904C14B +:10274000F8D0A888487571AD07741FE7D97BF1A34D +:1027500092BC6FA8BFBDDC792CAF864CDC48F82654 +:1027600095FB3D5C7AB893D1E95A506D46F8ACA11F +:1027700084797E92730957735D5BC20B2FAF75C06E +:102780004CF1BD235F3125C5B45545823E5AFE1735 +:10279000DF647B0389CDFE2BB028FE9F129F9554EA +:1027A000B0AEE1CE6D1DAC629A286E82FBE582145C +:1027B0008A85895BEC3265111C7360703D59264C2B +:1027C00016EBB7914A700915520B0780732774797D +:1027D0009169023466D5C1D1FBDB6B14A5E0411EC3 +:1027E000E8AF98EF767996FC84936CCA2DDAF2DB29 +:1027F000C02F77404816015F26F18453F8850136D3 +:102800005332A14EB8B2EBB9EA20B590721FF991DC +:102810005252786DA67D0B4F0142A04FFB13DBCCCB +:10282000A154BFE4BFAB113A9170E6224ACE891C95 +:102830007BF3FD70A6A5A55EB4E8263D584EF014C6 +:102840009E682F68B81210B2624CFF4D15AC9A7694 +:1028500023CB738BCB1C6659B5307F8CF673C27C4F +:10286000783ED613F97D67D3CF9E0F6E315FF34C60 +:10287000F15D56ED9800E356A1182B19C2FB31DF2C +:102880009B2A608CC981B960445B8D174C86549734 +:10289000D12FB21A0E8E798FFCF40C242519C71F84 +:1028A000324AD72401B097471B6E4AA2518886FE50 +:1028B0008F12197CF8233E05E9E79EC806419F3B2D +:1028C0007CF2D0AA387B9154455569A86D3DBBFE7A +:1028D000BD2CE95FAFB751E3F35DAC43ACAE6335FC +:1028E000AF8A7AE7296A6B53104E5826B8C4F59A16 +:1028F00024F77C2F32CCBEA151DF0B960D6EA014B5 +:10290000005186A342648D8E5DD5998265BE6AFAB8 +:10291000594E2B8B1905495A0892BCF766E0185995 +:102920007E94CDF8382FC5488273863917A0FCB144 +:10293000B1EB98BBFFA9F49CE05E558789F87BE179 +:102940000D1DEDA70485D4D1C0FD0986DFC8A9FC03 +:10295000A2DC036C9E1907D03656E0B23F6932D92B +:10296000B66758A9FAFFE5B30048AA59D4234F42E5 +:102970003C668C6FB9EBB41CA12266F7C1222B59BF +:10298000F543E94E2ACD99DC539CC93D050E7BB237 +:10299000574E6EE1EE8E43A1C4CCB924B38DA0EFA7 +:1029A000F82B0E6816C23E07504228EFD099666495 +:1029B0008A5825966F2F2EDE71C7E2D13A14EED9D0 +:1029C000F3C320B9A4C0A7C62F980D7898788D506E +:1029D000C788E485EB13EFEC6D97B211BB88A5BDFA +:1029E00065032105026FCFD2EF1327FAED150B8B8C +:1029F000019C34564CC1CFEB3FAD6717A8C4676349 +:102A0000FA1C83B95196A32B58587CB3683159B23C +:102A10001EF8C6903EA2298D686DE63BED0D8A6FCB +:102A2000FCD74C69F534E9B05A1778FCBBA1C04714 +:102A3000ACF1D0AECDEE9A4C57107542322F3D9D81 +:102A4000123757ABF3952F997F750D18CAC27EE9DF +:102A500098F266DCD8C416E5CC82924DCA59DC26C1 +:102A600047CAA11E5628704E2A8173C6DE392E40F1 +:102A7000A1F36CCC1EEADE83A329CBAD012158560D +:102A80001FCE4BB242F3FE665F8DE61A8E9B82FF2D +:102A9000C403847EB41F1F57EE584C1287459FDA3B +:102AA000A6CED137C5FBA4AD885BDDFDE683A76D5F +:102AB0006441F4A45D1C79DD8F15D6F424CAE8A422 +:102AC000F2C3B2ABFCAFDAF20E81AD26E41E857420 +:102AD0006AC77B30BDB962A500994EF7885B1A685A +:102AE0006DD37DD9301F3526C769B10E48B95FBF98 +:102AF00075C60D687041CBC6A5A66D1DE33E80FB73 +:102B0000EF46EBE25684FCD718F66508845AEDCE02 +:102B100040C006EBFB4E21383BD43A861C9390FC18 +:102B200085CC933793FC9795E7E0FAE97E4BA67046 +:102B3000196AB7DB1ED6E46467701521BC0DAB8F34 +:102B4000ED761AA3138726B3C3FB148103E1B69174 +:102B50002C6F53ABEFD8596FC7A682BC25DA4B65F3 +:102B600069D742DB3C4A7F6B20F864F344BF3A4BA1 +:102B70006C60E6B120BA390A501BF08816264EB7B1 +:102B800034555030C02CF3DA0DE3207F5BE4FFD0E6 +:102B90002505520530D444CBED8237669F901AE26A +:102BA000AE613EDE7ECA0461663BACB5BEAEDDDF23 +:102BB000B1AD5DA77C80D62E76C710CC10A250EEAA +:102BC0007E17E980FEEE3E8508A7A01082D0D6B819 +:102BD000B69F2990BF3FDFF56FE53F4BA36967467E +:102BE000541436F7A7AF98C3EC0759B503E60CA504 +:102BF0008EE2883B5A668101590419E99389FCB435 +:102C000001860BA97190BEB9BCCBF49E49F636AAD9 +:102C100076ACC7D894062BB1C25D57AF96DAF2E115 +:102C2000DD6206A8C913961E511F7287668EF6BA1A +:102C30006833718BEE42BA36DC988C76EFE6524AF6 +:102C40001FB1F9B6DDACC6BFCD8914786B0ADA12B4 +:102C500024603E3EA4215D6AE85AE1DAEAF55F129B +:102C6000F4DA897F094973CA1FFB2E79D2471D36D2 +:102C7000A68FC6E968A054E673564C3E48E3630845 +:102C80006E43D10046771A45DCCBE7DBC65E6F9E0C +:102C9000CAD8928F345D4FAAC2D297DAEE326EB2A2 +:102CA0009C49F19AAEC43F0D188421CB63403597FF +:102CB000A7504B5BDA1872AD32E79CA89E93279B16 +:102CC00044C10B4FED8B39644134132E5AFF6BD73F +:102CD000AD36DDA27168A034263CD0E1F617372668 +:102CE000BCCB0951AC04340552B557F60BF1CB48B7 +:102CF000B97C6CD027BAA2593474C8327BAEB660A6 +:102D00009FDE87869C485E86F61C94FB1D940F35DB +:102D10003446520DCD46A5DC61B099E9DEEB29467B +:102D2000B892F569F543EAACA14C69384225DC1745 +:102D300046CA18D3CE55B3D8EA585754B99EF7208F +:102D400061589E347875B602E975201E675F7F0270 +:102D5000A7163FA6D0FCDB1ACAA314C65B7E4AFFA7 +:102D6000B531A2A7B290954A858262F3B2AC95EDD7 +:102D7000648DA7C9185F1058DBF0019CFFA15A2F82 +:102D8000C247958BE1B72C527264CD7B49E08D4EE2 +:102D900037CD65B2BB9FAD2043EBEF04E98E74E8FD +:102DA000AD0B219008BA380617F560FF5E39E813BD +:102DB0008D7B04EC7453EA94B5E5F1D23EC4204017 +:102DC00005D4B01A61D9EFF2FCD53B912DD67FB96D +:102DD000BFB17DA48A822711E5D2C4D9C7198E3329 +:102DE000BBC759D2BE94EE56F627E83D4BCB2E0515 +:102DF0005D05D2869706A625CFD84282D2284EFA04 +:102E000032D0F37B34D4E101D80C301CA50F4D0037 +:102E1000E855DC1C8FAF2D0033B30020E39130EB7D +:102E2000A946E6AC8A0E6F2507AE65D61D46BFEBF8 +:102E30004F8A6DA91C558817B8CC457EFDD9D70D92 +:102E40006DE21BE0EA15F26D32FD1DD658CEC1C60B +:102E5000ABF5237E0F520A74444303B1845991AFFA +:102E60007160098056E854315C46B04FEB5C7B8062 +:102E7000F8C20B898D14928B531AEDCADB9E0F1A80 +:102E8000FBB811B56786D5DDC4EC3081F6E24AF2B5 +:102E900033E925AFB35E73EC9E5BC2B386715974A0 +:102EA000A6E4F34B74CCD1F3D409A2584AFDBEA3D7 +:102EB0004919E7DD567E193BC5FD8DA8D229468DFF +:102EC0007A84B8ACD66CED4E52E96322173D7A276E +:102ED0003F208910CAFA9CFACBDAFCE225F85B465F +:102EE000DF13FAFBA83C49B7E911EF1226A9C9E69E +:102EF0009C9B12DDC34022CDE4DB951F81001B6447 +:102F0000172A564BF7F576CDAA6134DBD290C689E5 +:102F1000B2B2ABB0C2D7D1DC6FFE7E8D7FEC2F4357 +:102F2000C4429768C5FF6C998789848B0EF279A299 +:102F30002DF935287FB6D0D49C5139C4B77A42CB0D +:102F40004B3E573D775078B3EC8EBBB7DF8128E31B +:102F5000D84314372FBD90C32924E67D7EF33F4D1F +:102F6000DAC79A8E255E2AFCF846AD012C79494BCA +:102F7000B9825DADF851E394A9AE31A6A90FDE8602 +:102F80003A27DFFDBAF615E8B4D17DB03618777D63 +:102F9000027836C23773476871401C0A3840415383 +:102FA000D7B4A9214C810C3B3F1A81C7CD68EB46B1 +:102FB00020F542797A1459516037F96ACBAAA76291 +:102FC000B09FB154D8AEA6898DE05BFB92C439EEB8 +:102FD0002962FC8E42538D2053227BE4EDBBD2EC60 +:102FE00077B20A00E72A056EFF46BD09B6ABBC05FD +:102FF0004DB674A78FC6B3E72928A614BBDA4804D8 +:10300000C6ACC3D6318492F44F6C920F6FB2346267 +:1030100026013C6AA7C441EF3EBCB2377EA1B3197A +:10302000FBF7B0EA1DA5E85C22B06729856A5A4320 +:10303000C518E574761C770913F6B5A562EC9D47B3 +:10304000A4729122610502978032B1B07AF24C41AC +:10305000653A2E7E8C613DF1AB73064746A0506DFC +:103060008D14654F47D5C3694B5BB930FE8D770032 +:103070007F1F284D90F2DCE253DC657D4C627B5D66 +:10308000DA6F36BCFF16E3152BB79B4501E5AA8323 +:103090008BE8B709DEFC8ECC13368B1FE8DB3FEFE5 +:1030A0007B55727103511B5C869224EB38685FFF7D +:1030B000B4D231F10B08E1E1F635756FCE4E94973D +:1030C0006346BC1E59AF8F757D8FD75EF495E904BA +:1030D000C52AA9DCE9B6E158FC05A8A1F0B5AED730 +:1030E000AB005A6DCE13298CEF1D82DDD23AAAD6E1 +:1030F00021DFE482154F79E5FFD9B3E9006A7BA2AD +:10310000CBFBA7D3BF71904B5E10C956C1040B75A2 +:103110009A8683344EC1570777795470E06AE8C3C2 +:10312000A95403FF4228F3A65C770E10B428D5AA51 +:10313000BE1181380BC96BEA7295A6DA6CF6F259AA +:10314000EA214121E14A19061140398A23D34F343B +:1031500095B4FC81ED1DB7FB08ED6036C7F5F4CEE4 +:1031600045EF6E18FAA03CBB8205F710BD71EED595 +:10317000C685680C6988C1BE8B5679BE43AD459142 +:10318000C17CB6815D1737D9305C5B3A6F29917C81 +:10319000726A50E437E24F2089B0B64ABD62B8A4E3 +:1031A000965B34A4B7714452316F96DB844FB907F4 +:1031B000F7357C8469B1FDE419EE9CE61FEA62D420 +:1031C000D832428EF38DC2281E175F86E0E2460297 +:1031D0002808BE802A479912C1FEADE7B13570B507 +:1031E00032D61D971C787CB667DFA0D7B1F8D0081F +:1031F0006A62627D74659B9896CEF06C966F57FC00 +:10320000220ACCF626B7DFF09C69F3FA29E7484D8D +:103210008182961CACBDDA2832BF60DA5F819C30B7 +:10322000FD424B5655240028A13317D08B3499B555 +:10323000D2E3367556D5B7F0E8731933BCC65E4D88 +:10324000E4B65AD6FC0769F3358AB540916CDE893D +:10325000EB1EBFA846E7A5AE94DF374E9F0E5F6713 +:103260003A649FC043FB5C780F8ABF2783BF61B07D +:103270004CD7CADF65EACFA3707407CA715B9DB7EC +:10328000369410369D745FC292BCED02F72DC2DAFF +:10329000846912C209A08214FF4A5B275BB081D700 +:1032A000188DBA4D99CEB37CB97FE2C80439ADEE22 +:1032B000DC4546F9B1F80291894A8669EF5167A663 +:1032C000EEC2A30EFD39C776F46994EE991A113354 +:1032D000445863858767C59531AF358A73D2378186 +:1032E000B5F90228906B2349822EFC6CD9714F10DE +:1032F0002C758FD76AC70F5CB7633C2F96DDC375FB +:10330000EF6C4DE4F3956FDA30E03F83834ABCD233 +:103310001D2C519263CFB830D717C9F1B7FE19F7FA +:1033200069B6573AF049875B7F8F2FBDF78E5104FE +:103330002527F37EC2E7C73D3F8B5306D2ADA313CB +:103340005C92619B34106DB8D88A19493CC7C2BBE6 +:10335000DE810548C4D9FC2185E1A8C756E4E4CB49 +:10336000C9FE2626E7A8F89B711AD1BF63C96D92E2 +:103370002182C768DD6599E9D2AFB218F684E2DF31 +:10338000471B70E26EE4B622103F04B79117E08C41 +:10339000BACED28DCF9D1528765E0C78F6EDF4D995 +:1033A000A9D33D258DCC28C9FF30F5C469A193145C +:1033B000C366D148F8FEDBDCDC8DD2BD8FE7C86F79 +:1033C00011130A2FADC85DCEF1C5883314C496BD64 +:1033D000834FFF8020A44AA645C29F0A381A758DE4 +:1033E000F973B15C6E8A78A327C740F57EB6129058 +:1033F000C02A9F791BA852EF5AC424E63B575F5757 +:10340000C08934AECB452F388C7218D47AC1A01540 +:10341000A4D5D09D4A9DFD78701CA7DF74A1F84704 +:1034200019682D86B6E5964FEC53CB23A77A001F7B +:1034300005E59603862F36B40E32CB8B3B81D9102F +:10344000072BEBC97244E46C96A6409B1A7D65AFCE +:10345000DF67E3FDC0A1676E63C42AE9C7B75DB249 +:10346000A5C05C3CA8522A7A1A0388B99DBBC24405 +:1034700022FAE351DF854B0D353128BB69A8B7BC73 +:1034800063BEBA83E0F4D247AAEC31F5A52AC44B57 +:10349000DB3253FF998DCC9AC2CB80B4430D90B3ED +:1034A000D3548D79F10DB29950CF806DD65FF43C35 +:1034B000AB6AE88B7A354FA47CC7AC1B4A534B549C +:1034C000929BC3CA82598218421FC87DEB0E101509 +:1034D000BED7526334F0B3E6B2412D848B4D9517BD +:1034E00013E3C0454909241ED4C43983A51BF92818 +:1034F000978C04226C6A551DE8FE871FCEC67EB7E6 +:10350000E8E881F05AD6DE9CA9A731DA5F179BDE86 +:10351000E603B451F831BA47314FFFB1F25D4B4B7E +:10352000D798B0FEFAD7926D8E20057152648D2B1C +:10353000E90351F38A238B334B931261429587C978 +:10354000FCC2567674DF72BEB6F9CDAAA9C7520E78 +:10355000913B637DB6A08DA71890D138D6FCCEDA0A +:10356000C079B60F9AA0AB5B2C98BFD77877358619 +:103570007E874BE369A3D902C907BE286764440C60 +:10358000024F6BD4EE8376627DE67D6DAEE32AFF5B +:10359000B1CC085BBB047CF676C0398371F110C7EF +:1035A00056EE7B88076E2AAF8CE6CA6AC351165660 +:1035B0005504A4A48A5052F7428F42ED10DEE49FD6 +:1035C00087E5B6349A49F41EE293F2F2E7AF0ECDE6 +:1035D00097411DD423BAEDE24E8ECA24B3714AD668 +:1035E000312D7FDA5016428BFC15B6832ABCF35F6F +:1035F000529E0BBA7AB9E060EE688EC63DEB9A0E29 +:10360000FB3F3264AFDAE61A55B9CD550F240128D5 +:10361000C9A273C5685AFCED4C8F779DAEB822B035 +:1036200031F6246E059EEBDD67A2FFFDC67875417D +:103630000280157522A3E0FA8F7139B32B72EFACBB +:10364000C57995C2A6983B86BA1F98FBAD4A77B557 +:103650000BD094637AA7060FC6C16FEAF98373B4DF +:10366000089C3874DA7054A6E0317FC34180394F2A +:103670006C289D01C3E49AFE878720A04486CD482C +:103680009D6B09BBE7245B18AC3AB810D69778312C +:10369000C03E07DDBF39E114D8232A300B0151D5D4 +:1036A0005B8D68BCB83AA6A6BEF7B850ED82C0E400 +:1036B00014969354D9B3A4F0C55770390F6C01CC4C +:1036C000136560D7B3D8441B890CA9675832E455F9 +:1036D000729E7C07C0BF607FDC0DACAD574758AB16 +:1036E00032C72B4235338D8CCD14B72954214D6C04 +:1036F000BC653C9E421B77BC5F87965599EB5A7A16 +:103700000DB985DB6B33322537887126A474035FCE +:1037100009D1051EFFF1DE4B3C02021D826F04B091 +:10372000C771AD77AAF5ABE36595D2456B7DAE4029 +:10373000DFB50EA77D5FACE3DB280F1BE8927D6D44 +:103740008F4DB80836A741DE49E0860445A5A88319 +:103750002A5780F5D7680F2FD6B251F3233AF35A80 +:1037600046E270D442BB2BACE1AD3CF12F8265BC8C +:10377000B1DE73A85C0D04EC9EFEA510420927B5CE +:1037800006227B18F5016806284B50E9AE6921E94D +:10379000E4C1FE01459C0895A9F9A1BD1B4CC41CC0 +:1037A000EA5EB01EC5F2FBF11C6FEDAECCDE3CA3B1 +:1037B0005A38399920B3E29A58F236605F498A90B4 +:1037C00003A58DB0CF1CD2082CD86B6AB4A31E877A +:1037D00005504E264DF3FB9F324B91150A939335BE +:1037E000610BAE99FABC78A13320F24C2A5AC83D3D +:1037F0005543BE8BBCFF0580D181AB484D902DACAD +:103800009096A4BA1095EF6D0D6B6E693EC22D0CAB +:1038100034A4D7B06DCA35A9F84D10C7F5B6AC625F +:10382000DAD709D47A5C6BBF7A558BCE2E77A23566 +:103830009E074E1A679E58DE96FABCF0C22DC179DB +:103840006A308DA09E73CAC9B06AC68D8F86F96230 +:10385000E2E3B4CCA848FF9626B58D58BAF9B7ACC8 +:10386000E8F6AD1D2C0DA0DB9E19129D9872A4C820 +:10387000694CC028D570E21E4ED773323A44F99C89 +:10388000751C7C360DF64A9F61E5900BACF36034F5 +:1038900000D301ECC56BFD304A68DCB8C8BCD57BF1 +:1038A000656AC646F00B6C0EB16A92DC579A081D29 +:1038B00078D808BC5FFA06276DF92AA614EB7E5D5E +:1038C000EE8C9747D5CE5530185D6CEF156CCA97C6 +:1038D0004247415B29AD1F07CA12A28631FA42D383 +:1038E000D7631234ECCDF3AFF3DA74920A310310DC +:1038F000E76A8C2893249F3DB28CB422AFAFA8D244 +:1039000058F8B5E68CAEC0A016183C079291077A1D +:103910009AA59373011659E58D29EE6976255A59B2 +:1039200006CE64D8FCDA23D6C2C52CCDC17C7EA8D5 +:103930000A82C53D5B7F17680D211EF7C02C92746B +:10394000BC4344F3D34FE1E93A48E93D9207BA77E3 +:10395000A10852F5F099B542AA0BEFF10B07D1D8A7 +:10396000F3C7D398FA7FEB2604A06902D5DE7778F7 +:1039700010EDA2B504BDD2BD8C6ADD4AC4798EEDCE +:10398000E0CD3452272E1558D31D480C344D5CFA27 +:103990007522AAC4946D7D57F3E3CCA0B34D2C7966 +:1039A0007FA441D144F8793028C0EAB1685E2EBACC +:1039B000CE7F798BB939E462A0A636ABD857CBA5B8 +:1039C000D150B3C781ACC093550290594BEAB2C5F0 +:1039D000BD3F11852ED13F9C9B4EABC7C7A389FC31 +:1039E0003BCFC50CDE9E4E993920CFEFDE40D66727 +:1039F000F63D34172CC13E34444718E07B7134C285 +:103A0000563629B66C4A2F6AE6D9421714E52B942C +:103A1000632DEEF49039ABE4F7AE71A025340A3E85 +:103A2000511C751373A7FC71A9C1F8DF3893EC1111 +:103A3000B92C63B04058EDEA4802B30B5AE97390D1 +:103A40001365B65614B95CEBC7470250378366DD81 +:103A5000B223CE363DCB9AA09F3F886F60E9FDEB45 +:103A6000118ABFB486D65B8A547E86969C6BF1958C +:103A7000B2B6EA5B2C4BA7230732F13E7D784D7A34 +:103A8000708912BA0BCA8F562C371647F1A1A211B2 +:103A900025935EACAC45C700D8AC782B8E569CF114 +:103AA0008AF466A000AC44378C7B2C98B2B7A07126 +:103AB000CDD243DFDAFF2C48B0A28CA55EB63B35F1 +:103AC000F0EBFD69A453E45E3FED4EB12F0A5D12A9 +:103AD0007E996D0A91509F2CF066A506E5D5F27689 +:103AE00099E2328AD869531E89809358ABA5D29740 +:103AF00004C9F89580AAFC241B9527F03605A33C41 +:103B0000E1779CB44EE4C991E1AFF54EA07CB020C2 +:103B10005037EBEA9FDD12830E1BADDCD314509FB0 +:103B2000DFB77BF801E13D89B8F29A805E069A65BD +:103B3000859FB7E4863E140E8C4A186B6C3B74AAC2 +:103B4000F4A9526C9F19A2084942DE4F87BB2F5B34 +:103B500060253007DDE7FE8C881B4E7FC2754BB4B5 +:103B600026134523FC6F188C2A75523160D2978A30 +:103B7000209E37267F09D2017317BEC2960FEE52E0 +:103B8000F0A523FBE65C1561FBF24DDB753C445A66 +:103B90003AE0650F6891DFFDAE2B8807FDFF7A1EC6 +:103BA00093BC05890646362A7CB72E7A1ED58445F5 +:103BB0005926C3AFB62A5484494254057C9832D260 +:103BC00093F9092323E5F15C1910C2E5097B8637D7 +:103BD000E780E05E2DDEDFDA1E5C85B928C0F3F1F8 +:103BE00041DCBC8D360D7BDAEF9EE2084ACA2A869C +:103BF000225426C891064A2F7222170A3520690CD2 +:103C0000447E3553260CD3D1C46B0F01F8249B2579 +:103C100079A0D793DF30F1F4B37B99C5B3CD70733E +:103C20002A450504BBEC59AA01F7B357FAB77E98A9 +:103C3000F39D8569908D25BB89D1B049FA3BC59923 +:103C40007714710C688DCE81B5034873F0779E822E +:103C50009184306669B0FAB07DBEA27261303A1EBE +:103C600034049FFC2A80342928AF9E7ECD69F8FC5D +:103C70003A85DD3E072DFFF8D65245E33944C96544 +:103C8000AFC4028BAE7962CAAA62A37CCAF0CBA78A +:103C90003CC0E9CCD1C39AA2ED5B846039A3BE8756 +:103CA0009D7D96A10E01593EE42D6E9667AC55C0E0 +:103CB00061288F6AD7BC0A838A288C6F772426A94B +:103CC00045BC6A158A3C0FE4AB26C7DA2563023E81 +:103CD00016876EAF32AA040A9C1AE51648E38E15C1 +:103CE000AADD0C856016BEB3C528927D6F29499D5B +:103CF000118D5DF8A77BBEF0AFDA2D6A034B31550D +:103D0000F03DF379A73EFD2B2CEED896265477CCC8 +:103D100020092FFAE96335C26F571CE2B4C5C4BE4F +:103D20000D8AE2554C495BB6A46BFFCAEA6DB5C07B +:103D300036E6943C82CB20E9D74CFC370D4D8D56AE +:103D4000218270F5EE92D65D450491F1A26F0208D2 +:103D500043210362A311DF09AF531B51C7AA52C30A +:103D6000248E17DB77545E7FE0E686348BB27224B4 +:103D70005D9D0C918E733D6BC89F294E8F370978DE +:103D8000838EF7A2483502F6AD5BBFA4FEEA78A7A2 +:103D9000FA1A707DD002DBAF2D68A4E27FA565C75B +:103DA00026A317C5645D60522B068F7AB35F87E048 +:103DB0001FB3BE62BD4A37E0B08311C8398D5AE7E0 +:103DC0009DBD2A06CA50EA536AA32E81B57B220DF7 +:103DD00047EFACE0CCEA8DBCB8CF69D754BE7607CC +:103DE00038335DD563781095EE876B87E1CC8478A6 +:103DF000D37B7BFB45C374AF064CDE7D8FE9AFBE42 +:103E0000AE3473CE6E73130B10DEABF7B07A3A712B +:103E1000EE29D1DD0A4A6090CC2362A943FFAFEAC4 +:103E20001DA15F768463F2EF108DE0652871816FCC +:103E30000178AD8751390B21C94216BE35C80071D2 +:103E40003E3E5C48D6352E5CE041A2FAEB928BAC4C +:103E500087B3B0D6D43BB06B5457091EB73FEA388E +:103E60003B7BF0EEC1C4DB958AAADC69904A05670A +:103E70003725511C870517E3BF4E385F3EF63A8958 +:103E80001F99413600FA0BF10FF59C14EEF3BE3E7C +:103E9000F3C20A3B160BC918A151C7C76333D4C775 +:103EA000C95795C676D629F396C577D68B94BC713B +:103EB0001F2B951F3C97240F81332579ACB89B8429 +:103EC000D00006DE393ABA6DDAD36E0C578B711713 +:103ED0008FE44966034F22AC1E859CF349DFD7ADC2 +:103EE0004C3EFC68C13244626FA92C233982CED982 +:103EF0005F272E9A31AFAC1379A593A0BF3A25FD69 +:103F00004E0EC23F8A438DAD6EC41901D69E402C21 +:103F1000AF5CF3F5640EF85A12C9242A21310C560D +:103F200037B1AD74D1A49C6820907844EA3F8602F2 +:103F30005CC33ACF6DC5840B116AC56FE764FFA8F7 +:103F4000EFE78C1278984D45C122A50A4EEB1C1064 +:103F5000D8078D8D99C25B09F4D34070FCDFCC0E7D +:103F6000BD767F2D5CDA2ED789B79454D182918AA1 +:103F700069757EAAAB2A54103D6CA7C4FD63E9BEE7 +:103F8000B3051A4970D28D1DBB1D1F29757D18C13F +:103F9000566F9B37F617B8A01036303988D9C7BA94 +:103FA0004B688D0D052D709A053C6A15FDA59CB4D6 +:103FB00042C818D3428612ED4392DDBF82664A534F +:103FC000B1C1F461ABD334F48301D17D162AC3624D +:103FD000BDCF5339256C9CE5B44AE0720A3B68AA10 +:103FE00074E141B2225022A6FE3694E5D44B3DBE88 +:103FF000257E2C320529BF1CF37B23689F57826ED8 +:1040000049111F7B754DA5A318D727EBECB3464E7E +:1040100092D4B7927AB2406CA5563778B3E4B230F6 +:10402000EF4B13D503F07E6FA63205B6BB005202EC +:10403000F72A5C206F9F5E39622CEB202F408A2B81 +:10404000B7445071A9FB8A3EF470B71D0B9D0368FD +:104050008537E3FB608227FB6E16B4909F085E8D68 +:10406000DB2969663119C0EDBAC750EFB3B6A58137 +:104070004BAD78613329A41EBF62758403A7F52D6B +:10408000B2D763F39E4CB4207EAA92000EE73F2F76 +:1040900026F1B86FDBA79B8268B07EEB3AF11ECBAE +:1040A0002E8ABE9B3D453CEAF1E44CD088F9050AD6 +:1040B0000BEDDC4D4A099F437ADFA435247066B9C5 +:1040C000C1BDF5CFE85C7DF8D868BCD0E59119C1D9 +:1040D000340D58943F15F7F5293F62A0276FDCBFD8 +:1040E0008C75F99FE467B7769FE984BF8D4D5D2697 +:1040F0008AF57C9055B3B31009B3CB456EC00875F3 +:10410000C5427D8B3A32B8ADF7965E26E4802583B2 +:10411000ABB2719ECA84FA808E2C4E0414C898C526 +:104120005197168FBE7BCCD327A9AEBCE4C0DA73FF +:104130007D0458F1939F34F0F34D6546D75CBE5231 +:10414000A2D9081663520991AEF052440200123E01 +:104150009904FFC44C1B53073E42F55F0903939D2E +:1041600015FAFD6B0AF3A2B85B98FCE7C583A23E83 +:10417000B25A2AABDF91795FD1B0DAE89E6E6E2E2B +:10418000BB8D839B64B6D3F28B086C68607356F06A +:10419000A8B47FAF86D520B38B3B121B732747EFA4 +:1041A0001F617EF8D43C0F6E597AC14401912BB740 +:1041B00005876435B552B780FD4C1CE874702AFA47 +:1041C0008527781C7B0EB9730546E0E930D93FC0DE +:1041D0009D14A53EC4E5AAD7F4B63E6D60695DBAEC +:1041E000341A2B42E1D0C97AA906AC43E022FB4E37 +:1041F000AC74527F0C00AD4F83F00CCAA653E67D21 +:104200001DF144AC8C4964F79BAD1901D065E1E028 +:1042100031D3659C1EDB2968FE7001F70EF29350C6 +:10422000404168AF14E79FA12DBE5B64390CE934AF +:1042300032391C6287E541845C1EEEB67B5DA17E4F +:10424000714C7994C30CDF134FA6A91AA385A9FC5E +:104250005139B8D96EFCF28E1C0022561BEC996DB8 +:104260005B35C2714472951EA01AC092BCF2D6FC96 +:10427000FB062E3DEED358FAB728039F2673DF3294 +:10428000071D045606D014639B3FE4515DE28A5338 +:104290007AF60BC455C86E20AF3BDF2467AD1E6EA7 +:1042A000F0167C6868BC3F965923FA91C58FFA0DC9 +:1042B000C449F56A46959DBFC65764700B4B661896 +:1042C0005A4380924950FE0BB9D0B3985A5F734A53 +:1042D0000CEFA444BC23E8321015A9076B478D11DD +:1042E0007745E403DDC35EFE4442FB0EFF555351A8 +:1042F000C8BFF348C68A02DE3AAEE5DE0D4287A6A5 +:10430000A1D7EA39FDC1F763F47580775D5EF39557 +:10431000E6FDB68B2FC4B9DCBE7EB3B2F20F42FC11 +:1043200010DDA6575A113DBB0C9FC4781DCE550910 +:104330005E9BD0DD3FFC7AC182E19510B99E77BBD0 +:10434000BAA43B7B7CAD75C495487DA72C12491758 +:1043500071683CE47E9354AE54CD2200EB9E9ED116 +:1043600087147BE7F43D27D7917531CA051ECB67CB +:10437000C50F272CAB4182BFA79D9F8FE476C1D884 +:1043800086E31722F3C8EF1EFDC2A36EB6A5078A07 +:1043900044F3FC768FEB5E371637FF19D883C0F6EF +:1043A000E1354E7465F580C35ADF5BCBC460EFAD79 +:1043B0007DBF7F98460E08AF10FFAF44A3E6BBCF8A +:1043C000A2A339CFB7BF6D9F70C626ECC2D88F1697 +:1043D0006252842D01DA8DBC2FA464C0693D469BD6 +:1043E0001A1E048EDCB23FE236AB1D0BF4BA21106C +:1043F0001D6D3AA90496ECC6FC3714FAD01379FD6A +:104400002D7E2874F4B9FCFC021663AF8F64207E05 +:104410005BF181EA95D8BDFD261A9ED529B83EF2FA +:104420005CCCF62D7E82775670003E5E5B25F9D619 +:10443000D2AE56985868C0C9C111F02F8188C08784 +:10444000136ACA35ADEB6B943EEB9E32314C75343A +:10445000576A686536694D1CDE5887D37AD784E978 +:104460007C420C6FE4BC7FDF56DE302EDD7E8CAEEE +:104470001F350A7B080B986FD01E6FF3535DE21D4A +:104480001343E9D5611E8C7A3236D66A7070C656EF +:104490002B89F0F8B71F6074F7C55CCB9609236EC3 +:1044A000922AB690971AAE7B5F2F7666B59EF87EFD +:1044B00016A8E2305199E3005CAE7CF8411F61B070 +:1044C0007413776D4FEFACFCDB245E1B66109A61B2 +:1044D0001F88135F4452F430B243D2DCCAFE5565E4 +:1044E0005324C9950D42EDC89E1DA7C4F9D7954622 +:1044F0004688DF065EF08DDBA25F8DBBE2C06F7188 +:1045000063B3F225800D3D84FFBC81CE62C3C4AC91 +:10451000F2E13FF110A2CF8A87B7DA628819FD165F +:1045200016C985C90C6F4D8E1ED9F28F68AC457EB9 +:10453000DD534062CCCE4572F143A03DC24678C601 +:104540002C782B40F5625C052ED26EE128292005DF +:10455000ED1B7E89CD1D935DD3BE6E9544BA548FFD +:1045600096BB0CD05623A3A6BFEBE4095EF84A29FC +:10457000597EDF0971AAE48293B0A3CCDC1C196CCC +:104580003B6429471B7A85F6FCBD5DFF10C7DDD172 +:10459000C6AC32FACCB26E309F8486343058BA6AD8 +:1045A0006DDD3F27A87083ABCAD6BA0EDBFA78DF81 +:1045B0007EEB84BCDF212B9A677A09F3FAE32DF5B1 +:1045C0007284BD0D09039CF2DD4EDADBFBEA155D5A +:1045D0004D4C17922763E4A345C43F2A45872BF629 +:1045E000AE6C01D5519216731825D8249CE73A90E9 +:1045F000B3342F47A605BEB4E305B1ED3054A3088C +:104600009D6CBCD0D4EA0E0626689739253EFE6F15 +:104610009D7074E66CF502975EE0EF544139C98EE7 +:1046200027F124CDF729888CA23B3871A05992A993 +:104630001DBB3E14B86FCDF5F9370A926D9552F651 +:104640002ECDD80C6F6FB431A998CA11C04EF64A5E +:104650002EEF4783A87FB9F8C119A9A66B711EF682 +:10466000C1306FF17932A3681BA4ED3CC89F84531D +:104670001B19FB0A5D43FC907E7F106CCF7D685652 +:10468000290EB59EAD8FB2B018519B8832DAADDCE1 +:1046900000BFBC4A71D35350AA58CC87ED17654C64 +:1046A000474588ED421309DE7EEC85A2E448E284AA +:1046B0003C75A7C40FF260CE7B0619C0B4C72D921B +:1046C000555520CB2CDDAE2239AF6B03C603C1DBC1 +:1046D000D57BE2E83332CE97E310D8C87495BF7C1F +:1046E000B7EE0E0CEEC76781D477654D7953F89419 +:1046F00062F0E042779F3A7186057E53500F1DF2BB +:10470000ED663F72A6B5974107C5E3C11775913BAA +:1047100056690AD1449EBFBAFD4A01A7F85143BF6A +:10472000A444BA79564CE0C3BA7490DFFBFA897D91 +:104730001E29C5E7ACEFFEEFF01F11BE18CFD16BFD +:104740009EEF7091995523D708FA0271D7777302BB +:104750000F66C2328BEAC0EE05E8D25E67F0FF2436 +:104760007556CDCCE9CD5E008C2F5E0BA8DE9ED8B1 +:104770007008B8B087E49CCF62CE6A03FDAFA26038 +:10478000C90158AF25C4041B195461F91C71D52007 +:104790004CA43BED4623F4FA9AEC73C7A5F9E7C89D +:1047A000AAB77A059B52D416C39CA55BE67E503708 +:1047B00054437DAE1F72F352E9E69DA01DEF6B1AC4 +:1047C000F763B8CCAD9083D2E038C58BEA83E5AA15 +:1047D000C41069AEC660F367B41F69B0C6502D88B7 +:1047E000D2C7A29D5B185A86F9001A124968407216 +:1047F0009503EA83AD38821E35B28021F99B5E387D +:1048000036EF6D54A04749AD4CF0CADA45FED49559 +:1048100001C6EA66D5BF852DED986F62C2A98ACD23 +:10482000A311A380238AFB5DB7BB4EB99E3CE1A6D2 +:104830004D9E15F24B1744FD698ABAE0384E6C451F +:10484000B234751E289C8A87AC1732401C2B0FBDD2 +:10485000413EF673FC3256B074376C96E386E9330A +:1048600000F3CD4AC554433BA6238176121D3BC4B9 +:10487000BE2A5D474A0A55A70E0A8E84AAAB81213B +:104880001ED8B965457535A7736342BB5E12E884CF +:10489000BA5EB76D2DA77399BFF276066B372425E4 +:1048A0007813D7995FAB17FC81503FBB2EC413B56B +:1048B00084D10B60B7497928D4EF2ED0AE74F3D9E8 +:1048C000BABC6239C4FF7611F79CCDC0B12C383523 +:1048D000B17F16E80C7290C4F7859E009C4E2EF3B3 +:1048E000694C3C38A72B6F47F15F88D5CBCC46DBB2 +:1048F000379D70F4BBD4EF227ED7C096FD67B1ED33 +:1049000028DD006F5F3DCA5D899ECA227448C521BB +:10491000ADE7D706883EFEEE979458BA757F5EDC09 +:104920005230FF3B8A5EFBC321A7644770C7AF6B61 +:1049300031CFA92781C7457EC5407ED03804F86BAA +:1049400021E9CF930FE5CCD995AF45C65E9CF7C55D +:10495000F8B19EAD257CA587FC051BFEEC7926A849 +:104960001852D59351335B896B77E32AC4DFAB22AE +:104970004775A4A3B3E2430C91B951E0F26A03482E +:10498000FA60B3AC706FAE0FAB172FE22862D5EAB6 +:10499000D296CEBDF937F94470C37ED1839F684665 +:1049A000A4B50830387D965D2A9911C493DFBF8382 +:1049B0000257B15C57DC37062F662AA01B0061C482 +:1049C00057437CC7C0913B77A85D0DA23E157B8005 +:1049D0008DB5CBF3590161B5059E59261C61323363 +:1049E000E66E7331A3097B73D33985A6279AC4FD7C +:1049F000F3E2FA27DAF0BCE71E83387C5B5819FE35 +:104A000048CD5077CE8D66FC3E2C71E69F82523F9A +:104A100099878FB1BAD82CB7A776EECF346C704D8A +:104A20007194613DC42B5B4AFE4D23B418E420F21F +:104A30005062B2DFDE5BEF32C1712A073D0D43A940 +:104A40006FFBCB1DA3E110A798CBA877E1D18740DE +:104A500085722B36F4E1DBCAB3F2DAD289BEC8F62E +:104A6000170EB4B47C039DEE77C8394CC193EC3B70 +:104A7000EDF5855B885D65C58C4D46745A48A4C2CA +:104A8000115A8E978E170B48F087EEC88A90ADB2F8 +:104A900061F6D2B8C418B1634B44A4E5607111A3A8 +:104AA000ABC3B385C704104AC70C327F5F81A5141E +:104AB00022972D35FCAF175E3A729CF7F7E86C5AD7 +:104AC00047DB879FF19651C817F0432DB3FBF3AD39 +:104AD00071ED43B2D7D017AC82F12C99EC72190664 +:104AE00013F953410355636F37D2A0737054053ADD +:104AF000BE9DBD32183679BEB03AF7C3046629F8B8 +:104B0000C314EA3260835E6CA0FF07C3A9BC209186 +:104B1000528192EEBBE0806C4E85578F684779A634 +:104B20001418F43FBA5267151C808D133A85B516D8 +:104B3000C71F417061ED96BA8083D67960861C5E8E +:104B40004A4CEFD389387572023AAE5096A20DA73F +:104B5000585B046E0DA0486B2EED2F7ED00712C659 +:104B600091E738D42BA031F4CB4E0F67235CC30FF1 +:104B700010B4F3AE8D2F63FF3D221A81E16D7C7678 +:104B80000812860C50AB9C935A333F997814EDC2AF +:104B9000499E642DFA1CDC18D0B4DDDD928D54786A +:104BA00066693B89CE82F774177DF4654E6E067A8E +:104BB000A9B6741174E52DB253EA9A64FFBCF5AA44 +:104BC000974200AABB7DF51E4B6C7A821DFCD1E694 +:104BD0006BA5DB1EFF89ECA27F951875E456ABB977 +:104BE00095D3A839227D5712F6154EAD329F170482 +:104BF000B53AEBBCA720A8C9F8502780A2A153A5BD +:104C0000991817E91E571A5C788C12407C76851328 +:104C100006D0A2FC8CF0C940EB8868210FD04EA8CA +:104C200041675DF25E70A8C03E162FB4A968733567 +:104C300076B982EF06EC331C996424EC25245CD50C +:104C4000AF0F932F3824EBA00B0AE689E408F6F7A0 +:104C5000FE5E25E5F174F29FA9B129D859980C3E62 +:104C6000DFE3E7E93A9E87AD4FCD6AE8EBD5225402 +:104C7000A7C056C0C50B234FCD8BC18B044618B7B8 +:104C8000360E1578A958AD7F4FB101B8EC3C7E388F +:104C90003F45C759BE50363CF3AF13D80E4617797F +:104CA0003A2A4404B9F10649BAC7DF285B09F881FA +:104CB000F538D604EE857FEF091D1847535CAD47E4 +:104CC000B8509F0867AD1F4A9522DC43BD3F8376ED +:104CD000727D94312BA5DD8F507BBD352765A714E0 +:104CE00018AA869FE57DC489FE26A75E4B322F4F0A +:104CF000F15BCF8FAC5841720C5FD08A18BDDD35A7 +:104D0000F25568157C1B88AD0298429149DD94727A +:104D100042F691EF8027E5C11736BFEC682E8CCEA6 +:104D2000FD8770821ABD37F0ED843D5B1C15AE2FF8 +:104D3000A8C32FCFE5909D114F844BCC8463274FA0 +:104D4000AEE36AAA8BA7D5B3CB173AAD9EE3768EB6 +:104D5000ED349BA798747572E88A161EDD0F9C725D +:104D6000BA4C772331075367338F5B87B62F11DF38 +:104D7000BDA16A1185D94E068D2944D100F0B60433 +:104D800040617437AE8088A7BCF34B52E9B4DF9022 +:104D90003D24AE4DB1DB06126D0C371C280ECB281E +:104DA00053D246818BC357DB8ADB5F39CEC94B0CAC +:104DB000A13718FF2F3E250B8746F4DE74D3DC6342 +:104DC000EC214B759D6331B51CF2CA83F4ED17DC01 +:104DD000D2DAD3210CFC0385A8A651C0CAADFE636C +:104DE00057DE15F226CED9281BAF164E70037A7DFA +:104DF000BA25B2FE89F4B1DE0EDD6658B7BE83C5B2 +:104E000013371582C07150D3001DE5BE278EDB031A +:104E100030C0C2719F087A6D1F61A9C8118BB38819 +:104E2000A8B5D8538EADFD81F09EDB674954A1AB88 +:104E30005E9097EFC4EBDDF1B2D39DB78CDE5AA63E +:104E4000B13F4DCC4CF80375B1F30E515D37C1C085 +:104E500002DA32BF639B4D53123BB050F3BDCC011D +:104E60003DD5188BF50BEAE2F21646D9D32AB3B139 +:104E7000DAA28B90ED8C841CB13C235375A1F820F1 +:104E8000A57EB331A925CC3440F0587BF07B13AC20 +:104E9000AA4AC74A4FC4C53A2052806C5BC731AD9D +:104EA000CB500BBA8BD54F6B6DA5DF80C152DAB9F1 +:104EB000C42BEA01A49769496AB85C751FE3A6DDB3 +:104EC00087BF3695C969052A78D5C40F1FB002F689 +:104ED000F151DBE4C586F7D24C9637CAAEA3F28D0A +:104EE000F32DB0D6D6F92FDFC3B683C754F1BE3247 +:104EF0002FD49244FE6FE13924986E208A0BDFACE8 +:104F000094B4E857923BDE3676611139B5C25877D2 +:104F100038625B972B86E701459D1E1D4AB22AE643 +:104F200007DBC002481F7232334F4F90008C7F4A1C +:104F3000C9241D5BF4D61D5203C6E1CAA8CD1BE2ED +:104F40002D42D73E6C0BBD3A1AC184A7EDDCBF3AA7 +:104F5000EB0EEF639711C3622C471A469014D43EB0 +:104F6000570ECEA631AF6FFF880407AF46407DECE9 +:104F70007C726772D79462B9748AB6F53844AC47CC +:104F8000D6A0DEDDC766FCAF038A1B6B3387BEC4C9 +:104F900057C91B91DAAAAA7FECF13E779767D30B2A +:104FA0008926E7F53639699FD4FF9BA4192E4F480F +:104FB00040CA9A1A2E0492AD7253E473AA6361CB6D +:104FC00098283BCD41958ABABD5CB31B56BEC1E162 +:104FD000FEB4EA6672F7A566309B24D99E7A222633 +:104FE0007444EB51851D7D23F4393BC497CBB8D86D +:104FF00086225EBE4F2A827249766C322C715DE841 +:10500000AEE8A832808FBD3556D05E0FF41E982FC3 +:10501000295CF336A3562512C51B564650AA2834E0 +:1050200083215D4148A3E7C0A74F09F68E4BD53BCE +:105030005C287598A97B9BBA0CE6A9328FBE953F78 +:10504000C8D163DD55C7BEEE9D9C6353546DE54AE0 +:105050000D16E9B55ABE5B4B5C06CAF790A7DB316B +:10506000E1999CC889EAFE573BC40D95FBD886FAA6 +:1050700097E0B63FE9E08AC372BB6C661D6612B565 +:10508000C6EAC27209C8CFCCEE610740102E7C463A +:10509000DFD8239B9E8D2CDDD333AA35F8B0A1C574 +:1050A00012B66DC8CC04FEE4BF702B28E69F446B9B +:1050B0009F27E0851A4F3D00C576C2709D105D0C9C +:1050C0003E249F18A43E9051FD7EA3C34F35DF813F +:1050D00093101196F03F024BC4C26A07C8C5F94E3F +:1050E0009201669FC5819723B674561954D17BFEF1 +:1050F00004B2E22CAF5D7FED472BF9B8C25F2E7F83 +:10510000F834766D41A01255CB62E73530A1A2315B +:10511000AAB7C09358E7C44B60E81A7895210439C0 +:1051200093AD517AE200682F858F318BA6E66C0B28 +:10513000680A25C50114DDCFC2517CEA5C91FE3FAF +:105140006B5F888AB1B79FA6A234CC43F49CED195B +:10515000D95580CA6A0E510DEBCD8C33B8CF962E3F +:105160009119E95C11A2D4330D2E0370EEF47F0582 +:10517000B1305934EFE2C147287D4D2E5B9214596E +:105180001A64DFAE98A9CE18AC579F4E134867DC5F +:1051900092FCD448AFC53511701A3886643DF8BB0F +:1051A0004D036E2CB710C4FCC9ADD93E8D1E918144 +:1051B000A043FB59FF25A2729C87A1C2B2930AC6E5 +:1051C0005B9BBD8148272B7F9497090712A95AA1A1 +:1051D0002776AF21BBB17B4A5FFC8AA48427718A02 +:1051E0000CE8196405C02D65B4F02B1FED2701CF25 +:1051F000DD208AEA485E1B58F5386F0883FD4FC5ED +:10520000335C8F923022C0C2E236D5C6B263615998 +:1052100034D64580576C720F8102A9B45EA683FD17 +:105220000EC5F623E85554B636123C7C52D2754969 +:105230001571F15E415F0859379C301D85F7F0B557 +:10524000051BEE4879D46AEDE0C7305AB3871DDA02 +:10525000CE04B1687E355E7807BEA9B331FE9F17D4 +:10526000A22D071029172A03FCDEDC372D7F0751FA +:105270007A826742F1CCBED003E6DC110FDAC2823B +:10528000AD76FA03CDB0C090A3375A8B70AD031141 +:1052900079A20A114D7F63EC0E739F233AE698EFD3 +:1052A000837B02BF07A21810366FDAA501DDA7B510 +:1052B00016B05AF880557604A46B87F43B77ECDA85 +:1052C000E7463717227F6147CCB7B17ADE68E45AE8 +:1052D00012ED5339049AC9B441C47345EC815C0B97 +:1052E0007D92505B92EA45F6A09F3C1DC3D821AC4D +:1052F0005B808F7268990CCB11F00A46012FAF3199 +:105300001A9C8B3B1B81D790DB010E874EA441EE8C +:10531000B7F4FAC14D5C757D7C75953EBDAF440A0E +:10532000273905E4A2D32142F03C15D28CD6058A58 +:10533000EA862C017EA531B4D054FFA1428826B95B +:105340001E77B3B2069FEEC54AF415AA057811C5BB +:10535000258290C5955395C5404E22F1D6CEE7EEF5 +:10536000B64C4374D0EF15692CF48F53D8E26361C7 +:1053700018F0FC63BA792011283D6CE74580730F63 +:10538000B279F57CBE44061387040A5D8E6B0CEE81 +:1053900007B94D8795FD63DFCA29589554380B35F9 +:1053A000F155DE1EB395C87D0C5EBAFCD1F7BDB9D0 +:1053B000BD773C7A5601EC7A9FAAFE6EA560AEE7F7 +:1053C0005462172935298CBFE7944DFEB3FC97AF83 +:1053D00028771A5999AD35DFFB894DC951B6DABE28 +:1053E000A8955E83803CEFF382FF14AE56C703425C +:1053F000EF854E3FABF844121C32BCF79FC611FB41 +:105400005C2457D78CF78CC37DBB4899446620EA4F +:10541000086E4AA82BB3B5B53F6287A2B72369FAD5 +:1054200049967BF8347F38C233C3F74295C55A5446 +:105430004B42D0D65F0B1030F3BB3F2C2016A9EAAD +:10544000AC3CA77076988085F25F4FFD9CBADE2851 +:1054500075D73F50383D23BF7BB9499B43B171B4E9 +:10546000A5807DD64684D64D0E3E40650E827BDEFD +:105470001F367CFF36FE6CB72DDA2C44B3F6471886 +:1054800084E64F20D72FCCC20A3022D6C47432F71C +:1054900076D9D1864D5C421492468A3AE455609A98 +:1054A000C878A4B7F4C08816FC1B98F22E147A5D55 +:1054B00030C355D91EE74C9A51CC95BDFBD03E4E1A +:1054C00035B6E8282751CBAD14ADBD4431ED63911D +:1054D000181857BFBB99956EEA2F7AC1366D82C8EE +:1054E00076C2C88B11897E8BF46EBAFC6B86ACB227 +:1054F000BB0612FD340C0FAA0CC16705FBF1D94D98 +:10550000A0026FC502032DF48AE0997FDE9D3BDF88 +:10551000718F09A00BF97BC3C60835A5D798D2DFD8 +:105520001AA3516C20637317249FED2657349E599C +:1055300040CCF7BD602190FE2ABCADE2F6899948C7 +:10554000FC6C8FF76A5DAD392DFE51C9030D842DBA +:10555000F7CED7A44F8DAFD258BE289FADFB6D4A72 +:105560004358F449E979579E0046C15ED7CF0A33C4 +:1055700017DA43EF5EA41E3E6C05B98BE8D417F131 +:105580001737B5989585A65CDF80500C3A8B6D4730 +:105590003F0BE751E2038D8A70432D60FA700F4292 +:1055A0001F6A3386442F550F70BA5B0773D4020D00 +:1055B000B2B1792E00C9E7BC69E35BBEEB9D04097B +:1055C0000271C19511FB94C7E92A216AB1DA5A65C3 +:1055D00091381DCE0FC26236F23A441BCE8112774B +:1055E00095A0C8DF795545D52B2FCA7877B7DBD082 +:1055F00091B04B664816F963AAA4938C275E287E67 +:10560000A7A4E650ABD2C384479DE3C73A6D74EEBE +:105610002995BECF90BD6294E3714FCF5BD11B54EF +:10562000F6864B42666D84283BA0B3FA9316C4C439 +:10563000DA80C117296A8048FE3D34E20558EAAE97 +:1056400042CFB191774FE8AC3944AE082B89DF5691 +:1056500021870E60AE76D86225D630BA6E11FCADC9 +:10566000011FD276B12D79DBEDFA071CABCF726149 +:10567000F6313F9867D8700EC38A44FEADC5FBD69D +:1056800048B8D6E48B31B4192A1671DDAB20998B5A +:1056900022EBC94B4F4F69887EB77907A64F6B0E37 +:1056A00058061A0C9D83E837B5D9ED9220B6DD5720 +:1056B0002F05E6440C7220721EEB0F0C93AB1A49B7 +:1056C00033563AC72CA20F81A212BBED9AADED2141 +:1056D0009D25DB76EC992F88E14B26DF39EA8DEDAD +:1056E0006472F099A75DD92BE75B5E0414043B68F4 +:1056F000C7F0D684FF276B9CCFEBC7ECEDB5D32F5B +:10570000C093A9719E65CFB5B37A38D9843E6349F9 +:10571000582045E7ABBB6582AA4C3361F942514A38 +:105720007090A796729B5D0E97C5F7BCB8F1197C77 +:10573000C4FD325BD81EBB5EED875794D74785000A +:105740009D457FE64F6517D45C066323917D631208 +:10575000DAD62698DD53ABD36FAEA3CD691C91C8C2 +:10576000F4B5AB501ABF98B4A97D6D0FE309DF18EB +:105770003792E20B8111357C564F96F9D17BAB9E67 +:10578000E9A0A1AA6558896A5E300A76A79DFAEB5E +:10579000E9712EB729F0E01BD7820F28CAB9415909 +:1057A00062DE8A7149DCB2F577FD87B95B7B7FB930 +:1057B000495CDC205A6A3BF0FD2B214ADDE2DB1C10 +:1057C000CF3A164654444A7A74E7A120B712910F93 +:1057D000BE96430775014C7EF61CE1DC5B48658490 +:1057E00073D7C53ADE1DA59AE199D92A1558FF4D00 +:1057F0006C5BDEA0AE364B0EDE8B93635FF1EFA1E8 +:105800006491DFEEAE3AA0E18FFB4E33381266AB07 +:105810006C209E00D3617231DCFA0BE4C3D4348176 +:1058200089432C8BDA8F0B88BD9932749D14C9ABD8 +:1058300052B1473408761E012A6A14AD927697F960 +:1058400014BC98BC7725A66C9E7F0EE01E6A72EF92 +:105850007D754BCF44AAFDA344C7EB6A6BDBC0A3A5 +:1058600066ABA77AC0A6BDB70B96C0684666F7FDC3 +:105870006F04356B83F84F8300B4F7DD2B5A0DA905 +:105880004839F681C4D1AFB3A1996FAD343CF8A5C6 +:10589000D2F4ED9150D8439117DF2935301D1B5CB0 +:1058A00069F7753F15495C55DA9DEFAF4A39C5A5D3 +:1058B000BEE06B2AE18EED9B609A29F884549CAA85 +:1058C000990B183009E69CAA83FF013AFA6A41CD88 +:1058D00060C93A7C14D1C6E64A1C708D80D325B5C8 +:1058E000AF44D80A753FB0657FA959CA9A7E24E9AA +:1058F00049BCFB3C11F9988A17BB38D1286B40FF93 +:10590000D99B096A28EF04B1679B2AF4E17789DB08 +:10591000261ADB8FA385E83B8659F0AD92A67FC996 +:10592000D83B2AC690D3AFF51896E47A2CF4BEC0C3 +:105930009D1D0C9F1C9A77BB3ED60825D3456D0A4A +:105940004C48B3DF5CB146F5A5BE1F7B8E39D05BFA +:10595000D9AAE81CAF9B377A279E69F4DB34DCE2D6 +:10596000E1FB0C914E4C6EB2B89BF86305A59371A8 +:10597000282C860EC2006B578F462FBEF3E5818719 +:10598000E5FA373A192DDFFEC053B177957617BA8D +:1059900068F59B229158C190B9BC19A6DC667BC3FF +:1059A00088AB6FA4E3D8E85D80343899A06F4DFBD5 +:1059B0003BC663C822A0973A5C445B92DCC3D72EF7 +:1059C0009744BA4C3A4E54259D5FD8FEFC68A9F71F +:1059D0006049C0029C4E5697C182C7D24920E95403 +:1059E000E1489473CFD43BD59B9E032342D4B69D0C +:1059F000EE6A1F096205D199B8DC3A4A40E483D2C5 +:105A0000F6B2B97B0DCC70AF6A31BC9774577FEF9B +:105A1000884D1B248BD89546C3C9A750B08457CF57 +:105A2000A04A6E3E6192793126BDDCEFAA753FDC5B +:105A3000588B118D50F3152F6A3CD6DB2726C1F702 +:105A40002CA44FA86D67633E7AC984757EE06EFC16 +:105A5000C8D626AF776E33498FD6444109565A329D +:105A6000314BFCF48C28018E137C3C9BF6A5778986 +:105A70003D78CD74C6ED3E1C10FFE6FF5F20044E5E +:105A80007BF9402BFB5D195290F7755556C30A946C +:105A900003916240278A2C111D3BA7EB6FFCDCF8B9 +:105AA000DA723F484FB3C0BE4BC4D822F535E91B6C +:105AB0009C01BE5BE31C649D2640966F199F488540 +:105AC000DF260815FA0F3327F79BEEDC8ADAE9E1C7 +:105AD00030DCAD82961DBCD3900D99E3D16025FAE0 +:105AE0008AB45559A417465377C6E419C7F68E07EA +:105AF000AEECBFA9CEB82001B601766CFC2872814D +:105B0000BDB0302F6643B4CA48F3C0E75E668D5619 +:105B1000261CBC0178255C6C513C33CF91F6C684C1 +:105B2000749339F89B4CAED4FFF65145DBA71DD8D2 +:105B3000B98414610D224724A221ACFC5C2FF79A92 +:105B4000EC49DBF43A312259AFC5A131528AD1F286 +:105B50004F9441E892479756436EA20C52349AD51F +:105B6000637260F18F81A19A1876A98FEA5B83B97D +:105B7000550B8EBD22939096FE6DEED24CE0D6C0B2 +:105B8000D7EB9E3B592BFC75D78BC88540EF8938E6 +:105B9000C08AD794864933DE0D459B8C16F31CB61C +:105BA000DD33CBA1B483ED60ED654D6E48CF075377 +:105BB0002DDF23AE7BE8E7234E9835FFC8428E9C4D +:105BC0004CBE1D53479813D4C739E6C6ABA26A042E +:105BD000AA3A2574A4D334745B7EFF4B198CABC9ED +:105BE000F47B6F43E873B79F58B6EB7520947A6DDA +:105BF000C19308076924A6E568E144ED1F39D18EF9 +:105C00008EB5C71E5D0755A9A4CB5A72463DC991F2 +:105C1000979C75640ACE3C770525EA7670023918A0 +:105C20005E7B743DA1BFF4D933400CE15C0ADE5DBC +:105C300042F6F7D5C24BA43D85D52FF95581397968 +:105C4000E30B5E39113842CA327DCA87F32B8919BA +:105C5000FB8D9CD048C760615DC755212A9C12BE50 +:105C600040401D5C7C00CEC9525E6A5E9054B6C74F +:105C7000577072A78882161157790B0C43FB159247 +:105C8000BB658375BFE564F9280B1F594D2AA357DF +:105C9000C5B29380B13948DC302ED96854DFB02AC0 +:105CA000BC92C46A3D7B79878CB73985C60868ED9C +:105CB00000E445EC6004DBDEF3C011E8290DFB8055 +:105CC000707B32CC3F00CA53D9F33095F2ADDC0281 +:105CD000AD063BA60F120D4DB20A3A78C31D7A529B +:105CE0008C3EFBF2CEFF6FFFD093F3B1E56AC95350 +:105CF000047D825342ED4F21986AE968E88EAE71C7 +:105D0000E73743D030E7686B7C0AA41A94D40CC9F7 +:105D1000A86708BE89F264D1C5D1ECE8EB0212C6CF +:105D2000228D2CB2BCEAE6BFFE1385ED308E840DC9 +:105D300005F2B80A687AF7E87E9CACA6071A338E9B +:105D4000E16DF91A67AE408E7C63B862D87BF43996 +:105D50005BA387BF95839575AE3FD658BC09260FC8 +:105D6000A04A9722D510ED84B1842BA02F784F73D1 +:105D7000BCB4155A87C3976563672DC4323FFCA630 +:105D8000CDA96B0BDD9048CBB95F1BE923210FC474 +:105D9000D5BF35464A3CE708FC429AA8F61F8794CF +:105DA0001B246373C9ABDB3EADD13909CA866E953E +:105DB00035F6D9254E4D167BAD6A3A91A515E810FA +:105DC000D829CD4003170DEB121775C13AB2B5BAF9 +:105DD000AAF5E3E40DCFBFB10777E3E36665487E3C +:105DE0003CD76099C625D504370FFA69EE57AB9BAF +:105DF0005198A493671ADB2CFD8BE5A4F6DE4528A9 +:105E0000602DFAF8C1947E6588D95D7AEF80F47FC1 +:105E1000ECC1FEBF7B0A2E484A62ACDDE285453309 +:105E2000C5241B59E82A13650C273808A685CC938E +:105E300047DB10C1AA430BAA4B9C986588BC67CB73 +:105E40000CC8DC6F0DD493406F8399A11A0C4C39A8 +:105E5000AD505F11A993B8EAF300F1C84EF108897B +:105E600063234E8C358D1E2842CF539DFBECC60319 +:105E70007C66A73BFA9168680B9B9D0166E60DB1B5 +:105E8000A86975301FE9280F1772FDADBAC0954497 +:105E9000C5D88E876622B327A28F2250131D6BA907 +:105EA0003946B661093826F02C5D390C364BE2E1F3 +:105EB0008BE4A95BDC78F26CE626D980F41A52C731 +:105EC00036C0FB21CF7A276D032A112880517A1D15 +:105ED000EA1BBB979C25317336DCC822518A1DB959 +:105EE000A4DC0C7E342B385558E25DD95619A51721 +:105EF0002478AB94FE34467CC112F816B10C14E839 +:105F0000800BDF92F2DA658FC5BB2C9C78DC72AF18 +:105F1000E7309CF57B2827F1218D7280073F7005C3 +:105F2000B60273176BDFB4116FA9BE858052A472DD +:105F3000B70911D50A35F48E202424E8798C76BF70 +:105F40002A47381037D4EF863004CCBD30490A7662 +:105F50000CD1831756CBF5E7BF51CA499843B60316 +:105F600014C6C5455E88F87AF59B580067167B8392 +:105F70007E00AF76462F1DE6F75F21E885AD0A214A +:105F80006D35628D14D2F459EDBCB2110D856C4C97 +:105F900084822E74B5D12729AD717465276732DEEE +:105FA0003098D076F810E502271DE1B38D215666B2 +:105FB0004789EBDD2E260D369B9A0A5DE60A28F608 +:105FC000D19CA111C8C6E493EE4B2A45A3B7048B1C +:105FD000944D4B631870B9E15276A5DAFEE6CA61BA +:105FE000F4C44EF8F797F32F2B723315A91E21CA6C +:105FF000605A71A7F4EF3623A7E0C239A55A4E05BF +:106000003237F92E06413028C2738ED60E99730CA2 +:10601000CB1C7A2F1761CAA8676C46DD680A54D278 +:1060200040053F682CD4A6EF006594FD974BB16501 +:10603000F92EF5E63BB18AE2F8B1512C4EF31AC8BD +:10604000E43111B629975F268571CE50A4519F384F +:106050001C42D461C55ABCD32D7750638204A1423F +:10606000DD0E82E055E44D4DB1255614D1E44C933C +:10607000C19BD24063BFFD125001DE6BE2BF924C68 +:106080001E1F8F0F8E1E5F0567D26F407730AE2CBC +:10609000EC98009F6BD7603C4269B55400ADE7B007 +:1060A0007E0EF0E1A7810DAB27621888347A807EDE +:1060B0006BD8D321B0E32E443930B08086B18FA79E +:1060C000ECBB4A9846518DC77357D04052BF71D927 +:1060D0002870198E5CC88AF55D87D7ED1126B81E29 +:1060E000BC885C22A7FB4D0224C6AA68351E30DF9F +:1060F00016D3C50BD7B7FAB9E577D818A24610EB77 +:106100008A354BB3D9E016B9016340CB5C732B7C65 +:10611000682D390AA5C9B51DCC61E072D1BF6EFAF0 +:106120009CCAFEB7D0360D57470362F2E34F807822 +:106130003F713947449C212753DCF5DF7FA9D10CFF +:10614000E36B2BC090BEE53AF11AE586942D35A598 +:1061500079DD5C4CC407C0C3105B64A9976593AC40 +:1061600019375812389160F5D1EA35268B453065DC +:10617000F59F5481FE3B04FD33BA890DD1AD19B4AE +:10618000EFD15D2995C37F9788F97DC9528C58E47A +:10619000CB3B84B829C0CC7AD169E239F2CFEBE7A6 +:1061A000BA4922A67F49A5FF209EF5128233C1D6A7 +:1061B000E000F6C886238793A4DEC5EF136DCA1EE0 +:1061C000BA3AAE157E12B65A18AD89C472A443D23B +:1061D000D084E61E8E80F916AF973FCFA5972B4649 +:1061E000030A69C44EFCBD623DA30428A4D790DD18 +:1061F000DA0207DF8946F779C625F3866574DC4243 +:10620000524A124F5EC20F81A943EC3DC12779EA81 +:10621000AEA4525B1AF0055C058CBEE951B64DDFA9 +:10622000D9EE949FD86FEBE7F01CCE1463E33D9B4F +:106230000740EB8E84A3B6DA794DFF1AF6D39AD4D1 +:10624000054753EDA3844DB8ABB1E235DDF57636A5 +:106250009EEFAF0DAE9A30154B906A12F2619446E4 +:106260000338F58979A218BF0B8113E9DF44108444 +:10627000E0DF31AA9E7AFDE40AA6FC822DD9504BBC +:10628000185501DECE5B6959508FD237000B7ED690 +:1062900017205AFD7071E386F590AFA60085AADB42 +:1062A0008B5557AEA7F47971A2CE0D356A25DD1B4B +:1062B000AFF011D9C61B1C6BF1C1C56011E2A7B6C6 +:1062C000A1039321043D0C5C5114260BC48171CBB6 +:1062D0006FA0088359D1A9555A65CF8CF8C2EF58E1 +:1062E00060AF0FAA9319034DB4639A64356468EFE5 +:1062F0007FF2187F644200E1D10B8CB5C14C443E63 +:106300002132B7416F8DE8B97E6271590E23556A0B +:106310000811206195AC48AD2CBA56F262C248B162 +:10632000B7258B2CEF6CEC003B6ACFCDF808ADB0F5 +:10633000244986D56811543CB9D1A7426B6DEBF462 +:1063400058419BD880376BB9DA4AD30666FB1FEBFE +:10635000924AF7AE678B622F9BDFF730921223D001 +:10636000A6C555276895C934384395E2A264816370 +:10637000D94CA11AC40D61FAA8DC4A89F3AFEBBC71 +:10638000C5FE501FA1C5D79C73BFE4446FD0A77C46 +:106390009A456F4AF59D4EB1C729B7DCD565FB8B91 +:1063A0006E8785FD817536AFA606CA27A65C6998FB +:1063B0001A4C5E39B08893EEA5F258ED369296EFFE +:1063C000D38D3E3E4F8635BC69D222197A2F0C0FF1 +:1063D000C7FB13C0F8973BEF3B81148A160BE4B55B +:1063E0006DD8E159BCA6715D024D99D7A762FF3700 +:1063F000C9591BD721641339F695E0ACF50790E72E +:10640000FCDD79F9FA58A8C52918C5D4B6DA9AA8D6 +:10641000EE4218E50280A932BEFF16F5F61D0535DD +:1064200047B40893F262184D7BC93FD6972FB8C680 +:106430005E26157B3A30466FADC34E5FC5034956A5 +:10644000D4B22F7C4F1C6EBE8D42BD915A9B505BC7 +:10645000EE4D968E436B68E45AFE32CACCE96DC2AB +:106460003E1F608A0E21C52D1ED7D4614635074FC9 +:10647000B12DD3FC38FFAAC353360C1C1A50E418B4 +:106480000AD8AD1AA963DB83C84D6AA24CF9391B3F +:1064900056853298BEE3719FF63F2734FF8FC64979 +:1064A000B2CEA535728D7294B8E142B8E05BCA5D98 +:1064B000772639C01036942E777C55EB94802E9F2A +:1064C0007D60F4D72C26A3F3D6E8B3921DFA3E28BC +:1064D0002BCCC0B287E2A3A2D6252183329C344DB7 +:1064E00048D86E99203AE4EBB93057CD2D43417D21 +:1064F000A8951FC627C369956233AFD04B0592E7B5 +:1065000033F6500FEFF84CCD2DC9DDBB8CA231D244 +:106510003CA06CC12C4432541E7A019878C87BD9B7 +:106520009EE62DA2A8DE705D27A92DE3E02C1C427B +:10653000E306257009001D57C130FFA0E1043B614F +:10654000B346CF443E29F2FABFA4F338992FC6854B +:10655000B0C0A82E6AD9290A8BB1F9E7A9DC09DDF8 +:10656000B1EEA2B317B1FD311919F8563D5AEB5EE1 +:1065700008AB8703BE98C83706C67A92932A4DA700 +:10658000D75A2CC2FF44A977B83FD04036E07C539D +:10659000348DDED05FBBE1BE0C2D14B0BDF9C661F9 +:1065A00050C09E62753240E3CB6EC7C17AFFB90618 +:1065B00038790CB7FABBA486CA5FAEC35E0A4C8AB0 +:1065C000F6DE4B3C87F97920704B94F1F753361186 +:1065D0004406EE778E71BE5424FE90EB6A3BFF9F1B +:1065E00064956F2940FC4BCED5256B3C7F0360152D +:1065F000039627CE7BFCFBE91D0FD74B641B76630C +:10660000F795647C95F18834D41DFE538D25A9D16E +:10661000FBD0F93845C3C536C63A66D1E8ABA17799 +:10662000FF95B903B51C599BAC32F352F4B5B59B39 +:10663000075642CE810EDA14CC786FAC20B361D607 +:10664000106C1FBF9B232846E4321ED41ECF2F0997 +:10665000CA4D0F2767CB0A6EFEA4C621419F62D4A4 +:106660002DBF5331BB6C8FF25CFD51E6241EBEC3BF +:10667000B8228EF288DC8EEAAFF9EBDC51A0A5558A +:106680001D76CC845C17C0F2A7AF2A8298E4B8AF1D +:1066900079BD68D7C4A50DBEA66F983C3EF43CD525 +:1066A00004A271BE8E00CC9D978496520D31A287B4 +:1066B0003EB74CFF025BC382EE6B2CB50BA8857E08 +:1066C0008DC5AFA9FF8C70DAF5B8EBBD6A889E2E38 +:1066D000FCC3A57B63240E44D4DF59C2CD79B2A993 +:1066E0000E50B10CEAAAD1A1A23913EFC5BE108396 +:1066F000B369E1BC6C3522F1B66AAE8D93B436FB5A +:106700001B4FC9E29C84658BB8F8B4E8BE870F10B4 +:1067100070EA75C41366467B0F4AA91CE34B5F3BC6 +:106720001CCDED38F1DEB14B513B5DFDF7D0D52FDF +:10673000511A1208731FF868561E0B21921C12B1D1 +:10674000AD6049AF531706E3CE238096E87722FB6E +:106750000484069A22BC45012E01F2BD7BC284D876 +:10676000090C83425E24542FE2A489A2CC97D4A2C0 +:106770002D3915436EB37CC49B5887C9281275C147 +:1067800007A1FD521E16BE5613C11E915DF185561E +:106790006977EDFF60EDFC4634FFCEA965CF22BEE0 +:1067A000ADFAD41C658053CEBCA9D99F5795CAD6E3 +:1067B00040A70B5EA98DEF9CC6854E125F7115BA7E +:1067C00066AA9B0873B717534B7EFF76D970853B3B +:1067D00066E6E158E9146DEA2153C055257CDBA536 +:1067E0005477EBFEFFC551AD4A5CE158073DAFE47D +:1067F00064BA3F52FF7EBD76BD8FB43DF18FA75284 +:10680000F0DAE05570A323BAA24D22A201A02F6DA9 +:10681000EBFDC240EF3DC3D591CAEC132F698C5EEE +:10682000529547BF26A41D7F01EB60D92CBD41BE08 +:10683000E9E4A279A04E629DACD4E6A0CA016FF94A +:1068400028CC24AF8CEE0FDAD07BD1E05BA1F5A38E +:106850003E606407BDF1AE03FF116450CC7B65B8A8 +:106860006CDB69641B31A73F52DB969E6A91AB6D6E +:10687000AD0DFCADAB59E2D568D5837CBFE87FB3E5 +:10688000B0BC283B6299CDE02FB23016E428AF9817 +:10689000E53E052F88148B7539B92A395707E592DB +:1068A000780FEB9C69E1384DA78C4A20AEB82C30AC +:1068B0000C73329D3A0CB4AD1589148561D189AC45 +:1068C000F65D50EE8EDD9D3DF7570B5E783D51EF46 +:1068D0009DBB3E5D9E46EB6EC638E5FC0F76C489D7 +:1068E0006E084E1BEB758ED6DF71F8B6D2429FD183 +:1068F000F0BB6F5B2876955F765EF4A2C5559F92DC +:1069000049EC5B77395BBEE9174506D0F73931C6EC +:10691000CF4A2DA04F25FC60443CEDCDEAB6475947 +:10692000FCA7421EBE9228DDE3CBBE7445AAE84B0D +:10693000C8F2AB82DC08752098B66E0C92C3007B5F +:106940002E85DFB69BA760E061C6D54A31B2F61F3F +:10695000889B57CDC6B5AB2B963128E75F7D4DCFD1 +:1069600098C93A3191ECA5226388B06551B872F5A7 +:106970007D91D7B41585BD3151E4EAF729E5A95ACF +:10698000226B91DC4DE54FF85121B08CFE90A74869 +:10699000CABCC426CCC96F783D0558DD6199542B1B +:1069A000AE373723F94D61EA1A90BD5E40D80A67C9 +:1069B000812695AADA3082B8EAF3331DCA4386AB42 +:1069C000B0731B918D8D3696E2FB577327C7E95C38 +:1069D0008877889101CD68FD70FDF55CBC3B36671A +:1069E0008F06F36EB95CEC25277BD20549077BB691 +:1069F0000D8CACF65073AB3803F0937A58903BABE8 +:106A0000E64614B9C21AFFF373BA7C4AFDED76C3A9 +:106A1000D85F63C8339CE123AEA34E110360D66CEC +:106A2000004515B34D5D1DF7FC6D71CFC20EF166CB +:106A3000DA518E9603A583588FF6FFBB721FFAFFBB +:106A40007AF3AB57CE12836136A121D946486B67E2 +:106A50009EA53396976A5E8BD515BF25342689FC93 +:106A600090F5859A293523AFED044F672DCB5186DC +:106A7000D6CC848357DE47C04C438AEEA88F65C9C5 +:106A800057D5E4695AE10A054E8D4496C0CC92A7C9 +:106A90002E05F7FF4127BD3622BE40993ACFDD22B1 +:106AA0004C8C5FA747AEAADDA6C503D6B4085574C3 +:106AB000CD2585531A62D625A3194B21C147F75915 +:106AC0004FDD3BC7C3626BF55FE35103C2C6659000 +:106AD000E92778A3028E01CC688B0330D1DF95C8FB +:106AE000F56F5CA3CA9D381533F05353AAF7081EFF +:106AF00065527D29E4CF69296E2218A4F582C5A2CA +:106B0000D8BD21007F4E84AB9FF1A885925199A7F3 +:106B100087598581A5D3893C752BABC0AFF89CE024 +:106B200078DB9C65A7713C081A169FA4DF0763A950 +:106B3000094DED3F96BD162E2DBC89BF762BA24187 +:106B40006604740C020AA516347F0826DC2694F627 +:106B5000C72A6052D7AB15D92C628BB62268E60ED5 +:106B600091A8C8AE18AF82AED6E5784AF9C0414BBD +:106B7000B2B76E6B98C52CD1903EC0F4EB0F0C3EB3 +:106B80006FA881481519E14E64F83EAF17CBC9DEF6 +:106B9000B1B36ADF9CBF36C806DE489E4E088E7AC7 +:106BA0005475DB1BAB6F1AC8D198BBB67FC597D89D +:106BB0003452E5D98F1F6F73AE543034BB47E39521 +:106BC000EA0B5AB5694A93B016A1A10FB73EA60FBA +:106BD0001257D20A44029EE49DB2BE23D624E65345 +:106BE000CAE8A12913C9A05192FF2ED39F34FC45B6 +:106BF000DCF28F7248E222996F08622EC4EA71209B +:106C000003280872BA239F60CB319A8A771D42B954 +:106C1000B19A074B5EEDB79EB1090C1C570874F48E +:106C200026A6B0D3F40A3AA931C3C45C69447824D7 +:106C300068D321E2F664BECD671701B04CC4721C64 +:106C400084EDC8D61BC242D8CBC5B808627880FF95 +:106C500044FBB847A047E951F33BFD87B276A9A2B0 +:106C6000095761AA7BD485525E4BBF240830DC33C0 +:106C7000B72710248A03B19A11B03B7E0B145E7AB9 +:106C800010AE2E5B805004B0F62AE7463444C06351 +:106C9000A0180AABDBEC46A7C3DAE6F0E450A0B4D8 +:106CA0008F47BEBB70BF9BC93C73FA0FC3EB037920 +:106CB0005B76C1183F6C91EA4214D4D9CBE7AF6937 +:106CC00002168A5220AFC2DDDE77C4B8591636AD3F +:106CD000E50A1A296B67FAA153FEED6AE48C93600A +:106CE000FE0FD5818AB6F6E6DD825094C2BEEB96E1 +:106CF0007C9099A7693BC0827A94EC2976CE429029 +:106D000046B140DA2271FA8792099A1DE12BEAA76F +:106D1000D5A0F6B951675463BFF0563D883659A3E4 +:106D20008B35F4EEEF7BB98630CB6DDDD381CC664D +:106D3000C57980495EE37C7009A1BD958349E3F183 +:106D4000170ED0D7E17215BBEAC72ED88574B01DD7 +:106D5000740C0CBE5397043503FF514FB3B9704701 +:106D60007B8159AFCCCC5FE3F5A1EB6D3B388698C6 +:106D7000D2F5D647AE7B053E45C2D18D4D9B0BD09B +:106D8000C87286E97C85F696D9423E978A51DF1C07 +:106D9000050537B88D111D349017B3E64C1CFABAAF +:106DA0003A82B1C06DCBD5B3B15A894E009134A5AA +:106DB00054D85A506BCBE4D26DE1E5F4B6EB2256D1 +:106DC000F99F11A322231520A7A20B97D473300794 +:106DD00061D8B442EE21385320035ACAA57B2797C5 +:106DE0004182F98DA602093B647285695B53C689AD +:106DF000A599CD90C59578DE4A6677F3E50EBF9DDF +:106E000059CC0D83AC84041189EA970DE9DAF31F9C +:106E1000BE377B7C88598AEC59E2605F1C40DF36C4 +:106E2000C9DF2DB75229FA921AF43C533DEF77533C +:106E3000733AE938E8616F5A06DB42316E9AB73827 +:106E4000403604198EC11737F55C0750F4433426D9 +:106E5000FAFCDE6D3A48ED30CEC575ACDE6603FD5A +:106E6000D8479E991EF6AADB8D0E671A3AAFA70C7B +:106E7000556A9C600F008BD7D798CEEAC38322E671 +:106E8000EA4F246A2F95578F89A6EF97CF008A1172 +:106E90007271D61F6DB5DB581180A915C7C24E9D02 +:106EA0001D29D78EF5AE1FE7C44814AC54F0721AF2 +:106EB000A00C7F0644762A19B00E7CA25AFAF8205C +:106EC00006B21E4689AFB498014A5F1C1DFAF4BC95 +:106ED00018B966C2BC3BD2FB9813796CD052A03F64 +:106EE00030EA7F587DF7BFD2A40A848C2A143EC3AF +:106EF000277EC3B4E912CB6659FE15E3C187D4CE11 +:106F00008AC138CB893F922BB6DAA471200D77273E +:106F1000909A6933CCB0D54ACD6339F4BF85435CD0 +:106F2000BCF0F82D6864146FC8E6FE8438BB2A01F3 +:106F300022BCFB7F16BD55FDE7B53D9E71C1B7670D +:106F4000C77193ABF90D8472F7B847AE9AAAE740C0 +:106F50003BB1FC0C7380EF8DC6DCE20F74DC435751 +:106F60002BBCAB966FC8555BE335BF9D76F6A398F7 +:106F7000B900DF1F935C022E6FA9A6C5CB1A35EBB3 +:106F80007E14178D69272283EA62DE89099F3A966B +:106F900001D1A7F45758254E952F37A398F0DF302D +:106FA000AEBAF5BD17C261B7A6F4EFEFE54B954851 +:106FB000A22026F0C7279450BE3C96330FE7699A6B +:106FC000813CD5881452D095D888CB482AAB51B68D +:106FD00066D35A8C8CCBF860AD59731C56C8B4CAB2 +:106FE000245595CC2000F1D9380E6244015605375E +:106FF000E7D1D09B0943C279B6F3213FA092F8694B +:10700000363FC81E4CE8A95228766032C2708DA364 +:10701000D7F56BDAF061A0913979A4BC5B374CC627 +:10702000BB5BFE92230224BE11783A30E1C13BBA29 +:1070300058515906C5269FE88FD53A0C091769A9FA +:10704000A0999BF3E5C242A600D2D4E5197F838BB9 +:10705000ADFCF5F28865A4026DA3BADAF887632562 +:1070600008273FCC3B321D7C3574BC11FA577F7228 +:107070003EBADB8893D844E9A046596DAFF535E0B8 +:1070800009D9293937112426748AC588C59A92D21C +:107090009686562FC8D7E6611DEBFC922940D42373 +:1070A00026507C4762643612C0DFC86698286ADCC6 +:1070B000B5176557BF968C910EA22464DB12697FC9 +:1070C0008081AFAF8BBDF69237C3098F9980076976 +:1070D00013170D66C8F90E67029C755557BD85D10B +:1070E0000E9E3ECD7BE2BBFADD5AD36075339D73B5 +:1070F0008F943D416C98E19FC8546199CF2F57DC24 +:10710000DEF6D7D380CFCB2BB6825E9E2B7A9464EB +:10711000594141DFF81ADCCAA75E3A40497B4D0964 +:1071200093C4ED1238129F0AEDE977D7D434D963AE +:1071300052C577F3849A988FF5DCD8EF7FD902F89F +:107140003D7E3767676301A854B20F8F5EAC6DCA8E +:10715000AD9289D255D7E0D7177B1BFAA5DBF34454 +:10716000F22CEBC280A920EDD093917D224C55FBEF +:107170009FF1F743C5A87FCD3DD5A3E128D4261ABA +:107180008F2AD637F86A67B102106DEFAFAE06A44A +:10719000EA44F4058E0F4F1EA41FF73E20DD508FEA +:1071A0003C4471833B596B4FCC39F8A4F0206AA161 +:1071B000901D89185094A9C796886FD298B441E65B +:1071C000B81A85115EBA7B3616D81A3D2071398DF2 +:1071D00097B00589D31A0C5D263AD6495E19D3F8C3 +:1071E0004B43149889E5DB6B68AD60179573CA92C1 +:1071F000F3C58CBB5A0604FA8CE4EDB036BB2347CA +:107200002C03E93535FBC5F97DA627BEB69BB472C4 +:107210004D9C8B05A032B9CC23F5DE4EA0F8DE667E +:10722000ADED7AA4127C8FD580348AC9F7D391D67C +:10723000071725B67726E05E6016B39A3B9B99F553 +:1072400055B48DB58D0B7DCE68F5C1CA85CB1DDEDD +:10725000B046C268DFCA695462DB55D5457650B185 +:1072600094932BDCBA90794174ED574E5754C2C8B1 +:10727000C61FB76B21DAA9284C3D94934D396A8F0C +:1072800084A7457013C2034826DEDC4BE640FBD9D9 +:10729000477B653DE9E3CF75BAE280340A5B50195C +:1072A000A3344DBD7F89B99EE822A5902607C20868 +:1072B000CA704BA2CE59C9CFC9CCAF3D90C107EC23 +:1072C000CD1620844467CC57AE96D5D78B80C94D58 +:1072D00058CC2760F6DE2A95ABF3F22AC0D8B17CF1 +:1072E000633C32F854A0E7B3E96A1784113F6FEBAF +:1072F00037AED1CD01DD05E682A841E355290593DE +:1073000026DBBDD6213BE7E4FFB9196E6FA011273C +:1073100089E2446CE5D6C160641982B7DFF1A3BB92 +:1073200065D473BCAAA578FCE475876EB7C8776B83 +:107330005E90B83CE7A31727FB5DF8839EDA18B18F +:10734000819130E981722B7261CCD1299ACF50E1C1 +:10735000116B4D748405B69A9C0948F07C8C1AAF69 +:107360004128CB4DD0A3D077F9251DCD306967BE1C +:10737000FD8A09590DFA229EEE2E888ABE0BB9AFFE +:10738000E85FD7952429C0C30FFD469FD7CF60493A +:107390009DEB15FBCF35C1273452A504B1AB5FBDC2 +:1073A000B061BDCFE53734A9CC5BBBA43EB9FDE4E9 +:1073B0000C7337CBE91A47D7338075A8FDEAFF2F46 +:1073C000EE3EDD77FA310F8020E0902A2A4B158CB3 +:1073D000C1782AA38D97CD043559BD465E69103317 +:1073E000CA9168D7C6022A2583A32CD00F7C327B92 +:1073F0000FE1C3084BDE78B04113E8BEB5557648BF +:107400007853F01A1EBC85396C4FDD3673F4F29553 +:107410000F69131C68338389B0AFC88E59284CD8C4 +:10742000F3F8C3FB7C20F76157647D1E9E1D7550E9 +:1074300023DEE6FE02B3B59856A68BA7410FA8B887 +:107440005BF11499619AB2DC3E21620E0679151E39 +:107450002E6B8BD847527D7A960035E359F74083DF +:10746000B701807D709254B2D39455401B5F600980 +:10747000CC0613CAEC21796C94D4C26345153A0941 +:10748000ABEE2F1B34C217C21A398145B2BA8BF842 +:10749000F158B0EDFA1C83558A94A8D73F23B4EE77 +:1074A000B7BFC0DBBA67B97D00B3A027E9C4960EA9 +:1074B000B66984277186CD3BAF2A6B0044472EFE08 +:1074C000818D537CB81F04C55BBB8AAF548A1BC532 +:1074D00073FBD88E9BB9F33520A1A0EC68BE99FC54 +:1074E000EC35B1445A7DC7C0C5B9B48DE7671DE519 +:1074F000B1DF4A2032D668AD8301F560EED0791451 +:10750000F4A9973E817A15D5F7CC26BAC787D1D78B +:107510002BCFD8D482290F7ADD26696ADC81EF2946 +:10752000021AC3F47EBD6DE6FCB3E7FC7ADA52BE04 +:10753000D043145A51FC0F40A4B6F55ECB156CD164 +:10754000873CBCC04BFCE8547F219F5F0BDB0D4D9B +:107550002E6743BDAE2572C9EBB714311FD2ECFCC8 +:10756000B781ECD54F23F88A7F072EAF9A754D600F +:1075700065F26F8866DE1ADD3152738F3296C974F8 +:107580000A5A9AD67822FC8C052B3FCA20EBBC4CB9 +:10759000E942FEDD3E2B5B521AA1CC505F2E3243F6 +:1075A000EE1B4107CA6F3856B337DE4FAEE4F39E89 +:1075B0001CE848A7B2F4F7163917A2C24F928D26DD +:1075C00075D0EAA6DD7555F0838FBBBD57D8291558 +:1075D0009720CC1F9B394A7DE069E0398E56A0C4C4 +:1075E0005E3D442534A1493A1BA4FCF6936DDD921F +:1075F000CCC00CECCF5CB9E1641776F5B74A88567D +:107600005D1B6F3188AA24A380024DF424C4B667A1 +:10761000A84BE50EA6F31F71C5E20C22923D742C17 +:1076200001F48BACE2D2AB3FF8FF62D6D06D081408 +:10763000E1C00DFD777AEE95CA171183DD39CE656D +:1076400091847F91791B5C08EE7984357CB0C1C34D +:10765000D1F950E2768609AC99E08EC847B01E8316 +:10766000DBAE124C79C490AB6E8CB8DDDE497D6C1C +:107670007DD34A3828130C2A29EED144C95E15352A +:10768000935D7ED3AF4BC040764814797D8541969B +:1076900036FE7EA7F374508B4E128A59F744CDC341 +:1076A0009D5E3A9AB739877F1A1E620C3D78C427CF +:1076B000C243995FD186A3AC624FF17190C86D103F +:1076C000447559EAB7521F40E95EFF236D00AA11C5 +:1076D00061DFC4397FEFECEE48624BBB7FFE1235B1 +:1076E000EC876F2EF9F28E20C9BD366C695063535A +:1076F00069E9AF76D91ADD94C16D6B7FECB5F330D3 +:10770000EDFE8AB51827DA2E19B562A9D3250F66C2 +:107710004CD356AC1B7C4E04981AA82759D7A5A960 +:107720006B24DBFFE4F0310A87B79ADAFC0DCE3820 +:10773000F86FEBFD888CF05C00236877A7EF9D8DD8 +:107740002F8AA0836005E563E4DB21E75B68A3245F +:10775000CF63389ED9144465C62D2420F1C7B6D80E +:1077600010345E17DA4BDFDF36EA225DD12E993412 +:10777000367F2D0510099F47A56DAAFAE721017BE9 +:10778000E6EE50B132375E53FFE924B30F2BAF1D45 +:107790003FCF4BE5DFA5D164AD6704E9CD5BC9C43C +:1077A00089B8CC15B0E79F30AD544EA4C874F144ED +:1077B000319715CF29A396D33584ECD003AAA5D54C +:1077C000389789E5468FFAD3AB46A9A968201FE907 +:1077D000BB7E31AB9BD8F0A09E1E671ED098ED6695 +:1077E000CABADA0A02364B5483FE3D8758FCD68566 +:1077F000386278B5110A90CDA97176E76B78566D2D +:10780000BBC5A36C4DCA2BF51F3BEFC368C2F2DFAB +:107810009945CAE1346F1D4AC67D6507C70A5B3CBE +:107820006B92FBB908991E88971D5DD0134F712C80 +:107830000EED7CDEDD44746A50FA5F488BD4DDAC1B +:1078400015895F553D6D0E082A3D2315DB38867A74 +:10785000948BFB38689DCDF691509A1FEA7980F69B +:10786000620F1E1B3829579D6AD018D4B67ADEE500 +:1078700044BD759B6D793DE7D0680CA06F289FA62D +:10788000BA741F0F93EA2C0FF86A68F2857028F813 +:10789000433D6DC278D2EA760C999B8DD83769D773 +:1078A000037AF3A611EA2EED3D8AC41886555822B4 +:1078B0000DDEBE0378832B5242E75515BE6C7B7FED +:1078C000247F8CEEDE9CB73AB51ACEBBA55FEC33B5 +:1078D000B1065934FBA1CA41A043C616AB68B38CAC +:1078E0000C3E4AB596A6B0AD92111075F032212724 +:1078F000E263782CEC71A60AD3B1680C215ECE1736 +:1079000023556B5FF9FDF2D232BFA4F195522DCE13 +:107910002FE4B9D0A0FAF409AD837BC7255F4D0DE4 +:10792000F7356477FA934C8D99622914FAA840E8E8 +:10793000A1FCDBF7624FBF1F9E3EE4E0B9D6D73F04 +:107940006F15CF529301AD0C284154896042969A2D +:107950009D891C18DA4BFA9D31370BD1563325E23D +:10796000C8C1B33E3D057C52C7EF827D9D83B7B051 +:107970006C29942E35FA9836B102D7D87244603CFF +:1079800008032E53A7F2B9C0E1683F16D67991A635 +:10799000F9241701451E659D6C6ADFD7476697235A +:1079A0005D211CB8FEE6E53555103F05EBA92A4FD1 +:1079B00072598297F9835B2E5C20F4EF7A559DB063 +:1079C0005D72C71ADE34A7FB21ABCB48FD04D88E0D +:1079D000548B3D08032855EA21568E21E08EA5954B +:1079E0000500A7A152BBB03D79F2283C378F244057 +:1079F0004E3A6AC76F34E9F6FA62BE42EB124E8E17 +:107A0000060C17438E5DAFE1B4686A2E84F29702CC +:107A100007EAB79B31674894A3FE823877F70EEBED +:107A20004183C4607AF6A96D0C9B289C938A33929B +:107A30001BEBAB76EEB99EC11DB0B8C99F1569921C +:107A40001DD7EDEE0838851915DC11EBB2C5DD4404 +:107A5000CEB7B3EDDF7F175FE9AC214F2BB82B0515 +:107A60001D704905C2DBB31331CDF5512C9B79ED67 +:107A7000E949CA324FE28A62C8AAAA5F1463A870B1 +:107A800085515740BE1A8BD47DB23C53C7637FDB10 +:107A90001EE222C38A2C48E5AAFEA88800FB103A01 +:107AA0001F30FE9589BD52C2F3934FCE40A9941E5C +:107AB00062CDE1941DD0E091D4E0CA0DE1BB560047 +:107AC000448F8427EFAA51D33AC884880041B4E98F +:107AD0000ABDA67235E686018300E735084A914360 +:107AE000B57D00F088ED467E839B4894D88B5FCBB4 +:107AF000AEB0EB7C9701F2107A63B6FA1E49AB8305 +:107B00006D500D638F8202DA0981771608F3E26601 +:107B10008ACF9E4035B500B4C0FED21F84EEBF357B +:107B2000AA105E67B15716A5BFB5BA19219860C3F0 +:107B3000E99FA4E33E36E4301D1842FAFB6426BDFB +:107B4000DE8819B49A5593DB9466B56D8130010CCB +:107B50000302ED4E6F6C23544346434015F1949A53 +:107B6000F4BABA825263B21DA2E0D08844D9502A36 +:107B700049CDC515401938F5023E36F0F5D63459D1 +:107B800098BB9510ACA2E334F9B97A1C53F575DCB7 +:107B90009ECE4BF8886FE46F20AB19D8391A1C8B36 +:107BA0002E2FB05963630B514C296140271CDA45D5 +:107BB0006ACE043C26A100F1980AA42BBB41FB49E4 +:107BC0002B78068A3049177668B0FCCD4E74E1D424 +:107BD00011D783CC4E96EAF0B20F60F97E316F4F29 +:107BE000ED505D138EC9EA0084D61C365A029C788B +:107BF000C141368C5DCDBE262904E26FBED48934E6 +:107C00002B5F511B58CF2D05FCC6E6627DB7823530 +:107C100003CB82CBA336F86227CD34431A0DE09410 +:107C2000DC0E55EA98977E30840CB7C914C71FFE46 +:107C3000BC4FA1B9E9154A9E84C05E19A5163ADE6B +:107C4000938E92D377B1500B6698E4C6020B7C7486 +:107C50006BDED4947069A3091104DDF781FB459EA6 +:107C60007A6F7D63193134B9EFAEDCF4221564F616 +:107C7000978A80696821734122EE52284252B15E90 +:107C8000CD14372C5017E988E36B77B93B5AB08392 +:107C900013445B7999447FF4EF67D36C09E1C6EF35 +:107CA000D17362B4E08EA87E68F5DA18A7AAC9DBA2 +:107CB0004687C82DE2A0A5084D3BF6100A7897C06C +:107CC000A6398A4C43450E2BB886504134899E878D +:107CD000831907D1806D18F75D6B894AB2FD1E3A92 +:107CE000E0BFD0ACDE5C1CF08322AA586506A30D71 +:107CF0001A547C766710513A9D14D51DEABEC57A98 +:107D0000FD0513D84923DAC2593BA9A63A7E0EF5E0 +:107D10008E1859EC507827DDC5A6718D16BF352F0A +:107D20001DB6C3082714AC8794AC6381CB68555C3F +:107D30008EA1F3E425880B265DFADF684A1C1B6BD5 +:107D40001260617596934CEA67A57A75DC17DCFDC5 +:107D5000B88D8C90772275AEB26963BD343B1A85BD +:107D600078C8F4F835334513E1DE959F2785136D08 +:107D7000AD2FD72E3CE3B53F97042CAA13F73869F3 +:107D8000DAFE3C1A679DA2D13A66A54F7729750F96 +:107D9000D165219575FAB1C890F101C907EAC9B159 +:107DA000269EE10F80C9B42E946C31DD3555F41652 +:107DB00015AA203F63EF42FB9908D9E6AD9E169ABB +:107DC0007F774F200C63DB3DAEF3518C4DF23A28A8 +:107DD000E9E040B47BF8E9FC34D3DAA6ED0C6C4A58 +:107DE0009079437644E9C0FD7E9B9700B1103D8CAD +:107DF00066CA8102D630F0D21CDAF87DF21A5A76C1 +:107E000036F4CD4824A04D7BA0EA9BEB9C872F1A2B +:107E1000CDE498869A7C369EC85F4BEF0DE3384CD4 +:107E2000FAB1C5F671066C92BD09BD1489FD4C0707 +:107E3000B2B965BBF787EEA5BFD8D643DA7148F96A +:107E4000CB95C31CF12F252CC1B1CBF093E1A2D669 +:107E50000A3A709A8A348DA56FD90D095005A25C33 +:107E6000674B653427447D3616F7D7B39053798D29 +:107E70001F6A2467D44C1118ED4DE8EB5EAEC96B58 +:107E8000A497C8F25C1A333E3A749CAE01736F4BF0 +:107E90009C10A0689FA83A5DE42D1F0AC196455327 +:107EA0007E8DE47963CAF8A52B0816983A498EC4EA +:107EB000EC992A4FCACD9EC3CDC8F061758D7C91D7 +:107EC00029F3EB396746729C97CB388546DB54A67D +:107ED000BAF2B5775E7BC491750068C56BBFD8C038 +:107EE00089FA9DE2491785600CFA7C1CA4D0F3EB5B +:107EF0004478E422C6C77FD275E0C55F5D3B27208A +:107F0000026D189292754B2B7A82A5457BDA39F275 +:107F1000B70B33D5CA585A415248AD73BF6F3A3880 +:107F20001E588057AE34B92CF84276FC0AE306217D +:107F300057400963A70E5FBE5AB738BB974A070D73 +:107F40003FA6C453A75B164DA248625BD92D33BE32 +:107F5000044EEB348E5B6285C02E4D20A334E06866 +:107F60002B23B31994E70CAB9DEDF5619F1B267293 +:107F700074C9B229442C0911259AF66DAB405FA350 +:107F80008E8FAC4E283B79FD8C1F938D00692BC3DF +:107F9000D5D8CFFB75D188B2E48D751485960F4D79 +:107FA000E8B0AA57521753CFC0EF6BF5DB6D779649 +:107FB000E4E31D8D6554A4A9E01490EE543543E22A +:107FC000B9E81DED7394BF6C8A89BD0D668D2539A6 +:107FD000A66E9B81C8AED805CD2EE91E25C21AA17A +:107FE000C7928DED60B4BCADD69AB4462B7C1038E8 +:107FF0000690B035B6FEE368FD25BF959CC6D6A3B6 +:108000000AD7286D8D5FE0FDDE85E993D1BB2D3B5E +:10801000DE66CA644A14DCB04DD7FD5C679B8D8771 +:10802000C8813C09C99DEEF464BAD464EE2EB0F563 +:1080300006FD34D237CE47299838EA97ADACB85907 +:108040008F6CB29C4D4F2ABEF6AD7372C554DEEFF5 +:10805000BA5F3BF85DE405197B7D50A5B7C04E794A +:108060007FE0EE6423D34E86248E5507AE9A0389B3 +:108070007F966C3333230ECEDE90A1F054B763B6F7 +:10808000CC37E2F86D7C5D193044873D9ABA55A72C +:10809000667AEE1EEE15A17E2E7637903D7BD2D805 +:1080A00067843E99BE5F4BFA39F7A22CF57BB24349 +:1080B0006414BC8D6D83015FBF06E542B2608F58CA +:1080C000A475D693B0E8B1F78C72573B28348F343F +:1080D000B14EF60A1AB26398F0E935FA07A75B5E6B +:1080E000996300ACE080A233135DCC5DC91AFD4FEB +:1080F000A6E27726BF2F1225525706C1535A697739 +:10810000294BE765952A154A83890FDBAE42E6A61F +:10811000F1A941B5AD7B352C990B822238C80B44AF +:108120003EE376161C2CF8F8E0DF30A71E5840E836 +:10813000E579F6A65F085579786358C42FBE227F8B +:10814000A59606621CC50CC8D107555EC53872815C +:10815000A98B0E4B4EFA7A8276414FA4DA0CAB4AC9 +:108160005A84583E5D3210B2E31F13E783123BD8A6 +:108170001117B8A24E9D3BC0E048FDA40F2082F924 +:108180001666611954EF725529304BBF3376A267DA +:10819000ACFC7056C7C8254E0833A5DF9BD7B87B0B +:1081A000D912DF69A66ABAB62713804E8C97F641BA +:1081B00016B04381940652A4BD5D3A1782CFC5998B +:1081C0008DEA0186AAC486B2C6DB3E49B4B97C4DAD +:1081D0009901973B416940E0E0F2EC21CF2C7AB85D +:1081E0002E36717BEB730187A0D64D8E3106C3C04E +:1081F000CF3954662497EA2343C1D6706A042E808F +:10820000FE1980B1DBF5A9598808A06357B4899E8F +:1082100009ADA45EF598CCACB220E68890F1690374 +:10822000D9C1978874B107B623E276421507AD48E5 +:1082300062AF1C3421D0F9A5878838CC4CC9170A05 +:108240003DC955162056F2CBA2655045346CE44D1D +:10825000A8D60478969AE0788587B748D95036DF53 +:10826000369E1EE721A2E7CE26A13D3BE828A9B312 +:108270000E4D618BCD340879F73771A3CA1DFCC050 +:108280000EC476C4027A5837E44AFCAD27D771F69B +:1082900093A0D343DD5432732EAB479569078BEE21 +:1082A0000CE7347379E3DC3B9FFAAA5804AE80B63E +:1082B0004B7800DA12C9D261E713BC25494EEFA909 +:1082C000D054A6FABC67F570FD1EA0BC7529C47E0B +:1082D000F201A5C0AB39984D9846BE3F62545CDCB4 +:1082E00067B225B4609406B76034FED3A27638280E +:1082F0005ABD4E11B41FB7E9DC6276A59E93C5BA8C +:10830000354612B67A0BD15E4EBCB2A1BCA4575F03 +:10831000ECF0AF08214632984D1FEFCFAD8CB5F28F +:108320009BC3245758F93C8BA8996653485B84E358 +:1083300075B22EB0DB5B5B750919E3D0F8CE6751DF +:1083400081AFD10DEC579B1B2C1720C2CB00786658 +:108350003A2D5A8739C26C3E437DF9CB4D348EECB1 +:10836000B31F5052F988C177F5AA0341AD37C98DC3 +:1083700026ACEF28C21F6F10C04000ED414048B44A +:10838000DA601086325A01E073B16E3748DF22C9D5 +:108390002B73349B915E9D4DE013F1253FE29B19B9 +:1083A0009A0C8C42244A42CABD6D34818C356108D6 +:1083B00041326EE2C45EF16245D7C264A86C1DD53D +:1083C0006226BDE271F4AE74B6D063558D4C268D35 +:1083D0007DB3E4AD87E2B67FD0303EA351DAF6AB91 +:1083E0006E3700D4700F07186045ABA2F73AD38CF4 +:1083F0004729A86560742C1426AE5B1829B5271F81 +:1084000001EF60749EA03F834405B8E8EC271C0789 +:1084100081BB77460A6F5DDF135AF256736AA42058 +:108420007A7F815AD7B2F0F3E3C77F65AC6964D82D +:10843000E639C5ADD7FD399B067A761D40614C0EF5 +:10844000EC363C1E8D314973064B27B895D5D527A0 +:1084500006916949E05692D6F839D74FED9A850AC8 +:1084600067E26C1266E57622DB2B1CA402347ECE1A +:10847000DF759FE731E55C277248E1AB689484685B +:10848000B0B6EB350287FB0DEA8D459B6D662BB9C7 +:108490000849A3CECB9F0B68BC6F42FDB067510269 +:1084A0003AF32D29894F55447E22BBD77AB46F0DFC +:1084B000A04A57E64B365C2E54A05717DEE7C12181 +:1084C0006585BD6B0D376FDDFE067C47A88E58A510 +:1084D000DDD4CF682776156D6D0A4C13019837B936 +:1084E0004696A434A74BDEFE3E307AB750216ADEB2 +:1084F0008B60DAEF20FC45ADB5ED4C3051A139D49D +:1085000005C8E9AD2C5E9122D5249E8E6D3A3B18AC +:10851000B0FDA25F8554FB2FAE0985A761AF5791CF +:108520005E77DDA3640D982DA1E2F93DF903097989 +:10853000D3888CA5EACC612C967D6E6E728940350D +:108540009A53EF62202239B4AFA11DFD9528D1BA0C +:108550003C8C226DE910E1390F684843B22A7F9EB6 +:10856000C2F85926D460BE229226EB0B96023281C5 +:10857000AFECE5F1D766B9C77059C4697827468C66 +:108580007D9FECD394519F7824065BC6C77AC4ECD8 +:10859000B55E14E8930D674EE96639368E4FF936AD +:1085A0009405CD8274967B56E3267DAB7358FEDB33 +:1085B000D8A863A448B8A8DE9DB004D0C997823B70 +:1085C0000B2F16ECCC99A4D227085A9DCB0EE72A84 +:1085D000A5CD6D9B488211D79856F733B691FEAB67 +:1085E000120ACFA9C1A182F0D809F218D81FCFAFC3 +:1085F000DF0119427FFC1AF1E3492DAAE8DCA3B0A0 +:10860000F9B8F81AB515645B756E80C314D7E334F6 +:10861000B123166E511A4B2F0A5B0FD05640FD73D3 +:10862000CC5C708AC57FE71C0615853D6565BE93E9 +:10863000DF54194F3A2806057D3E3062EFDAD3B693 +:108640009C20BBBE287236D3F771FFCC5958199ABB +:108650002153428E015707CF8A842DAE373E9A7A36 +:10866000C8173C39BB43D938DDF15B6C188896825A +:10867000FE4A85539E6697B619609E5112A4CFBFDD +:10868000DED6B36838027A2BDB94A1B5EA2A9D596D +:108690004859FC4ADA97F7692D0F6BA4C61CF94DAF +:1086A0000BECE4DBDE79A91CB6CBE9F52F4CFF1D02 +:1086B0007C66A101E95EEC7FF1E66ED129F20FAC98 +:1086C0002E31FB613268219B843AB47C403058459E +:1086D000A3EA8B3AE73AD9E150C2AE93B1A10C5C60 +:1086E00063820E2748430A637BDB8CE2CA2DD0CF1E +:1086F00085AE1719A17211629ED33DCE9BC8671C2F +:10870000D329835108862E293A795E68B3EE8DDB32 +:108710005DDE74A0D5C203B9BF8835AD784070F670 +:108720004BB40F94DF159AEFD6FA79BBE3CDBC5862 +:10873000678A51968728674D945605C034BD91E1EC +:1087400065F518F7277EB9BB4F7798AB87122B01D9 +:10875000AB87A7780823D90EEC4D8BD4D51E35F501 +:108760007959835FEE824328A503DC87336D1CB201 +:10877000D87CEBDBD58E17977D03277AF5356425FA +:1087800021160AD2EEA0293114C6793445C7A9BEF4 +:10879000BCED6DD812DEB2916E0CEFF35FD34CFEE0 +:1087A000C3F842E5A2DA1A48475A0A36889B995F0D +:1087B0005DDE29A083882D7DB36003678CCE7E6249 +:1087C0008924E0ECA4E696C9ADA6753E39FB4A6261 +:1087D000736BD3EDB4AEB35E09F0E2773011AD1C2C +:1087E0004495A9487B013BEE9DB26A7BAD2CC05CF1 +:1087F0003417304FAA8065D982533B53F285F97DF7 +:10880000FC7224F6D2F1FC8B5E81E4A18DC99944FF +:1088100001E8010F767A1AC313A86B58724C4BC249 +:108820005DB27509C062E167D17F86EAC9DAFB787B +:1088300038AB92257DC0BD336B88BE35283D1C6B9F +:1088400060E669047B4C0A0607C556ECC849D55654 +:108850004F29A129249D75ACEEA122DD8FB6ED56DE +:10886000C97AE79543CB3EF77A571B55A07394DC42 +:108870009179587F6532A7DAA74EE0205DFAC18A68 +:1088800063BF5D4213505D4E3E1EF472A5EBBBC844 +:108890001263376E28E8721C7AF9DB8574D4466A55 +:1088A000606C927F0BE053456AA34A89F882B0A5B9 +:1088B00095E5A5E94FBAC0BCC1B5A323D1667AC777 +:1088C0007D21EE76719BE2F19FC0F9BA7A4C7C96DD +:1088D0002CBF7DFFCD3F75213B225964044978317F +:1088E000908BA93E3372995A70210ED499A3819826 +:1088F0004C54BF1E4B58FB831CD49279A36E304658 +:10890000604019197A079FF36B56FF0AE4D9A13228 +:1089100055EC49DB592A469036A8155D76769FA31B +:108920005E2C7DE7AC17DD6A7C88167FD48F80B41F +:108930008DC06B6A05D16FE6790C408F7769BE24D4 +:108940008B1E328667F71E59E4C1EEB736CF5CC581 +:10895000798EBC96CC0DF026AD987B5D3F12A93286 +:108960005EFBF8E9366DE62863187D090D736FA08C +:108970002DEBE78EB1A9B49F4135AC67811D0DD4B5 +:10898000580FFD393F16DD7D72CB0AF7D10CB31BB2 +:10899000DA326829EA15F1E1E23A1017ACA5611F55 +:1089A000857B71F57595B7BF1D765C0BF6A2217AB4 +:1089B00084466670A7B51F0B4025BAA205062DFF99 +:1089C000794C96CD914E9BBC7CD4D74F18DB5595F6 +:1089D000AA7EE526B93B2CDA094BD0F47C3C819F7A +:1089E00045FE59508D040327BEF59D3B2ACF30E24A +:1089F00016AD42EA38730B34D29ECF619115E65121 +:108A0000F08B8BB5BC218A613D59039B0332355BEA +:108A1000EDCAF412132C78103CA1909A4F29838050 +:108A200072A6CDE614E6E299B72CF95610AA21A059 +:108A30002150FE26B3412128906A6BFFBB3C813A4E +:108A40002FB2387D7537A82B11D705E18692FBC070 +:108A500055FD9090EA6DC1E8840A6848D88ABA95B5 +:108A60008FC8FF5E6BB1F628AECCF23CCC92229060 +:108A7000D7A240BA2E0C06CDB85A665D3960F628EA +:108A8000053CF55C37E001A298B9CC1DED036165AA +:108A900091FC88E1804D62CFFC4276C39F7A1D60D5 +:108AA000EE593720CD84F6234989C6317463D97BCA +:108AB000EB73C389C96BD6C65B2479EEDD2FD3D2A5 +:108AC0004FE2B6DB1BDFDF71F339C29AE79F06F492 +:108AD0003A4F89AC4CCC9A806EB15FCC5EF9E7B26C +:108AE0002E2D63F581380B0A3E12678ED67A001858 +:108AF000FCD7EA02185E3C03FD3540F28ABA65F005 +:108B00007C7470ED1C774B90E105C76C717778B77A +:108B1000E00D1D9DA9D19252CE010FC2B4C3BC0F6E +:108B2000AA90F8E023916B1970C8CAAA0BABCC3B92 +:108B3000751EBA90DF3233FD2730CF169FF28A1AA6 +:108B4000B9FB75D0D5DD98207CA0A2FEC3C852A980 +:108B500088DDECFD7E441B1396820A29EF5B4024DE +:108B600081A3BCD26E03AB7C570839DDCF554F30A3 +:108B7000B5B7EB7F543A619141D85D7633C328DABB +:108B8000BDC352C38392E576FA7287B7372029DDD9 +:108B9000F8520E6498575A821841064EE2DE278634 +:108BA000AE57917EA8F3FA06DD7111E71498EAB585 +:108BB00086B20914D73469BB6BBD191CB77BB3CC23 +:108BC000F5357B24B1BA6FDF11C4DC4A86404242DE +:108BD0001039A72D678108852515C592D23F100150 +:108BE000F83327FE40EDB588EF8BADD71C9B01AC69 +:108BF000B3A5F8692A93C10163E6E9220AB5B8F37F +:108C00004358707986814361130B53FC0B1612672E +:108C1000E7530C2DFC89BA8F4D930D014E7AF45910 +:108C2000A928DD83F47EDF8BCCCDF055265ABEEE2D +:108C300012FF9B1800FAC1E47800773915F1AED71E +:108C40003178CA102E5E882E05CA71A1D0FFC705E3 +:108C5000FD8CA844774247BCE4160CBD67EB734C0F +:108C6000D37FB1785AFC9A83B221445BC01CB79D74 +:108C70004D2D06C3B922EE32B9103E8DCDBE71C165 +:108C80000FFD1BE975E7D8A810D3DAAA693BE87491 +:108C9000EBCA8F7B23E84DFA35858AB9EB0B3D6033 +:108CA00006F44A9AFA461F82F30838DB0706548214 +:108CB0005D7C7FE79EB4A8C4F3B887104BF24EECFE +:108CC0001AC679E1B96BDF60D09BD8C89966766D1A +:108CD000BFF226406A11DC25160BC5E4A8D52A2A66 +:108CE0009865B721F69218B5A492A633C81AC03277 +:108CF0008C5F1BA3BFBCD13FD7B07589ACA0968A4F +:108D0000904AA5C06FC3CEE74612764294B108736D +:108D10000E3A7BF41AC412E41A46D0355B2D432276 +:108D20003F8581C55EE26CFFE43FC9709A51EAEB72 +:108D300091E9DC5F6532CAE053434941E4BB262C2C +:108D400062F907CCC61F3CE24ED9A49C0BEC404014 +:108D5000B730938582B00D4CF98CD58BE92857F547 +:108D600082542BF24C8D9999B4398E3254B03932E9 +:108D7000AC91F721BADFBB4F4D6C7AC353AB6DB3E7 +:108D8000253E61051A759E97A9C43892318F8CE4EF +:108D9000ABD00968DC0C09C9C730AD6380D5B6BC5F +:108DA0001B768DC8E8B8B7003E2AD31236FEC451F0 +:108DB0003CD667D2E655ABDD66E2895E5DD3248D95 +:108DC000D14CE410E48B532E0DB3A8F26ECC01F419 +:108DD0008B90E942FDA9CA0F8D00CAE90DD8E0D8F1 +:108DE000E49C034323603FAA7C4A7B5C2B138910DD +:108DF000C77DB651F0FCDF09B111EACB41121DA5C8 +:108E00000DCA00C1B99EC06CEE1B1921EF645CA4B1 +:108E1000C1F8FEDE23FD8F3ADCCC1D08D93BB072D1 +:108E20009C10912B161BEAEBFCDB8AFDA54C298FCD +:108E300016D0EFC9F797B7DF9046A78B9C9354A63F +:108E400030EB2661C64884AA387211E0A8A9F0B4B4 +:108E5000E86676F6829505D15B039FDF021A797E7C +:108E60007F8803F1847F713CFA29AF414892309D9D +:108E7000553A910B7946D43AB6A0869F37BA5BD95A +:108E80002540449403AD10531F437B20B38CCC7713 +:108E9000ADC463D1BD702D4321D92063FBF463AE13 +:108EA000EBA1257607C7F88B3BCD213D1932C7AE24 +:108EB000802DF97D5B3108AEB4FAD43C92D53208EE +:108EC000A6295849263E8541746D6694BAF8E96230 +:108ED000854DF3464E869C37F6C5484739E83F1A1C +:108EE000BAC73CF6D23BA4771393561BE2D2D906FD +:108EF00051641257C8B6E57BBB1D661828F57F0A7A +:108F0000C50FBA9E02CC38ABC67BE3DEAA38C3528B +:108F10006CEF5A668459E9D02D84872B64721E0C3D +:108F2000671E7A0B3E1BA71BF9D0B69077B64FC5CC +:108F30004753A5DD61844AB244F3B57CB273376C04 +:108F40008580821A5F51E0B3484B7B258942435BA1 +:108F500042B24524050AAAC7ED117F3A02F2401534 +:108F6000491F10819CBA92FD5C32BA01B3329BEF6B +:108F70005039BC1CB7F9AAE9C8FAABDC79F311CEB9 +:108F800095FB308A6C0F7782ED9BA3680911B36360 +:108F9000B51C6AA0E770F63FAED255D55DCE1C2D4C +:108FA000998376F642D91DEBE594B96A3530914044 +:108FB0002314626587C7410DFF6A6FAD47DBAB6F56 +:108FC00081F56A1E518D3A1485D9EDF953D92CD902 +:108FD000B5D5CC70F6248D6F56DFB3798126F01DA0 +:108FE0007AA6E6BFE16ED82E7937745BB283AEF411 +:108FF0001205CE037A011AFD5AAB1EF2DBA3362A04 +:10900000EE95544A74E068635F281603442ECCF949 +:109010008183208FF02E2DF25CCFFB0E22324B95F8 +:1090200014F611456DE94E6A5F3DF9C7E3F25CBE87 +:10903000EECD18E6C01EB1A7D77A66D9A2BB172518 +:109040000471EE667BEE1198D22C70BAE0BA1C5215 +:109050007224DCBD858808AC26DBA776CDCB4581A4 +:10906000F919DA825E3393CFC806FD65FDAEF78B42 +:1090700070C0F2996A2266C805F9F6364AC32F8C89 +:10908000F0C5BB5B9CEA9F4C8D6BF87724451AB00A +:1090900069DF98944B9FB9EDAEBBFD4C3B96F27BDC +:1090A000984D6852D574014AFBFC232258CEE7B78D +:1090B0007426870269A3BDD6E953F77CBE36A2E5C4 +:1090C000C3DE68E3F0E9B95A11E82D0232E8D71699 +:1090D000E1322669B20FACEA19FB6CE1DDD0922BCC +:1090E000734BFC7AF3541B55A08368420EDDF546A2 +:1090F0007FA01B3A7963049954FB5B0D9328AF372B +:109100006D4593B0AB13660730AE728F7BB02634DB +:10911000DC0B3723A5960A3AD12EE254373A008B5E +:10912000DC629279CADB935ADFEF3201B15727A391 +:10913000304C6E849C2861896114479098B9D8039B +:109140000220FB0362E792681AC53040217FAFF02E +:1091500079FCA3881F0F02D80238D1B312980C6192 +:10916000730C9B4BDBFD7CB54F8075A915825A872C +:109170009BB4D508248D2A1CB5AAC6852601D5CF57 +:10918000193933C60B978FF591C8491C3A24D1433E +:1091900007AAAC6D5461584149C127953678C8BCBF +:1091A000CEBADDBBD81F75784F942C790666F8D7F8 +:1091B000A0F8FAB0A0606C363EB37E87B9C9DB3444 +:1091C0005963AEC06F3C615C9B0F7806F66E04B5C8 +:1091D000576CD7AF8DC765B046B8514364F59BA3B4 +:1091E000626DA94AB846CB605AA94225635BA58A3D +:1091F00068710774190BACBCFCC8336C9657625885 +:109200008B3B4F124B0521880FD9C57F7AFF175131 +:10921000DEAF43A0A7092F91B371F91582EF24D5D2 +:1092200044134DEC11F3FDD710C77432B2CF5DABD0 +:1092300017188C5E5F210B794A349EFA4D9FEE938E +:109240000E6A137D58256A371EA569D421663BAB8B +:109250002BC153A4C92B57187C9A07F308864D30AD +:1092600032D6065A5C7AF1ABB56766784905056F68 +:10927000A5397FDDD1DB662AA14BD4D5A53168E8BD +:1092800088C413EF7D9C4656ADCA58334B33C8197A +:10929000731F0C1DA8E5FB0A41E90E8E8A91845CC0 +:1092A0004179F5D7B7AC027891014F14B0612C2108 +:1092B0001D9E4E6E4285CF2375B1552B43E02CF198 +:1092C000AB3C3A8494E7F457499746F66F53B4D4CD +:1092D000A5F8D2687419BFE5B4D8F18731D9C3387D +:1092E0006C27C4895CEF120FE7671F2D3BC14ABE94 +:1092F000B0E7128A6109125E70409AF334CF8A0196 +:109300006A57C3D24E70100F2F70C0B13E73BD1597 +:10931000232FF958007E27A946C872BA119EFB8EEA +:109320009AD7630C4BE4204C4287D074D088A85362 +:10933000225E26847057A08BBF9F955B77F882636F +:10934000275DC5C1F5C475171F9DF8FC3CB32E4FB2 +:109350001F37F947E20E29CBE0A62CEC95938F6FCF +:109360000F408C3816EE2B47675A9DAE4DCF8FF8C5 +:10937000C0603C6E82F2331FB38A250E69E5340269 +:10938000981D6152E36889BA98B849E3E8FD7D56B3 +:1093900070776DC0752B65797A9DE8B8973BEAC008 +:1093A000625AA3D3CF0B0B7DCB0BE5CBC6BBB0630F +:1093B000C424D8E30D930526EA432C268D9F931CE5 +:1093C00034769B7EE45B9F39F161EFC50F11128605 +:1093D0005DCFA540083CCD3A350459DE92289D0169 +:1093E000B64A9D4139BE54DE001A53663F3FDD79CF +:1093F0005DB0E4F88B157B28FAB81A2B673D890617 +:1094000033B4FC3A5300CB17FFBD3417A39BCC53A6 +:10941000B9C17F0F18C270B1918787767184DFB7A9 +:10942000E46C60427FADE9D65C968955FC3D7B9942 +:109430001104FDDB154F0BBA0AA87D7E44C21CA89F +:10944000EE4DCE89089F94FDB59B3FAAE75B721B4A +:109450003A18EC40E78A9B1163D3C9D2876C0C861B +:10946000EF48B419779A4ADD0D728CA7EFF06EE3DE +:109470002D6748E9DD4EC221223FEAEDFB800D83D6 +:10948000C87E6B9FFC0AB8810EE685C98BFAE3B6ED +:109490008C372EF805973D26C462D295A2EEA9DA44 +:1094A0005A1A436410F8D5F505D35FA9C46C31B7D7 +:1094B000F23255B9B322F1CAEA070BD7E88858EA65 +:1094C0009789CCD3AF5500A1447918366440F05A3F +:1094D000B3E2BF07CB10FE1A3568A4192BA69B6C0C +:1094E000E89EE6D6BAF8A6E2310BFFAC26D7A678FE +:1094F0009A53E6A4BB45C42595466B0CF775CBD2B1 +:1095000086E6D2D347678954E66F344DBD316D325C +:109510006DD31E7C804216B387F9B511C9D8D1DB53 +:10952000C803520A93363ED3CB4F30A0733403F0B6 +:10953000FEF8C54E3067AA74C4B91B7552B615D271 +:1095400046EDB2615D2F5E8611D62A3333FDD44BD2 +:10955000C4497B1673C4ED3EE8FF080C4AD7A5A1A9 +:10956000145318F5F031CB5775ED1AFF2AC4067362 +:10957000B47A07AF53DB28E28F1BEE7A6B871D7737 +:1095800062FE43EF4C7C2748CBD9433F6ABBCD00FA +:10959000172FA7DC1C191EA1EA05A0C0C3635BB886 +:1095A0006852F87E51D44DB1587251B2455B5A4160 +:1095B00068F4CED4DED5F97797D347DDC7C5F17A05 +:1095C000C5AC8CCBF40CB100398F59ECD3236AB401 +:1095D0007D35889ED68595DF0AAEA309D45EE7F176 +:1095E000F7D377583F39DBC73B6C2B95EC8E81A0C6 +:1095F000FD763DD0A1B33A2F002411438E8BC64196 +:10960000919EDF983E2F6103BEE29490F41EA2C2A9 +:10961000DF5E8144B8957FCC5C58FC771F000AFD63 +:10962000CAA88CB8114DAF8034792BCE62C4549146 +:109630005421F3AE00F87EC95E41A4D153BBB6F508 +:1096400049F4114D4ABEE354AC2A3DCB1AD87452AA +:10965000D7DAF0ACE02393E7C8C86A7ECE50B618DC +:109660001DD6AE5392DA7DEA7F6DDD6F6404177DFF +:10967000C65D4E2FE473F3576EAFC8ECE2925536D9 +:109680004C787F8F91808AE7E8C76396950E09062C +:109690007B4EC8929CBECDCA9E11E99D36C93C74D2 +:1096A000E6432B9C46C978EF0B86D7C51260E7B816 +:1096B000D7352D0019CAA4D84F23F2B9BF31363D92 +:1096C000C4C4198FB216B3217C686708EC879AC7A7 +:1096D000F9FA10AD56B193E615904D351BCFAFA1F9 +:1096E000C2D9357B42015AEB5B4CDD698549C675B1 +:1096F0008BC3FA0992B097A9EAA67A128219E139C6 +:1097000070EFBD95EB81668B44180F0BCFCD07E949 +:10971000DCF7F950986E5A6047FAFF3591ACE635A0 +:10972000D6BA8FC9D24540E8B1F4328ADD9CA5E7AC +:109730001C954C1920DF46257D597B055DEF7ABFCE +:10974000EBAFE6B2ABD88A2C392BDC5B64D385BF98 +:10975000B29EF90E4E802CA0C1721EB96733C8B8F4 +:109760002A424F3927C456C7A61E37DDDDB2C4DCF6 +:10977000B3519E395C3E8BF7F2623B632344DAD7E8 +:1097800044670726366313317DCC69786F05C6C2FE +:109790002062255F7C23FA3745C6830C906FA77C37 +:1097A0002B5A903609E37849A6B45359710A992681 +:1097B000E21E077E17EA3663844A7AB03A9EB0907A +:1097C000E0B368A1743A4F1AA7239A07CC011AAEE6 +:1097D000459BD9122FA35548E5337D32ED55CF1C5B +:1097E000871C92AA6FD40FA56B60C534E114481C86 +:1097F000C3A7CA37D1B315F0ED1F9351DA1E63FA30 +:109800005C4B0CDEF8C77CF47387368D76B9DBF2DF +:10981000F5EB48CDD9B9BA3880D502A2A6689AF43A +:10982000A242355084FBBB4CEA052FA373AFC1762F +:10983000C8AFD53A5AC84DE65E0602992342FB13DB +:10984000CC9B2F46AC4649557D92323844736DD936 +:10985000A0F831F878520759B01D824B5D48359712 +:10986000A3CA5569C45C3D49F28290C1520D42A021 +:109870007E26040A6822D4226699F73D2DDD1F8ECC +:10988000D48BC550462A5CFBE5291E2D8D6B9E9816 +:10989000D4D5C97BBA8BFE22F76047241680BEE080 +:1098A000A5937BA98644745FB926FA5255FB3E6D99 +:1098B0006B35E685329869C236288B57986AE22B59 +:1098C0003D6EFDB6B4DC1580AE5407C31D7E4BBBA8 +:1098D0009BDF466A8929414C0E1240C6A63F77722B +:1098E0008FC102088B5D2A9077669EF5CC33BAB0A3 +:1098F0009FD68A6DEF67827DFA9A3A0649A422AE16 +:109900004F14A02874A6DF14418FB8C2FD242A5832 +:109910001FC0CF08F4AEC765BB08073232601842DB +:10992000D195E214295146A1B1DD9013197C4FEF76 +:109930003EB270BC9F76223632C3230A05DF36F86A +:10994000E94CE113BCE56A605E1E2D1A7BA3D8AC1E +:10995000A1552386AD77D40329B757945BD681BF31 +:10996000EF6DFB9C5FE492D6FB7CEB15A42BEF180C +:1099700084DF610674F849711FF4B36B4AF6AB9E3D +:109980003D6A10C235F09A9045C7CBA410527711AA +:1099900000CDA33060E67797B8059245E9FA8BC20F +:1099A000355AA271D28BF42128A7D9DE96E5DD16AF +:1099B0003BCF35A244547D8D22056B092B7B471C80 +:1099C000CA1A070681B6070AE8784015D5ADA53151 +:1099D000B656E90433AA1AD56A36A40124B0270082 +:1099E0003DF2382F8066310C5BF3EF730CF719A54D +:1099F00070F9D9DF2E128D6B7D9D3894B7AFEA795F +:109A0000A03EEF983CE91E961FE6B8EEAF525C37D9 +:109A10004B587B22CB59285C74AFE053B486DD925F +:109A20008DBA8CF20647BAA5D0D2054637054E56F8 +:109A300079AFB33DA320BD680535557686A6EC7D8C +:109A4000CB0E3E1DAD284EABEED78176123E3EFBCF +:109A5000843AD8139D1A6AEF5CA180D68368ED7FA3 +:109A6000FB15C87390977BA6889F8138AC1F42A1D5 +:109A700017B8BB7D9682D0F110F3BEEFECF1E4BCD9 +:109A80005B564A2C1D7A79CD96902DBE97B33FB682 +:109A90008DFE205001FE3943D8B7792A5C29E82A87 +:109AA0008C5FD64DE74085E87C96B1FBF5F5C18A21 +:109AB000384B30E0A359D94851638184BCA012418E +:109AC000B09581153575FCE244583DDD08AEE36084 +:109AD00097038241340BB156EDEF605899680485C5 +:109AE000F32243A8D59532AFFACF9F4F5609C18BC9 +:109AF000D8F812A4E5A61FC2481593B46764BFAF97 +:109B000048028CED7F3E945BCD9C35AD85B220ED57 +:109B10006419C2EC9B00E4926BFD5B82BF1BA1E861 +:109B2000D209F9B94596410B0B215F2EE29F51FBFB +:109B30004649F0433524F852E9DF03F05072C5FC82 +:109B4000C84AEB959BDA3A7EE319868F10BB28F55D +:109B50001F5A9C33006A8DE1DF2EC28795C5D7005E +:109B6000945CC615EE9314E42F7DB3E7AD73081E25 +:109B7000D63E3CC808B3BF48F3C97751072C6FF8ED +:109B8000F3C60E9D3B990887963DBB2166A1BB1885 +:109B900011793B7B677C649C7A2753CDE2DE897226 +:109BA0007A6A7FD3326F6E2E80522E79CCADC5DEAD +:109BB00006BC2F0EB8F81D735AC73C1D0E41B55791 +:109BC000CFE6E405A04857A5A19D7435A6D144C3AE +:109BD000B5ACB873E625CA97BB55E7007A8B124B34 +:109BE000E78E50151C6B069D176F18E25FA5657315 +:109BF000ABBED86263E7D5BE0B55ACFDFADF0C8A6D +:109C000009778E23E792F0D10E17664E0512E5D73D +:109C1000B38518FD550A9FDEF8E2A56B872BD91C8A +:109C20007D2A7F0F25D2EB28DD6FBE4D6304297896 +:109C3000409B6246BBBB649334D5B0D7D0B27B9611 +:109C400080A22B1815EF70F41379C8239AE3E6CDA0 +:109C5000C574E51537212F500D6C78063FE7811646 +:109C60001C69557F328DC3888504474F5B14FA4DBC +:109C7000982CABCD3B43316A06A14C34B507D9E6ED +:109C8000D3048B1026A804AEA36D502A9885C3096F +:109C9000C07B2F369138CB8D3F2AE989C5E8D43077 +:109CA000D41931D789376497C5730BEDAB0A23B14B +:109CB000528AE4FC60B724D79C64CDC6F819689B2F +:109CC0009564B0EE80C21722B8AEB5A7883D199949 +:109CD000D86243B73301ED0E82983E55420934F005 +:109CE0005D828A2F21749EB704F7F765C2E57EA6D0 +:109CF0006B28B48D2B55011133D07F5D944696614E +:109D00003D0EFC4D9699649AD99DDDB5E8FB749D96 +:109D100094348C611453C78FE1352C8F3246A1D215 +:109D200088322C670DC8F4FED9E8C7FC2683A383CC +:109D30004FB61A8ABB306BBD6503A0F3D0F782CE55 +:109D4000BF2DB55B22D13369F459FBA6634B640781 +:109D5000410C9133A96C4E8AF5BC4747FE20633D08 +:109D6000DF67104D5E90C2E00ED3EC51F81B82AC61 +:109D7000293F195791A30774BF2993CADB7C7765E4 +:109D80001750B25E260BF8C34B4AE5DC4C5FADFCC6 +:109D9000CB048282F918308FDCA2828DB816572747 +:109DA000F168870A9C013C128EC696E9EB7843A6BF +:109DB00084BB9B88DEB4968A1EB6BD0D5DDC3AED91 +:109DC00030ED4E094146B1C0C03165AC5ABBE948DF +:109DD00032A699670C58BD6A7C4494F40EAE170AFB +:109DE0003B158935DBC4DE8075F366766378BF5535 +:109DF0002C5A16140B9E0DA2D5B5CB1E3BF49CAE6F +:109E00008A9B85DFA08B6F538EC9F94AAE3DC91E70 +:109E10005619878A9D0F43F867765C804E0D27B6EA +:109E2000F8F339A6A33EDB027BCBA9D56958098993 +:109E3000EC1A6DA55799232D2546CB76F714736C34 +:109E40001957FE0CBEDB58706D78AAA0987468C4D0 +:109E50003F8BECA3ED48B8C40113C01C9AC02D4B36 +:109E60000673797BCAE305A59A71C0B61A6B709D1B +:109E7000EC67E5BB23ABFDE6511D22457B1E1107B8 +:109E8000F2509FBAD54F3E4A3FC3CC3C5FE4E484D6 +:109E9000483FD7A42DED5DA725E1F586D3DD76BB40 +:109EA000E14E91CEE7DEA06F8C8499BB0A9D6AA635 +:109EB000E1953E7D6435FB7D7386AB6862B996CBD8 +:109EC000AD26DD21FCCE7D376E76FCB57ECFE72456 +:109ED000390C06B201D3498DFB9AFFDCD9C19D9D97 +:109EE000067A909CD13C825B230061BC8CF2E0D16D +:109EF000B1E002F9F9BCEE4772516CC7A4CA10A3D5 +:109F0000B9695C7CB5F20959C374DE8749F5C6F3BB +:109F10000E535C2B3ADD070673A5AD41D78497221B +:109F200047281172E099BF5E74161E8C4734156F76 +:109F3000003B56A41E6D2F55534D9EC77004DC0286 +:109F4000FD818855025D77C5C8504E5042AC86FBF6 +:109F5000EA15FDB6BB13794548D8C77560D653627C +:109F6000995D3EF0BE5DB3E1F8D23F2DF3FD3A5B63 +:109F7000754E637F24E3FF83E76F650663D89354D0 +:109F80001A95699E628CDADCCCFF31F6FEFF1B402D +:109F90003540F59739F47C2D9533608D1825EB8984 +:109FA0006DA7F293EC676B49792FECE288002302EE +:109FB000D721FDCE56AC83039A83A4BEBB5E06F8C0 +:109FC000CBE10464FA1FBB53CC63B0F931B73C2139 +:109FD000B55398C880E5D7BB456CDEAFE46794887D +:109FE000EA5E43FE156A5741E0BEAA9C42E219723E +:109FF000B87BE77BA3FE75B596D121DFF95D3C0CFC +:10A00000DB031A40E3EA9AFB4037AE3CBA1C4D6AC8 +:10A01000FF0CAAF4C701A6C34C837F3592929242EB +:10A0200021C98DFB6BAD0DEE9B676773680A578284 +:10A03000DAB5D11508AE44B01ED719F8096680FB11 +:10A04000B7D36ADD50849F11CAED84BF7F45D2AC7F +:10A05000C0FC368D02ADEC6017E9366FAC41FA9268 +:10A0600073C4D6AA1D9ADB12756CEA969730333901 +:10A070008268E0FCD4CBE541BC2701577499F13CE0 +:10A080004AA919E8EABAB122E91A85EB7FF3CDD8DB +:10A090001CC03B0B3123ACB13A68DBD0AB7771B954 +:10A0A0003380A983FDEF257C447DEC6910033143A7 +:10A0B000794530EBC9B226A0FE0D1616BB40110B38 +:10A0C000F01028EF4184094AAED818514E182344A5 +:10A0D000C994FC4173364252880B418E2882BC01E0 +:10A0E000E272CF3BB398A6DCA9170C00924CA420D7 +:10A0F000B00DD9CE4147F0D6898E6D38A70F4B45AC +:10A100000CFCE2D1446D99C26C64FE00DD4C4993B5 +:10A110000A64FFF1F9DD4919C724AFC936D87D3E7D +:10A120005201A950A4C9E11C5838DC3128BF793943 +:10A1300008876232BCA7F2B1DB052D6C25EF892BB5 +:10A140002D331FE138448853132819510375D776EE +:10A150001B97DFD297805261618F9929590B7F95A8 +:10A16000AC7E4E4EAEFE52A19EF3B60B40B6AFD6BD +:10A17000E9BDC2676F5038E0E5DF0AB8B7A7F290D3 +:10A180002753A887F2D27F6A05F9DC18A8F50D8B52 +:10A19000E1BBABC4F1773094608105F8B9E8ED809C +:10A1A0007EC7BBB81C2A5828A5C42671C52DED78DA +:10A1B00058556277D28B9FB49559568684503B0E82 +:10A1C0008F04EB65877CC836266A71CD111E4282EA +:10A1D000A659B147A4544CF180AAA24F066857B4BF +:10A1E000B83B91E496080DAE06C1793604B5F7B5D3 +:10A1F00011DDF16217FAC5D2AC0913A313EBE4AE7B +:10A20000B32B504CC284AF05FEBBC28E0A52221340 +:10A21000AF27E9B0D222877E37A2C5D1A404460970 +:10A2200014D857A15C8FD5AF975DA98B64F3DB374A +:10A23000184E7D8B0BFB3F32B169986320C035C24D +:10A24000C014DA74748DB3A6E762A41317352039ED +:10A25000941CACD7A200C7A289A191E06E86515888 +:10A26000F95938C154B0A041A66EF23471A4070860 +:10A270000070E60B6059B029DEF9235C4FCDEA1C73 +:10A28000DA88845FC55DD40475F221EED31FB3D3A1 +:10A290000098807ABE3F00061A6F9123B8E7E81055 +:10A2A000E0AB017612B3DE6C1D185C7CBC929DC8DD +:10A2B000DFED311DC3E467C47284BFB6DA7A7CCDAA +:10A2C000685E5160EC4552131E267B2460F8002E18 +:10A2D000B37A6BA5271B7A79C7501D6C6F1137CFE6 +:10A2E0003F6EBF777EC28B84554A40F29303C80B02 +:10A2F00029C98171DD98AB06A68DA3E5C9C374CFCA +:10A300009128299A45A2580366CF7A0545D787EE4A +:10A31000EB0F09868E26EE3DB6A37048FE17F0F0CF +:10A3200037033C378F12679EA59543FDF2E5248BDA +:10A330006EFF8EE2B34CCFDC5633935A35B329E926 +:10A340000823670F3E83DD0D404DC90493EF792547 +:10A3500067023F52C3A20FF3935EF584D475513D5B +:10A36000686DFD961771360994E8477075A3C7E9C3 +:10A37000440B5543BED063B032CC211ACAD271A06F +:10A380002656554910A54B68A76FFA23CC5363DDB9 +:10A3900023B08FDE3C30387376B1CFB012BC078665 +:10A3A000DFF5C071ED6DE4B111425F6583D237CD49 +:10A3B000895149C5E65BDF6BDBAEAF40C337D56A79 +:10A3C000825E60B621435FEA3C8A091927A42F41C7 +:10A3D0008B0863C87118796039B09BA68092D82326 +:10A3E0006A29B5CBB2973F499A6D25C8437F3DE5B1 +:10A3F00049AC79270638B41ABF8D4C77244B7809BD +:10A400003F6EBC49C2871EA12FE134C106700518FA +:10A41000021B1CF8450EA6F0D8A503455FF16DE3BD +:10A42000960D067656B0EB109B9EAFDE5F15D76E8D +:10A43000B240BC5C60E74EFB960A5CBBE54524D4A9 +:10A44000E9830EA0F868817F44B537C8154FB22F55 +:10A450000059C71F58E072783CE541CC410CD5113A +:10A46000BA2A5D92A67085CA2F747D961184EEA2D9 +:10A47000B991F6319102F15C8A39007F3FD4081F0F +:10A48000074B7288F7E5FA9354E1FC86DF3C47BA44 +:10A49000F3CA947611D8725ED6655C585692037AE8 +:10A4A000B63519BCDCA99CAED611643CBF9EFBE05E +:10A4B00004DB084DF43667846B6E46AC5538853B3B +:10A4C000C91E8F0B472C7A9FB172F9EC82C443638B +:10A4D0000937628C6DA23651554F6808D777D1D0B5 +:10A4E0004206B40E2B2F52B235ACBE7468501F9189 +:10A4F000B758B17B12989389574D8F3AF31FD611F5 +:10A50000373B30BD78668E533F0C17D0D75929A6FC +:10A51000E6BE908B3EE6F07D2F6B3A0179312B78C9 +:10A520005186F7F4EA83F1B00ADD1F1A59BA88415F +:10A530004E5627B3AD0FE172797309A62BA0E6BC86 +:10A54000B1DADCAFF1422C8F1E4C895442938972F0 +:10A550000E19EE0BCA4987F51626F111E3299EE183 +:10A56000E7A3A1C72C0FBA4B92531EFA619159422F +:10A57000329E7F6262DBF366DD2EC39587A2030EF7 +:10A580008F4935CEA05A9EDE3D852E0C6083CEBF0E +:10A5900075B43F02F26A12219245FC2939A2433771 +:10A5A000B9A6B3DA4D6ACACDC8C11837094FEEBF94 +:10A5B000514969348555C22E99AB117BE5673BB68D +:10A5C0004F33D18252F55380C37F29AD3596068330 +:10A5D00080F6FF81071A62D24EF9C74FCB6B6D37F9 +:10A5E000F121D9110CA6CAE0CF441AB895F55F390C +:10A5F0002A8455C9E570283E3AF8F24A425F54373A +:10A600005C463AB3E13CF2D79C5D294A84CD4A8747 +:10A610001C285B56FE7F76AF2D0ECC0FF871F66FBF +:10A62000911488BFBF252B717483DFE703BEA89BFD +:10A63000132A5897161F3A5C691D4957CE2F0FEF02 +:10A6400061B8ECC6B96E0C56974B7913E1EA8BBB37 +:10A65000BA3B2C2786476D40D70F9B19D4A528FC01 +:10A66000B2EAB43110EF260EA9D2A55CDBC45A2D94 +:10A67000E87BA3CBFFF62A184BE56E0B959F903134 +:10A68000CDDB00328CB7E5DD68EC068ACF6F0C8C31 +:10A69000BC131CF82A4701283AC85D5807A9CB44C7 +:10A6A000DE195C875D40913A7E1B637FFB40BCA74F +:10A6B000C5C2E4B9E4A619B38DD51B47F7966A0F56 +:10A6C0002E6E861BBD241FB1431ED0E800D924ACDA +:10A6D000A814EA269F6832CEAC9AA8093696421E84 +:10A6E000E7BEB5EC50F39BD6B90622D6F37319E05A +:10A6F0006E595A4313F056A13AF4064DB9096A5AF5 +:10A7000019CCEBEF21E5A6233FB357D0ED3163D74A +:10A710005DF58D44F44AA446620FBC3560DCD495E7 +:10A720000C7FFD74F8FBFC642D50A0A48D8ACDC372 +:10A730008F24A1074BC0188C080759A194087CF7F7 +:10A74000B3FCE970E8348E298A87FA9B4DD154AA6C +:10A7500081AAAD9C640785C0E08838CA8E9402E265 +:10A760005BC21D8BE7307E57233FCDAFFC94C3D037 +:10A77000A712309375EEC1442871251233B6D81F45 +:10A780000048C385CA2583EF69DBF252051B7CC8EC +:10A7900065E36E5EEBD71A265812F52BD9C604CBAB +:10A7A0009C5040013E742FAC8D8C2EF54845E5D071 +:10A7B00077FDE58ED9E447426A3189B319765EBBED +:10A7C0008AA2ADD17A3F1AE5759DA9912C9710F711 +:10A7D0004942734CEF5C895FB6A7331B786536B08E +:10A7E0000E6E7490224DD9FA9B45E067B227172769 +:10A7F0002A57076C8449903BCA049B8987F51FD070 +:10A8000053479D4AEC532F11D939E5107B9220D73D +:10A81000EF9C13081D48A531621920F3C8B790AB0F +:10A82000110A9437E54202BA2ECFDD13CD41E290F2 +:10A83000399953874DAE93766D6EB9BAFFC5B0BBEB +:10A84000C13047F1C595B9A1F56737BBE683DCCACE +:10A8500011013427AA9CECE076791076929B317630 +:10A860003D913C65FB0F0BF3B56DC3FA8114CE220D +:10A87000FD1077A478F9BBFBF3B50EBB6292FBAF7A +:10A88000DCB445F813187C429616DA906D3561BF3A +:10A89000505412C9FF7CA19739F18462D1435F9E65 +:10A8A00032C82D4374329800DB57F4E68E7266E0AE +:10A8B0006FA365D53080F4161D56EC5198E85710FB +:10A8C0005FD631A1AAC7C350991E2A146B9D29D502 +:10A8D000E929620EB335CECFBEC6E126A9604D7B15 +:10A8E000120F153678BB4F8E8BD69C5A96767F5FAB +:10A8F0008E7496DC24C63D4AFF925CDD71AEBEEDDF +:10A9000064BC8C80DE2E43A11EF0C4D80BF1C7CAF4 +:10A9100069CC7F0610779EB20A3B514A56739A1053 +:10A920003F03C908CC70A077D7004FE18A132AA94A +:10A930005218956EE20FECD12C93ECD464EA678F39 +:10A9400019E80FFB2767A4C018711B69EBF91C38C5 +:10A950006A752EA02600A022D0F479899B5EFED4D1 +:10A96000E0CA019713673BF4A6796E65500E3B99D8 +:10A97000EC459852BC2383D3E95839B8D2D6424427 +:10A9800083CD563CDA6298363791D7DA2795E57150 +:10A9900046E702B175BC8D878F378C29A1CC212F5A +:10A9A000FE1BA59541307D518245165D5331937E46 +:10A9B0007976F9A66F170C0F7636B526908B03DDE6 +:10A9C000B0C3C699B491CB00822FC170A0218E0272 +:10A9D00069266A5F53A3468B866526CBDC3C5EF70F +:10A9E000EC21F30E81B6DEA47AA73770EC32DFD10A +:10A9F000160206B3C1104FD192D9ED769F7BEC16AB +:10AA00009CB045B71293049FBEA721E6DE5A26BA32 +:10AA100046D4A897BB38A006AC89D164FB4DCEFACA +:10AA2000171008199CBA4AFE5006B27DAF5FD1805C +:10AA300024FF83BC93BC3E72F0829AE481BA6DA27B +:10AA4000E7B9F088FC498D8C9564AED1CEB39A35C8 +:10AA5000DC118873E27BC800BB819D896ECCBB563C +:10AA6000C46787C43B78796545555E1ED2ED492F92 +:10AA70008A7514A8004723602FBD82D16BA952A309 +:10AA80008AAE5206B6D9678B9812C4BCAE253A740A +:10AA900051C0C21DB02DFC4786CE3F6917C915E6CF +:10AAA0004FDDB1E9C43EBE36731952C5BCB2B377AF +:10AAB0007178DF00237205E72842EBDF47EF78FA71 +:10AAC000DFF7417960F5F1212079126A2E9A5682DA +:10AAD000CC0F7DD1944F25914FDE68B462EEF3D94F +:10AAE00073A95051370F9580D32FD2A29CED2C0D16 +:10AAF000B807D849038E18D2A3517F71297CF3532C +:10AB000078811875E0DE3FAEDC6AA91331C262AF0E +:10AB1000C80761AFDE81D0646A6E237B4ED0E2400D +:10AB2000E3ADB719E6006DB1DC4B9C4F0521A8FEE3 +:10AB30005A4017134BD65AE093D5371989E35C3046 +:10AB40002B684717E446BC9DCF5C38C2FE543DE5F8 +:10AB50005FBAC41FDE840A043BBBC2BB0303947C00 +:10AB600090AD7FDB94B43B58A1A080150A04B6A633 +:10AB70002C1ABAFB55761B3E4ADDA24EBEA1E34E0F +:10AB80008186DAB69AE2ADB5C53B5194A4AF4AFED0 +:10AB9000CF2EE35CC178743BA4B9C416794D2B6207 +:10ABA000BC4AB6C9B63563292225FBC15993552045 +:10ABB0002BFD3495DB15B6F04E253E009B0A85CF64 +:10ABC000A85B9E445AE78B0547B51DD337D1137F49 +:10ABD0007062C0AD37F482F57657E2FE0559705ABF +:10ABE000E1879A9F594977408655AE7FC6BA8B68F0 +:10ABF00062BA8AD5810F6D347161400E2C376DC4F5 +:10AC00004BE8C2F8C3BDDAA082B4EEB3284B93D9A7 +:10AC1000E607C39E6E2315566EEDE6A20FBEF1C188 +:10AC2000C71F6DC5F5DAD1241AD6E9FB708B6ACB44 +:10AC30000F217FE447977AB08B5EBEFEC1953B5EE5 +:10AC40002C30D9DC87E150181D4669A4D7653B63D9 +:10AC5000C4700F1FD30FE70D5780E27A1DFB3F6FC3 +:10AC6000E3755BAAD6A3B510A02CE3A08BBE7681BA +:10AC70005C91A9405212F57AB1A600C8C4D0834BAA +:10AC80000760F8D499C407BD8B5CF2E26483E3E10A +:10AC900007C6E815BDCDC9E4E1236065FD47B90FDE +:10ACA00002FC3369B4F4FE2A9CF6AC4812E8DFD209 +:10ACB000AB1537BE06E8DD12F7EBAD1E16F1DC630F +:10ACC000D772A0701B7F9F2ABFFB085169E7DBB1D9 +:10ACD00004AF4BA8A297BAE342342FD40AE4C46568 +:10ACE000A81D4187F02E29E47841033560FDCC771B +:10ACF0003BB6F823A4B323D85D70966E5735BB944A +:10AD0000CCF7485B43865D18300E218A4F6969FE97 +:10AD1000C4F3987F3E1AFF2DB1C19F58BDCEE8BA4B +:10AD2000A187FE150214B11C638558785BEFD7FB31 +:10AD3000437DEA73EF09640863E27F21323FC07507 +:10AD4000208DB4050BA3F0A83C0A20CAFCEEA7078F +:10AD5000A76D159CDE5FD672284C7A311B3112C26A +:10AD6000161857131853AA209E1A768679FEC1EB3F +:10AD70000BA6B6323A396F81AD870A6CE3F1A5ECC8 +:10AD800093AC2EE6C4E2F4F0F7D2855633DA3420E1 +:10AD900037374A8D1E773BAFB71E9E32B252A59A07 +:10ADA0006A75FEDA8B529DE8C2DAF23B3482B6A9AC +:10ADB00080AECC769D6423107BFD2C111F83EEFDAD +:10ADC00051F55E870F65BB52D965A3B3541F3C9400 +:10ADD0007492E3F86776D898F61565C4B7DBEB9400 +:10ADE0007735D2B8FF44ECA7F641C5D690577FBF60 +:10ADF0003491F720D9BED33CA87DD1525F82855AC9 +:10AE0000B3B1BA5EBB3A1DE870671EFD5472C7BF8E +:10AE1000A0C3F42374097ED92B832C6422005B1415 +:10AE2000C07683C885F6F6626C5B0F8D2A94FFE8C6 +:10AE3000F4144189C7C29C95869FB11A0ACD94E348 +:10AE40000FB1734FDF369DBBF024703A8FDDE92DD3 +:10AE50007B35AC17D3FD681E9C473BDDAE15E95F23 +:10AE6000287360C0AA9ACB5B15DC375B3C44759CA9 +:10AE70007E9F4D2866804063A44046E0D89ACE94D9 +:10AE8000C160099B5731D09301435B95EA2F890933 +:10AE9000C8A5138C76949CBB0FAC30CBDCB7308A42 +:10AEA00095539859527C5D4BE94FD6F76B08705417 +:10AEB00099B59AD8F524FF102A39A9664B19E123D0 +:10AEC000DFC8CADC4C36947CB889256D8757E127EA +:10AED000BA5504D3E669C16DA3A53CEB42E8096C01 +:10AEE00001E8B8BE50120DAB88A033512864024D62 +:10AEF00024CB32BDC3B3EFC96492B998BC8A99BF61 +:10AF0000ED242278DEE6FB73621540F4F9DFD815F4 +:10AF1000F88C88C6D57152E844826789355CC2F4E2 +:10AF20003F7F8C9BBDCF300280C629EA7CA54D8D2A +:10AF30005507DAEE8F0CF9C903B67F3DC6A003E5CD +:10AF40001617360965BDB9642B227F0BE26C1C8B8A +:10AF500043C27AFA4E48704F930D3476B5A5141259 +:10AF6000064B5BA5ABF56147EF3C9B32F3743FA604 +:10AF70000B0AA5CCEECDAF4C02539FEDB4F8E21D09 +:10AF800019B156FE8F9E36E80B1B215DE75C0D6202 +:10AF90004EEB4B63E089AE844D1DB7218E84BB74AC +:10AFA000593D0480F3621D246BC134FB366F8BC79F +:10AFB000ECD18D857D1FD7C328A2D1C0DDD7AA0BC8 +:10AFC000B2F3BE53FB6D04CE60B102B54CD0EBDDE5 +:10AFD000D52C890B958A9BA0FA1202E540856D96C7 +:10AFE00048890B8680BD960FAFE8307899A5FD049F +:10AFF00072CE2A83484025962A58420E022C6407B6 +:10B00000CBD816A3A5D1DB58C094BD9C0DC49AE241 +:10B010009B33D96D02787ED2F8C39F5BA11430A018 +:10B020002938B9938BAD64E9906A6B4CE4B82BF680 +:10B03000E205B0D4871853FA3DF17F96F36E160BF4 +:10B0400097A6F9537989ACB7E7837B712A84BCC092 +:10B050009C8883ECE2DD9A7D8239C2E3B5361B50D1 +:10B060001ADE3CA539CFC7D333A3A557466C775713 +:10B07000D54990579A1EC70C83FFCC1D283E503DE2 +:10B08000EE9910D6C56105C9B8E4716DADBDA34C8C +:10B09000E657DEB6274FF5F83C675CE6612107DB33 +:10B0A00025A7034BA3CFFADC4CBF90ADB8A3035E3A +:10B0B000689BFE57558451E21D528A6B5E94D9B944 +:10B0C000E59983E07F560C51A520B9FAFEE318E319 +:10B0D00002A3370D085343908669BA7761D665FDA0 +:10B0E00011B1148B00C44A0CA8476E0B89A6930CAF +:10B0F000E97233D0346B6581F333480B255B3752EB +:10B10000BC3BB38568788577B038B041E8BA9CDF3E +:10B11000E6E33F502B15C9FE93724EDFBFDD021BE5 +:10B120003B44FF711F91F802CF4120CDF82733B186 +:10B13000F730A18AE543D3E76AACED714F34568FFF +:10B1400045B9FA341B04956453D85A68D936A6FF1A +:10B1500084DFF7A716F03D13F4A267ED3E7AAB51FA +:10B1600048F08560BB59FAD510CE258CD3D0272363 +:10B170004FDB9E643DD05F839CC8725E69412D9316 +:10B180001C527373A3EFFB61EFF4D3D4C41BB4C49C +:10B19000C2A113FFD6579C0213CAADFC5148FE66EC +:10B1A000C7952D9394DB0EE14A26C49B1B6EC89E67 +:10B1B0004FBD599C43A93628BDC6597E501D4D4AE6 +:10B1C0008CFC33ED46604091640006EEFBA875C729 +:10B1D000BCFE13307E7460071CEC723E6644A9818D +:10B1E000EEDB4A2F06D46623993FCE93488229D1BD +:10B1F0000C3126577423D62A29988AB4C150135C7F +:10B200004E939EC4D5A57C0041B664CF7499E2C22A +:10B2100041FB70A3001D5D8438019D0452B96CA7E9 +:10B22000C48CD00A272A456DEDCB9C4AAEFE8F34E4 +:10B23000DFF0B929B21DB910747BFD61C8C259ADE8 +:10B24000B1E1DC596E7947B4213489D10F4C98466D +:10B250003708815A9541561F8F0E242C5ECE428DA1 +:10B26000B3C4F441574CD98706F6664EA13C7E988C +:10B270000256E6F26BEA16852868A29417FB7664FC +:10B28000BF453B0AA3638358C39C8770F643A0B8AD +:10B290002D6570F9CC493036984E80CE07DA5131A1 +:10B2A00095AB2DC0F0CD247AEA4E65EBA98006411E +:10B2B0001B4063239CF89422550BB1351880331F33 +:10B2C0002928B990349FEBDA509B63E468DE8ACD7D +:10B2D00008C8ECA59EB12FB1ACDAACA62C9F3169A1 +:10B2E000D634113953FBB772246E00DE000F4DB017 +:10B2F000DBEC7DCEF296E1A1AFC67C32BFCE27B2A9 +:10B30000F3DE58141B0A17257C39A1A0ACC761A82D +:10B31000B8548CBC649D74F52A0A1FD17F2B1D473D +:10B3200038A3EF143D50718B5075FA59F12073F426 +:10B3300052F189026BF922B3A34090446AF8374F67 +:10B340001988183994D1A08613E5DD6A86DBC6C357 +:10B35000020328F736FB43F5C79FA392CA21486929 +:10B36000173A58A077DAFB891FA40EDB232D851529 +:10B37000DF3A27A9CA4D63A3483134555119989C27 +:10B380002B53C4948B1B195CE95978303135406DCF +:10B39000654D0C391FDF0B3C737626F297BCAC7DF4 +:10B3A000B18E5D2E47C870F5C3B4C712A4B2382F52 +:10B3B000CFA6A35E118D76134C3139626C65537C38 +:10B3C00009CE9D81F3B43F026C2565376651068F27 +:10B3D0008315C740D01FDF59E5A2C7C2E31CAA38B6 +:10B3E000515D09D2EA7F2B0D0D732F820F7D64A66C +:10B3F000ADC45A7C6B953A93C317DDB88D084DFCEC +:10B40000D2147E6E0B701D76B5D57EC64967FA8460 +:10B410000F5F69B56CC64F9011FE85EE8130126AE0 +:10B42000FA0BD24A8E2089489B27A58EABF40D5D7E +:10B430001369E7F10D1D6A3DF54542F31D327702B0 +:10B44000C4DD82BEF06C0FB2C1F26B4EF22BCFB0F6 +:10B45000D29986A2C25827103BE5739FC517C64AEA +:10B46000923262E54213FCF04DE579276A0CA6E7BB +:10B4700001466AE240328BF93A14E21887BC320185 +:10B48000DF6C68915A661EE711FBA1260B2DAF7D7C +:10B49000F20DB2B1A0002115CF6F9F0956AA6EC858 +:10B4A0003D29FBEF7365FF75D11536DD7A9AE9B555 +:10B4B000C99E5D3D6F555285B05E16CC7E5179EBCD +:10B4C000301D519D09C72719939159E631B862B0D3 +:10B4D000632BA9B25BFF4FCBB071D532BF8CADC728 +:10B4E00059DD1AB2CDBBED94051FB18168029E31C2 +:10B4F0009701DDCF02F82F42E9DA1DA7443875879E +:10B50000AEE53BDC5D512038B19EC9B025D0933803 +:10B51000C25F080D1DE6056D6FBB8734F4C46A3841 +:10B52000535B66FC73A5D406DD7739BA1E2D76878A +:10B53000A24DA5A1DB8402D8B391BC60D17AAF172C +:10B540001DED7A55E22B98973F01C726341158CE4E +:10B550002ECEA2D2359195442A3461071BB324899B +:10B560006E7B834BAC9D592AE8621D7793C7289C5C +:10B570003416ACB8091406B5BE0CDBA89F440A4FBC +:10B5800042896BADE8A7260DDB2F1C8F6F1DB80D10 +:10B59000C8B8104F4C00B5978A15432B79418B2DB5 +:10B5A00058EB718DF18C65C5234A37332E7136986F +:10B5B0000C7979709CF40A1E7095A3315F0DD1E06F +:10B5C000C95038A21794AB9AFF1192043BA668F3B6 +:10B5D0008B21F8747B89A38832B33B78CD764453B2 +:10B5E000F77F3E97102C1C15F28702BE0B47B86CF4 +:10B5F000664452144DB8B730A36189DC6A9EAC81B1 +:10B6000010616151F25F1B4B1E3FC44D0C0FF1A442 +:10B61000804F8B9EDC264E002E43BFD479B2DC785F +:10B620006AA77F0A67B038581250E3EAC98F22E947 +:10B63000B622A6911091BC8B72488619E07BCBE3B1 +:10B64000B508F1485D021E568CB4E5CA1A4A9BE45F +:10B65000423D87C70CBC1F8CB23159D5879D1A104B +:10B660007D70C8D910CE9AFA465F096B08368825D6 +:10B6700052C13F24189E26C6F2D83BD601323E3234 +:10B68000214941B23E3FFB043F5C1B4BFD6D25E66B +:10B690007690FF352D27C3088CB929A81050AA56DB +:10B6A0003B8E7D33087299FCE5725419E1E6BE1FAA +:10B6B0007057BA01776FD4D5A31945ADE11CE122CB +:10B6C00052B05270913F82B3E73C4FD2BDC4666A1C +:10B6D000BEC7D2F781A07EFC834611DFACBE6F6A85 +:10B6E000F65191C81C337E9707B5C0AB4E71AE932F +:10B6F000B7384600706C1BC13841B2CAD49B81D2A6 +:10B70000784041FF6DC1E44047D554763FFD8F90AE +:10B71000655A472746E25FE54A5FA13741E069BEC7 +:10B72000972A359DCBEBBE23A0005F17D7409CF234 +:10B73000E6398C1D0CD08ADC03F00D4A8D8AC48B4F +:10B740000F8AFCE80F722C156EAF429D03CB5AEBAB +:10B750003B2DC409D53002021FE2CF9449FD8994E4 +:10B76000B3674016A71F6D9F335D4CFB282CB8E8CC +:10B7700084607B5515132E9B69294652A4A0B1E91C +:10B780002A4DE3AD7D25A6FCE834908DBDC826FF8B +:10B790001E9FE309093CA747918C12838C065A30FF +:10B7A000BB68591BB849D344A4DFE28AA59E38A0E0 +:10B7B0009C244A54593353BA676B7B39862B082C27 +:10B7C0008079ABA0FE1973840D90E9CC874C53149B +:10B7D000B9D1747BFEE75E1C3B2C54B5F556FDF1E8 +:10B7E000A8AAB6174FDB6AF375D1CB842AA27A9543 +:10B7F000A379EA08409F56F7110DA86CE0C1AC523E +:10B80000BC5DA3DCA77292FDB3F36597293DEF40C1 +:10B810003B5D242764AEC4DB5A18FE33235B6BE325 +:10B82000BFDF9DEBB6EB8B2B0CF0308F92D6132342 +:10B83000D0805C5BA1C507EE6EFE3330770A8BD2F9 +:10B8400080C52A472F1C35F0FBFE77E86577CDBB16 +:10B85000DF5E8405BA25054EEAFE2A00DC69EFCCDE +:10B8600030327274312ABFF8B9975D91BD5EA5B2CE +:10B870005BC0B2E3D993E3912864A1707C0A67FEB0 +:10B880003B56F5C5F2DB480C15EB9949E4E74D341E +:10B89000B1D687474C2D43AEF904E493237BEAC825 +:10B8A00010E771F51A8F0A94995BB26C7A4E75FAAB +:10B8B0007C734464F69CA6CF8725EB1BC263C33C14 +:10B8C0003EF679A9B3ECEC33E25F2906392E9EF8F7 +:10B8D000D04DCFE747483BF370DBE225F2E65F0A45 +:10B8E000133113CB672B6AC38898009C4967F88D86 +:10B8F000B9533A970B258727B3EAEC52E2AA1860AE +:10B90000B2ECE24BFBAAE1B125A59AA2583ACB676B +:10B91000EF9B1BCD0EBFD9BBD3FFEC9BE46D456EF7 +:10B92000B6897D3E94BF9B8A45D3D1AC90BA9A4BE1 +:10B93000CE479EE4239F7BB52D1E668202CF4083B7 +:10B94000E05697DACEB76BB67EA29CC401903BB5A9 +:10B95000B7CB46FF8FD088AF39E0548763EDAB2378 +:10B9600068B9B9836DAD3ECD775ADAA4DE8A3FFE61 +:10B970001B59C7E44EFD62532C840024719CFE4E7B +:10B9800057EA06150804508B546A6540FCFCB99AC6 +:10B990001F251B30B6CDC32B2BDACADA5FAA51574D +:10B9A0004B6EEBD23C7F9B9EF5EE2D5B10504D1DF8 +:10B9B000E5139D51DEC557B6D30C31BA4DA94346A8 +:10B9C000B780201ABB081D4778122BC3B54CF02650 +:10B9D000B047B3BEBC1C44AC94EB43DF2C022D1526 +:10B9E000490D3AEF7E47DA0DA453FFAC1E4A137B94 +:10B9F0001087E5158CB7D4A232753E673A9DD660A4 +:10BA0000BC0FF0CAB94AF0E6B23BAB52221570E364 +:10BA100067BB280ABC77FAD87A0279D735588419D7 +:10BA20008AF17DA079620E9CFBBB32BD5FF8C396A4 +:10BA30004FD357025DD00D57E086194E165C2DD1BD +:10BA4000C837B8CD740C860D7688AAD4B774E7C70A +:10BA50009AE1AC8C8B047D0A27851CFF37C17F37A8 +:10BA60002E54FEC527DDF86CD39B3129BDA6854A2F +:10BA70005599F460C0E4C618F4D23548A1C66B5697 +:10BA8000F63AE6ECA8471945608E4A4D997336AEF2 +:10BA9000A65B82E7DE4793161B76AA75BF28BEEB2E +:10BAA0007F39234961D623277871A691AB50113F86 +:10BAB0002BFAEF7D52B0F091DF73A4DB62D245A682 +:10BAC000C4F77AB31D2EDCDE94DBC903EACE124C38 +:10BAD00025D79CC88EEF6FE61EE319B5495C313758 +:10BAE0002946ED72A6777F3FC3886182B6F2D1FD09 +:10BAF00026A5AD640824926C4E78E1B98C7C195E61 +:10BB0000E1A7BF6B7690E0C50A96C4EF2002B3466A +:10BB10008C9FE950A883100E130EBA571200AC4C3C +:10BB2000C94764024BD765240F4376992BF4D1C0E3 +:10BB3000BB59F078BB50F541ECA4FA2AFB6A851991 +:10BB4000C460A900F3930A890A198C3B0DBBAF8727 +:10BB5000E488ECF410A4DFE4E1A9D4BE311D997DA2 +:10BB6000DA3C3AFFFD6DD6D9695F029DCE9BD619AE +:10BB7000C1D025B53EEDAB6BC993A8E87A1B0BF09D +:10BB8000D8D905C5F7EBBF5CF0FC7E0E9B9D0FEF8F +:10BB90003398FEC1776FCA9A488EA6E3D3DEDD3BA9 +:10BBA000376B6B1E9B101EF56FB093B5F86D5D097A +:10BBB00085C58D7674DB254249C9A01A169CCCAB8D +:10BBC00087BB00C2C3CE1C4C97C5780AA08B944695 +:10BBD0005B2597C5DC7115899938D06F2316120E35 +:10BBE000C84FA9D9D758115F8F09FD0E63368990C8 +:10BBF0009B073554B2243D60C431C61EA6E2D084F2 +:10BC0000ECA00FB1958A76ABECD89D31BD3B8A1480 +:10BC10002FC9FF4F66B9F61B9DBD0737AEFF7A945B +:10BC200057A28682B7C821314CC1E0FC89CF6E385B +:10BC3000B534CD9595204BF55F713C75A6D44DE19B +:10BC40008F2CEC3386A93C145A326C07237D4B2A87 +:10BC5000FA65F832C34412C2368BFC86E273E067A1 +:10BC60002D7EC8810956E5BBD824B23AD1535388FA +:10BC700058AB9881D26FC57A31B17CF129AAD2C470 +:10BC8000CFC3AC8EC6EDEC4115BBE2550A790E89E7 +:10BC90003DE9510056B566217E04F57B288F4B3374 +:10BCA0004C46F88F5DB5E87E4B491CE27468D44180 +:10BCB00027C477EA269794BA5876810DBA3E86282B +:10BCC000F170AEDAFFB3E27B21A6206126F02C1BD7 +:10BCD0001B893CE7CB8584E16E8FDFFF293C97779A +:10BCE0001ABF41315174158AC786B66934A3BB3F68 +:10BCF00057C1024076D15844BB7C8F0D606E84E9F9 +:10BD00002DA21BC18B1376AA3A590BB15C1BB07CD8 +:10BD1000B80B06DEB83D6D5596F5807D7CA0799414 +:10BD2000CFB6C69E11C4876339508BFB1451751C66 +:10BD300017BE0583B6393F88B065D94EE0CFC785B9 +:10BD4000F840A57A218D6972DA02E28C59015E040D +:10BD50006289BA6E747F99DC05CC19E230AD7DAD95 +:10BD6000F1A3AE9EC276EE80CAF7DFE35E07948F42 +:10BD70002DACC3CD2587806A5EBEDEBF71E4AB3BD0 +:10BD80005E1B3CFC84FF2B80ABD81034A66E3DFDBF +:10BD90003CA460DE8038FF4121C2B5FEF6FA935A1A +:10BDA00004014062AE96B190652F4B860043E1AF2F +:10BDB0009B814C1BAD9E7831FE3F230FA66412235E +:10BDC000993733E3087D9551E655B86F03E8477519 +:10BDD000DD8AF08C973C718FC4EAA7B056C5AA3BA8 +:10BDE000BB4CCDAD41E2FFDA9FC629FA8C63F0353A +:10BDF0004A2F7BAB898436F0C2D24EB3EAA5EDF36D +:10BE0000E812F1C17FB36BD7631EEF0F940261F1AB +:10BE100033A410D7AB8880BB2F80D2B353BC731729 +:10BE20001774C34ED7C6F4B7308C77E48CB2D3E71F +:10BE3000CCB77E90FFDDD93176A9664D305843707E +:10BE40000DC3FA3DA3C912ACAE6FB841610BCABEB7 +:10BE5000FFBCF7E4B6265783EDA920A72C729F0FED +:10BE6000A207024876775AF43CC4C7D0C73FCB8CB0 +:10BE7000BED5B0379D4A980AC78AE49053AE686B26 +:10BE80007F95D49E55E2BED43DE29B611C8A5D80C5 +:10BE900027B8E3E16786ACEAD0ABAF0675BD9E90EC +:10BEA0008B72811E598ACA8737C3A58D9888ED2069 +:10BEB0003EF95AEFB25468EFF643640D05AFDD1258 +:10BEC0000AE7ED3DC176158C358282A04C1F2831E2 +:10BED00078A93B4EF4D01ADA86E41E9685E484F9FC +:10BEE000D6559A7FA1C12608854062E3050C4E1BFA +:10BEF000C0C44B226E23EABB2437D3EB8250F664D6 +:10BF000049D1C3B7EA96396E378035C5E0A4DAB3B4 +:10BF10007822EC8A56DD8ED2B57E36F7DE364FFDBE +:10BF2000CA3908D6B1C09478BBA9A2F8A7FFAE0A57 +:10BF3000CA4D1EA227855F1430266B188142DBC5CF +:10BF40006467FF5E0C5CD59E49C07BAA2871B2ACC9 +:10BF50003F1BBB9F379B9266FBC9BE1AE5428FC44D +:10BF6000A91A75517A8FEEF97ED287BF2CB9038B4F +:10BF700025CB07888A89B404C7660E102236CA7793 +:10BF80000316D9BFD62B984ED098E458220A7405D0 +:10BF9000CF7A93AF8CA48906E0495B377EC141F725 +:10BFA000BE75CB8CCBDF6169D1F1AD350C6D7855A9 +:10BFB000B6CD6F2E2AC921209B16A01B3F6A26A54D +:10BFC000C7AA5C07AFC5A6719EA490C83622F46CC0 +:10BFD000592F0957A85BED2BCE2D9954D9553E5AB0 +:10BFE0004343EE78B2133B15D53079D8A14BAA3D27 +:10BFF0006E157430C4FEF460384B1F5C04E5FEEE31 +:10C0000027C535E9D5D8B9F260C79A712F25322BEB +:10C010000AD5E15D67B266AA445A852AD4B2CB0C30 +:10C020005E2767813900991E958B87ECE70E889211 +:10C030002A88EDA5226CF56AFD5FD35E1DDD669D45 +:10C0400078B9866BFC976B4F138BB3FC1532C175B7 +:10C05000F2B7F6AFCE895B305AE27AF334CCE8FA25 +:10C06000BA67AE653755265C37317A72C9E45CA48D +:10C07000131591FC2F09AF6F2D9D3A26B0803B9987 +:10C080002F330E71B574C5641DE8828D2A05F8F949 +:10C090007277CF8759E44FE8CE6C52176D12955CDA +:10C0A000EFF7C7336C1600780897E8D701C2D98438 +:10C0B000AF3B25854D5A3D31ACE956F8F8913FA983 +:10C0C000BF1949F32E4FA61EA19C3780DC08ADAFE7 +:10C0D000270042624B322D242C6742AB38A79A8B43 +:10C0E00027D9D49AEC4E366D7734A26F79F290E767 +:10C0F000A31B99F591DA2873B5954C1079A3D0F468 +:10C10000CF5B08DB135F29E04500020A80EC5A3E52 +:10C11000D7901919B5EA646A6ABFDC79DA3C6C7A9F +:10C120004405CF673C62346611161C6493C4BB3966 +:10C130005611D0852F66B4CFCE526A6B2EE7B8EA7F +:10C140004BD01B0677D586488FBB43361C3C05D9A0 +:10C1500010DA02714A89A074D03BF8538318A88979 +:10C16000DD5638BD4ED431BCC5F0F504AE5C7FC899 +:10C1700045C1D6B8D56842DD83B015678B07F49901 +:10C1800099933236C1D50D2354D829A87EAEC4A9BF +:10C190003F200DB0D6D950FD66BC1C25B19797390C +:10C1A00096942AF900A84B46E7B06D98FAFA79857B +:10C1B000C1B22C6A5CC70913DFCFB90C81D5D44555 +:10C1C000FB27FB2834751212846C9AC1159A572BE1 +:10C1D000FE8A589D92914A056C4992FD9F86BC58F3 +:10C1E00093D7740A8A2678EA376D52384B1C89C176 +:10C1F00048B03CAD48995BB6AD8FD2AF2F9FA593A9 +:10C20000067B498EE7911949EE41F09A50C085802E +:10C21000AEED427824F63AEFC0D744467C9F76DEF6 +:10C220003CE99DDF7984380520EDDA4E371B69B88B +:10C23000B3CA0D94373A2A13148E2CEC227B0D6866 +:10C2400066CB8931BE5F413E16ECFC700EF821C111 +:10C2500036D0FEA985E542CAA76DB542371FBBD2CD +:10C260008B3835296681A85006AD3B5B1C9A80C689 +:10C2700066176B752C6A88FE7A98ED3A0F1C18F5D4 +:10C2800012AB7D36A3456603CBD9C26A789CB1F167 +:10C29000188501B20031E99F90FBA21161239DD660 +:10C2A000CE0270D20FB1292F25FEF8F46CB5A46C24 +:10C2B0003B7F7CE0CBDF0A9D2919E8DD8A5B5C517E +:10C2C0007DD3330DED5E06675D099371EFE5633352 +:10C2D000B9B0D6AC4A660FAE9BF81E98B5C0E4065E +:10C2E00008DBB480D1C5B2AF102CAE825C3A1FC857 +:10C2F00007EFE4F8FA7C1B2F8054D2831342816449 +:10C300000A352EA4885C9A11F56ED86CD67940CA8D +:10C310006698103B6C862E6C1151DE55B50A26339B +:10C320004F3F4B9B1DD9178D3CF5EBF8A49C4C5C03 +:10C330003F63A09197CA646D49469C81CB9EDFE321 +:10C34000202B456FD89046FA913EEC43643E88839B +:10C3500007DBC0651ABC686823CF7FD049DCC28187 +:10C36000726D7C5E3E188446BA9E91FC73A237CAF9 +:10C370002FD3BE841866755989D99A5E57A4498A05 +:10C3800029FE6F8D8FDC64C10AC1DD4661B5CB45E6 +:10C3900085CD52A717141DEE17B2BC749EA640841B +:10C3A000FDC7E40CF3C5984853FA3D7A09713C1275 +:10C3B000C24C94271714F48655F2837E372E3CD551 +:10C3C00022C0602B0A9B38425C285281846715B5D5 +:10C3D0003D4BB344B5DE84A9D85380BB08E7444441 +:10C3E0000D47D463523A2943887677B4EC66382EE9 +:10C3F000719E23888EFD1F81032836E1BA975E81E6 +:10C4000046D329CA2D424C834633E5B05AA98BCE78 +:10C41000D5A863076B08DE2549F84D9D108FAA4704 +:10C42000304941D15941EC6C7C817D2F6EB1E6CA17 +:10C4300041B75CCC92F901C2655B87C9B0CB403192 +:10C44000E96E036B874B9517EF3D6DB7BE6FDF5BF2 +:10C45000D408BE950D4166B5E41674C7B1040AED63 +:10C460001BA2CF8E83E0BA8F41B411CDCA89B2FC32 +:10C470000879CA89A01762C96110907E6E4E833D0B +:10C480007A5E1CCDC5769D02E2CF88BA7F722922E2 +:10C49000332FCA7244CDACEE2E9F95B221116B9E04 +:10C4A000E531219A3066C31A5360E09F892C91933D +:10C4B000050EDECBFA94FD1E024B1EBA1331A1818C +:10C4C000C1C86D5B9F1332E9AB1B3CC5F5BFAECE57 +:10C4D0008B036907EB389B134CB3252C9693212BC8 +:10C4E00079C2D0F8587DE52A00AC9D44EF56243E31 +:10C4F000BAF86ADBB92713E786C3A02B924CD80C95 +:10C5000046DE727520D356CDD1831712453388434A +:10C51000383C071B2FBDB14E223AF43D4CCE5FB8DC +:10C52000858B5E69B333DFC9198830F69261308339 +:10C53000353D566556201CAD31D3BA108EB3604FD1 +:10C54000A566D95EDFBBEF1530192DF3313BF1A1A4 +:10C5500049370BF5BF6E944DF66CD2E4C1CE91E332 +:10C5600071C67F307B6F7C091A49CD6790B37E56C8 +:10C570006EEE7E9740286B38CFB29C90F255B0ECAF +:10C58000B4004F791201A8ABA4F7B57472BDC3FE15 +:10C59000FA28E01D5CCBBD874D5755DA8DB848BFF2 +:10C5A000D1911CA033CFD65006B9F3DFDC51D3E9CB +:10C5B000E1C9E18C5355B845738CFB568F24E6B91D +:10C5C000F5B44C6A2EC51809E7B207D7AF10DEE5FF +:10C5D000C49406599D76DC581BE27F5A5D155DFBBD +:10C5E0006FC623D7A8EAD94F1B520C6A1DE27B39CC +:10C5F0003F8B68E75A565A74B159B0EE1CE573CDBB +:10C6000025718F708CA21427BE2C4F0D020D11D9ED +:10C610009F08A77B458202FF0432553F529E22703D +:10C62000A068F36095C21DE713A6A5D51C71BD8651 +:10C630009968468928E2BDED72969250F4B45ECDB9 +:10C640000817BF5CFE231EEFCD1CF12EAE9467AA27 +:10C65000F4DE85098D60F5988623A57125FD232FCD +:10C660008BD919FC4167309E7D4CD47FB62B0D369B +:10C6700068D84925D07F8F7F2D788CF576FCEE9990 +:10C68000471036C9543612E312C1A04600904A9AA8 +:10C69000FECD8C2F863488CB105318483ABB5F965A +:10C6A000BA2C28E59564564E14F8B0F393720950ED +:10C6B000B630C8AEC8ABE691B60409AA13B9ED4AC4 +:10C6C0006CC0B13D2D4CB70925CAC2870741D45D66 +:10C6D0002754E8386A440B255CF7BCFE04CCD1CD66 +:10C6E00055B82472A6A8D410FC438CA785A2892B28 +:10C6F00020D6AAA5E995F5988678A3A44F6D1D6369 +:10C7000073B092ECE4C6FC5B566C8975F85F7716E3 +:10C71000F3EA986FFC433E6C8B40D71DEBFC4F5FF8 +:10C720002A37E7F956BD9620F22284F3D410DE6052 +:10C73000B8C330BFED63F50DB4E4C830A21C85A6C4 +:10C7400045E3C7DAB0FCE8E52AD0597ABF3877016B +:10C75000D4E1621B566E30C840BF6E1077DFFAED31 +:10C76000A6D426EEA73F291B917275936D50C8562B +:10C77000AB6A25795A4FDD2058BB7AEC1CF8BF48CC +:10C7800003DF2A3362CBD7D4D2E672A4054E263C0F +:10C79000D00AEFE58F6CDD747A0CDAB7FD016D7CA1 +:10C7A000CCFB3AE8D754039FB32BEE0D31494CDC58 +:10C7B00067390213511CCD5E2F4DA43E85E6FBF078 +:10C7C000C59B3FCA64F9C432FA1852604018AE4E95 +:10C7D000536CBC93063C8D6A8D25225A382F8806EF +:10C7E000E804AAE0CECB2980B1826B68B9FCDEA751 +:10C7F0003219124D09657435D7248E7ADE54D1ADC5 +:10C800007584F2FEE4FAC3AEBC829257B3B742AB72 +:10C8100064E13921A80432635FC7CFBFDEDD6CA4B9 +:10C820000D86DA6AAE9B6A7860F71227A195790BBC +:10C8300067308BBF46B1590F6DB813949DED16EE5E +:10C84000DBEE705C56D7F0A5632E263F2CF2B7F5D1 +:10C8500037A053AFA1E29BE08658FC88170AFA8004 +:10C860001D1A6630B9F633D3FA0E8ACE6E2642A56B +:10C8700010F4852F2C11E90A892CF1E736EEFAC065 +:10C880009C5CE69311969BAE9F30388284DD9D7F41 +:10C89000926D515B4069C50FE05B44195F77658914 +:10C8A000D3D0DE45BEE856A77DC1F70396FB2E2AFE +:10C8B000AD0EED61BE71CED50963D558388FFE043B +:10C8C0001E0C5D81D99C88C6E3114BF47B03D25DBD +:10C8D000928BCB572DECE9699F99714F6349B50B4A +:10C8E000C2D5A8628D04B5EA388FFFF2891143FFE3 +:10C8F000396D944BCD1368F3FB3B192060825D804A +:10C900005A6DB90D4B63F656778E7E0D0166B48D68 +:10C910005A8F41682AB3F6B25E3B4DBFCC7C6AECBD +:10C92000078109EB504737044D09BAE5DB1CD56E8A +:10C93000E3D5E2CAF98FC44C72381E556919850FC8 +:10C940008DDBA6C64D7879D921FF99AB355F1B7A6F +:10C950000011795BC9A77520E1D693F9500BCF710F +:10C96000B700F6CD88ED1256D8CDC384EF1E61898D +:10C97000F47E4672955E2494BEF49E3582EA9EAFA4 +:10C98000DE3AE90E62E413772D3E549CBF0C131A75 +:10C9900039EABA24253DD839440B96ED130EF68BAF +:10C9A0002D6B5D6200371ED30012E09B100D1D8AB7 +:10C9B0005ACEBF311CA8BD3C0E160654CDA5DA01D7 +:10C9C000F9869CA2CEFA97770C94404D843C2F9820 +:10C9D000CD9F1E1DA8B0224903462469436FC7029C +:10C9E000A4726E63CC100602970EC78C3DB12C0862 +:10C9F000769CD747126A7911D50A755881A5530AD2 +:10CA00001E228D73FEB78975CA2193DCC35B5E3A23 +:10CA1000C9250A8194E9185AFA464233F8FEA23A27 +:10CA2000DC2B308C25C0FB0486A79DA9CDF86C2398 +:10CA300023646E59FC08ABADCDCE3584D6BF32D55C +:10CA400012BED42A4E96B8631AF25D98460F68DA81 +:10CA5000B0A091B7C12467551273DE2E0C29116066 +:10CA60009B455F0C568D196979A82CF1F53768EF55 +:10CA7000228278D45F0D2C928EA4E7866B4966756E +:10CA80003731D12740157B2EEC524E5A4F9FE691FD +:10CA90000A7CDEA0924C9BE4B0A5DEA5C45784C6F8 +:10CAA000C44CD00942DBB6348DACCE4E82A35E5866 +:10CAB000F52002EC74529AEF9BA24D11EDD3C5E321 +:10CAC000B66F158650CB40B1F9FDE7176A490F43A1 +:10CAD000A8945D44B02820E4AC55EB6430607ABD86 +:10CAE0006253685B17346D4A2FE5682461715B718E +:10CAF000ECDDB8D49CC9AFA138731BD3BEA235EA14 +:10CB000050B8BFABA41AD04C27284776FA22A121EF +:10CB10003FBF5DDB17A98FC797EFFCE05DC52CB366 +:10CB2000998F95016BDEB4B9C0F5B535E19BFE4038 +:10CB3000B6FD8E52C78B93AAA2FB2E552C89851D5C +:10CB4000D2B8BB46504F3E4CF389EAEBF86DCE6F3E +:10CB5000E621281224C71C1648ADD3B8445701EC6F +:10CB6000C1F369037D36FC6F7D89CF1996FC33BF15 +:10CB70002D00E2A91E3B5B2E825F90439AFDEFB62B +:10CB8000A75862572418BE5EE512BAC790B7534A39 +:10CB9000F295E558FFBDC5AA160E847BFEDA62BE8B +:10CBA00014AEEB25C370B5153DE3DD3F1CE63981BE +:10CBB000DBC25CD3B8600BFA3DEBA0AD230C07DE03 +:10CBC000A260223580B3E9CCCB95B679990438249C +:10CBD000E3ACD51D35E37E2B4251000A692CF5AA42 +:10CBE000B3EB88592A4C17C97F27094AB46D231E15 +:10CBF00052A7D38F472ABA33E0C0A788BF10CE3ED2 +:10CC000083FF2DDF6EC33CDE4A6E5AF45919E6C12C +:10CC10004AC3B7DACAFE3CD9291B40BAFCAD9F0F04 +:10CC2000181D1B28011AF1591FDD1C035691F2DE55 +:10CC3000B8C791E8BC1E8D3FF733DB3F1BC9A8A6E0 +:10CC40001F29D0C094D49B3FFAE22701E0E7A9D185 +:10CC5000CDA40177B17DA8D6AB4821F70B9315364B +:10CC6000757788DFEFE558C21D24C50B3B569FFD45 +:10CC7000322D27C0B774F79B43CE5EF9F5BEEC3E6C +:10CC800092A8C04C59B1275E7F09C7B529BD30CAEB +:10CC9000357E7093E420E4EC029A0A203FE1F979B2 +:10CCA0000A3A3A915E665ABD65863F422FEF3EBF13 +:10CCB0006D2420FFA4544EB583FE05E1E6D16B87B9 +:10CCC0000CB172B7F2E28CA2832E33BF6F506E3577 +:10CCD00052204E7578AA6986AF69237CED6FE1A377 +:10CCE000AAAC8EB6D438943FDBB74DE17772B6B9B3 +:10CCF0005F5B7193DF7B25A2B5C0C08B641CD26ED5 +:10CD0000A20FD5C3C6F5CD185CD9EA9E6403BCD882 +:10CD100035F6149756371B91F4FD75778E2B0C0959 +:10CD2000B850AA788CD5372BE696D6569BA2FD0331 +:10CD30009D38B977E1BEAB67D251567B61EDB6F84D +:10CD400015EA6CE097A826AE87435D40543D71BA62 +:10CD500027B86307C1229C2E7A4AAECE54BC0E314E +:10CD6000FD8CCA70F9DB9C9E4FF801F892C68A438D +:10CD70001D85D65CA7F75BA01325C1CE842106F9DB +:10CD80002B4959A7B443BAF377F8C01E75140F7135 +:10CD9000086C2DDE6549B2A6B419FFE84D8AF77A12 +:10CDA0000150F57C717CE023A2FD2530BD2FCD1D07 +:10CDB000B43870033BE0DE14D1771A7737949B5672 +:10CDC00033BA4EFE84C572CAD16C1A6161CCAB48CD +:10CDD0009F2AC04CC0F6C71E6DD5ACE3EF4C025D78 +:10CDE00001929F429655E85574E2E256F873720F2D +:10CDF00041F11C8A0EFBE787CF805EECBED77894AA +:10CE0000A2184D33A98A0DAD3C1CBEF62180376EA9 +:10CE1000EE58CFFF5AE99B7A4B9DE6988C1EAA3FAD +:10CE2000CE124E198C1D5A29411FF7BDC59E92C0C6 +:10CE30007B382AB1D089AC3770300247EB74502A66 +:10CE4000D07BD12A024503BD9607F44E9E3EAFAA81 +:10CE50001E6C65667CDDCFB7E38F5CF8E143C8628A +:10CE60007D41B255D7D34565FBFBD6FB2C66A44B61 +:10CE7000A7D2B6FC6BB6F7381D5E4CB64A873E3E6D +:10CE8000E0FBFF7EC1EBF46E3FE360A655B30EC13D +:10CE9000980C7B421D7D1ACC573708768022CC57E0 +:10CEA00037AC20B03CF8D1470BBACC1963BC315831 +:10CEB000F81DC9BB6E6EF9CA50A25865E00B30A6CA +:10CEC00045AFA3E902434808018BC6E774C7A685AE +:10CED000EE87127916894A6E0D1A89348951A92C68 +:10CEE000A2BC4F135C256D808B09A9965D21EBF4E4 +:10CEF000C237EC887D9FCA3B8B9BFC9C33FC3E99E0 +:10CF000081841541241E84DF28C98A94CCB9A9895B +:10CF10005D5541361CB175E8812C382CE14A53BA75 +:10CF2000E9B1843E501AA9E2ED1C1F36431371D2B9 +:10CF3000AD8567D4CE05EE3DEB6D448EDF8C883930 +:10CF40005C8C2B77B46C5E7A5E3D87D8527C7F6BAD +:10CF5000B8A550EA79F424A2DE76946973E39FCDF4 +:10CF60000FE1734F9FD9625F5E888887529E4AFCAB +:10CF7000FE511ABBC67B602E770D28BE83176C56F8 +:10CF8000AA563A582D1EBF4702ADFEFAB24539E9FE +:10CF9000A629C55BDE6AFD86B166FD9CA4BCCF9563 +:10CFA00081F7CDFBFA81FC202B3E6B34AD43B640BC +:10CFB000953C6AB7456518405175465BB76081E19D +:10CFC00056ADF260E6221DC09911B8EDF2BD4BCC12 +:10CFD0002898EA16925ACAA7922DE76078F9B231DA +:10CFE000B42B54B19A68143DF46FAC055355A21795 +:10CFF0009F2287B8BF698B66A0B524D7F4A48B267F +:10D0000056C17739904B483717D26E40656E6AF635 +:10D010001738F5396E4AA8E7EE8F4461938729DE09 +:10D02000C8A92A3714E529C9D7D878E11A318499D3 +:10D030002402046CFFA050446889A586DA1E376478 +:10D0400062EA50C70DB6CCBBB83A1F86D3143BA5D5 +:10D05000762BDBEDBD61E48F129E1165D4DE07A651 +:10D06000561FA4D13668AF7E56CE1BA887DCF1824E +:10D070002A70A6C7A93F27C47CA6864C05FD3803A5 +:10D0800016C50B3C3CA255D7FE72CAAAFF2B09AFAE +:10D090006E431FB2E93E52E1374204648E8BC0EA10 +:10D0A00042CC7D41769E7267F8302AAF9320E9F03A +:10D0B0008CAA20CA34632429CFFC71E89AA47AC2CE +:10D0C0005D7B70930C72CC472FC1CEBAFFFD4752E7 +:10D0D000377F7FB447459712C6D699A9C5C5F39C3B +:10D0E000A156B9BDCF8C602BC82BB6420E3E520B59 +:10D0F00069675C1A10165F59F95E8C0EBF62E4D93D +:10D1000030E92286C708BC042C1BFE67048BBF7362 +:10D11000955301F176EF15787B98EAC64AD098D3FB +:10D1200068D9F3F6C73ED863B095B9FE94F9AF7AE3 +:10D13000A8BC2B938EEAF7411A794C9F842C0843A4 +:10D14000885B32E5105568FDE98A3ED1B322C6F707 +:10D15000F5311C54BEEE5FDE738827ED64B3AE4933 +:10D1600029532F693DCFA5CD5C04EE3C5A198E5F43 +:10D1700054B17FBA047FD6AEE6C1AEC9C3E8D29936 +:10D18000AB74A198180F9B7755CA1B699F5DB05D62 +:10D19000EC01FC63816F2AC033AFA1ECE5BB4A54BC +:10D1A00028E24A3DBCFEAA86EC8D8124EE72DA7339 +:10D1B000EC392596C0D9F40940781B36AD5D0B7566 +:10D1C00067158F8D02EFFE592931E628F68F53F14E +:10D1D00011A1286AF4F06A3DCED54A8872A496F06F +:10D1E00013E5B76EA45E6E697F71E9D0A396A05D6A +:10D1F0003555DCCABA36A3F33BF0F12178F4E0B040 +:10D20000C5692D0989E42964D34AE63FFB5EBC0366 +:10D21000879C832C83BBDB8EA754B737F161FDD38A +:10D22000B1FF8C0D9DA494916ADCD0FA8FCBB2D162 +:10D230007F9BE7ACB957B3B573EC7C13098B52E114 +:10D24000E1E6FE016E8529C69F4FFAAF3CD16E0A1A +:10D25000D253B67ACF2199BCE9A16433E32DD0AF84 +:10D260004E786F41A0A8E979F1AC391A8190822BF0 +:10D27000FC5220A2A63116A014018C65040DB9350C +:10D280003BD0CE71DBC976B1601FA9752BB1F6A575 +:10D29000F3EF5B61D9B0F518FE38ADD33E5BB2D188 +:10D2A00049FB5355F5131C93D82FE005DA84FEC2D1 +:10D2B000BEF15907B9723BE78D860F0F5919E7DEAA +:10D2C000FB1241D4DD81CBC198F9C23A4FD3FB4B5D +:10D2D000C6CAA8304F55B5F3290E806C0103CBB9EF +:10D2E000BF12C59DB8CC394266F463F47F724836EC +:10D2F000D47B32CA996059E5E22AAB8AAE98BF0066 +:10D3000016EC6B11FD4726EE26E66CB7AF28399A6E +:10D310004AD15CE2306FC30635A46063B4ED0EC53C +:10D32000E7300398E6BF507409DA4FBDC9F442FDF7 +:10D33000DEF26E406C25FEA3A7F63BF749E5976C3D +:10D340006141558385519050A725ED4F12444638D1 +:10D35000A21D66799F62D355D1355E67858FF4AE85 +:10D360003D945F478739D8CDCBDB13D83FAC23C57D +:10D3700062097F405DF5CF44BFB93ECBC20CC70602 +:10D3800045EA9C141E3252B31CD5E399C4186CB103 +:10D390005931FA45E4D9CDE0DD3508C01FAE9679A4 +:10D3A000AB4F53A4A5B6C671EE1E357E9F1E3775D2 +:10D3B000C9B9E36AE8039A0D7051BA0B5E8FC331A5 +:10D3C000D188CACCC48C08749EEF84337B9E73B71B +:10D3D0003A7456185334CD7BBEDC5E909313712D96 +:10D3E0003BCCF4FD4D608B587468894BF7717054D9 +:10D3F000499F6BB98EBAE0674D9DECBF2AC6E1DA52 +:10D400008E27E1D2570883166AECE20E7812C40C1C +:10D410007372DE1FF1CA011DA299EF201C645947E7 +:10D4200042BB945AB7655D5232A02AD3E7645A6D65 +:10D430009AF52568117AF51A2E02226E577FBEE002 +:10D44000F9943D91DD27292EDF83B8CFC8771646A2 +:10D450003C45B1A51AD14B2F741CB724A9299B3E7A +:10D4600080CA5A89EC187387CC2AFB5A75372F511A +:10D47000D3925DBDF07A286B05C5338EC43993C055 +:10D480006778BAE7615EC7BB1FEF7A6E3175F84CFB +:10D490006F4E2DB25DC09C68D46EE9CB1C2AB4A639 +:10D4A000AEEE6AEC6870390FF01E9D77A618C93091 +:10D4B00066E0BB3F2DEDFD1E3C66A4C059F20D4455 +:10D4C0005C9BD6FAB3D9FDABC8A4EAF755511B73E0 +:10D4D00026E151DC803F76A2E7160A0E10AB551FFD +:10D4E00036C821E52B6A314D9016C1E8992D3D9D36 +:10D4F000171490174DFE7630C3B2E86F0D2B418B99 +:10D50000B1D0BC510CDC87B89648345264039DCD31 +:10D510005A8F979BD2A9D746A99977CF63D16C41EF +:10D52000E366A2DF1634C50717AF4E7336A8E4BA18 +:10D53000C689DA859EE4693373A1A9FE2071C4F718 +:10D54000A4CCBFEA919E773A5B05531D822A202026 +:10D550008FE58C3F3838AD267D79D9DF69A9244A1B +:10D560009F9DA5326D4365ADB68DB4E774A192A8B9 +:10D5700006CFC5DF71B8B8E9FF109DF8380943CC74 +:10D580006C890CC90E214BD3D6367698B1D726714B +:10D59000361807718D17A1E9EC8CC923E97B73B1AB +:10D5A000549DB79AF83D375FFE77E12AA1439695DF +:10D5B0007F8930B29DC1AFC5BB3F402093D4154396 +:10D5C000B193BD5E436C5305418DA04D1A7E0CFE98 +:10D5D000F1D0EC9E3C3E5049D7328331FEA7BA933E +:10D5E00088C2E96B71E3A96183389B5C7B59924FD8 +:10D5F0009896714ED46B0C34718D0F847EFD5D1046 +:10D600009135D3CFC29A693271ED046BF32849D5B5 +:10D61000F6398ACE15AF05E285EA121DA077794D5D +:10D62000EBB895133D82CCF2CD777C600DC944DD1B +:10D63000F9EF14F6173F52B9F9C9E709A5E0E589F2 +:10D6400039BF6D146CE1EAA600CFEA5766CC9D673E +:10D6500093A4201CAB2CF15C3D05E01BDC3D8A61F2 +:10D66000CC801B1741089AAE7B037977AA32ADEDC7 +:10D67000AEE1DFC78435849E6429426ED266AFA1D5 +:10D68000A48E4C72BADE532AEAB7FA9BCBD7E0F9E4 +:10D6900044ED519F5CF0AA17F8AC61B6509D6492BE +:10D6A00074FFA6922EA9D887932C23F7E4A64004F2 +:10D6B00041D730D5C3CA7D2FEED78CAD25D7EAEF41 +:10D6C000222585139F7AC578FF8C3A90B9379E3B07 +:10D6D000949AF490BBF2B7933DEEE926F8F1ABC013 +:10D6E00022CE581F48B7BC1A1C2D4962F3A62DB292 +:10D6F0003B426F219E63D9AB48259BB2DE69FE6D2C +:10D700007A2869A129663F600C823EE5EE58145ADA +:10D71000E0EC1F4603DF3087E7676FB858A60F902D +:10D72000B311E6FD9DF7D2F53F2083FDD8F277B91E +:10D7300093145BE4DA70AA4BF8AEF113B95AC75BE5 +:10D740009EB10B6DE637C1532534BF76F1F914D481 +:10D75000D1CD862C595F9A041F26CFF8C25BCAD957 +:10D76000F91E9C19D48F631E3C012F9813C7F29B9E +:10D77000A0D6389A4F794778006BD404041548FE38 +:10D780002177EC2BFAA814C104CDDDC300615B66E0 +:10D7900049FDF09B4B77DEDE0BC40F15B2960A02F3 +:10D7A00076A768E744A516BF895EEB72674D2B2408 +:10D7B0000C9E60819B5CE860ADE8E5E24C075DC6CD +:10D7C00055E90354A205914924C56E8F5CB7576A89 +:10D7D0001833A8AF598D84B7113B422FB50FCE50E7 +:10D7E000FA8E472F47EA91E8803C0BA83850D56D58 +:10D7F000E248ADB6AF655DF6773FBE44C0FEDAFAEB +:10D800000E3705A7E9A905B9AE0401A1B97D7A1DB6 +:10D81000D97F1B3F3B2CAB34A9B7E7FAC704C786B7 +:10D82000E44EF55F097DEC623DB80D3BA333463F06 +:10D8300038200E2BDD285843EE7B937003979333EB +:10D84000386EC904B6DECD688C51E966F93D8F4764 +:10D85000BE9DD5C52A75F2F3E10073DE81DDA61702 +:10D86000FABD0315EE1773B864CE12CB5B1781E5D2 +:10D870008174874C1E0101070976EBCD9D1224723D +:10D8800049EAA1A378E30DB94CCA48691691ECE1C5 +:10D8900052E715B68DF0D296B5C89722F0FEBDBA04 +:10D8A00093EFE09C33ABD76F08622CFB494752E4FF +:10D8B0004B419EA87784C6BE2C07D28B50AF273928 +:10D8C000050ACA5DEBC936A2CC32D0326E8A75F732 +:10D8D0006D28C8977A7976A91B229855783D4F0014 +:10D8E00086B861970F8DF8E211BB87A63606D0EE99 +:10D8F0006DECD42F7D739B684A8473A7D01C5C5851 +:10D900002EA8C556863B38C1E6A20199792121800F +:10D91000F29B576CD50C929BE51D588FF6CB7BF68E +:10D92000ECAB38420D7F4FBE84F2B9FDD7B41EE296 +:10D93000F92A3791009E72A5110EE9ADDEFFA3739F +:10D94000A2EE45EFF389C4968CA82F0A8562F3E70F +:10D9500012E86882F8C2FC89F164DF5704677AD65E +:10D960001270688A9A01F2467CA9539D7624EFD8FA +:10D970003AC47AAAD0B4320C963F3C57BB9F3F3290 +:10D980002026D3E940CAFE18264305CECEC5DFE1E6 +:10D9900036E1EC4251E2A3272AAF784637B2F2AB28 +:10D9A0001A8BC2FA8F01EBEF887D6E799F1DA4540C +:10D9B000BA1DAFD296F54577277D6541B51E81DC4E +:10D9C00033E8FC3A472E249BBB68642733957EAD31 +:10D9D000061A8B695FCA10FC06D44F3FB37852B366 +:10D9E00046AEC25B81F77642770C3B0293810C38DE +:10D9F000D255913D95A1D1C06DBE1B0B5DF2830840 +:10DA0000C77F135A00CBA0A132E4BD3E4824F2B533 +:10DA1000034A60468CE57DBD518B10C81EB0BCA387 +:10DA2000671FC469FF066B0F34E13F112D7A7F4BEE +:10DA3000282244C5CA35CC3377A7A8C2E7D44760AB +:10DA400074B2518E5035019629737495C55887422A +:10DA5000DA942A2D2545469E8BCF29B474DB44D613 +:10DA6000971F37D7CE9644D6DA249162C857FD83E4 +:10DA700028A0C70E34512A01997823DB65201A307B +:10DA8000C8F26A5B69B652F9F17A4C6953BC4CDB57 +:10DA90009932E0A0755A7460CE7214BE771C0CFDEA +:10DAA0009E960E107A3DD2C205A83C6D231C682DAF +:10DAB00043C360071F2E91A3AD8052A70926EC7ABD +:10DAC00003575A3C966AD401216B4C3A71930FED7F +:10DAD0000C5DD2CA3A99ACF976383A19877CCB11E9 +:10DAE0002477B8FE30086873B1F08AD39F6CA43FE6 +:10DAF000F99704451897170A8DB13003EB2EDDC650 +:10DB0000DAFC927F6B5296D37324A34B19CEA043B9 +:10DB1000672AA07BDF2ED4F7EB2C1B3B12017E6E15 +:10DB200021BDA680CEF7198A63735F0234D8F5B29F +:10DB3000EEABF74284C8ADEAAB04653114426DA682 +:10DB4000AD1B2207E13B429B79F91A2126604BCDA0 +:10DB500017C4A8BECC1AC3CCC98A5E1BC82DDD3C35 +:10DB60008A434CD7ED2FE2FF4822492E69808BF57E +:10DB70000C0F18BD1044E28B7270A4F7BEC54CE0C8 +:10DB800009A3E8B99BB64D5C301B7D208AAEF23804 +:10DB900025E5D0EF68AB6828D596737CCBE584E4A7 +:10DBA000F44E0D334651C252099E623E0DCA4ED804 +:10DBB0008BAD40E09ED19EE3EF295983CD853FCFC9 +:10DBC000FF47AE91DDF0535541B335598C7DC57A91 +:10DBD0004A1D96691D72B164DC50571A7D704775F5 +:10DBE0003CD3606CBE61C23EBBB65736DC84C6BD5A +:10DBF000AB3FF920C1ABB30455E7550A4F9F659B76 +:10DC000087AB06147612F6ABFCA1179DAEB63D614C +:10DC10002D20DC44C5D0873311FB8A2BD2A82AEFF4 +:10DC200082CA46CD30278E66CB80B3965D9EC6D025 +:10DC30006FBF4343105B930D3BA7B4C6D16E74B660 +:10DC40009DED285B5A3B51F7593614CFE82AA9F7C6 +:10DC5000592F62735B7FE2F6A4E526E402B5E47F08 +:10DC6000A9FFFBE122998EAC1AAC65E187795706D2 +:10DC70005B26A84BD522061BF4F3E38D32502029F6 +:10DC800076D1F4465BAA4EAC9E8C041A65C75470DC +:10DC900078D6F7A5213D2BA9452766DE61D6CED1E2 +:10DCA000839A19FE96376EBD61E6CF51D4CA0CD562 +:10DCB00057465C1E68BAF3F1A2AB57E17E2D2BE804 +:10DCC000FC49A9D9DB3B4A29E6F218F228285FBEB5 +:10DCD000A8DD8B9CF982BD0217CADE92226B24F16B +:10DCE00033199458F73CBB289CA76FE4D6B7ECFBDC +:10DCF000635A2A5BDF85C0BAFC1627EE92778B5FEA +:10DD0000922F065AE4929139AE8B46FEBBAB2A3372 +:10DD1000D1F4FF2D046F738A2E62C71CCF330C4DD4 +:10DD2000AD5AA61762F63095C5F5B7368A5DC1883B +:10DD3000BD7B3A5924F0C76CEF1F8B39581F363D15 +:10DD4000A972E062C67C59C4435F0B0AF7BEFF2983 +:10DD50004B0224BCC677E31D7487ECDA4C33B6FE65 +:10DD60004E998B922DE3E705475B089C8572EF89FE +:10DD700043FA088804F310A9FED12077B977E7CADF +:10DD800076A352FE8987D3187587DB7F26134589D2 +:10DD90003272C5651EF45350D085C99B261C5A5754 +:10DDA000214F7EB9F769DBBA5564AB7C6A7E0EE41D +:10DDB000CE7B1D4C161FFCA04A44D11827B30B4B39 +:10DDC00047A66D4581D1BEE8A32C9C23CC9600913B +:10DDD0003377CDB8EBB569B861479EFA9DFAB7675E +:10DDE000270857F6887ECA63DD1719742C345981C9 +:10DDF0005AFB0E04B1869F2C8B7110E500DF087D65 +:10DE00004B7927D6483F84011A37B31CE5D57ED11C +:10DE1000B5BA171065EE5ABA191E4E993B17BCD504 +:10DE2000EB20261E6E27DBFB11CD53946893E3FF96 +:10DE300045F2EB7C1C2034F0D0629E5C1F33C6D7C9 +:10DE40007224EF4DFCB5CBAC89417A334EA1846D81 +:10DE5000D2751B0896C2273246C07FDCBB8C6FD9B7 +:10DE60005329DE719E8C38EECD884501C95DD5C23F +:10DE7000669D842109558FC3E5469EB5688B8A7DD2 +:10DE8000CFE7BFD0689A4F32D4FBABEA4377037534 +:10DE9000B6441F3501CAD86E054B18032428C4A9FF +:10DEA0003022664ED36DF2DE515470EB9D835E0CD2 +:10DEB0001FD4A4166AEE7D589CA0870B7786D03EAF +:10DEC000FE3A7A03919F257437C165C386492D7840 +:10DED000A6C662C8E30CEFA0311B81DEF38A31C312 +:10DEE000676E1ED64B0AF52F7A2C2BEB1EAA968F47 +:10DEF000CEC95AFCEC48911D0982F926285891D6C2 +:10DF000058FD056AE77D825440561C2B69B48F6921 +:10DF10009E238871C7FEB5A93BE326EAA84A9B0960 +:10DF2000A23A633D6EFAE46DAFDAD54C2C18297B2A +:10DF30006DE7D32F45DB1FC139FA93BB5BCCACB483 +:10DF4000F8A536C776FC72845E840DA605591C2B95 +:10DF5000BA75822A23BD53EE0DE47746808FF9EE21 +:10DF60008A7BCCB78100FB16E6FC2AE5ECE82F940F +:10DF700062EBEF3D0DBE6943926B2027627C313C22 +:10DF800020DEBA7C30ABFB70D36C09596B9173DC2B +:10DF9000951E89C1116FA9CA7FB1DD32AACFB5869E +:10DFA000AE5BE99FA5B99315409473FF6C1E59268B +:10DFB000006AC704ED77B759B0190BCEB4F85140D9 +:10DFC0007256352901F8C19A867122BED9C360BC48 +:10DFD000CBA35EE3530BA0B5591286128CAF578AC0 +:10DFE00010E6ED456FB93EA2E5792B74E8C12081BA +:10DFF000C560E9B36B480EA2FB6DA1F2D519A62648 +:10E00000B53FD04F66A1FCC68EB51D7E81416572BD +:10E0100031A0DAA97D863844D335A37D8C3CD0A3CA +:10E020005020C3E0E15237AF96730B5622819D74A6 +:10E0300038B0A11B33B0F2BE5BD6CB601A5F5C94E4 +:10E04000BB3CB798BE7F133BBC7F498DC7264FBAF8 +:10E0500055CCCB12F8862B7E218FF3155236C41582 +:10E06000802CECC4D25BD12968C2CAE0DDF37A57B8 +:10E07000FBACE5A738CBA687D6EE79794BB7C40DB4 +:10E08000AF1D83C5FC055AD3AE2AB2AFD4DC8933A9 +:10E09000A200772D84C7B5AC1099A69FD19842BB3A +:10E0A000D1A07A2FC42F92D511291DC4BBB8699C69 +:10E0B00058DC7657870389B48A5B5E27AAEDBE7663 +:10E0C000D163DAC2C4E29E0D37CB65A453268E011C +:10E0D00030E3E61B9C486108553AD69300DCF360B8 +:10E0E00052BBCC5097106787E28CD95FEEFA84D090 +:10E0F0006AA1A4A0585A44B51E89FD5E9E0271CF44 +:10E100000009EAB5EFF71C6AE2E0D24B91AF5D611E +:10E110002B005572A8534C73EC13717DC8611ACD56 +:10E1200004F4529E7F64812D10BC570D66A3703E8F +:10E1300081453B97D6150A56D3C66EAC164762A0EA +:10E140004FF80CFE2EB0B8DAE6104CA095D6A824F5 +:10E15000F5093503CD06D388F4EC97930776F5548B +:10E16000D5992D78E948F6C41C2C875FA898C63D40 +:10E17000E4AEF447415F917FAC60A9797DF6C8FDBC +:10E18000E4A5F6EB71003605BD5B8DBAC4E44442EC +:10E1900060F7FBACE214B26ED051B5287D0B5EE99E +:10E1A000D7B0F802FA3A6D2BBDC00DDEE3D7652576 +:10E1B0004B9463C4F011090B1C0246A695A18C3C3C +:10E1C000ED0F91D4266213CE34FCA1C21D964029D6 +:10E1D0008DBB5BBBAE31C8E8C97806E0FF63A147E1 +:10E1E0003129866F2180383A14ACE13EDB5CB404FF +:10E1F000484B82D42301C39E45C910E66FFDF03C15 +:10E20000A577E03B8F039D2269824DCB2A88A9C662 +:10E21000CDD0E9470F058272D173EC4179221819EC +:10E220004843FE818DCC7D606DAE5084B1C92137ED +:10E230001273CF7E6AE28CB4B0A793EEAF3054A0D5 +:10E240001D72EA6CDD4CA78809CD345C6A7FD01959 +:10E25000ADBC5339BD9D8468A213E936D2AD4C17CD +:10E260003CA3555CB24A44D2EA63FD33AB341D890A +:10E2700092845CEAC10B4CF43352579D9F145CC0EE +:10E28000775AEEB6C8D7FD702596AB6D0905D75104 +:10E29000CCDBA51DF083FFB8E20A688359D93AADFB +:10E2A00020B8EE129E2C7A48C1299052DCF12E81C2 +:10E2B000EC2F365D71BABE6D3A2784FF9D6737FD3E +:10E2C00014A8EEAA8CBC97E6B71036C254396B017D +:10E2D00024CD0960B60453930E93C7A83409029A5B +:10E2E0000626F9C13B6D7D5025F2BCC7BC54A25037 +:10E2F0005907AC6579DB9B1A08726DE5661E1C4FE9 +:10E300003366F3B65F52D3521A8C8B7402F03EAE72 +:10E310005626C4A5F609EE13B007B5D8CD2D741C4A +:10E32000B92F44258B3D6FCCCF28EB406DF6394D8E +:10E33000A129D3EFB116C0AC76421D96C2D8D7E35F +:10E34000015B498BD62C7521168AEF0652CD3A5DBA +:10E350000279D8809E20B7DA435D7C65C30A29CC58 +:10E360004440EA1BD83DBD2021FC9B3696B1B7FF47 +:10E37000257DB6091C59F1887A1B7A4D7D198CC30D +:10E380008CED17654E7EC87BB7D2C1DE85F9EA34C5 +:10E3900077C012F91CB77058A529BD04825A17C856 +:10E3A000CDE1FDB3BFEE4FE8FAEF6983681BD0F60D +:10E3B000EDFED1767B9EEA84E84E1029B67696284B +:10E3C000E691277FB1D1879DE7D7E7326929975238 +:10E3D000157593896377FF48D327D66B94BB633257 +:10E3E000003431E094278240C1D709617FB45005E1 +:10E3F0005F1F1FEB2F83F0458C18316BA7722679B6 +:10E40000224F585102E0164E6C3CA55CFB93C62C83 +:10E41000D312AB99F32D832C8EC31038E2946CC2C7 +:10E420006A13557173ADA1E9343E6AEEE2F9E05822 +:10E4300005521076C042014941B62619470CA4A4E2 +:10E44000DCCFB4E9E6CCF00CC9D1B7C266C6430153 +:10E45000A82B6A660D83953C892A397369FEDC63B3 +:10E46000F93AAC875A3F50EC6E98DFEA255F5BF9CA +:10E470006EF411E2A39261F168E181C5A347968D24 +:10E480002A1C1C7C002AD9DE2C392D8E9AAA6C7F7E +:10E490003441B0F215DAF886676722B16A07676A15 +:10E4A00021287580992B755A1BC1F0CA0E3AA49089 +:10E4B000A3294CC3489831C3E1E6F7798728573C34 +:10E4C0004BC9E026DFB8FF93D468879C12011A3845 +:10E4D000456FE3EBB21F9747F10FB84D2A1A49C0B9 +:10E4E000D1C854034695762346A0F188B9AC8A7BFF +:10E4F000DC24F4E66041F8CCA7D017289F1B08273E +:10E50000447E81FB3C086F8F0013E3FE5A8AEBE6E2 +:10E510009C8443E601AFBC2FCAC8910675E3C96469 +:10E5200003BD91D2E69B9B5E5C421C869CD6459BBC +:10E53000701F4B36322992B15221E16D273F677C23 +:10E5400049E658835E5F7783CA15AE1D849C983C6C +:10E5500031A9EC681263D8510EB94DEA0184F18EED +:10E560001A72AC07EA591E5D5114245121601B7DBB +:10E570005EE1DACD3897FCB83330AF0FDD3F188A53 +:10E580007089F7D1DD531B3F3BC521C997B0BF67E9 +:10E590002D1BD853F8CAF34ADCD7505524AEAD89A9 +:10E5A000D5172401EE4854C57BF311D977658CC586 +:10E5B000742671D26733A38C9B1ADE1B8909457FB1 +:10E5C0000ADECDCD35EAA9F7D7270A084194DAA8A3 +:10E5D0005F8D46539950EB9C164CC73A9DF1E9B8B4 +:10E5E0009409C6EA13CB7458C5728D13853CEDFEB1 +:10E5F000C4DF8FE38A7DF4E9BF030A5370A75D513E +:10E6000021C7ADF17D2922DC678D81DDFE48E3EE77 +:10E6100012E3CD8AD99FB926410B417D16818558D9 +:10E62000A7597B447E3521BB56A105CC2B914C27A5 +:10E63000F03213D729EE6CF5CC00FDAC127B20AA8A +:10E64000C4B39E5C10D2EE98758335E130332E272B +:10E65000C3E556BF7E0932151A0920AB5A4D2A036D +:10E66000E7DD52BFC2AF91642E6263216551ECAE0B +:10E67000B8330BB5B3C19E4DEEF19376AE4E14C3D5 +:10E68000EB0E8E7D10EA19B17868D888422BFBE238 +:10E69000873128F2C8C61AC6B90943FE82CA307744 +:10E6A000A9DA257C52522E099972D15D32FF512E82 +:10E6B000E67ADE8CE03BDE7E2855E252BA078DF327 +:10E6C000B9237B846844A54B59B97BDEAD2CAF726E +:10E6D000FC0E339B60841A24C81FDFA2B60E1724D9 +:10E6E000E1409AB2D18BCE50A38FD774E8463595CE +:10E6F000EA1D62FACD4AAFE023EE0D02EE085A475A +:10E700003FAF8EC6519634684EEFA96C5D40B08D18 +:10E71000EC820EB1B2E11CB91398B0FC497A5E28C4 +:10E72000A517F6C3C8AF083DD211BEE787781B7E98 +:10E73000315D4E15166D5B7E0771E9990392A94A0A +:10E740000D4C78B178D0CA068D7979DE8668FB5594 +:10E750000D3D971418EF94E023440FA31543D78E73 +:10E76000455B2FEFDF720FEE9D3316D6ADBA68C44E +:10E77000511D3B8ACEDF65C5704A3D3E8E0FBA8D76 +:10E78000EF9649540C6D2BBF0C38112FE0AF749EDF +:10E79000B67956E5922F759C03026AD55728E3197E +:10E7A00006B64E8FB009DFF3F1A7692B84DABE8D70 +:10E7B000CFC5987055ABE968741E84247F196578BD +:10E7C000D355F3582A9621E8E9B3D26DFDA805DDAB +:10E7D0000311EAC8A53B33FFEBF1CE4B039B8BCC77 +:10E7E000A2CA99DC39D62632DB427E80A2F2905151 +:10E7F000EC36535C5A8B3FB34C407F8B2A0CA617E8 +:10E800001B3AF3C525D3796D76F00AC331CCFFFFEF +:10E81000D4DEFE71574D2D02FF08E9BF1E5A26B106 +:10E8200036F4FCF5C395F35E4CC2629974924FC006 +:10E83000EA67A59CF58D2F08A6A54E0240B5F0937A +:10E84000F5B0CCBDEA57987806A170468471CAE449 +:10E85000ECBA218F45893CB7355613A560C157E402 +:10E86000CB6AC2DDC635735A7F4B8F846A6CA500B4 +:10E8700068FE92EDFD73E9DF218C78DB9E08C559B7 +:10E880005A44D39A3FAD36FD342B54CD6A286C8D53 +:10E89000FA6DFDCE0721FC0F2C3EAC6C2122558B6E +:10E8A000AE58EBC8BC577B7DA5E6485949A80588FA +:10E8B00059FB774A1BE39FA2E728FE918751D53A7F +:10E8C000ABD4B83FE36C7C88F1F6240CAA7177C80E +:10E8D000E115674000AA75E77CC33EEB3C3AFC506B +:10E8E0001AA34D3745279E71CA8669A9A896CABD45 +:10E8F0009FAFE130E43641CAF18854780CE9E2AACE +:10E90000A69AC1CDCCB101E9C91BD4A24D78F3F6CA +:10E9100042216A26DADA93D257AFAFFCB57989D3B0 +:10E92000932D0403F8F6D02519CFB0954A207BD15A +:10E93000E5E8F4671E137E30B4452833BD74D23940 +:10E94000E7BB6E3505A4185D5A93A14E545CDB18E5 +:10E950003DC28257A4F4C6F8847ADC26621DAA1C44 +:10E960006EA247CEA321EE4EA8DBC81D91E727700B +:10E970007798BDA69B1242DE052D832CE33716F552 +:10E9800043A91983A6C596A0B962A4E408ADCF5BDC +:10E99000CF2A85B9CA764E2BCD5D4D34B758F81FB6 +:10E9A000B4C8D4FC1ABA6DA2427D76A4E0407922A4 +:10E9B00029B329804F9FF499640709D3CD46276F67 +:10E9C00002A2ACF681A01099F037E180DE08A146E2 +:10E9D0009430DD102BC835C8FB581371222E73FFFD +:10E9E000ADECEA95F7EA4D63FBA4093FDEB3D175C0 +:10E9F000E06B7F0E483498A5ADE25567BBCF706DD4 +:10EA0000AE3079A5D4F013BB9AF67E6ED2140B3FCC +:10EA100075459CE2E79FB2F0F66EAC4E9CE567F65A +:10EA20001E50090EDD3FEC5B95F35FFB331643A0F0 +:10EA3000B6459894FE26F2FDC97DD30D37967968C8 +:10EA40006F32EC909840D2638A0083BF1787B13051 +:10EA50002B89F4E1D9508E407C59036E924BBD68EE +:10EA600087688AADE94ED6D9EF77931E8FFD993D21 +:10EA70007843DAA0B2329DAA7097A53BEB29839424 +:10EA800004C84A224C6DA19CBC1F2827DD55781D67 +:10EA90001E1E1EA8A562F6346884B120E4EAF13C8B +:10EAA000FE5A4C462C81AA0DA3E80C0F947609B8A7 +:10EAB00052FAD669E6C064C4BD8ECDAD768321EE30 +:10EAC0008B47BE732FDC9C84051D0235389EB70F23 +:10EAD00023C86E3D57B5479AF38B2034CCA41C1342 +:10EAE00055F1A819622278760482C745AA812C8440 +:10EAF000A57164964F0068BBB41BBE5CCACBC10253 +:10EB0000BFD45B15EF9AE22B913149B294C91F5BD8 +:10EB1000953F25CFFF3E30FFC748D22D00A579E5B0 +:10EB2000F4F503AA481E36F46B362EA00003092D17 +:10EB300017A7ACD310511E0A092E265C8EE816BF0B +:10EB40001A7C36E8515C23B890360E8F713B3E2517 +:10EB5000EEAE27E5B27D67259DB7575B7BF81D417B +:10EB60009C7D80187F9EC6492F5824B3122FBBD09E +:10EB70006697CFB207D99692BAD548D7611A425252 +:10EB8000867ABA53C4A97F36946772B732426E94BC +:10EB900076A180C5C48D6230EC604F3EFA7D009155 +:10EBA0003B1B62411ACE7FCA9352C9C376909F37EE +:10EBB000DCC26C983653D472484EE5B726446CC11B +:10EBC0002717BF04869030D12660AD142473740AD1 +:10EBD0009E38F8EA946FFAD2C4012BF92C1FD402A4 +:10EBE000AE80FE5D6296E7B6F4105F5E469ECD0194 +:10EBF000D6D85521BD066817DA3B9F3269EB15DE82 +:10EC00006288568427B0B0BED8360A3D5C4C6DB2DF +:10EC1000D7AA5CDC998EB1978772D4642585C5F339 +:10EC2000A34E3DC2E26EE18E9F1E29CEAAE2EAF219 +:10EC30008D4B86BA0B13DC51EDC1D6C75F150C3175 +:10EC40008C09767B8B77832A374A5F3FC7A8AAE572 +:10EC50001184EC04364A4B7868160BE9CF86FC2009 +:10EC600091524A0944191DCF23FA0AA36F3FDFFDD1 +:10EC7000F1B4AB00659894A570AA812E67694678B7 +:10EC800052570B23336F26AA469BFF910454605BB7 +:10EC9000A4B8F7B2C7D8CBFB686945EFE096F96531 +:10ECA0001B430804C3ABDE8F8B337E7A1DA857F558 +:10ECB000CE8B3F408B6095D2E6794C7FD65594CA77 +:10ECC0005C14050F7F0405986B29BBA4C980FFBEA7 +:10ECD000D1B5385F063D3574A21CA7F57D45B7DC7C +:10ECE0003828B6E37569484BAE87F6868641DDA2C3 +:10ECF000FA23E4BECB1CA2D0A1C913B4D5E7369643 +:10ED000014ACBD0CC3D1704E4169A0A0796584FDDF +:10ED1000F7859191B2F8D4C83A2D7A9670DAC51F6A +:10ED2000C668C961EA5EDE3A8B664059A402B094B7 +:10ED30005C14623133B077F08BEFC1F6F6910F2B94 +:10ED4000F150DB239C1EB24755AD9F4E9570A9959F +:10ED5000E1DC2172BC01B9539249BCD3D9DA7C18E9 +:10ED60001C36D0EF8F34863EAA2E33AAB5982517CD +:10ED700036906E25098640BB28E90F3EC414E1F3A6 +:10ED8000A5707EAC31BB6A9F34F09AB4F1AA6E379D +:10ED9000B5BB78CF30820E77EC9586E58849A5041F +:10EDA0000E28CF83737971895CA3D6B0E01BAD992F +:10EDB0007C683B812CCBC1FAE686056528A6097CD8 +:10EDC000B3CD00E7D44F1B53565E393C41D3E951D4 +:10EDD000F19D01917A6AD79A7BD5E8FD6F345C9CEE +:10EDE000F8854811708A9946FB8346EF0673C7F988 +:10EDF000C92E6DF8E84FF23A7E76DB6883BEC5E037 +:10EE0000CA8329B9526B26D0FFAB3DEE3E170B41AA +:10EE1000837F7072607590266CB5D60F866843DD6F +:10EE200063E398DF96E67BBF9517636BDF63E33E92 +:10EE3000D8580F48952D3FE4DE6284B3734890A400 +:10EE400033B568E83D709F7181BD795BEE5510EB7D +:10EE5000D85C2375754E9FB3A150CDD8AA19E895FB +:10EE6000C0BA7A7C3572011A57666E25464A30E27E +:10EE7000B6F39776216193826027B24E8315D9C885 +:10EE800064CA303E8D4A2C3B48E047866B471BE600 +:10EE9000584F81CCEC40F55957EA131471DA1745F5 +:10EEA000DFBD0B507754B60DE917D0DE9766C26010 +:10EEB000FBD0F03EF9271788684ED1286801ED2F66 +:10EEC000709D150F8E7BBB5CC218D5502D2755AF9A +:10EED00089C2F77E6FB0F5567B4A1ABB8D0B230DA6 +:10EEE000992CFA9FBDFC459B6192C1E56F580CA31C +:10EEF000EF901E57E17E73FE8471CD31A00AE8D9F0 +:10EF000002BA417CD9310AA5E388C04DE39A0B4A85 +:10EF1000855689E4352B492543E35D8D0C1B10D6BE +:10EF2000A763019E55C5D68B27139E5BD4CED572A1 +:10EF3000D14F470C3AB071FE8318DF6F901B303C05 +:10EF400091EB9BC94D76071D26F4865EFEBF2359C3 +:10EF50004250314D94DB03E25FD63E23D2F09E1047 +:10EF6000124ABE4B56B2DD5202033E23A013E5AC5B +:10EF7000EA6B168A3BCFDEB09ADC132ECD3E289783 +:10EF800054DE62A446F77A3FA23A51927EA2C28929 +:10EF9000DA9123FF6A8130A0624EAB9C1F28FF618B +:10EFA0005B8404A1E2EAE6DD5A9B564F3E85C05BD6 +:10EFB000F4873A9CAD6C25DE5574F1DC7A96F60345 +:10EFC000338935F1D708285D16BD7E2656EC7E9F25 +:10EFD0000B3C17886FB7BDAFA8D43536E7D5E0A096 +:10EFE000DC612E8496B3C09C6581814C3173E1D283 +:10EFF0009B7AA3A632CB1E01D1983C9BDD2055ED18 +:10F000009FF3146C2B8508CE74D834625374215648 +:10F0100006992F8514B22502947C55E1A05C2556F3 +:10F0200095C890C0F0257FBE6A91E55DFC433485AC +:10F030009157B95874EF5C0EE5E8CF2A2E45C9C642 +:10F0400080636F51DA9F13B8C69B7DBF321B1CB122 +:10F050007643C80548BA90716F89A23CAC020D6C2A +:10F060000F83E699FB3F54FB5C6BB9330C9DB7A74C +:10F070004C8EA8A63527A7433F88B89515830DFB6E +:10F08000A49073B06F0A9C73C57AAF7F6977AD4A5D +:10F09000636837F8D5DC9D50DD348A1FF3F93BA255 +:10F0A0008A4CFCB11FD63C25A4126435F8E4C07A22 +:10F0B0008DC1E31FDF6C4C05E15C1F4EDB26F2CEF9 +:10F0C0003C7DBB06C72B3FD265D33D3C6470834477 +:10F0D00021476041C2099A5AA9773D4DBF51B326D5 +:10F0E000B8F37CC9074351001FC88433B0CAC2E3D8 +:10F0F00083EF0BFA5652DC719CF0A45D499C060B21 +:10F1000011A28BEE6BF99CC054D506070E7415A5A1 +:10F11000BCFA37DD9F29715FD9A9AD26752011AAE8 +:10F12000C24459B868531C044FFA0F171DBE405112 +:10F130007BCEDB93DCA66466B1EC8A7AF19720BCC7 +:10F14000AD8F01D22FAE6D9002CE863E0F9DA620D0 +:10F15000A7FEA9E71ADA34EE64C3781F5678C8F31D +:10F1600092DA1A047412F09B00069DCB6598E66251 +:10F17000A7EC0CE7D1217A8AA706A1177991B5836C +:10F18000827ECE5FC31F4C35932A726DB48CC35CF4 +:10F1900049C59BF7DC9192D8C38AD6E66DDA113B5C +:10F1A00063B9EC5E1ED50DCFB640A3BB30854E31A2 +:10F1B00004D85FAC9A3133BDF7679B1FDC54C2287B +:10F1C0002321FBD536D51FA94AFF0F1304656275AD +:10F1D0005A017F14B4AB9C067449D5493E131257AB +:10F1E000AC889725FD07288AA7B8575CF5D6106428 +:10F1F0002299798674BD6F27DD762C52467008A55A +:10F20000FE7C2F954004B7C008F53529CC0D504140 +:10F21000C95D182A6F2E9625E45D40DDE86D25DE78 +:10F220007E98CD32EC5D0419C993A432A1BF975FDB +:10F23000D2FDFD20AEA371B6F8655E3D8C437FEC38 +:10F24000CC4DD25ABA03FD312CCEF4548412C8EE00 +:10F2500001F2E4F89761E0A6A2A81B4D8AEF0F2205 +:10F26000F31355688A21E1578D62F7248B2845B145 +:10F2700036D635DA0845D442FAE2348214488C6432 +:10F28000EAF595C835C990491A765D2798F990B383 +:10F2900027D16DF009BA35266DCA9767E151C57E51 +:10F2A0009A414381A385BF698C3B19F15E5DAA6DCC +:10F2B000AAF6E703F15B57707763E5A86D9CFB4006 +:10F2C0003E831EB1BB286B540EBA87B1AAC848173B +:10F2D000283ACEE3701C72EFCDABDFC6BE9F484428 +:10F2E0008E72C74BBB7199DA0134563F0995E757C7 +:10F2F000D787A17618354C99B4C03F0F700CFFAF7B +:10F300000B4E3A732BE711F62C961B10E86072B483 +:10F3100025409B35ED80B75F3AA379071695187B9A +:10F320006814CBC543253013FE0E93F43009E8FB77 +:10F330001260028A4CFF7646193A9DA0FDF244EB1A +:10F34000E4A64BD6A7E8B99476B89064AE5C922058 +:10F350003CE316B6F323ADE107AE2361E1FFE35DC5 +:10F36000C6FC9FBF6F618394B5F8609297C383D446 +:10F370003274C3A1F74CAE5290B7A2FD09669B4A06 +:10F3800004C15A3B86780E5C92222750009DAA52F7 +:10F39000F88EBDD5741F0FD232EBB776C33452BA94 +:10F3A000272089F31E41C0C7A0C99BAC4ECFA7A799 +:10F3B0005B79A8CD7E574EECCD28E7E479E2FEF3E9 +:10F3C00091627D7D87B8BAE1431E5134F8B06FBFBA +:10F3D000F2FA6F5BD0C173CCA6C27D257754B364BB +:10F3E0002D65B46886697C83C9BEF68DF08171761F +:10F3F00060479D9669AC721303007529F02879F473 +:10F400001071475B319D1992BA29765F189280E797 +:10F41000E18B63B85A35910A98E2D6E837B423FBFA +:10F42000258DD180024FC6AA733C9C646A40C237C6 +:10F43000542D294C23DC71E3B06827D246EF1DDF41 +:10F4400036A3EC5A8AB2D939695385FE7564198F8F +:10F45000436E6812101B94C60B3897C85662228CF4 +:10F460007BBDAF45190D222E1A493DF770846227E6 +:10F47000862B92C789D3A621CFFE943BB3308ADA7C +:10F48000CD910C7011BC29C99AC99C7088E3B35303 +:10F49000BB05D3C10F67C523E45F7A72E00748FC60 +:10F4A00000C2613370B701F866637C710B9904097F +:10F4B0003B258B4B32CBB5789BB39C96BDC786F76B +:10F4C00012734F85DE8F4F20AED8C1460481F4A75A +:10F4D00001C2B7C4FFF9D11CDE4755041397FF3AA8 +:10F4E000DFB5851E2F84BAEA49B78649DECD45458A +:10F4F000C61864D84B9BDEBFAFCABCD1B0E6356B33 +:10F500001A5F06D6766D479ED125EDAB491B54F1A7 +:10F5100021B9886643D4D5ED75F46C168AB1D6E06E +:10F52000416543C740456E4A173A13E51DF9A80DDA +:10F53000997C1829875515E001A2D6AA9239F48042 +:10F54000895251D2C4AA1DABB0BCED534C18AC4883 +:10F55000F147B9100CEEC5B42A25F5FD694117DD58 +:10F56000A3EE30290B764B147DE7002BB42E6519E2 +:10F57000877AB6FA96402E5790415D855155D5BF92 +:10F58000FD64BBAD2FF161A47F1DB164B20907B169 +:10F5900012F56E9768B64C80E504CD9953E9217653 +:10F5A000D77780D72AC8EB9927F1E473CDC69B792A +:10F5B00063E0A758FF0D29C2D8533F97264ECAE9EA +:10F5C000DAC3C9BC7B205FCB905C2409DC819C65DD +:10F5D0000C645EE000CE4F18AC720D77AC3586FB44 +:10F5E00049D61242DF80F0DDD56FCE576124A6A147 +:10F5F000E5E3BB82AAF7E648A70194DD444349024C +:10F6000019D322B3B8D0C503DDE1361DB2334D2C7A +:10F61000C39971448BFA48F898489604BFDADA0F18 +:10F62000E309B54AE6E2BDAF473D25EABB7C54C6D7 +:10F63000BD9FA2E2802EED63FE545CF51A94848196 +:10F64000B508596379D6CCEAE239A806D6415CFD03 +:10F65000D5EA96E021BE24003F792DE1A257F3F2CE +:10F66000BD9DC3F42D6E66BB1CABDD6084B83B6FE3 +:10F67000BCAB795A37584B04DBA982D12774534766 +:10F680000365685C96383B2BD253944CEAD8B30799 +:10F690003EAF4E5BEB1990F87D9AF981B2E4FE0E15 +:10F6A0000664791337A892DF26C3A2C349BDC11DE2 +:10F6B00078D2B473AFDD0309CC382DF6994EE5FA54 +:10F6C0004EF21E3DB62A84CB59C568413657487F55 +:10F6D000A9D65414CBB3C2A0D0BDC9949FC1EC37F6 +:10F6E000298B503B9A2048B370545AF899A0759BC7 +:10F6F0003E43EC7D2E980CC6A29D46175BE69DBF4F +:10F70000105A7F0668AAC9D248E46BD8F3BE6B9042 +:10F710006D1ED0C4F09EADA0F4E594A31A0C930620 +:10F7200039D7FDC245202790451CFF02F726DC098A +:10F73000A24409F81068A9BE5ED0051B809D0B2C61 +:10F74000030727BA0F410D4BB0AEEEF5412A9B9748 +:10F75000103E3CB923DC58DF69413AF319FB709045 +:10F76000DC54A766217D80909BB2EC83E5869ED712 +:10F77000AA7C41165252FD94DD2A4DA7BD8B9E47AF +:10F7800055A1998B02D208EB76B7F70A43643B1B6D +:10F790003B2C2382175D8FEA9E81490372253A80B4 +:10F7A000CD5FB6E39A0A39B06F0AB37AE188114C9B +:10F7B000CC42D3E6EB7BD11138C8C136280D64C0EA +:10F7C000BC5542EB6CE737333B30EB33E1FDD405FE +:10F7D000E094551AFE7701DC53337EF144CFF511E6 +:10F7E000A59B7CB766D1D57BE53B19213D2DABF2BE +:10F7F000506869361BF312ED82DCF70465971E9999 +:10F80000B26BAE7BB57E1FD51A614E205BA89DA85A +:10F810006CA930D5A19B829DABB03D045CC217D0D2 +:10F820001259D0BF73CE7C735407C157EC5F57ADEC +:10F830005633438D3FDD9AB9775DC038C9C83A5811 +:10F84000D7BCAC4092949B81881F94FFA8CE7AC805 +:10F8500017298E0E38A7D5068481CF06C6EE381339 +:10F860008AD8890D86A7F6088B741483B7F9A1D3BB +:10F8700076F4216952EE4ECF5CE82E22007ED2FC57 +:10F88000027D04FFAE5A9EF9645AE4A73731877DA2 +:10F890007630F8215697658D7F7017F6BFBB68DF0D +:10F8A0007CAB2376DA3699E4DE5F87BFBB53540D19 +:10F8B000ED844F767195140E218AD44FB2C9B9D513 +:10F8C0000539DF26F74B110450768179F75D506CCE +:10F8D0002FD2E8DB18D08E47202D14871E0CB4EAF7 +:10F8E000005D3CF519EEEAF71A57D2A7324B3F6F8D +:10F8F0006DB0FC9D4CE54BBC1A80893F05B532408C +:10F9000043F2C0EF0859507775047CCF1CC5399A73 +:10F910002974D2BEF77BDF57BF68352B8CFE16B13A +:10F920007B06F6A3F406A41C555E54DE694D3D8E9D +:10F93000364509C62CCEB1BA00A4B283E14D742E6F +:10F940009F31E7E69929D0106A1878CCB94E4E1746 +:10F950006001DE6813B1BF67CD8144D5CF3F35422A +:10F9600038FD3D260BF6CACC480CD6F181D1A18ECC +:10F970001579086C863C1C4B33ADF77858B0CC53E6 +:10F98000BACEF27F4D5AB481178E9C1B3373607AC6 +:10F99000D94B42290B2550109338C8415DB4C2C2DF +:10F9A0005BC1D14ABD7CFAC6E3D3A011859215078D +:10F9B000C30966443C0098A7F9EAD5F1D0E41C1FBE +:10F9C0000FF6BCE1791CDF24C715E16733BF56226F +:10F9D000307FBAF7C6F208BB7593853B9946F7F9B5 +:10F9E000704114497665DA55411F15882BE0F151B5 +:10F9F000FCDE7C9AFDE80E35B8EF9359CF57670BC4 +:10FA000022D8214D886268F572903F33DE4A8DC658 +:10FA1000257A501A26220ABF93644818096858BBF1 +:10FA20007E8CD5881564355DDDCD5FDCD85A6B8C56 +:10FA3000DC1AB311D6D9DE289AC9F05DDD9D48D312 +:10FA4000C13DCCDE23D5094E27CD5C2D68672AE762 +:10FA50008F11CDD126DA234A7FA20502E2BE97603C +:10FA6000DC66244BAC8FB5139EB5EA8203F2A97213 +:10FA7000C2C0091F67D036947680CC19A66E477332 +:10FA80005DEBBAA8027E1BD82ADC347FCE02E7E306 +:10FA90001D1F05BF06C6344A0E4E6815EC43B7E17C +:10FAA0008F3DE6E82A4CAD4E1359F60B0390362FE6 +:10FAB0002BD88A50BC977FDB81BB4D97088C0EEA10 +:10FAC000FF9DC8ED54F2FEF6C518B0BE341D50F6C9 +:10FAD0006C4E2F5744E332726ECBB8F7F207B21870 +:10FAE000DAD60E3DFF6DC9EC3D0987621DEAF808C4 +:10FAF0000E90267CAD2CCC793B62A471191B9860CA +:10FB0000EF8081C956B6C0E1CA68E1C9992E64EE9A +:10FB1000ECEC65B22D810FA0820B3A158EAEC0B50C +:10FB20002C92D581DE52C37A46712778C7F4461CE1 +:10FB30002F41BC9639B53F45E53CDC8E1C09B3D45A +:10FB400013431AE10193D3B9BBC169DDE9DF3BFA85 +:10FB5000031CD7C3946422BE532377DC55796D9C74 +:10FB600055B42AE133C9164D73249ADCD9F61B4DDE +:10FB70007601A1473FC5FBCB6CB1D662946A9CC7A6 +:10FB80005A2A079AB102CF0EA1844EAA2FAF29A2FA +:10FB9000C71C2B33801FE1FE9D6884051950364A2F +:10FBA000FC1C1F29393573324A574CE2A5AE7096BA +:10FBB000BCC902691149FD7C9017BFC8C7F9C6B816 +:10FBC0004EF9DFB4712B9B7F7D40AC50F2D00CC05E +:10FBD000E4D51B3DE5D72879BD25ABEA50AB729E35 +:10FBE000F5E54D26C78FE71A05E51FA02679CECB90 +:10FBF000BE88542D2C6775B73003B40BAF05402C6D +:10FC00008A027874B8EF8C1B4EB3C6126C180B9B2B +:10FC1000871E0CDCC252088D498519050224EC2090 +:10FC2000D9BDE878E65DA9F424A2F9E9FC6B37BFF9 +:10FC3000A4AEB9B936D103CAB9B4074608BD7E3FF0 +:10FC4000E16985CD8E0D56E9894341D3C48C33AB30 +:10FC50008AFE02CF556E603F4AC270B52918C7763A +:10FC600080BFD27806C26F4C98010549D3F2918EBD +:10FC7000EE0B65543C39033FAA7246C3D16E3C0477 +:10FC80001619828A5024C1AB0BABA4F001682D5C1D +:10FC9000B176F6E90F3ACD5783E8EE3A0D1B045DD5 +:10FCA0001D0541746FFF0A6F5F38C45B54471C34F5 +:10FCB0007F7472043784E8B8356465BB719C79E25F +:10FCC00091083FFA5F9C252D784EC190595350F012 +:10FCD0001D74B23F97C8FFF7AE447D92505C6D191A +:10FCE000363398B09CCD7E8063A1AFB99FE74E06B6 +:10FCF0009E3B1D90897423A82989B696298BEA2EEC +:10FD000079C68FAA7EB578182265CBD2907BD505AF +:10FD1000FF8D542B22051107F54008BA438695D272 +:10FD2000519FEF3ABC72920F4E94AA58777540706B +:10FD300072E0BC3880C0AAAC81444CA55A600F1C4C +:10FD400039FB07F9B7BD7770F7C352CEF5F6A2F0CD +:10FD5000E16E91BFC77111062D5CC4DC2975D98095 +:10FD6000BEA7CBCF5BFC212EE1D7E9E94A5666342A +:10FD700053F105D5A44D695B3AB709ED65A548096E +:10FD80001E73A2443DA91FB39E63A660E1623CB40A +:10FD9000A178729BD96023A4177852CBC62EC4A039 +:10FDA000D944B73FFF1B08E166DB29BB8482356578 +:10FDB000B96D33DCC0EEDC32E7BB2B0EB7D11C8053 +:10FDC000FF6ED6DCA77EC8BBE717E0D075A56A1624 +:10FDD0009BC57CF22102FB9009BDF5948C77DC7504 +:10FDE000496234F21E634E282F115A25640292890B +:10FDF0008EE29EAB8AE1F1F27A363B5340565B309D +:10FE0000025E25790218D12CA29980DCF781AF60BF +:10FE1000422BFE8744DF1882066A750352231F694E +:10FE2000A116086C113F9D8B6C890432501114A6E9 +:10FE30006299270150149EC450283645EE2051C2C5 +:10FE40005F1B39E238AE25E7693AB8BAD36CDEC435 +:10FE50000D07334B85CDA10668BD81501721D3F422 +:10FE6000404C8A65AEF5EED59274B2984368C86B83 +:10FE7000562CFBB4F8EB9E2DC8EFD7902555C3E167 +:10FE800024223F1548E02D71CEE0BB5FF22B5B884A +:10FE900018C88DC67474A963C583814B1F52AA808C +:10FEA0003C42C716630E8C0D1FE67AED1FEFEFAADA +:10FEB00014181EDA01A000028ADB50AC557A7CA728 +:10FEC000334733FF890CCAFC73B363B59E9FFBE5D0 +:10FED000DA2C3DEED54FB0CDA9F1A87CC4C9F765A9 +:10FEE0005F596B732DEBD06C13670FF1DEA2D2421A +:10FEF00088FA3EEE88DC52E00247C5E83FF58F17EE +:10FF000034AEC2BDB481B05638697376BA183F8634 +:10FF1000F7EB927F66A25D6C92FADA99A9735D3075 +:10FF200067AF2D9D499ADA17DEFCA63F3E11782374 +:10FF30004BC9CDB53AE40D3E5D9C70A1B07401296A +:10FF4000F0616908E76F59E8F985BD85A18104D2A0 +:10FF500056AF44495AD5A46682A1EE94E5316F3E6E +:10FF6000376041FE62049EEBAAE31864D23D7746F7 +:10FF700030B9984F754069997297A9FDB79C13C91C +:10FF8000C4635D11E1DA8D9E3363C460A53DE53441 +:10FF9000207B4B3C7AFACC0E25015960F4671ED0C9 +:10FFA00029F83DA27A36E1F14E11EF8D18507120FB +:10FFB00044448F2B2ACA7E8142F1600355AB1F4C0B +:10FFC000ECB1763476B0618627023B52600CFCDBE4 +:10FFD000E8E83BF7829ADC33902F2943294A87F4DB +:10FFE000D6F307DE605EA3849B12E307C647BAA67A +:10FFF000B4BC98771D8F7BDE3E55F73945CC48CF92 +:020000021000EC +:1000000034B5771A1961F9220D63073F7D93F54ED8 +:100010001D8F9A682D015A1C375E6B7810B67D0BC8 +:10002000459AD929374E130BB008BFEDB64CF67779 +:10003000C1FA7F0D79F1C6A79D1CB95183B2F40AAC +:10004000AAC6FEAB12FB928C346DF0A4C2CE9162B4 +:100050002AE77BA3F4CE3EB3D90310B0786FEA252C +:10006000EFB38D24EAD7C664CA9AD72BAF1010C15C +:10007000842DD2DB9C5126C64A019ABCD3FE7E3227 +:10008000CF5123EEB09FB893EE1DED6C0FBB3CE358 +:10009000C6ABE2BDAFC74D9FA4DDBB4C482389E78B +:1000A000B9B116E85B194030ABB5A87BB7D77888F3 +:1000B000D850721A77FA8228DCE741119CCEC3C46B +:1000C0002477C7E35540FECDC37B1DAD42EE29B07A +:1000D00001A55616835A5146C1A3D845476C5E7494 +:1000E000EAAEF2F0F4834991A5A4B2212B889C7466 +:1000F00097DC02BC106A82A585A142E03A2CE6EFAB +:100100007F378A1B397167D8F43D693BF2E4389F29 +:10011000BC640F73A50E8457B04F9CAAEF05E04A4C +:10012000562BD65AD5E0E529E8EBA473C62A6EF023 +:10013000F78197932D1C326C2893EBFF1EB25DC1A3 +:100140009EDF7B74967F4DAEBF072F11B1299BC6F2 +:100150005975A1199B2897D35095467C8D6221FF34 +:1001600019D92A3216C8BA30BAC72E23012F42CE67 +:10017000E1806CC038CF4264341FC93060E3355B26 +:10018000BA111C67CBF98935EA1DEED7F2C8CCED60 +:10019000B463D5E8BD6238075F0299A4A8B8230FFD +:1001A0000864A659D2CE038240D6FBC976004D79A9 +:1001B00063B5DEB251067C3F82B426F06564F54E2D +:1001C0008FA079A3F7BFF685E469D0A857165BA284 +:1001D0000BFFA250AF17C7FC8A7E625977F270B648 +:1001E0006144A3BEAA611F7F3B4A424F842D180B76 +:1001F000D450F9BB5CA6DF072AC78D9E3E8FE95617 +:100200002FA112C49B2CD55F56CEC78AD021BF2008 +:10021000C71BDCEEF28673CB2452AF45A255385F84 +:100220005BFFD0E46B1DA3C8D8D041772B5B1AD6F7 +:10023000A04D24F15F5C56DF2A96E09D78BC84AE29 +:1002400005655F191E2D9679D71F07DD720E31B037 +:100250008AC96E1CF1FD7ABCBBE4970532B832A2A4 +:10026000B12FAD0A5F314F2952750395DC9EDB5EDD +:1002700097FD2D45ED804E568FB8D0017C56F2A4E7 +:1002800075831B26938BFF45C0B60C956BC954072D +:10029000BAE263C68BF03E9C8C8F5BC8B269B1CE6C +:1002A000744357A7246FC0B877251F0E72F6988540 +:1002B00042B69FA61F79EBBEC464FA7BE19D7A1219 +:1002C000E72DBFF23DA84015C42821AF2AFD54C92F +:1002D0000D9F2B933DF881419B0232D22B89BFFEAB +:1002E0000DBDF77955BE510CF1F820B703D695B581 +:1002F00084698680AAB792C9044FA2C68F55F114AB +:10030000CA90055C2E07DF02C28D3624AD32F2EEB4 +:10031000303698CE8E3C6123E865A7A40758AA889A +:100320005FCB4D3D7B4E1ABCA387EE0FD9DC4ED878 +:10033000EFA9404EFDDF06B86B692D1E419852387B +:100340004A5A37813C4D652581E6CCEA869D8976FF +:10035000F2F16F8886CB07F1295E2BD9EBD9F6F441 +:100360000A9B3028F5367D6780FE508BC652B51F3C +:100370002D345E762E2F7F8C07EFCAACD80A9E4BA9 +:10038000661D08E6691CD3008A5D62FAE913129AB9 +:10039000131A22AF148E989CD3915B1E64AF203148 +:1003A00068697A7B201CD5C695E714A616E98D846A +:1003B0007C188FBB4FB0E5396529E0C22249DEDDEC +:1003C000D76787E327726859595652567B7A1A5174 +:1003D0001BD1BD2EAFF935643306FD9D91AFF7FCFF +:1003E000F9329E62CE9FC48470734FBA448059EC38 +:1003F00031446250EC02E1F8E6B7F2EB4D56032BC4 +:100400008F79E7BD14BFEBB258D74DD674342F0E99 +:100410004AE4340ADB46A6A030AC9351E5E5216FEF +:100420000314F5381F0F91280BBCFE1F21380FC194 +:10043000419A6CD496C9417A92A05B51C592A7CEDD +:100440007DFCB7EAC4CDCECB4A7BFB50785106C5C4 +:10045000BC61126B36CF797E2DCF61056CEB0863E2 +:1004600031FDDE54E8789F69489ADAAA124568C3DC +:100470009ECC6D726AAF30B181AF400830AF9471DD +:10048000FC096150BE1B7AB2D569EBA4B2AB840AF9 +:100490000C6C81D6F5E639041746E5A28EF0C90941 +:1004A000E10B4B835443398D19FED8910C8444449D +:1004B0000C5F40C1BF6FFF56D1D632DCCB6A4522FC +:1004C0009950776666F9A2FE166CE985DEFF0A513F +:1004D000F4AF937FA9F7623E0D69B044ADA121D579 +:1004E000A8D4CD61AE62E12F1709E5BA780D208856 +:1004F000E53D7889EB2ACD3BEE090C72E9C4DD14A9 +:100500003FC20EBC0AFEA22A0127C2B110E4658BCD +:10051000638167007207CB5CA0EB7596B606B5CD1C +:1005200017075CE09D759B0970A9E39D9E76F9D243 +:100530006E8E70EEC2BBB4B513B7BED0C86F4A4A58 +:10054000E272374C62357116174BE301E601122B4C +:100550009342CD38738432962F030EBC8F54D2A6AB +:10056000D6BB63A2DB6FEBA506CEBE3BE6EA4570C9 +:10057000FDF31D2DF119073D2128D92280D7AF4168 +:1005800034E9ED1A1E849278990D0C054EB3C157CB +:100590009C292D9EE649930E55A7E907E6B7425ED2 +:1005A000867C0341705500F27BCC7E275A3EFEBC10 +:1005B00021F5A8864405953B3DBE7A6A9FAEFF6251 +:1005C000305779075D18E4A99CDD7E0CFB2DF4966D +:1005D0008F4B7055E3EE57143FB71DE6277253C794 +:1005E000193A872E1D985D58B55B252F5D26B69666 +:1005F0002593D8E7DC5FF3164932D3A652B81266CA +:10060000064DDF538F348844E9C42593C6634CB24A +:10061000C660C417EE972194CA65F89C890B1B2C01 +:10062000DE4DA96820E79BC7F72FBC2EADBA84909A +:100630008A1CFB7A6289A347EAF9972F8BBBCE38D5 +:100640007E60725C521C0276E7C4C6F6284CA1ACF0 +:100650007BD8006C210FD5D6BD3556D13765046DDA +:10066000319289BFBA6EF3915F5E2621D78ED5276E +:1006700045C020E3DCF4D4F5EE9C1D7AE51418D4D3 +:100680004B0C011CA08B8E730CE514F25B83F9FDFF +:1006900081D0E9F1C26E502028BD684D94BC75260A +:1006A00053E14EAF99F9C0895BB0183F50D07288C2 +:1006B0002AFB47F9B9896DC88CEC0F8EC6616003BF +:1006C00066BEE0A364B5E30C2E3CBAE2C06985D6F1 +:1006D0008DE960E312911F935447D420C9EAAEAC70 +:1006E0008F1CC00EAA2763ACBCD38D2CBB42D6E9AD +:1006F00044EE2C03A107352952DF2241A50CC1A8E5 +:100700002AFDB16704BE9E04A0DFE15F5E44B80A23 +:1007100080B298E7FC0DA34BFE302E41BA222C414B +:10072000ED4B4929D4AC6CA20368DC96D698832B98 +:10073000EABEAAE3BB40E19DD06CA2196EB666F199 +:100740004E3370E495B254AB35BA45B64F110B7EBB +:1007500014C7032907BDDB373D225CB810F11956D9 +:100760009A60F3F94A1F33C02CA38ACCA4CBE6AB22 +:10077000D3FE2044D32E3D86CCA7ED1D9F26A59009 +:10078000AFF378DB591BAC3F7CA32BFCFCF3C73FDA +:1007900046750A1685225F184AA0C5E538AB33D3E3 +:1007A000C95D566EEC0DE2875BB5F1B9E2ACDD20B8 +:1007B000D41526C0CE015D996F849CD085C7DAB070 +:1007C000DBD7EA3F854986B7DB364C239F15AC540F +:1007D000A7DC9C7942B2218DD90A07CA71DA4E3D55 +:1007E00053AF9A6E8A281813F7D591466AD9BCF090 +:1007F0007C8C6DB54A567619069ABBB8088B540F97 +:1008000069A3F0D424150BDBCEEA17B88A0BECC130 +:100810004F4E53636550D73ABAD4EFC72974791055 +:10082000C76491474FABE4E2EF5520F33789D873A3 +:100830003C5051DE892F41DCC4D9B675CBAE527223 +:10084000FA0D3D1FC6A13104EBBF750284B159F406 +:10085000D982864F90E6283700C80D3B20FEA0398C +:10086000B9C13B16F77A31904C45B347E44FD043BA +:1008700022EE4304DDD0CC11B4551FCD388271F087 +:10088000112609249937E239D9B2092A22608486CF +:100890006202FEAECB215347253A6B32D1CF850E93 +:1008A0003FF009560BFA3FD0A537AA19725632E825 +:1008B0004D8D471BA1C23352413055206814EE2F95 +:1008C000F92A6FDEEBE55D425B73E2FDBC932DA57B +:1008D0007908D12D0CB377A86F6185700C0CDAC440 +:1008E000CD3AA3CE35A54229F19F012252B6180771 +:1008F000EC7BCCD66B611617AEE3227CC14014C3EF +:10090000F297FB427D852EA7DF15A0D3256A01A7AC +:100910007BCDE15AA42BCAAA1E59CC344E8A8B9D9A +:10092000855E1AB8ED66C1ECD4D9AD2999FAE60B0B +:1009300043936BF1D78A38ACEBF7F514AD29010678 +:10094000D08C69865E0BF055E51271F27067AEAA25 +:1009500079107BD3B631A7AB13CE010F2725DD3B32 +:10096000527150FA058EB7AD698712C6A543B663BA +:1009700099011291CE9A1928787E82B05F4AE4A339 +:10098000FC151EAF8648F78CFAD36C00844A123BE4 +:1009900097AEEF04BDEE1FD4D46D4776CCD51EE4E0 +:1009A000604E82760D857C39FA56CC35D346379C1D +:1009B000709C82C33C8EF7119BDD20934711B0855C +:1009C00077D97E167897D96776854D38DDFD4F98B3 +:1009D0004C5600F80DCB63B402F638469791CDE83B +:1009E000A48A0F871C7BFD31EC4AADC07FD406C7BB +:1009F000C2FA44F6528A9E676D512664E212575736 +:100A00004E7B9C70DEDF047BB0075AEA27FE1BF7A3 +:100A100023D8E8A3AC9B0276108FCB7BAC00BF83BE +:100A20007CA523C9709050F5E298D81A0333360498 +:100A30004AB58CDD9F08E79248CFBB0B608785C322 +:100A400069B04A90A359E4FFCDADC2977D662CC131 +:100A5000B579B474D4E55358DB702D7B9A853F2B60 +:100A600038D0F76279E59FE8E7B07BB3AE5078EA1B +:100A7000C9E0567056C309C82FD3865C531DD25F98 +:100A800081946BF6A13B841BFA808AB35F1AD93636 +:100A900051A512D7BC131074C5C0C79E7F69D80575 +:100AA00024CF060BE0C65CF993BF420604E529A4F7 +:100AB000A0BE21830DBD56451C5C84BB136E72FF26 +:100AC000AEDDE42136B748B99CC7833465D5BF890C +:100AD000A6451B5988704DA0061637E23C496D1E8D +:100AE000094FC9AFF63BB00F0755F8094C5750E313 +:100AF00070C1EF584F5C8C70744EBE642C4686906B +:100B0000B16078B05AD1186F2734E566D3DD3B2742 +:100B1000414DCA83423F84D638FB1D4ACAD43A2F7E +:100B2000C25350F1D87646EFD2DB3C8AF49768AED8 +:100B30009254A9218986E9983F1F165A5967633E46 +:100B400093C4762FE9083491F43A93A58B3D05D1EF +:100B5000AB00C7C1CA23444D0DEDD62071C2B5907C +:100B60006D6D421AAE82EC35D89F1B4B81F3614903 +:100B7000DC11A75EDA19CE18DC4630BEAFAA1B8F97 +:100B8000D105BF32345B2552305753668AD7136B79 +:100B9000651196113063C57B9CFF1894CE8ED97574 +:100BA000A80BFB6849F2A36EDC6535C4ED1215FF96 +:100BB000A8A031BF5FD71E16A9C038BB688F020B33 +:100BC00030B933E4D6868242E9530BA49A2A9D04B5 +:100BD00077E10C6D8550C43EEE147280EDEB1FE79B +:100BE000D66C98C0A52F4F666B5318F73886B36D37 +:100BF0000EDB306EAF3AE36B4E53E2EE952F78F991 +:100C0000BFA286B51AAB6512976C646BF9A332D993 +:100C1000C3E6DB3D5B641266D6A9271EC478B6998D +:100C200048AFB6856689FEED0AE7571EC606A1776E +:100C300021315351CC935D998EAC4A50AF862D0033 +:100C4000DFE54318FC3EB9ACF4B8757EA679CC73E9 +:100C5000FC89C301B6F1E34EE61B11A476F7C099F7 +:100C60009143373DB4EE1DF8AFDB9641421C602A3C +:100C70002266E248A0FCF10F00AA8F068F2AB8B2C4 +:100C8000C7E82AD6C8D097FFF1A03E0545A51FDECC +:100C90007EC5CEFC9D98032E600254E9BC5EB8F57B +:100CA000AC4DE24FAD1BA685E05BDD5F8A2D018F69 +:100CB000983A8BF6BC74E99CEFFB6B549DC10148DC +:100CC0004206698A15C5319E8211A61F8AA5B89170 +:100CD000239102F72659B88598138D53554415F47E +:100CE0004038B3EC0B11A83390C7B602CF3CBDF22D +:100CF0000736F2222058FB7E39A1FB32AECF989AFC +:100D0000AD8401964BE62C30401AC72E07363AAB1D +:100D100077E8981D944956DAAEF96792B5C38D61AC +:100D2000BD01856EF0BE42A8B5166B80CE7CE8771B +:100D3000CA54094B7874335948DB6EB150958B4EC9 +:100D400022C9237734868F3D1352B6F205A0EC7585 +:100D500093855D8E1A0D4561CDCA4F03EFBA1043DE +:100D600037F7EC78EBFB54AB4BB809FC911EE6056A +:100D7000063790065775416EF901C0A0D8C407C068 +:100D80006009C8E330B9E8F01FA45750F952A635FE +:100D90002E77104FA4AE75C5EAA945260A1C2B7400 +:100DA000055471438C51C4595C05C486F1356E936A +:100DB0004C977DEF9BD51B8AEA5886889EAF3016EC +:100DC000ACFED03BED8BB570023AAB192B145967D2 +:100DD000876D7ACAD907404D02D2BA7DD02148F436 +:100DE0009AC9E61CD5B047D5AAD3D4B764AA8EBF9A +:100DF000D876484504CA4F52F49B424F933BB7A262 +:100E000091327250122C89B72462808BD448600DC5 +:100E10008A38C3698B1E9A89198AF8973B8830F6FD +:100E20007B4C5FCA52648112206B26B6B909020D51 +:100E3000CFBC8BA6AEFA5D7705D40C54D8FCC28E1D +:100E4000E70B957F894B83305C5421EF016A59523F +:100E5000D2F9EF07B57AACA57E5263F066534563CD +:100E60005CEA514CA15E8AF443F844A24BAA310AD1 +:100E70004E6C8D7824C3B1DD7980AB4A00B591CB3F +:100E80000145B2FD4662C9351F3DCDA800F544F5C8 +:100E9000D12539D8B4236AC314AAE5F4FDCA58DDB4 +:100EA000983E764328BCE3477762143F711F215C6C +:100EB0004B02A83C6D40562EF1358BD04963CC6572 +:100EC000FC829021205C8A76F41B18C3F62095C41E +:100ED0000BFB88595B9CDF94898A213951BAEA1946 +:100EE00092AE9406B0E5D067F81DD8424E2AA8808D +:100EF000DD6A0A0C31DD711216FFA15BC21CDC6ACF +:100F00005CA61FD5C39FAA75222254C084D9C44FA2 +:100F1000ADE3CD2260ED102641F6866FEE88878B1B +:100F2000B2F1194BE83B585CB4737A3C88AEED34AF +:100F3000A55A88886F13336FAB256DA77F73E2477F +:100F40002E36E0D4ECB2915FB736EE80E5DFE0F507 +:100F5000001F1F16D964B3471591DA342F7C21A4E2 +:100F6000CA488B16D97C38B3503D2AAAEDC1B34785 +:100F7000E80B989BA516B4D1AACC5D340CAE90B901 +:100F80001F300C7C9D48978E7ACE0606155F2896FA +:100F9000FC0CF218D2D990D190786BCE83E332A0BA +:100FA0004B1FB931BEAF978B1A73B5A5FBA2F39255 +:100FB000ACC89C4BCAA8818740CB70A12B34EE00F3 +:100FC000B90ADF3B3DFE7B149F09966F05F8D3C637 +:100FD000D698A071064C9BF92C89D501386CCFD2DC +:100FE000F9C63C3297D6B8181D491CCBE0276A27B2 +:100FF000E4F16615693D74AC27EB13E0DBECC09AB5 +:10100000DA8294CF383FD614B08BEA026A88DAECE1 +:10101000ABD8C1E6AB47E28ECB3ECEA99E1C8ABBC5 +:10102000087C373D0C255EA312CC3F6683A1BBFD37 +:1010300083B4D690F94D25800877271D2FE1B5FCA4 +:10104000BBA61A9B1C79B124F7D9F5543E176EF54F +:101050002532F1D6C92F26B9A5B1BB1356DF1CC85E +:1010600008A0BFA2EEDF636C3B6EEC6FFC1583A1A2 +:101070008485BA0286048FE4528C70DC6813978BE7 +:10108000ED998317D8E3BE4043C8B7391BF7A3AA2D +:101090001CFF804C66D2C464E9806162E2B2A6E3C0 +:1010A0007340A5E776C523E739820CEA3B6A707E78 +:1010B000D42BC110F70A7BDA1E489EF22767431231 +:1010C000FAB7208E54D2834CAACD6828DC0C96E166 +:1010D00048664DD804C9CC15D8D825CFD30BEB24FE +:1010E000C6548F2BAF7A788A1FE076BBB1973B0F3F +:1010F000BB4C1209B605903712B5157D12F46D4040 +:10110000E1822A6D2E783AD53E3F026507EE3049DE +:10111000372C8BB3C16B01AFE64F276E0260068B95 +:101120008B327BD8E187E8FB07DE688ECD47A4F4DD +:101130007E40A15B2F241E4D780F6CE5749D1FFC33 +:10114000B1ECA914673515A9FBB712B0C702A139D4 +:10115000444547C3B751EAAF927C5AFED561275345 +:10116000794EEA3D88807466857359DCE2D67CC18D +:10117000D35E570E58673A932109C13B4BBD856733 +:101180005B4221AAA55D7203A62901209E0BF30BE9 +:101190007BF06ED81028B2AE9D7F767449F5B4C648 +:1011A000BDF5D5B7414BF6155E283181F3217B2281 +:1011B00061DB2D4E46F4D89903576DA0F0BB900E1D +:1011C000E0C3D898840B2A347245FD781A67D3F8A7 +:1011D00030FC66BC9472D6EA2F5F6E439F9424EA7B +:1011E00055ED176844C791A53C4AEDF29FBC9F841A +:1011F000A1C93998DE4A03FDADAC6BD0B7E1DDC7BC +:10120000DC35F82BFEA48CA6ECDFDF74A5B5D6D0B8 +:101210006C8A76EC66F6FBAB0A5AB1E7DCE49D2FEC +:10122000AD7F16FF9D69E5192CA6F97F415646DF73 +:101230002E6883470650D490256B2B64ED50B5F78C +:10124000C5154755F2B987E945974BA60CC2E3513E +:10125000F3C9363489C38CC4C0C61FC341975292A8 +:10126000C0C28B553C5CA39C865243BCEB54A2A2EB +:10127000D12F2CC5119BA819D17F2EEC516FC49F83 +:10128000C67557FAECB375C1C334064372FE3A72A1 +:10129000261ACF960525D9FACF848010126ADCFF72 +:1012A000E385A091B61919F8B3366821702DEDD0F9 +:1012B000A684CC7B295F780C20B494DF298E2C6225 +:1012C0009BDBCB8F7E9966608B5F0FA3AF8D6DC567 +:1012D0001BF98CA0ADF9DC93322C2F9DD72BD9FCB8 +:1012E000911681380F225CA6FD574FFA7A138E3E75 +:1012F000A086F9716D1AAC000C87635E634755D800 +:101300009E65F300A06AF729FC120422F6915BCDDA +:101310008D5745D133F72E602140D23B3C5E111AE8 +:10132000443E0D0EB4913084F16851D94171BE9D97 +:101330006DD289F5D771D15D855008ED8FF2F7DD5B +:101340005942F6A6BCF5E1F09B2CCF71C164DCD606 +:10135000B2EFB52BDD55C41AF4A59F88BB35F4B3A5 +:101360008AB34F4FEF5FE7C242F365FC8307E6198C +:101370008FF632D0BBCA7E0F9B0594778F305A9080 +:1013800037D142FE1D8713263A183E84967709EE20 +:10139000E9DA699D93CC8FE4972760950A4310683A +:1013A00040938F22AE7713BCBC5DF330B5BEFA2FED +:1013B000B0502A70B92D6BB63C39DAD0147E52CFBA +:1013C000AD5E3543D57B94C67207A36992BA089384 +:1013D00019D895F4C0CEF684C56EFD76F83A23EDA3 +:1013E000D41A6321239F9D1626BD8AD929259ABD2B +:1013F00058F897FC32062F5AAD1C45D8FE1630C05F +:10140000BEB6D00F7468476E9676DB9D1D5939DCE9 +:10141000C10ABD732E8921D1961F22DF409D5979C3 +:10142000FED18D35E7AF44E6B5D5FD5E22D243FA55 +:101430004A4539776964FC009F61732FB4A48180A9 +:10144000A20EB6C23A1700A1FA27F9CD301F7A06CC +:10145000D241FC3B77477A8102FABDEB74431F8D82 +:1014600076318FA41BA10D68CFA42FE39D4BD35DD4 +:1014700040C98C687C90AC4E67D743E76773E694AD +:101480003DA2BD019D1493D755C9415D5074BDC2A5 +:10149000A5D13E6CD075D69DAE1641E9F11CA3AE28 +:1014A000AE32EB907436CC153AD0EE7EFB341F5939 +:1014B0002288F1B6BC4CFE585C18DF367CDED85270 +:1014C000E5D7BA0A27BC6C9FEF92D385E255859F7A +:1014D00093304821A65BE7961409B3240C10CB4A3D +:1014E0000A9C652675C7A49A686E37DC8A7175AC4C +:1014F000A7CE7059353EBD28693EE829252AE5F575 +:101500002A84F7BB90F9409F1CBFF41A9DCB57D596 +:10151000C80606D93D4D9D040E4BD726A1EF801F6E +:101520009321AD7CE18FEBDC8F7F459114DAE73DB1 +:1015300040A1E230AE0CEFA8F8772E1BC2770ABFAD +:101540002CC8582727DDE2E15390C9AED82C15549A +:10155000718ED417AC1248C165B4F76B2A4B9479DD +:101560001477EFCABF3CC2A92AC538AD559C1EBE30 +:1015700021FD63B91D224A68D5E07C3EEA3F07F7AA +:101580000E055B6CD1A1C6857A0AF15032E9D5A36C +:1015900090708B7A2604AD648074D7D0698BCBD4DD +:1015A00014864757C46F77196DE0F4D994E313227A +:1015B0006C55815AC1F0E65029BC33FF677F4670F5 +:1015C00004FEAB78EB7475E76BAB4FD142A883395F +:1015D0009FBD7452DC292EC2D036E8FCB240D24600 +:1015E00055B10949D118604F0D1B7A56498612BC76 +:1015F0005F52219B651202F007CDB9DDAE54054C58 +:101600008E92E57A3D10D2D6F3C49FAD4E6B9BB758 +:10161000174A7C65DDF004C3E4F9CB8FBF8C0B6700 +:101620007E8AE447CBA292F3EB8E99CEE637110285 +:10163000D406B32CE2FFB1A5374E38910C6A74770B +:10164000E5FD7590907B8510741CD7F6A13B509EEC +:1016500098B6D29C188498B5AB014A94BA5D862797 +:1016600053FD11A5C72741D6E2FEF83EFF8D2205A6 +:10167000FA0225C5DF59B11B3481658AD91CAEA594 +:10168000FBD506088A6584B8EDEF49DAEB171E9999 +:1016900059FF05CA4434C4A6FCAF349FDDAF2DBC4E +:1016A00034ABA7EB06732A4AF00D50F3767C03FBAC +:1016B000B8AEFAF6FDE5783208BB23533277D81975 +:1016C000B15BB63CF3539EF4E9440EE4FC4361DDA8 +:1016D0002A89046E905C5C228F36B89E6BC2E0B99A +:1016E000C555338006F85EE1EB47E2A0CC57DAB08F +:1016F000075946CD21194EDCC541A57F0A38980B04 +:10170000DE291624C25C61DA880DE7C34BCCEA45BA +:1017100053E8D5B7940D2B086E873B1414A9EAFA49 +:101720005DFA25B7AC1B7B93B60062BF42E8137627 +:10173000D580E3BC60ECED7C6DA7AD3C6ED3E511CC +:10174000AAAC374A6AB959797B9141A20FE404BD2A +:10175000572E38534B952A487DCD0B160322B3D60E +:10176000BD5B0E1CA6BBAB7407D6DB068594D447C5 +:10177000399D6ED70BC5BC91BC216EE9FD331EF5BA +:10178000E7D2C4B69FF30B19B01546AF70AE0F7415 +:101790002BDEFD79924CC96367A0F51C140157B785 +:1017A00080AA7BB1B2961473A06185436214BF1AFC +:1017B000B30DA04A1A6D2DC507578887F001076041 +:1017C00045D96095823FBA3DE880849FE010B2E041 +:1017D0003B16AE9F7440382A3D5DB40B0FC893FC96 +:1017E000648C9BDB4A26D96EDC29899FA3B07AE7FB +:1017F000CA07346A0D173CC5A782009A7DC9E9580B +:10180000D7C40C72AEA002244D3C46F3D98E121000 +:10181000742055AE0B87B98FACFF46AA7DC977F708 +:10182000E0589A996458E0B6AF242185E57FC9BE97 +:101830000790DFE02B8CFD884A2D6910B798574838 +:10184000BC4FEE195D9A6924D41C7406D28CDFF368 +:10185000A7F2B0E0674C283F4929B1D44A6A125C2C +:10186000C82BB85EE010C92043AB8C7EB1087A402B +:10187000FAC3DC3E887E694D101049F0336706CA12 +:10188000AA00AEB659443F49BDFEFD030580B6B07F +:10189000B4D592BC7C9FE2E89D3680EC513B8C77BE +:1018A000420C58A0B1B9ACA9A2B1C1488E8B9D6DB4 +:1018B000EC10BE79DDB2A7A5FD520F6868D809000B +:1018C000AEB2ED79ED81D922F019E81FA6CABDCBE1 +:1018D000B9EA7CCAD4FA4EA8471769390074C6ED34 +:1018E0005C9C6B82C35EB1FFE868B9B8F1197D8773 +:1018F00013BBA17659907A9A0A47689ED5DAD4909C +:1019000087586A504141970B386D8B8C107852F292 +:10191000C495421C4D18319C60FE64E90042CD25FF +:101920008A7E4A302676E28750F180B4DEB9E91E1D +:101930008511E41A91C2C1B6520162A6A653938CD6 +:10194000CBE9313343FACC31CE376E6C89E454CED7 +:10195000393CB6E5B8294A27BDB7A46045EFB603C0 +:1019600054ADC814CD5AD9103CDFFADEEB68DF0560 +:10197000502F02734BF7BB9351B43CA4398F862F81 +:10198000E525156D2C60B0FE83C5B775AAE92A62FE +:10199000D145DEB3E3A0E9681F7FEC5EB8B0004537 +:1019A000AE3635A9AA020B6B9E5CDAD0CFAA1B79A2 +:1019B000C1DC22F596B3258C75E33B3EE160F494DF +:1019C0001785023CE06798E5F153202304CB26EB12 +:1019D0004931364BACD14F17A932C0E7448069C8B2 +:1019E000F44311BA78101B379E3D3CD98D28BBBFFC +:1019F0006654CD0D7D060DF0ADF7533AEE8106D25B +:101A0000F20311741684353E9CEC738CE42192F63B +:101A1000FBD758D17C4A6472343C6DEB13966B440F +:101A2000529348D78064B7A9225EC37AC401DA8290 +:101A3000D4D165FB9EAB7D2FCDEC0BB27AA7D78BB3 +:101A40002F844F3B656A652867AA98E159A2C29125 +:101A50001ABDD77AF0FE81A36CD1A5E3804443067A +:101A600052FA37EC57DB29B87D3EA8DF93869A5DA2 +:101A7000A6C27BB4046AE534D54F44FA62C050165E +:101A8000832C62BF762E04A74319BBAE34E7528481 +:101A9000CD00DFBB9589DC65D94E2615456822F55A +:101AA0006ED8627A9B90D931D77452EBA5E91EBDEE +:101AB00044E9166C1D2D888DF63AC8013DAF3244BD +:101AC0005EFAB2D5E0DFBC30891B29BF8DF15A1216 +:101AD000957162E720DF0807C748EFE6D84608B2ED +:101AE0008BEF148D9736DD2ACC6B494A551806C406 +:101AF0009087B29DAFC724D75A4E1269D580E40AA9 +:101B0000B73736AA4850C41536C4F61DF5D155A7C7 +:101B1000EFF3120574C422A96DFCE2969D1F901A82 +:101B2000D6F3EE1AF58A087B68B126297DF2D12218 +:101B3000E20831DAEC9F2CF56782D547D9D7A27A33 +:101B40001DCDFC4962547C2CA56FAA0D30B28BF0E0 +:101B50002CB4F5E14D04AED8389F11D556DCD32313 +:101B60005986345EBB91F1D9013AF1F6EBD768BBE7 +:101B70002430715BCFD9C20D1502877FBE52068A11 +:101B800000C6D11F0434B37166A7377C37AD7FE739 +:101B90004FBB2A3756DB091DB08DFEF938100C2DCE +:101BA000F39E5A80B64D0289B6FB7E91D196F9DE3E +:101BB000BDB476A81904FA910DA85FABCDDAA7F2EF +:101BC000C0657D9ECA4EFE1D0EE70832AE742A9C8B +:101BD000C8CBD705C61DA95388DAD7C77D331FB92F +:101BE000D1393CCBEF173FBA19E4DBD40CB4132640 +:101BF00095B98BF3B0F67351D169E49C77BD911E12 +:101C0000CBDA2410D1C513A4EAED8363A39E11B5EA +:101C1000EF072A7ABF5FEF599B5C09A43D1891CB6F +:101C2000C67815DFDFD5382EF4DF5F2BBE699997B4 +:101C300007CDECE58BB803DAD17368DD0B6B74511B +:101C40000F5201D8F8EB8110328694D46A98B89973 +:101C5000FB19630BD22A3210E6FF0505CF829D32B5 +:101C6000006406184C48CB0751F8B7640AFE16D436 +:101C70004E4DB0EEB05B15E81F001EEDB6B5470146 +:101C80000D955C6501500DAA9A0E102A41ED8C5EEF +:101C90000DC0981DC7E73FAFC4893CFE791C9B8FE0 +:101CA000098D8C985D1B643BCA1A35C3D773DB243E +:101CB000ADBF0511D27B7B6D53C1E9794F83801095 +:101CC000F0C00B5A03FD640EE88B4A96F1CF07A7CC +:101CD000F61CB53ED0FDE5B132416437DD181A156A +:101CE000DD23F15A893B87F912E6F6C0828FF8BBF3 +:101CF0004D32D58DFE3A202DE819A9993FE3D554F0 +:101D0000B8D88712B46D091855E44C26C3ABFC60F3 +:101D1000A75635109DEE9ADCDCCA013BD2BD555763 +:101D200062A7F1C1E0FC8CA66700F59CEEBC00FF49 +:101D3000B1C65C2C90067C3F8F2D3652813A6226CC +:101D4000E8AE73723A4422BE8029FDFC1AD4F86FC3 +:101D5000BD90A695332DDBD95355C7404D052E8632 +:101D60004DBC6D9C6DA81FD91AA4660431B1AD2677 +:101D7000B3EBCC77AF08A627AB67C1B4698D149BD2 +:101D8000A30D9801791552974C8CE7FB1AD372FF7B +:101D90006E07002AA4C1269867AA3383BA0B22795A +:101DA000905D923D073B2996BF5BA3DA148D944E5C +:101DB0009FFC81558A25AAC75CC3C5C44384E882B9 +:101DC0001508EC79C69D6EE4D0A3237EC40C298D42 +:101DD000032DF53A370D1E5867DAE4BE1F122AF8B4 +:101DE000822F784931F840E08227FF779D83E6F81B +:101DF000F06FB603B42C7F7E76EF1994FBCD656847 +:101E0000233166BA89751BE54017D1A99B4243ADC2 +:101E100075556BB5384491E6B3BDD9697E77988A1C +:101E2000D2287E9824B292B9A620D83336960EF4E2 +:101E30001F065D5D4C586BD820D25139097491A5AD +:101E40003E51ABF14B1E9FF34E4497BDF5179F518A +:101E500066E6C939C0E4B9D593F5A996327EDB1997 +:101E60003DD7DF972C55AC6CA5EFFB1893CAA6F9AC +:101E700002BB23FF322FC070860F12A1B50B97AFA4 +:101E80003AC95061D7F534737DB317736DAB4AB05F +:101E9000AAD1575AA46A3FDCE20A553EC764689348 +:101EA000883E950525AC88D5C116737330517FE502 +:101EB000BE35AEE4E8DB477B0BF004F55490D42844 +:101EC00054520C4CF23DCEA9D6DE6B70BF0658645E +:101ED0003A245B8DECF79BF98C568A89E54192CECA +:101EE0005D7FE3B74D5BDB2365A3FA3680C426A58F +:101EF000893117525AB91CA3DD64195B076A57412F +:101F0000C6A6B2E3D1AC3237BDB9197547456B519E +:101F1000EA32BF880210EC530F3590245A1EF67730 +:101F200092AD81B13B1661B1CF4012E873FF709D55 +:101F30009CEF7FD274A790495596013FB7F696C2A1 +:101F40001760013310CB9708111032A9A9AC2AB23F +:101F50007DC456ACAAFFDA941C38F0B8DDCA7DD334 +:101F6000E73424BFEED0A500DFC62DABBEBC258C68 +:101F7000B84207342F2C2BEF58889DB82BF8D8295E +:101F800058BF892C11190598B750F796BC870C8655 +:101F9000C9344183C92EE00BBCAE33587A967A6DB2 +:101FA000BF9718E88DF8D8F820DF00B26C05C5C9D6 +:101FB00051D05814C663EFA42A91FD39118997FEB8 +:101FC00099A0EBF63CD5AAAACFF03A1D99C9FF38E3 +:101FD000069E9D1EAA4965A6519D785ACE8DFEF596 +:101FE000FBD9C8339D8442E669487C1C5B16806D32 +:101FF0005FB218035F9442716C7263BD074D9E0817 +:102000006B340CAD3780563CBACA62063F6F6A3EED +:102010003C9824EBE6AB9C99D5B927387AD84DC0CB +:10202000EF3CB2C00D54D40D9EB6FFDEC887FA88CF +:10203000F6C395E814E67D42C7C55F7AA2FFFA01B0 +:1020400076CBEA96CBCC6574B4B42E58A1AD30EC07 +:1020500056F9828B7F809033CD45DAA66078E24EC8 +:10206000D5ED6E572999EBBBC84EF7358CE3D68872 +:102070001FEC52D8B6B5A738EB4C9DA7F0C35FDB79 +:10208000228776A1B5652805EE5B8963805CCD7FEC +:10209000469A390C88F74D3863B6EB149012F9F371 +:1020A000D7F5F51E9BE2DB809FBAE3DE929E8BACF8 +:1020B000CEB607541969EC1FA684BD1F00E4011BAE +:1020C000F138B61CCC68B15310B7B7AC8D1F15C131 +:1020D000C40D45A0CA5CB53A04F90928C77A0EDFD9 +:1020E000B172689F76F92EC2D70A57C95389E01D8D +:1020F000ADC4A76631D3C2C416E5B0E75446EA3A88 +:1021000010341944577174C8207BDDC5948443860C +:10211000E4E1437805211A31A482BBC1A320724FA8 +:10212000C8BF17C63B57736E91EEC5F41D48E45FF8 +:102130004E49C9120CE8CC503056204CEE7B36018B +:1021400016865D5F2149473B2D6512F305FC4D3432 +:1021500042624308D2ACEE17EFB97CE5DD3686E18A +:10216000C4912120F2738FE95F836AF963B9AEB934 +:1021700078A399C7F92CDC21B1EB30D2AB9D9684C2 +:10218000C31B0424FE8584A3DFBF62A6F111906EF9 +:10219000BD439488469BE41D9576F63CA19231019F +:1021A0004974DB28F559F1F63A929568E9CC126A40 +:1021B0005061BC3FB1189BC8824EE7B03AC52FF6BC +:1021C000C725BAE11BBAE7E72AF6D107A2C457042C +:1021D00029049C626C26FC0E2EE36432B481BD5C43 +:1021E000C335338240D0247107EE58A63CBF500758 +:1021F000472BD5BE96D94927762C362553EA94B776 +:1022000080C1A2D8385B78690A06002BDEF072FE26 +:102210000227ABFD8F0343215C870E70B0B0B4077B +:1022200082C660FF9217F12C3A80D6EFD0E5517D3F +:1022300003C74622C09F71566B87BA634BAFAE4D42 +:102240008482F4405EC2ECE1EF819450D2C98212E4 +:10225000A57FBE788BA31903E210F41611DDA95FE8 +:102260001BB33096DC5139BF6463C2C588F487A9BB +:10227000AC3ED7CD36B8A313542082E0C4C31D09A9 +:10228000CD329335B25921F1B598AB9D8C6CB8170E +:102290004BFDC6E6E6950884237C30C9247F29F5EA +:1022A00050D6C42D9B8606DC4A5595508790DE8516 +:1022B00056D320F69E43D79715FE76F71232E227C3 +:1022C0003FDDED27B70EA6984FCF795B8FB5BDEAFE +:1022D0003FAE7FD8B7B03A648633C8FD025336406C +:1022E000019D4E1C60F5EA9D5A7175D772CF004072 +:1022F000996F0F80EA8119537AF2DDC32AEBA1D0DE +:10230000A4B2DE0C92915A4C565EFB326BAE7BB19E +:102310001C456E46613EA875BC1A04B82F6A2F533F +:10232000D488A0B31C9C34F0C0868421188AF89FFE +:10233000B39F644E32D7BF8F43DC783A31303A9244 +:10234000000DB5F8375DA088FF5C54F03F8D767CBA +:102350003609B430BF99849C8F3FA25AE7EB22D64E +:1023600086339EB3E68951ADACF2703EBECDD372DA +:10237000187A70C2D65C4368D872480CD5D842BF70 +:102380005A2F3CBC4DAF1FCC7E7C4303A60556099B +:10239000305CFE109DBF98C2A288E0B5768C3FEA03 +:1023A00067597264F247DE17DA4DF3FF0F8E6E92B3 +:1023B0003930CA554C14F20E8C03792EE06B8287AB +:1023C000C30600F34A713F8F465DF0CC3CAC05A4D8 +:1023D000CA24EB18FEAAC06ABCD4056442A4F1C1A9 +:1023E000C050A41D58027179B6BC5C02390DACF81E +:1023F0004136D8A1A7DD4A12969C3DA795BD82FD26 +:1024000078D4DF837585F8EF46F68184363499B544 +:102410006939F6D07DE34F0CC0BF1F878CF95AFF96 +:1024200005BCD380E15D645734C5077DD3D5DD6B32 +:10243000574416D2A48AB1A8518FD8B120972992B7 +:1024400088D279754B23FA43138393B7D9CDCFF94B +:10245000ED68A9C6F6A7CCD57D65A324883CA63631 +:102460000B253126F17335641506362AC299575566 +:102470007DC0BD2524C51ED91B62C93032B9165393 +:1024800055C1FA4512F2377F5D3555AE7839CD39F1 +:102490007DFF37F92210887A149B22A9F1797B03FA +:1024A00014B164320EDED95BC855CFD48DC2E4AF0F +:1024B000C43C5C2FEB90019C0284CF0824CB5E04CB +:1024C0000885613C17A739CE75AD10EA8DBC8D38F3 +:1024D0003BCCAC69C5BEBBA5B9EFF136EE14C193D8 +:1024E000322F3B7A9EA91A3669988E77DD5B930B63 +:1024F000B6EF03021B3D3A4D6AAE32DDF11ACDDC78 +:10250000500D6D4574329E693E97F2F0DF8A451199 +:102510005102699837D9DA96E713BC552CBEF900F9 +:102520008A022E443A55EBFA414A2F57474173A28B +:10253000F73A90E288C27870F8756ED935AE535587 +:102540000176641508B75DAF32AED49D3FB56B37E9 +:10255000EAF81E276DD21DCD210F00F0D70184802F +:10256000446B5AFCF2E373F9EB22C773B4C7E5532B +:102570006B449623446F000609687AE104FD0CACB5 +:10258000B0C92E96022E818E88B29287721E7F2647 +:1025900041FD07FB1999BFB0D749039CA9C0BD2DC8 +:1025A000D630292FE0D376892A267EB446A9F58A2B +:1025B00092DCA6689886AE1B3E4F0F21E6ECFD3DEF +:1025C000B652EF9785A364B5AA804F8356F171C4C4 +:1025D00013C4F2B438265F0A81C195BAF576A7957F +:1025E000C75CC718218E8364C9359EC25AF73DB6B1 +:1025F000644C54B00B9B0F54F0064756135D30A14A +:102600008F8678E29CFED347B137A64095C719C79D +:102610002203F2C5B317FDFEAC8BE8DE45C1AAD597 +:10262000183F5078A7D5D5A007A9C70DB5230DFB36 +:10263000ADF6EC6478E16886C194023DFF6C8A5780 +:1026400053FADC6C68EFD7A61D34E992CF82E8D24A +:10265000CF713B9CA0EE850C940AFBD65906F71E61 +:1026600092BD64A08CAB5EEDF42CDBAC66EC50C08C +:102670007CA814361BAA506F19714D65A43E0168E1 +:10268000A0EBC92FBAF3A7C4CFBF51414E45EFBF4E +:10269000B91EBDE14632A33C9E7CD4EF2E77C042EA +:1026A000958493AA5C082AD40D348C3DFE6893FE71 +:1026B000A42FDF9FCEC867066A84E1DA5A587500F6 +:1026C0003E6E3EE092BD0AB4E6D412C6BD3D10098E +:1026D0004B3197A8500D60E6150B9F9529A8C909A5 +:1026E0002925B2FA3BAF2DA7B859E4DD40234A3281 +:1026F0006C7335B3ED3F4A4ED422CD77BC950EEFC7 +:1027000059FBD0D955F681C06B1BECF3891BA16B2B +:102710001F25A1B1BD2A3EFD88D26033993C4151AD +:1027200005DAF251D4A142C8792124255A4A307AD7 +:102730007780CD91DA2FA72258E32392AC33941BF4 +:102740001BE1A646A5B8D917B608C5575D77CB9B40 +:102750007D5B80218B7679FA2D751881A215E60FA5 +:10276000EAAD6255F453DCBEB151E8FD4538B52AF7 +:102770001A7B6BBE3DC456DAC9995D032B21C82D67 +:1027800036A5452449D07201DD65085948AAD78588 +:10279000721E54AA02300EC685CC9C83E299526602 +:1027A0006CDFE278BA2259C82552BB112B79F33677 +:1027B00092E9B696A46EA4A952A41F682D20AE4932 +:1027C000596FF6B1569021635B7362ECAAFE253E09 +:1027D0001391301DBB1112669203540F751E0E9A91 +:1027E000C5F7AEACD2F3499A764D09E351773AE694 +:1027F000F74D98DBD610CCF30182A17E8BBD4F291B +:10280000C131C5346DB0271D7846C8D2370E75F773 +:10281000EEE6F8CD4EB69D0F51F9D7AFDBD3B18CB4 +:1028200001C64F0FA383A73FEF000CC48FA3DC7A30 +:10283000CBAEA4DDBE1954A9CD184806CD8C525597 +:1028400027E80F6F91AA460608DF731222AC90CFDB +:10285000E86EAF36F4EAA6E3B5FD6FC4EE5C541D36 +:10286000A7B9E4F640A9E023F093BB3E2080B0274F +:102870007EFB86B1E6010C162059BF7628B0A61E55 +:1028800013D42AE502C9ED743AA71BD70C6AAF1B13 +:1028900079875B0B57A2F626CD6EBCC6D4733E710A +:1028A0008396C423BFCE7686AB3414D784E85744CE +:1028B000F7A30ED5ABB76DF608A8A57FB934D467DA +:1028C0002A18D5BE14AFBFEECA249B9C82F8B4CCA4 +:1028D0003C8E38940F39E8E25D3F3D85283FA5E006 +:1028E0000DC0B2C7B033FCFB949FF69F8ADCF9A001 +:1028F00090C45775E888E8DF3C5C53BAAC323F01BE +:10290000957DEB1009BEB9CDE118FAC763A769E35D +:102910005A7F49EEF9B2A202D3A6BE8DDFBD8F1F4A +:10292000872ED4F764B2255010BD2A42EB521E0404 +:1029300048F9BE4A5D888F419DF2B0FD2B44252C9D +:10294000DF0057B1C77EB0189B8CA8C5C44013A93F +:102950009E3E074324ADB84814AEADD4150F6EA308 +:10296000114543AFC29F07E829C913623E1F89DFA3 +:10297000598A99959810F342C5C37347AB8898CA92 +:102980003CCD70EB8A59550983F59793DB0101ED36 +:10299000D9082895D3CCAFF367611EC94363DA6EBB +:1029A0007A8C61C23761E06503869B337F29DF92B1 +:1029B0005173C3DAA8F75127E84FC4E0B751850631 +:1029C00092165329F108AECBFECF8EF519EAA37FFC +:1029D000F5B1967E3FA572E2356DE52218C8C29624 +:1029E0001B52E23188270EABAED2E333E8A264116A +:1029F000A198EEB46C3FD915034E750B0101ED653E +:102A0000940D6CB819768C3A7E2DCC5446F641C0A4 +:102A100046E02644845F5A487A712E690778C09F41 +:102A2000D426AEE3ECAC36C509527F0828AC785604 +:102A30000DFAAFC608A212569A7F3B1D0ACB5CE680 +:102A4000EC1D638B7C820C27F27A3DB45521AE09D4 +:102A5000DF33AC7AD40D474F3868E318006224E8BE +:102A6000E741BE8EEB2610A1FAC75FFA77204FE14F +:102A7000D0F21D2A3333562FC1F6DC0A67522DA837 +:102A8000A9C836DEC81CF9D614240DD160A6F25DA3 +:102A900090CCDBB7C4242D7A2004F29254DFEFAE41 +:102AA000DD6266DC05ECDDF4D0F2B487C9C66C5B90 +:102AB000FAEDEA803A3E3F3176238BB2EF4D9E9F8E +:102AC000BF5320A32B5F59F811F0E4388148FB3540 +:102AD000E9237084672AFC9B684C3598160997A3F4 +:102AE0006B8F77E20E13CB5FE40A139F7ABD144A13 +:102AF000051B1A4B79AC5D232A5BED4629C3F3EF26 +:102B000085454FFB7DF39BA7F7A497CB08A4A4783A +:102B100002D6F5C2AD46B6FA3F1C66F3A0417C3042 +:102B20007C375C54EDB2FA825308FE80FB6AB4CF66 +:102B3000BAA01F97D84EE6317C64C01BE1828F7427 +:102B4000823817DCE6875B2F6EFCA17688CFB291C6 +:102B50005CBC6D5973ACDABA399F3E532C71E97E77 +:102B600096A8C4981593275651B04C2D1B30E1E61A +:102B7000DAD959D8E36208AC8B57D7765495D0AAE6 +:102B8000121BCF35BB9F4D7460AE8C469E6A7CF89D +:102B9000264CE6AAA3CF7DC11974BE820D2320A9BD +:102BA000F5F0B6D372AAADE7E510081AF3938E38A4 +:102BB000309D5086703DF4A0A658E353829869F981 +:102BC000AA6758A7898C63BC13E63A0744DDA9308D +:102BD00052367A3DF8B51161C5518B8F6C8BEE651D +:102BE00002C8815E92BAA3BBFC2A8C32F7783DB151 +:102BF000D277F0C490DF32AA1A3DA561B9E86055DA +:102C0000FDA682A84A62273E3FCFCAEBED304F9E19 +:102C10006B282DB814AA7F9A3ECD04A74A26310C02 +:102C2000807B56F0FE18988CF38F7FD107682C704C +:102C30000797B3E6992E7ECE44504E5118BC610FD3 +:102C4000C5B4F25FC498C2E9FA833D00A912CE551B +:102C5000FA896204A99F6D6EAE1C868F7431C961BA +:102C60009BE9CCFA44760961A025699F83441F053E +:102C7000F60A5848B6155E5046FB0361142F3750CC +:102C8000E55498724A7182A321EC90CFD45D0A7DFD +:102C9000444D8B0B5D531698F564DB8B3D2C1B3537 +:102CA0006416FC08DF12E357F36422D286C3E1C442 +:102CB0003C0A6BA6AE9B54DE6BCBCFCD0D70186E6D +:102CC0002F54252BAA0577108FDEA61F4807576FB4 +:102CD0003AB75AEF15115A590B0FCFA5C38CE2CB57 +:102CE0007B6F2A91D79F13A724421BF10D4F5CC91C +:102CF000A4A204F6532F905426C33F281E13A4B158 +:102D00002C655C189B97307BDB76ECFC5225BC94E1 +:102D10007FB90D18EE4DF8D15129DADD76BF335F5A +:102D20001DBFD6E104C1B9B1C944F4F8647AA872F0 +:102D300010A4A807A4D47848454A1E3020FAD061D0 +:102D4000DF181BF66E580E80F44EE61585CDC86C64 +:102D5000FBFFD1F142C70B4E824461C09CEA6CEC90 +:102D6000BC1F784E4C270C0867333FA99F938BD824 +:102D70007E9AE036537C8D62782691F0BC3E2058D6 +:102D8000EF23D6887EA857E85C018162F104F050F9 +:102D9000458A68A4CAC2F1E22A49562E5111D8AD1B +:102DA0002D20B8649952043E98FD58E0FCF40EE9D9 +:102DB000440A07862EBD32F53419EB83F947D5B1A5 +:102DC00084B2E28334919504961CE8EBF0A42A8A3D +:102DD000E86AF932A82FA0B2D2AA8AF59DD51E5E64 +:102DE0007C43238FCC8DCA3639EFA9F454E7921572 +:102DF0008FA4F12A79F86F7FA0D72EE09FF957AC06 +:102E00003AAC65CB014DE31D28E32897236B674956 +:102E1000FA25EC895F96304D42818A78D120261BB5 +:102E2000060E8C25840809F6533DBA438A387E2065 +:102E3000EF37B72C061DAD13BD6F7D8E6176287AF6 +:102E4000F15D8ED76E272C0C6A3F3C35D4F08F7D18 +:102E500054AADB55B85A17F0BBFD6D65FE5A4C43BA +:102E600053287BE6F853DFC5AB391C4B93D7D7F912 +:102E7000CCC483264DB5F42966953F1F4C8D51195E +:102E8000A876C7A9CBC62FF166968C6CD67E50A1CA +:102E9000D704ED9FB2A65879232374CD1FB3F6F95A +:102EA0008822E9F932F6F427065079166BDF6A4A70 +:102EB0000883F147D72A5EE46FC2C9742876E0F22E +:102EC000437195FD403C7137FFD68ABB9D2D8F899C +:102ED000E6A40800121E1757FEF9576C9459E573C3 +:102EE000683CCB1B152310F59AB422314382AC5EAB +:102EF000CEF3922E569CF68377810DFD152A7BD753 +:102F00005B3461076929521E4A81CC6E2E229EB025 +:102F1000DE34BCED2DA465FED60B8CE0A698EFEA5E +:102F200097BA3B2EFD9F856CA5705904160ACD609B +:102F3000AE6154E1E0ACA63B80599FF22277169F28 +:102F4000FF2BA8386D108E7D39723596C984ED033C +:102F500040A132631853E9F0CF27610A2956C4FB18 +:102F60004BD8DC39E9B39D917BA828AB5913F066A7 +:102F7000095EEA9AF398BB90B33D35C6BF86D3414C +:102F800039291776DC8BC5AC16748471605306E65C +:102F9000EA0C62D8FCF5B3EDA06671611F1AC66336 +:102FA0001FECA3E5F9F02D61413E8AD2243F1A506F +:102FB000DC8558050EE2466B55E12AD99904AA61D1 +:102FC0001E1AFF051A9A19B18AC56DE503554808FE +:102FD0008B55CFDD8B0AF25E7D134C1DD47D477E71 +:102FE000F7597575FA708475E32B99A532788FAD12 +:102FF0007C47DD9BCB5FFF62CB0C238FE6E2FE2A92 +:103000008217F6109FF42FB6A7AFC8D95537686757 +:10301000488E5C891E5760AFD723BAC9BFD5E9A7D0 +:10302000D7C0BF737E074F8C1EB27C7060D08B55AB +:103030008AE3A6F4BFB4E230C03DAC11B276F88D9D +:10304000855664ADB6F159E64B9F09159E5D8C948B +:103050000E5A6D40C99F80D2370778EE4F6942649F +:10306000E0AC9A2A8E076D3B1CCE5AD399DB8BB10C +:10307000C7DC9F8A1E375AA382254E6A21B543A317 +:1030800046A10D26737081785C970CC6A944B246A0 +:1030900050E2522F24195133B19B6A03F65B485B0F +:1030A0004A753D7E66558E457A8FCB3A833F8405BF +:1030B000B25723A09E6651B500A570E673A74AE9F2 +:1030C00040EA8396EE6AA4F560D43C73E497382412 +:1030D000ED400FC125D85EF6C5301071949CD728FD +:1030E00042078348E549CC183D9F8DE06E425390DE +:1030F00033851993CCD2AD5B09698219DC168E4AEF +:1031000004B4A17DC60B3FFE7EDF435DB68E8B9778 +:10311000141A2E4E5C6DBC98CB2888F623A3CE776C +:10312000D192EB6F856A03C070F010DDB6237E1379 +:1031300086EA5423E0B16FDCACCE769F5FE288353F +:103140004CB04989913CA273F517D3DE8E92F9D821 +:103150003BA789CFB43A2EE598ECC88CEE2CD1E48D +:10316000AFB5964053553A363167ECCC155B135EDC +:10317000B7CAF6C2B801CC1121957C8288A5F0654A +:103180002404BB92900D423867098ABA81CBEF5470 +:1031900076406DC5E8755F45FC3C3FFCC07051C38F +:1031A000E8DB8D67A3D8507BB359FC366BE82AC4A3 +:1031B000EA46B836F73F5D249C29B05A318F492D35 +:1031C000FA89B1F62BF98A03A8B620792D1B9DF058 +:1031D000644CB8DBF26E80AFA6AC45CFD228588BDA +:1031E000DF5066F6104421D03BD5C294781EC49BB4 +:1031F0000017CF85F9B693BBD9DF8DB4934459A797 +:103200005B3128927D4810B8C5633F86F319BEEC48 +:10321000FA89BF4C990D5A44B69876E496A8D326FD +:10322000164E9D27EDBCCFE6F3739FB34649DDC62E +:10323000E9E396A0847AA2ED8FC53B3774137DD560 +:10324000E96C61310D60166FFE322FB11714B4C2F4 +:10325000BF72988775164D6AD15D91C4FD58A2BAA8 +:10326000BA791B8DB6F90360E8305B8FC6835B715A +:103270009D1FD3621738E5777DF6B394DBE90E2204 +:1032800045C056E11C3F11B4D63D430FF2814B8A35 +:103290007C29220759119148DF4B9262EA5370CD85 +:1032A00002A9A01F29C1112DCBAB006BEF61EF3735 +:1032B0005D5229370449C7003222E25CA11128DDA2 +:1032C0006170D61E031BB6DA3355EC90033F2263C0 +:1032D0008A5FB49631E5B943802F687C7B32BAF0BF +:1032E0005C565C7EAF0C816BED87393CE74CEC257E +:1032F0006B3B8B436393F429F277149346915342CB +:10330000525FBEF1D6DFD99E1743D054BFDCDC71CB +:10331000CE91B0A4C7C3B0CF59359C1709E310D0E4 +:10332000B38FBC4BD540F32A766418B94E40B6CA69 +:103330001C2F35C356DD3618428DEEE7E2686C303F +:10334000FEF97A5271B90255930B95DA5C572A321D +:103350002B11F89511721041429907DDE563052F95 +:103360007B2F51114064F6EC36AD4996FACF7A5C6A +:10337000F8D5D3F5822728A3C6CF35BFF747ADF2DE +:1033800092017C146255A4E206FF7DAE8D00CF6BE6 +:103390008B5BF4507512BBB9BDC451BB4FFD3E31C0 +:1033A000B0474FA393B9759BFF0F281B5382C97C6D +:1033B000AAFD3F9F10D496CF4F5AE05DB22B6F28E5 +:1033C000B596F3E8DEB01556FCEB0EEAC0E0737D6F +:1033D00056459491100FDB073DDD46E3D679A6EE06 +:1033E0004BEA0012243070A43C0AA79C2E53B5B0BF +:1033F00090A784EC6644779537812C0B1F9855175E +:103400008EA07D68F8BC58CA393ADB479240B76A4B +:103410007C327787D43E157406D03AEC8E716E23D9 +:103420009B18002778585FD8428530ADD4FFB3157C +:10343000D16751C4679C18A4FD456707B4708E0E10 +:1034400081A10FCD0C41BD58B51A714FBA79D80E74 +:10345000EE4A90853A8F593D4B4E935D78CF4DF5AE +:103460008ACE4D1A6693A467692F6951DD17582DCE +:1034700046602727449798DAF1204F5AF23E7509A3 +:10348000F89C22ACBD67105C29119C92DD210B27B2 +:10349000A644A289173A84A84108BF971C47AB05E8 +:1034A000A61D71BE21DFA904688713C04038D1E290 +:1034B00054C33F55D7CF7CA0526B42B96E61FA8D91 +:1034C0003C19B3728940E11207ED5FD816C105DCE3 +:1034D000CAA5BF99198A769C5247CA9D221706072A +:1034E0000E740F54BD9831C29EFC8AA8C3EC7CFFB9 +:1034F000CAD3C610B866EF080CC6DE041BD20FB0E4 +:10350000F3782BAA638B248BFA22C967AACA7FADF2 +:103510007393A91DFA43B3E3F9F84FA4164E516D06 +:10352000F9960C8B04F100C318620BC030492DB919 +:10353000C1D33A28DA08ADEA0D7C4EB6D099F9E845 +:10354000A21956E40B20617819EFCE6B68560FDA9A +:103550004B2FB63D4D85BF88B8ACAA65BE6E94B9F9 +:103560008D4142F33AF485FEF531FE9B6BFD986385 +:103570005E4C24A42A0C9D043C19FE5E6F7F2E65D0 +:103580008409887F19C8BB8CE0870A5848EA7F7194 +:1035900069B385B9BFDCD96314F6AEEA8D090CC4F2 +:1035A000AA8777AE88C29ADBAD9A602A6355769473 +:1035B000D91CF27CB36D0D683B73CCD250FADA792A +:1035C00015E0A2311AA22E26B5FF3C32F070C3AA34 +:1035D000B53F9A718498B2D8530C3378138CE1F0CC +:1035E0003201231FF3E53F62715D63CE58D0F45D75 +:1035F000C11B9EBB7CFD70C1A544D5B03395E74788 +:103600002F6070DAA718B655A4150452E1E396E6C8 +:10361000F9672E1F647D6E20A8D74F032F87EA30ED +:10362000010AF57D72E5CE7A82DBE182FBFDB7E629 +:103630000A470A6AEE6F975A01CFC48C554AE926A9 +:103640001ECBD1C5C07A65F71849D7B2261909F53E +:10365000480057A3304FCE359222CB31FA0127775D +:10366000BC3B6E87F89BD18CD3219DDA5338BD7A51 +:103670008CDC1CD89C54911F7C98AB485DB75DB521 +:103680001780452CC131AA826DC214B85C6E64A942 +:10369000BF86A285CD27A8AADD0B0B715F47124D0F +:1036A000CF15D039C11EFCD5435FA220DD58B2F43E +:1036B00041BD56D295ABF7A97B0B36538D8E822C2C +:1036C0002CD9891842101FA2A7DE0D8A9B9817EEED +:1036D0006727AFF5EF69ECE30A1389F21F11D9856B +:1036E000AA9001EB675E26211FA09EA900B194D28B +:1036F0007521BEFBC5318A33E2496D1B4EC090195E +:103700009A627AA740A2A640A366FD11395D65D4EE +:1037100000CD1E8145CD40F8A188F84031DD7765A8 +:103720005C28F9BA263C641DFE46BE58954EC44638 +:10373000763272C69A3D754CE81B93B3EE791F75CD +:10374000765CBDA93CFC6751393CF4C3223DEBD10A +:10375000C902F67EFDA43FDA997F616EB1C62E8460 +:10376000E91766DFBA80282FDC7E65B34791A6DAB9 +:10377000B8F5C97992FB054FF81D5AC2BFDD4FD786 +:10378000C7F82B8300963335F8243B13FF9EC6F50C +:103790004C5576B394AC0FA250681066F6969DF225 +:1037A00013980ED57E20E8743D205A858509B78888 +:1037B00025F20090787A9B7B19ED6053FB6BAEF39A +:1037C000DFD9B155074B6585BE84A4603A9033E9D3 +:1037D0005A74B1E441BDF8D73A76C27B36BA9ACC76 +:1037E0009857BF05C4652061BB0240F1D468A5E2CB +:1037F000A9B61FE3B79FF0CAAF8DFA2D2B0C6DBF92 +:103800008AB31916EDDDC644D538F88F9227AD126C +:10381000CCDE4632A8D52B6BB0E32A97AC95C76DAA +:103820009585A75099D346C24ACA4741D634E03F4E +:1038300008F3CBC5EF5DCCAD12805E63390E8128F5 +:1038400051851729F767503B12D4A9C2286D178AF2 +:1038500012ECFF10146ABC55ED975845CC0C5A7306 +:10386000C3953D083F7D6C17EA32E94B4A17F4B91E +:103870004139A1A58A34B892E47F146A561609FF2B +:103880001121B24A12D42DE760ABCE0B540F7468ED +:1038900031FE65B73DCBEA33CF25CD1FA25F12E0E5 +:1038A0008A09C961396E9EA86EEF104ED24F0D7015 +:1038B0005EC0AAE1144616D85FC787EC58EC1AFD23 +:1038C0003BB9DFE723D584682C8DEE1DB8CAE751DC +:1038D00063A62C78D98ED7BF19A7B38745907DCD25 +:1038E000F2C732FE7E59A72C7B67884926B939B4C6 +:1038F0007CBB227089C3B47774B39EBC7156BEC9B9 +:1039000097B60D0100C2EEB26FF0CD9EE7CFE3593E +:10391000D3B05752DF7668FECF4FC8411B13C78321 +:103920009309FCA540380CA7D3C591C2AEE8EE3E82 +:103930009177E4D0E6CB206D7B99D40D3A586F6532 +:1039400018375D2740CA1372C1F8B54DF328C57901 +:10395000124617BE060E0EB46930BA8DE0310A1752 +:103960005D1BE3BAE620F1D44AE069CCE0852AD0B9 +:1039700017EB61B15F29714FBCCBDBAA097AC6ACEA +:10398000B3E4E7B00B76B18AA57C8E2FB0A946943C +:103990002E1ABDC2C2F5A084D88070C84FE7778EBA +:1039A0002BCECF6953C7816E35FDC74814E8CD389B +:1039B0000D295B1B65F693188B7D8E4D9ED1AD4214 +:1039C0008DD21706D48F6390E6E78C153FA48EFD49 +:1039D00027C6FF9C653D64B7A8386662607A380ADE +:1039E000A1907643D2CFAAF8F607CCF26B66D257F5 +:1039F00046CE1FCF57FEBF16F277C5DD96B41D75B4 +:103A0000805373395CFC35365CA85204BEF281D613 +:103A1000EF9FA8DB1F64B0A396F07E97B3EBA3796A +:103A2000886F410FCC343DB2F146A1CB2B84355C7D +:103A30004A324CA6B677C0B953264A003674E879A4 +:103A40000B20FFBA43D08B94F9745A3010B5B77875 +:103A50005F940F9D136FD163B8F7E2166798D6AEE7 +:103A6000BFABD57EC5674508275A8BF7BDEDC96D3D +:103A7000045F35FC1B04153984A5D21709BBAF714F +:103A80005D94C51AEA4F79F92C94F41B1F7E84606B +:103A900093771A9B8F2C677B13D49E9979C3498B9C +:103AA000361EBC392CE9A62007E6C1C345F23B040B +:103AB000AA7570820AAF4D4E74D1631715292D1D5A +:103AC000C52E358DC0CBE371E89169B797985DF449 +:103AD0004C9B0E91A490CBA62F3BC28050E6E6C52E +:103AE0005B49B458ACDD18031BA251152A0DF0EE4A +:103AF00057680544381D35CD87B546169BEDEF6EEA +:103B0000C95EDFFC1A1EDD428F151B297AEA930A73 +:103B100027FFF52C2A67D4E89A0AD6D48187ED5A74 +:103B2000C3527ED3D6A788AAF4F9F957075713A82A +:103B3000FE0363C3E49597F0E4DB4FB822B7741635 +:103B4000C9E1EA8715E3D18FEE914847FA09210BC5 +:103B500048CF8CD42CBE3AD78ACFE5EEB4EC505087 +:103B6000F793807FA0EBEF638BA0762375BA316D5E +:103B7000391D4D915D31136E9E7D371F4387B2AF66 +:103B8000B84E8240C0CEECD5AA63E46C50C48DF828 +:103B900097485D7E6193FD53EB87D493E220F21347 +:103BA00079F7A491690B81CF5F3BE0CF209FEB1C9D +:103BB000E9250FB1F3D5AE242CFAB90263555C6246 +:103BC000DBF00F1F9517B035469A8033FBC5503B8D +:103BD0000CE9CE8830E1BFFEC79274F61D6CB4B715 +:103BE000A1A7E919BAAE46C143AD96CC6A99B45FB4 +:103BF0006B07BB67BF70107D0D777EB48E91E2E7D7 +:103C0000826DC76564441E2EF8764CF7CAEF261500 +:103C1000A95D47D641E0943214DEACA19C46E7EEA4 +:103C2000532D5656482524E4FB01099503592D339D +:103C3000FB7B2AF02280F47ABE23E420FE95D28D0D +:103C400024253F21BC8E0A2E5F37322703F1B06353 +:103C5000E9623654750F004F129FF1F59E4906E355 +:103C6000AEB4C542725EB9F5AAAFA57F74E66B50DB +:103C7000428B4BF63345324B29CB947F97D7FC7A56 +:103C80008B01B8F78D5E5433F7C98386574D4D8C41 +:103C9000FFC47B429F0ADE5021EBDFD8F7CB821BAB +:103CA00069A372318BE0F7AF98F09CEA4B4C46F574 +:103CB00097CA9D2B490A5B9E1CAD714302A544BC6B +:103CC0007188E7EFA09B9A48D76F59D9F739147FCD +:103CD0008BB3543D180451A40B0A5DD8C47D160A59 +:103CE000593E91DA588D29A5AE171B7C5F1A4A1FE1 +:103CF00095D7F3F2FA2E3612878066645476BB931A +:103D00009673CC9E5B7973657399AD48DEDB0E7557 +:103D10000A0687D5C62F0D2F24A01B631BDBE823C3 +:103D2000D9E9CA34E2C697704272D3A8C7CA566AA4 +:103D3000C3469B758A877E37877C8EB22DA29CFEF8 +:103D40004AE2FFF64F7F17041A9CE5332C5E28C722 +:103D50000771DADF36289DC32DBE973F159AF06AAA +:103D6000E645BB98CA810124384E6D700789269EAE +:103D700014FA2DF818DCD22FB9F28AE9357F000D3C +:103D80001CAE9E88375BC4D5078948D845649254D9 +:103D9000DEC46EBCA268B484CAE8FFE828CDE74E52 +:103DA00038B422A04BC9DC6E00A10D105BCA1C21E7 +:103DB000A94C4FA2E6B6300245C60E44E8F3820F86 +:103DC0007C0C6E4B3BC544A82668EA0EDF1AD1A6D0 +:103DD00049EFC5682D2B84FA8F3DDD830810B85C50 +:103DE000E397EAA6D56E45438CEBEA6677FE9DEE37 +:103DF000AFF3FBC56DD5EB9DFE642628496F64BB10 +:103E000091BCD0073155AC38F36D58D0FBBDE2F909 +:103E10005BBA7817F6BFC3CCC792207C483D6D06CD +:103E2000B33D4DAF3070FF6ABE1A2CD925CC166356 +:103E30002F58002B65620EF8D0A8F6AE54EE020F94 +:103E40004D9CD1068E823588F666F1C4AE01806045 +:103E50007F3D7C4610982E2ED9E2CCC257EB1E0A2D +:103E60005B23CC066FF45605BD6D57AFD6EEA74663 +:103E7000B9E369120F3AF407C8CE695407709E4C33 +:103E8000790529ADC385740E5730DB0D7A76DC09D0 +:103E900032E6BB50E9A7579AAF22E01621AAA3C485 +:103EA000644C679084A415C781CA3E424187CDA364 +:103EB000699E4111DE06D253A862FD1951CB1B4702 +:103EC000DD1A2E180B7DB1E1F19DE11926F730378F +:103ED0000B25985C646E5E80FF456BD2D8275471C9 +:103EE0003E4E5BD10A912DD599AF812A95EB82C2C6 +:103EF000104F685DD448C952CD56ABCE8730AB2643 +:103F000040AEDE063AB198FF3183C475CD35AA7E46 +:103F10006085993E45D57038933B07C7B4E084620D +:103F2000F9C13A61FA799702AA6D357F7E304CFF6C +:103F3000D571D7BB5BA95335A7F1207CF01B298C29 +:103F4000E482D1B1A9695487BEA3B19009D954FACA +:103F5000104FB0A47FE9B1F8130108924ECA1E2891 +:103F600009F81C30E62BFA2DE7939C1937FD508C8D +:103F70009F3304CDDA165ADB1315871C5F126A488B +:103F80004A41A505ADD51C8D1EAF0C1AA289F94B6F +:103F9000291AFE5AC307317D3796E9A1665A3406BD +:103FA000C0ED5308C92BC8DE12B4CEC0F6497F71EC +:103FB0006411CC71065AD2C1B308C80A95BEBB625F +:103FC0006B6E60CCBE291D265AD6BF6A169E0FF7AF +:103FD00033771F48A044319B957A599298A739B9F5 +:103FE000806DBFB6FADC3EB033C0297A70F0505C09 +:103FF000006C27AA37ACD03852D9D34B2A2DD9061A +:10400000BA616233825930D0C19107A468B2524379 +:10401000E737EEBDD6E46CE0B387BAF159FE8AC546 +:10402000AC0CB36CF1E3302D4CA4EB0D4D56FC8A77 +:104030004F884B47F609037D0B86EF2D31FBCF519F +:104040006657A8625D3236A898F98FBE36EFC50272 +:1040500022B4A8916192DBA9BC5FAD97D07EF9B381 +:10406000D6784CB24AAB62F64056A85603B79F4882 +:10407000F245AF49CBBDF03BF5A7FBF731717EBCF4 +:104080001A191C413C23E93366BC675A66A1CDC9A5 +:104090009C3AF928FFBE02DF1CFFDE1181E4852D6A +:1040A0008DD421AA6BEB775D7CC82CDB5F24D96FA4 +:1040B000EDB10A274CD96BDBE2D1CEEDE66FDD40E6 +:1040C0001D03F3B26A0FDDE89A498B2E7C17EC9240 +:1040D0002D8F042358928A9D1C996A12A899D3E9BE +:1040E00024DF82C7BE833AEE1C636C12B876CE28FA +:1040F000C03D7B0DD373302FC405E49CE4B249CF9F +:104100005979B137E03490BD60C47BA3FED32DB4A0 +:1041100001CF0BFD49BDDD4126B6A16BE14FDE07A6 +:10412000DF6788BCF1998331B26F34B1EF6F6124DE +:10413000BDBBB986FD36D06ABC2BE1A90160A18662 +:104140003CB22C18BE565B0E7EAD1D0ACD12C74484 +:1041500034BF0E2D85F75512FDA198B625F47F6763 +:10416000E3859864C1E128473F4CD2700BBB433BC9 +:104170009A50FA2AD195978F1A513E71FAD706DCD8 +:104180000DE5A2FB2792096AA777B34451F02CAF43 +:104190005A8137145958ED4E61CF132D2ACB810027 +:1041A000CD3E0A23C479621F740507D943AD358C0F +:1041B0007F8BF5314D3BBDD7977B655B5D1F305FD6 +:1041C0005D5E98F6E244860289E9C4E178E0CFE3D7 +:1041D00040ECE67FD357E99C675698D56CE5639E23 +:1041E000B1D69B40B299E58570B56A4458C19C64CC +:1041F000B3FE08AE26BA2E091E6249E13CF954BD51 +:104200000169AB7E00B9DDBE572311A5E533C23D80 +:10421000B375DE8B8426A0080E20887924B05FF168 +:10422000FD1580E19B7083902B446C26A5788CBA99 +:10423000BC0106D4F0FAA63FCB5AB1C09A4E7CB36B +:10424000B2D6A2111E01D37C0AD5FF16339E24A13B +:1042500090A8B4E22A8459C744F2075677522E0335 +:10426000D704C52498AF2EC36CB62676C4BD02B061 +:10427000BA7A6D70328A69D3630DC9AFB33D2B6DC5 +:10428000D83619389FD426E5077B394E904A2EEF51 +:10429000AC08636F3F0BA545EF53802E011679F8EC +:1042A0000C98BDE2C1DCE351D1EA2EFBE61F27F9F1 +:1042B0002FBC4BB30826864CF882B8D5C19933D5AC +:1042C000A5DDA7EE9DAD91F11F959B6E9F7B978815 +:1042D000ABCABF4852F8F0D9251CA16ECED5E63244 +:1042E000CF2C4660E0143A6326157DF7C1381AEFEB +:1042F0009C854F14EB261A7D8DE6FCADEC3EA89C08 +:10430000B3054411C6B19D4DAB02045E110C6C2E79 +:104310007FE5AFC676F75CDC711FA2837C3E294C3B +:104320006A98E7741963D0B3E37E351ECC2846BC87 +:10433000D488E0F7AFE09E5709B07847C8C71C6340 +:10434000D3144925BDDAB877E705B7ABCBD99E9D25 +:10435000AF32D66E79EB70E6249CA47743C54A95BC +:10436000874F27F03BDD28AD7583B013E250372A25 +:10437000959D8E3115E7A460293D38BBE96846CF8D +:10438000D89314FB94AA24523EE89514E2F877439C +:10439000CC33A4004B292C420174037F92EB193CCF +:1043A000AA58A39F6E3F6247B4CDBF710029BB617D +:1043B0005367F31C289A4A4BAE4465F1E7796EE8DF +:1043C000B90E360989F5C9356BC81B78F1DB3CF5A8 +:1043D00021B6096E2DCE46C59DE45DFF92833B3725 +:1043E000810C8A1DDBCB1FC84550953F17C6EB12C9 +:1043F000880BBAD44299E5BD7F8721CCF017788B22 +:10440000DB1EDF5795062BF166B0DEB54DDF2C5A6B +:10441000520FEFDEAA2D492DF22CEEB3153AD77EBE +:10442000BF3FDAF9862B4D5AD00D95CB8CB6969BB3 +:10443000E930F59851F2FECE830BFAEF95D2592769 +:10444000F8594BDCEC0777DD593C55C7C1D6292D0F +:104450002041685A9283EB37F73740910B79B9299D +:10446000308933784EF94D95ECA7AA1F98B219F709 +:1044700090846B2F16ABC7680AC12047F6CA2E1965 +:104480008C3E3B41E3B2EDB715C46B2DD904AF6C44 +:104490001346DB8A87F4695B76F2696FCE9C3F92A4 +:1044A000608D475731F05F2A4DD70ABEA557434D5F +:1044B000451636964AD959EC0B2894121EDDDCFFBE +:1044C000C966F09C67D3A89CEAA8B82E45135D1175 +:1044D000D46BC64599668E4D51F98A1698B68A27CF +:1044E0008C71004F3CC0FA43731B12204938DA3FED +:1044F00012F16617549468CC2E44A759C8286B2C27 +:104500007A8F34188B34D24C029FAC8C2D0FF54629 +:104510009170F82820B9C2EE984C8EBE5CF2849B54 +:10452000203AE6EF8B24B12CC0BF7F7A6968B220B5 +:10453000469A5EB4D0014E10C9B8E01588BA76FC30 +:10454000ECEA006005AB72F66E3EAB210EA6126679 +:10455000B4A9C279B5625FD3293446362AE6ED762E +:1045600017563EDD8B308EC414B0FC9B20855987D6 +:1045700076928AA683346F0CA9DFDC4442FAEE54AB +:10458000521ED72826446665B30CC722FE7F109EB4 +:10459000F2CBDB4750A85F1AE148D0441655AB4F29 +:1045A000C2C8BEFFE3900C91B10D66C1A89E47A2A0 +:1045B000DF6076D69FD643A288C171B57AB4F0A6E3 +:1045C00096C6D138D8C5677EB9EE2CEA7F9D39A34F +:1045D000E14E31C4FF5D8F58FD5D4C10D4FC227458 +:1045E000693325AC9C8A1792A8E8C51CCB2133946B +:1045F000B26193AFF6ED3505FF93DBA768A3EE6AD2 +:10460000BF603E684EB871F11C05310066B9C2B09A +:1046100005BBCE1D04D2C627198F3D097872747F61 +:104620002EA2EDEC77CB16D3E86DA22D7971092976 +:104630005C0E6D78F00EBFED7161CF072A0CAFCA2A +:10464000901300295FB43FFCDD3BB302FB630B24F6 +:104650006DD161DB1D93D3D5E7C14961F8101438E2 +:1046600085E50928743FE6610C03D270DCD1321075 +:10467000522073C4460EFBE9FED26A6050354951A0 +:1046800042271ABC1035AFF10F41E414F0D5C15CDC +:104690004E5363FB75D2CA6DC75B00057E0533863A +:1046A000D009E41EB28B36EE87CC1D4C7F457014CA +:1046B000DC52F9E562E80A61939635B035AD5DC626 +:1046C0003AB4F91191D6D9B51A413D89D1F9367567 +:1046D000373411275B816FB2635F6034929B48D798 +:1046E0003A43ABCA60A37D1F8941D8015FE73145DA +:1046F0007929220AF90BD34D2A765292DEE9F7B8CE +:10470000A6CA6FAC69574EB32B9EA203D654C0CC39 +:10471000BF0AF480B7E751E70037D8ACFA5ED2831E +:104720002A559D1FDEF48AF1E2BAE5A5F8FBD20C0A +:104730005C83C39D351C8710D7A9ABADB9E23A0D98 +:10474000E633B0D5238DB0B5FAD4919CBF4E605AF4 +:1047500063BE4949348756571F83F7E18DF24A47B4 +:104760001F5B20CF00E427C3DA32B1C94048175499 +:10477000358509E75CC8F2AE2EAC8AF38002332B94 +:104780004FAB9240E7B19263C3E4D9FC26C0758A6F +:104790001884B8C928FA7E5ADC82F7CD579B32407C +:1047A000B83014A3DE79E03FC8F47C8C6917785EDA +:1047B000D4EB166CD9522307A559DA47AFB7FDA140 +:1047C000E0D7139CC4BF4EA5487FA54110BD07FB91 +:1047D000A56D3CC7D87379A2001D236E1FA3F2C933 +:1047E00033B844C0C1FE1F25DC82CF14F62290945A +:1047F0007438013A14BD0DC9793257D9164DD21407 +:10480000D98F6ADE4DDAF364F8532B3DB1AF60E522 +:10481000D31BED219D825FBEA0622E70D051F03778 +:104820002D89E3E850AE2FEAE25D08153D913BAAE1 +:10483000541A18AB150DC3E6FAC6C2655A3385DDA6 +:104840009597ED10BEEF66603B2EABE744F4253C38 +:104850005CBB6826BCC3105DDD5AF7DF9FD0883D86 +:10486000D86284327A6C90E24484DAA2E1724EE635 +:104870004E2D5CE1E7DF179A3126A7AA6161391452 +:104880007E21E57D8420074EAA8112AA42A5F12F40 +:10489000621C5315C6DDBFA6905DCCBBA184F6B6E5 +:1048A00000FD63627C20685B0E45975A61CB6FDF29 +:1048B000451814CCD4CC12BE508DAF11E80DA148D0 +:1048C00026D3BE050D4EB9059E8BE6E9DBD89F5C6D +:1048D000910194A0E10BD73F5C8E34A113EB95229C +:1048E0002FBB9E34449B70DE3ABCCE64DC4618FE7F +:1048F0002BE5337AC250D2BE25F37035C4CE505961 +:104900006204C3636085E9A88050F5AE644C829E62 +:10491000C2137150C3A8FD6F89FEBCFB4C06147F07 +:1049200058A706EAFA15A1933DB6016CD889040090 +:10493000B188C65A7536A27A28F202677F40B4E978 +:104940005A3F57172EC01A172BAAC06143F81EAB47 +:104950009C1FF7836657972FC3FF4E52837D673A9C +:10496000346536A941749A149D3540445161799457 +:104970007C348D96C1D9C1EE60A9E6077521E06E41 +:10498000703EA9F3583BBDE1D13CD0F77EEEC3A603 +:10499000625E6BDF83A56B6ED6F444007CF44091BD +:1049A000573254324B43E77639080F28ADEA468038 +:1049B0004CBBDDAFCD8BAE51900A1B67C46817F6B8 +:1049C0000EA3A231D653C08E89AF498045FFCFB622 +:1049D00081B877AB900C936ED10C588C5241A69C49 +:1049E00048F2545253A4F9CDFD7EAAC63143CB916F +:1049F00029FEE1FF49D64D7311F68C90AE68167B07 +:104A0000D1C6A550FA69C5E12CE826185F3BEAB982 +:104A10004EE037282E8F7F1DBDD08E6EEF5F14A61F +:104A2000762711EB7A43568700DAB5BE3321D8DCFE +:104A30009D9D5CF3D659321DC6E82725D0A0F0A76E +:104A40002EA37EF850C739C997B0192473E63DF9F3 +:104A5000F0FA52E7C5B3F186EC6A006D8A9AEBBCB6 +:104A60004D6E80021D0BC03BB54EF3DD3BDBF8BC49 +:104A7000C2592EE93022AFC7050B6FE41E9A3B489E +:104A800071DD7B453B132AC68CC67F4C766B49890A +:104A9000EDA2F2C3BD46D737976A38B2B287C6B027 +:104AA0000DD78C4F22E98A2DAA64485E7640EC9699 +:104AB00027B884E8702A9E15226483A01366B4E8A0 +:104AC000BAD0F6AEB917746CE5314827617127BAD0 +:104AD000AD8AE4D4089DB8284580E82915F6674CCE +:104AE000AAF5CDE3CA3C652D6CD95ADFA81BF82086 +:104AF000B28668362AF6666A3669FF57B25B4DD4CD +:104B00000A5EAEAEECC2BC0A32DE37582488BE293B +:104B100022EC69266577EAF299EE1A527F8E67BD1C +:104B2000104EAE007855D5DE77D909D960B5BA6D8B +:104B3000AF7BECAC8C7C450FFFD30D4A847DD80154 +:104B40008226E2DD94FF2EED0787CA2057239D04BD +:104B5000E4E8F1ADFEFC2E5CCF0A230F926ED90083 +:104B6000ABB3ECE5699B96292476E27F3F1B9EBFA1 +:104B7000EF57FB5029E0535BBAF1BBF3BFD0B75EF0 +:104B8000B94A9260D1E0F6D0CBDD33528316F0C340 +:104B9000DBB3F780EC0C0624281EE8C9B8EB2E40E6 +:104BA000A19D62798BDD46395D15B4AE7287CE74F6 +:104BB000D3728F05CBC51EFD153D8FC7E6DDA6D987 +:104BC00088A25BF820431E60E235B5AED21B4A785E +:104BD000593E126E8CD40BF521652904C8FA6AB1CE +:104BE0008F1F259CC0D24CD8FB23A02F37E855E35C +:104BF000E92AF2BF5E1991678B2B6C17B61708A8CC +:104C0000221DC53BF2A1A99277B78D216D2F783A6D +:104C10005E9FB8BBBF8A87EBB7FEEF41B907EED303 +:104C2000A26B4EECB2F233023F88C7FD0C681977D5 +:104C3000B4E7886F9D09C78D2AE3BFCD8DE7BB65BB +:104C4000D45BCAF3B69D5D25B2202B6CD586FC21C2 +:104C500004779B56C63B8964CCEBFFBF942EF86764 +:104C6000CF20B6B5A47761B85CBF869D7A1BC58D91 +:104C700051AB18E4C81BEA30175AE0CAD2573E3C81 +:104C80004752871A02E2C6E4EB46049CEEC3EB2CC3 +:104C90003B66322CC64DF3BC89DAB9972602B5EFD4 +:104CA000B3E9FA268B2BD67153F45BAD8ADAF16542 +:104CB0002BE2053D4C7DB193B6D5BC548072183BB8 +:104CC0006EEBCC038BBCFBBA93A48373094A68A335 +:104CD00006DB4EF48892E28DF181955BFF3E1B8DE1 +:104CE0003EFFF641FB1BFABCC5C61AA134FB833557 +:104CF000E932E77B35B5F0E97A13911283AB3916C7 +:104D00000470F3E0AE58605F2F31467E0D2D3A5CA3 +:104D10004831F2A37B80041DD7687F6BAB87597C39 +:104D20000E521B685F6F8C65028DA79F61CB8DA6AD +:104D3000712577F1B920A149E2AF0B932E735D493C +:104D40002AA7D45D108D90FB71B61EE259E643CEC2 +:104D500054DA4005528EB24690C7F5A4E2294B942E +:104D6000664A477AF4382D68CB96D2ED40EA05C5FD +:104D700010296FF07E285436B2B915E76F2D60B652 +:104D8000691B3BD68124BD9519CE92B1FB4EC264FE +:104D9000C6DE9C5C22D0E99222132E86BC01CE4056 +:104DA000F746F539ED3177D457EA48AEA439CAA1B0 +:104DB0003D22A9C43F2C37F14F7C4E3BDAA8AD2DE4 +:104DC00008B66A53B0A76E659E4D3288F5365A9282 +:104DD00061763D4B40FB81C034C3ED80FA89B8B3A6 +:104DE0009919D0BA6C9926FEF7CB29479014B2E0F6 +:104DF0004036A2105C93AA8C157823882C1FFA5E8B +:104E0000A898419735807C93E7D12040C34B2AA3D3 +:104E100084A8A02EDA7EC383E0699F8540F78D6C5D +:104E2000B3CD6D0D2CBA1F4C7587AF4D50804176B8 +:104E30007E7BFA76DC7062E5B9C64368A752F8DE7D +:104E40001F9C1821620D85F0E68915F6163B6DEA68 +:104E500060FA448FD46EE065D7DD2B4C47CD4D8191 +:104E60001E9B5BBBBD24CF7039C3F688623E978121 +:104E700062CCB66F402074699E02878FB7C2A5FCD2 +:104E8000D781034F3E564A6DBD23368BC276EBE287 +:104E9000C30ED5E9910A26344FC1A8831470F6BC1D +:104EA000A7CADF0A30B24D9A8DA09206F77B2E4436 +:104EB0004246B8E9377708B56A45F6F3A0C9BAA4FF +:104EC00008A05B3FF7BDCC70B321F9D91E478B44D6 +:104ED0007547F82DDD59E71912738B75D2ECDD6F2C +:104EE000A807DD35AFC471935FE6F2769319559943 +:104EF00014CA9DDF74DECFC6AEEA8F22A178C90343 +:104F00002462ED79E452E4A71CFED619878344029B +:104F1000A264E6FA5CD2367F0D45E0F438BE39A7CC +:104F2000B8406894579F3BADCC9C4870D59C9A5034 +:104F300064A3A120CE8E30CB9E018571D9A35DD70D +:104F40005409F7D442DB4F53D9EAC3FF64D0882514 +:104F5000245F4F9B59E41CCD340582A082CB63892A +:104F60003F1253E0885991C9659FFF9BDD4C0F1399 +:104F700024FA5DC0EEE536EFD161F33BE4F5E5835D +:104F800037D985DF534A857730A7AF22CF4C62E30C +:104F90002494E4B4464F0A3D041C52D146E5F42E55 +:104FA000504E2869944219E7BF8F20A8DCC6D595DA +:104FB000BCB855C8D3B084B971074DBB99C2B6D23D +:104FC0004B6E3DFB951BF89CFAD261E7C6896CB429 +:104FD000C1E49FD1D62E92B36C4EF95E60724F49F8 +:104FE00065831A78123EFCF06797A396B1A8AFCFFD +:104FF000719D59D0AE019CE092DA9D3DECBA8A7B5E +:105000001AFFF0E050EC81860265BFF5D95A0E71A7 +:10501000EDC7C98AA45EDA95D53C9CD1433D4FF7D4 +:10502000323E2009E0210E85994D991B4D0CF96700 +:10503000592C80CFE78463B16BCA500F83EA4CE8E8 +:10504000726E3E834B04252496C997A462C9DE4242 +:105050001F09AE657199705BB1744CFCC42BE60DF1 +:105060009008D031BE63C3BA4985FB88CD1CDD52A0 +:10507000B682978C40D42B63E6F790356C8A65B77F +:1050800059B09CB54B62C99E4990477C081EECAF55 +:1050900099A7374129D223D14C39355C5F57BC429F +:1050A000768443F0C27DB5FD30A0CFE309D35E34F2 +:1050B0003081A32B11F2A0374E0B554B069D3E2895 +:1050C0007F66D82CBAF0D37CBC3980C5ECC456A41A +:1050D000584EF30DCE93F9847F6D58F441351FBEC1 +:1050E0001FF6D94D81B450C6F57C99A9DD5023B97E +:1050F000905DB9234B53B12220D984CBEA5C48BFE1 +:105100006C50B8BF7CADD7FB6521C11AA2707E84FC +:10511000CF6F7206C187BBE3FD85F7D0C16862110E +:10512000507823A522A13AFEE56B6961F6BCB8F17F +:10513000924B8810256E75165D8AA61C2B6B87D83E +:10514000392F79EFB874A5809ED9A1D75EF168D2C6 +:1051500025E389585B60DC1B38DA86924E3246D9EB +:105160005AA8AF778D37B997F73CFC0B7875C88490 +:105170009B05263BA354B822E660BDA791AF779F5D +:10518000851FCE6DF06FA3BACED885D975560ABDEE +:105190004641D0165EB221BFE3B454CC91A551D3A1 +:1051A0002615F7A94E77C7D3FF0CA15A1DD8B644D0 +:1051B00059C9099016DD53838EF0EB822C87339CFE +:1051C0009A068EDD08C9A48940DD367BD6598194C4 +:1051D0003F28C765E4D164697E0D796FC4C842D2A7 +:1051E00068BF4BB61DB925EA20B2A4A1EFD05A95ED +:1051F0003097D529FD74EDB27C8F8268CB7FBB4D93 +:105200002487955546B383E850A44581EC592780FF +:105210007B0C0CBF4F14657A8706285B312E987182 +:105220005154DC241BE1429335048080EA1DE6E101 +:105230002BA0B8D9B75945F0FE43D0C654CD229B18 +:105240006E87DBAA8CA6DB76CFE7FD7C5A06967BC1 +:105250000BE7F78128839CDA08A589940DA0499B68 +:1052600030B24022EF6A3AE6484667169108F0F0FD +:105270009CA35F9DF4DFEC1C63426543A9D03123FE +:10528000622BDA60720FE80C04E3E5D487252699D7 +:10529000EAC71D05307DFF567CFA811136933174C3 +:1052A000E0DB00E30D03BE01124BD83029AECC91F8 +:1052B000E5360DCD12EFF1FCE9A7642161D46FB39F +:1052C000D0F3743870C754B7D3EF28624755C5453B +:1052D0009F952D2C49AC6097CF4EE29EE70F0CAA0C +:1052E000017FF646BB5E4436AC37755CA8553D443D +:1052F000571E1F322014487E76932DBF565636D93E +:1053000051F3BF85D387202B72263710B725078A24 +:10531000E7F17DE2492417364571977C04580084F3 +:10532000A71E1837241AFFEED4C5F28B0DAFA7883D +:105330001C5E56DC941F95058A67EFFF0A26C3069C +:1053400060A95240410B8C398747E1F04FEE7B3129 +:10535000504C1FBB651A572ADD195FA0913CE446EB +:10536000BB61752D0D9FC1C98E1534C0B026754126 +:10537000F87C21C2346E9A6AF70448BD11DEFEC083 +:10538000587E91BC5120439BD9A40A91041F6CE51F +:1053900083EBEFF4C7E8620D0A46D33B25530CB705 +:1053A0003F96F9AA89A80181ABF5E2CEFEB675CB8E +:1053B000EF4BE94020C356C5C5935EAD713109730B +:1053C000E842510193C427BEA87183EE010CA78E59 +:1053D0001BD933504470ABD7895198E00AAA8E1577 +:1053E0000E763917F8EB6CBD80B07020AD49F44DE6 +:1053F0005FEDA74BFED506B2258A61FEDD747B8387 +:105400002DB3BB9531CB744EFCB93722146BB1F27E +:105410001F9B41B4A809A34E5D29C186A876DB8AEB +:1054200040710E9D0CA84F35C211A32F965AC81873 +:105430000E3ECFD4B82D0EE66FE0F57A8758B779D7 +:1054400051092F51F169E8994277B1E6AD4A1F51F0 +:10545000391427138B71543F00F91CC535BE05E77D +:1054600045E707E7244F5B0B55A12B29069EC66D28 +:105470003645896138A69ACB7CCACA51B566D542F1 +:105480008602E3C57BCC6C99EC592A2001938E628D +:105490008CECD9E5538BC9D55A4560B002228B32CA +:1054A000E57AE982D8C5E46A7C46AD0F420DA38453 +:1054B000A246E4A4DB00AB206F8B12A2CFE8989E3B +:1054C000396F1B6579E854349FA12800B2871D9578 +:1054D0001F05232A506FEA197D88DFDD2E0A205030 +:1054E0000826BEE5EA2B05CF7C7A7399842ED8A4D2 +:1054F000BE21320FC311E1C87B019BA2118550AFC1 +:1055000082B22C9B788BD0D6AD56E052AD31A65DE1 +:105510002C221AA26D57FD1A9821D6864039A03642 +:10552000B692838591847A4A08F4C3106842117058 +:1055300007810756DFA0C05CB21ACD0F2ED5CA0670 +:10554000A03E4C1245E74D14D03CA7D104950E6205 +:105550003E324EF279C4C59C4120A6FC69A900C820 +:105560009E16009583BF6E54206FE20D5C3C0013C5 +:105570006A2DAAC3406E4FE84A0E80CEC0CA4F556E +:10558000311B30B9C16320989A77D3F5E11CE759F4 +:10559000F7986BCA91550387726BD77944111E84B3 +:1055A000050495862CCD88E7B353A9F59C55850352 +:1055B0009ACA61F54E3BB802CD1DBFC6F6D618603B +:1055C000AA1EE33AB5411C5FD42CCAC631F9D301F7 +:1055D000370AEF8CA9446F1F2771549CE3BAAC3D86 +:1055E000C9FF529D8E079C744C2BDDA34CEBDD1F35 +:1055F000F14D75BA991E308385CA46D972D98CE2AD +:10560000D72AC76E3E601181144D4DCB0FD0D1D833 +:1056100050E16D645BD79D4104D830264FB5B6A8E4 +:10562000F0FC91CF35D421E7B7CAA1FAEB621A9FFB +:10563000C9C4E8E5AE00E0D71BE1846F96524B7B0E +:10564000857B62FE5AD9E4D4B04EF3461E29C2824D +:10565000977689F32EA1BEA3252CAB218C46728BA5 +:10566000E4943FEB3F785B33B789DD987EB991CE08 +:105670001546A40C8C33E07B964395604CE039458D +:105680001F7650F9064162732D552F6A5F09433525 +:1056900021ED9E5C053633B48E2D8AC05E941AF9D6 +:1056A0007CE852C1B245C67AACA90EC6D414323DCC +:1056B00068AA7FCF7185848B062E3A9F9DF3A45DE7 +:1056C00081A5090E80571AE365E96D251B2C12345C +:1056D000BFE9D4D38E5DD0F5F6B00655A43DC11711 +:1056E0004B33C25546FBC088BAAAC2BD66056301EA +:1056F0009D7616C2B8459AA656F6AA70B874F1B04F +:10570000592CDAFDFB0EA4561BFB411E7F759AED4A +:1057100054F80780F860A5C60C41FB689792AA0F61 +:105720000728ED9425977133213E9698302025085F +:105730009BDB290EF73BA2CA6E172FC8C34E536DD1 +:10574000614C32610E6681F817FCF44EC3DB86B6FD +:105750001CA6EA4E107C2E04A0EE1F442AAB619CCE +:10576000E8B17C3ECB91EF5A30390AA281D7E7D01D +:10577000025584E8990AF4A57AE7021A51D117462E +:10578000A911F631A13ED85DEA95659DA0DB7E8228 +:1057900099B8531448FA5C28809D7B86EBCD7948F4 +:1057A000484F9E8414F7DB5F847087921C35BEC619 +:1057B00006C1052F7D2B053153057919290B1C8A4C +:1057C00040B2305F08BF5ABF9B11439D1E692B46F4 +:1057D000E09D6927BFCD112C187990E6A4F3C3434F +:1057E0003E6649E98D1B5A5629C89955A870B7706D +:1057F00091097115934A3E3CAF223B4BB0FA5C21B4 +:10580000F953082FC11B122EB0DCA96A8F58FAEF8A +:10581000B23513AB2B5308F0C2A0C51982253B1A31 +:10582000AA3364A1A31693D13971F3D24151C113A4 +:10583000797B878272511CB2BB28A8BBF117AECE10 +:105840007CB83D9B719BCF6D0714BBF8DF8077332D +:10585000B64C10BD525DB58862606182B7B7537EA9 +:105860007A693A5489FA73B091CB97A9CAE48FAA9E +:10587000069D32BB7AAD8C529ADD1ED24E80778F58 +:1058800080C4FD5A6C89013B338EC92045B62A2D50 +:105890007423B9FDD02E90BEB5055AD18F08D60518 +:1058A000CC5CBF3526F423E46D68D4CB851AF5268D +:1058B0003C31A96052284F53668BCCFB594CF252B5 +:1058C0009728473EBF5435A82F37AB996A1B974599 +:1058D000693A1D2581724ED44FD43857BC285232B4 +:1058E000F5A2629EB00C4A4E0CB9A9FD92333E91CE +:1058F00073FE0BF1D93B491875294BF838CB7C3234 +:105900009A5063E0D345727D0F0401C42681508113 +:10591000FA6A2F165AFFD0AF374882524062473F8B +:10592000CE3E00D4C472DFC72FCEEC03F8A17E595F +:1059300044F2F74EE0EB7983C1A64F9678670D2DC0 +:10594000E181FE3E998413CCBB0B16DF4676B6D3BD +:10595000CDEA2CA9CEB2C239179572E68A2B6F9286 +:10596000C9D55945060066678E9D0FDA7BE4622B28 +:10597000457E6B3F1B4D83A07CEFDCFF40A0BB1C32 +:10598000D5B2C22007BE2047DD1E56137BC632BCEF +:105990005DE63B4AF5D4BF0B1DE821F860A89223D1 +:1059A0003F523CE15BFEEC00927AFBB88127F72482 +:1059B000484B70D5F20F2782B6568AF3D3CDE60056 +:1059C000FD480055C970EB72F58972979222C44860 +:1059D000829790839B3064331991E7DEC8395AD897 +:1059E000D4E2746DD879069814ABE6E2EE0AE7DBF0 +:1059F000D3F211F9D4D59C9E7A828EDBE553E86010 +:105A000053734A4AEF69E8E6B885018625C3EB4639 +:105A1000AB50D1BCE611410793FFFF1A7F45931DA0 +:105A2000D83BD68F45B5872F90B023C783DCD95C90 +:105A30008EECD6C012080B9EBA6CDEB40AEB276F50 +:105A40007863D77F3C7ABCB736014BD03349F9C86D +:105A50009704CCF7B0B9FDC4ABB0EF62ABBA8FF42A +:105A6000560005A37FB473C9014B2CB9E8C1721667 +:105A700094CD24C74EB22626EEC01C2A0A98E49F75 +:105A8000AE7B72127374A5E5CB07DED1CB706FCA03 +:105A90002430FBD7CF12CA05302CF5EFD0D8DDCE9D +:105AA00059DFE018662273EA4312FDE6563F797427 +:105AB000B3EFEF92DE17D22DB486CC25BAE5862F50 +:105AC000D5F2A9B62FA772F6E0B38979E43BE17568 +:105AD00058638D1252B18EEBE50728F81FDD7E9DCD +:105AE000B193BED2675C163493E0DA34A622C22B9F +:105AF00044BAC3F35FBA7366B4616FDE5E1BA1B7CD +:105B00001E5574770AFF54E46850479DCD4E0951E5 +:105B1000CD13DBF48297B62B67A287A0BAEB8BA5D7 +:105B2000DBE51EE76B1E42E9FE0182F813D08648D2 +:105B3000266ACC8EEF2B8B47B5E650D7A29475E240 +:105B4000FD52FD8CC8C8121DC5CA00D1CE66D79AB9 +:105B50003E8CB9C06F92E000FB4AB693E3BEEE05FF +:105B60001779030F91BFCD19CE95534BBF711EF915 +:105B7000F350462209241F5D6CB48C774BEB6E34D6 +:105B80000732F277898BFCDAA21FCE28489B3D6151 +:105B9000E216910333A76F88F5A9633D5FF4A47102 +:105BA000EEBE65B9592121B068563EDF029846D64F +:105BB000773A2EA3FBCF3CF7EE053B6A18FECDE902 +:105BC000536B3586E9E882D7DEFC2749F44F42164D +:105BD0005CE403B98391A9EC843B56D701ECE06EF9 +:105BE000943CF3A4BF1AFB9045473D542E37028CDA +:105BF0005697631E8CA7ADA8E951B61196C055C83B +:105C000003D89F7B2E10E255F782898FC727AEB34A +:105C1000F0F334F0194648CCBDA505BA2B2BA0DC17 +:105C2000396CA0860AA90465B1E8B4192FEF8EA3D8 +:105C30007D147CA134DD5460A0AAE8B75ABA4EE9BD +:105C4000EB236D8C63A7EF3D6EEAB5C5D7ADD150A0 +:105C50007DD2AED1C4B20B4EBDAC5ECD1266D3EDDB +:105C6000C74B99FCC5A2D3933B7FFB2397235B8152 +:105C7000D23F9F4C27E5318F9F77C60119BC015B4E +:105C8000ADA982FAFF7EAB8B9925D399677C813CC5 +:105C9000DF323324CFCAB7F58BFBCA76D3CBD4DB44 +:105CA0002DEC03AF93D574610DC3C45D94EC96489D +:105CB0001E621A0D6A34DEBEFC0C48AC3C37DFF8BD +:105CC000F2A5D232CF2AC7B15BBFF60808FD753303 +:105CD0006F8003BEC650E5EA650EAB643A42F01F22 +:105CE0004165E1811147380BE460F9378D6D521B36 +:105CF0005BE7BCA0E9E6FF63B4443F7013585AA9C0 +:105D00006F30316A1294ED4629970D3C3859A73F00 +:105D10001F3B66EC5BBE43E62D5A7848B6D3DB1CCE +:105D2000BB6B961835A2B231E11390EB7F564C480D +:105D300073D8EF06EAC279BEFB5B00172C433F1A0B +:105D400055AB5C0F55F2AA523CB2506232CD8EEA8E +:105D50007F758090CC655729725E2225E6F794D82E +:105D60001AD8B5E053CE52CA182F8FB42AA674E3BE +:105D7000E397E8A0744F608CEDCD6D8549759AE48A +:105D80003A84F85094B130BCDF345709C6DCD19E58 +:105D900040DA3B3D171A53028C1EEC1AF369A45FDC +:105DA0005678AC8E003F09B916943CC8C68C71FF7A +:105DB000082E2893F227D731BED69EC2ED3E64A6A8 +:105DC000024F1D353E9169732CEBAA28ED9792384E +:105DD0001B005B13293F9C90027DF57D91F407CD5C +:105DE000CAC875F5061A87034EA119381B2E1D1C4B +:105DF0007249028312A6BADEF1E5B5BEF3FC4DECA2 +:105E00002457F99EDD96D9787B9FA78AF7AB43305C +:105E1000FD28E088FDAA9E6D7791D3084423F64DB6 +:105E20009ED3B79A9E589E037309F550B1BBF40AEE +:105E3000DC11638B33002C9F1C8E726B9E9B303267 +:105E40004FD08A2A8E6DA8ABEBA2A602FBF7C6A99B +:105E50004014B5902BE8AFA4E1785380066F7066CC +:105E6000516A773352EC0BCE2AB4D339770F6C08D2 +:105E7000C746E9B80787903A6A61956AC2D943BCB8 +:105E80007B530EC2858ED2E4B924830AEA0A3AB45F +:105E90000B7D7851D7727D76F423ACCF7829673AA1 +:105EA000E21CB02B9DD072CCE5EA8362C6B5B79FE9 +:105EB00098D041A7F3674D82CF0EFB3CB25A234BDB +:105EC0001374967CD966FA66C9395ED3C38AD796AD +:105ED0008168A8B76AABB3EF79E7EAC5C25BDDA01A +:105EE00037A51C3DB0E38D8377862C91A720A7DED4 +:105EF00011ADEF77A110C467CC297D9049E52CD274 +:105F0000F506DD4C0E797CC017106E07F026F70100 +:105F100095BE16615E230A1DDFEB53DFE648E149BB +:105F2000ED0E3CA7DB07428FEBB9DF1CC9C4017D36 +:105F3000AF34B11DC0CAF6A8B097B63BB9F69A44C3 +:105F400012A39F10BCE53136FF1C41287515E80DE2 +:105F5000BE64048F0604EBD3D56447D717AA5489CF +:105F6000235D363C3448DA482396438435D7CAE368 +:105F70007F23396A7D8AE65CA762098307904CC853 +:105F8000E2CC89395421D8C02DCB513CF41680E89D +:105F9000A62F69EAD4D3A2EC9C24F8C3A916B8377B +:105FA0008822DC9849AE89A5E3D0E86EF3BEC8909C +:105FB0006391F55F735BF084871FF743FAD037472F +:105FC000832D9452DBD1697B099707B62C14F30714 +:105FD000851540C03780C1BE77B9EA732A6D5281FA +:105FE000F0AFABF00C269A86F9B74C3CD8FAF685A0 +:105FF00001D373C87E0C7548DC9672BFC91CB05AB9 +:1060000000F6424908D9E3F9D2FA9384CC1DF85836 +:10601000F0184E3F181FFE92A38FF87F8E0D8F470A +:10602000B2462309FEF6DA8A26D62021690C21958C +:10603000A51E38827C9A66C4F5215DD3A99CDF8CAD +:10604000D78218920A88E4A391E234794371062B2F +:106050001B30D70997D05E2E14A62BE551107A0677 +:10606000B0C0208CDF1A185A8984A102A9C8E34362 +:1060700050679BE23356A319C6EE04225D8083BDB0 +:10608000D2F7D6056DFCD463BA40C1A4AF960346DF +:106090001BC9C5AEACAF2C20475636242969856C88 +:1060A000ACEE77CDD8603A6F1B8AAE6AB196379F57 +:1060B00035CD24D9BBF9B6E4DB3C7AFD2F3C9713F0 +:1060C000552B7D76CBF9261FB2F4E816159787FE7F +:1060D00096A89BA4676B17EBAFE5A0D85AE726CA32 +:1060E000B6834EAE7D27C46011FBB3D949AF944649 +:1060F0001779C63302C72A4E8D43FB396066375A7B +:10610000D8A3F22599652A68A3DFA73A4B536CB64A +:10611000CF9BBCDA2789C62A97F00831C5D512571C +:106120001F29C3FB1418DF60F0D164918C97894B51 +:1061300046DDA8CDD866F8F3D32157A084EBB29002 +:10614000EC9A3679FDDC3A55458639249D1AFF785C +:1061500002B6CCA5A2A232CD8CA3F2CE32CE3B7633 +:10616000EB6BF9CB69F2F6004FA344764A754177A1 +:10617000D1D4235780F0602D0A95F2B8B860FC7C2A +:106180003A9533FD12026DF529AD484B026C34820D +:106190006C6B52BF4E40847577DFF13389BEDCE70C +:1061A000517E622A25861E333D274F3D9ED149DA16 +:1061B000DD21B168F681B24858EA5FD5AC1C3BBD21 +:1061C0004E808EF0B05DBD8E1BC084EE8C2E1244CE +:1061D000B953F0BA70A70A945BCC0C52C11509BF31 +:1061E000630C1712152D13C18DB9A9E476D38280E3 +:1061F00058F80A939CD6A09300DE28103586801F9D +:10620000C201C66153AE9B3E6A612D19437DF18D7B +:106210004EE740A3CB770CAFA4B9F8866A0F2BD01A +:10622000E7CF96936E1ED97D3043754D170068BE3B +:1062300032F9D1E3944C6F316FC9CAEE97F421FA69 +:10624000D09CCD77F849DEB2147FB862C246152AD9 +:1062500015642CF2F3BAEA8FB6C1A457FA27A72423 +:1062600031FB2CD4DE288BF7DD56C50B14ACFB3488 +:106270007E2F945A4B82BD16C374E71424C5F85A76 +:1062800008E90367AFA7846843A1FD6C988E0E23CD +:10629000AC114E38D3A9ABDC66945FE372D1B8027F +:1062A0008C6775A69935A836D3EFA74C9583D96C22 +:1062B000A7C59EF23B851358535A10EBD5B6964AA4 +:1062C0006DEAA21195304BF80FE6A8BF7539DA7B5D +:1062D000E6A49FE74BF34AE554F0A53F608466A728 +:1062E0005B68A8C26DEE544791A63BCBDE9646DEB6 +:1062F0009A2296C07877B2449C16FECBBAA85E3339 +:10630000553EB7B0FC7FABA3E6AB1C09C07FD2F40F +:10631000ED266AD22912285A9250BAF98C4AA08DD9 +:106320000C2489807B2AE77C0D7C7D2B76CC007841 +:106330003DF7A3E71AF613C7BE48F5668C1CFEE0CE +:10634000B026B3613E4D7797AD9E712CBA7E0D6835 +:10635000FFAF5BAA541B231D2D64E714545DADAB46 +:10636000F9E9A7464DBE7BB495F7A6E9FCEB484C8E +:10637000B786DF9B18C7B52CDF43B786C8CEC60EDD +:10638000A09B77E04545A666358038C2D602661EDA +:10639000E2AFF8E9443CD2EDDB0C71C8158EBFEFDB +:1063A000D6E911850091EBB15983C98376D6DF5DBB +:1063B000EDF1BEF73CC86A0AEAFB896098D4C79E33 +:1063C000B95D863979DDFB5E65B0BB3B2B31BE8E96 +:1063D000F77A7087ECF8A468C94B3F48ECB4C7B4AF +:1063E0004B76536900C5CA8683245581D361003634 +:1063F000589FED3D251CC4559340DA83DF5FCA16D4 +:10640000F88CA0CCB01E2B9729D336EF7BC3ACCA37 +:106410004193E0CCCC73000B35724E4E0189B3FA38 +:106420002693728161F97CAF58C55F4EB957B2545B +:106430001520AD3A049A10ECDB254F000DE46650B0 +:106440009D45988E97054545517E46C020143C8653 +:1064500047A52E541FF4BB6225B76AB9C0F4DB21EF +:10646000DD2F4D36B2523700D8B5733E90D2B2838D +:106470003C95F794B5858C1D6F3BB91C60D89B6E1D +:10648000646EA36EF28B8B72120FBF1C1E536BB81F +:106490003A81B7FC6582AD5CFC9D2CE7F7D2344EA7 +:1064A000FC4D421FC9905079727520284F81913E52 +:1064B000B40E845735C8EB138ED7481C2B8DE4DB04 +:1064C00041AC45605FB4E52614A1912B05EBBAE61B +:1064D000CA0EB815CDFB245D870ECA1981652FE35E +:1064E000A85DF68A6E845E4C1039ADD2BEF430C71A +:1064F000A4F4DBBD3E9C5001D98E76348394B7FD65 +:10650000F18D199873A9B7E7C21EE81F5D24C11267 +:1065100013AB96F35BF70ECE5643E8CDDC9106F74E +:10652000EA1F5D3E99A5A848E606872AFBCF16B963 +:1065300060FE4B65D5946C6BE839C659930D9CEFA2 +:10654000ADAC536F5A0C6F3E12074A5C7BED71A9DC +:1065500032F56542EB1AA2EAF942C8F28A2B928E12 +:1065600063BB09E39647B32C0B3710FBFECB39F521 +:1065700084380EE1316C518038ECBF56D0EA1A9560 +:10658000808F23FC40C9614835E6183DFCB83CD0FB +:106590005A422B26056D9739490D78389C959DD523 +:1065A000F046DCB20D0B9E69CCC31D058FD7ED5CA8 +:1065B000F3F18519925E963168080589FE5F5FD711 +:1065C000CC46DF8F0343A349C0CEC76ECE6243E7FC +:1065D0009D90762FDE459F32613EADDD0461F06512 +:1065E00072A860EBC988FC8AA86472B6FD7FBCC73C +:1065F0000DCB002D8F59993E04B47C28252AAD5827 +:106600002FBDD4D52C91D66B8A0A310C7362C5008C +:1066100060BFE2D7168F621A10E2E9A7E1BE4D4DC6 +:106620001931126F667B8A763772A6C8057B128491 +:106630007F11955EDA724CB938D71A9DBBEA83C9CF +:10664000483261105940559C41187114128B0A4907 +:10665000774399141B96B21EBF2C01A807D5A359E6 +:1066600033E8BED53A1DBBE1382D67F198F9FA1031 +:106670001A2BE33BF21598BE4569D4888D76470FF7 +:1066800040263AB8A63BC152918DA288E1D587FB3E +:106690003DDE391F54742A0C7DE2D01E302532476E +:1066A00052398A4DF52F0DBB5C64211F2C8D47C3D9 +:1066B00032EE570A989C428DDBDFCEE0E9900E75F2 +:1066C000F9C7653E80C58A43EA9695592541EECBC8 +:1066D000AD51428A5824F7F4B4CEBA0F1C579F7EAE +:1066E00085FD83EDB2A53AB0EFC8F6FE52729EA9C1 +:1066F000985D8FC0851F2EFECF6DF066AAC0016227 +:10670000FA75332CFF75A8B25CF7DE089566325D2A +:106710006E3D6978C81604B0DB56D00D08FDEBA6B7 +:10672000F4A18C8079DBC7FDF382286D4F0FFECE7C +:106730005BBFB0CD02A8A04F626E1161A4EE12EA59 +:1067400009D844B36B03E31622D63D97FA3FCA57E4 +:1067500072B9EDD7A799285F5B6D8880903EF69956 +:1067600091AA9B07667B01675EF27459F33044ACD3 +:10677000B476CD1D601960E6FE19CD60A463742661 +:1067800035DF1A654A237D55F13EF1CF0861B5A684 +:10679000BBFBFA10F5C041128B9C2E77D8A50B3F9E +:1067A000BE004D9287972B0F446246483DD347F871 +:1067B000C78A57B19B2D06F30B869753E23E03D150 +:1067C0009C006A4D593B46BA9D939F08DE8D2E145E +:1067D000512AF06241C902770AB89A82AFD1C28EBB +:1067E0006EF5A13461D234A19C132860F43904C140 +:1067F000BC075BCE69B6D1D19079BB14B4C0FFE2BF +:106800008761D6FD8A07F7FB90BE6AD49D8B263739 +:106810005364BCEF771F6DFCF23D98FC94B3F821F4 +:10682000637E2B5A9CE75E20FEABB4314A98889D6C +:1068300009ED9B2015C0491A829179FADE2C1D437F +:106840008E5F8FED6BB46B8B9E60668C740ACEDFAF +:10685000F95528B95A38DD733B54B34BD0AA0B8A8B +:10686000F5EF3BF9DCAA6EFD64BA432731A28D49EE +:10687000639571A4082AA3B48798FB987ABECA507E +:10688000A9CF8483266609C645349EEACAC4D16569 +:10689000DB6F70602B205528F38933138932740E17 +:1068A00021D14D826BB32D47EB80E172373EC40A94 +:1068B00088A60DB91F308DF2702C25A822EF908884 +:1068C000F7196ACD7F8FC2D52BD4B8AF52ED52578E +:1068D000AF66C81BC46053E77B2A0EE1B819525952 +:1068E000539C28607AD4DFE05F6B1F432E434F68D0 +:1068F000AEFB2F0DC3AFA15D3FDFF6FF0CB09C6474 +:10690000C44DB72805AB0C5D552CF3CB2E4CB1D93B +:1069100070FB86A3230C1E578184530FF83F4D62F2 +:10692000D2971E3FEE0AAF7D79FDBD02DAD3ECE9C6 +:10693000FBC00BFEB3B06E0F917ECA4DDE89F9B37A +:1069400040A5C14B4CEF664458831834BE9D5BC7CD +:106950004FCA78CE4846BEBE101255A494BF1DC47F +:10696000DDBBF65E61744313BC8E3A58FCDCEF9DD0 +:10697000712067855F6FF024686A1557EA86C8A59D +:106980009A31D26C73C029D4312B9C043A0E84F412 +:106990005C2C1102C4BD899DC662D6B6470A214946 +:1069A0003A03275E704F37FBA39101551299EF57B9 +:1069B000FA3D9E1B9938B629C76C547A48BF94EDAE +:1069C000B4894322111CE31E1E1F104B2EF8D03F2A +:1069D000AE0EC94E7E1F37B1CF994BEA79CC85ED0B +:1069E000FDFDCBC4C47AD9B85073463EBAEFD10886 +:1069F000A9D79852D120BB8A85CE9018D95C1B1696 +:106A000016DB08A98F9E87E9F6D9D9004B7FEE499E +:106A100089184A52C54DD11123629F63F5C0A3DF87 +:106A2000368F2972668B1A569D10C70A725EED1D4D +:106A3000B87E00A8606D46AB9F283D2211DD672817 +:106A4000D02709CC143F1B1B00556DB10C1E478F7E +:106A5000351ABBFABCCEEB38FA26ED5BBEEAC5B1FF +:106A6000A73090781EBA4338F671F516971DE56089 +:106A7000877845F7691B5C2BC92F58799FF98E964B +:106A8000885848DE01899CF640D9EED8516CAE5E3C +:106A90001B5B35FFCAC8F89D2FBD1263228E45329D +:106AA000B64D5CE428AF6B2EDA355EB746D6C5B876 +:106AB000CB40F46C6E4CB6B6FD22880AF249CE7615 +:106AC000E9FFE5BAA5BCF9B413981034371FB03903 +:106AD000FD32B7D792285DE678A299B55BFEB4F493 +:106AE00092B15AF8D28070E8716699412942308D8E +:106AF00056146FE178BB6CE5B6B98E1691ADD6C26F +:106B000094A019F64F4EB1B60E068AB77596B51316 +:106B1000B07CCBFE02D7677B502476B7ED49B9FB3A +:106B2000754F4E5D042E75568D17DBB0AE62BCB549 +:106B30006C24F4CC8F11E259E508241EC451967FD1 +:106B4000E340F58DDBB4D1E93B286A0CC0ACB27FE1 +:106B50007C7F6F417DBFF4AF04FCA99083FFFAF501 +:106B6000855B74F6CD25A68BDE7A32C94EA9043337 +:106B70009EAA41E1999B2A426A415F234DF071F040 +:106B80003BA840B5A7E151E0E7228D08A1E9C7572E +:106B9000A1E9257ACEA366291BC56596F41D214D72 +:106BA0003CAD14F9463FF174EB11080688FE0CF970 +:106BB000A653CB230B08DCFF833FC0A3B6D2C71973 +:106BC0002C8474260D0D8E26D5E115BC3667D5A80C +:106BD000CE0BCC52CE2409D18696B71713DDB0A8C0 +:106BE000A9F22837A07D5F7ECA7EEB6805D5908824 +:106BF000F3B8DD848FA35B14EA34871C4716A8BB67 +:106C0000BF7B3AFED5A30927302D60557779EBBAC3 +:106C100055BFA56072EF9704F8B1205A4473698F8D +:106C200055822EDD1F8BD9F31F33D010F7F1AA7CCC +:106C3000ECFB46EC28A1BA791FD051B1FEA9ADD921 +:106C4000550052CEEA5063DE6F93B503AB6E2ADD7A +:106C5000DED04138E9E23285F08BC0E6505F46FD78 +:106C600097F46D9F01D6030DF742886B7E4FA93DC7 +:106C70004EE0B980767EC49D1C039AB9D77E5F032F +:106C8000D58ACE3930CA7F4354BB68DEB0B9AF4530 +:106C90006B95CA0214CC592C86D7D201CE412D3324 +:106CA00069657666B875CFC45AA165D62BC060DD1C +:106CB0000F76C93DB19BBDE452BAC68A78844F496C +:106CC0008C45B4C09AA1A0477F5B9C38660582CEF4 +:106CD000A1E6B4ECCEE2308FACD86B6B2E5681B10E +:106CE000D3C4A6207C4902F218D40F7361B14B556E +:106CF000F41272BDB0E9A186342E365E6DF5B4058E +:106D000009CD79626B7311E0496FE2860058E54363 +:106D100045B4F3BD3A7E30B282CBF595D4206CE217 +:106D20005AF37CA858DB5DD9A07EAF2ED0E1A7082E +:106D300017D88D242F91989DF27F93F41C867CA800 +:106D400028143E659D2D45FFF8EAA4163A7AB7F956 +:106D5000108C326FDDDEF45DCE9B0F3AF3766DF072 +:106D600059D655F047C76F1D444AC6BAEB28ED63A4 +:106D70008D4239C7CF8542891CC9C934B898F2D52C +:106D8000E693BC57C8014CFBE37BF0075FB0E1C55D +:106D9000E9C868D43C87115410F9D23EE1F769067E +:106DA000F0E031942E62CC3F2F9F50D75CAE7F76BF +:106DB000EBB09A21A5D1D903DC63C07EEE30063C4E +:106DC0008BC6FBBEE6C65549A6C2AC8FAFA003D0AA +:106DD00098421D270822BE0009FC5CDB1180D9EB1C +:106DE0004C679D173ED761C724859092746CC81E6E +:106DF000C70E2F1E74EA172F2929426DE49E35A372 +:106E0000DEB88F24FBE499CA646009A3CA7CC15D23 +:106E10003A0FB134CE15D497D2AF6234186DBCD4CA +:106E2000AEB3E41BAA1FC5A1F135317F8C01EB196C +:106E30009A3C1CC8BD715760F1A472F394DE57AA46 +:106E40002E70DAA462408FBB3C1DE14D187657B519 +:106E5000873939941F3285CAF5EEC29503AD436672 +:106E6000C2BCC5AA13DC83B418754BFE972DA65976 +:106E70000FD354CD9680B9B299E4E349EF1F6A96D7 +:106E8000E58C89C1F5A7564CC00CED8172DBCB03B4 +:106E9000B05DEF7C75A44818FACF9CEF1241E25424 +:106EA0002502B5D2C299B9B91FC988A33714B18FC9 +:106EB000F55CD83A42F884BD39BF27058C9D172868 +:106EC000226A759460136BB8E17FF61B4728A5060C +:106ED000C870BB02EEA630FB1A3C030997635D0D38 +:106EE0001C6E9D3A629E49CE82D298373973B29910 +:106EF0006ED5E83A19A90B7AB2C03A63B368335732 +:106F00006941840BF865F2E07E0B04ADE8E3B92A31 +:106F1000C4193F9D814282D978788E286908A1776B +:106F20001C261247EC289853026F037CBF9B2E153A +:106F3000017F519CCA0E69A1D05BC0DDEB3869DCD2 +:106F40002D3EC500DFC1519E0633CAA5A02DB55107 +:106F50006B93F3655B8FFCC673D6361ED73CDC4D56 +:106F6000C4927CB96CBF20A44F69A91A3821DFC62E +:106F700029E0ECE5BEC5F41E85088E45606AE8345C +:106F8000ACF200D8FF998C4080930326E51546D2D9 +:106F9000676E9600BC14B4C4BDB10D48DF5655CF22 +:106FA00003AF98B51D5A04A5D9E96BDD6705009BB1 +:106FB000D1ACE666E9ABA3664847DC033C90698147 +:106FC0003008AD95C4D515F17DA3B76E79A1A9762A +:106FD000428DED828FDD6DD322806C4CA790E7C689 +:106FE000F38BF449BC6A33E57FBAD8BDD764A300FC +:106FF000126EC6E779BCCF0CFEB09BA0A13D49C480 +:1070000090C4F3B4A0D3C2E901575976F862CE9781 +:10701000DFA9C6C6FC15FCB0498B4D1A08F0E46523 +:10702000BB240492EE33E11A2C7139A8F14FCD073D +:10703000E6FFA71A879351A5318A768B69D18B7D9C +:1070400093BBAA9C251B96D9D8554ADFE2C53DAC17 +:107050002C8B5ABD86DF27E9BA3E3A88C22E3322EE +:107060001F6CB29F50C8EB497A84A26C1CCDBFE064 +:107070009340B6AF52A4856AD9B54E901BD8925EA4 +:107080000358600CF0A624968D7A83D2254FCEB794 +:10709000A6F11212A720FFF55774FB6236F23C6D81 +:1070A000DABD940CB969BFB0FC436A245217EE777D +:1070B00080516AACFEAEC710016F3F6A1EFEBAEF88 +:1070C000678BA93DF9584FD49F7CE8B40EE4B50313 +:1070D000CAF7D96AB74F84C537A4F89FCB4AD2F410 +:1070E000A0D8C445B71A16CFB962451DB72960F3B9 +:1070F0006D9F3E37E0B67F44FCA15E34715E9266C0 +:10710000496FD768909B4C6B432CF69E41973CCDC2 +:10711000D615F6A25A81883C90ADB2F787C5D6EE57 +:107120003CC12D9C33380E0F2A04DC169318DAFE6E +:1071300010445B100251AAB950D24DCF76E3D9DB8F +:1071400080B976B8E8C69F7D37D2FB2DC6476E74EE +:10715000FCFC1118F4D1AB09EAF52004F851F81041 +:107160006A80ADE6D78C97738EAFCC10D64FF7CE32 +:10717000D85382BEE05CAFD6E510CD34BE7C36D5A8 +:107180007E94D1C4FCC42FFD09AD67C24E2FE2240A +:10719000F38AB5BF9E4A84079C6C9A9E6E8501E671 +:1071A000A39BF3AA9B3FB25AAF530A095D7A861894 +:1071B0009404D965A476BFF8B4B29DEB11E29F8A1E +:1071C00009FFA57069633A1B4B3922CC9431CE2E4E +:1071D0008B95CCCB0F75EFA8205AF637515F7AAB61 +:1071E0008F62B5B0C22E81BFDB4F9BD3FED4770434 +:1071F0006DD5462F261432B28174E3C5AE5601E434 +:10720000E201EB6FA4F277362A44CE4081D254BC1F +:107210000F3DA2E43BFD86DF982DB40210C67961D4 +:1072200044087700AC864432CC85CDF34EA57C5023 +:107230005E63BEA21C86DB7C3ABDFD7EE059A20CDB +:10724000D7F7084632AEE9844063D08A7019575D9B +:107250002A5CCBA74732EC45D9C35A16B255213F19 +:10726000D5DA7EC51C5FB2BE2E95CCE188E3A28C38 +:10727000EB068C1AD372CD97D2D65CACD2D8DF365F +:107280005608B3B6CA58FDD81A4DB9F66C95C32244 +:1072900032A451A559A008079688C2B64F25DAC175 +:1072A0006DDC31ECC12FB0098C4B0D123AC403E5F3 +:1072B000A9F5DF45406A1C2D6B33E5BD4A8F383B8D +:1072C000502727F8FC875035D3417BCAD4334A9DD9 +:1072D000E54B3882AB714272EC269B25CF64314678 +:1072E0000395FA1E8793A3379812E97798535EA403 +:1072F000D8AC53B870736B398E1F80C2DB94BF2338 +:10730000B320C62B2A942F2EA680CA18FCEAE6C505 +:1073100054CD7BA6B83444E43C2ED93C35F29015CC +:107320006E7B2E4A9F30F6BD0CE7E61AF9574E40A9 +:107330009DF2E04350776C8DBB726333150688FA7B +:107340005B057D378F134962293DFDDA7EC485A236 +:10735000F32E8B130A0596C368B189BE8D545C5E0B +:10736000691A7E27CD8C59DDE4F71CA9F61EE5D3FA +:1073700030DFFF132CDD0B20425E4820C7FE0B0CD4 +:107380001683D18D07E3FAA431C9469CF5BC64B2DB +:10739000A45A23731C9BEC7C9F47E81811E9D6C8BC +:1073A00090A5A87FFEAE22475E5F98C936E4FF84B1 +:1073B000796BDDBCAB57E0F85B37067274D524A758 +:1073C000D6343139C768E5E7B603D7920E95C701C1 +:1073D00019966CAB66362E3F1DC77D684A8AD73E2C +:1073E000C7DE5F58CA43E3FE128669DC781C72CFA1 +:1073F000F0CC4107222FCD5FBC283F6E1F91299012 +:107400000288D3C55A89235A26AA69840E273BBF0E +:10741000AAF9064EE1C322A7C953414B9BC8C4C772 +:107420005730C5DEF17795898FDBD028369DB8853A +:107430005F19A3E0BE2609D8A844A1FB301E40E78F +:107440005DD5FBA428D7621E570ACFE0B31BDAF044 +:107450006132FFF5DF91472C775ED84328E4BF9671 +:10746000AD8092989A5CD780B75D1F85D767C210B0 +:10747000C36AB1D5193E13C0A4F82E6FDC1D1804E1 +:107480002B59685C751C1B3E906EED885BCFD18AD2 +:10749000AEFC52179067847DCA77D9BC3530A0B452 +:1074A000636F106F2F625F413E1985986A85001BDC +:1074B000F7B34F6349858B5A0A3FFB722838E50CB6 +:1074C000252D26EB4A410BA577C3F4BF5C3A30F17A +:1074D0002BC4F6C203A3FC42C8CB40EAE7D7857FA2 +:1074E00015916A03F799BD2F473FD809D8437263B6 +:1074F000E47EC75D54B25D867D96568D3902C171BA +:1075000019CF3DEE295614BAB92692A9897D51C0EA +:10751000B8A2854A202B18243AA889BC8D21D8F21C +:1075200015BB93306212F2007682662A4417B65F6A +:10753000DB8D5590D0B4C0200596DAC800D1DA8C26 +:10754000D56042B9920A45752E363C6DE8F3A9899B +:10755000D049C29413D031F50545C2C9C637DE47BC +:107560001436D63B7A1A06BE6F19853133F76DDCB7 +:10757000E07C445B0A295A22DBA884A04246DE5CF8 +:1075800036202679B3C89351F561AD2B58218CAFC5 +:1075900065B4484DFCB3188AC6774BA23BBF1B1C91 +:1075A000154F64DA949D73F80593402E2D8DD811F4 +:1075B00017DDA3F864AA33B0037EAD3D0ADAC9C172 +:1075C0004C1C9AAB562D673571CE5E726CBF674806 +:1075D0006B707EDF3355EC5D528213CF608156B203 +:1075E0005542680B41140312D2255125554F265A96 +:1075F000F5B2574D7522E2FEC28C709076C1D1551E +:10760000EBCA77D5634FE21F1C581926BE9C1D5E3E +:10761000A247C3D664060C491CFFDF33FB7CF53957 +:107620001DB769FE17F36E406D4F06D42E90A0F083 +:107630005FA17B30E121168DF30B027B91A4AEF5A7 +:1076400007EAF6F35F87D40266B477A84687A025D9 +:107650006E965F3F3D3A917E6AC2F8B008BDFFE882 +:107660004C0FC1059F0B7989F10C0BD5D5C8E98961 +:10767000811AC01F3BCAE6B5DD788FF964148653C2 +:107680002D98A6986390C3807BBAADA26CB18F642D +:107690006D9138EF3CA7777FDDC9D8F3E015451C25 +:1076A000B01318055D0F872D26B1847B73B070CAA7 +:1076B0006ADD8FC91C96B7F93D45BDAA059FDCD18F +:1076C000FF9F04FCEDB923606EA54C4A6DDBF8D139 +:1076D000F3E55B16E32EF97CFEE77587E693B3C10D +:1076E0005592AC8DD8A3BAF70FCFE361B1D37C4EDE +:1076F00051B33213CBF980B3E5B8CAE0FDAA121F2B +:10770000A203771AB3DA66FA14C4C4A3E2C20A3831 +:10771000363DBD568F3B39807741DB802B1FCE7BBA +:1077200033810DC3173096C32A64840292C51AF7B9 +:107730005E62426975516E728A969DAF1CFB665CF3 +:10774000A5B9E001959D84514FF74CC73DB4850D17 +:10775000D3C25C57C7F68D83726B1312B2AFDE04CF +:10776000FBA9ADEAB1D398C8F2E37120D486B00F7B +:1077700098AB81DCBC3E2CD73A0FC0CF55496D3554 +:1077800039D3E63581D05BBDBBD713D396FE558385 +:107790003A92C1FB7E6E6494B214D12264341633E3 +:1077A000F9BD85B67A90EFDCFE9FA4DE1CFA8969EC +:1077B0008A384E99BD68FA2333B92BEAF8F86D0B75 +:1077C000325E8C1F9F7F4B76C95621484E7882CF00 +:1077D000C3C1168DE5A075DCE777C719753755EF7E +:1077E000163C1FF98DFB2553FF249A4F7290566F5C +:1077F00072692BE6C94B087EB1BB969F05E8C96547 +:107800002FCF96457655BC1E26B48D089A0D49910A +:10781000555078AED092931FDDD74DA19BDC4A39ED +:107820001A2EA49BFD6185B148956F3915F929DBA6 +:107830006F7A7EC303CC8F34C561FA5EAD2903C570 +:107840004A0FA9809FB5363BBBAFD1BEFC50B2CB2F +:10785000AFC4025266A5372CA0217EA999EAB5399A +:10786000E6C3A11FB466642F1C5F0A440DCA767F6D +:10787000110DE220584AACC8F3DA50A007D12F21ED +:1078800040C38883BADC903B2071107D8127A7EC30 +:10789000C8F39BC840ECEA00DD701065FFBE4938B4 +:1078A0008DA036FC9D7D325286BEA7C2A1BFA4A585 +:1078B0001400B9B385C2F6517E433E75120975971F +:1078C0005F56DDA6324E374FCB6A9FB631CC2FE4E0 +:1078D000DEF0E7646295681A025D875163B9FF497B +:1078E000DFD911A5D4FBF813F39A5ABDDE3937F16D +:1078F00054CE53B9002148AA9D4544FFB92523B26F +:10790000AC5AE60FDC62D429FEC47C2BCD396470FE +:107910006CDC8938FC9B50171882D3C9C4EEA15582 +:1079200087C66C9E72F997ED6DDD94172FD18A7022 +:1079300016D9D2E61C342E3BFA855E2515A73328CE +:107940008CE60E0863E486932BC573AB28C31D0534 +:10795000A4BE05E53F05775B009F7E5CB3F2F9901E +:10796000B2D71116B99B04C679DB9BEF0E9A28019A +:10797000672CFF01AA7917FFBD4DA59D19D10DA058 +:10798000C8809A753311CCD166CBCCE161FA52B282 +:1079900022E3E8CB15D123F096A5C8C19EE129AC1E +:1079A000E2659B9A3375B8984C4C5199D293937376 +:1079B000DE175448428D0F45F269CD3955D97756B7 +:1079C0005D21DBCAE3478102E2EC6ECE268EA63E45 +:1079D0006E2E83F6CB1F47E7457985A629DDF89EF5 +:1079E00006706D8ED1B631474DE518B36388437A82 +:1079F000029E8B9C8ED23A7C5EC2F26EE4A2A215ED +:107A00002880D720BCCD567CD356A79338209CD055 +:107A1000CE7FAAD90CD29D114B3E4C0B8C7862EBD9 +:107A20004E9989013D3423D106555730D43D4DD070 +:107A3000DDD8FD018D54C002DA6357F547C7DFF684 +:107A4000107AD7200FC8BF1809D51422E399F4255E +:107A5000882A87BB159A814F2D1108069D01864102 +:107A600093E95D64C9861EE560ED004BEFECDEF343 +:107A7000D5465612F9159B95E4E56F3A76CA859E70 +:107A8000B3981B85B0B730029DEADF128819E21463 +:107A90000EAA0F3C6BC12D8BD970761CC84A1D698C +:107AA000E569F5468DF9A9A41117005E6074629F1F +:107AB0000A17F39776862766536A8F0213BE936779 +:107AC000BAC667A4187B8C820BA48315B2EC41C59F +:107AD000C463E8AFC315239AE8A66A6578EED8199F +:107AE0001B1006EEEAA0451071930A6FCB35D95AE8 +:107AF000E030C40C7861E7A954556113AD1EA9F6B6 +:107B0000B4FC02F53C9E93596CE027669252548A6D +:107B1000F68560B248AB0967A91DB6604D7981FE54 +:107B2000CB6C2B44D1228FDDE6319F254EF57FF9BA +:107B3000BEA5A0645974602904E322ED2B0882439A +:107B40003A57B3A5C846703D31B537D8EB0D8125FE +:107B500018BCDDDAE01C6421BB6799D53B250B2FEF +:107B60005CFD2CE19F13CAB3276EC16B6C628C9CC9 +:107B7000A7BE60C5396D6B651CED2A7BAF8A19AD58 +:107B8000320BBE3035B1B27642346A803AA86F66A5 +:107B900065DEED2812E4BE150D4A61EF540DB6A95D +:107BA000D530E85047DE9DBE8414433A3E7FB52A67 +:107BB000F4D6E989B10C32876666CEE21CBC93101C +:107BC00008608860057F960F815F49CD54BF3609F4 +:107BD000781964417F7F54020F68B356C44C2AC69B +:107BE0009683BF2D917136987E3FC3816A79804418 +:107BF00071B8AB8E3BB97625CA0D4D1617AE59221A +:107C00006C4A24FE82504753EAE9B8982DE29A273D +:107C1000F00170F2C313373F3A1AB5FEA00FE167C7 +:107C2000FD521E348443A4771294BEB85A4B72BAE4 +:107C30000BD15C8ACD6824D8A9C60EED50804EDFEA +:107C4000B47931BF7CC385F06EE14A4ECE1EA7A445 +:107C50002AD79F3F80480BA6F255BF21B77A68818B +:107C6000BE5A686D2957C9F992565903EEAC6CFAA1 +:107C70001F45B810C57C28C6D84F21EC1D55A8401B +:107C80003EA043BFD07F7762A78388A57E91A727B8 +:107C9000841E8193660C6E63414B47E8655DEFADD2 +:107CA0009C38A6371C1C5EB4AB18DACAE652DFE17A +:107CB000F6E3F7ECDC9B08B5429689DB5589F8754D +:107CC000F1B7F65591F1B2E3330665F2E5EC4B8F6F +:107CD0005B17BFD6C3FC2B88124F6AE988A66BDA04 +:107CE000039C8B108B8D5537BDDDA1E520EBB009D2 +:107CF000AB57B8A5979C66E8EC67B37C14F8D13312 +:107D000076A784F51E478994206C9200F18403AB1A +:107D1000DE22C44658246B96EB2A85D2FB4C7B6648 +:107D2000589E6EC2540EC10E70F2370D3241C3E937 +:107D300020C580A4FDBEC5EFFCCFCEBC30E29A7951 +:107D4000BE15BA63ED25A00A4C3A28A7A187238A5D +:107D500031AD73C57BAD57032907527807F7C28C45 +:107D60003327C7EDB1B76940D8253E08A173D6AA1D +:107D7000151E72E37AD72D7FE2DBBC5F356F1F3AA9 +:107D8000153E02C7C2BD495BD276DA3554036EBADE +:107D90003A726E5A0253C1D8F92ACC61933B73A24E +:107DA000084046F0A333D0D8595174B3D501976F2A +:107DB00066179B865A39A50273D5CC2E7CF616D74A +:107DC0001C8B22BC36C2A2A6A059B3D3EC3111E65B +:107DD000B26A67DBD133B31BE08831A86A685B0EF7 +:107DE00026888C8A95761AD6A3E5F247C561ED2CD4 +:107DF000ED291B435D3B45540AAC034B14FAF5D601 +:107E00009D37E3D1792C800C381187CF95D54C88DC +:107E1000E566768901204F3144049A78ABF5964B9C +:107E20003388DE06A1087B1CDB602765A498D54754 +:107E30009A2F0DADEC9146018B59FC6E852A66296F +:107E4000F562873D3B3437490328D37BE38DF38AC2 +:107E5000CF007AB82E07355D31C77788B3FD6B4701 +:107E600073A98390AE1C04B3F937903B70C71B5CB9 +:107E70009E329E257DD2C059446E3BA2C978C7B3BD +:107E8000FCDC93E2F0B3AE47D5B7946B788E71FE0D +:107E9000C0B289B4EABE1C1D2943387C237525C6AF +:107EA000AFBC890B116D13902987865C2424545A2A +:107EB000EC647B439002978AC608BE4ADBC3960CEB +:107EC0000B8ABC16CDA827EE82407FA895DD8502DF +:107ED00031CEDB958C5B3C0F5AFCFD3C9C975CC320 +:107EE000FE79CF7A86D53493092D000190BE59EDE5 +:107EF000B1E4E0F1B82B0C3C24A4E6230518C7C27A +:107F0000941E5B0995658E3B3BD8C3137207AF2F58 +:107F1000E51E29F1CCF1E2BD8AAF5A81B64669F37C +:107F2000133B47106937161A3E3EF4A9DED2F2F928 +:107F3000A6AD2B5CA8115DC9D3FD6815FB4803AA4B +:107F40000D0B810A2036FB9C8B132FB3A11A588589 +:107F500076C7ECEDDDA1932C5C7A66B3F9FBDB967A +:107F600071EA68379535FA5C8F1E4DFFF366DA5774 +:107F7000CBC125D478249AE5AF0FCB5AD9FF7964C9 +:107F8000B7FF61349378B657330153FDDFC7DEAFD7 +:107F9000884E7E13D96BF1206A0E2C9156BDF606E1 +:107FA0007E71BFE618DACAB7458A0C6B265505758F +:107FB00099E31AB1350D49E06025325A630C2E8AD7 +:107FC00072ABC765EDF999374249BD3D57249166BB +:107FD0005B50CDA1C69058AB051CD9B68C4BFB307D +:107FE0005C4B02CF3BA56CCCA8666271425FBE259C +:107FF0001BEE69E3FD772622465D47EC6701121F01 +:108000007BF48DB98FE199D7291D09EFB7F446505C +:10801000C0545D99B00F826E1029905F3F474DEBC1 +:108020002077FC5C774308509C9EB075AF1C38EFFE +:108030006FF5B4E502A64D675DD1FC2F7B660C9F02 +:10804000DB034BE7CCDB3A3816D4AC7734286A2D07 +:10805000BF2B6D028AB97F9367A7EA49B259E10E37 +:1080600006B73B7D355F871DB3CF5526A7FE11911F +:10807000A3392A6B2D0386D3BE207401BBD8D05EF2 +:10808000C0DAD4C8F1841F15C12C23404DD310D9B8 +:10809000A68098D6D8852418A41F5C0092EC174EB1 +:1080A000F8F864190B630725CA4839394CF3D53BF6 +:1080B000DDB11E2009688522D340934627B203B361 +:1080C000D05302451D0C4D103272E34E7BE04E0141 +:1080D00042C65ABF100458EEE3DFD42907AD4F4023 +:1080E000A518CC64F39A0E175D2AD5CE5CF9B8D8E2 +:1080F000553AB84856371047CF14658D97C6453F57 +:108100004A8A79DE3FA805C0DA202C480D69301F65 +:10811000C49AFD95F284E56DE31A9167B8D5A34E34 +:108120009B5165AD216210B20C81B992A2F3878791 +:108130007D61302B56CFE5147B37009BEA115F56EB +:1081400032683B02E4F8A3930032EE550B3BEFD1CB +:108150003D03438B612F5CABFA63D26C04C0DD0539 +:108160009E4F379227AF390D2134BF220ED4A7D8A6 +:108170002B9EA40EF878323B59F9B9CDEF893949D5 +:10818000B68A9FDD39475C6B806444AE10EDF659CA +:108190001AEAEF7627281457FBDFF8EB2A4026AFC0 +:1081A000035C71530E1A3F033C7490F191710618F1 +:1081B000A183D6DF74BA17FF5BC105EC65572A5758 +:1081C0004F464B6893C49BAD823777DFBC680BFE8C +:1081D000F0671BAAEE2845B4F664AEAA997942CDA1 +:1081E000D4958C9F498283C590909735F0FEE5AE7B +:1081F000FE4940CCC5323B94DA3DE1E0E41C079DEA +:1082000051FE94CA00D65B302E780DDF3D38E195E3 +:10821000F51DD60A0918AC12B22B2C54A07FEFDA48 +:10822000EAF499AD185F5D6FE539879D24FD084339 +:10823000CA2D6D17B0B0EB183D3F80C9C7BC52EED8 +:10824000CD0A72999F6A276038E2321DD16145F5E7 +:108250000E6BF97FB4114A99F6F7035FCE981608B2 +:108260006B37145179C8CD7671933657DC3B751C4A +:108270004739954A952560CC9E3A9C70C67642D681 +:10828000768E0218F8791C8833D3B8F59A05D3CCCA +:108290000DBB40077EE03CA6FECC95862663101BF6 +:1082A0006775DD61BBB0674C7AED8843ADF935D7B2 +:1082B000CF8FE7633FD25B37CDA43EDA1B9185CAEF +:1082C000ADDFD970BC3E46A90523B580B568BB407B +:1082D00017C34CEB78AE1FF3BA96BF050102633BA0 +:1082E00032BB619E2FE26E486A3B6011A83348EDB5 +:1082F000B10EAA37F2E5C0B2BA1971DCE0D3853607 +:10830000F194BF547CC278138229B757B49ABCBD8C +:1083100023FA9216438E64A940DD83B3F3FC9CFDDF +:10832000B97B0224C7BCDD113D63C413EE05CB99B4 +:10833000611536A24D59A5BF7A49F34CABA05DC477 +:10834000F3977E85AAC94896B23BE613DD1A2987C2 +:10835000104DF62269B68A7FA4E3A611635FEE9002 +:108360005A2BBAC3EC646C21C891126EB75010300E +:1083700077477BF44426440ADE6BC809C9D8AAD9DA +:108380005638C8BB64594F998D6B6FFD2DD1CB69A1 +:10839000CD7C845CA5FAA19E848B9FE3842EF4B1EE +:1083A0009CDC4523F07FA42A9BA10D458AA3FDC632 +:1083B000291D0C8707E21734196736D294550F0B25 +:1083C0006B4FE44D16163C0C36EE32CF2F97819250 +:1083D000D35F8A408E584956B068C3E64005C33D16 +:1083E000C422F8818C9A45AFDCB27F2AAA6C376729 +:1083F000BB315EDC18E5F610E22CEBF1FB0B768E60 +:10840000BEA240771E8D70EF3CA5D009F8B276DA97 +:1084100016EAD8F047735C9F2B5D27C008C618800A +:10842000AC2CBB2DCCB7049A411E4AEE2E4602E678 +:108430006B07E77415DE46A2BB143CCDC8DE55EFD2 +:10844000E74635FDEE2DBC00CE3BE4315E0B4D041E +:108450004CB92B67C0FDAA034B09D13700C1793F46 +:1084600065EABE3D7D23E5C7B0E04B20C2C3D6A57B +:10847000727AE40881319B66F5F234F105CB2B6A00 +:108480006875E987047DC429C0606FFFEEE2B02003 +:108490000B36C463DC9D9343D3904081BE2E035AB8 +:1084A000453F5468FEB7D41EE2FC090DB7C5A6804F +:1084B0007B050A92DEC005F2CF94F0A1ACAE6BB1A1 +:1084C0003F7843AF1922C5C7E3FF8C54331BD6371F +:1084D000B2AE0C042368F38BCDCACADBC72BDEE730 +:1084E0008FBD502E63CA620465EE610C961C38394C +:1084F000D7EE9606027CC480E987E9DA2AF11C2BC4 +:108500008401E86C6EF2503DA1DECF58DC177F4548 +:10851000FF9EA5F36F7DD00ADF0CABD88132C63148 +:108520004D47132AF344AB954DE3F3038E23BB422F +:10853000E0A846A25CDB651E5BEA9265ACFAED93AF +:108540004070B9FC766F268409BDC83481679A28CB +:108550007BD153BDC238BF2302CC715AFFF6D72F4F +:10856000C378051E4F6A695AA82E85C421CF61E5DC +:10857000E49D6B9C8DA3FE7DAC63EBCD3B793A9083 +:1085800013A04911CF32B1284DFF547A5468FBCB68 +:1085900090D68CAD7215AF70E64EC55ED9213F3EC8 +:1085A000F3DFFD92C006A857997685589C32C3E741 +:1085B0007826212876482EE68D12F30902E8A5993F +:1085C00034E12962BE629C2894A35475E341396367 +:1085D0000B194613411EF5FA4F88450324928E6706 +:1085E000C76C0A442962F047C332509A65E9A6A2D3 +:1085F00000E11193D6E9CF01FF013E59E051025B42 +:108600007255B311B1E5C9550E8423F5DD89708C1F +:10861000C1905B73A3258E4FF3A0FD98B604F1F0D3 +:10862000635BB1F05598B58A83947CB04F9D5748F1 +:10863000C1FB4E5EDBDF35B933AF95BFD5F632D81F +:10864000F4FA47A23B109C88E59580742DBAF88512 +:108650001944EFB96EA5BAC97F54CA3EAF6480C74A +:1086600097628A9816B1FA46ACD7BC2164277C5031 +:10867000FCDEB6FD16B33D34F4F91811351943FF8D +:108680003AAD3B5D645BD699530C48E8B0E1765453 +:1086900028775353578872AC26E069704D626E8C10 +:1086A000E63EA36F82AEB0CFBFCF63EDC7E3184FF6 +:1086B0003A5AAB7586A20ADA6D6E5F406E9D81E80C +:1086C0003280463908529EDDFE39EDAE67F45CF625 +:1086D000BA31818844282EEB2668B4D57EE5AAE31A +:1086E0004E6C620E7A8079563BA221FDEEB90715D9 +:1086F000BA324E7172A223EE95D33EFDED3A189434 +:108700000BBD3827617F7AB5A551EA9E132DA1DCF8 +:10871000D5D944047EF842A9FABCC36A22FF749BEF +:108720006DD02A2A29C51DA0769ED4B4AB1DE6853E +:10873000E12C699F00A8D69C8C208E91C266527253 +:1087400035DE3E62E49C9363E50CD4EBD8AC85281F +:10875000B66E596104BCCC2F6C66E17965C23CB23F +:108760004EED9162BE0DDFF6CADDD0028C9162291A +:108770006287EEAB815EB04244A1457E4275BB2369 +:10878000484A259F691832CC11D67721E796448054 +:108790001D617620AAF11DC205DED85D739BBF3B2B +:1087A000F0D3351AE0DB98EB485E00B7F6DB3545D1 +:1087B0005CFE69B3D4E892EDB603FCEE022780ECD0 +:1087C00005127B103A330770B43B73CF5D617C9523 +:1087D00054B45DE3060CFAB39C004F9EA63304EE3E +:1087E0009ACB258E5F336B2B59B6E1D51C9DA7CE56 +:1087F000946875ED55D304F9ADA46097A55AC933B3 +:10880000D57EA96BE04A45EA6AB7C42F4714F30E38 +:108810002EB35AC19C95F1245990AE7332C9BC89CC +:10882000C4E25945907C49B88366AA3CD31A3E03FA +:10883000B4F736D839B7E694138EC75BE5D8D915A7 +:108840002C86158B0DD6F86F98DC028E38C9691806 +:108850002E175DF20497E4E2A0BA06263BAF593327 +:10886000DD365CCFD04E56103AD869C98D040CB1B4 +:1088700082536A7A4C1F3440403EB7B2C909E1497D +:1088800007DDD0429678583795BE7481E1A9CD4076 +:10889000A14E2DDE99222AB7C64E13B93D92DD694D +:1088A00048B3629FBB42530797833774C9B83436C5 +:1088B000712EE4F0C2EADCE7EF3C75DF264E43821E +:1088C0003D5DCD83947FC2C163AD26F3BD9DFBF4B6 +:1088D0005779146E996CD80247FE30B03AF046F0E2 +:1088E000FF0FD9D8DF2964EEE21F95627E2F663232 +:1088F0006EADE03CDD01E47CE7304CAD48765B9B3F +:10890000BC0AF213ECAB353E1CFC49C24FEE42D61A +:10891000BBDDD45EEEBEF9A7F6A158CE12470949D9 +:108920004C6293DC0CF100EB534779C7C1F3FE7E38 +:108930004652B711D98FE2852061A886702D5198D3 +:10894000C41E1C90A9244215B81378B3C40BCE9949 +:10895000FA0A96D0D041BA6B51D85EA1740CCC7E85 +:1089600023BC2F99932CD2C8014EFAFF8EBE915F83 +:10897000CABF2DFCF6B0EA08C73A88B7EC6F9B1760 +:1089800005FB0BB8710DE408FC31BCE07425DF3D3C +:10899000E1A9EC394E5F21D18D054D70F034783569 +:1089A000B24500908D64223D73C15DB486391330A9 +:1089B000D3C1E6885CC3E56A30C9E74C916DF72CFA +:1089C0002BDF81738710D33718DBFFEB48DDC23113 +:1089D00021CD9564FD7556BC0D079626A53E9DCE0E +:1089E000958B65FAAE558E4F13764C87EFCBED6CB9 +:1089F000702B29630C20F5CB91817DF610D653A204 +:108A0000B3CA404B800102FE0097A1813C312FC1C7 +:108A1000AC2E65F880B12E06293D94902AE1A28AF9 +:108A200049E360C104721FA115D0B04B0FB082FCA6 +:108A30004DAC58BFFF5772B1B91B142B238D2EBC00 +:108A40000ED3F7057E620628B431659D52CC2CA06A +:108A50000629779194C21390B43CBF6431C7C774A0 +:108A60002E3B4F57AF92116ACDB49A4C44A1F0B34C +:108A70002E456CFF6318CA112BDE9E246A788BEAA0 +:108A800067B2DD88797C5D1DFE6A713EF53B12722E +:108A90001626182022EC6B0CE24BD44402402876B8 +:108AA0006104C4C5D8448BA062DCFE9CEFBD9C8BE6 +:108AB0003B6783360A0BCFDCD8B8F4822C27E09AC8 +:108AC0003C245B49E98EC55A5C33A82BEAD68176F3 +:108AD0009FCC0A9529D7D188BDC23548DA7227AD17 +:108AE000CD0814B4C8820D33A175990C8ACBF71D3B +:108AF00039BF764AB0803BE89CF54C521AC710A8A3 +:108B0000636FD00C0A84705AEAFCF2D5544DE5F537 +:108B100051D7EBC418616F4A2259EE933DE93C0FDF +:108B2000523A157896016FFD4A6025BC8AB192537E +:108B30005762E5B9D963AEA2548FF95B049C32B990 +:108B4000D948E2146B35F2BD70688880C6607781C1 +:108B5000A6A4404DB7DF8577A846B1F62EBB2CD032 +:108B60005E388893BE2EE89F7F54729BDA2479206A +:108B7000D76CC07E7B80C74764A3CC54CB93BE3FE9 +:108B800059712C147901877D8CA94263B6225ACB86 +:108B900008BEBEE45AADF9F7070150816A4808E7FC +:108BA000CA7FCE249C7137EB91D2CE8A4B6F04CC16 +:108BB000A5BB5CDA99A6F06543E3A32D8D43347120 +:108BC0002CC1DD9DEAF9254C8CB031236C7271B556 +:108BD000448907427601E537433A6C6CEF6D4D0AE4 +:108BE0007396826638FB36CFB30B7D6551D3989769 +:108BF00073B7A1E677E6940F21A44C3729265A33A0 +:108C00004C12835DFA622295D4DC234F2545CAA11C +:108C10000105D07E84AC5A4A4B8CE5C4C36F1C9CC2 +:108C2000D5229A168B0EA15C029F46762B65226692 +:108C30000995CBD197D99851CFABB874CA6A42A1E4 +:108C40004687310C412F1FE78E60525DA3AE5B2635 +:108C50002432669D0FF7EA7A50D8986E7644433BEB +:108C6000A239822C404AFB940E1B6B08063317FD79 +:108C7000AA582E8C71020324F454EFD9C4B5105CA9 +:108C8000C25CEB9A84D60F3ABC5DD434C552A2596B +:108C90001AF3EF65F2EA606B0CAF94C008010A406A +:108CA00039E9014ED81E31EC9FCA7405169A86F632 +:108CB000923E8010CA71BBCF934F982EEC11693A47 +:108CC000F0AE5F9B86C73B41101E847BD4033730D8 +:108CD0003AD57CBD60A03D38329D04480DB8D78898 +:108CE000A371032E5D5BE27F25DFEC02D8101B40F1 +:108CF000E615CD58BA1F8A4963729C52CFD4FA2B1D +:108D0000BBA90E31F73AAC2621180B7580DAE56362 +:108D100034157A5B5BFE80D844075FC35863774C99 +:108D20007A2EF6AB721519007BEF739573542FB042 +:108D3000F13259770402734936D9E9A68CDF3F1620 +:108D40000B43CEFF22DB321CD349343A9334F8ABC9 +:108D500014ADBBB25DEFC2FD16D758F286E649B03E +:108D60003EDF697383E4227C338DA5C359F4985A9E +:108D70006F51DCF1AA7D8DA28EBA16EB5DE637A7A6 +:108D800006811E14ABD2D6B1CC86B877E9CBB677C4 +:108D9000152E58CC0C84916C7E4F92C252474C35A4 +:108DA000451777F2F511AD40374C63ECB9B0F7F9E0 +:108DB00068C5D01170A4A142AE8B5573D0DE2B696B +:108DC000CD8237489406567F10437DAA0C083B316C +:108DD000DAFFF0899480780BC668496D7A2D1B35CF +:108DE00033821EF279013FEF6EB86BD53EC1A024ED +:108DF00043A5AC6D811BDE071BACB133A617828186 +:108E00003BB56B3E831CB33EC29EAD1D8BC956194C +:108E10007688743F8ED13B4281514A252AA7929889 +:108E20001D60756069E8C123879D71EFB49EC42EF3 +:108E30000AA50572198224E371D0279F06D194C335 +:108E400013EAF3C09853CC55D05441F64EC76B4348 +:108E5000D7A1B68C2D9B5FD2C2D240A2048D7AD905 +:108E6000679F17576507CE2C61A8D628BE58419337 +:108E70001685102D08447DDA22E8409EA03D379CDF +:108E800015CEAE10D9B9A27D9CB2CB8AE1DAAC8EF8 +:108E9000ADB3468E617DC75DDBAF14E38765E73E0A +:108EA000F59C54BC7F8E398B44CEAE9E875F25BC2B +:108EB0004C83E1FA4E495BDA9EB1785C4DA7B79CD2 +:108EC0005D86455DCDC129F94AB1E4304A8010B0D4 +:108ED000A23FC9E115A062E1108D2E890394A27210 +:108EE0001934E2AFB4DB7A1BA6FBE708D164F3EADE +:108EF0001CE90BA639C23F55FE35F4CAC161033BDC +:108F00001DCEB9E38C13FCB75CE862C50D86D5B6FF +:108F1000B687E9D6ADD4001BDDE74ACE8FD66F26E3 +:108F2000A8C862671A48C01C7B2360090FC2B1C47D +:108F3000030BD8B5EA0407D1768D09AF5A724D52AA +:108F4000C8B71E573ACC7886103FA9CE58715F1C1F +:108F5000F38CBC7B73139718E46698793FDA09F4B5 +:108F6000FD51034CA7ACC5B44B0BCE007B3BF0636B +:108F7000AB4073497BBEB4C3ABACC220EE6612AF4C +:108F8000220F473FA5A5120CD83231EFF51E1175FF +:108F90004EF0AEEC9793E9888F0636E6883778D4A2 +:108FA0005259DCD4FD6322A7429AE22D8E6C8C16B6 +:108FB000BDC1253C002AF7611921E211343FFC4D67 +:108FC0004C1E53F2721E8EEE606EE30F86432477C2 +:108FD00019A469AAFFDD7B6696952DC3A0747B95C5 +:108FE0009F60B8274DD216CA11E75A5DE71C479318 +:108FF000CF84B3BAEC60AF2B68C1B438A2228F63C0 +:10900000131C42412F5FC40D369E2F553198878225 +:1090100069F4D14F8C2B1D38E53D93992EE8DF9DE7 +:1090200011644F870A951C0F261310DBE7C61354F3 +:109030008725A8ADEA46545D4300A42FEC5B16A338 +:109040009229E7B619741204C9FE7A0BCC61924BCF +:109050000B8549D16C9D51E6A14BFD237AF4D3E4F5 +:109060000D5A5703AC800C886D17E67B112A82A934 +:109070006B97F442D6E3919D2F198349F68CBCA8D7 +:109080002FA1B430B1AE98EFCC9CC39FC6C5CE51D2 +:1090900013DAD56DD7960F512D9CD67536AE8C87C9 +:1090A00020F7E7B3D9275B479704C017B2E59B7E4B +:1090B00021CF3D2D7DA5E36E3C81992B306E4C2D4B +:1090C0007840BB458666893606B00602F2CF7BC47F +:1090D000009FF4E782CB2F38E33AA614874E6F0B3C +:1090E000A3965275A095B135C692352183F4972089 +:1090F000171C9E56B910EE39974218F0A9E04D6939 +:1091000092635E5369F32B20A2594E0113A3705949 +:10911000C8286A5C75C44F1A12264C13B967FF62DF +:10912000791F05E2BC03ADA5CFF3949B62A2721C2C +:109130009F236B33D2F07A0EAB7DB8C5674167D9F8 +:1091400011F2D2BF66985FE1D9FAC2AA018B6DD441 +:109150002B85CD1B618F1447621BD4B37A3781EA0C +:1091600026DF5D5855C533890019F9C8C0D198501C +:10917000662186685CF150D84B6D0216E226804A63 +:10918000B7C03E429E9651BE5625A322DE9F3F4366 +:10919000636D4EB9C1A90798EA1E3B186DA81DEB77 +:1091A00075AC68D6590031163B528D003CABB76D9B +:1091B00018C7076F94F21F7EC186775F90126DF813 +:1091C00023C4C8EBAAFB7BC9CC8B92C5B7456D3EC7 +:1091D0006CE3ECE1E8B93F33CC5587055CAF6B2E0F +:1091E000EC684678E2170A8C417CB1F9F1D6E7CEFB +:1091F0004AA727432334E9AFCED7460960DEB658E5 +:10920000CB7D3A1104867DCCA9B8B5BF909751F7B4 +:10921000608F619A14080A5A6DA58DF6CAEAEC3778 +:10922000836ED5B5D201BC70D8DE8A62DFE71E44FA +:1092300000C056B26F7204F5032A33F7EFFD125ADD +:10924000DE36494F39C8E15C03AE7927C1A65E6EB0 +:109250005B271F4E88E8C00C13C7E76A29C5F528AD +:1092600018AF8BEDBFFBD7DC4DBB77FAD9F4C3BB8E +:10927000A7E44BF5399EF7BB3BFABD31C8BAEEF512 +:10928000C5428608D9B5F211745A5EFDBD16DE9D41 +:1092900012209773C2B3A89C20B72DF76E2C172C01 +:1092A000AAEAF5EBE5F2DEFC2D3364E8B25F706705 +:1092B000B141EB5097CBA24249CE4A0E0CBA7A91FB +:1092C000F2C23E2893778B1C5EF108202395F21C96 +:1092D00089565AAC02B693D50733FF3E9560FF48D6 +:1092E000C908CB3EC2E0216C14850F47B514116844 +:1092F000B82FDD38A2A1ABD499C93B939FAC73B80A +:1093000090BD9616A01FBB4F3DE3EDFCE4FC99E831 +:1093100018633A415C1CD81E107FA83519FD6BE616 +:1093200048EC8B73B7AB49B756527904FF4DEE0644 +:10933000A57DD9FFADF7898210A7A5CD51F7BE87CE +:10934000F6A12ED8F164C12FB01873DBAD9F8486CF +:1093500071E3AAE66F3CEF46CEEA39551DC1098A92 +:109360005E13F671196BB7838A709DBB2BBC0D65BC +:10937000CB4F0920EE1101EB3A341726540704971E +:10938000A331265A7037C144C18F562F10E2E68CA4 +:10939000085E91CE9CAF54E45DCF1B1286F50E0E95 +:1093A000A2F827488AAEC3020CCF94D97D3DDEA037 +:1093B0000660C65F4D273331D775184D2FE045C87D +:1093C0007870ABAD30893087C3519389E9A3960299 +:1093D00015259D7DB8590CB2C75C0B0D5B9AC80C66 +:1093E00097A3785FC6FC7B936B28F596698EDB7339 +:1093F000B072D1EF818396AF49C78213832027A330 +:10940000F73D0B6A82224E1A214566267444039763 +:109410004D566B559852A20D40CA4D352553FD8DC2 +:1094200097854F2C7BD1053C77B46200B08BAD772C +:10943000828024F8E7656BB89B840BCAE559C34664 +:10944000C7853EEF942D34D13AA5F0F86EF460FF55 +:10945000D3164058E23C76E10F8C031066638161BD +:10946000B9C136390118ACC1BD085E7F1094152909 +:1094700002F1C0956073F8423AE1256F4F6690FDA6 +:10948000927649BD8858432BA760A58F267526E3A1 +:10949000995E8D5A1C11DF0D2FD4686774C3A934EF +:1094A0007BA8170EBC02220808B272FCE0AD466A27 +:1094B00003C76146DDECD6F316CF48BC49939E4DF9 +:1094C000B42F64ACD3B384CC2E180C067C8BF8BBC1 +:1094D00021F5BBEECA2A4E0208D12E40E6357E5C4D +:1094E000B07C217C5D6E84619C6710D8C41CECF05C +:1094F0007EE6898D7519B5A27FFC2CA6F38BE87FDB +:1095000009D259281D672B56B13ED27431060BCFB4 +:1095100095B1987DCF335AEFC5EEED780CC60CF8B7 +:10952000A7742E47B58FAAB406BA9316E603E1884E +:10953000556B73D4E470B80A756FB81CC7ADEB1BDC +:1095400077C4CC615589F2391B0E034F79701CA288 +:109550001CED4ADDC20EE72CCE1B4CE00AD0C4EA5B +:109560007C088784094FE5C09707F41F89FF61B124 +:1095700051D80C0725B433CC68A278993C284935DA +:109580003F7A02AD3B7ADFBCA4541D7E9BF8CEAA85 +:1095900015E6882F17A64B40A0C655F890AF1C1EA5 +:1095A00041EEA168B8DBDE0B221433BA1E97937329 +:1095B000D11DAE487099268A8B8F3323BFE2CAA48F +:1095C000D7CC8FC9D3C295AEDEA3C002069F8B1045 +:1095D00037518DC9B52C438DA5258185DF729984BE +:1095E000C0BA9C51C4EA8F4C5B6B3195990EC70B86 +:1095F0009DB294715764F08CCBD4F74833673AB17D +:10960000B96A2E90C18E5C84E3B6C5536D9837A9B4 +:109610006D0C86A1E762F8FB77FBB31AF3BAE6C7D5 +:10962000D00BD466E42FB954B944825B27C4228D91 +:109630008C4CDCAE45D39BBD9B5C33BCD5EFD5D108 +:10964000A10D914245E43DAD8D50D660090FDD235B +:1096500024FCBF7D6201BA10DACE8AB1C83A60B785 +:109660004546886F28079BD87A519041A4BE057A59 +:109670000A1E1D621E5B71879330C3793CA92C675B +:10968000CE906D6C5F0E96894F551B4C5825FF6C24 +:10969000D905D03E31B13FD506FBFE7F3E46FA05E7 +:1096A000063A78034B314556C619609A67A7522689 +:1096B00087EA64A39799AEF96AB5C055D1E6711FE0 +:1096C000714A52E0185439B481AC131998ABE6943E +:1096D0007A5AFA3B8F839F055B05D484C533DF40FC +:1096E000902FFDEABF8929469AE1E5365117F653D6 +:1096F000B968B7AA41942863D58016728C14406A61 +:109700004055DC5708394A6FC325E6712A0FA0E49B +:10971000F34BE1FC99EAE62E61BC214109A5895091 +:10972000356716B166E9853BEDCCBD8688351FCD22 +:10973000C2AF26D680635455AA99C5B533770AC7F8 +:109740003CA506CEE32C547BF46DE5D44A55623833 +:109750008F9AEFABC31647C89A06121BE4381665FA +:109760008D425C984D62E188CEDFA788DD11D2780A +:10977000040FC884D9192A54515185D53B4340C799 +:10978000E9C8AD66E3732A401CD41DC3D7CE7A1F47 +:10979000C1DCCA7774B0FC04255F01136618C33EB0 +:1097A00039CA825D8B943CEBA6E7027E190C57C048 +:1097B000175BA8DC41BF8C2D3A7FB75151452D1561 +:1097C000201B304E4B2EA3B0DC53E9454CFAC4BCF1 +:1097D000E82E1835E15528B22EAEC113CD5182ECDA +:1097E000AF0CD0ED6E0DDA0DAD29BACC3A666EE154 +:1097F000A17820E750A5FBAE2B69DA42B6ABE2BBFD +:10980000AC2F2751A89F87CDE2CC1229069D948BBF +:1098100064E567E10DA5F55C85C737F1AE41B6CECD +:109820005999D3C97C355723347C71D198D6FE051C +:10983000753B5CD356BC5B02E336F6163F35D97BED +:109840008B2FCABF6E932A62EE1E9139C0D630CFDD +:10985000C9092792F1754E2978F41A5110BFCFFB30 +:109860004282ACF7376A16FE1026B1C6E6509B99C5 +:1098700097B98CD05134A964B74BAD7EB628133A52 +:10988000FA0D1F7924304372F7FF6C879FF625D3BA +:109890000BAEABD261F17C7507712B4F9DF5E18862 +:1098A000E0BC3FBFECD3BA380080D22D5A4BB5870D +:1098B000411C32ADED97A050B33F3E944F33C6CD1F +:1098C0009B2B5872A58C82DF712445A2D1D09FD6E4 +:1098D000BADDB11DA2AC9E7C8C6794250BBAABCED1 +:1098E000C3F939175CFF3363D37A60AF979603AA45 +:1098F000944A5276BD46BC372A16C053D84775A144 +:10990000E808C333E77CE67EBF604A92A0FF80424E +:10991000FD751A1CF0D6E1D12BE4D55985AE53B1B3 +:109920003646C733D77FDA59918E358CCAA3089E45 +:109930004C7DDDD5EB4A63DD0BBD4EA0A64DC0C806 +:1099400090449BBA1B743476A4CF441207A632EA23 +:109950003DB0118F5D8F1702BE7B9E0DBF013D563E +:10996000004E1A46D87FF5A84D896A90031408A4C2 +:10997000BE923851A8731EA9365FA262F9A507A549 +:10998000931B1516054CDBA70BBA9B7B6E9FE9AFAB +:10999000C8F359EC5834F742E768074BB065D8B0C4 +:1099A000C8ACD53C56673CE1FAABD7DA2F44D67643 +:1099B00031219EFA6C9C8ED6B40B6ECF1A138FCBCE +:1099C0009314BCB1692B1C4C921F4A4FBFAC11F4CD +:1099D000C6498F3B0013B43BEB04D6CF8E1856ED2F +:1099E000F7475B4EFB170FCAB675506B3DE3C59644 +:1099F000222E64D1DF65A5FADA2BBB666E6561D6CF +:109A00007DFC048331B45A8E65AA98BAE71F306F83 +:109A10004535CB79C1EFBDA511935F99D97EF3810F +:109A20009AF19743822D6D254FE1B5B14C894208DB +:109A300098506E9348543FAAE121D7BDEFB6A07A63 +:109A4000F5AB4A2B2F9258244B308C384951A0EC5F +:109A5000977521BC93329308E97502D6BBA36F8832 +:109A60007C6F386EFA19DE1B5617755EC914D34227 +:109A700046F43CA6F25021DDAF169B6185579DCA86 +:109A80009BBE966EC168CA075401C435E39C3C6610 +:109A9000CDCEA93CC66F26AB5EE94C975518DE27A4 +:109AA0000FEF5A7B8ED3535C04EA88404423CD7178 +:109AB00003BDC7D9106554DFB0F38041613DF38623 +:109AC0003E3A4649F0B1C963638664D5EB1C22A6D1 +:109AD000896D4F5446B8452155730BD81742FE91F6 +:109AE00059F72FBF5339FDD3BF574319B55A6A925F +:109AF000DCFF5F71A2470D9ED2D2FCCE6071340DA7 +:109B00009139905B441F87BA3A4851AFAF832F9485 +:109B1000BF95EB927C19A9D739C7A0326D5A99A38A +:109B2000EEED1C60811FB5E0C7266A1B0A48F5549C +:109B300086A3B7136227008E59FAE2DCE64BE4F104 +:109B4000D80296425149AE170C3F567CD7F70B3DD1 +:109B500017F9166A5FF6F4FCACEA307D2E798F3681 +:109B6000E027D6BB1C1E549B8463EC3D75E000EAE5 +:109B70001CB7D1E700ABAF62A3AD6FD6C600DB4424 +:109B800017E8CA229BA45B6A9C7E0FC5D95E5AD196 +:109B90008C35EB81A7BD84293F1DD1806BD3E0B408 +:109BA0007D054AB02F3DCE54BD67D952C8B4DDE61D +:109BB000EEC21EE0AF773830B0B2FEE638E671573D +:109BC0006514E92B0090BBA2B80CDD039224ECDCF9 +:109BD00072F8AEC140C01972581B2E42B8933AF2C7 +:109BE0009099D562734A184936822177F02DE7643F +:109BF000952E0B01E0497FEC6442BF061B9254AFE7 +:109C000065AB26A0C70213EBEC105A961961CF186A +:109C10005CCE87E01E53376D66ED48FEF1EA95EEA7 +:109C2000F302BEB41E37C0EF19A59D4C813005B2BA +:109C300082CEBB68E0DC5A4D90F081396B8D653582 +:109C4000BD2890C3E573FCF92ADCE56243A9805185 +:109C5000611A168ED6A39CADAD7DAE6C61552E24D7 +:109C6000011CE6C8F9CC5238E8B8FDA6A28D8F5881 +:109C70001842C2E3E45756B425CED356CA5FA98D25 +:109C8000B2D7E1267C16211AE0BA78CF010F08B3CB +:109C900048FE91DE4CE7D5FA25C6A18865359F14AC +:109CA00004759D0714297713600304EBE9F5931FEE +:109CB0005BB3686EFC58E0F0C634A0C22FCCA8BFDE +:109CC000FDD21BA81013170A3D4CC140C8FD5721F7 +:109CD000260FE3D4B9D843C07919F59226A0C1A5BF +:109CE000967A862A12C8059A6FF0B758C3468C43F5 +:109CF0009ABD7BB83DE1BC9A9417D9A424FF3CE0FF +:109D000008ED865839C44844F3064C0F58E1CA930D +:109D1000A069F69FD487712C88D93A8D081ED72D5B +:109D200078A1D247936B284FED40CA5A505B0E433F +:109D3000A042298BE73D44EF2ED584E907A5CBCE81 +:109D400058F08B0BD7F1E00542E782E9DA6EBC628E +:109D5000FA202CBA363966CADAFC741BA4BF6265D5 +:109D6000CB6003F4AE989955F071FCC751459ABC8D +:109D7000422A9C2886D5F0A537B66F29C63941A757 +:109D8000235621BE67FEF40D4E59CB2DD9FD5E2E14 +:109D90007C78E05084739117B48C5A2277A4D2DB7C +:109DA0004D8D5E7CDA1E6CEE9F6A76F79E80A3383E +:109DB00069ED8F1E8D5F301F045836E58A442612E8 +:109DC000BE4CF78F2BFAFDE462DFCDEDB7599F3C17 +:109DD00069207BC2986DD2E542342D923636799057 +:109DE00069FD54E343BE239BC265EF5C0CF42590F0 +:109DF00011C5C7F8E1C76258925D02ED7D70957597 +:109E0000F3CEB2B70D41A74AB7C7C4A6B5690C9641 +:109E10007EE6C2572464DC4EB37001F8D08FFFCCCD +:109E2000A6A56B5E0EF724577DDF2F0D788E851E5D +:109E30002069C837C2E5FA300CDE85873B18D2C3EB +:109E4000F41F33818BCA014F487918F390F4D24242 +:109E50006442188CF84CDE933A4544A2F0EB4697E6 +:109E60001DB7AD863E8C0D0BC8BBDB3E12DF131C4D +:109E7000F9117EB4253DF6A6D4B7D611F2E5E82F48 +:109E80008A5DC7047360200FE26FEF57EED11A8D21 +:109E9000C98FB341539D26DC76E21925F9CA96A2F3 +:109EA0005CD186853EE22347A2649E31433B8638DF +:109EB000CCF7A6BB67F904AB9EE7F42763810C4D92 +:109EC000EF8E595B40BB50F30C287E226750F8435D +:109ED000DF48DD46D78AD6A2A4251428ABD1FE1EC2 +:109EE000A105D90AAA420E92684E1EBFBF0DEF739C +:109EF000ADF73FF75D14C58E478FF44C916655A7BB +:109F00001432BCA1357757712BBD63B03B8E01264F +:109F10001F9D40A6B3C8EAA6A7194CDE4A24DCF56B +:109F2000BC48A943F89B9DC6FAD52885AFEC3C7880 +:109F30006552D0D6DA4DE0F4AFAC1FD29949DEA716 +:109F400066C09E451B71DD08F2C3AC5975BEED7746 +:109F50000C09DBF1DB793224DF0C767380110EA162 +:109F6000DB4375E00EAE78865229D9C04108FCB7B4 +:109F70002907372DAFC236D28C8679325E96E7E458 +:109F80007BDBD3AA7FFE8B2B1CBAD8AB6D88A35783 +:109F9000B9C85BE992EEA726F5C6A3452342D22DA8 +:109FA000BC1FBF31EA6C98CD3E4E399F2B31EC1768 +:109FB00051F20DFFDA2D476827331B6EA0CC1F82AC +:109FC000071D1730EDF886A2CFEAC8A0D99463D355 +:109FD00009444331FD04F2CECC469D5803410E990D +:109FE0008F42E1D1E5FBE3592E0F2ED84F9FC98A4E +:109FF000ADBE133EB5FBFC076F2891926C9E460EDA +:10A00000ED2D6629E92DE14135FDCDDCBB37A0D131 +:10A010007E0CF8836D4A64FF5B24758E65E854F806 +:10A02000DC2EFE4874A5D8C02F97DBD700A454DCE3 +:10A0300099D4C12537C6F57F5BAAA0261DA185D17D +:10A0400099587C3E935EE1DF0942B694CB274941A3 +:10A05000A2797C605D6CB0DB66D0A280EC289D9D0F +:10A060005BC94D1350EB49B52848CC3B1B9E3AA920 +:10A070001924276C8C46DD4D1B4622A5BC33F47A8F +:10A08000863A983419F6192BB790CA44F3D75A4236 +:10A09000A832987CCDA5637D9CCD8E189780FCC896 +:10A0A00058FC571F70921AFA2D97C9FE24591E3D6D +:10A0B00007237D9C8C2FA3294274C9A3047BE84508 +:10A0C00054F02F5ACCA956C632E4D31BFD58FD04D8 +:10A0D000EFA6A5F3707B2395EFA0BB4752A6D30351 +:10A0E000BF12E29DE60B89DEF09E08D3128DDBD213 +:10A0F00027F4480B855870373C758C1DA52333AF6A +:10A1000009C75579F8BD476D60BF187748A0139708 +:10A110006931767E29B458B401A4666F1B3A8C9ECF +:10A120007E8E088120E96B8365E46019AB801ABAE2 +:10A1300022C1A8B00FBD6FF51111114B2AB11E132A +:10A140007EF8EA2B34EA77ED2736B50431B568CED0 +:10A1500047DE0083632847F6B3C833B530537494A1 +:10A16000AB579805511CC9B2BAF14F0C91B4E23902 +:10A170005CA0722AC2638412AD34363D55BB8E1E7C +:10A1800086FFF5D24485F03673E686B153FA7A64D9 +:10A19000B673ED64842A1227DF82E76D8FF1519840 +:10A1A000337CBAA51E16A5F2992CFEB1D0B540F2AB +:10A1B0008BA90A2B2344997E716B2281EB6EE6B446 +:10A1C00056FABC82E910425008284182E332B1E4D9 +:10A1D000A67C72C93B5005DC68E0AB70B312E0842A +:10A1E000C95A89779D4BDAED5CCC77D5BEB74DB5B2 +:10A1F00076F56A04784FDD0211C5BA130BD2C69FFB +:10A2000024BF0A98BE3A5F9F4C250754B410C5DBA3 +:10A21000AD0D6E1D7B077C1A162F294A46E07F0183 +:10A22000E03A28F0467C991A309CC5B926ADD85C36 +:10A230001514F0D9641866EA237A31F569C15675A8 +:10A24000D2E346909D1132B72EC8ECCB0458FFA242 +:10A25000C1EFDF94C4C705A2B70B3ED4FB58E40B93 +:10A2600063CDB8BA2E1740C86C9A2B39CFCECB43EA +:10A27000ECBB9974B1166DC2E564D2917A47891A24 +:10A28000021EC04D6D33CFE6CE7188EAC55280CE36 +:10A29000E51AAD0C1D2B15157F15E68A7763F907B6 +:10A2A00090EF743BBEB73E505A111A0DA9DA0F62F7 +:10A2B000CD8127AFEF9B464B68BD176CCD623F62E7 +:10A2C000E67A35F7403D7C9B73F24F846775EFACBF +:10A2D0009BD18B80950EE91E4DF612B3FF83E232BF +:10A2E000D74CA630B55C381FF6FCB116FE9694BF6D +:10A2F0005B8FDC99DA193030C366373AE7544AC6C7 +:10A3000033BF6BD057DE84071A03E0931F9408FC19 +:10A31000C9C479200604656DA79A45117847397735 +:10A320006B0CF421FCD71939E4049B8208909AA79E +:10A33000D7B52D53ED360142178832B2CE054BDB2F +:10A3400025A82CA4C07A42CBFFF0312E69AFA89487 +:10A3500019F8959FDE8EE10B203FB57757205CB949 +:10A3600049353A89F9CCBA38E60BE68CE98C149970 +:10A37000C33E0CF20A18E332C0A39D30359068F852 +:10A38000111563A610C5094EEBA58DC0F56BA02E67 +:10A39000F12DF64E503EBDF243985B7C2934642982 +:10A3A000CF586B21D202B86813FFA194A04E4BDBAB +:10A3B0000A665E344F7DFAE785B40ACAD31FB7C96F +:10A3C000198338B9D84BE692327A8AFA03DCF7B4AB +:10A3D00077C6B30B44B1E4FC87D0C1CE3952D283E7 +:10A3E0008A1B38E8C2BF3254FF6D19921EF2859461 +:10A3F0007E30F59BB060F6AE5D7F6F7093C07FBF1F +:10A40000F890650E2AA0F63DB9C949C95D8E631260 +:10A41000E2753612B1AD80A3762C06DFCD99EBE65E +:10A420009A361CA7C87E6CD3ECA6718DB94DD56940 +:10A4300043E42F4D4DCA1D7579CA45D78224FC7F50 +:10A440004D7AF7C569E7BAFA0F68EB7B594566A5FF +:10A45000EE3A81B52E9D71BFA9270604CF1EA1A596 +:10A46000687239165E0861B075CC75AD21A5178A82 +:10A47000AA9C6643C70F0464CC625C22C2D69A2CA5 +:10A48000F129413E944B6141E5BAF4ACB9013BBCC2 +:10A4900057C4DE572C376BEE6DC1C610E1DCA959ED +:10A4A000E9974A9E99F79810EA3116B21547248920 +:10A4B00086D398A64B57C66F4D5EDC29B8A91B9969 +:10A4C0009EE5C84ABC4B718AE27B5DB9EB01CAE1EB +:10A4D0008A47ABD4D8AA05D57DC83B1C926D29D23A +:10A4E00097D79D184A40326AD3D72C081AE788A913 +:10A4F0007C24458735EAFE4F30CD9ACABED593EC11 +:10A500005DE9479225443A854386CE912786A05936 +:10A51000CB358E02FA195B1397CB4F9B71A94BB7C2 +:10A52000786C4D6BD1DE34AA3D5EB182A5BB32B8EA +:10A5300061A234073B21A441B96835CC549DE004A5 +:10A540009F43AE93DBC32F127AE204F71E0A819772 +:10A550008EBB8FEDEF886D3E1FC972F9C27B0DD7A0 +:10A560005D6D6BFED37059FF615D86FAD553645EF5 +:10A57000880C9B608EE5C85871FCD5E59AE8918FF0 +:10A58000BAB6D6227695ACB18AA14B93D3914268E4 +:10A59000B2BA983499C3234C7958B53FC0A83459FE +:10A5A00018C54A9055C75E53469A85BE251BF1369D +:10A5B00076782AB326917AB8B1FAF8BF842D1CBBFD +:10A5C0008D66F2160CFF090C256D365275DD34CE02 +:10A5D00038CD76D3545BC5C315A5AB26DB41F0C996 +:10A5E000EB69DF66D210502B9628BFE9427A14B58A +:10A5F000682A20130A8D4D957A20527991A535202D +:10A60000A7063AC31B1D4826BE60B61998453ED51D +:10A610001F24880FB0ACA53313D7B38D80A96384F2 +:10A620006E54A2F73DAA44AEB13DC3D5983C42DD7D +:10A630001EC763F211972FF065E43A762A8F016501 +:10A6400097D9ED131F1361973FCF38A78306C5E451 +:10A65000F6EAA9882F13714B45842126C1B7E6FC81 +:10A66000F8E70EF874F47D0FBEFE358F9FE72405E2 +:10A67000A10C18953E921328D787641B7546254C6C +:10A68000323067C2EFB20730EC060855F242A2B58D +:10A690006D4BC3F3B320098DBA76531C83A7D6D074 +:10A6A0004CA35A47E2B551635B472F517FE3DA74FD +:10A6B0008F075B56E1E4E5AE0F3F82C627666C6903 +:10A6C000FDFD8464EEFB79E9395EDEC2217A9905ED +:10A6D0001F1E7BA0D2F2F615C7BCC17AAB6C9E865A +:10A6E0003CACBD6D7F9E8A6F3DB898CD512AB4FEBB +:10A6F000ADE8387504385F636A00607E77C8F1831F +:10A7000003EE2E5403979C638E5CE348870BDC803A +:10A71000B4DCAA16CCABAEF10BD8B46A48B5AE30F7 +:10A72000ED1D331014DA309B7C9C2EDB32611FB29E +:10A73000BE46D66766D0877B03406F763A564D4E4D +:10A740000B91D33F56E709766FF33CB6C4869F71F1 +:10A7500076808E0AC260EF770B51E49E3630D5EEDC +:10A760006839A94F582678DF3E0E1D42A89872EF2F +:10A77000DC75604D7017CE0CE13E97E09DE4172626 +:10A7800048C40028094FFD5DC6B5C763916367D60D +:10A790001DBE301B341BD197A1DA3227C0FBB7F4A2 +:10A7A000211EF4046C282ECCE3A96F4D20A6CD63A6 +:10A7B000AA6862BE2613970EB1D5AC44AD0E4454C0 +:10A7C000EA289B60E561FECF5BEA831B126E407D49 +:10A7D0003BDFA27E64849DB3589082D585655A2262 +:10A7E00049AED2342705D33363D800E1C7D2C81BA2 +:10A7F0001DB836F1E814CF4284CBBB301588FD5329 +:10A800009E646E2ADDB0B6AB008CC001814E7738F5 +:10A81000E66F117D40D1D6E4C89C9454A5E363E46F +:10A82000831CF166CFD9A287FC0C4DF58AD995CD52 +:10A830006AEB091A08E0376E0BB59E95F5E28BBA04 +:10A840000A59972E5500C388E94819699585191C3E +:10A85000392F519A8883239CB3505B24ADB4116681 +:10A8600029FCA4E57A061965ED5D068EB1D6DA6F8E +:10A87000ACE06AD7352D6CE61302ABBDFB2FBDD221 +:10A88000122B97EA0DAE3035A87E5A05D0908F3541 +:10A8900052F2CADBF269B237CA2E1574B5F822C873 +:10A8A00018CAFF31767D00E6361610A95261662C73 +:10A8B0005FC22D2EA7851B6DDCA6B7BA0D141DDF58 +:10A8C00014ADEBD1487775A2909E589A291F940732 +:10A8D000CB9AF465976383DB4DFE957DB91FFEB27D +:10A8E00065DF059B776710221F1F1F2D039480C70C +:10A8F0000DC879A1F305FC3391C5612DBEE1A90214 +:10A90000BCA045205A0468162D26E061EB43075C85 +:10A91000D50556C5502A8BE0E001F687687F657E35 +:10A92000B1FDD90CB3415D8D7289EFE912AB13C84B +:10A93000934A1F08D6938F7C2E0AFEACEACB62E8BE +:10A94000E580EB3FE4FC61500944312B82358C7586 +:10A9500074A1E8D08BABEEF1C9B59F957C19BCEB27 +:10A9600078D7B7CE358A0F600855467C220C10295F +:10A970009C44C9882D21944D19371D8D38958D948F +:10A9800066DED6C6705B3238F4B71C50DF59D91B6F +:10A990002C2724BF1F42F7A271FDE2087A396E6EA0 +:10A9A0008C7D23AF16B8CABFAB8FC28F21FD6C9AC6 +:10A9B0008F7224A1299E92D2E7665F7508C6116A3C +:10A9C0002EB2781DD12A522FAD7C61085AADD2F338 +:10A9D000D5CEA993F58FFF456F4B2C9434BCDE2860 +:10A9E0008A6FD77887BABD8EE9B2B8B1B745F5247A +:10A9F00094B0EEEE09C94BF52460633179580742F3 +:10AA0000E98949EF70D9AC8BCDD031DB551ADE9F87 +:10AA1000369BC241280CC936DFA9D6771C5379F280 +:10AA20008DAC632722E92AD146FAF1925A6635AEF7 +:10AA3000532F1E93F31273F45C037E4A56120ADC02 +:10AA4000E12EE08C2479AB313D1D8C77A1457A94C1 +:10AA5000FD1102AE1213228DE4891C66913D245E25 +:10AA60002AE6470AA432A7972F82662FB28370FE88 +:10AA70004B9651E680F3875B38B774FE3E92996639 +:10AA80008C10FED97F29C6478FDBE7B1998C574BD5 +:10AA900081E2BE4CD103519D5EA661AADAA6CB8CA1 +:10AAA00076D9E6AD4CF267A9812D661A6AE0C683B5 +:10AAB00096C1FEF9B0421ED79650664781795F78FD +:10AAC000ACD77325DB16EA253126872AD204CA368D +:10AAD0002A05FE1B6DF18292085C97FE2762626F69 +:10AAE000BBF6A71C73685FC03029EE8583C50FA431 +:10AAF000454F53B0EF65B8F6464FC50143F01DB35F +:10AB0000AA9394B979FD683A31EA8AB44B430D9E11 +:10AB1000BB0EBF706CD2407BB2CDF837E879315BA9 +:10AB20009DBA54E178315E29DB45AF0BA97313223E +:10AB30009A8032F9A6BE2D6A8FB4B5F88A071C2513 +:10AB4000B0761E23154B0B4797E93E4ACCE03EA258 +:10AB5000DF5BC2B8885721F6848BDEDDE783B50F53 +:10AB6000FB48539F823098BB3C58AEA651C6BF1FCE +:10AB700007A9439D9B1600A2998E3AF3640B2D5AA8 +:10AB8000232DDD4E6136D960D6AEA90097582FE44B +:10AB9000FFCBB3F0B9285945DC7476EBA022C1AFE6 +:10ABA000070DE85D6DEDC4CE8656B44315FDD07437 +:10ABB0006302386B69B86FE216C92D81D581CCDF8D +:10ABC0003181D84EA0E8BA92685E4C01A81ABBCD7C +:10ABD000DDC828DD9D33DF43F5B7D924CDF27C7283 +:10ABE000256AB73DD6869332C250CC595D1D85E6A5 +:10ABF0004C91878C75D393D2F33904870D68CB9C25 +:10AC0000437A61087CE411521B2F8E786AD6524039 +:10AC1000F4CE119D3C75EDED558F27C39D2AF4A40C +:10AC200055FDABA9CD052010EFCE9481B79A0B2A24 +:10AC30007A83526639EB8D3AEDBC4530BABDE1BC42 +:10AC40003E85373A927A6681C0ADCEC9624573645B +:10AC5000C25D00938321B1DCA69CC86C1443B5C6C9 +:10AC600049C5A057BEDA68D4E5CF9FC2E157A30417 +:10AC700053492ED22CF8C6041EBC1596093EF23557 +:10AC8000D1D8186CC496DD9BAB0CFA896C2617D111 +:10AC900086A244300E47AFEA0211A96A0079718199 +:10ACA000EAE6AA97146AE3E962B65F1AD2C1B1581C +:10ACB000CEB0D1F0814736508FC67A4DEEF3F49383 +:10ACC000DCCE5C4566B1644F454BAFC3B0EBB11110 +:10ACD000F58F9F5BE54AFABD83A964D0A04B931022 +:10ACE00038329410D2D212CDCA2C86B840A0091C9A +:10ACF000CF67BBE1E2C289D8E08CF47849703C426E +:10AD0000F842F1FA051CE5FFB0D0FF4B473E872E15 +:10AD100055E0180A29868696D63A0F97D5628A3961 +:10AD200036FC253B24E9C48378F17029BF9D58E2A5 +:10AD300059621A76B2A71314EB3249064859BF3646 +:10AD4000098211625BB2A67D9DB8F403BD8A5734B7 +:10AD500045B7CE2B03343B8C7045D7CA22BA9851E5 +:10AD6000F448E5324E0A9AB8D4CA008A7069FA1CCF +:10AD7000F92D82A10B70CC488D9B9CE244993271D5 +:10AD80007D9946184F8A89E5873A1270F455BE3A84 +:10AD900044D88AF08FD851A49DF94B97252C4CB0FC +:10ADA000328EC51CB486EDA7273738050E434752AF +:10ADB000D9EA31C75627831F38A1CE00680FD14F7B +:10ADC000A1326D7DD52D2EB844665E3C4E1E79E8CD +:10ADD000F6FE20CB6530EC0D508B479494CFE1C844 +:10ADE0004D76D4057845E41A4DAE38D063CC435B3C +:10ADF00074A63A39226A3F60BF9CE362BDBE3D7EC5 +:10AE0000F4A0E66F79F5BB4994A20769CA56F5FC30 +:10AE1000434D0E1CBD173E295E8FB9EED10F91B286 +:10AE2000F6EEF16AF78650A7511DCC708C5EFCD40B +:10AE3000C76FB24BAB96AFD2C68B48A66481D244E3 +:10AE400041D4B282C47B7E59E1BC681A5512C482D7 +:10AE5000FB5473265071580D76F3D0E6AE8C2CDC83 +:10AE600041EC81158467F511AA6E504C9090F6E87C +:10AE7000A45B6A6E493F1C8640B5A659CA1DE5AB66 +:10AE8000CA9E7C5CD6F1549ADB534A83E7317EF24A +:10AE9000BD6283759D4C0B85AA0C3FE8645AAD4298 +:10AEA000E57E22741F0C30CECB3C68B0BDECF4853F +:10AEB000F3A441161C59AB15B2E30840B981B6A002 +:10AEC000C4389F94418CD4EBAE38A20FA1B4C56BAB +:10AED00032BCBF0CEC72EB7C7BEEDC1677B042A18F +:10AEE000F592BD74BAC968A67D2ADCBDB22F2C0AC2 +:10AEF00032DE4953DF4BA8BAE38BD0AE6DD5B596A1 +:10AF0000E7F8362FC86EBF3E7E62D61BF4F83D6D63 +:10AF1000985CC8871579159883FA53B37419A5EB13 +:10AF200000DD5F6C42EDC40F9E540C60E026FAD742 +:10AF30006DA89C94628DB5B560D93FA8A78C3FFFE2 +:10AF4000D91025246BA6FD6540F61ABC774D1A80F2 +:10AF5000AB4C7D1EC440A56F6EFB04702F1DE8270F +:10AF60003F8DCBEE3B8241D9E72FD7CA45786F079B +:10AF7000512096C574FAF59CCBDF66FB228B542FCB +:10AF800042E9EB6EE82718BAC207643FC7E4529E55 +:10AF9000A98D1CCF23A9C86226911A7A35CE913982 +:10AFA000C38ED27425CECE49CA055E58B8075982E1 +:10AFB000FB0F80D0152CA9659906554AC6267A82C2 +:10AFC000995B6D84C04562824939BCF01FEA58180C +:10AFD000E1F3D1296629A6A0D273EB9FA00176FCEC +:10AFE000348C2FDDFA3A2CDF1E30E112F41098AFCA +:10AFF000886BE9E0A1F2D2421348F0AAA6D0926D84 +:10B00000FB973D3B16A3699E56369DAA3A5E573B79 +:10B010006FB2D342F1D974EE07A729F42C4FA8A53B +:10B020005B37067A55E51D0858CF30EEC9E7258015 +:10B030004EF1C62E302F51D37FF9EF222C3A949E39 +:10B040008FCD020C0851E30904E01725AF8A3E12A8 +:10B050001118A9E7B7BEB2B878496976A13409CE0C +:10B06000C57F753C0712656D57DA422AE5B678460A +:10B07000DE809609493010C342D151CD321C3ABF0F +:10B0800074FE171DAE764D100798371A5290D0C82F +:10B09000EC1992586182456FEA76F352A77548B26F +:10B0A000C0C3BB25D69CF1EEEA90FB2BDD864BA2FC +:10B0B000A1EA4F8720B127C837498ADCAD0281B8A1 +:10B0C000E494C6E4567F7A4730DA1FEF682BEA280B +:10B0D00027753547ED027029136BF1375C63AB863A +:10B0E000474E031A261E0E51711B17B9B352022781 +:10B0F000F41CDCF496C5BC61929A59A94F58F2EB46 +:10B10000B427279B321E08C9E458DC601BACCE6311 +:10B11000CAA0DD9DBA2E071FE2DEA60EDFC6986D1F +:10B120007674A18257E45634FBBD4B9E2E32627C6E +:10B130006030386CCF962A5DCB9715D6CC2B3C0867 +:10B14000BA0490E302CDB204E08B86F193F4C79485 +:10B15000D4B88E41382388707C16523F4D758DDBF4 +:10B16000EBA5F4109C7E65F6136D6DABBC1413E774 +:10B17000EF7CA63021CEFF0C6035C00985ECEDFDDB +:10B1800022B19EF1EE9634F74A65189465DE150AF1 +:10B190007277386D50FDD3447A1B016DD1370E3D67 +:10B1A000D421F3938144568B180205F928AB8F19EB +:10B1B00061BB3F01200A0E0C820BCB546F4D42E164 +:10B1C0005D78DD2F96DB2FDE678AA948CE3A82258F +:10B1D0007331676150F2B35A4B6E1C8979EE3E0CA5 +:10B1E0007A53E9D695B450BCA9209A49AD1A619614 +:10B1F00080F04C1991FED7453959153FD239E7EA0D +:10B20000E3B22A063BA6812FC5D14A43C4268EB796 +:10B21000FA6D728B13A9F076CD4CB78709F0527690 +:10B2200033393B384A4D65F709850E5B929ECEF85F +:10B2300008E6D7FDE3EAEB625F8A0F9E4CB7227AFD +:10B2400047F04198CA0DD405AAAAB4A4D91A6FCF61 +:10B250001827683AEBBE5E486DD58A4CB3BB04D65E +:10B26000042D119879928D2AA96484B14AB04EFEBA +:10B27000298F5DD4C08D7629AEE5B61BB2FF4FE6AF +:10B28000E36D78CCAD93C3859098A25FD68B54655F +:10B29000F1D4510982A6D0B3022826F1B2EBCE53E5 +:10B2A000F84D2A413F3B64FB6035ADCEF388ABEEF1 +:10B2B000F11CFE432F6F9D3C0D49C9CD497336D615 +:10B2C0002B7A14C6A74D222FB54827BEF456153247 +:10B2D0004FBE6ABB51A57DA57FEF4A179B035AE677 +:10B2E00020221793E6EF2E4D2E0A26491089348628 +:10B2F0009A7B8DBEA8A62A788D3C7BA73235DCB31D +:10B30000D86560A7D71AD18261916818C50159F92B +:10B310003B6B3927DAA0753134CE9D6CE24B8C2E15 +:10B32000605CF48E309AABE928A8E10D049CB2D0A1 +:10B33000EA32CD725F5B0F66449D73019AE8DCD7F9 +:10B34000D7BD98C40A002D291DB092EB6821D80101 +:10B350001ED3F0CBF72082CC12DE58BECC6ED6CEF8 +:10B36000E242BCF7090FD7408A55A3003E1034FDD6 +:10B37000874A91849F537ABAF3D8AB33229DE80A67 +:10B38000A80D4AA1231186485A075DFE3026865E25 +:10B3900048CFFA5A264C43A97A75A9645A4B72973A +:10B3A00045694BF6FD1119C5E746FF5F1B2C79393E +:10B3B000D739F361B98FC16F27AFABC441124A03CC +:10B3C0009B089B650B15429DCA84731D34D6D6FA23 +:10B3D0006A422CF2245D120FEB9813FCFF7816C41E +:10B3E00012B1D7D7DD06B7E63F3CE3B1CB59B18CFC +:10B3F0002697E16093C3F01B8BE274458954C23BEE +:10B400008815F42DB5FE6979DEA1104DA793E32FC1 +:10B4100079FB714AA3C3A1FED351204CAAA2A4F97F +:10B420005DD530E1DE706FEC96B45EDD9CFCD356EA +:10B4300006239F8A4F7A465B024B7BC673DCE70686 +:10B4400082D711F5E7D91F096CE358B67B45F39213 +:10B4500087911BF1F828C2632DC223A01B44233E11 +:10B460005C7085FAA27297DCAC7DC2C6520F0C6E7E +:10B4700058C2D29FB96B0F92928F2F3E668176C6CB +:10B480008A149C06A9199605FDF1BECC5D2039F001 +:10B4900049092017DAA5F6A7D46A5E6D59CC0E6E5D +:10B4A000F92E06A4CFC38D348EB30073ACFF10F910 +:10B4B000EE7FDAD44C644E6C4FEA159FF7A89F29B3 +:10B4C00034E976781BFF2DB48B36E0D18167D59BAC +:10B4D0002F6C6A81F43F5601510618D4FCEED092CD +:10B4E000413F5D9E0CCAA782688980F1E37282B3F6 +:10B4F0005A88938FD659CD83A975C0905CFFDEAC76 +:10B500000CE504D4A82BB31452FB8943A650B82CE5 +:10B510002CBB993B08304E7ABDB8A5A425E15C024E +:10B52000EF2C568C4F4DF8194C426D299E7F27EA1F +:10B5300074CFAFD1196B51647D4D02126BB4D36CD3 +:10B540002FC13A53664B0F2CBC62D10BF74A3C20FB +:10B550008A77611FEAB777D6B64E44B6F31A2960E8 +:10B560004E9944FA9F9D5F5231E80B21D545FC541A +:10B57000BACF75DA8B21595C6BC980AA04E2527F7D +:10B58000B27070954AE7A0465DD1A482DD7507DDF3 +:10B590003182F35F34C48458C717FC2C099B2ED624 +:10B5A0003D03660472E7B0356FBC4194E51222504A +:10B5B00008BED9906575B325848AF2681481DA6A69 +:10B5C0003C63C8F2986F4BC468C3252384732E4331 +:10B5D000810D666556FD761970DDFEE096091DB099 +:10B5E000A3224B34740CB1009462CA4EE9152CC7E7 +:10B5F00045829D7E1FC5798175FE2E762A247CBCEE +:10B600001A1121F017ED5125D2DA0B4E44FEED232D +:10B61000EF4C70F014E2C43B6DD379637FD82A9469 +:10B620003E0BA3D8B53D4942966EE30D85DFE56D2F +:10B63000B6B905496A2B3E7C3DE27A39BB1C11E65E +:10B64000A0B29E1004D34FBB01A4176FD2FCD48EBE +:10B6500018899F4A37999E5B26BBEFAEF28DC106D3 +:10B660000BA44745A69F48135EA2826A25266F65F4 +:10B6700004B429D8CF8812B7E34F100DE2DFECAB4A +:10B6800041A5A34811C22B1456559A7D564BBFBEF7 +:10B69000790B63257F969B7F6D93BEB9624713D26A +:10B6A0001C035D3EF8C10D59454C995AF6675B463F +:10B6B000372CCF46D922B7CF91FBE4461637E45654 +:10B6C0006711411D8B10A50B1E9EEEC8D1F8FC57CB +:10B6D0001E1C01C1480E054CF1CBDD9392E45AC407 +:10B6E000B2B16AC7659F22EA23C12307B44B4E5605 +:10B6F00081F6D2C34B0AEA3D8EA67BF7BDBBA7738A +:10B700001EEE245DC1EDBACB3F56D511CDE9678A57 +:10B71000C31496150F201A09F26DCD5C5FF34FA28A +:10B72000FBA6CEC113242FC7BA635A6DEF225E5415 +:10B730005F615B42F367533DE13EC47C645ED2DCF3 +:10B74000E1BFE582913C2A44B3CAC0635E220BBFCD +:10B750008A7E1FEA1F2B7C413DBE838E8D03CD9FC9 +:10B76000F21FD8303F27E805B3CC5816C64EE9D1B2 +:10B7700067972745217415F67C9BF65BFD74A3CE75 +:10B78000FD6EFFAC662A478E790E4021B019993CB8 +:10B790007F3BAD60D26CB4B629680B87E1F8624E8E +:10B7A000470021AFCD90E07444AD824EB0766A2F51 +:10B7B0001F03CBDD1ECD2A7199FD429ADD1B395D39 +:10B7C0003A6BA80297F560F736C20FEE869DBD3240 +:10B7D00001C73572F16F7042F0DF9616312925836B +:10B7E0001368254B39DBA258C95D2538FAEB0241B5 +:10B7F0008208CA436DE606A24C14A7A3AD3F127699 +:10B80000DB4920F4C3A06BB7002D26F8145409DAE5 +:10B81000BC6614402A4EF7F0159C485A63C9D553AC +:10B820007D33CFCF1DAC8CA4D391EC725925883ACF +:10B830008F4252EE0D7333ACD2105762A7917791BD +:10B84000C194A6E390487B3494C57CC6C1F5342FDF +:10B85000C207D956759527B0325F4CD1E3CD05EFBD +:10B860003B72B054312518A78AFBD5EC712934C33B +:10B87000C56EEBA9EB2D0B61292CEEB2A7C7716247 +:10B880002C4213F6B5EFB40F308A60C1D2BA7408F7 +:10B890008A89FD35A35062D0F702C36D18B63FAD5B +:10B8A000EF3F6C0B2E544959E7AC29D8AF9573DFA5 +:10B8B000F1410A4FFF919B6D4BCDAC1F1294DF8C71 +:10B8C000E99CE527C93B90BE2B965A98556DE7F148 +:10B8D000238C8CF060109284AE571C955EFCDFD7F1 +:10B8E000ADB66EFF39B0A29AA57D81D474783FFAC7 +:10B8F0002C4634A535C6DAC839FE5764802C30583A +:10B90000CD1B3BE549B2CE0C00E56E03BA3A2F9C45 +:10B9100079AB08015261287B94B6B6A29A9E13CEE9 +:10B92000ADC4A0A9CF048BCA106C45E647C5525DD3 +:10B93000163EAB07523F6FFA3A3FE84CBF339604CE +:10B94000A40187B43A4F333A32B193F2E7CF75D2BC +:10B95000F9BC556C41D16779FF628748C167B5BCB6 +:10B960000856F80C54AA7DDA79F7593226C6083EF3 +:10B9700002D4378D5D013F7DAA3B08BF30B618D198 +:10B98000A971360DDD0A5B9906DACB0029B551E0C5 +:10B99000F97CE545CC1321216DAA3F33BA7814D840 +:10B9A00093A7BFFCB264D51ADAC82B5E2BBE2E213A +:10B9B000070136894C410326BA4D50F7108ED34308 +:10B9C0006962857CFBB891D3C5310E126E3FCC08FD +:10B9D00015FBF39D52469BA80F3B1D63EB79308B03 +:10B9E000062B854CD6047D4B18FF65C20BDF683FE4 +:10B9F00075864E31DCD48D8660D94D277C44A350AA +:10BA0000E47AA5E5BD5818AC32CC76A5A78789762F +:10BA1000FD5AA9F9313DD5C86FBC0E1E58997B4B14 +:10BA20007A97C6E594D329E423BFDFFF6C9B893F57 +:10BA3000886FB148CEA2E4F39A41D98D3367CB73B6 +:10BA4000BD141043B76F6C76D436AC9E5E22D77FA0 +:10BA5000D349DF3198B0F03C444F909F4F440F16CC +:10BA60007BC6F461BA18339E71556C4C048A8518F4 +:10BA7000AED1B6770E8FF378B4C85496AA0EBBB386 +:10BA80006C3C67EA62D35230104D7C64177957AD35 +:10BA9000D8F064914066472267303C278BA25680DD +:10BAA000D4AF9E9C7DFD69CB7557637EADF40D7B55 +:10BAB000E8DE4AAFF5E61263CA77A92C12C33D79D6 +:10BAC00049A1D7E4AF3A9341BD9D42B2A95F4DB7BA +:10BAD000AAFC6A7645BD19BBE303136FFB3AFF2747 +:10BAE0005C298867F8D4A3F22837A64D206B47E27B +:10BAF0006D5A769F917248D9EBD4EFEAAA32BF16FD +:10BB0000F43E2699B23A7918F7C9C85793EEFCAEBD +:10BB10009F19A392A970F8DF109EDC920A4567DC9A +:10BB20006BC1D7E171C19FC289DF20EFA2D4830628 +:10BB3000683B386259956B2A765EE299ECB86C4E98 +:10BB40007A8C38CADC698FC1F05D8DF4811833CEF0 +:10BB5000C41801FF74D4E6A11574DA8628A40AC4B7 +:10BB60009A633C1C6B25D55B6873EFBE566D8F479F +:10BB7000AC97D7E734DBE3332EC4CE105B2BDBE985 +:10BB8000E4515A683278667F9BAE77D59E3F1DBBE5 +:10BB900052BF4B5064871ACA3CAD0ADA37E3EA5702 +:10BBA000B95B8239D286DE29917A29F92A1421B823 +:10BBB00048B5FA11B871DC222BC1335D1A5F4DC054 +:10BBC0006F6E9AAD4C1BDADB7A216469BFD14CD918 +:10BBD000668C581636283BE59B4828A8E48721A5A3 +:10BBE000FD6114CD9D9F6CB3F13910A5D3C436BE51 +:10BBF0004E970A772733EF3E89F867E71EF3C63979 +:10BC00005FADC35BE0252DFCCD4BE0CD51591EF857 +:10BC10001F8DB621820B9C432639E7EE06A4D11B6B +:10BC2000EF95C7BD5DB2D9B8C7C1554FFDE5DC1C66 +:10BC3000E3E9B7B728BB34BEFC5F3E78CBD2E8FC63 +:10BC4000D45D127CB0E185E1EE7166892009B52BE7 +:10BC5000AAD85925D8FD51A5520B2E4F661634503F +:10BC6000AD0FDD5021B7E773369337E2EF48E8B404 +:10BC70001F6646E3D29D233A59072A2ADF46F5D0AC +:10BC8000419CBC491E867E17732E0F5FBD2E2A076E +:10BC9000985A89BB3DE34AA70A52F663C219DDC828 +:10BCA000759D7E3F20DA6670BE3E24D5F345C33FC6 +:10BCB00069AE66BAE14291009462E8F8000BDC21BB +:10BCC000616A738B25DB8798051C669E3DFD13CB4F +:10BCD000D38F1A7BAA8AC6C09AA09F2EE1C6FF27DF +:10BCE00084A14BAA0F8E0BE702FCA2F47DD2802523 +:10BCF0005D18DF1421356A2589BB816D7750C60038 +:10BD0000DDD1F20E99942994B10FC4F53CD391E79B +:10BD1000D848539C833B7B24BD18D0BE08BFF18A12 +:10BD2000444409D46E3D504C85465306F4DDD36C33 +:10BD3000031F8C4F2DEBF2A9E9C1DFD28CC4A0EA1E +:10BD40006013CE96AE8165DFBB3572E355EC7BC2E6 +:10BD5000B0CEB0025AE7D23540502C765D9A842D91 +:10BD600025877377F605316E7887C16F6C490FFFB1 +:10BD7000CF99EE1BB01D86D2330C753A8BAB89B5CB +:10BD800080979B46FCAA4F59F3D43560DB7D961211 +:10BD90008E9C23149FC7E01275FDE80471F311DE39 +:10BDA00075F6EBF3BFDCE882CDBB0F522C63723823 +:10BDB000E42B825E2E547403F080688D3B83103533 +:10BDC0007BFC0F0C2E5CFE8A94BA35FDE516F52639 +:10BDD0004DDAA88506123B3B7818F56763F728DA39 +:10BDE000A842268F5D27A70102B11E49F2DDBFA937 +:10BDF0006E84F1F5A173E9D18358017B78F11BC5FD +:10BE0000CA95F1BC344A54981A62D9C726E21E4931 +:10BE1000FB43C0813E84591BEEE29B5B327F55B1F0 +:10BE200011791D3AB74F23056038DE5C0731FDA557 +:10BE3000D0D3281E451004CA664D0302F89940E786 +:10BE4000DD2845165BE9F6BF5EDB04446D0935DA93 +:10BE5000A45603C43A57B64C689FA11BFC2DEAC7F1 +:10BE600031CCACF3F8E4680778E3996C89017F96EC +:10BE7000D22F372ACCD5E31538077899869884E6EF +:10BE8000FA80DE6BAB09ADA196DD0A5413898FBA37 +:10BE900008F66986B3A68C86B0C675B0F551ADE6D6 +:10BEA00099DD6CC7D6C27FB226DBB6729D219F1585 +:10BEB00096F4A4B877AAAAB8D96F60B9F093CF5F07 +:10BEC0009A213E28E2D1CD41FE3D15167B91973354 +:10BED000AFC41489179607F5A897A8A0410FFB7A5D +:10BEE000BD0E6E345C88D574E120056809D5567B9B +:10BEF000A1353E85BAFEFBF2614A6B633E925471F6 +:10BF0000D4ED22D678698524B4019CF00D13E17C30 +:10BF100029E73F94DE81F733E9BE0272BED7B42130 +:10BF20001D8797C590E6576B8D0A3A5F085ED45B14 +:10BF30004FFA2CB9054BEF13324E63412656429A05 +:10BF400055793B639B2ECC040D606FC026E8E9D089 +:10BF5000983A798654E20C931966DCB2CD25774184 +:10BF6000ADD6033EE2628710DB301A688583ADA64A +:10BF70004DE36A1B749BAF837B10B8FA468C23E5B4 +:10BF800077DE0C77C1E302CA1710CF1F68FF3CB9F8 +:10BF9000E8A2B7E3DED0164DD5AF6EA2389CD90823 +:10BFA0004BA686D404D917427E5E4C89767FAFA01B +:10BFB000E6CAE37D02EEDF6C489A240CF2A5EA069D +:10BFC000877A219CC5A76D111C356E632F08DBCBCA +:10BFD000B84595261052E4C2358212F2652BCA226A +:10BFE00085C8910992826836533D5666AF6A2C4DDA +:10BFF0006C791F6F587B2531DBBA4E16006538C24D +:10C00000C7F0A7676AA3653FAF35FA3B95D8995D3E +:10C010001FE472EE547628AD5BB403E156FA20D2E9 +:10C02000EFFAFF0F69B7B22F2DCF02BB1FB430A0BC +:10C0300065028BD749EBC12286B136230514F63E43 +:10C0400030C95A2262BC2FD8990BBF15F87C696F92 +:10C0500089E4BC07B27F4EC0874833BC006C0FB385 +:10C060003AE79551CFD4678D982DA1D9869EFEBE13 +:10C0700051963CD3F94640280C11C356FA4C071C84 +:10C080000AE1C094901A7B34115155DBE264A7ACED +:10C090006848F14BCE48E637670FC99CA941367A0C +:10C0A00025073F532C05577D548BBDA48D4B34D5AC +:10C0B00011899FD4274BB861A0448CF79A33B850AC +:10C0C0003CBF9F0782BBDF9B42347D3B0F899E9420 +:10C0D00084B1A771C585434802C1665ABF930CF667 +:10C0E0003BB4E49BDDC243D20114CC63C02117638F +:10C0F00096107E3462F1BE15E50DF7352EFFC4F7BC +:10C100004B042AB7DA9D435F94091103D8BB6CF442 +:10C11000533ADF8002E25B881EDD0F00228583FE3A +:10C1200070928F19191090330A8BA3DDE2B92E9704 +:10C13000815DEB4A9F6114952E8C0517A560E07810 +:10C14000A4C6AC070CD95E8D0B3D984B602A058DBB +:10C150009D1506C0D3092F33BD38E9CBCE8A5D3D8E +:10C160000244291AAD6C65599241130A85B42741DE +:10C17000B00F4FA25F98FAE2B2773F87D11B11FE52 +:10C18000B8991CACB5BD65C4E5035A1A9001B56BEE +:10C190003A44382E4A3CC2C9DFA281D6167112AC8D +:10C1A00094E2DB1C50049DF4EC66BAED6832DB4D82 +:10C1B00015459B0750204105905100CA94CF0DBFF3 +:10C1C000A95F91B7D69E94833A583D89DEBDC58F4D +:10C1D00076DF1683481CD34FB5254994997F6EE5C9 +:10C1E000C5BF624FD0213F51BF9970707C761B2034 +:10C1F000A424AC7D2DD91B448960E02BA494C843B2 +:10C200003DF423712F3B4432A1E59FA7B7508336FD +:10C21000D14449EBA46327A40FA99877EDF5A2C2F6 +:10C2200041020EFACCA6BCFD54D688D80107CE2216 +:10C2300020E4B53C6F64EA94ED337C54511F03064F +:10C24000FE0B69ABB138CACC03D8877569B4E46317 +:10C25000D02E122F4B4C1B94D6CAC7436316F064E2 +:10C260001DEA66CE6425677081A2BAF606C3D20EB7 +:10C270009CDF6383B514E5500FA3D862B9852EF116 +:10C28000912E2C6EAD985B7992C722F725344F49D9 +:10C29000960277BFF0079AB3F20F1B49967AE85BD4 +:10C2A000E70425007FF67811032005CC9A9DB53967 +:10C2B00073680487B5BACDC6C82C0C26D843CF24E2 +:10C2C000D852519994E2FAE68FEC9FB6DBBAD202CB +:10C2D00091CBCC3B6B766663F99A974D8B70693A3C +:10C2E00014C4C00CB9F10557F4CFEC5C799232E577 +:10C2F00052AD9642EF6F4375EA09031CEF349C522E +:10C30000D1C8EFA58FBF4CC456FDBAA331500F0260 +:10C31000DDB146AF2871CEB32429C138DED3440F36 +:10C32000A76025C9B7B324AFCCB364CECC1EAC365E +:10C33000D476302490A763F881F8E039D95C1CB733 +:10C340009834B6009A40470A35E3298EDE56171115 +:10C350001C20D3742535C2D3A702C003948760B9CB +:10C3600022C8DB0232B8CBB080D10522FCF86426AB +:10C37000D3CEEA7BD45964F471506712B939D8D45A +:10C38000001D80A94BBC8C61711ECE79DF1871CB6A +:10C390001A675C93A07B3A8A082EBC500AC9A18A0E +:10C3A000AF5AA535DB55BB83DB0BF029751350E184 +:10C3B00005D8B09CEE4198747A634C49C353C2359A +:10C3C000B59C198DB090E1B84C73CED19695D8300C +:10C3D00071888E569190A2F1FDB08DE67541ED2ADF +:10C3E0003B21F319A71C463DA779F6793C38AB8C65 +:10C3F0000EA4A1D0489C2410F763B67C1B8C6BF272 +:10C4000055BFFD473CE64CC17A98FCD02B63F8DE63 +:10C41000043773B1D2743CEB75DFCE63115929FB3D +:10C42000D4E3362D92D73BDDA6E18ABC7460CC1EE6 +:10C430002E2E6C257CD56FF65EFA054FCC95FA2131 +:10C44000A58A54611E412F08415476AB5F92E3B434 +:10C4500053B761C530C32F8A158B7228680D1D86AE +:10C4600041213F818AB11DFE3C40056F8EFF1C902B +:10C4700051C11EF78CC4A135F24467D8BCC869838A +:10C48000D85EAF6C3DE20AD989E1A6361F8196F3EA +:10C49000464A9EF7CEE7C969680DCCFDE48A9D3413 +:10C4A000420B8DA65429F584FC44D4EF00748B3DD7 +:10C4B000085DD8D4A4D54A6DC20295A7D86ABAC37C +:10C4C000CE38972C994662FCDA302173BC498B2513 +:10C4D000BF5EED4042D0F69120940D6B8881234FD2 +:10C4E0004E040D921D4F3C012AFE6F4F6282ADFF3C +:10C4F0004501479FA39B81900A2D69260FBAD5AEAF +:10C5000069805E770BCDC6735C40390A20007DAA36 +:10C51000D009541EC124DA9C2A547653F92407EA20 +:10C52000D124C2D407BE65F0C8A4FAC98CA43BF5D7 +:10C530004A4BB1261291EA1196BC0E2B8E4CD61B9B +:10C5400028FBE03DFBA910D1B12BC43A9929D116A3 +:10C55000B744685F53459D5F645DAA047E5DBC116E +:10C560004F43D9CD2C123501924F2811E74A0FD7EE +:10C570008ACD40876B2288B67D289FED6A39F35DAE +:10C58000D5015C6A2589A4EC99E9E7E26816FD1DEE +:10C5900081739B710A15DF0EF3EAFEB9FFFA0D569F +:10C5A0001F0F076D9526A20FBE5D30F3B3D04394E5 +:10C5B000EEC34A28D6BEE53951AEA83261702B4B86 +:10C5C000F6774AB54D1D4F4EE5F839A29CAC25C310 +:10C5D000B47B07A3C9384571C6460BB74624A328C8 +:10C5E000A0433F2B4029CEFB2748CBD1E1793663CE +:10C5F00049B5FEEDEDFF9908645628702ED97E628C +:10C60000A6AD6A5E7E4691184F3692D4288B02D82A +:10C61000752DF0AC721247F5DE67A08C91C941CF41 +:10C6200035482B1D057DF8969C948AF77EC62B0114 +:10C630008F584C9F1D734A616DFA053A111FAFDA8E +:10C64000F7E21FB3C8845A548047438BC70F715514 +:10C65000AE3BC8F1A1F3190ED6AD6E3243C66FA43E +:10C66000A77EF868704EEBC18C93C2E8BE38DF72CB +:10C67000DEBF6F8FA1FFEFD1DA403C870B4A7EF718 +:10C680004A8A18657D82D5318AEE7D377BFB94F925 +:10C6900064FC2A22F6BEFABDF0314084571D85594C +:10C6A000C086FB7C539540C4DAFB394D1BC59C3DCD +:10C6B0001E6906DB5E9B4EC776477181DD093668D1 +:10C6C000C9640EBE63EE883E83820BD4610E707225 +:10C6D0000FF8E96D70E4C200730D2CA8C306DC44AA +:10C6E00063992ECE56F215D8F127F48D8E7774AC5F +:10C6F000D3C353222F94F8AC88D5B088D88BB473A9 +:10C7000089A95ED86BBC958AC4FD8317417D200D35 +:10C710003413B2440FE89DC00C7FCFE60039683374 +:10C720003743B6312628795C8E00874241F512A541 +:10C730005AFF6641C2071D538407768C419CB12B7A +:10C740002E1FA3002FFA9F8C8BE5D7241DD92FBA5B +:10C7500086D5CEE839769525A39E4BB48F1F1C2C29 +:10C76000C46C826560692C33063A715FEEE072FC3E +:10C77000BEF2FDC619CFA1FEBBB66EC095CF2F1578 +:10C78000659BF7B9F296D226AA3737411326CDE733 +:10C79000C81FBA28A85A6F3F5EA351D938840076C3 +:10C7A0002153998467EF8F3CB48281AE503EEC3ABE +:10C7B0005FC36ED11BCAF0FC9BB1BA5F9AF24F5CAB +:10C7C000B926AE4B40C9E22D0E19DF4B98803EB41E +:10C7D0007B04B17A0F92F68DADAE6EBB6C53B36A2B +:10C7E0009683F34FD68DC387EE5AFC734157E30708 +:10C7F0009761571C0AFECB4F9D05B0B4154D4744B9 +:10C80000E8D5580582C74CA50AC011268146EC9090 +:10C810003834D7B413E4C8ABE38F59A36DC2116D9C +:10C820005801FB527DB0604A6008FA7B0E527D626F +:10C83000123CB0CE23B4FA53F8D6851EEE72EA1538 +:10C84000D66094F2D2D45B2B5FACB0D35DB840EC31 +:10C8500076221830B4B8B654393CD513CCACF5F0C8 +:10C86000B483B8E9C70D167C14CA8FC68AD1403389 +:10C87000C3A0A59FC6C07E32FA67E7F81F4DA43556 +:10C88000CC9BBEDC4243F95FD56D44F62E58E55B88 +:10C89000CA5CFE3BB6B4AA21AE442562FE608F316D +:10C8A00091865F74C5BC4AF6A3EB7AFE0945D9A808 +:10C8B000D212540E79D9A5E395AD8B308DB07B346F +:10C8C000CE48A37EB289E4516FAFD77832BB97BA16 +:10C8D0004483E469FE22DD382F7C53C7695E75B955 +:10C8E000392BAF6E9D328741C3918F06FA38137F83 +:10C8F0000E80C218F654C8B4A7B8A1B7877F22B873 +:10C9000087D787071024C024C200AEA0F0984EE855 +:10C910009D0F8FB1B3D3AD3FAC26B642A0148D515D +:10C92000D3160FCDBE72C714798719EEC8D89B8570 +:10C93000A4E1096E2A90177CE4A0261A26D90B36AA +:10C9400063C370209A0238AE08B15EE3D80ACBFD0B +:10C950002D8F3C1854BFC689F7BC8E0A272CA435EE +:10C96000C1360DB8082C0469458F12E6C7F0CD0515 +:10C970004A55175199999219A7FEC8A7A5B9BB9B0B +:10C9800068DCF807BAF6452F58FB8463AFC4DA7742 +:10C99000DDDEA0FEB515DAC14458C8F682CEA5FA90 +:10C9A0009C9586EEB0F856EEBD198286F4C6E14D30 +:10C9B000E0F2DD86113AA386637957A239B813DB1A +:10C9C000F78316B11A1A95BDFE9AA2B87744AA8DBC +:10C9D000CBFC04738DA241EAA0484FA0D0F347C11D +:10C9E0002F347CD338435480954933D3B1CD996DDE +:10C9F000A18D7DFA9C99A2223EB5891C3FC32D686A +:10CA0000890834C0167C923AE40192986EF113249E +:10CA1000B7E02C5F1713C587CCCBF6159AFBCDF189 +:10CA2000B414FB4AE2C3405600AAEB272CFD6C3439 +:10CA300036129722EA67981A64F7FEFF4B03347C9C +:10CA400028D44AC6AAF72E3BA5C19B2CAE8A072440 +:10CA5000BFB0A6DA51A1C6A8249592C4FD3B1A83A3 +:10CA6000AC69C0244010AC236BBBC0BD5011504F0B +:10CA70006D129CD1EB7AA92F18A994FA6A4E8A45B7 +:10CA8000C01DD62CC8451CCB6B37BDC2364FE92A1A +:10CA90001EE60F44C8AEC0DDCDBC0DDCDE5F6268B3 +:10CAA0005C41584ED4115E120565365D4D1A9EFDEF +:10CAB000C5D29BA287342A0B228E9551F5AF06D59D +:10CAC0007F69C053FFB7F57AE1F24CF094D9D7A94A +:10CAD0004869888B401F49293380CCA202F8EDF0C9 +:10CAE000A4C9F75E5DCFB5D58024A0BAB760DF4B8F +:10CAF000A44619E2478983E40095CADEE2772F1540 +:10CB0000C2F41FBF0E5A9A96F09875219D35A4FA6B +:10CB1000997B787B34828675206D9FA612F45B1614 +:10CB2000D9E144931AF690F69A6ED85FC8C1041DF5 +:10CB30009C7466E168AD51D5EAA16526928B78A018 +:10CB400050766EBBB648C0B66C7F64D5FE7F61C3BD +:10CB50003AF86370C831276EB0B433BFDD0DDBC364 +:10CB6000E591FCE08E4629F3FD5DF016E8CB76A951 +:10CB70002E3EEC1C327DF6FCAC4AAD26F03E6BAB93 +:10CB8000746D44F3A6E5B1E8D86993B64BEE828C98 +:10CB900046B96E05A2E343D6DDDA6D19B9DD80270B +:10CBA0007346B557780D7DF7E283BD6E4CF785EB84 +:10CBB00063AD921030F435672BAD0F3CACB6BCF4CE +:10CBC000DA79A901BA1717272FFA27B3B2328A0BDD +:10CBD0003D18ED560ADA896065FB02C66F169A9118 +:10CBE000D576CD1BD433309173458FC88C15CF6C5F +:10CBF000E9C78728ECE9EADBFA1A8BF8647666E77E +:10CC000005D8D949FD8E36C163F5E9FBA88CA51A74 +:10CC10000D63226CAE31F4E90CE8D2D7115D1AF73E +:10CC20008763CE78AE89E921F3A53F8AA09B9188DE +:10CC30005646AD0E24ADE68A8C91DF3E6AE883E568 +:10CC400007F47A8047D1B8129D929EE3247B4E0C64 +:10CC5000C9BF9FD224505CF41868F709DA30CA695A +:10CC60006FD01067876626C611225ADC4E8631CCFB +:10CC700057DEF189C3EA21900D3C39CE3F4F516810 +:10CC800066B23E63E405E5121C12D45F03BE51C0D8 +:10CC9000368094947CB9E53AD9C4D864C7FC70ABAB +:10CCA00026E56317D1776F93D77067F96E9E58901A +:10CCB0007767E0842B47AD9943DB5D1196EC87BB2A +:10CCC000DBCDD05666E97ACF48BBC7144D6B10CA8E +:10CCD0009BB9A4D1DF3AAC609EC8AD63624FB26627 +:10CCE00070F89FC155E50DD7B61916963354B6C7DF +:10CCF000A11D692299BA9E2C98704146C0EAE49021 +:10CD000023B5CB9732E9CC3124AD7F758909DB8C13 +:10CD1000D6689A0AE5043D6F4788F4C022D22923D9 +:10CD2000A8D8DF5CCC14CEE47C6F5273E79C8C15E2 +:10CD300091AC9D446CA8C35760B482E39DE5D64C8A +:10CD400048F2418FA9F014633353EB6D7F6EE3F526 +:10CD5000E7AF4ECB9E6E920709E78C058F62782F66 +:10CD60007A34D351F28A7BE537203343C53F51DF14 +:10CD70002DB8EDB6577DF84C546A81C2A357D82A16 +:10CD80000F6AC954289FA47D68C9609D48B8FD9F5B +:10CD9000A6D0C638A3380BF3F714D8A504DD3BF7AB +:10CDA0007CCA9F7C01C0365DB0D96CBC681F9EFBFD +:10CDB000F920377643AF32BECD19620490A4073D07 +:10CDC000B3CB4142EFEB38492EEE53C48CB202286C +:10CDD000397642F90A5424D55F67A171E1C1095738 +:10CDE000C752639BAC4A7942F682806580B644F7AD +:10CDF000136FA96087ADA0C802E566A05816212B65 +:10CE000021D11623A2F777CEF3D91394FBD0966DD8 +:10CE100046CBBDBE67289FBB21F339903BE05CA5A4 +:10CE2000DE7F3F2B1549E8115D9F85E66603406B69 +:10CE3000A5E14B1EB397FB9CE97330A86D8ACD3BEF +:10CE4000762AD1C8487D2A58032FB98B686644B129 +:10CE50002BE015BE7F17B8C34BC63EE4A03B3A5546 +:10CE6000E8865BF476E5056025ED481D23CE8290CB +:10CE7000ED52D17753E50E28FF89BCC85D9DD7F3ED +:10CE800084FC069924221FB885478C20AA72B49B83 +:10CE900071D8E82BF31C57417408A476CD82C9C021 +:10CEA000F175762BCC2EC51D842BF1A4DCCEB3B747 +:10CEB000F0ABAAD369C2A1A40036244D89AE7F9EEF +:10CEC000F47E240858D1318DD7E5EA6E673A2F11E8 +:10CED0009369C5D21146258D475B2681DD19F5BBC7 +:10CEE0009E5830A4814CF8A0CB93DF291EBAF17A6A +:10CEF000C0D67D87D5A115BE1E672DEB1A13C6B30C +:10CF00000B2BBA267B4D29AA6097452A51988A0592 +:10CF1000EECDF6BBBB50E870C8D12B4CCC40FB8D9E +:10CF200006CFA610534B4D9F4C75017E04CE25278E +:10CF300034C3E826F14BBED9876C758F1C7AA8B430 +:10CF4000F14446982856BF7D61C7D6DF84CB5E602A +:10CF500071DA93CC005B544F3F26EAFB23845B4E8F +:10CF6000DF7B26DAD6B45355C127B62BD4C179BEA0 +:10CF7000D28BFC11101A4C8C91C456E6851C9EA4D1 +:10CF8000AE5B59DDB14941CE6526E5EFE86899B859 +:10CF900038B66CFC2510700506BA74FE0AABC2499F +:10CFA0009BF6BABC490378DDB9E220451342206BF9 +:10CFB00095AD7A7BD3AD6D2A2ED0C79DD9DF6FD6C4 +:10CFC000B22A156070E4DFF94E9E6B84E6DC62E203 +:10CFD000CC24E04D5F57A49372C70A0F45B7764340 +:10CFE000E5ABDD3AA54DFE0EFBB206996424D68C66 +:10CFF0007DE8BCBEA60631429F6E3EF20A85D9533B +:10D0000044EBBC8CE97E8EF46D2766C68E0D754FA1 +:10D01000DEB5BC41B1AAC75E676C3CB8E2E50F055E +:10D02000CDD97C66766BDE658057D45D6F447BED31 +:10D03000EF30222A2643160A6736AFC1571A5F051A +:10D0400071896429746C9D1B086879037FC34C6FD8 +:10D050002800169AEFB11EE868F89C22C535D9D68B +:10D06000A5569E4E52BFA522EA5FC9BF317F0D4B28 +:10D07000F42703581B3A8DF18B086CEB11863E1296 +:10D080008AEF98ABDA95258F1345F29EF9DAD357DC +:10D09000FD2D05B0444241CF19F96FD05B99198439 +:10D0A0001B500A5566A40596CA69EEAAD09683FC61 +:10D0B000F12DC86F59A2DF84BD157E240F2219C738 +:10D0C0005ACEC0A8516FFE323834B2CC7C7C0AA84C +:10D0D000D3862D2060E9AF5FA121D4E2DF23E94EA2 +:10D0E000F01DEEA4D88916E95F582B96F0D65A4861 +:10D0F0003CF747A3725B9D175E7BAEC3531F511075 +:10D10000F000001300070119C80E37046F087B3CBC +:10D1100088420000000020121E05BD0D3303263298 +:10D12000FE2CFFA8DEA8DE4616045A00301019387F +:10D13000140A1AAE07CC00CC4C46004C000080010B +:10D14000012626808000000466100010144028018B +:10D150001E6648FD00401C2D00C800C8006F03A7D4 +:10D160000764960001010001000000050A000000AC +:10D170006400DE0332002003F9000100FF012800F3 +:10D180000F042800470828000F0428004708282813 +:10D19000010A3C0105733C7801050303010001020B +:10D1A000005802011B0000FF91059001BFFF66D0EF +:10D1B0000700000000000E000000BCFF3535000035 +:10D1C0000000002001D007FFFF0C0C0F0F00D0075C +:10D1D0000101000E000E00000B00000000000E0018 +:10D1E00000000014000000008000000000000000AB +:10D1F000000000800000000000000000000080002F +:10D20000000000000000000000800000000000009E +:10D2100000000000831C001C00000B0000000082C6 +:10D2200019001900001C0000000081160016000003 +:10D230002F0000000080000000000000000000003F +:10D2400080000000000000000000008000000000DE +:10D2500000000000000000000000000000000000CE +:10D2600000000000000000000000000000000000BE +:10D2700000000000000000000000000000000000AE +:10D28000000000000000000000000000000000009E +:10D2900000000000000084000A0250001464050928 +:10D2A0000F0011004B0000800080001C1F40000098 +:10D2B00003000800080000001F1E1D1C1B1A19187F +:10D2C00017161514131211100F0E0D0C0B0A090866 +:10D2D0000706050403020100000102030405060716 +:10D2E00008001000100010001000100010001000C6 +:10D2F00010019908070605040302010001700004EB +:10D300000232321919327610000004370000000092 +:10D31000043700000000086F001E0000086F001EA8 +:10D32000003C003E0019003200321E198066CD021A +:10D3300014CCA00178001B5A1E9623A00000000008 +:10D3400000000000000000000000000000000000DD +:10D3500000000000000000000000000000000000CD +:10D3600000000000000000000000000000000000BD +:10D3700000000000000000000000000000000000AD +:10D38000000000000000000000000000000000009D +:10D39000000000000000000000000000000000008D +:10D3A000000000000000000000000000000000007D +:10D3B000000000000000000000000000000000006D +:10D3C000000000000000000000000000000000005D +:10D3D000000000000000000000000000000000004D +:10D3E000000000000000000000000000000000003D +:10D3F000000000000000000000000000000000002D +:10D40000000000000000000000000000000000001C +:10D41000000000000000000000000000000000000C +:10D4200000000000000000000000000000000000FC +:10D4300000000000000000000000000000000000EC +:10D4400000000000000000000000000000000000DC +:10D4500000000000000000000000000000000000CC +:10D4600000000000000000000000000000000000BC +:10D4700000000000000000000000000000000000AC +:10D48000000000000000000000000000000000009C +:10D49000000000000000000000000000000000008C +:10D4A000000000000000000000000000000000007C +:10D4B000000000000000000000000000000000006C +:10D4C000000000000000000000000000000000005C +:10D4D000000000000000000000000000000000004C +:10D4E000000000000000000000000000000000003C +:10D4F000000000000000000000000000000000002C +:10D50000000000000000000000000000000000001B +:10D51000000000000000000000000000000000000B +:10D5200000000000000000000000000000000000FB +:10D5300000000000000000000000000000000000EB +:10D5400000000000000000000000000000000000DB +:10D5500000000000000000000000000000000000CB +:10D5600000000000000000000000000000000000BB +:10D5700000000000000000000000000000000000AB +:10D58000000000000000000000000000000000009B +:10D59000000000000000000000000000000000008B +:10D5A000000000000000000000000000000000007B +:10D5B000000000000000000000000000000000006B +:10D5C000000000000000000000000000000000005B +:10D5D000000000000000000000000000000000004B +:10D5E000000000000000000000000000000000003B +:10D5F000000000000000000000000000000000002B +:10D60000000000000000000000000000000000001A +:10D61000000000000000000000000000000000000A +:10D6200000000000000000000000000000000000FA +:10D6300000000000000000000000000000000000EA +:10D6400000000000000000000000000000000000DA +:10D6500000000000000000000000000000000000CA +:10D6600000000000000000000000000000000000BA +:10D6700000000000000000000000000000000000AA +:10D68000000000000000000000000000000000009A +:10D69000000000000000000000000000000000008A +:10D6A000000000000000000000000000000000007A +:10D6B000000000000000000000000000000000006A +:10D6C000000000000000000000000000000000005A +:10D6D000000000000000000000000000000000004A +:10D6E000000000000000000000000000000000003A +:10D6F000000000000000000000000000000000002A +:10D700000000000000000000000000000000000019 +:10D710000000000000000000000000000000000009 +:10D7200000000000000000000000000000000000F9 +:10D7300000000000000000000000000000000000E9 +:10D7400000000000000000000000000000000000D9 +:10D7500000000000000000000000000000000000C9 +:10D7600000000000000000000000000000000000B9 +:10D7700000000000000000000000000000000000A9 +:10D780000000000000000000000000000000000099 +:10D790000000000000000000000000000000000089 +:10D7A0000000000000000000000000000000000079 +:10D7B0000000000000000000000000000000000069 +:10D7C0000000000000000000000000000000000059 +:10D7D0000000000000000000000000000000000049 +:10D7E0000000000000000000000000000000000039 +:10D7F0000000000000000000000000000000000029 +:10D800000000000000000000000000000000000018 +:10D810000000000000000000000000000000000008 +:10D8200000000000000000000000000000000000F8 +:10D8300000000000000000000000000000000000E8 +:10D8400000000000000000000000000000000000D8 +:10D8500000000000000000000000000000000000C8 +:10D8600000000000000000000000000000000000B8 +:10D8700000000000000000000000000000000000A8 +:10D880000000000000000000000000000000000098 +:10D890000000000000000000000000000000000088 +:10D8A0000000000000000000000000000000000078 +:10D8B0000000000000000000000000000000000068 +:10D8C0000000000000000000000000000000000058 +:10D8D0000000000000000000000000000000000048 +:10D8E0000000000000000000000000000000000038 +:10D8F0000000000000000000000000000000000028 +:10D900000000000000000000000000000000000017 +:10D910000000000000000000000000000000000007 +:10D9200000000000000000000000000000000000F7 +:10D9300000000000000000000000000000000000E7 +:10D9400000000000000000000000000000000000D7 +:10D9500000000000000000000000000000000000C7 +:10D9600000000000000000000000000000000000B7 +:10D9700000000000000000000000000000000000A7 +:10D980000000000000000000000000000000000097 +:10D990000000000000000000000000000000000087 +:10D9A0000000000000000000000000000000000077 +:10D9B0000000000000000000000000000000000067 +:10D9C0000000000000000000000000000000000057 +:10D9D0000000000000000000000000000000000047 +:10D9E0000000000000000000000000000000000037 +:10D9F0000000000000000000000000000000000027 +:10DA00000000000000000000000000000000000016 +:10DA10000000000000000000000000000000000006 +:10DA200000000000000000000000000000000000F6 +:10DA300000000000000000000000000000000000E6 +:10DA400000000000000000000000000000000000D6 +:10DA500000000000000000000000000000000000C6 +:10DA600000000000000000000000000000000000B6 +:10DA700000000000000000000000000000000000A6 +:10DA80000000000000000000000000000000000096 +:10DA90000000000000000000000000000000000086 +:10DAA0000000000000000000000000000000000076 +:10DAB0000000000000000000000000000000000066 +:10DAC0000000000000000000000000000000000056 +:10DAD0000000000000000000000000000000000046 +:10DAE0000000000000000000000000000000000036 +:10DAF0000000000000000000000000000000000026 +:10DB00000000000000000000000000000000000015 +:10DB10000000000000000000000000000000000005 +:10DB200000000000000000000000000000000000F5 +:10DB300000000000000000000000000000000000E5 +:10DB400000000000000000000000000000000000D5 +:10DB500000000000000000000000000000000000C5 +:10DB600000000000000000000000000000000000B5 +:10DB700000000000000000000000000000000000A5 +:10DB80000000000000000000000000000000000095 +:10DB90000000000000000000000000000000000085 +:10DBA0000000000000000000000000000000000075 +:10DBB0000000000000000000000000000000000065 +:10DBC0000000000000000000000000000000000055 +:10DBD0000000000000000000000000000000000045 +:10DBE0000000000000000000000000000000000035 +:10DBF0000000000000000000000000000000000025 +:10DC00000000000000000000000000000000000014 +:10DC10000000000000000000000000000000000004 +:10DC200000000000000000000000000000000000F4 +:10DC300000000000000000000000000000000000E4 +:10DC400000000000000000000000000000000000D4 +:10DC500000000000000000000000000000000000C4 +:10DC600000000000000000000000000000000000B4 +:10DC700000000000000000000000000000000000A4 +:10DC80000000000000000000000000000000000094 +:10DC90000000000000000000000000000000000084 +:10DCA0000000000000000000000000000000000074 +:10DCB0000000000000000000000000000000000064 +:10DCC0000000000000000000000000000000000054 +:10DCD0000000000000000000000000000000000044 +:10DCE0000000000000000000000000000000000034 +:10DCF0000000000000000000000000000000000024 +:10DD00000000000000000000000000000000000013 +:10DD10000000000000000000000000000000000003 +:10DD200000000000000000000000000000000000F3 +:10DD300000000000000000000000000000000000E3 +:10DD400000000000000000000000000000000000D3 +:10DD500000000000000000000000000000000000C3 +:10DD600000000000000000000000000000000000B3 +:10DD700000000000000000000000000000000000A3 +:10DD80000000000000000000000000000000000093 +:10DD90000000000000000000000000000000000083 +:10DDA0000000000000000000000000000000000073 +:10DDB0000000000000000000000000000000000063 +:10DDC0000000000000000000000000000000000053 +:10DDD0000000000000000000000000000000000043 +:10DDE0000000000000000000000000000000000033 +:10DDF0000000000000000000000000000000000023 +:10DE00000000000000000000000000000000000012 +:10DE10000000000000000000000000000000000002 +:10DE200000000000000000000000000000000000F2 +:10DE300000000000000000000000000000000000E2 +:10DE400000000000000000000000000000000000D2 +:10DE500000000000000000000000000000000000C2 +:10DE600000000000000000000000000000000000B2 +:10DE700000000000000000000000000000000000A2 +:10DE80000000000000000000000000000000000092 +:10DE90000000000000000000000000000000000082 +:10DEA0000000000000000000000000000000000072 +:10DEB0000000000000000000000000000000000062 +:10DEC0000000000000000000000000000000000052 +:10DED0000000000000000000000000000000000042 +:10DEE0000000000000000000000000000000000032 +:10DEF0000000000000000000000000000000000022 +:10DF00000000000000000000000000000000000011 +:10DF10000000000000000000000000000000000001 +:10DF200000000000000000000000000000000000F1 +:10DF300000000000000000000000000000000000E1 +:10DF400000000000000000000000000000000000D1 +:10DF500000000000000000000000000000000000C1 +:10DF600000000000000000000000000000000000B1 +:10DF700000000000000000000000000000000000A1 +:10DF80000000000000000000000000000000000091 +:10DF90000000000000000000000000000000000081 +:10DFA0000000000000000000000000000000000071 +:10DFB0000000000000000000000000000000000061 +:10DFC0000000000000000000000000000000000051 +:10DFD0000000000000000000000000000000000041 +:10DFE0000000000000000000000000000000000031 +:10DFF0000000000000000000000000000000000021 +:10E000000000000000000000000000000000000010 +:10E010000000000000000000000000000000000000 +:10E0200000000000000000000000000000000000F0 +:10E0300000000000000000000000000000000000E0 +:10E0400000000000000000000000000000000000D0 +:10E0500000000000000000000000000000000000C0 +:10E0600000000000000000000000000000000000B0 +:10E0700000000000000000000000000000000000A0 +:10E080000000000000000000000000000000000090 +:10E090000000000000000000000000000000000080 +:10E0A0000000000000000000000000000000000070 +:10E0B0000000000000000000000000000000000060 +:10E0C0000000000000000000000000000000000050 +:10E0D0000000000000000000000000000000000040 +:10E0E0000000000000000000000000000000000030 +:10E0F000000000000000000000000000494D90A456 +:10E10000010100010100000000000000000000000B +:10E1100000000000000000000000000000000000FF +:10E1200000000000000000000000000000000000EF +:10E1300000000000000000000000000000000000DF +:10E1400000000000000000000000000000000000CF +:10E1500000000000000000000000000000000000BF +:10E1600000000000000000000000000000000000AF +:10E17000000000000000000000000000000000009F +:10E18000000000000000000000000000000000008F +:10E19000000000000000000000000000000000007F +:10E1A000000000000000000000000000000000006F +:10E1B000000000000000000000000000000000005F +:10E1C000000000000000000000000000000000004F +:10E1D000000000000000000000000000000000003F +:10E1E000000000000000000000000000000000002F +:10E1F000000000000000000000000000000000001F +:10E20000000000000000000000FFFFFFFF001F01F2 +:10E210000A1E0E371E10015100010105640001FFA6 +:10E220000301730103080056A700B070010101014A +:10E23000F001000000000000000030584537303089 +:10E240000000000029030F00030000000304270161 +:10E250000A290E05075025030000000000000000F9 +:10E2600000000000000000000000000000000000AE +:10E27000000000000000000000000000000000009E +:10E28000000000000000000000000000000000008E +:10E29000000000000000000000000000000000007E +:10E2A000000000000000000000000000000000006E +:10E2B000000000000000000000000000000000005E +:10E2C000000000000000000000000000000000004E +:10E2D000000000000000000000000000004C0013DF +:10E2E0000601122F260D0401012700090021340028 +:10E2F000000000000000000000000000000000001E +:10E3000000000000000000000000000000003A02D1 +:10E31000011B0000FFAA059001BFFF66D0070000A7 +:10E320000000000E000000BCFF35350000000000BA +:10E33000200108D00100008402A6094B801C1F00A8 +:10E340000300201244941102003A00064044C841E0 +:10E35000E8FB0C0C844C168007808088108080803D +:10E3600080808080868080828080808080818080A4 +:10E370008008000000000000000000000000000015 +:10E38000000000000000000000000000000000008D +:10E39000000000000000000000000000000000007D +:10E3A000000000000000000000000000000000006D +:10E3B000000000000000000000000000000000005D +:10E3C000000000000000000000000000000000004D +:10E3D000000000000000000000000000000000003D +:10E3E00000000000000000000042410D0001540048 +:10E3F000000000000000000000000000000000001D +:10E4000000000000000108002009838180808080D6 +:10E41000C00100000000000000000000000000003B +:10E4200000000000000000000000000000000000EC +:10E4300000000000000000000000000000000000DC +:10E4400000000000000000000000000000000000CC +:10E4500000000000000000000000000000000000BC +:10E4600000000000000000000000000000000000AC +:10E47000000000000000000000000000000000009C +:10E48000000000000000000000000000000000008C +:10E49000000000000000000000000000000000007C +:10E4A000000000000000000000000000000000006C +:10E4B000000000000000000000000000000000005C +:10E4C000000000000000000000000000000000004C +:10E4D000000000000000000000000000000000003C +:10E4E00000000000000000000008070000015500C7 +:10E4F000000000000000000000000000000000001C +:10E500000170000402282828283276100000043701 +:10E5100000000000043700000000086F001E00002B +:10E52000086F001E003C003E0019003200B4321497 +:10E530008066CD0214CCA0047800B4641E9623A09B +:10E540000800400000000000000000000000000083 +:10E5500000000000000000000000000000000000BB +:10E5600000000000000000000000000000000000AB +:10E57000000000000000000000000000000000009B +:10E58000000000000000000000000000000000008B +:10E59000000000000000000000000000000000007B +:10E5A000000000000000000000000000000000006B +:10E5B000000000000000000000000000000000005B +:10E5C000000000000000000000000000000000004B +:10E5D000000000000000000000000000000000003B +:10E5E000000000000000000000400000004051005A +:10E5F000000000000000000000000000000000001B +:10E60000A5E4D66100100000010101100000A20D78 +:10E6100000000000D0040204D00402040000000046 +:10E6200000000000000000000000000000000000EA +:10E6300000000000000000000000000000000000DA +:10E6400000000000000000000000000000000000CA +:10E6500000000000D00402040000000000000000E0 +:10E6600000000000000000000000000000000000AA +:10E67000000000000000000000000000000000009A +:10E68000000000000000000000000000000000008A +:10E69000000000000000000000000000000000007A +:10E6A000000000000000000000000000000000006A +:10E6B000000000000000000000000000000000005A +:10E6C000000000000000000000000000000000004A +:10E6D000000000000000000000000000000000003A +:10E6E000000000000000000000000000000000002A +:10E6F000000000000000000000000000000000001A +:10E700000000000000000000000000000000000009 +:10E7100000000000000000000000000000000000F9 +:10E7200000000000000000000000000000000000E9 +:10E7300000000000000000000000000000000000D9 +:10E7400000000000000000000000000000000000C9 +:10E7500000000000000000000000000000000000B9 +:10E7600000000000000000000000000000000000A9 +:10E770000000000000000000000000000000000099 +:10E780000000000000000000000000000000000089 +:10E790000000000000000000000000000000000079 +:10E7A0000000000000000000000000000000000069 +:10E7B0000000000000000000000000000000000059 +:10E7C0000000000000000000000000000000000049 +:10E7D0000000000000000000000000000000000039 +:10E7E0000000000000000000000000000000000029 +:10E7F0000000000000000000000000000000000019 +:10E800000000000000000000000000000000000008 +:10E8100000000000000000000000000000000000F8 +:10E8200000000000000000000000000000000000E8 +:10E8300000000000000000000000000000000000D8 +:10E8400000000000000000000000000000000000C8 +:10E8500000000000000000000000000000000000B8 +:10E8600000000000000000000000000000000000A8 +:10E870000000000000000000000000000000000098 +:10E880000000000000000000000000000000000088 +:10E890000000000000000000000000000000000078 +:10E8A0000000000000000000000000000000000068 +:10E8B0000000000000000000000000000000000058 +:10E8C0000000000000000000000000000000000048 +:10E8D0000000000000000000000000000000000038 +:10E8E0000000000000000000000000000000000028 +:10E8F0000000000000000000000000000000000018 +:10E900000000000000000000000000000000000007 +:10E9100000000000000000000000000000000000F7 +:10E9200000000000000000000000000000000000E7 +:10E9300000000000000000000000000000000000D7 +:10E9400000000000000000000000000000000000C7 +:10E9500000000000000000000000000000000000B7 +:10E9600000000000000000000000000000000000A7 +:10E970000000000000000000000000000000000097 +:10E980000000000000000000000000000000000087 +:10E990000000000000000000000000000000000077 +:10E9A0000000000000000000000000000000000067 +:10E9B0000000000000000000000000000000000057 +:10E9C0000000000000000000000000000000000047 +:10E9D0000000000000000000000000000000000037 +:10E9E0000000000000000000000000000000000027 +:10E9F0000000000000000000000000000000000017 +:10EA00000000000000000000000000000000000006 +:10EA10000102EDE00000F7E03100F8E00000F9E06D +:10EA20000600FFE000000FE1330010E15B0011E1A0 +:10EA3000810012E1100013E1000018E1570019E114 +:10EA40003D001AE119001BE11E001CE10A001DE156 +:10EA500050001EE1500038E16F0039E13D003AE11D +:10EA600028003BE13C003CE114003DE1C8003EE1F0 +:10EA7000C80058E1B50059E133005AE141005BE1BB +:10EA800064005CE123005DE1A0005EE1A00078E1AC +:10EA9000140079E1140088E1370089E1320098E13F +:10EAA000640099E13200A8E10400F0E1000030E2E6 +:10EAB000040031E2C00032E2000033E2FF0034E241 +:10EAC000FF0035E2FF0036E2E80037E2940038E26A +:10EAD000710039E2EB003AE2AB003BE2FF003CE2BE +:10EAE00067003DE2CD003EE2B9003FE2C60040E2F1 +:10EAF000FE0041E2D70042E2570043E26F0044E2E9 +:10EB0000310045E2480046E2010047E2FF0048E2EA +:10EB1000FF0049E20F004AE200004BE200004CE235 +:10EB200000004DE200004EE200004FE2000050E223 +:10EB3000000051E2000052E2400053E2020054E2C1 +:10EB4000620055E2010056E2060057E2050058E275 +:10EB5000840059E200005AE201005BE200005CE23E +:10EB600001005DE200005EE200005FE2000070E292 +:10EB7000010071E2F80072E2700073E2040074E2D6 +:10EB8000640075E2040076E20C0077E2100078E29F +:10EB9000000079E208007AE260007BE200007CE29B +:10EBA00000007DE200007EE200007FE2000080E2E3 +:10EBB000000081E2000082E2000083E2080084E2BB +:10EBC000000085E2000086E2000087E20000B0E27B +:10EBD0008600B1E21800B2E26100B3E28600B4E25E +:10EBE0001000B5E20000B6E20000B7E20000B8E2B3 +:10EBF0000000B9E20000BAE24200BBE2D400BCE28D +:10EC00002D00BDE20000BEE20000BFE24700C0E20E +:10EC10003400C1E27300C2E20000C3E20000C4E2BB +:10EC20000100C5E20100C6E20300C7E22800C8E215 +:10EC30000000C9E20100CAE20000CBE20100CCE220 +:10EC40000000CDE20000CEE21400CFE20000D0E2EE +:10EC50001400D1E20000D2E22C00D3E20100D4E2A1 +:10EC60001400D5E20000D6E21400D7E20000D8E29A +:10EC70000000D9E20000DAE21400DBE20000DCE28E +:10EC80001400DDE20000DEE20000DFE20000E0E26E +:10EC90002200E1E20000E2E22200E3E20000E4E21E +:10ECA0005A00E5E20200E6E20000E7E20000E8E2E6 +:10ECB0000000E9E20000EAE20000EBE20000ECE222 +:10ECC0001000EDE20000F0E27000F1E20000F2E27C +:10ECD0000000F3E20000F4E20000F5E20000F6E2DA +:10ECE0000000F7E20000F8E20000F9E20100FAE2B9 +:10ECF0000200FBE23100FCE20100FDE20000FEE266 +:10ED00000000FFE2000000E3020001E3010002E373 +:10ED1000010003E3010030E3080031E3000032E3C7 +:10ED2000000033E3000034E3000035E3700036E315 +:10ED3000000037E3000070E3450071E3020072E376 +:10ED40003C0073E3020074E33D0075E3000076E3EA +:10ED5000000077E3010078E3020079E301007AE341 +:10ED600002007BE300007CE300007DE300007EE323 +:10ED700000007FE3000080E3000081E3030082E302 +:10ED8000100083E3030084E3470085E3000086E38B +:10ED9000460087E3610088E3000089E300008AE31E +:10EDA00000008BE300008CE300008DE300008EE3A5 +:10EDB00000008FE3000090E3000091E3000092E385 +:10EDC000000093E3000094E3000095E3000096E365 +:10EDD000000097E3000098E3000099E300009AE345 +:10EDE00000009BE300009CE300009DE300009EE325 +:10EDF00000009FE30000A0E30000A1E30000A2E305 +:10EE00000000A3E30000A4E30000A5E30000A6E3E4 +:10EE10000000A7E30000A8E30000A9E30000AAE3C4 +:10EE20000000ABE30000ACE30000ADE30000AEE3A4 +:10EE30000000B0E30000B1E30D00B2E31B00B3E358 +:10EE40003500B4E34500B5E35000B6E36000B7E336 +:10EE50006B00B8E37500B9E37F00BAE33000BBE3B1 +:10EE60003A00BCE34400BDE35400BEE35F00BFE3EF +:10EE70006F00C0E37C00C1E38A00C2E39700C3E3F4 +:10EE80000000C4E30D00C5E31B00C6E33500C7E383 +:10EE90004500C8E35000C9E36000CAE36B00CBE360 +:10EEA0007500CCE37F00CDE33000CEE33A00CFE342 +:10EEB0004400D0E35400D1E35F00D2E36F00D3E31A +:10EEC0007C00D4E38A00D5E39700F0E30000F1E38F +:10EED0000000F2E30000F3E30000F4E30000F5E3D8 +:10EEE000FC00F6E30000F7E30000F8E30000F9E3BC +:10EEF0000000FAE30000FBE3FC00FCE30000FDE39C +:10EF00000000FEE30000FFE3000000E4000001E475 +:10EF1000FC0002E4000003E4000004E4000005E457 +:10EF2000000006E4000007E4FC0008E4000009E437 +:10EF300000000AE400000BE400000CE400000DE413 +:10EF4000FC000EE400000FE4000010E4000011E4F7 +:10EF5000000012E4000013E4FC0014E4000015E4D7 +:10EF6000000016E4000017E4000018E4000019E4B3 +:10EF7000FC001AE400001BE400001CE400001DE497 +:10EF800000001EE400001FE4FC0020E4000021E477 +:10EF9000000022E4000023E4000024E4000025E453 +:10EFA000FC0026E4000030E4000031E4000032E41C +:10EFB000000033E4000034E4000035E4FC0036E4F3 +:10EFC000000037E4000038E4000039E400003AE4CF +:10EFD00000003BE4FC003CE400003DE400003EE4B3 +:10EFE00000003FE4000040E4000041E4FC0042E493 +:10EFF000000070E41C0071E4FC0072E4FC0073E4A7 +:10F00000FC0074E4000075E4000076E4000077E49E +:10F01000000078E4000079E400007AE400007BE47A +:10F0200000007CE400007DE400007EE400007FE45A +:10F03000000080E4000081E4000082E4000083E43A +:10F04000000084E4000085E4000086E4000087E41A +:10F05000000088E4000089E400008AE400008BE4FA +:10F0600000008CE400008DE400008EE400008FE4DA +:10F07000000090E4000091E4000092E4000093E4BA +:10F08000000094E4000095E4000096E4000097E49A +:10F09000000098E4000099E400009AE40000B0E465 +:10F0A000F000B1E49F00B2E49F00B3E4FF00B4E4D9 +:10F0B0000000B5E40000B6E40000B7E40000B8E4E6 +:10F0C0000000B9E40000BAE40000BBE45000BCE476 +:10F0D0001000BDE40800BEE40000BFE40000C0E48E +:10F0E0000000C1E40000C2E40000C3E40000C4E486 +:10F0F0000000C5E40000C6E40000C7E40000C8E466 +:10F100000000C9E40000CAE40000F0E42800F1E4D3 +:10F11000000030E53D0031E5000032E5230033E535 +:10F12000000034E5230035E5000036E55C0037E5F6 +:10F13000020038E5C10039E5C1003AE5E7003BE5EA +:10F14000E7003CE5B5003DE5B5003EE5E6003FE5FE +:10F15000E60040E5010041E5000042E5000043E52E +:10F16000000044E5000045E5000046E5000047E5F5 +:10F17000000048E5000049E500004AE500004BE5D5 +:10F1800000004CE500004DE500004EE500004FE5B5 +:10F19000000050E5000051E5000052E5000053E595 +:10F1A000000054E5000055E5A20070E55D0071E542 +:10F1B000400072E5490073E5530074E5590075E5B8 +:10F1C0005E0076E5630077E5680078E56E0079E536 +:10F1D00074007AE57E007BE58A007CE598007DE599 +:10F1E000A8007EE5BB007FE5D00080E5FF0081E55B +:10F1F000040082E5000083E5040084E5040085E561 +:10F20000420086E5000087E5690088E55A00B0E520 +:10F210004800B1E51D00F0E53B00F1E56100F2E5D5 +:10F22000D200F3E53100F4E50100F5E51000F6E564 +:10F230001000F7E51000F8E51900F9E51900FAE506 +:10F240000000FBE50000FCE50000FDE50000FEE538 +:10F250000000FFE5000000E6000001E66D0002E6A8 +:10F26000650030E60000B0E61B00B1E63B00B2E608 +:10F27000BB00B3E67700B4E67700B5E67700B6E604 +:10F28000BB00B7E6B300B8E63300B9E60000BAE663 +:10F290000000BBE66400BCE66500BDE6DB00BEE640 +:10F2A000DB00BFE63300C0E6BB00C1E6F200C2E609 +:10F2B000FD00C3E6C600C4E60B0030E7030031E7FB +:10F2C000000032E7000037E7010038E7000039E7C7 +:10F2D0000000B0E70600B1E7F000B2E70300B3E7D3 +:10F2E0000500B4E74100B5E72400B6E78000B7E7C2 +:10F2F0001F00B8E7C700B9E71F00BAE71B00BBE76C +:10F300000000BCE70C00BDE70700BEE72000BFE738 +:10F310000000C0E70000C1E70000C2E70000C3E74B +:10F320000000C4E70C00C5E7F000C6E71F00C7E710 +:10F330000000C8E70C00C9E70000CAE70000CBE7FF +:10F34000AA00CCE76700CDE77E00CEE71D00CFE73F +:10F350000600D0E7000030E8000031E83E0032E867 +:10F36000140033E83F0034E80F0035E8770036E852 +:10F37000020073E8300074E8060075E8230076E8C0 +:10F38000650093E8000094E83F0095E8FF0096E8E8 +:10F39000500073EB1F0073EC410074EC510075ECEE +:10F3A000000033ED000034ED000035ED0000EDE02D +:10F3B000030000000000000000000000000000004A +:10F3C000000000000000000000000000000000003D +:10F3D000000000000000000000000000000000002D +:10F3E000000000000000000000000000000000001D +:10F3F000000000000000000000000000000000000D +:10F4000000000000000000000000000000000000FC +:10F4100000000000000000000000000000000000EC +:10F4200000000000000000000000000000000000DC +:10F4300000000000000000000000000000000000CC +:10F4400000000000000000000000000000000000BC +:10F4500000000000000000000000000000000000AC +:10F46000000000000000000000000000000000009C +:10F47000000000000000000000000000000000008C +:10F48000000000000000000000000000000000007C +:10F49000000000000000000000000000000000006C +:10F4A000000000000000000000000000000000005C +:10F4B000000000000000000000000000000000004C +:10F4C000000000000000000000000000000000003C +:10F4D000000000000000000000000000000000002C +:10F4E000000000000000000000000000000000001C +:10F4F000000000000000000000000000000000000C +:10F5000000000000000000000000000000000000FB +:10F5100000000000000000000000000000000000EB +:10F5200000000000000000000000000000000000DB +:10F5300000000000000000000000000000000000CB +:10F5400000000000000000000000000000000000BB +:10F5500000000000000000000000000000000000AB +:10F56000000000000000000000000000000000009B +:10F57000000000000000000000000000000000008B +:10F58000000000000000000000000000000000007B +:10F59000000000000000000000000000000000006B +:10F5A000000000000000000000000000000000005B +:10F5B000000000000000000000000000000000004B +:10F5C000000000000000000000000000000000003B +:10F5D000000000000000000000000000000000002B +:10F5E000000000000000000000000000000000001B +:10F5F000000000000000000000000000000000000B +:00000001FF diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 11bfa65a31f0b..75ad34895264f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1418,11 +1418,6 @@ static inline struct timespec ext4_current_time(struct inode *inode) static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) { return ino == EXT4_ROOT_INO || - ino == EXT4_USR_QUOTA_INO || - ino == EXT4_GRP_QUOTA_INO || - ino == EXT4_BOOT_LOADER_INO || - ino == EXT4_JOURNAL_INO || - ino == EXT4_RESIZE_INO || (ino >= EXT4_FIRST_INO(sb) && ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 90358b0de42b8..585c3e52eb20b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3923,7 +3923,8 @@ static int __ext4_get_inode_loc(struct inode *inode, int inodes_per_block, inode_offset; iloc->bh = NULL; - if (!ext4_valid_inum(sb, inode->i_ino)) + if (inode->i_ino < EXT4_ROOT_INO || + inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) return -EIO; iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index c8d782bf8c5ce..ee915ddc8578e 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -218,12 +218,12 @@ ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh) { int error; - if (buffer_verified(bh)) - return 0; - if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || BHDR(bh)->h_blocks != cpu_to_le32(1)) return -EIO; + if (buffer_verified(bh)) + return 0; + if (!ext4_xattr_block_csum_verify(inode, bh->b_blocknr, BHDR(bh))) return -EIO; error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, @@ -1385,6 +1385,11 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, /* Find the entry best suited to be pushed into EA block */ entry = NULL; for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { + /* never move system.data out of the inode */ + if ((last->e_name_len == 4) && + (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) && + !memcmp(last->e_name, "data", 4)) + continue; total_size = EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + EXT4_XATTR_LEN(last->e_name_len); diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 28ccc85bc1a12..fb8eef6be9f9d 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1411,7 +1411,7 @@ const struct file_operations proc_pagemap_operations = { #endif /* CONFIG_PROC_PAGE_MONITOR */ #ifdef CONFIG_PROCESS_RECLAIM -static int reclaim_pte_range(pmd_t *pmd, unsigned long addr, +int reclaim_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, struct mm_walk *walk) { struct reclaim_param *rp = walk->private; diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 273f06370dc1f..48231b0484d91 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -43,7 +43,7 @@ module_param(record_size, ulong, 0400); MODULE_PARM_DESC(record_size, "size of each dump done on oops/panic"); -static ulong ramoops_console_size = MIN_MEM_SIZE; +static ulong ramoops_console_size = 512*1024UL; module_param_named(console_size, ramoops_console_size, ulong, 0400); MODULE_PARM_DESC(console_size, "size of kernel console log"); @@ -51,16 +51,16 @@ static ulong ramoops_ftrace_size = MIN_MEM_SIZE; module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400); MODULE_PARM_DESC(ftrace_size, "size of ftrace log"); -static ulong ramoops_pmsg_size = MIN_MEM_SIZE; +static ulong ramoops_pmsg_size = 32*1024UL; module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400); MODULE_PARM_DESC(pmsg_size, "size of user space message log"); -static ulong mem_address; +static ulong mem_address = 0x9ff00000; module_param(mem_address, ulong, 0400); MODULE_PARM_DESC(mem_address, "start of reserved RAM used to store oops/panic logs"); -static ulong mem_size; +static ulong mem_size = 0x100000; module_param(mem_size, ulong, 0400); MODULE_PARM_DESC(mem_size, "size of reserved RAM used to store oops/panic logs"); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 982d333f56850..6e5c2777aa9af 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -298,11 +298,21 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, return ret; } +static void *memcpy_pstore(void *dest, const void *src, size_t count) +{ + char *tmp = dest; + const char *s = src; + + while (count--) + *tmp++ = *s++; + return dest; +} + static void notrace persistent_ram_update(struct persistent_ram_zone *prz, const void *s, unsigned int start, unsigned int count) { struct persistent_ram_buffer *buffer = prz->buffer; - memcpy(buffer->data + start, s, count); + memcpy_pstore(buffer->data + start, s, count); persistent_ram_update_ecc(prz, start, count); } diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 89423d02f93a2..96dfed5084494 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -95,8 +95,11 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, err = -ENOMEM; goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); + err = vfs_create2(lower_dentry_mnt, lower_parent_dentry->d_inode, lower_dentry, mode, want_excl); if (err) goto out; @@ -110,7 +113,9 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, fixup_lower_ownership(dentry, dentry->d_name.name); out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); free_fs_struct(copied_fs); out_unlock: unlock_dir(lower_parent_dentry); @@ -316,8 +321,11 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode unlock_dir(lower_parent_dentry); goto out_unlock; } + copied_fs->umask = 0; + task_lock(current); current->fs = copied_fs; - current->fs->umask = 0; + task_unlock(current); + err = vfs_mkdir2(lower_mnt, lower_parent_dentry->d_inode, lower_dentry, mode); if (err) { @@ -377,7 +385,10 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } } out: + task_lock(current); current->fs = saved_fs; + task_unlock(current); + free_fs_struct(copied_fs); out_unlock: sdcardfs_put_lower_path(dentry, &lower_path); diff --git a/fs/seq_file.c b/fs/seq_file.c index fbb1688bff87c..706b413e741ec 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -69,9 +69,11 @@ int seq_open(struct file *file, const struct seq_operations *op) memset(p, 0, sizeof(*p)); mutex_init(&p->lock); p->op = op; -#ifdef CONFIG_USER_NS - p->user_ns = file->f_cred->user_ns; -#endif + + /* No refcounting: the lifetime of 'p' is constrained + * to the lifetime of the file. + */ + p->file = file; /* * Wrappers around seq_open(e.g. swaps_open) need to be diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index dab9569f22bf7..9779c35f84540 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -91,8 +91,6 @@ static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) return alg->setkey != shash_no_setkey; } -bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg); - int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, struct hash_alg_common *alg, struct crypto_instance *inst); diff --git a/include/linux/fb.h b/include/linux/fb.h index 3cde50f14de03..50f8742b91a8c 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -503,6 +503,8 @@ struct fb_info { } *apertures; bool skip_vt_switch; /* no VT switch on suspend/resume required */ + + int blank; }; static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { diff --git a/include/linux/hqsysfs.h b/include/linux/hqsysfs.h new file mode 100644 index 0000000000000..60e6713e39038 --- /dev/null +++ b/include/linux/hqsysfs.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * Copyright (C) 2019 XiaoMi, Inc. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __HQ_SYSFS_HEAD__ +#define __HQ_SYSFS_HEAD__ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_OF +#include +#endif +#include + + + + +#define MAX_HW_DEVICE_NAME (64) + +enum hardware_id{ + HWID_NONE = 0x00, + HWID_DDR = 0x10, + HWID_EMMC, + HWID_NAND, + + HWID_LCM = 0x20, + HWID_SUB_LCM, + HWID_BIAS_IC, + HWID_CTP, + + HWID_MAIN_CAM = 0x30, + HWID_MAIN_CAM_2, + HWID_SUB_CAM, + HWID_SUB_CAM_2, + HWID_MAIN_LENS, + HWID_MAIN_LENS_2, + HWID_SUB_LENS, + HWID_SUB_LENS_2, + HWID_MAIN_OTP, + HWID_MAIN_OTP_2, + HWID_SUB_OTP, + HWID_SUB_OTP_2, + HWID_FLASHLIGHT, + HWID_FLaSHLIGHT_2, + + HWID_GSENSOR = 0x70, + HWID_ALSPS, + HWID_GYRO, + HWID_MSENSOR, + HWID_IRDA, + HWID_BAROMETER, + HWID_PEDOMETER, + HWID_HUMIDITY, + + HWID_PCBA = 0x80, + + HWID_BATERY = 0xA0, + HWID_FUEL_GAUGE_IC, + + HWID_NFC = 0xC0, + HWID_FP, + HWID_TEE, + + HWID_USB_TYPE_C = 0xE0, + + + HWID_SUMMARY = 0xF0, + HWID_VER, + HWID_END +}; + + +struct hw_info{ + enum hardware_id hw_id; + struct attribute attr; + unsigned int hw_exist; + + char *hw_device_name; +}; + + +#define __INFO(_id, _hw_type_name) { \ + .hw_id = _id, \ + .attr = {.name = __stringify(_hw_type_name), \ + .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR|S_IRUGO) }, \ + .hw_exist = 0, \ + .hw_device_name = NULL, \ + } + + +#define HW_INFO(_id, _hw_type_name) \ + struct hw_info hw_info_##_hw_type_name = __INFO(_id, _hw_type_name) + + + +#define HUAQIN_CLASS_NAME "huaqin" +#define HUAIN_INTERFACE_NAME "interface" +#define HUAQIN_HWID_NAME "hw_info" +#define HUAQIN_VERSION_FILE "hw_info_ver" + + + +int hq_regiser_hw_info(enum hardware_id id, char *device_name); +int hq_deregister_hw_info(enum hardware_id id, char *device_name); +int register_kboj_under_hqsysfs(struct kobject *kobj, struct kobj_type *ktype, const char *fmt, ...); + + +#endif diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h index 976b4bf48b653..fc16d8d94f5b5 100644 --- a/include/linux/input/synaptics_dsx.h +++ b/include/linux/input/synaptics_dsx.h @@ -1,11 +1,10 @@ /* - * Synaptics RMI4 touchscreen driver + * Synaptics DSX touchscreen driver * - * Copyright (C) 2012 Synaptics Incorporated + * Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved. * * Copyright (C) 2012 Alexandra Chin * Copyright (C) 2012 Scott Lin - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,73 +13,103 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. + * + * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS + * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, + * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. + * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION + * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED + * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES + * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' + * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. + * DOLLARS. */ #ifndef _SYNAPTICS_DSX_H_ #define _SYNAPTICS_DSX_H_ +#define PLATFORM_DRIVER_NAME "synaptics_dsx_v21" +#define STYLUS_DRIVER_NAME "synaptics_dsx_stylus" +#define ACTIVE_PEN_DRIVER_NAME "synaptics_dsx_active_pen" +#define PROXIMITY_DRIVER_NAME "synaptics_dsx_proximity" +#define GESTURE_DRIVER_NAME "synaptics_dsx_gesture" +#define I2C_DRIVER_NAME "synaptics_dsx_i2c" +#define SPI_DRIVER_NAME "synaptics_dsx_spi" + /* - * struct synaptics_rmi4_capacitance_button_map - 0d button map + * struct synaptics_dsx_button_map - button map * @nbuttons: number of buttons - * @map: button map + * @map: pointer to array of button codes */ -struct synaptics_rmi4_capacitance_button_map { +struct synaptics_dsx_button_map { unsigned char nbuttons; - unsigned char *map; + unsigned int *map; }; /* - * struct synaptics_rmi4_platform_data - rmi4 platform data + * struct synaptics_dsx_board_data - DSX board data * @x_flip: x flip flag * @y_flip: y flip flag - * @i2c_pull_up: pull up i2c bus with regulator - * @power_down_enable: enable complete regulator shutdown in suspend - * @irq_gpio: attention interrupt gpio - * @irq_flags: flags used by the irq - * @reset_flags: flags used by reset line - * @reset_gpio: reset gpio - * @panel_x: panel maximum values on the x - * @panel_y: panel maximum values on the y - * @disp_maxx: display panel maximum values on the x - * @disp_maxy: display panel maximum values on the y - * @disp_minx: display panel minimum values on the x - * @disp_miny: display panel minimum values on the y - * @panel_maxx: touch panel maximum values on the x - * @panel_maxy: touch panel maximum values on the y - * @panel_minx: touch panel minimum values on the x - * @panel_miny: touch panel minimum values on the y - * @reset_delay: reset delay - * @gpio_config: pointer to gpio configuration function - * @capacitance_button_map: pointer to 0d button map + * @swap_axes: swap axes flag + * @irq_gpio: attention interrupt GPIO + * @irq_on_state: attention interrupt active state + * @power_gpio: power switch GPIO + * @power_on_state: power switch active state + * @reset_gpio: reset GPIO + * @reset_on_state: reset active state + * @max_y_for_2d: maximum y value for 2D area when virtual buttons are present + * @irq_flags: IRQ flags + * @i2c_addr: I2C slave address + * @ub_i2c_addr: microbootloader mode I2C slave address + * @device_descriptor_addr: HID device descriptor address + * @panel_x: x-axis resolution of display panel + * @panel_y: y-axis resolution of display panel + * @power_delay_ms: delay time to wait after powering up device + * @reset_delay_ms: delay time to wait after resetting device + * @reset_active_ms: reset active time + * @byte_delay_us: delay time between two bytes of SPI data + * @block_delay_us: delay time between two SPI transfers + * @addr_delay_us: delay time after sending address word + * @pwr_reg_name: pointer to name of regulator for power control + * @bus_reg_name: pointer to name of regulator for bus pullup control + * @cap_button_map: pointer to 0D button map + * @vir_button_map: pointer to virtual button map */ -struct synaptics_rmi4_platform_data { +struct synaptics_dsx_board_data { bool x_flip; bool y_flip; - bool i2c_pull_up; - bool power_down_enable; - bool disable_gpios; - bool do_lockdown; - bool detect_device; - bool modify_reso; - unsigned irq_gpio; - u32 irq_flags; - u32 reset_flags; - unsigned reset_gpio; - unsigned panel_minx; - unsigned panel_miny; - unsigned panel_maxx; - unsigned panel_maxy; - unsigned disp_minx; - unsigned disp_miny; - unsigned disp_maxx; - unsigned disp_maxy; - unsigned reset_delay; - const char *fw_image_name; - unsigned int package_id; - int (*gpio_config)(unsigned gpio, bool configure); - struct synaptics_rmi4_capacitance_button_map *capacitance_button_map; + bool swap_axes; + int irq; + int irq_gpio; + int irq_on_state; + int power_gpio; + int power_on_state; + int reset_gpio; + int reset_on_state; + int display_reset_gpio; + int max_y_for_2d; + unsigned long irq_flags; + unsigned short i2c_addr; + unsigned short ub_i2c_addr; + unsigned short device_descriptor_addr; + unsigned int panel_x; + unsigned int panel_y; + unsigned int power_delay_ms; + unsigned int reset_delay_ms; + unsigned int reset_active_ms; + unsigned int byte_delay_us; + unsigned int block_delay_us; + unsigned int addr_delay_us; + const char *pwr_reg_name; + const char *bus_reg_name; + struct synaptics_dsx_button_map *cap_button_map; + struct synaptics_dsx_button_map *vir_button_map; }; #endif diff --git a/include/linux/leds-aw2023.h b/include/linux/leds-aw2023.h new file mode 100644 index 0000000000000..cb9709deb720d --- /dev/null +++ b/include/linux/leds-aw2023.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __LINUX_AW2023_LED_H__ +#define __LINUX_AW2023_LED_H__ + +/* The definition of each time described as shown in figure. + * /-----------\ + * / | \ + * /| | |\ + * / | | | \----------- + * |hold_time_ms | | + * | | | + * rise_time_ms fall_time_ms | + * off_time_ms + */ + +struct aw2023_platform_data { + int imax; + int led_current; + int rise_time_ms; + int hold_time_ms; + int fall_time_ms; + int off_time_ms; + struct aw2023_led *led; +}; + +#endif diff --git a/include/linux/mdss_io_util.h b/include/linux/mdss_io_util.h index 4a399762cf505..5aa60766a21bd 100644 --- a/include/linux/mdss_io_util.h +++ b/include/linux/mdss_io_util.h @@ -118,4 +118,6 @@ int mdss_i2c_byte_read(struct i2c_client *client, uint8_t slave_addr, int mdss_i2c_byte_write(struct i2c_client *client, uint8_t slave_addr, uint8_t reg_offset, uint8_t *value); +int mdss_prim_panel_fb_unblank(int timeout); + #endif /* __MDSS_IO_UTIL_H__ */ diff --git a/include/linux/mm.h b/include/linux/mm.h index 61c1ddc7ebb09..51cb40956ae60 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2201,6 +2201,9 @@ struct reclaim_param { }; extern struct reclaim_param reclaim_task_anon(struct task_struct *task, int nr_to_reclaim); +extern int reclaim_pte_range(pmd_t *pmd, unsigned long addr, + unsigned long end, struct mm_walk *walk); +extern unsigned long reclaim_global(unsigned long nr_to_reclaim); #endif #endif /* __KERNEL__ */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index af18d5d0245ee..74404b28e79b2 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -361,7 +361,7 @@ struct kioctx_table; struct mm_struct { struct vm_area_struct *mmap; /* list of VMAs */ struct rb_root mm_rb; - u32 vmacache_seqnum; /* per-thread vmacache */ + u64 vmacache_seqnum; /* per-thread vmacache */ #ifdef CONFIG_MMU unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr, unsigned long len, diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 35feeca7bf2c8..391f3a8a9d545 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -46,6 +46,8 @@ extern void *initial_boot_params; extern char __dtb_start[]; extern char __dtb_end[]; +extern void early_init_dt_setup_pureason_arch(unsigned long pu_reason); + /* For scanning the flat device-tree at boot time */ extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, int depth, void *data), diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 85c415342c166..97619a74b4109 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -3,6 +3,7 @@ /* * Copyright 1995 Linus Torvalds + * Copyright (C) 2019 XiaoMi, Inc. */ #include #include @@ -220,11 +221,6 @@ static inline struct page *__page_cache_alloc(gfp_t gfp) page = alloc_pages(gfp, 0); - if (page && is_cma_pageblock(page)) { - __free_page(page); - page = alloc_pages(gfp & ~__GFP_MOVABLE, 0); - } - return page; } #endif diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 7d3c3df658860..bf2c6cfdbdce9 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -267,6 +267,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_SERIAL_NUMBER, POWER_SUPPLY_PROP_BATTERY_TYPE, + POWER_SUPPLY_PROP_DUMP_SRAM, }; enum power_supply_type { diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h index da8f5a8622dde..9b4c06b75c95b 100644 --- a/include/linux/qpnp/power-on.h +++ b/include/linux/qpnp/power-on.h @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,6 +59,9 @@ enum pon_restart_reason { PON_RESTART_REASON_DMVERITY_CORRUPTED = 0x04, PON_RESTART_REASON_DMVERITY_ENFORCE = 0x05, PON_RESTART_REASON_KEYS_CLEAR = 0x06, + PON_RESTART_REASON_NORMAL = 0x20, + PON_RESTART_REASON_PANIC = 0x21, + PON_RESTART_REASON_OTHER = 0x00, }; #ifdef CONFIG_QPNP_POWER_ON @@ -68,6 +72,9 @@ int qpnp_pon_wd_config(bool enable); int qpnp_pon_set_restart_reason(enum pon_restart_reason reason); bool qpnp_pon_check_hard_reset_stored(void); +int qpnp_pon_is_lpk(void); +int qpnp_pon_is_ps_hold_reset(void); + #else static int qpnp_pon_system_pwr_off(enum pon_power_off_type type) { @@ -91,6 +98,8 @@ static inline bool qpnp_pon_check_hard_reset_stored(void) { return false; } +static inline int qpnp_pon_is_lpk(void) { return -ENODEV; } +static inline int qpnp_pon_is_ps_hold_reset(void) { return -ENODEV; } #endif #endif diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 611db59c52c55..c7a4cd5fda082 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -7,13 +7,10 @@ #include #include #include +#include +#include struct seq_operations; -struct file; -struct path; -struct inode; -struct dentry; -struct user_namespace; struct seq_file { char *buf; @@ -27,9 +24,7 @@ struct seq_file { struct mutex lock; const struct seq_operations *op; int poll_event; -#ifdef CONFIG_USER_NS - struct user_namespace *user_ns; -#endif + const struct file *file; void *private; }; @@ -151,7 +146,7 @@ int seq_put_decimal_ll(struct seq_file *m, char delimiter, static inline struct user_namespace *seq_user_ns(struct seq_file *seq) { #ifdef CONFIG_USER_NS - return seq->user_ns; + return seq->file->f_cred->user_ns; #else extern struct user_namespace init_user_ns; return &init_user_ns; diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index 7414d3984561e..b1041c11f1f77 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -677,6 +677,7 @@ static inline void msm_usb_irq_disable(bool disable) } #endif +int qusb_phy_run_dcd(struct usb_phy *phy); /* CONFIG_PM_RUNTIME */ #ifdef CONFIG_PM_RUNTIME static inline int get_pm_runtime_counter(struct device *dev) diff --git a/include/linux/vmacache.h b/include/linux/vmacache.h index c3fa0fd439499..4f58ff2dacd69 100644 --- a/include/linux/vmacache.h +++ b/include/linux/vmacache.h @@ -15,7 +15,6 @@ static inline void vmacache_flush(struct task_struct *tsk) memset(tsk->vmacache, 0, sizeof(tsk->vmacache)); } -extern void vmacache_flush_all(struct mm_struct *mm); extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma); extern struct vm_area_struct *vmacache_find(struct mm_struct *mm, unsigned long addr); @@ -29,10 +28,6 @@ extern struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm, static inline void vmacache_invalidate(struct mm_struct *mm) { mm->vmacache_seqnum++; - - /* deal with overflows */ - if (unlikely(mm->vmacache_seqnum == 0)) - vmacache_flush_all(mm); } #endif /* __LINUX_VMACACHE_H */ diff --git a/include/linux/zpool.h b/include/linux/zpool.h index 56529b34dc635..068e23ec64dbb 100644 --- a/include/linux/zpool.h +++ b/include/linux/zpool.h @@ -2,6 +2,7 @@ * zpool memory storage api * * Copyright (C) 2014 Dan Streetman + * Copyright (C) 2019 XiaoMi, Inc. * * This is a common frontend for the zbud and zsmalloc memory * storage pool implementations. Typically, this is used to @@ -36,10 +37,12 @@ enum zpool_mapmode { ZPOOL_MM_DEFAULT = ZPOOL_MM_RW }; -struct zpool *zpool_create_pool(char *type, char *name, - gfp_t gfp, struct zpool_ops *ops); +bool zpool_has_pool(char *type); -char *zpool_get_type(struct zpool *pool); +struct zpool *zpool_create_pool(const char *type, const char *name, + gfp_t gfp, const struct zpool_ops *ops); + +const char *zpool_get_type(struct zpool *pool); void zpool_destroy_pool(struct zpool *pool); @@ -81,7 +84,10 @@ struct zpool_driver { atomic_t refcount; struct list_head list; - void *(*create)(char *name, gfp_t gfp, struct zpool_ops *ops); + void *(*create)(const char *name, + gfp_t gfp, + const struct zpool_ops *ops, + struct zpool *zpool); void (*destroy)(void *pool); int (*malloc)(void *pool, size_t size, gfp_t gfp, @@ -102,6 +108,4 @@ void zpool_register_driver(struct zpool_driver *driver); int zpool_unregister_driver(struct zpool_driver *driver); -int zpool_evict(void *pool, unsigned long handle); - #endif diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h index 1338190b54783..57a8e98f2708c 100644 --- a/include/linux/zsmalloc.h +++ b/include/linux/zsmalloc.h @@ -34,12 +34,17 @@ enum zs_mapmode { */ }; +struct zs_pool_stats { + /* How many pages were migrated (freed) */ + unsigned long pages_compacted; +}; + struct zs_pool; -struct zs_pool *zs_create_pool(char *name, gfp_t flags); +struct zs_pool *zs_create_pool(const char *name); void zs_destroy_pool(struct zs_pool *pool); -unsigned long zs_malloc(struct zs_pool *pool, size_t size); +unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t flags); void zs_free(struct zs_pool *pool, unsigned long obj); void *zs_map_object(struct zs_pool *pool, unsigned long handle, @@ -49,4 +54,5 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle); unsigned long zs_get_total_pages(struct zs_pool *pool); unsigned long zs_compact(struct zs_pool *pool); +void zs_pool_stats(struct zs_pool *pool, struct zs_pool_stats *stats); #endif diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index aaacfcc467390..73952579aa341 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -8329,7 +8330,45 @@ struct afe_spkr_prot_calib_get_resp { struct asm_calib_res_cfg res_cfg; } __packed; +#ifdef CONFIG_SND_SOC_MAX98927 +/*Maxim DSM module and parameters IDs*/ +#define AFE_RX_TOPOLOGY_ID_DSM 0x10001061 +#define AFE_TX_TOPOLOGY_ID_DSM 0x10001060 +#define AFE_MODULE_DSM_TX 0x10001068 +#define AFE_MODULE_DSM_RX 0x10001062 +#define AFE_PARAM_ID_DSM_ENABLE 0x10001063 +#define AFE_PARAM_ID_CALIB 0x10001065 +#define AFE_PARAM_ID_DSM_CFG 0x10001066 +#define AFE_PARAM_ID_DSM_INFO 0x10001067 + +#define DSM_RX_PORT_ID AFE_PORT_ID_QUINARY_MI2S_RX +#define DSM_TX_PORT_ID AFE_PORT_ID_QUINARY_MI2S_TX + +struct afe_dsm_param_array { + uint32_t count; + uint32_t flagToWrite; + uint32_t Reserve[2]; + uint32_t params[100]; +}; +struct afe_dsm_set_command { + struct apr_hdr hdr; + struct afe_port_cmd_set_param_v2 param; + struct afe_port_param_data_v2 pdata; +} __packed; + +struct afe_dsm_get_command { + struct apr_hdr hdr; + struct afe_port_cmd_get_param_v2 param; + struct afe_port_param_data_v2 pdata; +} __packed; + +struct afe_dsm_get_resp { + uint32_t status; + struct afe_port_param_data_v2 pdata; + uint32_t payload[0]; +} __packed; +#endif /* SRS TRUMEDIA start */ /* topology */ #define SRS_TRUMEDIA_TOPOLOGY_ID 0x00010D90 diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 4a68a9075dd8d..630d3bf93c1b1 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -274,7 +274,7 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample); int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, - uint16_t bits_per_sample); + uint16_t bits_per_sample, bool ts_mode); int q6asm_open_write(struct audio_client *ac, uint32_t format /*, uint16_t bits_per_sample*/); diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index a8e046b8b0245..d0dc1852a8f41 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -273,7 +273,10 @@ #define KEY_F22 192 #define KEY_F23 193 #define KEY_F24 194 - +#define KEY_GESTURE_NAV_UP 195 +#define KEY_GESTURE_NAV_DOWN 196 +#define KEY_GESTURE_NAV_LEFT 197 +#define KEY_GESTURE_NAV_RIGHT 198 #define KEY_PLAYCD 200 #define KEY_PAUSECD 201 #define KEY_PROG3 202 diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 400196c45b3c1..9431f9669c820 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -707,6 +707,7 @@ struct usb_interface_assoc_descriptor { #define USB_DT_INTERFACE_ASSOCIATION_SIZE 8 + /*-------------------------------------------------------------------------*/ /* USB_DT_SECURITY: group of wireless security descriptors, including diff --git a/init/Kconfig b/init/Kconfig index de0994b3fa5bb..ac48e8cdaa198 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -826,7 +826,7 @@ config IKCONFIG_PROC config LOG_BUF_SHIFT int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" range 12 21 - default 17 + default 21 depends on PRINTK help Select the minimal kernel log buffer size as a power of 2. diff --git a/kernel/cpuset.c b/kernel/cpuset.c index da45b5e07692d..ecbcd52be43a7 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1468,6 +1468,26 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css, return ret; } +static int cpuset_allow_attach(struct cgroup_subsys_state *css, + struct cgroup_taskset *tset) +{ + const struct cred *cred = current_cred(), *tcred; + struct task_struct *task; + + if (capable(CAP_SYS_NICE)) + return 0; + + cgroup_taskset_for_each(task, tset) { + tcred = __task_cred(task); + + if (current != task && !uid_eq(cred->euid, tcred->uid) && + !uid_eq(cred->euid, tcred->suid)) + return -EACCES; + } + + return 0; +} + static void cpuset_cancel_attach(struct cgroup_subsys_state *css, struct cgroup_taskset *tset) { @@ -2087,6 +2107,7 @@ struct cgroup_subsys cpuset_cgrp_subsys = { .css_offline = cpuset_css_offline, .css_free = cpuset_css_free, .can_attach = cpuset_can_attach, + .allow_attach = cpuset_allow_attach, .cancel_attach = cpuset_cancel_attach, .attach = cpuset_attach, .bind = cpuset_bind, diff --git a/kernel/reboot.c b/kernel/reboot.c index 5925f5ae8dff0..76e6228907029 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -2,6 +2,7 @@ * linux/kernel/reboot.c * * Copyright (C) 2013 Linus Torvalds + * Copyright (C) 2019 XiaoMi, Inc. */ #define pr_fmt(fmt) "reboot: " fmt @@ -17,6 +18,9 @@ #include #include +#ifdef CONFIG_PROJECT_VINCE +bool pullDownReset = false; +#endif /* * this indicates whether you can reboot with ctrl-alt-del: the default is yes */ @@ -312,6 +316,14 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, cmd = LINUX_REBOOT_CMD_HALT; mutex_lock(&reboot_mutex); + +#ifdef CONFIG_PROJECT_VINCE + if (cmd == LINUX_REBOOT_CMD_RESTART || cmd == LINUX_REBOOT_CMD_POWER_OFF || + cmd == LINUX_REBOOT_CMD_RESTART2) { + pullDownReset = true; + } +#endif + switch (cmd) { case LINUX_REBOOT_CMD_RESTART: kernel_restart(NULL); diff --git a/kernel/resource.c b/kernel/resource.c index d3c9b3648e0cd..0a0c47faedb87 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -104,16 +104,25 @@ static int r_show(struct seq_file *m, void *v) { struct resource *root = m->private; struct resource *r = v, *p; + unsigned long long start, end; int width = root->end < 0x10000 ? 4 : 8; int depth; for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent) if (p->parent == root) break; + + if (file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN)) { + start = r->start; + end = r->end; + } else { + start = end = 0; + } + seq_printf(m, "%*s%0*llx-%0*llx : %s\n", depth * 2, "", - width, (unsigned long long) r->start, - width, (unsigned long long) r->end, + width, start, + width, end, r->name ? r->name : ""); return 0; } diff --git a/mm/debug.c b/mm/debug.c index a5cb434a6eaa8..ae49e99382346 100644 --- a/mm/debug.c +++ b/mm/debug.c @@ -169,7 +169,7 @@ EXPORT_SYMBOL(dump_vma); void dump_mm(const struct mm_struct *mm) { - pr_emerg("mm %p mmap %p seqnum %d task_size %lu\n" + pr_emerg("mm %p mmap %p seqnum %llu task_size %lu\n" #ifdef CONFIG_MMU "get_unmapped_area %p\n" #endif @@ -199,7 +199,7 @@ void dump_mm(const struct mm_struct *mm) #endif "%s", /* This is here to hold the comma */ - mm, mm->mmap, mm->vmacache_seqnum, mm->task_size, + mm, mm->mmap, (long long)mm->vmacache_seqnum, mm->task_size, #ifdef CONFIG_MMU mm->get_unmapped_area, #endif diff --git a/mm/page_alloc.c b/mm/page_alloc.c index fe6669dc5029d..8f9e110959f9a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5,6 +5,7 @@ * Note that kmalloc() lives in slab.c * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * Copyright (C) 2019 XiaoMi, Inc. * Swap reorganised 29.12.95, Stephen Tweedie * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 * Reshaped it to be a zoned allocator, Ingo Molnar, Red Hat, 1999 @@ -1157,7 +1158,8 @@ static void change_pageblock_range(struct page *pageblock_page, * If we claim more than half of the pageblock, change pageblock's migratetype * as well. */ -static bool can_steal_fallback(unsigned int order, int start_mt) +static bool can_steal_fallback(unsigned int order, int start_mt, + int fallback_type, unsigned int start_order) { /* * Leaving this order check is intended, although there is @@ -1169,10 +1171,15 @@ static bool can_steal_fallback(unsigned int order, int start_mt) if (order >= pageblock_order) return true; - if (order >= pageblock_order / 2 || - start_mt == MIGRATE_RECLAIMABLE || - start_mt == MIGRATE_UNMOVABLE || - page_group_by_mobility_disabled) + /* don't let unmovable allocations cause migrations simply because of free pages */ + if ((start_mt != MIGRATE_UNMOVABLE && order >= pageblock_order / 2) || + /* only steal reclaimable page blocks for unmovable allocations */ + (start_mt == MIGRATE_UNMOVABLE && fallback_type != MIGRATE_MOVABLE && order >= pageblock_order / 2) || + /* reclaimable can steal aggressively */ + start_mt == MIGRATE_RECLAIMABLE || + /* allow unmovable allocs up to 64K without migrating blocks */ + (start_mt == MIGRATE_UNMOVABLE && start_order >= 5) || + page_group_by_mobility_disabled) return true; return false; @@ -1207,7 +1214,7 @@ static void steal_suitable_fallback(struct zone *zone, struct page *page, /* Check whether there is a suitable fallback freepage with requested order. */ static int find_suitable_fallback(struct free_area *area, unsigned int order, - int migratetype, bool *can_steal) + int migratetype, bool *can_steal, unsigned int start_order) { int i; int fallback_mt; @@ -1224,7 +1231,7 @@ static int find_suitable_fallback(struct free_area *area, unsigned int order, if (list_empty(&area->free_list[fallback_mt])) continue; - if (can_steal_fallback(order, migratetype)) + if (can_steal_fallback(order, migratetype, fallback_mt, start_order)) *can_steal = true; return fallback_mt; @@ -1249,7 +1256,7 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype) --current_order) { area = &(zone->free_area[current_order]); fallback_mt = find_suitable_fallback(area, current_order, - start_migratetype, &can_steal); + start_migratetype, &can_steal, order); if (fallback_mt == -1) continue; diff --git a/mm/vmacache.c b/mm/vmacache.c index 9f25af825dec6..1c8004a3ca1a2 100644 --- a/mm/vmacache.c +++ b/mm/vmacache.c @@ -1,45 +1,11 @@ /* * Copyright (C) 2014 Davidlohr Bueso. + * Copyright (C) 2019 XiaoMi, Inc. */ #include #include #include -/* - * Flush vma caches for threads that share a given mm. - * - * The operation is safe because the caller holds the mmap_sem - * exclusively and other threads accessing the vma cache will - * have mmap_sem held at least for read, so no extra locking - * is required to maintain the vma cache. - */ -void vmacache_flush_all(struct mm_struct *mm) -{ - struct task_struct *g, *p; - - /* - * Single threaded tasks need not iterate the entire - * list of process. We can avoid the flushing as well - * since the mm's seqnum was increased and don't have - * to worry about other threads' seqnum. Current's - * flush will occur upon the next lookup. - */ - if (atomic_read(&mm->mm_users) == 1) - return; - - rcu_read_lock(); - for_each_process_thread(g, p) { - /* - * Only flush the vmacache pointers as the - * mm seqnum is already set and curr's will - * be set upon invalidation when the next - * lookup is done. - */ - if (mm == p->mm) - vmacache_flush(p); - } - rcu_read_unlock(); -} /* * This task may be accessing a foreign mm via (for example) diff --git a/mm/zpool.c b/mm/zpool.c index bacdab6e47de3..a05adf76c721b 100644 --- a/mm/zpool.c +++ b/mm/zpool.c @@ -2,6 +2,7 @@ * zpool memory storage api * * Copyright (C) 2014 Dan Streetman + * Copyright (C) 2019 XiaoMi, Inc. * * This is a common frontend for memory storage pool implementations. * Typically, this is used to store compressed memory. @@ -18,11 +19,9 @@ #include struct zpool { - char *type; - struct zpool_driver *driver; void *pool; - struct zpool_ops *ops; + const struct zpool_ops *ops; struct list_head list; }; @@ -73,34 +72,8 @@ int zpool_unregister_driver(struct zpool_driver *driver) } EXPORT_SYMBOL(zpool_unregister_driver); -/** - * zpool_evict() - evict callback from a zpool implementation. - * @pool: pool to evict from. - * @handle: handle to evict. - * - * This can be used by zpool implementations to call the - * user's evict zpool_ops struct evict callback. - */ -int zpool_evict(void *pool, unsigned long handle) -{ - struct zpool *zpool; - - spin_lock(&pools_lock); - list_for_each_entry(zpool, &pools_head, list) { - if (zpool->pool == pool) { - spin_unlock(&pools_lock); - if (!zpool->ops || !zpool->ops->evict) - return -EINVAL; - return zpool->ops->evict(zpool, handle); - } - } - spin_unlock(&pools_lock); - - return -ENOENT; -} -EXPORT_SYMBOL(zpool_evict); - -static struct zpool_driver *zpool_get_driver(char *type) +/* this assumes @type is null-terminated. */ +static struct zpool_driver *zpool_get_driver(const char *type) { struct zpool_driver *driver; @@ -126,6 +99,41 @@ static void zpool_put_driver(struct zpool_driver *driver) module_put(driver->owner); } +/** + * zpool_has_pool() - Check if the pool driver is available + * @type The type of the zpool to check (e.g. zbud, zsmalloc) + * + * This checks if the @type pool driver is available. This will try to load + * the requested module, if needed, but there is no guarantee the module will + * still be loaded and available immediately after calling. If this returns + * true, the caller should assume the pool is available, but must be prepared + * to handle the @zpool_create_pool() returning failure. However if this + * returns false, the caller should assume the requested pool type is not + * available; either the requested pool type module does not exist, or could + * not be loaded, and calling @zpool_create_pool() with the pool type will + * fail. + * + * The @type string must be null-terminated. + * + * Returns: true if @type pool is available, false if not + */ +bool zpool_has_pool(char *type) +{ + struct zpool_driver *driver = zpool_get_driver(type); + + if (!driver) { + request_module("zpool-%s", type); + driver = zpool_get_driver(type); + } + + if (!driver) + return false; + + zpool_put_driver(driver); + return true; +} +EXPORT_SYMBOL(zpool_has_pool); + /** * zpool_create_pool() - Create a new zpool * @type The type of the zpool to create (e.g. zbud, zsmalloc) @@ -139,15 +147,17 @@ static void zpool_put_driver(struct zpool_driver *driver) * * Implementations must guarantee this to be thread-safe. * + * The @type and @name strings must be null-terminated. + * * Returns: New zpool on success, NULL on failure. */ -struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp, - struct zpool_ops *ops) +struct zpool *zpool_create_pool(const char *type, const char *name, gfp_t gfp, + const struct zpool_ops *ops) { struct zpool_driver *driver; struct zpool *zpool; - pr_info("creating pool type %s\n", type); + pr_debug("creating pool type %s\n", type); driver = zpool_get_driver(type); @@ -168,9 +178,8 @@ struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp, return NULL; } - zpool->type = driver->type; zpool->driver = driver; - zpool->pool = driver->create(name, gfp, ops); + zpool->pool = driver->create(name, gfp, ops, zpool); zpool->ops = ops; if (!zpool->pool) { @@ -180,7 +189,7 @@ struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp, return NULL; } - pr_info("created %s pool\n", type); + pr_debug("created pool type %s\n", type); spin_lock(&pools_lock); list_add(&zpool->list, &pools_head); @@ -202,7 +211,7 @@ struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp, */ void zpool_destroy_pool(struct zpool *zpool) { - pr_info("destroying pool type %s\n", zpool->type); + pr_debug("destroying pool type %s\n", zpool->driver->type); spin_lock(&pools_lock); list_del(&zpool->list); @@ -222,9 +231,9 @@ void zpool_destroy_pool(struct zpool *zpool) * * Returns: The type of zpool. */ -char *zpool_get_type(struct zpool *zpool) +const char *zpool_get_type(struct zpool *zpool) { - return zpool->type; + return zpool->driver->type; } /** @@ -347,20 +356,6 @@ u64 zpool_get_total_size(struct zpool *zpool) return zpool->driver->total_size(zpool->pool); } -static int __init init_zpool(void) -{ - pr_info("loaded\n"); - return 0; -} - -static void __exit exit_zpool(void) -{ - pr_info("unloaded\n"); -} - -module_init(init_zpool); -module_exit(exit_zpool); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Dan Streetman "); MODULE_DESCRIPTION("Common API for compressed memory storage"); diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index a8b5e749e84e7..b6d4f258cb53c 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -16,7 +16,7 @@ * struct page(s) to form a zspage. * * Usage of struct page fields: - * page->first_page: points to the first component (0-order) page + * page->private: points to the first component (0-order) page * page->index (union with page->freelist): offset of the first object * starting in this page. For the first page, this is * always 0, so we use this field (aka freelist) to point @@ -26,8 +26,7 @@ * * For _first_ page only: * - * page->private (union with page->first_page): refers to the - * component page after the first page + * page->private: refers to the component page after the first page * If the page is first_page for huge object, it stores handle. * Look at size_class->huge. * page->freelist: points to the first free object in zspage. @@ -38,6 +37,7 @@ * page->lru: links together first pages of various zspages. * Basically forming list of zspages in a fullness group. * page->mapping: class index and fullness group of the zspage + * page->inuse: the number of objects that are used in this zspage * * Usage of struct page flags: * PG_private: identifies the first component page @@ -45,9 +45,7 @@ * */ -#ifdef CONFIG_ZSMALLOC_DEBUG -#define DEBUG -#endif +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -62,7 +60,7 @@ #include #include #include -#include +#include #include #include #include @@ -170,17 +168,20 @@ enum zs_stat_type { OBJ_USED, CLASS_ALMOST_FULL, CLASS_ALMOST_EMPTY, - NR_ZS_STAT_TYPE, }; #ifdef CONFIG_ZSMALLOC_STAT - -static struct dentry *zs_stat_root; +#define NR_ZS_STAT_TYPE (CLASS_ALMOST_EMPTY + 1) +#else +#define NR_ZS_STAT_TYPE (OBJ_USED + 1) +#endif struct zs_size_stat { unsigned long objs[NR_ZS_STAT_TYPE]; }; +#ifdef CONFIG_ZSMALLOC_STAT +static struct dentry *zs_stat_root; #endif /* @@ -205,6 +206,8 @@ static int zs_size_classes; static const int fullness_threshold_frac = 4; struct size_class { + spinlock_t lock; + struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS]; /* * Size of objects stored in this class. Must be multiple * of ZS_ALIGN. @@ -212,18 +215,12 @@ struct size_class { int size; unsigned int index; + struct zs_size_stat stats; + /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */ int pages_per_zspage; /* huge object: pages_per_zspage == 1 && maxobj_per_zspage == 1 */ bool huge; - -#ifdef CONFIG_ZSMALLOC_STAT - struct zs_size_stat stats; -#endif - - spinlock_t lock; - - struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS]; }; /* @@ -247,14 +244,22 @@ struct link_free { }; struct zs_pool { - char *name; + const char *name; struct size_class **size_class; struct kmem_cache *handle_cachep; - gfp_t flags; /* allocation flags used when growing pool */ atomic_long_t pages_allocated; + struct zs_pool_stats stats; + + /* Compact classes */ + struct shrinker shrinker; + /* + * To signify that register_shrinker() was successful + * and unregister_shrinker() will not Oops. + */ + bool shrinker_enabled; #ifdef CONFIG_ZSMALLOC_STAT struct dentry *stat_dentry; #endif @@ -277,7 +282,6 @@ struct mapping_area { #endif char *vm_addr; /* address of kmap_atomic()'ed pages */ enum zs_mapmode vm_mm; /* mapping mode */ - bool huge; }; static int create_handle_cache(struct zs_pool *pool) @@ -289,14 +293,13 @@ static int create_handle_cache(struct zs_pool *pool) static void destroy_handle_cache(struct zs_pool *pool) { - if (pool->handle_cachep) - kmem_cache_destroy(pool->handle_cachep); + kmem_cache_destroy(pool->handle_cachep); } -static unsigned long alloc_handle(struct zs_pool *pool) +static unsigned long alloc_handle(struct zs_pool *pool, gfp_t gfp) { return (unsigned long)kmem_cache_alloc(pool->handle_cachep, - pool->flags & ~__GFP_HIGHMEM); + gfp & ~__GFP_HIGHMEM); } static void free_handle(struct zs_pool *pool, unsigned long handle) @@ -306,16 +309,28 @@ static void free_handle(struct zs_pool *pool, unsigned long handle) static void record_obj(unsigned long handle, unsigned long obj) { - *(unsigned long *)handle = obj; + /* + * lsb of @obj represents handle lock while other bits + * represent object value the handle is pointing so + * updating shouldn't do store tearing. + */ + WRITE_ONCE(*(unsigned long *)handle, obj); } /* zpool driver */ #ifdef CONFIG_ZPOOL -static void *zs_zpool_create(char *name, gfp_t gfp, struct zpool_ops *zpool_ops) +static void *zs_zpool_create(const char *name, gfp_t gfp, + const struct zpool_ops *zpool_ops, + struct zpool *zpool) { - return zs_create_pool(name, gfp); + /* + * Ignore global gfp flags: zs_malloc() may be invoked from + * different contexts and its caller must provide a valid + * gfp mask. + */ + return zs_create_pool(name); } static void zs_zpool_destroy(void *pool) @@ -326,7 +341,7 @@ static void zs_zpool_destroy(void *pool) static int zs_zpool_malloc(void *pool, size_t size, gfp_t gfp, unsigned long *handle) { - *handle = zs_malloc(pool, size); + *handle = zs_malloc(pool, size, gfp); return *handle ? 0 : -1; } static void zs_zpool_free(void *pool, unsigned long handle) @@ -404,26 +419,28 @@ static int is_last_page(struct page *page) return PagePrivate2(page); } -static void get_zspage_mapping(struct page *page, unsigned int *class_idx, +static void get_zspage_mapping(struct page *first_page, + unsigned int *class_idx, enum fullness_group *fullness) { unsigned long m; - BUG_ON(!is_first_page(page)); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); - m = (unsigned long)page->mapping; + m = (unsigned long)first_page->mapping; *fullness = m & FULLNESS_MASK; *class_idx = (m >> FULLNESS_BITS) & CLASS_IDX_MASK; } -static void set_zspage_mapping(struct page *page, unsigned int class_idx, +static void set_zspage_mapping(struct page *first_page, + unsigned int class_idx, enum fullness_group fullness) { unsigned long m; - BUG_ON(!is_first_page(page)); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); m = ((class_idx & CLASS_IDX_MASK) << FULLNESS_BITS) | (fullness & FULLNESS_MASK); - page->mapping = (struct address_space *)m; + first_page->mapping = (struct address_space *)m; } /* @@ -444,36 +461,40 @@ static int get_size_class_index(int size) return min(zs_size_classes - 1, idx); } -#ifdef CONFIG_ZSMALLOC_STAT - static inline void zs_stat_inc(struct size_class *class, enum zs_stat_type type, unsigned long cnt) { - class->stats.objs[type] += cnt; + if (type < NR_ZS_STAT_TYPE) + class->stats.objs[type] += cnt; } static inline void zs_stat_dec(struct size_class *class, enum zs_stat_type type, unsigned long cnt) { - class->stats.objs[type] -= cnt; + if (type < NR_ZS_STAT_TYPE) + class->stats.objs[type] -= cnt; } static inline unsigned long zs_stat_get(struct size_class *class, enum zs_stat_type type) { - return class->stats.objs[type]; + if (type < NR_ZS_STAT_TYPE) + return class->stats.objs[type]; + return 0; } -static int __init zs_stat_init(void) +#ifdef CONFIG_ZSMALLOC_STAT + +static void __init zs_stat_init(void) { - if (!debugfs_initialized()) - return -ENODEV; + if (!debugfs_initialized()) { + pr_warn("debugfs not available, stat dir not created\n"); + return; + } zs_stat_root = debugfs_create_dir("zsmalloc", NULL); if (!zs_stat_root) - return -ENOMEM; - - return 0; + pr_warn("debugfs 'zsmalloc' stat dir creation failed\n"); } static void __exit zs_stat_exit(void) @@ -481,6 +502,8 @@ static void __exit zs_stat_exit(void) debugfs_remove_recursive(zs_stat_root); } +static unsigned long zs_can_compact(struct size_class *class); + static int zs_stats_size_show(struct seq_file *s, void *v) { int i; @@ -488,14 +511,15 @@ static int zs_stats_size_show(struct seq_file *s, void *v) struct size_class *class; int objs_per_zspage; unsigned long class_almost_full, class_almost_empty; - unsigned long obj_allocated, obj_used, pages_used; + unsigned long obj_allocated, obj_used, pages_used, freeable; unsigned long total_class_almost_full = 0, total_class_almost_empty = 0; unsigned long total_objs = 0, total_used_objs = 0, total_pages = 0; + unsigned long total_freeable = 0; - seq_printf(s, " %5s %5s %11s %12s %13s %10s %10s %16s\n", + seq_printf(s, " %5s %5s %11s %12s %13s %10s %10s %16s %8s\n", "class", "size", "almost_full", "almost_empty", "obj_allocated", "obj_used", "pages_used", - "pages_per_zspage"); + "pages_per_zspage", "freeable"); for (i = 0; i < zs_size_classes; i++) { class = pool->size_class[i]; @@ -508,6 +532,7 @@ static int zs_stats_size_show(struct seq_file *s, void *v) class_almost_empty = zs_stat_get(class, CLASS_ALMOST_EMPTY); obj_allocated = zs_stat_get(class, OBJ_ALLOCATED); obj_used = zs_stat_get(class, OBJ_USED); + freeable = zs_can_compact(class); spin_unlock(&class->lock); objs_per_zspage = get_maxobj_per_zspage(class->size, @@ -515,23 +540,25 @@ static int zs_stats_size_show(struct seq_file *s, void *v) pages_used = obj_allocated / objs_per_zspage * class->pages_per_zspage; - seq_printf(s, " %5u %5u %11lu %12lu %13lu %10lu %10lu %16d\n", + seq_printf(s, " %5u %5u %11lu %12lu %13lu" + " %10lu %10lu %16d %8lu\n", i, class->size, class_almost_full, class_almost_empty, obj_allocated, obj_used, pages_used, - class->pages_per_zspage); + class->pages_per_zspage, freeable); total_class_almost_full += class_almost_full; total_class_almost_empty += class_almost_empty; total_objs += obj_allocated; total_used_objs += obj_used; total_pages += pages_used; + total_freeable += freeable; } seq_puts(s, "\n"); - seq_printf(s, " %5s %5s %11lu %12lu %13lu %10lu %10lu\n", + seq_printf(s, " %5s %5s %11lu %12lu %13lu %10lu %10lu %16s %8lu\n", "Total", "", total_class_almost_full, total_class_almost_empty, total_objs, - total_used_objs, total_pages); + total_used_objs, total_pages, "", total_freeable); return 0; } @@ -548,17 +575,19 @@ static const struct file_operations zs_stat_size_ops = { .release = single_release, }; -static int zs_pool_stat_create(char *name, struct zs_pool *pool) +static void zs_pool_stat_create(struct zs_pool *pool, const char *name) { struct dentry *entry; - if (!zs_stat_root) - return -ENODEV; + if (!zs_stat_root) { + pr_warn("no root stat dir, not creating <%s> stat dir\n", name); + return; + } entry = debugfs_create_dir(name, zs_stat_root); if (!entry) { pr_warn("debugfs dir <%s> creation failed\n", name); - return -ENOMEM; + return; } pool->stat_dentry = entry; @@ -567,10 +596,9 @@ static int zs_pool_stat_create(char *name, struct zs_pool *pool) if (!entry) { pr_warn("%s: debugfs file entry <%s> creation failed\n", name, "classes"); - return -ENOMEM; + debugfs_remove_recursive(pool->stat_dentry); + pool->stat_dentry = NULL; } - - return 0; } static void zs_pool_stat_destroy(struct zs_pool *pool) @@ -579,44 +607,23 @@ static void zs_pool_stat_destroy(struct zs_pool *pool) } #else /* CONFIG_ZSMALLOC_STAT */ - -static inline void zs_stat_inc(struct size_class *class, - enum zs_stat_type type, unsigned long cnt) +static void __init zs_stat_init(void) { } -static inline void zs_stat_dec(struct size_class *class, - enum zs_stat_type type, unsigned long cnt) -{ -} - -static inline unsigned long zs_stat_get(struct size_class *class, - enum zs_stat_type type) -{ - return 0; -} - -static int __init zs_stat_init(void) -{ - return 0; -} - static void __exit zs_stat_exit(void) { } -static inline int zs_pool_stat_create(char *name, struct zs_pool *pool) +static inline void zs_pool_stat_create(struct zs_pool *pool, const char *name) { - return 0; } static inline void zs_pool_stat_destroy(struct zs_pool *pool) { } - #endif - /* * For each size class, zspages are divided into different groups * depending on how "full" they are. This was done so that we could @@ -624,14 +631,15 @@ static inline void zs_pool_stat_destroy(struct zs_pool *pool) * the pool (not yet implemented). This function returns fullness * status of the given page. */ -static enum fullness_group get_fullness_group(struct page *page) +static enum fullness_group get_fullness_group(struct page *first_page) { int inuse, max_objects; enum fullness_group fg; - BUG_ON(!is_first_page(page)); - inuse = page->inuse; - max_objects = page->objects; + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); + + inuse = first_page->inuse; + max_objects = first_page->objects; if (inuse == 0) fg = ZS_EMPTY; @@ -651,48 +659,59 @@ static enum fullness_group get_fullness_group(struct page *page) * have. This functions inserts the given zspage into the freelist * identified by . */ -static void insert_zspage(struct page *page, struct size_class *class, - enum fullness_group fullness) +static void insert_zspage(struct size_class *class, + enum fullness_group fullness, + struct page *first_page) { struct page **head; - BUG_ON(!is_first_page(page)); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); if (fullness >= _ZS_NR_FULLNESS_GROUPS) return; - head = &class->fullness_list[fullness]; - if (*head) - list_add_tail(&page->lru, &(*head)->lru); - - *head = page; zs_stat_inc(class, fullness == ZS_ALMOST_EMPTY ? CLASS_ALMOST_EMPTY : CLASS_ALMOST_FULL, 1); + + head = &class->fullness_list[fullness]; + if (!*head) { + *head = first_page; + return; + } + + /* + * We want to see more ZS_FULL pages and less almost + * empty/full. Put pages with higher ->inuse first. + */ + list_add_tail(&first_page->lru, &(*head)->lru); + if (first_page->inuse >= (*head)->inuse) + *head = first_page; } /* * This function removes the given zspage from the freelist identified * by . */ -static void remove_zspage(struct page *page, struct size_class *class, - enum fullness_group fullness) +static void remove_zspage(struct size_class *class, + enum fullness_group fullness, + struct page *first_page) { struct page **head; - BUG_ON(!is_first_page(page)); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); if (fullness >= _ZS_NR_FULLNESS_GROUPS) return; head = &class->fullness_list[fullness]; - BUG_ON(!*head); + VM_BUG_ON_PAGE(!*head, first_page); if (list_empty(&(*head)->lru)) *head = NULL; - else if (*head == page) + else if (*head == first_page) *head = (struct page *)list_entry((*head)->lru.next, struct page, lru); - list_del_init(&page->lru); + list_del_init(&first_page->lru); zs_stat_dec(class, fullness == ZS_ALMOST_EMPTY ? CLASS_ALMOST_EMPTY : CLASS_ALMOST_FULL, 1); } @@ -707,21 +726,19 @@ static void remove_zspage(struct page *page, struct size_class *class, * fullness group. */ static enum fullness_group fix_fullness_group(struct size_class *class, - struct page *page) + struct page *first_page) { int class_idx; enum fullness_group currfg, newfg; - BUG_ON(!is_first_page(page)); - - get_zspage_mapping(page, &class_idx, &currfg); - newfg = get_fullness_group(page); + get_zspage_mapping(first_page, &class_idx, &currfg); + newfg = get_fullness_group(first_page); if (newfg == currfg) goto out; - remove_zspage(page, class, currfg); - insert_zspage(page, class, newfg); - set_zspage_mapping(page, class_idx, newfg); + remove_zspage(class, currfg, first_page); + insert_zspage(class, newfg, first_page); + set_zspage_mapping(first_page, class_idx, newfg); out: return newfg; @@ -773,7 +790,7 @@ static struct page *get_first_page(struct page *page) if (is_first_page(page)) return page; else - return page->first_page; + return (struct page *)page_private(page); } static struct page *get_next_page(struct page *page) @@ -799,7 +816,7 @@ static void *location_to_obj(struct page *page, unsigned long obj_idx) unsigned long obj; if (!page) { - BUG_ON(obj_idx); + VM_BUG_ON(obj_idx); return NULL; } @@ -832,8 +849,8 @@ static unsigned long obj_to_head(struct size_class *class, struct page *page, void *obj) { if (class->huge) { - VM_BUG_ON(!is_first_page(page)); - return *(unsigned long *)page_private(page); + VM_BUG_ON_PAGE(!is_first_page(page), page); + return page_private(page); } else return *(unsigned long *)obj; } @@ -882,8 +899,8 @@ static void free_zspage(struct page *first_page) { struct page *nextp, *tmp, *head_extra; - BUG_ON(!is_first_page(first_page)); - BUG_ON(first_page->inuse); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); + VM_BUG_ON_PAGE(first_page->inuse, first_page); head_extra = (struct page *)page_private(first_page); @@ -904,12 +921,13 @@ static void free_zspage(struct page *first_page) } /* Initialize a newly allocated zspage */ -static void init_zspage(struct page *first_page, struct size_class *class) +static void init_zspage(struct size_class *class, struct page *first_page) { unsigned long off = 0; struct page *page = first_page; - BUG_ON(!is_first_page(first_page)); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); + while (page) { struct page *next_page; struct link_free *link; @@ -958,7 +976,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags) * Allocate individual pages and link them together as: * 1. first page->private = first sub-page * 2. all sub-pages are linked together using page->lru - * 3. each sub-page is linked to the first page using page->first_page + * 3. each sub-page is linked to the first page using page->private * * For each size class, First/Head pages are linked together using * page->lru. Also, we set PG_private to identify the first page @@ -983,7 +1001,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags) if (i == 1) set_page_private(first_page, (unsigned long)page); if (i >= 1) - page->first_page = first_page; + set_page_private(page, (unsigned long)first_page); if (i >= 2) list_add(&page->lru, &prev_page->lru); if (i == class->pages_per_zspage - 1) /* last page */ @@ -991,7 +1009,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags) prev_page = page; } - init_zspage(first_page, class); + init_zspage(class, first_page); first_page->freelist = location_to_obj(first_page, 0); /* Maximum number of objects we can store in this zspage */ @@ -1122,11 +1140,9 @@ static void __zs_unmap_object(struct mapping_area *area, goto out; buf = area->vm_buf; - if (!area->huge) { - buf = buf + ZS_HANDLE_SIZE; - size -= ZS_HANDLE_SIZE; - off += ZS_HANDLE_SIZE; - } + buf = buf + ZS_HANDLE_SIZE; + size -= ZS_HANDLE_SIZE; + off += ZS_HANDLE_SIZE; sizes[0] = PAGE_SIZE - off; sizes[1] = size - sizes[0]; @@ -1226,11 +1242,11 @@ static bool can_merge(struct size_class *prev, int size, int pages_per_zspage) return true; } -static bool zspage_full(struct page *page) +static bool zspage_full(struct page *first_page) { - BUG_ON(!is_first_page(page)); + VM_BUG_ON_PAGE(!is_first_page(first_page), first_page); - return page->inuse == page->objects; + return first_page->inuse == first_page->objects; } unsigned long zs_get_total_pages(struct zs_pool *pool) @@ -1266,14 +1282,12 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle, struct page *pages[2]; void *ret; - BUG_ON(!handle); - /* * Because we use per-cpu mapping areas shared among the * pools/users, we can't allow mapping in interrupt context * because it can corrupt another users mappings. */ - BUG_ON(in_interrupt()); + WARN_ON_ONCE(in_interrupt()); /* From now on, migration cannot move the object */ pin_tag(handle); @@ -1317,8 +1331,6 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) struct size_class *class; struct mapping_area *area; - BUG_ON(!handle); - obj = handle_to_obj(handle); obj_to_location(obj, &page, &obj_idx); get_zspage_mapping(get_first_page(page), &class_idx, &fg); @@ -1342,8 +1354,8 @@ void zs_unmap_object(struct zs_pool *pool, unsigned long handle) } EXPORT_SYMBOL_GPL(zs_unmap_object); -static unsigned long obj_malloc(struct page *first_page, - struct size_class *class, unsigned long handle) +static unsigned long obj_malloc(struct size_class *class, + struct page *first_page, unsigned long handle) { unsigned long obj; struct link_free *link; @@ -1383,7 +1395,7 @@ static unsigned long obj_malloc(struct page *first_page, * otherwise 0. * Allocation requests with size > ZS_MAX_ALLOC_SIZE will fail. */ -unsigned long zs_malloc(struct zs_pool *pool, size_t size) +unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp) { unsigned long handle, obj; struct size_class *class; @@ -1392,7 +1404,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size) if (unlikely(!size || size > ZS_MAX_ALLOC_SIZE)) return 0; - handle = alloc_handle(pool); + handle = alloc_handle(pool, gfp); if (!handle) return 0; @@ -1405,7 +1417,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size) if (!first_page) { spin_unlock(&class->lock); - first_page = alloc_zspage(class, pool->flags); + first_page = alloc_zspage(class, gfp); if (unlikely(!first_page)) { free_handle(pool, handle); return 0; @@ -1420,7 +1432,7 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size) class->size, class->pages_per_zspage)); } - obj = obj_malloc(first_page, class, handle); + obj = obj_malloc(class, first_page, handle); /* Now move the zspage to another fullness group, if required */ fix_fullness_group(class, first_page); record_obj(handle, obj); @@ -1430,23 +1442,17 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size) } EXPORT_SYMBOL_GPL(zs_malloc); -static void obj_free(struct zs_pool *pool, struct size_class *class, - unsigned long obj) +static void obj_free(struct size_class *class, unsigned long obj) { struct link_free *link; struct page *first_page, *f_page; unsigned long f_objidx, f_offset; void *vaddr; - int class_idx; - enum fullness_group fullness; - - BUG_ON(!obj); obj &= ~OBJ_ALLOCATED_TAG; obj_to_location(obj, &f_page, &f_objidx); first_page = get_first_page(f_page); - get_zspage_mapping(first_page, &class_idx, &fullness); f_offset = obj_idx_to_offset(f_page, f_objidx, class->size); vaddr = kmap_atomic(f_page); @@ -1482,7 +1488,7 @@ void zs_free(struct zs_pool *pool, unsigned long handle) class = pool->size_class[class_idx]; spin_lock(&class->lock); - obj_free(pool, class, obj); + obj_free(class, obj); fullness = fix_fullness_group(class, first_page); if (fullness == ZS_EMPTY) { zs_stat_dec(class, OBJ_ALLOCATED, get_maxobj_per_zspage( @@ -1498,8 +1504,8 @@ void zs_free(struct zs_pool *pool, unsigned long handle) } EXPORT_SYMBOL_GPL(zs_free); -static void zs_object_copy(unsigned long src, unsigned long dst, - struct size_class *class) +static void zs_object_copy(struct size_class *class, unsigned long dst, + unsigned long src) { struct page *s_page, *d_page; unsigned long s_objidx, d_objidx; @@ -1542,7 +1548,6 @@ static void zs_object_copy(unsigned long src, unsigned long dst, kunmap_atomic(d_addr); kunmap_atomic(s_addr); s_page = get_next_page(s_page); - BUG_ON(!s_page); s_addr = kmap_atomic(s_page); d_addr = kmap_atomic(d_page); s_size = class->size - written; @@ -1552,7 +1557,6 @@ static void zs_object_copy(unsigned long src, unsigned long dst, if (d_off >= PAGE_SIZE) { kunmap_atomic(d_addr); d_page = get_next_page(d_page); - BUG_ON(!d_page); d_addr = kmap_atomic(d_page); d_size = class->size - written; d_off = 0; @@ -1567,8 +1571,8 @@ static void zs_object_copy(unsigned long src, unsigned long dst, * Find alloced object in zspage from index object and * return handle. */ -static unsigned long find_alloced_obj(struct page *page, int index, - struct size_class *class) +static unsigned long find_alloced_obj(struct size_class *class, + struct page *page, int index) { unsigned long head; int offset = 0; @@ -1605,8 +1609,6 @@ struct zs_compact_control { /* Starting object index within @s_page which used for live object * in the subpage. */ int index; - /* how many of objects are migrated */ - int nr_migrated; }; static int migrate_zspage(struct zs_pool *pool, struct size_class *class, @@ -1617,11 +1619,10 @@ static int migrate_zspage(struct zs_pool *pool, struct size_class *class, struct page *s_page = cc->s_page; struct page *d_page = cc->d_page; unsigned long index = cc->index; - int nr_migrated = 0; int ret = 0; while (1) { - handle = find_alloced_obj(s_page, index, class); + handle = find_alloced_obj(class, s_page, index); if (!handle) { s_page = get_next_page(s_page); if (!s_page) @@ -1638,24 +1639,29 @@ static int migrate_zspage(struct zs_pool *pool, struct size_class *class, } used_obj = handle_to_obj(handle); - free_obj = obj_malloc(d_page, class, handle); - zs_object_copy(used_obj, free_obj, class); + free_obj = obj_malloc(class, d_page, handle); + zs_object_copy(class, free_obj, used_obj); index++; + /* + * record_obj updates handle's value to free_obj and it will + * invalidate lock bit(ie, HANDLE_PIN_BIT) of handle, which + * breaks synchronization using pin_tag(e,g, zs_free) so + * let's keep the lock bit. + */ + free_obj |= BIT(HANDLE_PIN_BIT); record_obj(handle, free_obj); unpin_tag(handle); - obj_free(pool, class, used_obj); - nr_migrated++; + obj_free(class, used_obj); } /* Remember last position in this iteration */ cc->s_page = s_page; cc->index = index; - cc->nr_migrated = nr_migrated; return ret; } -static struct page *alloc_target_page(struct size_class *class) +static struct page *isolate_target_page(struct size_class *class) { int i; struct page *page; @@ -1663,7 +1669,7 @@ static struct page *alloc_target_page(struct size_class *class) for (i = 0; i < _ZS_NR_FULLNESS_GROUPS; i++) { page = class->fullness_list[i]; if (page) { - remove_zspage(page, class, i); + remove_zspage(class, i, page); break; } } @@ -1671,15 +1677,22 @@ static struct page *alloc_target_page(struct size_class *class) return page; } -static void putback_zspage(struct zs_pool *pool, struct size_class *class, - struct page *first_page) +/* + * putback_zspage - add @first_page into right class's fullness list + * @pool: target pool + * @class: destination class + * @first_page: target page + * + * Return @fist_page's fullness_group + */ +static enum fullness_group putback_zspage(struct zs_pool *pool, + struct size_class *class, + struct page *first_page) { enum fullness_group fullness; - BUG_ON(!is_first_page(first_page)); - fullness = get_fullness_group(first_page); - insert_zspage(first_page, class, fullness); + insert_zspage(class, fullness, first_page); set_zspage_mapping(first_page, class->index, fullness); if (fullness == ZS_EMPTY) { @@ -1690,50 +1703,73 @@ static void putback_zspage(struct zs_pool *pool, struct size_class *class, free_zspage(first_page); } + + return fullness; } static struct page *isolate_source_page(struct size_class *class) { - struct page *page; + int i; + struct page *page = NULL; - page = class->fullness_list[ZS_ALMOST_EMPTY]; - if (page) - remove_zspage(page, class, ZS_ALMOST_EMPTY); + for (i = ZS_ALMOST_EMPTY; i >= ZS_ALMOST_FULL; i--) { + page = class->fullness_list[i]; + if (!page) + continue; + + remove_zspage(class, i, page); + break; + } return page; } -static unsigned long __zs_compact(struct zs_pool *pool, - struct size_class *class) +/* + * + * Based on the number of unused allocated objects calculate + * and return the number of pages that we can free. + */ +static unsigned long zs_can_compact(struct size_class *class) +{ + unsigned long obj_wasted; + unsigned long obj_allocated = zs_stat_get(class, OBJ_ALLOCATED); + unsigned long obj_used = zs_stat_get(class, OBJ_USED); + + if (obj_allocated <= obj_used) + return 0; + + obj_wasted = obj_allocated - obj_used; + obj_wasted /= get_maxobj_per_zspage(class->size, + class->pages_per_zspage); + + return obj_wasted * class->pages_per_zspage; +} + +static void __zs_compact(struct zs_pool *pool, struct size_class *class) { - int nr_to_migrate; struct zs_compact_control cc; struct page *src_page; struct page *dst_page = NULL; - unsigned long nr_total_migrated = 0; spin_lock(&class->lock); while ((src_page = isolate_source_page(class))) { - BUG_ON(!is_first_page(src_page)); + if (!zs_can_compact(class)) + break; - /* The goal is to migrate all live objects in source page */ - nr_to_migrate = src_page->inuse; cc.index = 0; cc.s_page = src_page; - while ((dst_page = alloc_target_page(class))) { + while ((dst_page = isolate_target_page(class))) { cc.d_page = dst_page; /* - * If there is no more space in dst_page, try to - * allocate another zspage. + * If there is no more space in dst_page, resched + * and see if anyone had allocated another zspage. */ if (!migrate_zspage(pool, class, &cc)) break; putback_zspage(pool, class, dst_page); - nr_total_migrated += cc.nr_migrated; - nr_to_migrate -= cc.nr_migrated; } /* Stop if we couldn't find slot */ @@ -1741,9 +1777,9 @@ static unsigned long __zs_compact(struct zs_pool *pool, break; putback_zspage(pool, class, dst_page); - putback_zspage(pool, class, src_page); + if (putback_zspage(pool, class, src_page) == ZS_EMPTY) + pool->stats.pages_compacted += class->pages_per_zspage; spin_unlock(&class->lock); - nr_total_migrated += cc.nr_migrated; cond_resched(); spin_lock(&class->lock); } @@ -1752,14 +1788,11 @@ static unsigned long __zs_compact(struct zs_pool *pool, putback_zspage(pool, class, src_page); spin_unlock(&class->lock); - - return nr_total_migrated; } unsigned long zs_compact(struct zs_pool *pool) { int i; - unsigned long nr_migrated = 0; struct size_class *class; for (i = zs_size_classes - 1; i >= 0; i--) { @@ -1768,13 +1801,77 @@ unsigned long zs_compact(struct zs_pool *pool) continue; if (class->index != i) continue; - nr_migrated += __zs_compact(pool, class); + __zs_compact(pool, class); } - return nr_migrated; + return pool->stats.pages_compacted; } EXPORT_SYMBOL_GPL(zs_compact); +void zs_pool_stats(struct zs_pool *pool, struct zs_pool_stats *stats) +{ + memcpy(stats, &pool->stats, sizeof(struct zs_pool_stats)); +} +EXPORT_SYMBOL_GPL(zs_pool_stats); + +static unsigned long zs_shrinker_scan(struct shrinker *shrinker, + struct shrink_control *sc) +{ + unsigned long pages_freed; + struct zs_pool *pool = container_of(shrinker, struct zs_pool, + shrinker); + + pages_freed = pool->stats.pages_compacted; + /* + * Compact classes and calculate compaction delta. + * Can run concurrently with a manually triggered + * (by user) compaction. + */ + pages_freed = zs_compact(pool) - pages_freed; + + return pages_freed ? pages_freed : SHRINK_STOP; +} + +static unsigned long zs_shrinker_count(struct shrinker *shrinker, + struct shrink_control *sc) +{ + int i; + struct size_class *class; + unsigned long pages_to_free = 0; + struct zs_pool *pool = container_of(shrinker, struct zs_pool, + shrinker); + + for (i = zs_size_classes - 1; i >= 0; i--) { + class = pool->size_class[i]; + if (!class) + continue; + if (class->index != i) + continue; + + pages_to_free += zs_can_compact(class); + } + + return pages_to_free; +} + +static void zs_unregister_shrinker(struct zs_pool *pool) +{ + if (pool->shrinker_enabled) { + unregister_shrinker(&pool->shrinker); + pool->shrinker_enabled = false; + } +} + +static int zs_register_shrinker(struct zs_pool *pool) +{ + pool->shrinker.scan_objects = zs_shrinker_scan; + pool->shrinker.count_objects = zs_shrinker_count; + pool->shrinker.batch = 0; + pool->shrinker.seeks = DEFAULT_SEEKS; + + return register_shrinker(&pool->shrinker); +} + /** * zs_create_pool - Creates an allocation pool to work from. * @flags: allocation flags used to allocate pool metadata @@ -1785,7 +1882,7 @@ EXPORT_SYMBOL_GPL(zs_compact); * On success, a pointer to the newly created pool is returned, * otherwise NULL. */ -struct zs_pool *zs_create_pool(char *name, gfp_t flags) +struct zs_pool *zs_create_pool(const char *name) { int i; struct zs_pool *pool; @@ -1855,11 +1952,15 @@ struct zs_pool *zs_create_pool(char *name, gfp_t flags) prev_class = class; } - pool->flags = flags; - - if (zs_pool_stat_create(name, pool)) - goto err; + /* debug only, don't abort if it fails */ + zs_pool_stat_create(pool, name); + /* + * Not critical, we still can use the pool + * and user can trigger compaction manually. + */ + if (zs_register_shrinker(pool) == 0) + pool->shrinker_enabled = true; return pool; err: @@ -1872,6 +1973,7 @@ void zs_destroy_pool(struct zs_pool *pool) { int i; + zs_unregister_shrinker(pool); zs_pool_stat_destroy(pool); for (i = 0; i < zs_size_classes; i++) { @@ -1913,17 +2015,10 @@ static int __init zs_init(void) zpool_register_driver(&zs_zpool_driver); #endif - ret = zs_stat_init(); - if (ret) { - pr_err("zs stat initialization failed\n"); - goto stat_fail; - } + zs_stat_init(); + return 0; -stat_fail: -#ifdef CONFIG_ZPOOL - zpool_unregister_driver(&zs_zpool_driver); -#endif notifier_fail: zs_unregister_cpu_notifier(); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 41b1819d8ab85..6f78baeefd7db 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -482,8 +482,13 @@ static int mark_source_chains(const struct xt_table_info *newinfo, static inline int check_entry(const struct arpt_entry *e) { + long size_of_base_struct = e->elems - (const unsigned char *)e; const struct xt_entry_target *t; + /* target start is within the ip/ip6/arpt_entry struct */ + if (e->target_offset < size_of_base_struct) + return -EINVAL; + if (!arp_checkentry(&e->arp)) return -EINVAL; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2bd31846858c6..8e787a9d4c935 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -576,8 +576,13 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) static int check_entry(const struct ipt_entry *e) { + long size_of_base_struct = e->elems - (const unsigned char *)e; const struct xt_entry_target *t; + /* target start is within the ip/ip6/arpt_entry struct */ + if (e->target_offset < size_of_base_struct) + return -EINVAL; + if (!ip_checkentry(&e->ip)) return -EINVAL; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 71e0084ca383a..7ac46537db8c0 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -586,8 +586,13 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net) static int check_entry(const struct ip6t_entry *e) { + long size_of_base_struct = e->elems - (const unsigned char *)e; const struct xt_entry_target *t; + /* target start is within the ip/ip6/arpt_entry struct */ + if (e->target_offset < size_of_base_struct) + return -EINVAL; + if (!ip6_checkentry(&e->ipv6)) return -EINVAL; diff --git a/net/key/af_key.c b/net/key/af_key.c index fbd25f58d18e6..84c141c6b2a9e 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock) return 0; } -static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, - gfp_t allocation, struct sock *sk) +static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation, + struct sock *sk) { int err = -ENOBUFS; - sock_hold(sk); - if (*skb2 == NULL) { - if (atomic_read(&skb->users) != 1) { - *skb2 = skb_clone(skb, allocation); - } else { - *skb2 = skb; - atomic_inc(&skb->users); - } - } - if (*skb2 != NULL) { - if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { - skb_set_owner_r(*skb2, sk); - skb_queue_tail(&sk->sk_receive_queue, *skb2); - sk->sk_data_ready(sk); - *skb2 = NULL; - err = 0; - } + if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) + return err; + + skb = skb_clone(skb, allocation); + + if (skb) { + skb_set_owner_r(skb, sk); + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk); + err = 0; } - sock_put(sk); return err; } @@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, { struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); struct sock *sk; - struct sk_buff *skb2 = NULL; int err = -ESRCH; /* XXX Do we need something like netlink_overrun? I think @@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, * socket. */ if (pfk->promisc) - pfkey_broadcast_one(skb, &skb2, allocation, sk); + pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* the exact target will be processed later */ if (sk == one_sk) @@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, continue; } - err2 = pfkey_broadcast_one(skb, &skb2, allocation, sk); + err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk); /* Error is cleare after succecful sending to at least one * registered KM */ @@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, rcu_read_unlock(); if (one_sk != NULL) - err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); + err = pfkey_broadcast_one(skb, allocation, one_sk); - kfree_skb(skb2); kfree_skb(skb); return err; } diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 649ce68440331..c6c7af12e9b57 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -78,6 +78,7 @@ $(warning kbuild: Makefile.build is included improperly) endif # =========================================================================== +#LIB_STA := $(srctree)/drivers/video/msm/mdss/libmdss_get_rc.a ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),) lib-target := $(obj)/lib.a diff --git a/security/commoncap.c b/security/commoncap.c index 740966aeb0bba..49587399a1ac8 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -96,8 +96,10 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, for (;;) { /* Do we have the necessary capabilities? */ if (ns == cred->user_ns) - return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; - +#ifdef FACTORY_VERSION_ENABLE + return 0; +#endif + return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; /* Have we tried all of the parent namespaces? */ if (ns == &init_user_ns) return -EPERM; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 3ca46e5e43dc5..0a4fa33c2b2a4 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -1,6 +1,7 @@ /* Request a key from userspace * * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2019 XiaoMi, Inc. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -466,16 +467,11 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, ret = construct_get_dest_keyring(&dest_keyring); if (ret) goto error; - - if (ctx->index_key.type == &key_type_keyring) - return ERR_PTR(-EPERM); - user = key_user_lookup(current_fsuid()); if (!user) { ret = -ENOMEM; goto error_put_dest_keyring; } - ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); key_user_put(user); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index c936371c7f871..2abe138be29b5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -164,6 +164,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS select SND_SOC_WM9713 if SND_SOC_AC97_BUS + select SND_SOC_MAX98927 if I2C help Normally ASoC codec drivers are only built if a machine driver which uses them is also built since they are only usable with a machine @@ -879,4 +880,31 @@ config SND_SOC_MSM_HDMI_CODEC_RX config SND_SOC_MSM_HDMI_DBA_CODEC_RX bool "HDMI DBA Audio Playback" depends on MSM_DBA + +config SND_SOC_MAX98927 + tristate "Audio SMART PA 98927 support" + help + Say Y here to enable Audio SMART PA support. This allows + monitoring switches by userspace via sysfs and uevent. + +config MBHC_UART + bool "audio MBHC with UART" + help + Say Y here to use UART para. + +menuconfig SND_SOC_TAS2557 + tristate "Texas Instruments TAS2557 SmartAmp(R)" + +if SND_SOC_TAS2557 +config TAS2557_REGMAP + bool "Use of RegMap API" + +config TAS2557_CODEC + bool "Codec Driver support" + +config TAS2557_MISC + bool "Misc Driver support" + +endif + endmenu diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 39e419308fb99..fe4654f5f7331 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -191,6 +191,8 @@ obj-$(CONFIG_SND_SOC_MSM_HDMI_DBA_CODEC_RX) := msm_hdmi_dba_codec_rx.o snd-soc-max9877-objs := max9877.o snd-soc-tpa6130a2-objs := tpa6130a2.o snd-soc-tas2552-objs := tas2552.o +snd-soc-max98927-objs := max98927.o +snd-soc-tas2557-objs := tas2557-core.o tas2557-regmap.o tas2557-codec.o tas2557-misc.o tiload.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o @@ -380,3 +382,5 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o # Amp obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o +obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o +obj-$(CONFIG_SND_SOC_TAS2557) += snd-soc-tas2557.o diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c new file mode 100644 index 0000000000000..fe2fb626a18f1 --- /dev/null +++ b/sound/soc/codecs/max98927.c @@ -0,0 +1,2428 @@ +/* + * max98927.c -- ALSA SoC Stereo MAX98927 driver + * Copyright 2013-15 Maxim Integrated Products + * Copyright (C) 2019 XiaoMi, Inc. + * 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 +#include "max98927.h" + +#if 0 +#undef pr_info +#define pr_info pr_err + +#undef pr_debug +#define pr_debug pr_err +#endif + +/* #define USE_PA_MAX98928 1 */ + +struct max98927_priv *g_max98927 = NULL; +EXPORT_SYMBOL_GPL(g_max98927); + + +#define USE_DSM_MISC_DEV 1 +#ifdef USE_PA_MAX98928 +#define MAX_BOOST_VOLT (0xc) +#else +#define MAX_BOOST_VOLT (0x1c) +#endif + +#ifdef USE_DSM_MISC_DEV +extern int afe_dsm_rx_set_params(uint8_t *payload, int size); +extern int afe_dsm_rx_get_params(uint8_t *payload, int size); +extern int afe_dsm_set_calib(uint8_t *payload); +extern int afe_dsm_pre_calib(uint8_t *payload); +extern int afe_dsm_post_calib(uint8_t *payload); +extern int afe_dsm_get_calib(uint8_t *payload); +extern int afe_dsm_get_average_calib(uint8_t *payload); +extern int afe_dsm_ramp_dn_cfg(uint8_t *payload, int delay_in_ms); +extern int afe_dsm_get_libary_info(uint32_t *payload, int size); +static DEFINE_MUTEX(dsm_lock); +#endif + +#define Q_DSM_ADAPTIVE_FC 9 +#define Q_DSM_ADAPTIVE_DC_RES 27 + +static unsigned int i2c_states; +static int delay_array_msec[] = {10, 20, 30, 40, 50}; + +int reg_common_map[][2] = { + {MAX98927_Brownout_level_infinite_hold, 0x00}, + {MAX98927_Brownout_level_hold, 0x00}, + {MAX98927_Brownout__level_1_current_limit, 0x14}, + {MAX98927_Brownout__level_1_amp_1_control_1, 0x00}, + {MAX98927_Brownout__level_1_amp_1_control_2, 0x0c}, + {MAX98927_Brownout__level_1_amp_1_control_3, 0x00}, + {MAX98927_Brownout__level_2_current_limit, 0x10}, + {MAX98927_Brownout__level_2_amp_1_control_1, 0x00}, + {MAX98927_Brownout__level_2_amp_1_control_2, 0x0c}, + {MAX98927_Brownout__level_2_amp_1_control_3, 0x00}, + {MAX98927_Brownout__level_3_current_limit, 0x0c}, + {MAX98927_Brownout__level_3_amp_1_control_1, 0x06}, + {MAX98927_Brownout__level_3_amp_1_control_2, 0x18}, + {MAX98927_Brownout__level_3_amp_1_control_3, 0x0c}, + {MAX98927_Brownout__level_4_current_limit, 0x08}, + {MAX98927_Brownout__level_4_amp_1_control_1, 0x0e}, + {MAX98927_Brownout__level_4_amp_1_control_2, 0x80}, + {MAX98927_Brownout__level_4_amp_1_control_3, 0x00}, + {MAX98927_Brownout_threshold_hysterysis, 0x00}, + {MAX98927_Brownout_AMP_limiter_attack_release, 0x00}, + {MAX98927_Brownout_AMP_gain_attack_release, 0x00}, + {MAX98927_Brownout_AMP1_clip_mode, 0x00}, + {MAX98927_Meas_ADC_Config, 0x07}, + {MAX98927_Meas_ADC_Thermal_Warning_Threshhold, 0x78}, + {MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold, 0xFF}, + {MAX98927_Pin_Config, 0x55}, + {MAX98927_Measurement_DSP_Config, 0xF7}, + {MAX98927_PCM_Tx_Enables_B, 0x00}, + {MAX98927_PCM_Rx_Enables_B, 0x00}, + {MAX98927_PCM_Tx_Channel_Sources_B, 0x00}, + {MAX98927_PCM_Tx_HiZ_Control_B, 0xFF}, + {MAX98927_Measurement_enables, 0x03}, + {MAX98927_PDM_Rx_Enable, 0x00}, + {MAX98927_AMP_volume_control, 0x38}, + {MAX98927_AMP_DSP_Config, 0x33}, + {MAX98927_DRE_Control, 0x01}, + {MAX98927_Speaker_Gain, 0x05}, + {MAX98927_SSM_Configuration, 0x85}, + {MAX98927_Boost_Control_0, MAX_BOOST_VOLT}, + {MAX98927_Boost_Control_1, 0x3e}, + {MAX98927_Meas_ADC_Base_Divide_MSByte, 0x00}, + {MAX98927_Meas_ADC_Base_Divide_LSByte, 0x00}, + {MAX98927_Meas_ADC_Thermal_Hysteresis, 0x00}, + {MAX98927_Env_Tracker_Vout_Headroom, 0x0C}, + {MAX98927_Env_Tracker_Control, 0x01}, + {MAX98927_Brownout_enables, 0x00}, +}; + +int reg_channel_map[][7][2] = { + { + {MAX98927_Boost_Control_3, 0x01}, + {MAX98927_PCM_Tx_Channel_Sources_A, 0x01}, + {MAX98927_PCM_Rx_Enables_A, 0x03}, + {MAX98927_PCM_Tx_Enables_A, 0x03}, + {MAX98927_PCM_Tx_HiZ_Control_A, 0xFC}, + {MAX98927_PCM_to_speaker_monomix_A, 0x80}, + {MAX98927_PCM_to_speaker_monomix_B, 0x00}, + }, + { + {MAX98927_Boost_Control_3, 0x01}, + {MAX98927_PCM_Tx_Channel_Sources_A, 0x00}, + {MAX98927_PCM_Rx_Enables_A, 0x01}, + {MAX98927_PCM_Tx_Enables_A, 0x01}, + {MAX98927_PCM_Tx_HiZ_Control_A, 0xFE}, + {MAX98927_PCM_to_speaker_monomix_A, 0x80}, + {MAX98927_PCM_to_speaker_monomix_B, 0x00}, + }, + { + {MAX98927_Boost_Control_3, 0x09}, + {MAX98927_PCM_Tx_Channel_Sources_A, 0x11}, + {MAX98927_PCM_Rx_Enables_A, 0x02}, + {MAX98927_PCM_Tx_Enables_A, 0x02}, + {MAX98927_PCM_Tx_HiZ_Control_A, 0xFD}, + {MAX98927_PCM_to_speaker_monomix_A, 0x81}, + {MAX98927_PCM_to_speaker_monomix_B, 0x01}, + }, + +}; + +static bool max98927_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98927_Interrupt_Raw_1: + case MAX98927_Interrupt_Raw_2: + case MAX98927_Interrupt_Raw_3: + case MAX98927_Interrupt_State_1: + case MAX98927_Interrupt_State_2: + case MAX98927_Interrupt_State_3: + case MAX98927_Interrupt_Flag_1: + case MAX98927_Interrupt_Flag_2: + case MAX98927_Interrupt_Flag_3: + case MAX98927_Interrupt_Enable_1: + case MAX98927_Interrupt_Enable_2: + case MAX98927_Interrupt_Enable_3: + case MAX98927_IRQ_Control: + case MAX98927_Clock_monitor_enable: + case MAX98927_Watchdog_Control: + case MAX98927_Meas_ADC_Thermal_Warning_Threshhold: + case MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold: + case MAX98927_Meas_ADC_Thermal_Hysteresis: + case MAX98927_Pin_Config: + case MAX98927_PCM_Rx_Enables_A: + case MAX98927_PCM_Rx_Enables_B: + case MAX98927_PCM_Tx_Enables_A: + case MAX98927_PCM_Tx_Enables_B: + case MAX98927_PCM_Tx_HiZ_Control_A: + case MAX98927_PCM_Tx_HiZ_Control_B: + case MAX98927_PCM_Tx_Channel_Sources_A: + case MAX98927_PCM_Tx_Channel_Sources_B: + case MAX98927_PCM_Mode_Config: + case MAX98927_PCM_Master_Mode: + case MAX98927_PCM_Clock_setup: + case MAX98927_PCM_Sample_rate_setup_1: + case MAX98927_PCM_Sample_rate_setup_2: + case MAX98927_PCM_to_speaker_monomix_A: + case MAX98927_PCM_to_speaker_monomix_B: + case MAX98927_ICC_RX_Enables_A: + case MAX98927_ICC_RX_Enables_B: + case MAX98927_ICC_TX_Enables_A: + case MAX98927_ICC_TX_Enables_B: + case MAX98927_ICC_Data_Order_Select: + case MAX98927_ICC_HiZ_Manual_Mode: + case MAX98927_ICC_TX_HiZ_Enables_A: + case MAX98927_ICC_TX_HiZ_Enables_B: + case MAX98927_ICC_Link_Enables: + case MAX98927_PDM_Tx_Enables: + case MAX98927_PDM_Tx_HiZ_Control: + case MAX98927_PDM_Tx_Control: + case MAX98927_PDM_Rx_Enable: + case MAX98927_AMP_volume_control: + case MAX98927_AMP_DSP_Config: + case MAX98927_Tone_Generator_and_DC_Config: + case MAX98927_DRE_Control: + case MAX98927_AMP_enables: + case MAX98927_Speaker_source_select: + case MAX98927_Speaker_Gain: + case MAX98927_SSM_Configuration: + case MAX98927_Measurement_enables: + case MAX98927_Measurement_DSP_Config: + case MAX98927_Boost_Control_0: + case MAX98927_Boost_Control_3: + case MAX98927_Boost_Control_1: + case MAX98927_Meas_ADC_Config: + case MAX98927_Meas_ADC_Base_Divide_MSByte: + case MAX98927_Meas_ADC_Base_Divide_LSByte: + case MAX98927_Meas_ADC_Chan_0_Divide: + case MAX98927_Meas_ADC_Chan_1_Divide: + case MAX98927_Meas_ADC_Chan_2_Divide: + case MAX98927_Meas_ADC_Chan_0_Filt_Config: + case MAX98927_Meas_ADC_Chan_1_Filt_Config: + case MAX98927_Meas_ADC_Chan_2_Filt_Config: + case MAX98927_Meas_ADC_Chan_0_Readback: + case MAX98927_Meas_ADC_Chan_1_Readback: + case MAX98927_Meas_ADC_Chan_2_Readback: + case MAX98927_Brownout_status: + case MAX98927_Brownout_enables: + case MAX98927_Brownout_level_infinite_hold: + case MAX98927_Brownout_level_hold: + case MAX98927_Brownout__level_1_threshold: + case MAX98927_Brownout__level_2_threshold: + case MAX98927_Brownout__level_3_threshold: + case MAX98927_Brownout__level_4_threshold: + case MAX98927_Brownout_threshold_hysterysis: + case MAX98927_Brownout_AMP_limiter_attack_release: + case MAX98927_Brownout_AMP_gain_attack_release: + case MAX98927_Brownout_AMP1_clip_mode: + case MAX98927_Brownout__level_1_current_limit: + case MAX98927_Brownout__level_1_amp_1_control_1: + case MAX98927_Brownout__level_1_amp_1_control_2: + case MAX98927_Brownout__level_1_amp_1_control_3: + case MAX98927_Brownout__level_2_current_limit: + case MAX98927_Brownout__level_2_amp_1_control_1: + case MAX98927_Brownout__level_2_amp_1_control_2: + case MAX98927_Brownout__level_2_amp_1_control_3: + case MAX98927_Brownout__level_3_current_limit: + case MAX98927_Brownout__level_3_amp_1_control_1: + case MAX98927_Brownout__level_3_amp_1_control_2: + case MAX98927_Brownout__level_3_amp_1_control_3: + case MAX98927_Brownout__level_4_current_limit: + case MAX98927_Brownout__level_4_amp_1_control_1: + case MAX98927_Brownout__level_4_amp_1_control_2: + case MAX98927_Brownout__level_4_amp_1_control_3: + case MAX98927_Env_Tracker_Vout_Headroom: + case MAX98927_Env_Tracker_Boost_Vout_Delay: + case MAX98927_Env_Tracker_Release_Rate: + case MAX98927_Env_Tracker_Hold_Rate: + case MAX98927_Env_Tracker_Control: + case MAX98927_Env_Tracker__Boost_Vout_ReadBack: + case MAX98927_Global_Enable: + case MAX98927_REV_ID: + return true; + default: + return false; + } +} + +static bool max98927_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98927_Interrupt_Raw_1: + case MAX98927_Interrupt_Raw_2: + case MAX98927_Interrupt_Raw_3: + case MAX98927_Interrupt_State_1: + case MAX98927_Interrupt_State_2: + case MAX98927_Interrupt_State_3: + case MAX98927_Interrupt_Flag_1: + case MAX98927_Interrupt_Flag_2: + case MAX98927_Interrupt_Flag_3: + case MAX98927_Meas_ADC_Chan_0_Readback: + case MAX98927_Meas_ADC_Chan_1_Readback: + case MAX98927_Meas_ADC_Chan_2_Readback: + case MAX98927_Brownout_status: + case MAX98927_Env_Tracker__Boost_Vout_ReadBack: + return true; + default: + return false; + } +} + +#ifdef USE_DSM_MISC_DEV +#define PKG_HEADER (48) +#define PAYLOAD_COUNT (110) + +#if 1 +typedef enum { + DSM_API_MONO_SPKER = 0x00000000, + DSM_API_STEREO_SPKER = 0x03000000, + + DSM_API_L_CHAN = 0x01000000, + DSM_API_R_CHAN = 0x02000000, + + DSM_API_CHANNEL_1 = 0x01000000, + DSM_API_CHANNEL_2 = 0x02000000, + DSM_API_CHANNEL_3 = 0x04000000, + DSM_API_CHANNEL_4 = 0x08000000, + DSM_API_CHANNEL_5 = 0x10000000, + DSM_API_CHANNEL_6 = 0x20000000, + DSM_API_CHANNEL_7 = 0x40000000, + DSM_API_CHANNEL_8 = 0x80000000, + + DSM_MAX_SUPPORTED_CHANNELS = 8 +} DSM_API_CHANNEL_ID; + +#define DSM_SET_MONO_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_MONO_SPKER) +#define DSM_SET_STEREO_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_STEREO_SPKER) +#define DSM_SET_LEFT_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_L_CHAN) +#define DSM_SET_RIGHT_PARAM(cmdId) ((cmdId&0x00FFFFFF)|DSM_API_R_CHAN) + +enum working_mode { + DSM_MODE_NONE = 0, + DSM_MODE_LEFT_ONLY, + DSM_MODE_RIGHT_ONLY, + DSM_MODE_LEFT_RIGHT, + DSM_MODE_RIGHT_LEFT, + DSM_MODE_CALIB_START, + DSM_MODE_CALIB_ING, + DSM_MODE_RDC, + DSM_MODE_CALIB_DONE, +}; + +typedef struct dsm_params { + uint32_t mode; + uint32_t pcount; + uint32_t pdata[PAYLOAD_COUNT]; +} dsm_param_t; + +struct param_info { + int pid; + char name[80]; + int q_val; +}; + + + +#define RDC_MIN (241833636) +#define RDC_MAX (403056239) + +#endif + +static uint32_t gParam[PKG_HEADER+PAYLOAD_COUNT]; + +static int maxdsm_open(struct inode *inode, struct file *filep) +{ + return 0; +} + +#define ADAPTIVE_FC (16) +#define ADAPTIVE_DC_RES (18) + +static ssize_t maxdsm_read(struct file *filep, char __user *buf, + size_t count, loff_t *ppos) +{ + int rc; + uint8_t *payload = (uint8_t *)&gParam[PKG_HEADER]; + + if (count > sizeof(uint32_t)*PAYLOAD_COUNT) + count = sizeof(uint32_t)*PAYLOAD_COUNT; + + mutex_lock(&dsm_lock); + rc = afe_dsm_rx_get_params(payload, sizeof(uint32_t)*PAYLOAD_COUNT); + + if (rc != 0) { + pr_err("%s: afe_dsm_rx_get_params failed - %d\n", __func__, rc); + } + rc = copy_to_user(buf, payload, count); + if (rc != 0) { + pr_err("%s: copy_to_user failed - %d\n", __func__, rc); + } + mutex_unlock(&dsm_lock); + + return rc; +} + +static ssize_t maxdsm_write(struct file *filep, const char __user *buf, + size_t count, loff_t *ppos) +{ + int rc; + uint8_t *payload = (uint8_t *)&gParam[PKG_HEADER]; + + if (count > sizeof(uint32_t)*PAYLOAD_COUNT) + count = sizeof(uint32_t)*PAYLOAD_COUNT; + + mutex_lock(&dsm_lock); + rc = copy_from_user(payload, buf, count); + if (rc != 0) { + pr_err("%s: copy_from_user failed - %d\n", __func__, rc); + goto exit; + } + + afe_dsm_rx_set_params(payload, count); +exit: + mutex_unlock(&dsm_lock); + + return rc; +} + +static const struct file_operations dsm_ctrl_fops = { + .owner = THIS_MODULE, + .open = maxdsm_open, + .release = NULL, + .read = maxdsm_read, + .write = maxdsm_write, + .mmap = NULL, + .poll = NULL, + .fasync = NULL, + .llseek = NULL, +}; + +static struct miscdevice dsm_ctrl_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "dsm_ctrl_dev", + .fops = &dsm_ctrl_fops +}; +#endif + +/* max. length of a alsa mixer control name */ +#define MAX_CONTROL_NAME 48 +#define CALIBRATE_FILE "/persist/spkr_calibration.bin" +#define CALIBRATE_FILE_R "/persist/spkr_calibration_r.bin" + +struct dsm_info_t { + int32_t averageTemp[2]; + int32_t bits_per_sample; + int32_t sampling_rate; + int32_t Q_factor; + int32_t working_mode; + int32_t enable_flag; + int32_t num_channels; + int32_t maxTempQ19[2]; + int32_t minTempQ19[2]; + int32_t maxFcQ9[2]; + int32_t minFcQ9[2]; + int32_t maxRdcQ27[2]; + int32_t minRdcQ27[2]; +}; + + +#if 0 +static int max989xx_create_calibfile(void) +{ + struct file *pfile = NULL; + mm_segment_t old_fs; + int ret = 0; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + pfile = filp_open(CALIBRATE_FILE, O_RDWR | O_CREAT, 0666); + if (!IS_ERR(pfile)) { + pr_info("%s: %s create success! \n", __func__, CALIBRATE_FILE); + filp_close(pfile, NULL); + } else { + pr_info("%s: %s create failed! \n", __func__, CALIBRATE_FILE); + ret = -1; + } + + set_fs(old_fs); + + return ret; + +} +#endif + +static int max989xx_calib_save(uint32_t calib_value) +{ + struct file *pfile = NULL; + mm_segment_t old_fs; + int ret = 0; + loff_t pos = 0; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + pfile = filp_open(CALIBRATE_FILE, O_RDWR | O_CREAT, 0666); + if (!IS_ERR(pfile)) { + pr_info("%s: save calib_value=%d \n", __func__, calib_value); + vfs_write(pfile, (char *)&calib_value, sizeof(uint32_t), &pos); + filp_close(pfile, NULL); + } else { + pr_info("%s: %s open failed! \n", __func__, CALIBRATE_FILE); + ret = -1; + } + + set_fs(old_fs); + + return ret; +} + +static int max989xx_calib_save_right(uint32_t calib_value) +{ + struct file *pfile = NULL; + mm_segment_t old_fs; + int ret = 0; + loff_t pos = 0; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + pfile = filp_open(CALIBRATE_FILE_R, O_RDWR | O_CREAT, 0666); + if (!IS_ERR(pfile)) { + pr_info("%s: save calib_value=%d \n", __func__, calib_value); + vfs_write(pfile, (char *)&calib_value, sizeof(uint32_t), &pos); + filp_close(pfile, NULL); + } else { + pr_info("%s: %s open failed! \n", __func__, CALIBRATE_FILE_R); + ret = -1; + } + + set_fs(old_fs); + + return ret; +} + +static bool rdc_check_valid(uint32_t rdc) +{ + if (rdc > RDC_MIN && rdc < RDC_MAX) { + return true; + } + + pr_info("%s: rdc=%d invalid, [%d, %d] \n", __func__, rdc, RDC_MIN, RDC_MAX); + return false; +} + +#ifdef CONFIG_DEBUG_FS +static ssize_t max989xx_dbgfs_calibrate_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + struct i2c_client *i2c = file->private_data; + struct max98927_priv *max989xx = i2c_get_clientdata(i2c); + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t impedance_l, impedance_r; + char *str; + + pr_info("%s: enter... \n", __func__); + mutex_lock(&dsm_lock); + ret = afe_dsm_pre_calib((uint8_t*)payload); + ret |= afe_dsm_get_calib((uint8_t*)payload); + if (ret == 0) { + impedance_l = *payload; + impedance_r = *(payload+1); + if (!rdc_check_valid(impedance_l)) { + impedance_l = 0xCACACACA; + *payload = 0xCACACACA; + } + max989xx->ref_RDC[MAX98927L] = impedance_l; + max989xx_calib_save(impedance_l); + + if (max989xx->mono_stereo == 3) { + if (!rdc_check_valid(impedance_r)) { + impedance_r = 0xCACACACA; + *(payload+1) = 0xCACACACA; + } + max989xx->ref_RDC[MAX98927R] = impedance_r; + max989xx_calib_save_right(impedance_r); + } + + afe_dsm_set_calib((uint8_t *)(payload)); + } else { + pr_info("%s failed to calibrate \n", __func__); + ret = -EIO; + goto exit; + } + + str = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!str) { + pr_info("%s failed to kmalloc \n", __func__); + ret = -ENOMEM; + goto exit; + } + + pr_info("%s: calibrate [impedance]=%d \n", __func__, impedance_l); + ret = snprintf(str, PAGE_SIZE, "%d\n", impedance_l); + if (max989xx->mono_stereo == 3) { + pr_info("%s: calibrate [impedance_r]=%d \n", __func__, impedance_r); + ret += snprintf(str+ret, PAGE_SIZE, "%d\n", impedance_r); + } + ret = simple_read_from_buffer(user_buf, count, ppos, str, ret); + kfree(str); + +exit: + afe_dsm_post_calib((uint8_t*)payload); + mutex_unlock(&dsm_lock); + return ret; +} + +static ssize_t max989xx_dbgfs_impedance_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + struct i2c_client *i2c = file->private_data; + struct max98927_priv *max989xx = i2c_get_clientdata(i2c); + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t impedance = 0, impedance_r = 0; + char *str; + + afe_dsm_get_calib((uint8_t *)payload); + impedance = *payload; + if (!rdc_check_valid(impedance)) { + pr_info("%s failed to read impedance. \n", __func__); + ret = -EIO; + goto exit; + } + + if (max989xx->mono_stereo == 3) { + impedance_r = *(payload + 1); + if (!rdc_check_valid(impedance_r)) { + pr_info("%s failed to read impedance_r. \n", __func__); + ret = -EIO; + goto exit; + } + } + + str = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!str) { + pr_info("%s failed to kmalloc \n", __func__); + ret = -ENOMEM; + goto exit; + } + + pr_info("%s: [impedance] = %d \n", __func__, impedance); + ret = snprintf(str, PAGE_SIZE, "%d\n", impedance); + if (max989xx->mono_stereo == 3) { + pr_info("%s: [impedance_r] = %d \n", __func__, impedance_r); + ret += snprintf(str+ret, PAGE_SIZE, "%d\n", impedance_r); + } + ret = simple_read_from_buffer(user_buf, count, ppos, str, ret); + kfree(str); + +exit: + + return ret; +} + +static ssize_t max989xx_dbgfs_info_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + struct dsm_info_t *pInfo; + char *str; + + afe_dsm_get_libary_info(payload, 100); + pInfo = (struct dsm_info_t*) payload; + + str = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!str) { + pr_info("%s failed to kmalloc \n", __func__); + ret = -ENOMEM; + goto exit; + } + + pr_info("%s: [average temp] = %d \n", __func__, pInfo->averageTemp[0]); + ret = snprintf(str, PAGE_SIZE, "%d\n", pInfo->averageTemp[0]); + ret = simple_read_from_buffer(user_buf, count, ppos, str, ret); + kfree(str); + +exit: + + return ret; +} + +static ssize_t max989xx_dbgfs_f0_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t f0 = 0; + char *str; + + afe_dsm_get_calib((uint8_t *)payload); + f0 = *(payload+2); + #if 0 + if (!rdc_check_valid(f0)) { + pr_info("%s failed to read f0. \n", __func__); + ret = -EIO; + goto exit; + } + #endif + str = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!str) { + pr_info("%s failed to kmalloc \n", __func__); + ret = -ENOMEM; + goto exit; + } + + pr_info("%s: [f0] = %d \n", __func__, f0); + ret = snprintf(str, PAGE_SIZE, "%d\n", f0); + ret = simple_read_from_buffer(user_buf, count, ppos, str, ret); + kfree(str); + +exit: + + return ret; +} + + +static ssize_t max989xx_dbgfs_temperature_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos) +{ + + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t coiltemp = 0; + char *str; + + + afe_dsm_get_calib((uint8_t *)payload); + coiltemp = *(payload + 4); + pr_info("%s: [coiltemp] = %d \n", __func__, coiltemp); + + str = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!str) { + pr_info("%s failed to kmalloc \n", __func__); + ret = -ENOMEM; + goto exit; + } + + ret = snprintf(str, PAGE_SIZE, "%d\n", coiltemp); + ret = simple_read_from_buffer(user_buf, count, ppos, str, ret); + kfree(str); + +exit: + + return ret; +} + +static const struct file_operations max989xx_dbgfs_calibrate_fops = { + .open = simple_open, + .read = max989xx_dbgfs_calibrate_read, + .llseek = default_llseek, +}; + +static const struct file_operations max989xx_dbgfs_impedance_fops = { + .open = simple_open, + .read = max989xx_dbgfs_impedance_read, + .llseek = default_llseek, +}; + +static const struct file_operations max989xx_dbgfs_f0_fops = { + .open = simple_open, + .read = max989xx_dbgfs_f0_read, + .llseek = default_llseek, +}; +static const struct file_operations max989xx_dbgfs_temperature_fops = { + .open = simple_open, + .read = max989xx_dbgfs_temperature_read, + .llseek = default_llseek, +}; + +static const struct file_operations max989xx_dbgfs_info_fops = { + .open = simple_open, + .read = max989xx_dbgfs_info_read, + .llseek = default_llseek, +}; + +static void max989xx_debug_init(struct max98927_priv *max989xx, struct i2c_client *i2c) +{ + char name[60]; + + scnprintf(name, MAX_CONTROL_NAME, "%s", i2c->name); + max989xx->dbg_dir = debugfs_create_dir(name, NULL); + debugfs_create_file("calibrate", S_IRUGO|S_IWUGO, max989xx->dbg_dir, + i2c, &max989xx_dbgfs_calibrate_fops); + debugfs_create_file("impedance", S_IRUGO|S_IWUGO, max989xx->dbg_dir, + i2c, &max989xx_dbgfs_impedance_fops); + debugfs_create_file("f0detect", S_IRUGO|S_IWUGO, max989xx->dbg_dir, + i2c, &max989xx_dbgfs_f0_fops); + debugfs_create_file("temperature", S_IRUGO|S_IWUGO, max989xx->dbg_dir, + i2c, &max989xx_dbgfs_temperature_fops); + debugfs_create_file("infomation", S_IRUGO|S_IWUGO, max989xx->dbg_dir, + i2c, &max989xx_dbgfs_info_fops); + +} + +static void max989xx_debug_remove(struct max98927_priv *max989xx) +{ + if (max989xx->dbg_dir) + debugfs_remove_recursive(max989xx->dbg_dir); +} +#endif + +static ssize_t max98927_info_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + pr_err("%s", __func__); + + return 0; +} +static ssize_t max98927_info_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + struct dsm_info_t *pInfo; + + afe_dsm_get_libary_info(payload, 100); + pInfo = (struct dsm_info_t*) payload; + + pr_info("%s: [average temp] = %d \n", __func__, pInfo->averageTemp[0]); + ret = snprintf(buf, PAGE_SIZE, "%d\n", pInfo->averageTemp[0]); + + return ret; + +} + +static ssize_t max98927_QFactor_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + pr_err("%s", __func__); + + return 0; +} +static ssize_t max98927_QFactor_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t QFactor = 0; + + afe_dsm_get_calib((uint8_t *)payload); + QFactor = *(payload + 6); + pr_info("%s: [QFactor] = %d \n", __func__, QFactor); + ret = snprintf(buf, PAGE_SIZE, "%d\n", QFactor); + + return ret; +} + + +static ssize_t max98927_temperature_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + pr_err("%s", __func__); + + return 0; +} +static ssize_t max98927_temperature_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t coiltemp = 0; + + afe_dsm_get_calib((uint8_t *)payload); + coiltemp = *(payload + 4); + pr_info("%s: [coiltemp] = %d \n", __func__, coiltemp); + ret = snprintf(buf, PAGE_SIZE, "%d\n", coiltemp); + + return ret; + +} + + +static ssize_t max98927_f0_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + pr_err("%s", __func__); + + return 0; +} +static ssize_t max98927_f0_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t f0 = 0; + + afe_dsm_get_calib((uint8_t *)payload); + f0 = *(payload+2); + + pr_info("%s: [f0] = %d \n", __func__, f0); + ret = snprintf(buf, PAGE_SIZE, "%d\n", f0); + + return ret; + +} + + +static ssize_t max98927_impedance_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + pr_err("%s", __func__); + + return 0; +} +static ssize_t max98927_impedance_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t impedance = 0; + + afe_dsm_get_calib((uint8_t *)payload); + impedance = *payload; + if (!rdc_check_valid(impedance)) { + pr_info("%s failed to read impedance. \n", __func__); + impedance = 0xCACACACA; + } + + pr_info("%s: [impedance] = %d \n", __func__, impedance); + ret = snprintf(buf, PAGE_SIZE, "%d\n", impedance); + + return ret; + +} + + +static ssize_t max98927_calibrate_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + pr_err("%s", __func__); + + return 0; +} +static ssize_t max98927_calibrate_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + + struct max98927_priv *max989xx = g_max98927; + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int ret = 0; + uint32_t impedance_l, impedance_r; + + + + + pr_info("%s: enter... \n", __func__); + mutex_lock(&dsm_lock); + ret = afe_dsm_pre_calib((uint8_t*)payload); + ret |= afe_dsm_get_calib((uint8_t*)payload); + if (ret == 0) { + impedance_l = *payload; + impedance_r = *(payload+1); + if (!rdc_check_valid(impedance_l)) { + impedance_l = 0xCACACACA; + *payload = 0xCACACACA; + } + max989xx->ref_RDC[MAX98927L] = impedance_l; + + max989xx_calib_save(impedance_l); + + if (max989xx->mono_stereo == 3) { + if (!rdc_check_valid(impedance_r)) { + impedance_r = 0xCACACACA; + *(payload+1) = 0xCACACACA; + } + max989xx->ref_RDC[MAX98927R] = impedance_r; + max989xx_calib_save_right(impedance_r); + } + + afe_dsm_set_calib((uint8_t *)(payload)); + } else { + pr_err("%s failed to calibrate \n", __func__); + impedance_l = 0xCACACACA; + *payload = 0xCACACACA; + } +#if 0 + str = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!str) { + pr_info("%s failed to kmalloc \n", __func__); + ret = -ENOMEM; + goto exit; + } + + pr_info("%s: calibrate [impedance]=%d \n", __func__, impedance_l); + ret = snprintf(str, PAGE_SIZE, "%d\n", impedance_l); + if (max989xx->mono_stereo == 3) { + pr_info("%s: calibrate [impedance_r]=%d \n", __func__, impedance_r); + ret += snprintf(str+ret, PAGE_SIZE, "%d\n", impedance_r); + } +#endif + ret = sprintf(buf, "%d\n", impedance_l); + + + afe_dsm_post_calib((uint8_t*)payload); + + mutex_unlock(&dsm_lock); + return ret; +} + + +static struct device_attribute max98927_calibrate_attr = + __ATTR(calibrate, 0444, max98927_calibrate_show, max98927_calibrate_store); + +static struct device_attribute max98927_impedance_attr = + __ATTR(impedance, 0444, max98927_impedance_show, max98927_impedance_store); + +static struct device_attribute max98927_f0_attr = + __ATTR(f0, 0444, max98927_f0_show, max98927_f0_store); + +static struct device_attribute max98927_temperature_attr = + __ATTR(temperature, 0444, max98927_temperature_show, max98927_temperature_store); + +static struct device_attribute max98927_QFactor_attr = + __ATTR(QFactor, 0444, max98927_QFactor_show, max98927_QFactor_store); + + +static struct device_attribute max98927_info_attr = + __ATTR(info, 0444, max98927_info_show, max98927_info_store); + + +static void max989xx_sys_init(struct i2c_client *i2c) +{ + int ret = 0; + ret = sysfs_create_file(&i2c->dev.kobj, &max98927_calibrate_attr.attr); + if (ret < 0) + pr_err("%s sysfs_create_file max98927_calibrate_attr err.", __func__); + + ret = sysfs_create_file(&i2c->dev.kobj, &max98927_impedance_attr.attr); + if (ret < 0) + pr_err("%s sysfs_create_file max98927_impedance_attr err.", __func__); + + ret = sysfs_create_file(&i2c->dev.kobj, &max98927_f0_attr.attr); + if (ret < 0) + pr_err("%s sysfs_create_file max98927_f0_attr err.", __func__); + + ret = sysfs_create_file(&i2c->dev.kobj, &max98927_temperature_attr.attr); + if (ret < 0) + pr_err("%s sysfs_create_file max98927_temperature_attr err.", __func__); + + ret = sysfs_create_file(&i2c->dev.kobj, &max98927_QFactor_attr.attr); + if (ret < 0) + pr_err("%s sysfs_create_file max98927_QFactor_attr err.", __func__); + + ret = sysfs_create_file(&i2c->dev.kobj, &max98927_info_attr.attr); + if (ret < 0) + pr_err("%s sysfs_create_file max98927_info_attr err.", __func__); + return; +} + +static void max989xx_sys_remove(struct i2c_client *i2c) +{ + sysfs_remove_file(&i2c->dev.kobj, &max98927_calibrate_attr.attr); + + sysfs_remove_file(&i2c->dev.kobj, &max98927_impedance_attr.attr); + + sysfs_remove_file(&i2c->dev.kobj, &max98927_f0_attr.attr); + + sysfs_remove_file(&i2c->dev.kobj, &max98927_temperature_attr.attr); + + sysfs_remove_file(&i2c->dev.kobj, &max98927_QFactor_attr.attr); + + sysfs_remove_file(&i2c->dev.kobj, &max98927_info_attr.attr); + + return; +} + + +static int max989xx_calib_get(uint32_t *calib_value) +{ + struct file *pfile = NULL; + mm_segment_t old_fs; + int found = 0; + loff_t pos = 0; + + *calib_value = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + pfile = filp_open(CALIBRATE_FILE, O_RDONLY, 0); + if (!IS_ERR_OR_NULL(pfile)) { + found = 1; + vfs_read(pfile, (char *)calib_value, sizeof(uint32_t), &pos); + pr_info("%s get calib_value %d \n", __func__, *calib_value); + filp_close(pfile, NULL); + } else { + pr_info("%s No found\n", __func__); + found = 0; + } + + set_fs(old_fs); + + return found; +} + +static int max989xx_calib_get_r(uint32_t *calib_value) +{ + struct file *pfile = NULL; + mm_segment_t old_fs; + int found = 0; + loff_t pos = 0; + + *calib_value = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + + pfile = filp_open(CALIBRATE_FILE_R, O_RDONLY, 0); + if (!IS_ERR_OR_NULL(pfile)) { + found = 1; + vfs_read(pfile, (char *)calib_value, sizeof(uint32_t), &pos); + pr_info("%s get calib_value %d \n", __func__, *calib_value); + filp_close(pfile, NULL); + } else { + pr_info("%s No found\n", __func__); + found = 0; + } + + set_fs(old_fs); + + return found; +} + + +int max98927_wrapper_read(struct max98927_priv *max98927, bool speaker, + unsigned int reg, unsigned int *val) +{ + int ret = -1; + if (i2c_states & (1 << speaker)){ + ret = regmap_read(max98927->regmap[speaker], reg, val); + } + return ret; +} + +void max98927_wrapper_write(struct max98927_priv *max98927, + unsigned int reg, unsigned int val) +{ + int i; + for (i = 0; i < MAX_CHANNEL_NUM; i++){ + if (i2c_states & (1 << i)){ + regmap_write(max98927->regmap[i], reg, val); + } + } +} + +void max98927_wrap_update_bits(struct max98927_priv *max98927, + unsigned int reg, unsigned int mask, unsigned int val) +{ + int i; + for (i = 0; i < MAX_CHANNEL_NUM; i++){ + if (i2c_states & (1 << i)){ + regmap_update_bits(max98927->regmap[i], reg, mask, val); + } + } +} + +static int max98927_reg_get_w(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + unsigned int shift = mc->shift; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + unsigned int val; + + max98927_wrapper_read(max98927, 0, reg, &val); + + val = (val >> shift) & mask; + + if (invert) + ucontrol->value.integer.value[0] = max - val; + else + ucontrol->value.integer.value[0] = val; + + return 0; +} + +static int max98927_reg_put_w(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int reg = mc->reg; + unsigned int shift = mc->shift; + int max = mc->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = mc->invert; + + unsigned int val = (ucontrol->value.integer.value[0] & mask); + if (invert) + val = max - val; + mask = mask << shift; + val = val << shift; + + max98927_wrap_update_bits(max98927, reg, mask, val); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, reg, val); + return 0; +} +static int max98927_reg_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, unsigned int reg, + unsigned int mask, unsigned int shift) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data; + + max98927_wrapper_read(max98927, 0, reg, &data); + ucontrol->value.integer.value[0] = + (data & mask) >> shift; + return 0; +} + +static int max98927_reg_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, unsigned int reg, + unsigned int mask, unsigned int shift) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + unsigned int sel = ucontrol->value.integer.value[0]; + max98927_wrap_update_bits(max98927, reg, mask, sel << shift); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, reg, sel); + return 0; +} + +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + pr_info("%s: fmt 0x%08X\n", __func__, fmt); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_SLAVE); + break; + case SND_SOC_DAIFMT_CBM_CFM: + max98927->master = true; + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_MASTER); + break; + case SND_SOC_DAIFMT_CBS_CFM: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_HYBRID); + break; + default: + pr_info("DAI clock mode unsupported"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE, + 0); + break; + case SND_SOC_DAIFMT_IB_NF: + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE, + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE); + break; + default: + pr_info("DAI invert mode unsupported"); + return -EINVAL; + } + + /* interface format */ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + max98927->iface |= SND_SOC_DAIFMT_I2S; + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_FORMAT_Mask, + MAX98927_PCM_Mode_Config_PCM_FORMAT_I2S); + break; + case SND_SOC_DAIFMT_LEFT_J: + max98927->iface |= SND_SOC_DAIFMT_LEFT_J; + max98927_wrap_update_bits(max98927, MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_FORMAT_Mask, + MAX98927_PCM_Mode_Config_PCM_FORMAT_LEFT); + break; + default: + return -EINVAL; + } + return 0; +} + +/* codec MCLK rate in master mode */ +static const int rate_table[] = { + 5644800, 6000000, 6144000, 6500000, + 9600000, 11289600, 12000000, 12288000, + 13000000, 19200000, +}; + +static int max98927_set_clock(struct max98927_priv *max98927, + struct snd_pcm_hw_params *params) +{ + /* BCLK/LRCLK ratio calculation */ + int blr_clk_ratio = 2 * max98927->ch_size; + int reg = MAX98927_PCM_Clock_setup; + int mask = MAX98927_PCM_Clock_setup_PCM_BSEL_Mask; + int value; + + if (max98927->master) { + int i; + /* match rate to closest value */ + for (i = 0; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i] >= max98927->sysclk) + break; + } + if (i == ARRAY_SIZE(rate_table)) { + pr_err("%s couldn't get the MCLK to match codec\n", __func__); + return -EINVAL; + } + max98927_wrap_update_bits(max98927, MAX98927_PCM_Master_Mode, + MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_Mask, + i << MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_SHIFT); + } + + switch (blr_clk_ratio) { + case 32: + value = 2; + break; + case 48: + value = 3; + break; + case 64: + value = 4; + break; + default: + return -EINVAL; + } + + pr_info("%s: BLCK fix to %d\n", __func__, blr_clk_ratio); + max98927_wrap_update_bits(max98927, + reg, mask, value); + return 0; +} + +static int max98927_dai_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; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int sampling_rate = 0; + + switch (snd_pcm_format_width(params_format(params))) { + case 16: + max98927_wrap_update_bits(max98927, + MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_Mask, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_16); + max98927->ch_size = 16; + break; + case 24: + + + + + + + case 32: + max98927_wrap_update_bits(max98927, + MAX98927_PCM_Mode_Config, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_Mask, + MAX98927_PCM_Mode_Config_PCM_CHANSZ_32); + max98927->ch_size = 32; + break; + default: + pr_err("%s: format unsupported %d", + __func__, params_format(params)); + goto err; + } + pr_info("%s: format supported %d", + __func__, max98927->ch_size); + + switch (params_rate(params)) { + case 8000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_8000; + break; + case 11025: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_11025; + break; + case 12000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_12000; + break; + case 16000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_16000; + break; + case 22050: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_22050; + break; + case 24000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_24000; + break; + case 32000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_32000; + break; + case 44100: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_44100; + break; + case 48000: + sampling_rate |= + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_48000; + break; + default: + pr_err("%s rate %d not supported\n", __func__, params_rate(params)); + goto err; + } + /* set DAI_SR to correct LRCLK frequency */ + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_1, + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_Mask, sampling_rate); + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_2, + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_Mask, sampling_rate<<4); + if (max98927->interleave_mode){ + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_2, + MAX98927_PCM_Sample_rate_setup_2_IVADC_SR_Mask, (sampling_rate-3)); + } else { + max98927_wrap_update_bits(max98927, MAX98927_PCM_Sample_rate_setup_2, + MAX98927_PCM_Sample_rate_setup_2_IVADC_SR_Mask, sampling_rate); + } + + return max98927_set_clock(max98927, params); +err: + return -EINVAL; +} + +#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 + +#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static int max98927_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + pr_info("%s: clk_id %d, freq %d, dir %d\n", __func__, clk_id, freq, dir); + + max98927->sysclk = freq; + return 0; +} + +static int max98927_stream_mute(struct snd_soc_dai *codec_dai, int mute, int stream) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + int rc = 0; + uint32_t impedance = 0; + + pr_info("%s--- stream %d, mute %d \n", __func__, stream, mute); + + if (!max98927) { + pr_err("%s ------ priv data null pointer\n", __func__); + return 0; + } + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (mute) { + if (max98927->path_status) + afe_dsm_ramp_dn_cfg((uint8_t*)payload, 25); + max98927_wrap_update_bits(max98927, MAX98927_Global_Enable, MAX98927_Global_Enable_EN, 0); + max98927_wrap_update_bits(max98927, MAX98927_AMP_enables, MAX98927_AMP_enables, 0); + max98927->spk_mode = 0; + pr_info("%s ------ disable max98927 playback \n", __func__); + } else { +#if 0 + + if (max98927->path_status) { + max98927_wrap_update_bits(max98927, MAX98927_Speaker_Gain, + MAX98927_Speaker_Gain_SPK_PCM_GAIN_Mask, 5); + max98927_wrap_update_bits(max98927, MAX98927_AMP_volume_control, + MAX98927_AMP_volume_control_AMP_VOL_Mask, 56); + max98927_wrap_update_bits(max98927, MAX98927_Boost_Control_0, + MAX98927_Boost_Control_0_BST_VOUT_Mask, MAX_BOOST_VOLT); + } else { + max98927_wrap_update_bits(max98927, MAX98927_Speaker_Gain, + MAX98927_Speaker_Gain_SPK_PCM_GAIN_Mask, 1); + max98927_wrap_update_bits(max98927, MAX98927_AMP_volume_control, + MAX98927_AMP_volume_control_AMP_VOL_Mask, 44); + max98927_wrap_update_bits(max98927, MAX98927_Boost_Control_0, + MAX98927_Boost_Control_0_BST_VOUT_Mask, 0x00); + } +#endif + if (max98927->mono_stereo == 0x3) { + if (max98927->spk_mode & (0x1 << MAX98927L)) { + regmap_update_bits(max98927->regmap[MAX98927L], MAX98927_AMP_enables, + MAX98927_AMP_enables_SPK_EN, 1); + regmap_update_bits(max98927->regmap[MAX98927L], MAX98927_Global_Enable, + MAX98927_Global_Enable_EN, 1); + } else if (max98927->spk_mode & (0x1 << MAX98927R)) { + regmap_update_bits(max98927->regmap[MAX98927R], MAX98927_AMP_enables, + MAX98927_AMP_enables_SPK_EN, 1); + regmap_update_bits(max98927->regmap[MAX98927R], MAX98927_Global_Enable, + MAX98927_Global_Enable_EN, 1); + } + } else { + max98927_wrap_update_bits(max98927, MAX98927_AMP_enables, MAX98927_AMP_enables_SPK_EN, 1); + max98927_wrap_update_bits(max98927, MAX98927_Global_Enable, MAX98927_Global_Enable_EN, 1); + } + + pr_info("%s ------ enable max98927 playback \n", __func__); + } + } else if (stream == SNDRV_PCM_STREAM_CAPTURE) { + if (mute) { + /* max98927_wrapper_write(max98927, MAX98927_Measurement_enables, 0x0); */ + max98927->path_status = 0; + pr_info("%s ------ disable max98927 capture\n", __func__); + } else { + max98927_wrapper_write(max98927, MAX98927_Measurement_enables, 0x3); + max98927->path_status |= i2c_states; + if (max98927->mono_stereo == 0x0 || (max98927->mono_stereo & 0x1)) { + if (!rdc_check_valid(max98927->ref_RDC[MAX98927L]) && max98927->ref_RDC[MAX98927L] != 0xCACACACA){ + rc = max989xx_calib_get(&impedance); + if (rdc_check_valid(impedance) || impedance == 0xCACACACA) { + max98927->ref_RDC[MAX98927L] = impedance; + pr_info("%s: ref_RDC left =%d \n", __func__, max98927->ref_RDC[MAX98927L]); + } + } + } + if (max98927->mono_stereo & 0x2) { + if (!rdc_check_valid(max98927->ref_RDC[MAX98927R]) && max98927->ref_RDC[MAX98927R] != 0xCACACACA){ + impedance = 0; + rc = max989xx_calib_get_r(&impedance); + if (rdc_check_valid(impedance) || impedance == 0xCACACACA) { + max98927->ref_RDC[MAX98927R] = impedance; + pr_info("%s: ref_RDC right=%d \n", __func__, max98927->ref_RDC[MAX98927R]); + } + } + } + mutex_lock(&dsm_lock); + *payload = max98927->ref_RDC[MAX98927L]; + *(payload+1) = max98927->ref_RDC[MAX98927R]; + *(payload+2) = max98927->adsp_mode; + afe_dsm_set_calib((uint8_t *)payload); + + mutex_unlock(&dsm_lock); + pr_info("%s ------ enable max98927 capture\n", __func__); + } + } + + return 0; +} + +static const struct snd_soc_dai_ops max98927_dai_ops = { + .set_sysclk = max98927_dai_set_sysclk, + .set_fmt = max98927_dai_set_fmt, + .hw_params = max98927_dai_hw_params, + .mute_stream = max98927_stream_mute, +}; + +static int max98927_feedforward_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + u32 ret = 0; + + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + /* uint32_t* payload = (uint32_t *)&gParam[PKG_HEADER]; */ + + if (!max98927){ + pr_err("%s------priv data null pointer\n", __func__); + return ret; + } + pr_info("%s---feedforward event %d\n", __func__, event); + switch(event){ + case SND_SOC_DAPM_POST_PMU: + break; + case SND_SOC_DAPM_POST_PMD: + break; + case SND_SOC_DAPM_PRE_PMU: + break; + case SND_SOC_DAPM_PRE_PMD: + break; + default: + break; + } + return ret; +} +static int max98927_feedback_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + u32 ret = 0; + + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + if (!max98927){ + pr_err("%s------priv data null pointer\n", __func__); + return ret; + } + pr_info("%s---feedback event %d\n", __func__, event); + switch(event){ + case SND_SOC_DAPM_POST_PMU: + /* max98927_wrapper_write(max98927, MAX98927_Measurement_enables, 0x3); */ + break; + case SND_SOC_DAPM_POST_PMD: + /* max98927_wrapper_write(max98927, MAX98927_Measurement_enables, 0x0); */ + break; + default: + break; + } + return ret; +} + +static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = { + SND_SOC_DAPM_DAC_E("DACs", "HiFi Playback", SND_SOC_NOPM, 0, 0, + max98927_feedforward_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_ADC_E("ADCs", "HiFi Capture", SND_SOC_NOPM, 0, 0, + max98927_feedback_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_INPUT("MAX98927_IN"), + SND_SOC_DAPM_OUTPUT("MAX98927_OUT"), +}; + +static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0); +static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0); + +static int max98927_spk_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = max98927->spk_gain; + pr_info("max98927_spk_gain_get: spk_gain setting returned %d\n", + (int) ucontrol->value.integer.value[0]); + + return 0; +} + +static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + pr_info("max98927_spk_gain_put: %d\n", sel); + + if (sel < ((1 << MAX98927_Speaker_Gain_Width) - 1)) { + /* max98927_wrap_update_bits(max98927, MAX98927_Speaker_Gain, */ + /* MAX98927_Speaker_Gain_SPK_PCM_GAIN_Mask, sel); */ + max98927->spk_gain = sel; + } + return 0; +} + +static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = max98927->digital_gain; + pr_info("%s: spk_gain setting returned %d\n", __func__, + (int) ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_digital_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + pr_info("max98927_digital_gain_put: %d\n", sel); + + if (sel <= ((1 << MAX98927_AMP_VOL_WIDTH) - 1)) { + /* max98927_wrap_update_bits(max98927, MAX98927_AMP_volume_control, */ + /* MAX98927_AMP_volume_control_AMP_VOL_Mask, sel); */ + max98927->digital_gain = sel; + } + return 0; +} + +static int max98927_boost_voltage_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_Boost_Control_0, + MAX98927_Boost_Control_0_BST_VOUT_Mask, 0); +} + +static int max98927_boost_voltage_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_Boost_Control_0, + MAX98927_Boost_Control_0_BST_VOUT_Mask, 0); +} + +static int max98927_boost_input_limit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_Boost_Control_1, + MAX98927_Boost_Control_1_BST_ILIM_Mask, MAX98927_BST_ILIM_SHIFT); +} + +static int max98927_boost_input_limit_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_Boost_Control_1, + MAX98927_Boost_Control_1_BST_ILIM_Mask, MAX98927_BST_ILIM_SHIFT); +} + +static int max98927_spk_src_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_Speaker_source_select, + MAX98927_Speaker_source_select_SPK_SOURCE_Mask, 0); +} + +static int max98927_spk_src_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_Speaker_source_select, + MAX98927_Speaker_source_select_SPK_SOURCE_Mask, 0); +} + +static int max98927_mono_out_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_get(kcontrol, ucontrol, MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, 0); +} + +static int max98927_mono_out_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, 0); +} + +static int max98927_mono_out_get_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + if (i2c_states & MAX98927_CH0){ + regmap_read(max98927->regmap[MAX98927L], MAX98927_PCM_to_speaker_monomix_A, &data); + ucontrol->value.integer.value[0] = + (data & MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask); + pr_info("%s: value:%d", __func__, data); + } + + return 0; +} + +static int max98927_mono_out_put_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + + if (i2c_states & MAX98927_CH0){ + regmap_update_bits(max98927->regmap[MAX98927L], MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, sel); + regmap_update_bits(max98927->regmap[MAX98927L], MAX98927_PCM_Rx_Enables_A, + 0xf, sel+1); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_PCM_to_speaker_monomix_A, sel); + } + + return 0; +} + +static int max98927_mono_out_get_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (i2c_states & MAX98927_CH1){ + regmap_read(max98927->regmap[MAX98927R], MAX98927_PCM_to_speaker_monomix_A, &data); + ucontrol->value.integer.value[0] = + (data & MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask); + } + pr_info("%s: value:%d", __func__, data); + return 0; +} + +static int max98927_mono_out_put_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + if (i2c_states & MAX98927_CH1){ + regmap_update_bits(max98927->regmap[MAX98927R], MAX98927_PCM_to_speaker_monomix_A, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask, sel); + regmap_update_bits(max98927->regmap[MAX98927R], MAX98927_PCM_Rx_Enables_A, 0xf, sel+1); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_PCM_to_speaker_monomix_A, sel); + } else { + pr_info("%s: mono mode not support!!\n", __func__); + } + return 0; +} + +static int max98927_feedback_en_get_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (i2c_states & MAX98927_CH0){ + regmap_read(max98927->regmap[MAX98927L], MAX98927_Measurement_enables, &data); + ucontrol->value.integer.value[0] = data; + pr_info("%s: value:%d", __func__, data); + } + + return 0; +} + +static int max98927_feedback_en_put_l(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + + if (i2c_states & MAX98927_CH0){ + regmap_write(max98927->regmap[MAX98927L], MAX98927_Measurement_enables, sel); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Measurement_enables, sel); + } + return 0; +} + +static int max98927_feedback_en_get_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data = 0; + + if (i2c_states & MAX98927_CH1){ + regmap_read(max98927->regmap[MAX98927R], MAX98927_Measurement_enables, &data); + ucontrol->value.integer.value[0] = data; + } + pr_info("%s: value:%d", __func__, data); + return 0; +} + +static int max98927_feedback_en_put_r(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + if (i2c_states & MAX98927_CH1){ + regmap_write(max98927->regmap[MAX98927R], MAX98927_Measurement_enables, sel); + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Measurement_enables, sel); + } else { + pr_info("%s: mono mode not support!!\n", __func__); + } + return 0; +} + +static int max98927_adsp_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = max98927->adsp_mode; + pr_info("%s: value:%d", __func__, (int)ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_adsp_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + uint32_t *payload = (uint32_t *)&gParam[PKG_HEADER]; + + max98927->adsp_mode = sel; + + mutex_lock(&dsm_lock); + *payload = max98927->ref_RDC[MAX98927L]; + *(payload+1) = max98927->ref_RDC[MAX98927R]; + *(payload+2) = max98927->adsp_mode; + afe_dsm_set_calib((uint8_t *)payload); + + mutex_unlock(&dsm_lock); + + pr_info("%s: value 0x%02X\n", __func__, sel); + return 0; +} + +static int max98927_left_channel_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data_global = 0; + int data_amp = 0; + + + if (i2c_states & MAX98927_CH0){ + regmap_read(max98927->regmap[MAX98927L], MAX98927_Global_Enable, &data_global); + regmap_read(max98927->regmap[MAX98927L], MAX98927_AMP_enables, &data_amp); + ucontrol->value.integer.value[0] = (data_global & MAX98927_Global_Enable_EN) + & (data_amp & MAX98927_AMP_enables_SPK_EN); + } + + pr_info("%s: value:%d", __func__, (int)ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_left_channel_enable_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + max98927->spk_mode &= ~0x1; + max98927->spk_mode |= sel; + + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Global_Enable, sel); + return 0; +} + +static int max98927_right_channel_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + int data_global = 0; + int data_amp = 0; + + if (i2c_states & MAX98927_CH1){ + regmap_read(max98927->regmap[MAX98927R], MAX98927_Global_Enable, &data_global); + regmap_read(max98927->regmap[MAX98927R], MAX98927_AMP_enables, &data_amp); + ucontrol->value.integer.value[0] = (data_global & MAX98927_Global_Enable_EN) + & (data_amp & MAX98927_AMP_enables_SPK_EN); + } + + pr_info("%s: value:%d", __func__, (int)ucontrol->value.integer.value[0]); + return 0; +} + +static int max98927_right_channel_enable_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int sel = ucontrol->value.integer.value[0]; + max98927->spk_mode &= ~0x2; + max98927->spk_mode |= sel<<0x1; + pr_info("%s: register 0x%02X, value 0x%02X\n", + __func__, MAX98927_Global_Enable, sel); + return 0; +} + +static const char * const max98927_boost_voltage_text[] = { + "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V", + "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V", + "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V", + "9.5V", "9.625V", "9.75V", "9.875V", "10V" +}; + +static const char * const max98927_boost_current_limit_text[] = { + "1.0A", "1.1A", "1.2A", "1.3A", "1.4A", "1.5A", "1.6A", "1.7A", "1.8A", "1.9A", + "2.0A", "2.1A", "2.2A", "2.3A", "2.4A", "2.5A", "2.6A", "2.7A", "2.8A", "2.9A", + "3.0A", "3.1A", "3.2A", "3.3A", "3.4A", "3.5A", "3.6A", "3.7A", "3.8A", "3.9A", + "4.0A", "4.1A" +}; + +static const char * const max98927_speaker_source_text[] = { + "i2s", "reserved", "tone", "pdm" +}; + +static const char * const max98927_monomix_output_text[] = { + "ch_0", "ch_1", "ch_1_2_div" +}; +static const char * const max98927_feedback_switch_text[] = { + "OFF", "V_EN", "I_EN", "ON" +}; + +static const char * const max98927_adsp_working_mode_text[] = { + "full", "feedback", "playback", "bypass" +}; + +static const struct soc_enum max98927_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_monomix_output_text), max98927_monomix_output_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_speaker_source_text), max98927_speaker_source_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_boost_voltage_text), max98927_boost_voltage_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_feedback_switch_text), max98927_feedback_switch_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_boost_current_limit_text), max98927_boost_current_limit_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max98927_adsp_working_mode_text), max98927_adsp_working_mode_text), +}; + +static const struct snd_kcontrol_new max98927_snd_controls[] = { + SOC_SINGLE_EXT_TLV("Speaker Volume", MAX98927_Speaker_Gain, + 0, (1<dapm; + + + pr_info("%s: enter\n", __func__); + + max98927->codec = codec; + snd_soc_dapm_ignore_suspend(dapm, "MAX98927_OUT"); + snd_soc_dapm_ignore_suspend(dapm, "MAX98927_IN"); + snd_soc_dapm_ignore_suspend(dapm, "HiFi Playback"); + snd_soc_dapm_ignore_suspend(dapm, "HiFi Capture"); + + + snd_soc_dapm_sync(dapm); + g_max98927 = max98927; + + return 0; +} + +static const struct snd_soc_codec_driver soc_codec_dev_max98927 = { + .probe = max98927_probe, + .component_driver = { + .dapm_routes = max98927_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98927_audio_map), + .dapm_widgets = max98927_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets), + .controls = max98927_snd_controls, + .num_controls = ARRAY_SIZE(max98927_snd_controls), + }, +}; + +static const struct regmap_config max98927_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = MAX98927_REV_ID, + .readable_reg = max98927_readable_register, + .volatile_reg = max98927_volatile_register, + .cache_type = REGCACHE_RBTREE, +}; + +int max98927_get_i2c_states(void) +{ + return i2c_states; +} +EXPORT_SYMBOL(max98927_get_i2c_states); + +static int max98927_reset(struct i2c_client *i2c, struct max98927_priv *max98927) +{ + int ret = 0; + max98927->reset_gpio_l = of_get_named_gpio(i2c->dev.of_node, "maxim,98927-reset-gpio", 0); + pr_info("max98927_reset:%d------\n", max98927->reset_gpio_l); + + if (max98927->reset_gpio_l > 0){ + ret = gpio_request(max98927->reset_gpio_l, "max_98927_reset"); + if (ret) { + pr_err("max98927_i2c_probe : failed to request rest gpio %d error:%d\n", + max98927->reset_gpio_l, ret); + gpio_free(max98927->reset_gpio_l); + return ret; + } + gpio_direction_output(max98927->reset_gpio_l, 0); + msleep(10); + gpio_direction_output(max98927->reset_gpio_l, 1); + msleep(5); + } + return ret; +} + +static bool check_max98927_presence(struct regmap *regmap) +{ + int rc = 0, reg = 0, i; + + rc = regmap_read(regmap, MAX98927_REV_ID, ®); + for (i = 0; rc && i < ARRAY_SIZE(delay_array_msec); i++) { + pr_err("Failed reading version=%u - retry(%d)\n", reg, i); + /* retry after delay of increasing order */ + msleep(delay_array_msec[i]); + rc = regmap_read(regmap, MAX98927_REV_ID, ®); + } + if (rc) { + pr_err("Failed reading version=%u rc=%d\n", reg, rc); + return false; + }else{ + pr_info("max98927 device version 0x%02X\n", reg); + return true; + } +} +static int max98927_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + static struct max98927_priv *max98927; + int value, i, ret = 0; + unsigned int presence = 0; + + + pr_err("****** %s id.name =%s id.driver_data= %d \n", __func__, id->name, (int)(id->driver_data)); + + + + + + + if (!max98927) { + max98927 = devm_kzalloc(&i2c->dev, + sizeof(*max98927), GFP_KERNEL); + if (!max98927) { + pr_info("------%s devm_kzalloc error!!\n", __func__); + return -ENOMEM; + } + } + if (!of_property_read_u32(i2c->dev.of_node, "mono_stereo_mode", &value)) { + if (value > 3) { + pr_err("only support max to 2 channel!\n"); + value = 0; + } + max98927->mono_stereo = value; + } + + if (!of_property_read_u32(i2c->dev.of_node, "interleave_mode", &value)) { + if (value > 1) { + pr_info("interleave number is wrong:\n"); + } + max98927->interleave_mode = value; + } + max98927->spk_gain = 5; + max98927->digital_gain = 56; + + max98927->adsp_mode = 0; +#if 0 + if (!max98927->i2c_pull) { + max98927->i2c_pull = devm_regulator_get(&i2c->dev, "i2c-pull"); + if (IS_ERR(max98927->i2c_pull)) { + pr_err("regulator i2c_pull get failed\n "); + devm_kfree(&i2c->dev, max98927); + return PTR_ERR(max98927->i2c_pull); + } + + ret = regulator_enable(max98927->i2c_pull); + if (ret) { + pr_err("regulator_enable i2c_pull failed! \n"); + devm_kfree(&i2c->dev, max98927); + return ret; + } + } + max98927->max989xx_vdd = regulator_get(&i2c->dev, "max989xx_vdd"); + if (IS_ERR(max98927->max989xx_vdd)) { + pr_err("regulator max989xx_vdd get failed\n "); + devm_kfree(&i2c->dev, max98927); + return PTR_ERR(max98927->max989xx_vdd); + } else { + if (regulator_count_voltages(max98927->max989xx_vdd) > 0) { + ret = regulator_set_voltage(max98927->max989xx_vdd, 1800000, 1800000); + if (ret) { + pr_err("%s Regulator set vdd failed ret=%d\n", __func__, ret); + return ret; + } + + ret = regulator_set_load(max98927->max989xx_vdd, 200000); + if (ret) { + pr_err("%s failed to set load, ret=%d\n", __func__, ret); + return ret; + } + } + } + + ret = regulator_enable(max98927->max989xx_vdd); + if (ret) { + pr_err("regulator_enable max989xx_vdd failed! \n"); + devm_kfree(&i2c->dev, max98927); + return ret; + } +#endif + + ret = max98927_reset(i2c, max98927); + + i2c_set_clientdata(i2c, max98927); + + max98927->regmap[id->driver_data] = + devm_regmap_init_i2c(i2c, &max98927_regmap); + if (IS_ERR(max98927->regmap[id->driver_data])){ + ret = PTR_ERR(max98927->regmap[id->driver_data]); + dev_err(&i2c->dev, + "Failed to allocate chennel %lu regmap : %d\n", id->driver_data, ret); + }else{ + if (check_max98927_presence(max98927->regmap[id->driver_data])){ + presence = (1 << id->driver_data); + if (max98927->mono_stereo == 0){ + i2c_states |= presence; + for (i = 0; i < sizeof(reg_channel_map[0])/sizeof(reg_channel_map[0][0]); i++) + regmap_write(max98927->regmap[id->driver_data], reg_channel_map[0][i][0], reg_channel_map[0][i][1]); + }else if (max98927->mono_stereo & presence){ + i2c_states |= presence; + for (i = 0; i < sizeof(reg_channel_map[id->driver_data+1])/sizeof(reg_channel_map[id->driver_data+1][0]); i++) + regmap_write(max98927->regmap[id->driver_data], + reg_channel_map[id->driver_data+1][i][0], reg_channel_map[id->driver_data+1][i][1]); + } + for (i = 0; i < sizeof(reg_common_map)/sizeof(reg_common_map[0]); i++) + regmap_write(max98927->regmap[id->driver_data], reg_common_map[i][0], reg_common_map[i][1]); + + if (max98927->interleave_mode) + regmap_write(max98927->regmap[id->driver_data], MAX98927_PCM_Tx_Channel_Sources_B, 0x20); + + } + } + if (presence){ + if (max98927->dev == NULL){ + dev_set_name(&i2c->dev, "%s", "max98927"); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927, + max98927_dai, ARRAY_SIZE(max98927_dai)); + pr_err("****** %s snd_soc_register_codec id =%d\n", __func__, (int)(id->driver_data)); + if (ret < 0) { + pr_err("max98927 Failed to register codec: %d\n", ret); + i2c_states = 0; + return ret; + } + max98927->dev = &i2c->dev; + pr_info("max98927 register codec ok.\n"); +#ifdef USE_DSM_MISC_DEV + ret = misc_register(&dsm_ctrl_miscdev); + if (ret != 0) + pr_err("max98927 misc_register error:%d\n", ret); +#endif + + #ifdef CONFIG_DEBUG_FS + max989xx_debug_init(max98927, i2c); + #endif + max989xx_sys_init(i2c); + } + }else + pr_err("max98927 detection failed at %s - %x. \n", i2c->name, i2c->addr); + + return ret; +} + +static int max98927_i2c_remove(struct i2c_client *client) +{ + struct max98927_priv *max98927 = i2c_get_clientdata(client); + if (max98927) { + if (max98927->dev == &client->dev) { + snd_soc_unregister_codec(&client->dev); + i2c_set_clientdata(client, NULL); +#ifdef CONFIG_DEBUG_FS + max989xx_debug_remove(max98927); +#endif + max989xx_sys_remove(client); + kfree(max98927); +#ifdef USE_DSM_MISC_DEV + misc_deregister(&dsm_ctrl_miscdev); +#endif + } + } + + return 0; +} + +static const struct i2c_device_id max98927_i2c_id[] = { + { "max98927L", MAX98927L }, + { "max98927R", MAX98927R }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, max98927_i2c_id); + +static const struct of_device_id max98927_of_match[] = { + { .compatible = "maxim,max98927L", }, + { .compatible = "maxim,max98927R", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98927_of_match); + +static struct i2c_driver max98927_i2c_driver = { + .driver = { + .name = "max98927", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(max98927_of_match), + .pm = NULL, + }, + .probe = max98927_i2c_probe, + .remove = max98927_i2c_remove, + .id_table = max98927_i2c_id, +}; + +module_i2c_driver(max98927_i2c_driver) + +MODULE_DESCRIPTION("ALSA SoC MAX98927 driver"); +MODULE_AUTHOR("Maxim Integrated Inc."); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h new file mode 100644 index 0000000000000..1b088e7b28fce --- /dev/null +++ b/sound/soc/codecs/max98927.h @@ -0,0 +1,1257 @@ +/* + * AnishBestPingPongerAliveButNotAsGoodAsMax.h + * + * Auto generated by Maxim Integrated, supporting revision + * Search for #BYHAND for flags on special cases to fix by hand + * #BYHAND width doesn't match: (this is usually when a bit has shorthand or formulaic descriptions) + * #BYHAND width >= 5: + */ +#ifndef __MAX98927_REGISTERDEFS_H +#define __MAX98927_REGISTERDEFS_H +#ifdef CONFIG_SND_SOC_MAXIM_DSM +#include +#endif /* CONFIG_SND_SOC_MAXIM_DSM */ + +#define MAX98927L 0 +#define MAX98927R 1 +#define MAX_CHANNEL_NUM (2) +typedef enum +{ + + MAX98927_Interrupt_Raw_1 = 0x0001, + MAX98927_Interrupt_Raw_1_BDE_ACTIVE_END_RAW = (0x1 << 0), + MAX98927_Interrupt_Raw_1_BDE_ACTIVE_BGN_RAW = (0x1 << 1), + MAX98927_Interrupt_Raw_1_BDE_LEVEL_CHANGE_RAW = (0x1 << 2), + MAX98927_Interrupt_Raw_1_BDE_L8_RAW = (0x1 << 3), + MAX98927_Interrupt_Raw_1_THERMWARN_END_RAW = (0x1 << 4), + MAX98927_Interrupt_Raw_1_THERMWARN_START_RAW = (0x1 << 5), + MAX98927_Interrupt_Raw_1_THERMSHDN_END_RAW = (0x1 << 6), + MAX98927_Interrupt_Raw_1_THERMSHDN_START_RAW = (0x1 << 7), + + + MAX98927_Interrupt_Raw_2 = 0x0002, + MAX98927_Interrupt_Raw_2_WATCHDOGWARN_RAW = (0x1 << 0), + MAX98927_Interrupt_Raw_2_WATCHDOGFAIL_RAW = (0x1 << 1), + MAX98927_Interrupt_Raw_2_BOOSTCURRLIM_RAW = (0x1 << 2), + MAX98927_Interrupt_Raw_2_CLKSTOP_RAW = (0x1 << 3), + MAX98927_Interrupt_Raw_2_CLKSTART_RAW = (0x1 << 4), + MAX98927_Interrupt_Raw_2_MEASADC_END_RAW = (0x1 << 5), + MAX98927_Interrupt_Raw_2_PWRDN_DONE_RAW = (0x1 << 6), + MAX98927_Interrupt_Raw_2_PWRUP_DONE_RAW = (0x1 << 7), + + + MAX98927_Interrupt_Raw_3 = 0x0003, + MAX98927_Interrupt_Raw_3_PWRUP_FAIL_RAW = (0x1 << 0), + MAX98927_Interrupt_Raw_3_AUTH_DONE_RAW = (0x1 << 1), + MAX98927_Interrupt_Raw_3_SPK_OVC_RAW = (0x1 << 2), + MAX98927_Interrupt_Raw_3_BST_UVLO_RAW = (0x1 << 3), + + + MAX98927_Interrupt_State_1 = 0x0004, + MAX98927_Interrupt_State_1_BDE_ACTIVE_END_STATE = (0x1 << 0), + MAX98927_Interrupt_State_1_BDE_ACTIVE_BGN_STATE = (0x1 << 1), + MAX98927_Interrupt_State_1_BDE_LEVEL_CHANGE_STATE = (0x1 << 2), + MAX98927_Interrupt_State_1_BDE_L8_STATE = (0x1 << 3), + MAX98927_Interrupt_State_1_THERMWARN_END_STATE = (0x1 << 4), + MAX98927_Interrupt_State_1_THERMWARN_START_STATE = (0x1 << 5), + MAX98927_Interrupt_State_1_THERMSHDN_END_STATE = (0x1 << 6), + MAX98927_Interrupt_State_1_THERMSHDN_START_STATE = (0x1 << 7), + + + MAX98927_Interrupt_State_2 = 0x0005, + MAX98927_Interrupt_State_2_WATCHDOGWARN_STATE = (0x1 << 0), + MAX98927_Interrupt_State_2_WATCHDOGFAIL_STATE = (0x1 << 1), + MAX98927_Interrupt_State_2_BOOSTCURRLIM_STATE = (0x1 << 2), + MAX98927_Interrupt_State_2_CLKSTOP_STATE = (0x1 << 3), + MAX98927_Interrupt_State_2_CLKSTART_STATE = (0x1 << 4), + MAX98927_Interrupt_State_2_MEASADC_END_STATE = (0x1 << 5), + MAX98927_Interrupt_State_2_PWRDN_DONE_STATE = (0x1 << 6), + MAX98927_Interrupt_State_2_PWRUP_DONE_STATE = (0x1 << 7), + + + MAX98927_Interrupt_State_3 = 0x0006, + MAX98927_Interrupt_State_3_PWRUP_FAIL_STATE = (0x1 << 0), + MAX98927_Interrupt_State_3_AUTH_DONE_STATE = (0x1 << 1), + MAX98927_Interrupt_State_3_SPK_OVC_STATE = (0x1 << 2), + MAX98927_Interrupt_State_3_BST_UVLO_STATE = (0x1 << 3), + + + MAX98927_Interrupt_Flag_1 = 0x0007, + MAX98927_Interrupt_Flag_1_BDE_ACTIVE_END_FLAG = (0x1 << 0), + MAX98927_Interrupt_Flag_1_BDE_ACTIVE_BGN_FLAG = (0x1 << 1), + MAX98927_Interrupt_Flag_1_BDE_LEVEL_CHANGE_FLAG = (0x1 << 2), + MAX98927_Interrupt_Flag_1_BDE_L8_FLAG = (0x1 << 3), + MAX98927_Interrupt_Flag_1_THERMWARN_END_FLAG = (0x1 << 4), + MAX98927_Interrupt_Flag_1_THERMWARN_START_FLAG = (0x1 << 5), + MAX98927_Interrupt_Flag_1_THERMSHDN_END_FLAG = (0x1 << 6), + MAX98927_Interrupt_Flag_1_THERMSHDN_START_FLAG = (0x1 << 7), + + + MAX98927_Interrupt_Flag_2 = 0x0008, + MAX98927_Interrupt_Flag_2_WATCHDOGWARN_FLAG = (0x1 << 0), + MAX98927_Interrupt_Flag_2_WATCHDOGFAIL_FLAG = (0x1 << 1), + MAX98927_Interrupt_Flag_2_BOOSTCURRLIM_FLAG = (0x1 << 2), + MAX98927_Interrupt_Flag_2_CLKSTOP_FLAG = (0x1 << 3), + MAX98927_Interrupt_Flag_2_CLKSTART_FLAG = (0x1 << 4), + MAX98927_Interrupt_Flag_2_MEASADC_END_FLAG = (0x1 << 5), + MAX98927_Interrupt_Flag_2_PWRDN_DONE_FLAG = (0x1 << 6), + MAX98927_Interrupt_Flag_2_PWRUP_DONE_FLAG = (0x1 << 7), + + + MAX98927_Interrupt_Flag_3 = 0x0009, + MAX98927_Interrupt_Flag_3_PWRUP_FAIL_FLAG = (0x1 << 0), + MAX98927_Interrupt_Flag_3_AUTH_DONE_FLAG = (0x1 << 1), + MAX98927_Interrupt_Flag_3_SPK_OVC_FLAG = (0x1 << 2), + MAX98927_Interrupt_Flag_3_BST_UVLO_FLAG = (0x1 << 3), + + + MAX98927_Interrupt_Enable_1 = 0x000a, + MAX98927_Interrupt_Enable_1_BDE_ACTIVE_END_EN = (0x1 << 0), + MAX98927_Interrupt_Enable_1_BDE_ACTIVE_BGN_EN = (0x1 << 1), + MAX98927_Interrupt_Enable_1_BDE_LEVEL_CHANGE_EN = (0x1 << 2), + MAX98927_Interrupt_Enable_1_BDE_L8_EN = (0x1 << 3), + MAX98927_Interrupt_Enable_1_THERMWARN_END_EN = (0x1 << 4), + MAX98927_Interrupt_Enable_1_THERMWARN_START_EN = (0x1 << 5), + MAX98927_Interrupt_Enable_1_THERMSHDN_END_EN = (0x1 << 6), + MAX98927_Interrupt_Enable_1_THERMSHDN_START_EN = (0x1 << 7), + + + MAX98927_Interrupt_Enable_2 = 0x000b, + MAX98927_Interrupt_Enable_2_WATCHDOGWARN_EN = (0x1 << 0), + MAX98927_Interrupt_Enable_2_WATCHDOGFAIL_EN = (0x1 << 1), + MAX98927_Interrupt_Enable_2_BOOSTCURRLIM_EN = (0x1 << 2), + MAX98927_Interrupt_Enable_2_CLKSTOP_EN = (0x1 << 3), + MAX98927_Interrupt_Enable_2_CLKSTART_EN = (0x1 << 4), + MAX98927_Interrupt_Enable_2_MEASADC_END_EN = (0x1 << 5), + MAX98927_Interrupt_Enable_2_PWRDN_DONE_EN = (0x1 << 6), + MAX98927_Interrupt_Enable_2_PWRUP_DONE_EN = (0x1 << 7), + + + MAX98927_Interrupt_Enable_3 = 0x000c, + MAX98927_Interrupt_Enable_3_PWRUP_FAIL_EN = (0x1 << 0), + MAX98927_Interrupt_Enable_3_AUTH_DONE_EN = (0x1 << 1), + MAX98927_Interrupt_Enable_3_SPK_OVC_EN = (0x1 << 2), + MAX98927_Interrupt_Enable_3_BST_UVLO_EN = (0x1 << 3), + + + MAX98927_Interrupt_Flag_Clear_1 = 0x000d, + MAX98927_Interrupt_Flag_Clear_1_BDE_ACTIVE_END_CLR = (0x1 << 0), + MAX98927_Interrupt_Flag_Clear_1_BDE_ACTIVE_BGN_CLR = (0x1 << 1), + MAX98927_Interrupt_Flag_Clear_1_BDE_LEVEL_CHANGE_CLR = (0x1 << 2), + MAX98927_Interrupt_Flag_Clear_1_BDE_L8_CLR = (0x1 << 3), + MAX98927_Interrupt_Flag_Clear_1_THERMWARN_END_CLR = (0x1 << 4), + MAX98927_Interrupt_Flag_Clear_1_THERMWARN_START_CLR = (0x1 << 5), + MAX98927_Interrupt_Flag_Clear_1_THERMSHDN_END_CLR = (0x1 << 6), + MAX98927_Interrupt_Flag_Clear_1_THERMSHDN_START_CLR = (0x1 << 7), + + + MAX98927_Interrupt_Flag_Clear_2 = 0x000e, + MAX98927_Interrupt_Flag_Clear_2_WATCHDOGWARN_CLR = (0x1 << 0), + MAX98927_Interrupt_Flag_Clear_2_WATCHDOGFAIL_CLR = (0x1 << 1), + MAX98927_Interrupt_Flag_Clear_2_BOOSTCURRLIM_CLR = (0x1 << 2), + MAX98927_Interrupt_Flag_Clear_2_CLKSTOP_CLR = (0x1 << 3), + MAX98927_Interrupt_Flag_Clear_2_CLKSTART_CLR = (0x1 << 4), + MAX98927_Interrupt_Flag_Clear_2_MEASADC_END_CLR = (0x1 << 5), + MAX98927_Interrupt_Flag_Clear_2_PWRDN_DONE_CLR = (0x1 << 6), + MAX98927_Interrupt_Flag_Clear_2_PWRUP_DONE_CLR = (0x1 << 7), + + + MAX98927_Interrupt_Flag_Clear_3 = 0x000f, + MAX98927_Interrupt_Flag_Clear_3_PWRUP_FAIL_CLR = (0x1 << 0), + MAX98927_Interrupt_Flag_Clear_3_AUTH_DONE_CLR = (0x1 << 1), + MAX98927_Interrupt_Flag_Clear_3_SPK_OVC_CLR = (0x1 << 2), + MAX98927_Interrupt_Flag_Clear_3_BST_UVLO_CLR = (0x1 << 3), + + + MAX98927_IRQ_Control = 0x0010, + MAX98927_IRQ_Control_IRQ_EN = (0x1 << 0), + MAX98927_IRQ_Control_IRQ_POL = (0x1 << 1), + MAX98927_IRQ_Control_IRQ_MODE = (0x1 << 2), + + + MAX98927_Clock_monitor_enable = 0x0011, + MAX98927_Clock_monitor_enable_CMON_ENA = (0x1 << 0), + MAX98927_Clock_monitor_enable_CMON_AUTORESTART_ENA = (0x1 << 1), + + + MAX98927_Watchdog_Control = 0x0012, + MAX98927_Watchdog_Control_WDT_ENA = (0x1 << 0), + MAX98927_Watchdog_Control_WDT_MODE = (0x1 << 1), + MAX98927_Watchdog_Control_WDT_TO_SEL_Mask = (0x3 << 2), + + MAX98927_Watchdog_Control_WDT_TO_SEL_5 = (0x0 << 2), + MAX98927_Watchdog_Control_WDT_TO_SEL_10 = (0x1 << 2), + MAX98927_Watchdog_Control_WDT_TO_SEL_35 = (0x2 << 2), + MAX98927_Watchdog_Control_WDT_TO_SEL_50 = (0x3 << 2), + MAX98927_Watchdog_Control_WDT_HW_SOURCE = (0x1 << 4), + + + MAX98927_Watchdog_SW_Reset = 0x0013, + + MAX98927_Watchdog_SW_Reset_WDT_SW_RST_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Thermal_Warning_Threshhold = 0x0014, + + MAX98927_Meas_ADC_Thermal_Warning_Threshhold_MEAS_ADC_WARN_THRESH_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold = 0x0015, + + MAX98927_Meas_ADC_Thermal_Shutdown_Threshhold_MEAS_ADC_SHDN_THRESH_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Thermal_Hysteresis = 0x0016, + + MAX98927_Meas_ADC_Thermal_Hysteresis_MEAS_ADC_THERM_HYST_Mask = (0x1f << 0), + + + MAX98927_Pin_Config = 0x0017, + MAX98927_Pin_Config_DOUT_DRV_Mask = (0x3 << 0), + + + MAX98927_Pin_Config_DOUT_DRV_01 = (0x0 << 0), + MAX98927_Pin_Config_DOUT_DRV_11 = (0x2 << 0), + MAX98927_Pin_Config_BCLK_DRV_Mask = (0x3 << 2), + + + MAX98927_Pin_Config_BCLK_DRV_01 = (0x0 << 2), + MAX98927_Pin_Config_BCLK_DRV_11 = (0x2 << 2), + MAX98927_Pin_Config_LRCLK_DRV_Mask = (0x3 << 4), + + + MAX98927_Pin_Config_LRCLK_DRV_01 = (0x0 << 4), + MAX98927_Pin_Config_LRCLK_DRV_11 = (0x2 << 4), + MAX98927_Pin_Config_ICC_DRV_Mask = (0x3 << 6), + + + MAX98927_Pin_Config_ICC_DRV_01 = (0x0 << 6), + MAX98927_Pin_Config_ICC_DRV_11 = (0x2 << 6), + + + MAX98927_PCM_Rx_Enables_A = 0x0018, + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH0_EN = (0x1 << 0), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH1_EN = (0x1 << 1), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH2_EN = (0x1 << 2), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH3_EN = (0x1 << 3), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH4_EN = (0x1 << 4), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH5_EN = (0x1 << 5), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH6_EN = (0x1 << 6), + MAX98927_PCM_Rx_Enables_A_PCM_RX_CH7_EN = (0x1 << 7), + + + MAX98927_PCM_Rx_Enables_B = 0x0019, + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH8_EN = (0x1 << 0), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH9_EN = (0x1 << 1), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH10_EN = (0x1 << 2), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH11_EN = (0x1 << 3), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH12_EN = (0x1 << 4), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH13_EN = (0x1 << 5), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH14_EN = (0x1 << 6), + MAX98927_PCM_Rx_Enables_B_PCM_RX_CH15_EN = (0x1 << 7), + + + MAX98927_PCM_Tx_Enables_A = 0x001a, + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH0_EN = (0x1 << 0), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH1_EN = (0x1 << 1), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH2_EN = (0x1 << 2), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH3_EN = (0x1 << 3), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH4_EN = (0x1 << 4), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH5_EN = (0x1 << 5), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH6_EN = (0x1 << 6), + MAX98927_PCM_Tx_Enables_A_PCM_TX_CH7_EN = (0x1 << 7), + + + MAX98927_PCM_Tx_Enables_B = 0x001b, + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH8_EN = (0x1 << 0), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH9_EN = (0x1 << 1), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH10_EN = (0x1 << 2), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH11_EN = (0x1 << 3), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH12_EN = (0x1 << 4), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH13_EN = (0x1 << 5), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH14_EN = (0x1 << 6), + MAX98927_PCM_Tx_Enables_B_PCM_TX_CH15_EN = (0x1 << 7), + + + MAX98927_PCM_Tx_HiZ_Control_A = 0x001c, + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH0_HIZ = (0x1 << 0), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH1_HIZ = (0x1 << 1), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH2_HIZ = (0x1 << 2), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH3_HIZ = (0x1 << 3), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH4_HIZ = (0x1 << 4), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH5_HIZ = (0x1 << 5), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH6_HIZ = (0x1 << 6), + MAX98927_PCM_Tx_HiZ_Control_A_PCM_TX_CH7_HIZ = (0x1 << 7), + + + MAX98927_PCM_Tx_HiZ_Control_B = 0x001d, + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH8_HIZ = (0x1 << 0), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH9_HIZ = (0x1 << 1), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH10_HIZ = (0x1 << 2), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH11_HIZ = (0x1 << 3), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH12_HIZ = (0x1 << 4), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH13_HIZ = (0x1 << 5), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH14_HIZ = (0x1 << 6), + MAX98927_PCM_Tx_HiZ_Control_B_PCM_TX_CH15_HIZ = (0x1 << 7), + + + MAX98927_PCM_Tx_Channel_Sources_A = 0x001e, + MAX98927_PCM_Tx_Channel_Sources_A_PCM_IVADC_V_DEST_Mask = (0xf << 0), + + + MAX98927_PCM_Tx_Channel_Sources_A_PCM_IVADC_I_DEST_Mask = (0xf << 4), + + + + + MAX98927_PCM_Tx_Channel_Sources_B = 0x001f, + MAX98927_PCM_Tx_Channel_Sources_B_PCM_AMP_DSP_DEST_Mask = (0xf << 0), + + + + + MAX98927_PCM_Mode_Config = 0x0020, + MAX98927_PCM_Mode_Config_PCM_TX_EXTRA_HIZ = (0x1 << 0), + MAX98927_PCM_Mode_Config_PCM_CHANSEL = (0x1 << 1), + MAX98927_PCM_Mode_Config_PCM_BCLKEDGE = (0x1 << 2), + MAX98927_PCM_Mode_Config_PCM_FORMAT_Mask = (0x7 << 3), + + + MAX98927_PCM_Mode_Config_PCM_FORMAT_I2S = (0x0 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_LEFT = (0x1 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_TDM_0 = (0x3 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_TDM_1 = (0x4 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_TDM_2 = (0x5 << 3), + MAX98927_PCM_Mode_Config_PCM_FORMAT_ = (0x6 << 3), + MAX98927_PCM_Mode_Config_PCM_CHANSZ_Mask = (0x3 << 6), + + + MAX98927_PCM_Mode_Config_PCM_CHANSZ_16 = (0x1 << 6), + MAX98927_PCM_Mode_Config_PCM_CHANSZ_24 = (0x2 << 6), + MAX98927_PCM_Mode_Config_PCM_CHANSZ_32 = (0x3 << 6), + + + MAX98927_PCM_Master_Mode = 0x0021, + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_Mask = (0x3 << 0), + + + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_SLAVE = (0x0 << 0), + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_MASTER = (0x3 << 0), + MAX98927_PCM_Master_Mode_PCM_MSTR_MODE_HYBRID = (0x1 << 0), + MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_Mask = (0xf << 2), + + + MAX98927_PCM_Master_Mode_PCM_CLK_SOURCE = (0x1 << 6), + + + MAX98927_PCM_Clock_setup = 0x0022, + MAX98927_PCM_Clock_setup_PCM_BSEL_Mask = (0xf << 0), + + + MAX98927_PCM_Clock_setup_PCM_MSEL_Mask = (0xf << 4), + + + + + MAX98927_PCM_Sample_rate_setup_1 = 0x0023, + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_Mask = (0xf << 0), + + + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_8000 = (0x0 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_11025 = (0x1 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_12000 = (0x2 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_16000 = (0x3 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_22050 = (0x4 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_24000 = (0x5 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_32000 = (0x6 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_44100 = (0x7 << 0), + MAX98927_PCM_Sample_rate_setup_1_DIG_IF_SR_48000 = (0x8 << 0), + + + MAX98927_PCM_Sample_rate_setup_2 = 0x0024, + MAX98927_PCM_Sample_rate_setup_2_IVADC_SR_Mask = (0xf << 0), + + + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_Mask = (0xf << 4), + + + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0001 = (0x0 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0011 = (0x2 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0101 = (0x4 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_0111 = (0x6 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_1001 = (0x8 << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_1011 = (0xa << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_1101 = (0xc << 4), + MAX98927_PCM_Sample_rate_setup_2_SPK_SR_ = (0xf << 4), + + + MAX98927_PCM_to_speaker_monomix_A = 0x0025, + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CH0_SOURCE_Mask = (0xf << 0), + + + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CFG_Mask = (0x3 << 6), + + + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CFG_1 = (0x0 << 6), + MAX98927_PCM_to_speaker_monomix_A_DMONOMIX_CFG_3 = (0x0 << 6), + + + MAX98927_PCM_to_speaker_monomix_B = 0x0026, + MAX98927_PCM_to_speaker_monomix_B_DMONOMIX_CH1_SOURCE_Mask = (0xf << 0), + + + + + MAX98927_ICC_RX_Enables_A = 0x0027, + MAX98927_ICC_RX_Enables_A_ICC_RX_CH0_EN = (0x1 << 0), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH1_EN = (0x1 << 1), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH2_EN = (0x1 << 2), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH3_EN = (0x1 << 3), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH4_EN = (0x1 << 4), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH5_EN = (0x1 << 5), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH6_EN = (0x1 << 6), + MAX98927_ICC_RX_Enables_A_ICC_RX_CH7_EN = (0x1 << 7), + + + MAX98927_ICC_RX_Enables_B = 0x0028, + MAX98927_ICC_RX_Enables_B_ICC_RX_CH8_EN = (0x1 << 0), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH9_EN = (0x1 << 1), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH10_EN = (0x1 << 2), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH11_EN = (0x1 << 3), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH12_EN = (0x1 << 4), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH13_EN = (0x1 << 5), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH14_EN = (0x1 << 6), + MAX98927_ICC_RX_Enables_B_ICC_RX_CH15_EN = (0x1 << 7), + + + MAX98927_ICC_TX_Enables_A = 0x002b, + MAX98927_ICC_TX_Enables_A_ICC_TX_CH0_EN = (0x1 << 0), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH1_EN = (0x1 << 1), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH2_EN = (0x1 << 2), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH3_EN = (0x1 << 3), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH4_EN = (0x1 << 4), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH5_EN = (0x1 << 5), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH6_EN = (0x1 << 6), + MAX98927_ICC_TX_Enables_A_ICC_TX_CH7_EN = (0x1 << 7), + + + MAX98927_ICC_TX_Enables_B = 0x002c, + MAX98927_ICC_TX_Enables_B_ICC_TX_CH8_EN = (0x1 << 0), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH9_EN = (0x1 << 1), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH10_EN = (0x1 << 2), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH11_EN = (0x1 << 3), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH12_EN = (0x1 << 4), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH13_EN = (0x1 << 5), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH14_EN = (0x1 << 6), + MAX98927_ICC_TX_Enables_B_ICC_TX_CH15_EN = (0x1 << 7), + + + MAX98927_ICC_Data_Order_Select = 0x002d, + MAX98927_ICC_Data_Order_Select_ICC_DRIVE_MODE = (0x1 << 3), + + + MAX98927_ICC_HiZ_Manual_Mode = 0x002e, + MAX98927_ICC_HiZ_Manual_Mode_ICC_TX_HIZ_MANUAL = (0x1 << 0), + MAX98927_ICC_HiZ_Manual_Mode_ICC_TX_EXTRA_HIZ = (0x1 << 1), + + + MAX98927_ICC_TX_HiZ_Enables_A = 0x002f, + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH0_HIZ = (0x1 << 0), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH1_HIZ = (0x1 << 1), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH2_HIZ = (0x1 << 2), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH3_HIZ = (0x1 << 3), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH4_HIZ = (0x1 << 4), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH5_HIZ = (0x1 << 5), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH6_HIZ = (0x1 << 6), + MAX98927_ICC_TX_HiZ_Enables_A_ICC_TX_CH7_HIZ = (0x1 << 7), + + + MAX98927_ICC_TX_HiZ_Enables_B = 0x0030, + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH8_HIZ = (0x1 << 0), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH9_HIZ = (0x1 << 1), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH10_HIZ = (0x1 << 2), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH11_HIZ = (0x1 << 3), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH12_HIZ = (0x1 << 4), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH13_HIZ = (0x1 << 5), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH14_HIZ = (0x1 << 6), + MAX98927_ICC_TX_HiZ_Enables_B_ICC_TX_CH15_HIZ = (0x1 << 7), + + + MAX98927_ICC_Link_Enables = 0x0031, + MAX98927_ICC_Link_Enables_ICC_LINK_EN = (0x1 << 1), + + + MAX98927_PDM_Tx_Enables = 0x0032, + MAX98927_PDM_Tx_Enables_PDM_TX_EN = (0x1 << 0), + MAX98927_PDM_Tx_Enables_PDM_TX_CLK_DIV2 = (0x1 << 1), + + + MAX98927_PDM_Tx_HiZ_Control = 0x0033, + MAX98927_PDM_Tx_HiZ_Control_PDM_TX_HIZ = (0x1 << 0), + + + MAX98927_PDM_Tx_Control = 0x0034, + MAX98927_PDM_Tx_Control_PDM_TX_CH0_SOURCE = (0x1 << 0), + MAX98927_PDM_Tx_Control_PDM_TX_CH1_SOURCE = (0x1 << 1), + + + MAX98927_PDM_Rx_Enable = 0x0035, + MAX98927_PDM_Rx_Enable_PDM_RX_EN = (0x1 << 0), + MAX98927_PDM_Rx_Enable_PDM_DSP_EN = (0x1 << 1), + MAX98927_PDM_Rx_Enable_PDM_DITH_EN = (0x1 << 2), + MAX98927_PDM_Rx_Enable_PDM_RX_CH_SEL = (0x1 << 3), + MAX98927_PDM_Rx_Enable_PDM_FIFO_RDY_LVL_Mask = (0xf << 4), + + + + + MAX98927_AMP_volume_control = 0x0036, + + MAX98927_AMP_volume_control_AMP_VOL_Mask = (0x7f << 0), + MAX98927_AMP_volume_control_AMP_VOL_SEL = (0x1 << 7), + + + MAX98927_AMP_DSP_Config = 0x0037, + MAX98927_AMP_DSP_Config_AMP_DCBLK_EN = (0x1 << 0), + MAX98927_AMP_DSP_Config_AMP_DITH_EN = (0x1 << 1), + MAX98927_AMP_DSP_Config_DAC_HALF_REF_CURRENT = (0x1 << 2), + MAX98927_AMP_DSP_Config_DAC_DOUBLE_RFB = (0x1 << 3), + MAX98927_AMP_DSP_Config_AMP_VOL_RMP_BYPASS = (0x1 << 4), + MAX98927_AMP_DSP_Config_DAC_INVERT = (0x1 << 5), + + + MAX98927_Tone_Generator_and_DC_Config = 0x0038, + MAX98927_Tone_Generator_and_DC_Config_TONE_CONFIG_Mask = (0xf << 0), + + + + + MAX98927_DRE_Control = 0x0039, + MAX98927_DRE_Control_DRE_EN = (0x1 << 0), + + + MAX98927_AMP_enables = 0x003a, + MAX98927_AMP_enables_SPK_EN = (0x1 << 0), + + + MAX98927_Speaker_source_select = 0x003b, + MAX98927_Speaker_source_select_SPK_SOURCE_Mask = (0x3 << 0), + + + MAX98927_Speaker_source_select_SPK_SOURCE_01 = (0x0 << 0), + MAX98927_Speaker_source_select_SPK_SOURCE_11 = (0x2 << 0), + + + MAX98927_Speaker_Gain = 0x003c, + MAX98927_Speaker_Gain_SPK_PCM_GAIN_Mask = (0x7 << 0), + + + MAX98927_Speaker_Gain_SPK_PCM_GAIN_001 = (0x0 << 0), + MAX98927_Speaker_Gain_SPK_PCM_GAIN_011 = (0x2 << 0), + MAX98927_Speaker_Gain_SPK_PCM_GAIN_101 = (0x4 << 0), + MAX98927_Speaker_Gain_SPK_PCM_GAIN_111 = (0x6 << 0), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_Mask = (0x7 << 4), + + + MAX98927_Speaker_Gain_SPK_PDM_GAIN_001 = (0x0 << 4), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_011 = (0x2 << 4), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_101 = (0x4 << 4), + MAX98927_Speaker_Gain_SPK_PDM_GAIN_111 = (0x6 << 4), + + + MAX98927_SSM_Configuration = 0x003d, + MAX98927_SSM_Configuration_SSM_MOD_INDEX_Mask = (0x7 << 0), + + + MAX98927_SSM_Configuration_SSM_MOD_INDEX_001 = (0x0 << 0), + MAX98927_SSM_Configuration_SSM_MOD_INDEX_011 = (0x2 << 0), + MAX98927_SSM_Configuration_SSM_MOD_INDEX_101 = (0x4 << 0), + MAX98927_SSM_Configuration_SSM_MOD_INDEX_ = (0x6 << 0), + MAX98927_SSM_Configuration_SPK_FSW_SEL = (0x1 << 3), + MAX98927_SSM_Configuration_SSM_ENA = (0x1 << 7), + + + MAX98927_Measurement_enables = 0x003e, + MAX98927_Measurement_enables_IVADC_V_EN = (0x1 << 0), + MAX98927_Measurement_enables_IVADC_I_EN = (0x1 << 1), + + + MAX98927_Measurement_DSP_Config = 0x003f, + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_EN = (0x1 << 0), + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_EN = (0x1 << 1), + MAX98927_Measurement_DSP_Config_MEAS_DITH_EN = (0x1 << 2), + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_Mask = (0x3 << 4), + + + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_01 = (0x0 << 4), + MAX98927_Measurement_DSP_Config_MEAS_V_DCBLK_11 = (0x2 << 4), + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_Mask = (0x3 << 6), + + + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_01 = (0x0 << 6), + MAX98927_Measurement_DSP_Config_MEAS_I_DCBLK_11 = (0x2 << 6), + + + MAX98927_Boost_Control_0 = 0x0040, + + MAX98927_Boost_Control_0_BST_VOUT_Mask = (0x1f << 0), + MAX98927_Boost_Control_0_EXT_PVDD_EN = (0x1 << 7), + + + MAX98927_Boost_Control_3 = 0x0041, + MAX98927_Boost_Control_3_BST_SKIPLOAD_Mask = (0x3 << 0), + + + MAX98927_Boost_Control_3_BST_SKIPLOAD_01 = (0x0 << 0), + MAX98927_Boost_Control_3_BST_SKIPLOAD_11 = (0x2 << 0), + MAX98927_Boost_Control_3_BST_PHASE_Mask = (0x7 << 2), + + + MAX98927_Boost_Control_3_BST_PHASE_001 = (0x0 << 2), + MAX98927_Boost_Control_3_BST_PHASE_011 = (0x2 << 2), + MAX98927_Boost_Control_3_BST_PHASE_ = (0x1 << 2), + MAX98927_Boost_Control_3_BST_SLOWSTART = (0x1 << 5), + + + MAX98927_Boost_Control_1 = 0x0042, + + MAX98927_Boost_Control_1_BST_ILIM_Mask = (0x1f << 1), + + + MAX98927_Meas_ADC_Config = 0x0043, + MAX98927_Meas_ADC_Config_MEAS_ADC_CH0_EN = (0x1 << 0), + MAX98927_Meas_ADC_Config_MEAS_ADC_CH1_EN = (0x1 << 1), + MAX98927_Meas_ADC_Config_MEAS_ADC_CH2_EN = (0x1 << 2), + + + MAX98927_Meas_ADC_Base_Divide_MSByte = 0x0044, + + MAX98927_Meas_ADC_Base_Divide_MSByte_MEAS_ADC_BASE_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Base_Divide_LSByte = 0x0045, + + MAX98927_Meas_ADC_Base_Divide_LSByte_MEAS_ADC_BASE_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_0_Divide = 0x0046, + + MAX98927_Meas_ADC_Chan_0_Divide_MEAS_ADC_CH0_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_1_Divide = 0x0047, + + MAX98927_Meas_ADC_Chan_1_Divide_MEAS_ADC_CH1_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_2_Divide = 0x0048, + + MAX98927_Meas_ADC_Chan_2_Divide_MEAS_ADC_CH2_DIV_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_0_Filt_Config = 0x0049, + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_Mask = (0x7 << 0), + + + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_001 = (0x0 << 0), + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_011 = (0x2 << 0), + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_AVG_101 = (0x4 << 0), + MAX98927_Meas_ADC_Chan_0_Filt_Config_MEAS_ADC_CH0_FILT_EN = (0x1 << 3), + + + MAX98927_Meas_ADC_Chan_1_Filt_Config = 0x004a, + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_Mask = (0x7 << 0), + + + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_001 = (0x0 << 0), + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_011 = (0x2 << 0), + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_AVG_101 = (0x4 << 0), + MAX98927_Meas_ADC_Chan_1_Filt_Config_MEAS_ADC_CH1_FILT_EN = (0x1 << 3), + + + MAX98927_Meas_ADC_Chan_2_Filt_Config = 0x004b, + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_Mask = (0x7 << 0), + + + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_001 = (0x0 << 0), + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_011 = (0x2 << 0), + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_AVG_101 = (0x4 << 0), + MAX98927_Meas_ADC_Chan_2_Filt_Config_MEAS_ADC_CH2_FILT_EN = (0x1 << 3), + + + MAX98927_Meas_ADC_Chan_0_Readback = 0x004c, + + MAX98927_Meas_ADC_Chan_0_Readback_MEAS_ADC_CH0_DATA_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_1_Readback = 0x004d, + + MAX98927_Meas_ADC_Chan_1_Readback_MEAS_ADC_CH1_DATA_Mask = (0xff << 0), + + + MAX98927_Meas_ADC_Chan_2_Readback = 0x004e, + + MAX98927_Meas_ADC_Chan_2_Readback_MEAS_ADC_CH2_DATA_Mask = (0xff << 0), + + + MAX98927_Brownout_status = 0x0051, + MAX98927_Brownout_status_BDE_STATE_Mask = (0xf << 0), + + + + + MAX98927_Brownout_enables = 0x0052, + MAX98927_Brownout_enables_BDE_EN = (0x1 << 0), + MAX98927_Brownout_enables_BDE_AMP_EN = (0x1 << 1), + MAX98927_Brownout_enables_AMP_DSP_EN = (0x1 << 2), + + + MAX98927_Brownout_level_infinite_hold = 0x0053, + MAX98927_Brownout_level_infinite_hold_BDE_L8_INF_HLD = (0x1 << 1), + + + MAX98927_Brownout_level_infinite_hold_clear = 0x0054, + MAX98927_Brownout_level_infinite_hold_clear_BDE_L8_HLD_RLS = (0x1 << 1), + + + MAX98927_Brownout_level_hold = 0x0055, + + MAX98927_Brownout_level_hold_BDE_HLD_Mask = (0xff << 0), + + + MAX98927_Brownout__level_1_threshold = 0x005a, + + MAX98927_Brownout__level_1_threshold_BDE_L1_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_2_threshold = 0x005b, + + MAX98927_Brownout__level_2_threshold_BDE_L2_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_3_threshold = 0x005c, + + MAX98927_Brownout__level_3_threshold_BDE_L3_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_4_threshold = 0x005d, + + MAX98927_Brownout__level_4_threshold_BDE_L4_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_5_threshold = 0x005a, + + MAX98927_Brownout__level_5_threshold_BDE_L5_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_6_threshold = 0x005b, + + MAX98927_Brownout__level_6_threshold_BDE_L6_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_7_threshold = 0x005c, + + MAX98927_Brownout__level_7_threshold_BDE_L7_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout__level_8_threshold = 0x005d, + + MAX98927_Brownout__level_8_threshold_BDE_L8_VTHRESH_Mask = (0xff << 0), + + + MAX98927_Brownout_threshold_hysterysis = 0x005e, + + MAX98927_Brownout_threshold_hysterysis_BDE_VTHRESH_HYST_Mask = (0xff << 0), + + + MAX98927_Brownout_AMP_limiter_attack_release = 0x005f, + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_Mask = (0xf << 0), + + + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0001 = (0x0 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0011 = (0x2 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0101 = (0x4 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_0111 = (0x6 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1001 = (0x8 << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1011 = (0xa << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1101 = (0xc << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_RLS_1111 = (0xe << 0), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_Mask = (0xf << 4), + + + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0001 = (0x0 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0011 = (0x2 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0101 = (0x4 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_0111 = (0x6 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1001 = (0x8 << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1011 = (0xa << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1101 = (0xc << 4), + MAX98927_Brownout_AMP_limiter_attack_release_AMP_LIM_ATK_1111 = (0xe << 4), + + + MAX98927_Brownout_AMP_gain_attack_release = 0x0060, + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_Mask = (0xf << 0), + + + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0001 = (0x0 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0011 = (0x2 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0101 = (0x4 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_0111 = (0x6 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1001 = (0x8 << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1011 = (0xa << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1101 = (0xc << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_RLS_1111 = (0xe << 0), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_Mask = (0xf << 4), + + + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0001 = (0x0 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0011 = (0x2 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0101 = (0x4 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_0111 = (0x6 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1001 = (0x8 << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1011 = (0xa << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1101 = (0xc << 4), + MAX98927_Brownout_AMP_gain_attack_release_AMP_GAIN_ATK_1111 = (0xe << 4), + + + MAX98927_Brownout_AMP1_clip_mode = 0x0061, + MAX98927_Brownout_AMP1_clip_mode_AMP_CLIP_MODE = (0x1 << 0), + + + MAX98927_Brownout__level_1_current_limit = 0x0072, + + MAX98927_Brownout__level_1_current_limit_BDE_L1_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_1_amp_1_control_1 = 0x0073, + MAX98927_Brownout__level_1_amp_1_control_1_BDE_L1_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_1_amp_1_control_2 = 0x0074, + + MAX98927_Brownout__level_1_amp_1_control_2_BDE_L1_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_1_amp_1_control_3 = 0x0075, + + MAX98927_Brownout__level_1_amp_1_control_3_BDE_L1_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_2_current_limit = 0x0076, + + MAX98927_Brownout__level_2_current_limit_BDE_L2_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_2_amp_1_control_1 = 0x0077, + MAX98927_Brownout__level_2_amp_1_control_1_BDE_L2_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_2_amp_1_control_2 = 0x0078, + + MAX98927_Brownout__level_2_amp_1_control_2_BDE_L2_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_2_amp_1_control_3 = 0x0079, + + MAX98927_Brownout__level_2_amp_1_control_3_BDE_L2_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_3_current_limit = 0x007a, + + MAX98927_Brownout__level_3_current_limit_BDE_L3_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_3_amp_1_control_1 = 0x007b, + MAX98927_Brownout__level_3_amp_1_control_1_BDE_L3_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_3_amp_1_control_2 = 0x007c, + + MAX98927_Brownout__level_3_amp_1_control_2_BDE_L3_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_3_amp_1_control_3 = 0x007d, + + MAX98927_Brownout__level_3_amp_1_control_3_BDE_L3_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_4_current_limit = 0x007e, + + MAX98927_Brownout__level_4_current_limit_BDE_L4_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_4_amp_1_control_1 = 0x007f, + MAX98927_Brownout__level_4_amp_1_control_1_BDE_L4_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_4_amp_1_control_2 = 0x0080, + + MAX98927_Brownout__level_4_amp_1_control_2_BDE_L4_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_4_amp_1_control_3 = 0x0081, + + MAX98927_Brownout__level_4_amp_1_control_3_BDE_L4_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_5_current_limit = 0x0072, + + MAX98927_Brownout__level_5_current_limit_BDE_L5_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_5_amp_1_control_1 = 0x0073, + MAX98927_Brownout__level_5_amp_1_control_1_BDE_L5_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_5_amp_1_control_2 = 0x0074, + + MAX98927_Brownout__level_5_amp_1_control_2_BDE_L5_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_5_amp_1_control_3 = 0x0075, + + MAX98927_Brownout__level_5_amp_1_control_3_BDE_L5_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_6_current_limit = 0x0076, + + MAX98927_Brownout__level_6_current_limit_BDE_L6_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_6_amp_1_control_1 = 0x0077, + MAX98927_Brownout__level_6_amp_1_control_1_BDE_L6_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_6_amp_1_control_2 = 0x0078, + + MAX98927_Brownout__level_6_amp_1_control_2_BDE_L6_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_6_amp_1_control_3 = 0x0079, + + MAX98927_Brownout__level_6_amp_1_control_3_BDE_L6_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_7_current_limit = 0x007a, + + MAX98927_Brownout__level_7_current_limit_BDE_L7_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_7_amp_1_control_1 = 0x007b, + MAX98927_Brownout__level_7_amp_1_control_1_BDE_L7_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_7_amp_1_control_2 = 0x007c, + + MAX98927_Brownout__level_7_amp_1_control_2_BDE_L7_AMP1_CLIP_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_7_amp_1_control_3 = 0x007d, + + MAX98927_Brownout__level_7_amp_1_control_3_BDE_L7_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_8_current_limit = 0x007e, + + MAX98927_Brownout__level_8_current_limit_BDE_L8_ILIM_Mask = (0x3f << 0), + + + MAX98927_Brownout__level_8_amp_1_control_1 = 0x007f, + MAX98927_Brownout__level_8_amp_1_control_1_BDE_L8_AMP1_LIM_Mask = (0xf << 0), + + + + + MAX98927_Brownout__level_8_amp_1_control_2 = 0x0080, + + MAX98927_Brownout__level_8_amp_1_control_2_BDE_L8_AMP1_CLIP_Mask = (0x3f << 0), + MAX98927_Brownout__level_8_amp_1_control_2_BDE_L8_AMP1_MUTE = (0x1 << 7), + + + MAX98927_Brownout__level_8_amp_1_control_3 = 0x0081, + + MAX98927_Brownout__level_8_amp_1_control_3_BDE_L8_AMP1_GAIN_Mask = (0x3f << 0), + + + MAX98927_Env_Tracker_Vout_Headroom = 0x0082, + + MAX98927_Env_Tracker_Vout_Headroom_ENV_TRACKER_BST_VOUT_HEADROOM_Mask = (0x1f << 0), + + + MAX98927_Env_Tracker_Boost_Vout_Delay = 0x0083, + + MAX98927_Env_Tracker_Boost_Vout_Delay_ENV_TRACKER_BST_VOUT_DELAY_Mask = (0x1f << 0), + MAX98927_Env_Tracker_Boost_Vout_Delay_ENV_TRACKER_BDE_MODE = (0x1 << 7), + + + MAX98927_Env_Tracker_Release_Rate = 0x0084, + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_Mask = (0x7 << 0), + + + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_001 = (0x0 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_011 = (0x2 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_101 = (0x4 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_111 = (0x6 << 0), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_PEAK_DET_LPF_BYP_EN = (0x1 << 3), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_SCALE_Mask = (0x3 << 4), + + + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_SCALE_01 = (0x0 << 4), + MAX98927_Env_Tracker_Release_Rate_ENV_TRACKER_RLS_RATE_SCALE_11 = (0x2 << 4), + + + MAX98927_Env_Tracker_Hold_Rate = 0x0085, + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_Mask = (0x7 << 0), + + + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_001 = (0x0 << 0), + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_011 = (0x2 << 0), + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_101 = (0x4 << 0), + MAX98927_Env_Tracker_Hold_Rate_ENV_TRACKER_HOLD_RATE_111 = (0x6 << 0), + + + MAX98927_Env_Tracker_Control = 0x0086, + MAX98927_Env_Tracker_Control_ENV_TRACKER_EN = (0x1 << 0), + + + MAX98927_Env_Tracker__Boost_Vout_ReadBack = 0x0087, + + MAX98927_Env_Tracker__Boost_Vout_ReadBack_ENV_TRACKER_BST_VOUT_RD_Mask = (0x1f << 0), + + + MAX98927_Advanced_Settings = 0x0089, + MAX98927_Advanced_Settings_DAC_HALF_FIR = (0x1 << 0), + MAX98927_Advanced_Settings_PDM_MOD_SEL = (0x1 << 1), + MAX98927_Advanced_Settings_ISOCH_EN = (0x1 << 2), + + + MAX98927_DAC_Test_1 = 0x009f, + MAX98927_DAC_Test_1_DAC_PCM_TIMING = (0x1 << 0), + MAX98927_DAC_Test_1_DAC_HALFI_AMP = (0x1 << 1), + MAX98927_DAC_Test_1_DAC_LONG_HOLD = (0x1 << 3), + MAX98927_DAC_Test_1_DAC_DISABLE_CHOP = (0x1 << 4), + MAX98927_DAC_Test_1_DAC_TM = (0x1 << 5), + MAX98927_DAC_Test_1_DAC_INVERT_DACCLK = (0x1 << 6), + + + MAX98927_Authentication_key_0 = 0x00ea, + + MAX98927_Authentication_key_0_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_key_1 = 0x00eb, + + MAX98927_Authentication_key_1_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_key_2 = 0x00ec, + + MAX98927_Authentication_key_2_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_key_3 = 0x00ed, + + MAX98927_Authentication_key_3_AUTH_KEY_Mask = (0xff << 0), + + + MAX98927_Authentication_enable = 0x00ee, + MAX98927_Authentication_enable_AUTH_EN = (0x1 << 0), + + + MAX98927_Authentication_result_0 = 0x00ef, + + MAX98927_Authentication_result_0_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_1 = 0x00f0, + + MAX98927_Authentication_result_1_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_2 = 0x00f1, + + MAX98927_Authentication_result_2_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_3 = 0x00f2, + + MAX98927_Authentication_result_3_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_4 = 0x00f3, + + MAX98927_Authentication_result_4_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_5 = 0x00f4, + + MAX98927_Authentication_result_5_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_6 = 0x00f5, + + MAX98927_Authentication_result_6_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_7 = 0x00f6, + + MAX98927_Authentication_result_7_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_8 = 0x00f7, + + MAX98927_Authentication_result_8_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_9 = 0x00f8, + + MAX98927_Authentication_result_9_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_10 = 0x00f9, + + MAX98927_Authentication_result_10_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_11 = 0x00fa, + + MAX98927_Authentication_result_11_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_12 = 0x00fb, + + MAX98927_Authentication_result_12_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_13 = 0x00fc, + + MAX98927_Authentication_result_13_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_14 = 0x00fd, + + MAX98927_Authentication_result_14_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Authentication_result_15 = 0x00fe, + + MAX98927_Authentication_result_15_AUTH_RESULT_Mask = (0xff << 0), + + + MAX98927_Global_Enable = 0x00ff, + MAX98927_Global_Enable_EN = (0x1 << 0), + + MAX98927_Software_Reset = 0x0100, + MAX98927_Software_Reset_RST = (0x1 << 0), + + + MAX98927_REV_ID = 0x01ff, + + MAX98927_REV_ID_REV_ID_Mask = (0xff << 0), + + +} MAX98927Registers; + +typedef enum{ + MAX98927_CH0 = (1 << 0), + MAX98927_CH1 = (1 << 1), + MAX98927_CH2 = (1 << 2), + MAX98927_CH3 = (1 << 3), +} MAX98927_CHANNEL_SHIT; + +struct max98927_priv { + struct device *dev; + struct regmap *regmap[MAX_CHANNEL_NUM]; + struct snd_soc_codec *codec; + struct max98927_pdata *pdata; + unsigned int spk_mode; + unsigned int spk_gain; + unsigned int sysclk; + unsigned int v_l_slot; + unsigned int i_l_slot; + unsigned int v_r_slot; + unsigned int i_r_slot; + unsigned int mono_stereo; + unsigned int i2c_states; + bool interleave_mode; + unsigned int ch_size; + unsigned int rate; + unsigned int iface; + unsigned int master; + unsigned int thres_hyste; + unsigned int level5_hold; + unsigned int level6_hold; + unsigned int level7_hold; + unsigned int level8_hold; + unsigned int amp_limit; + unsigned int amp_limit_rel; + unsigned int amp1_level; + unsigned int amp2_level; + unsigned int amp3_level; + unsigned int amp1_level8; + unsigned int amp2_level8; + unsigned int amp3_level8; + unsigned int amp1_level7; + unsigned int amp2_level7; + unsigned int amp3_level7; + unsigned int amp1_level6; + unsigned int amp2_level6; + unsigned int amp3_level6; + unsigned int amp1_level5; + unsigned int amp2_level5; + unsigned int amp3_level5; + unsigned int digital_gain; + unsigned int pdm_gain; + unsigned int level_hold; + unsigned int ref_RDC[2]; + unsigned int path_status; + unsigned int adsp_mode; + int reset_gpio_l; + int reset_gpio_r; +#ifdef CONFIG_DEBUG_FS + struct dentry *dbg_dir; +#endif + struct regulator *max989xx_vdd; +}; + +#define MAX98927_GLOBAL_SHIFT 0 +#define M98927_DAI_MSEL_SHIFT 4 +#define M98927_DAI_BSEL_SHIFT 0 +#define M98927_DAI_BSEL_32 (2 << M98927_DAI_BSEL_SHIFT) +#define M98927_DAI_BSEL_48 (3 << M98927_DAI_BSEL_SHIFT) +#define M98927_DAI_BSEL_64 (4 << M98927_DAI_BSEL_SHIFT) +#define M98927_DAI_MSEL_32 (2 << M98927_DAI_MSEL_SHIFT) +#define M98927_DAI_MSEL_48 (3 << M98927_DAI_MSEL_SHIFT) +#define M98927_DAI_MSEL_64 (4 << M98927_DAI_MSEL_SHIFT) +#define MAX98927_Speaker_Gain_Width 3 +#define MAX98927_SPK_RMP_EN_SHIFT 4 +#define MAX98927_PDM_GAIN_SHIFT 4 +#define MAX98927_pdm_Gain_Width 3 +#define MAX98927_AMP_VOL_WIDTH 7 +#define MAX98927_AMP_VOL_LOCATION_SHIFT 7 +#define MAX98927_PDM_Rx_Enable_PDM_CH_SHIFT 3 +#define MAX98927_PCM_to_speaker_monomix_A_SHIFT 6 +#define MAX98927_PCM_Sample_rate_setup_2_DIG_IF_SR_48000 (0x8 << 4) +#define MAX98927_PCM_FORMAT_DSP_A (0x3 << 3) +#define MAX98927_DRE_Control_DRE_SHIFT 0 +#define MAX98927_PCM_Master_Mode_PCM_MCLK_RATE_SHIFT (2) +#define MAX98927_Brownout_AMP_limiter_attack_release_shift 4 +#define MAX98927_BDE_DSP_SHIFT 2 +#define MAX98927_Speaker_Gain_SPK_PDM_GAIN_SHIFT (4) +#define MAX98927_BDE_AMP_SHIFT 1 +#define MAX98927_BST_ILIM_SHIFT 1 +#endif diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index bfd98a82b8179..884f2809554da 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -99,7 +99,7 @@ enum { #define SPK_PMD 2 #define SPK_PMU 3 -#define MICBIAS_DEFAULT_VAL 1800000 +#define MICBIAS_DEFAULT_VAL 2200000 #define MICBIAS_MIN_VAL 1600000 #define MICBIAS_STEP_SIZE 50000 diff --git a/sound/soc/codecs/tas2557-codec.c b/sound/soc/codecs/tas2557-codec.c new file mode 100644 index 0000000000000..54bcef244fe14 --- /dev/null +++ b/sound/soc/codecs/tas2557-codec.c @@ -0,0 +1,586 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-codec.c +** +** Description: +** ALSA SoC driver for Texas Instruments TAS2557 High Performance 4W Smart Amplifier +** +** ============================================================================= +*/ + +#ifdef CONFIG_TAS2557_CODEC + +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas2557-core.h" +#include "tas2557-codec.h" + +#define KCONTROL_CODEC + +static unsigned int tas2557_codec_read(struct snd_soc_codec *pCodec, + unsigned int nRegister) +{ + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + int ret = 0; + unsigned int Value = 0; + + mutex_lock(&pTAS2557->codec_lock); + + ret = pTAS2557->read(pTAS2557, nRegister, &Value); + if (ret < 0) + dev_err(pTAS2557->dev, "%s, %d, ERROR happen=%d\n", __func__, + __LINE__, ret); + else + ret = Value; + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegister, + unsigned int nValue) +{ + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + int ret = 0; + + mutex_lock(&pTAS2557->codec_lock); + + ret = pTAS2557->write(pTAS2557, nRegister, nValue); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static int tas2557_codec_suspend(struct snd_soc_codec *pCodec) +{ + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + int ret = 0; + + mutex_lock(&pTAS2557->codec_lock); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + pTAS2557->runtime_suspend(pTAS2557); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static int tas2557_codec_resume(struct snd_soc_codec *pCodec) +{ + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + int ret = 0; + + mutex_lock(&pTAS2557->codec_lock); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + pTAS2557->runtime_resume(pTAS2557); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static const struct snd_soc_dapm_widget tas2557_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("ASI2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("ASIM", "ASIM Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_OUT_DRV("ClassD", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("NDivider", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_OUTPUT("OUT") +}; + +static const struct snd_soc_dapm_route tas2557_audio_map[] = { + {"DAC", NULL, "ASI1"}, + {"DAC", NULL, "ASI2"}, + {"DAC", NULL, "ASIM"}, + {"ClassD", NULL, "DAC"}, + {"OUT", NULL, "ClassD"}, + {"DAC", NULL, "PLL"}, + {"DAC", NULL, "NDivider"}, +}; + +static int tas2557_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + return 0; +} + +static void tas2557_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); +} + +static int tas2557_mute(struct snd_soc_dai *dai, int mute) +{ + struct snd_soc_codec *codec = dai->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&pTAS2557->codec_lock); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + printk("%s\n", __func__); + tas2557_enable(pTAS2557, !mute); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_set_dai_sysclk(struct snd_soc_dai *pDAI, + int nClkID, unsigned int nFreqency, int nDir) +{ + struct snd_soc_codec *pCodec = pDAI->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + + dev_dbg(pTAS2557->dev, "tas2557_set_dai_sysclk: freq = %u\n", nFreqency); + printk("%s\n", __func__); + + return 0; +} + +static int tas2557_hw_params(struct snd_pcm_substream *pSubstream, + struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI) +{ + struct snd_soc_codec *pCodec = pDAI->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + + mutex_lock(&pTAS2557->codec_lock); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + printk("%s\n", __func__); +/* do bit rate setting during platform data */ +/* tas2557_set_bit_rate(pTAS2557, channel_both, snd_pcm_format_width(params_format(pParams))); */ + tas2557_set_sampling_rate(pTAS2557, params_rate(pParams)); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_set_dai_fmt(struct snd_soc_dai *pDAI, unsigned int nFormat) +{ + struct snd_soc_codec *codec = pDAI->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + printk("%s\n", __func__); + return 0; +} + +static int tas2557_prepare(struct snd_pcm_substream *pSubstream, + struct snd_soc_dai *pDAI) +{ + struct snd_soc_codec *codec = pDAI->codec; + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + printk("%s\n", __func__); + return 0; +} + +static int tas2557_set_bias_level(struct snd_soc_codec *pCodec, + enum snd_soc_bias_level eLevel) +{ + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + printk("%s\n", __func__); + + dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, eLevel); + return 0; +} + +static int tas2557_codec_probe(struct snd_soc_codec *pCodec) +{ + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec); + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + printk("%s\n", __func__); + return 0; +} + +static int tas2557_codec_remove(struct snd_soc_codec *pCodec) +{ + return 0; +} + +static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&pTAS2557->codec_lock); + + pValue->value.integer.value[0] = pTAS2557->mbPowerUp; + dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_get = %d\n", + pTAS2557->mbPowerUp); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_power_ctrl_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + int nPowerOn = pValue->value.integer.value[0]; + + mutex_lock(&pTAS2557->codec_lock); + + dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_put = %d\n", nPowerOn); + tas2557_enable(pTAS2557, (nPowerOn != 0)); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_fs_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + int nFS = 48000; + + mutex_lock(&pTAS2557->codec_lock); + + if (pTAS2557->mpFirmware->mnConfigurations) + nFS = pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration].mnSamplingRate; + pValue->value.integer.value[0] = nFS; + dev_dbg(pTAS2557->dev, "tas2557_fs_get = %d\n", nFS); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_fs_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + int nFS = pValue->value.integer.value[0]; + + mutex_lock(&pTAS2557->codec_lock); + + dev_info(pTAS2557->dev, "tas2557_fs_put = %d\n", nFS); + ret = tas2557_set_sampling_rate(pTAS2557, nFS); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static int tas2557_Cali_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + bool ret = 0; + int prm_r0 = 0; + + mutex_lock(&pTAS2557->codec_lock); + + ret = tas2557_get_Cali_prm_r0(pTAS2557, &prm_r0); + if (ret) + pValue->value.integer.value[0] = prm_r0; + + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_program_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&pTAS2557->codec_lock); + + pValue->value.integer.value[0] = pTAS2557->mnCurrentProgram; + dev_dbg(pTAS2557->dev, "tas2557_program_get = %d\n", + pTAS2557->mnCurrentProgram); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_program_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + unsigned int nProgram = pValue->value.integer.value[0]; + int ret = 0, nConfiguration = -1; + + mutex_lock(&pTAS2557->codec_lock); + + if (nProgram == pTAS2557->mnCurrentProgram) + nConfiguration = pTAS2557->mnCurrentConfiguration; + ret = tas2557_set_program(pTAS2557, nProgram, nConfiguration); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&pTAS2557->codec_lock); + + pValue->value.integer.value[0] = pTAS2557->mnCurrentConfiguration; + dev_dbg(pTAS2557->dev, "tas2557_configuration_get = %d\n", + pTAS2557->mnCurrentConfiguration); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_configuration_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + unsigned int nConfiguration = pValue->value.integer.value[0]; + int ret = 0; + + mutex_lock(&pTAS2557->codec_lock); + + dev_info(pTAS2557->dev, "%s = %d\n", __func__, nConfiguration); + ret = tas2557_set_config(pTAS2557, nConfiguration); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + + mutex_lock(&pTAS2557->codec_lock); + + pValue->value.integer.value[0] = pTAS2557->mnCurrentCalibration; + dev_info(pTAS2557->dev, + "tas2557_calibration_get = %d\n", + pTAS2557->mnCurrentCalibration); + + mutex_unlock(&pTAS2557->codec_lock); + return 0; +} + +static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol, + struct snd_ctl_elem_value *pValue) +{ +#ifdef KCONTROL_CODEC + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol); +#else + struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol); +#endif + struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec); + unsigned int nCalibration = pValue->value.integer.value[0]; + int ret = 0; + + mutex_lock(&pTAS2557->codec_lock); + + ret = tas2557_set_calibration(pTAS2557, nCalibration); + + mutex_unlock(&pTAS2557->codec_lock); + return ret; +} + +static const struct snd_kcontrol_new tas2557_snd_controls[] = { + SOC_SINGLE_EXT("PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0, + tas2557_power_ctrl_get, tas2557_power_ctrl_put), + SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2557_program_get, + tas2557_program_put), + SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0, + tas2557_configuration_get, tas2557_configuration_put), + SOC_SINGLE_EXT("FS", SND_SOC_NOPM, 8000, 48000, 0, + tas2557_fs_get, tas2557_fs_put), + SOC_SINGLE_EXT("Get Cali_Re", SND_SOC_NOPM, 0, 0x7f000000, 0, + tas2557_Cali_get, NULL), + SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0, + tas2557_calibration_get, tas2557_calibration_put), +}; + +static struct snd_soc_codec_driver soc_codec_driver_tas2557 = { + .probe = tas2557_codec_probe, + .remove = tas2557_codec_remove, + .read = tas2557_codec_read, + .write = tas2557_codec_write, + .suspend = tas2557_codec_suspend, + .resume = tas2557_codec_resume, + .set_bias_level = tas2557_set_bias_level, + .idle_bias_off = true, + .controls = tas2557_snd_controls, + .num_controls = ARRAY_SIZE(tas2557_snd_controls), + .dapm_widgets = tas2557_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas2557_dapm_widgets), + .dapm_routes = tas2557_audio_map, + .num_dapm_routes = ARRAY_SIZE(tas2557_audio_map), +}; + +static struct snd_soc_dai_ops tas2557_dai_ops = { + .startup = tas2557_startup, + .shutdown = tas2557_shutdown, + .digital_mute = tas2557_mute, + .hw_params = tas2557_hw_params, + .prepare = tas2557_prepare, + .set_sysclk = tas2557_set_dai_sysclk, + .set_fmt = tas2557_set_dai_fmt, +}; + +#define TAS2557_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_driver tas2557_dai_driver[] = { + { + .name = "tas2557 ASI1", + .id = 0, + .playback = { + .stream_name = "ASI1 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS2557_FORMATS, + }, + .ops = &tas2557_dai_ops, + .symmetric_rates = 1, + }, + { + .name = "tas2557 ASI2", + .id = 1, + .playback = { + .stream_name = "ASI2 Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS2557_FORMATS, + }, + .ops = &tas2557_dai_ops, + .symmetric_rates = 1, + }, + { + .name = "tas2557 ASIM", + .id = 2, + .playback = { + .stream_name = "ASIM Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = TAS2557_FORMATS, + }, + .ops = &tas2557_dai_ops, + .symmetric_rates = 1, + }, +}; + +int tas2557_register_codec(struct tas2557_priv *pTAS2557) +{ + int nResult = 0; + + dev_info(pTAS2557->dev, "%s, enter\n", __func__); + nResult = snd_soc_register_codec(pTAS2557->dev, + &soc_codec_driver_tas2557, + tas2557_dai_driver, ARRAY_SIZE(tas2557_dai_driver)); + return nResult; +} + +int tas2557_deregister_codec(struct tas2557_priv *pTAS2557) +{ + snd_soc_unregister_codec(pTAS2557->dev); + return 0; +} + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS2557 ALSA SOC Smart Amplifier driver"); +MODULE_LICENSE("GPL v2"); +#endif diff --git a/sound/soc/codecs/tas2557-codec.h b/sound/soc/codecs/tas2557-codec.h new file mode 100644 index 0000000000000..20babdde5025d --- /dev/null +++ b/sound/soc/codecs/tas2557-codec.h @@ -0,0 +1,31 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-codec.h +** +** Description: +** header file for tas2557-codec.c +** +** ============================================================================= +*/ + +#ifndef _TAS2557_CODEC_H +#define _TAS2557_CODEC_H + +#include "tas2557.h" + +int tas2557_register_codec(struct tas2557_priv *pTAS2557); +int tas2557_deregister_codec(struct tas2557_priv *pTAS2557); + +#endif /* _TAS2557_CODEC_H */ diff --git a/sound/soc/codecs/tas2557-core.c b/sound/soc/codecs/tas2557-core.c new file mode 100644 index 0000000000000..d43bd95a41c6b --- /dev/null +++ b/sound/soc/codecs/tas2557-core.c @@ -0,0 +1,2023 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-core.c +** +** Description: +** TAS2557 common functions for Android Linux +** +** ============================================================================= +*/ + +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas2557.h" +#include "tas2557-core.h" + +#define PPC_DRIVER_CRCCHK 0x00000200 +#define PPC_DRIVER_CONFDEV 0x00000300 +#define PPC_DRIVER_CFGDEV_NONCRC 0x00000101 + +#define TAS2557_CAL_NAME "/persist/spkr_calibration.bin" + + +static int tas2557_load_calibration(struct tas2557_priv *pTAS2557, + char *pFileName); +static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, + unsigned int nType); +static void tas2557_clear_firmware(struct TFirmware *pFirmware); +static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock); +static int tas2557_load_configuration(struct tas2557_priv *pTAS2557, + unsigned int nConfiguration, bool bLoadSame); + +#define TAS2557_UDELAY 0xFFFFFFFE +#define TAS2557_MDELAY 0xFFFFFFFD + +#define TAS2557_BLOCK_PLL 0x00 +#define TAS2557_BLOCK_PGM_ALL 0x0d +#define TAS2557_BLOCK_PGM_DEV_A 0x01 +#define TAS2557_BLOCK_PGM_DEV_B 0x08 +#define TAS2557_BLOCK_CFG_COEFF_DEV_A 0x03 +#define TAS2557_BLOCK_CFG_COEFF_DEV_B 0x0a +#define TAS2557_BLOCK_CFG_PRE_DEV_A 0x04 +#define TAS2557_BLOCK_CFG_PRE_DEV_B 0x0b +#define TAS2557_BLOCK_CFG_POST 0x05 +#define TAS2557_BLOCK_CFG_POST_POWER 0x06 + +static unsigned int p_tas2557_default_data[] = { + TAS2557_SAR_ADC2_REG, 0x05, /* enable SAR ADC */ + TAS2557_CLK_ERR_CTRL2, 0x21, /*clk1:clock hysteresis, 0.34ms; clock halt, 22ms*/ + TAS2557_CLK_ERR_CTRL3, 0x21, /*clk2: rampDown 15dB/us, clock hysteresis, 10.66us; clock halt, 22ms */ + TAS2557_SAFE_GUARD_REG, TAS2557_SAFE_GUARD_PATTERN, /* safe guard */ + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static unsigned int p_tas2557_irq_config[] = { + TAS2557_CLK_HALT_REG, 0x71, /* enable clk halt detect2 interrupt */ + TAS2557_INT_GEN1_REG, 0x11, /* enable spk OC and OV */ + TAS2557_INT_GEN2_REG, 0x11, /* enable clk err1 and die OT */ + TAS2557_INT_GEN3_REG, 0x11, /* enable clk err2 and brownout */ + TAS2557_INT_GEN4_REG, 0x01, /* disable SAR, enable clk halt */ + TAS2557_GPIO4_PIN_REG, 0x07, /* set GPIO4 as int1, default */ + TAS2557_INT_MODE_REG, 0x80, /* active high until INT_STICKY_1 and INT_STICKY_2 are read to be cleared. */ + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static unsigned int p_tas2557_startup_data[] = { + TAS2557_GPI_PIN_REG, 0x15, /* enable DIN, MCLK, CCI */ + TAS2557_GPIO1_PIN_REG, 0x01, /* enable BCLK */ + TAS2557_GPIO2_PIN_REG, 0x01, /* enable WCLK */ + TAS2557_POWER_CTRL2_REG, 0xA0, /* Class-D, Boost power up */ + TAS2557_POWER_CTRL2_REG, 0xA3, /* Class-D, Boost, IV sense power up */ + TAS2557_POWER_CTRL1_REG, 0xF8, /* PLL, DSP, clock dividers power up */ + TAS2557_UDELAY, 2000, /* delay */ + TAS2557_CLK_ERR_CTRL, 0x2b, /* enable clock error detection */ + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static unsigned int p_tas2557_unmute_data[] = { + TAS2557_MUTE_REG, 0x00, /* unmute */ + TAS2557_SOFT_MUTE_REG, 0x00, /* soft unmute */ + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static unsigned int p_tas2557_shutdown_data[] = { + TAS2557_CLK_ERR_CTRL, 0x00, /* disable clock error detection */ + TAS2557_SOFT_MUTE_REG, 0x01, /* soft mute */ + TAS2557_UDELAY, 10000, /* delay 10ms */ + TAS2557_MUTE_REG, 0x03, /* mute */ + TAS2557_POWER_CTRL1_REG, 0x60, /* DSP power down */ + TAS2557_UDELAY, 2000, /* delay 2ms */ + TAS2557_POWER_CTRL2_REG, 0x00, /* Class-D, Boost power down */ + TAS2557_POWER_CTRL1_REG, 0x00, /* all power down */ + TAS2557_GPIO1_PIN_REG, 0x00, /* disable BCLK */ + TAS2557_GPIO2_PIN_REG, 0x00, /* disable WCLK */ + TAS2557_GPI_PIN_REG, 0x00, /* disable DIN, MCLK, CCI */ + 0xFFFFFFFF, 0xFFFFFFFF +}; + +static int tas2557_dev_load_data(struct tas2557_priv *pTAS2557, + unsigned int *pData) +{ + int ret = 0; + unsigned int n = 0; + unsigned int nRegister; + unsigned int nData; + + do { + nRegister = pData[n * 2]; + nData = pData[n * 2 + 1]; + if (nRegister == TAS2557_UDELAY) + udelay(nData); + else if (nRegister != 0xFFFFFFFF) { + ret = pTAS2557->write(pTAS2557, nRegister, nData); + if (ret < 0) + break; + } + n++; + } while (nRegister != 0xFFFFFFFF); + return ret; +} + +int tas2557_configIRQ(struct tas2557_priv *pTAS2557) +{ + return tas2557_dev_load_data(pTAS2557, p_tas2557_irq_config); +} + +int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate) +{ + int ret = 0, n = -1; + + dev_dbg(pTAS2557->dev, "tas2557_set_bit_rate: nBitRate = %d\n", nBitRate); + + switch (nBitRate) { + case 16: + n = 0; + break; + case 20: + n = 1; + break; + case 24: + n = 2; + break; + case 32: + n = 3; + break; + } + + if (n >= 0) + ret = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x18, n<<3); + return ret; +} + +int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate) +{ + int ret = 0; + unsigned int nValue = 0; + unsigned char bitRate; + + ret = pTAS2557->read(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, &nValue); + if (ret >= 0) { + bitRate = (nValue&0x18)>>3; + if (bitRate == 0) + bitRate = 16; + else if (bitRate == 1) + bitRate = 20; + else if (bitRate == 2) + bitRate = 24; + else if (bitRate == 3) + bitRate = 32; + *pBitRate = bitRate; + } + + return ret; +} + +int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain) +{ + int ret = 0; + unsigned int nValue = 0; + + ret = pTAS2557->read(pTAS2557, TAS2557_SPK_CTRL_REG, &nValue); + if (ret >= 0) + *pnGain = ((nValue&TAS2557_DAC_GAIN_MASK)>>TAS2557_DAC_GAIN_SHIFT); + + return ret; +} + +int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain) +{ + int ret = 0; + + ret = pTAS2557->update_bits(pTAS2557, TAS2557_SPK_CTRL_REG, TAS2557_DAC_GAIN_MASK, + (nGain<mpFirmware->mnConfigurations) { + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + goto end; + } + + if (!pTAS2557->mbPowerUp) { + dev_err(pTAS2557->dev, "%s, device not powered on\n", __func__); + goto end; + } + + nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_DIE_TEMP_REG, nBuf, 4); + if (nResult >= 0) { + temp = ((int)nBuf[0] << 24) | ((int)nBuf[1] << 16) | ((int)nBuf[2] << 8) | nBuf[3]; + *pTemperature = temp; + } + +end: + + return nResult; +} + +int tas2557_load_platdata(struct tas2557_priv *pTAS2557) +{ + int nResult = 0; + + if (gpio_is_valid(pTAS2557->mnGpioINT)) { + nResult = tas2557_configIRQ(pTAS2557); + if (nResult < 0) + goto end; + } + + nResult = tas2557_set_bit_rate(pTAS2557, pTAS2557->mnI2SBits); + +end: + + return nResult; +} + +int tas2557_load_default(struct tas2557_priv *pTAS2557) +{ + int nResult = 0; + + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_default_data); + if (nResult < 0) + goto end; + + nResult = tas2557_load_platdata(pTAS2557); + if (nResult < 0) + goto end; + + /* enable DOUT tri-state for extra BCLKs */ + nResult = pTAS2557->update_bits(pTAS2557, TAS2557_ASI1_DAC_FORMAT_REG, 0x01, 0x01); +end: + + return nResult; +} + +static void failsafe(struct tas2557_priv *pTAS2557) +{ + dev_err(pTAS2557->dev, "%s\n", __func__); + pTAS2557->mnErrCode |= ERROR_FAILSAFE; + if (hrtimer_active(&pTAS2557->mtimer)) + hrtimer_cancel(&pTAS2557->mtimer); +#ifdef I2C_RESTART + if (pTAS2557->mnRestart < 3) + { + pTAS2557->mnRestart ++; + msleep(100); + dev_err(pTAS2557->dev, "I2C COMM error, restart SmartAmp.\n"); + schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100)); + return; + } +#endif + pTAS2557->enableIRQ(pTAS2557, false); + tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + pTAS2557->mbPowerUp = false; + pTAS2557->hw_reset(pTAS2557); + pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01); + udelay(1000); + pTAS2557->write(pTAS2557, TAS2557_SPK_CTRL_REG, 0x04); + if (pTAS2557->mpFirmware != NULL) + tas2557_clear_firmware(pTAS2557->mpFirmware); +} + +int tas2557_checkPLL(struct tas2557_priv *pTAS2557) +{ + int nResult = 0; +/* +* TO DO +*/ + + return nResult; +} + +/* +* tas2557_load_coefficient +*/ +static int tas2557_load_coefficient(struct tas2557_priv *pTAS2557, + int nPrevConfig, int nNewConfig, bool bPowerOn) +{ + int nResult = 0; + struct TPLL *pPLL; + struct TProgram *pProgram; + struct TConfiguration *pPrevConfiguration; + struct TConfiguration *pNewConfiguration; + bool bRestorePower = false; + + if (!pTAS2557->mpFirmware->mnConfigurations) { + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + goto end; + } + + if (nNewConfig >= pTAS2557->mpFirmware->mnConfigurations) { + dev_err(pTAS2557->dev, "%s, invalid configuration New=%d, total=%d\n", + __func__, nNewConfig, pTAS2557->mpFirmware->mnConfigurations); + goto end; + } + + if (nPrevConfig < 0) + pPrevConfiguration = NULL; + else if (nPrevConfig == nNewConfig) { + dev_dbg(pTAS2557->dev, "%s, config [%d] already loaded\n", + __func__, nNewConfig); + goto end; + } else + pPrevConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nPrevConfig]); + + pNewConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nNewConfig]); + pTAS2557->mnCurrentConfiguration = nNewConfig; + if (pPrevConfiguration) { + if (pPrevConfiguration->mnPLL == pNewConfiguration->mnPLL) { + dev_dbg(pTAS2557->dev, "%s, PLL same\n", __func__); + goto prog_coefficient; + } + } + + pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]); + if (bPowerOn) { + dev_dbg(pTAS2557->dev, "%s, power down to load new PLL\n", __func__); + if (hrtimer_active(&pTAS2557->mtimer)) + hrtimer_cancel(&pTAS2557->mtimer); + + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) + pTAS2557->enableIRQ(pTAS2557, false); + + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + if (nResult < 0) + goto end; + bRestorePower = true; + } + + /* load PLL */ + pPLL = &(pTAS2557->mpFirmware->mpPLLs[pNewConfiguration->mnPLL]); + dev_dbg(pTAS2557->dev, "load PLL: %s block for Configuration %s\n", + pPLL->mpName, pNewConfiguration->mpName); + nResult = tas2557_load_block(pTAS2557, &(pPLL->mBlock)); + if (nResult < 0) + goto end; + pTAS2557->mnCurrentSampleRate = pNewConfiguration->mnSamplingRate; + + dev_dbg(pTAS2557->dev, "load configuration %s conefficient pre block\n", + pNewConfiguration->mpName); + nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), TAS2557_BLOCK_CFG_PRE_DEV_A); + if (nResult < 0) + goto end; + +prog_coefficient: + dev_dbg(pTAS2557->dev, "load new configuration: %s, coeff block data\n", + pNewConfiguration->mpName); + nResult = tas2557_load_data(pTAS2557, &(pNewConfiguration->mData), + TAS2557_BLOCK_CFG_COEFF_DEV_A); + if (nResult < 0) + goto end; + + if (pTAS2557->mpCalFirmware->mnCalibrations) { + nResult = tas2557_set_calibration(pTAS2557, pTAS2557->mnCurrentCalibration); + if (nResult < 0) + goto end; + } + + if (bRestorePower) { + pTAS2557->clearIRQ(pTAS2557); + dev_dbg(pTAS2557->dev, "device powered up, load startup\n"); + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data); + if (nResult < 0) + goto end; + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + nResult = tas2557_checkPLL(pTAS2557); + if (nResult < 0) { + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + pTAS2557->mbPowerUp = false; + goto end; + } + } + dev_dbg(pTAS2557->dev, + "device powered up, load unmute\n"); + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data); + if (nResult < 0) + goto end; + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + pTAS2557->enableIRQ(pTAS2557, true); + if (!hrtimer_active(&pTAS2557->mtimer)) { + pTAS2557->mnDieTvReadCounter = 0; + hrtimer_start(&pTAS2557->mtimer, + ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL); + } + } + } +end: + + return nResult; +} + +int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable) +{ + int nResult = 0; + unsigned int nValue; + struct TProgram *pProgram; + + dev_dbg(pTAS2557->dev, "Enable: %d\n", bEnable); + + if ((pTAS2557->mpFirmware->mnPrograms == 0) + || (pTAS2557->mpFirmware->mnConfigurations == 0)) { + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + goto end; + } + /* check safe guard*/ + nResult = pTAS2557->read(pTAS2557, TAS2557_SAFE_GUARD_REG, &nValue); + if (nResult < 0) + goto end; + if ((nValue&0xff) != TAS2557_SAFE_GUARD_PATTERN) { + dev_err(pTAS2557->dev, "ERROR safe guard failure!\n"); + nResult = -EPIPE; + goto end; + } + + pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]); + if (bEnable) { + if (!pTAS2557->mbPowerUp) { + if (pTAS2557->mbLoadConfigurationPrePowerUp) { + dev_dbg(pTAS2557->dev, "load coefficient before power\n"); + pTAS2557->mbLoadConfigurationPrePowerUp = false; + nResult = tas2557_load_coefficient(pTAS2557, + pTAS2557->mnCurrentConfiguration, pTAS2557->mnNewConfiguration, false); + if (nResult < 0) + goto end; + } + + pTAS2557->clearIRQ(pTAS2557); + /* power on device */ + dev_dbg(pTAS2557->dev, "Enable: load startup sequence\n"); + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data); + if (nResult < 0) + goto end; + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + nResult = tas2557_checkPLL(pTAS2557); + if (nResult < 0) { + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + goto end; + } + } + dev_dbg(pTAS2557->dev, "Enable: load unmute sequence\n"); + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data); + if (nResult < 0) + goto end; + + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + /* turn on IRQ */ + pTAS2557->enableIRQ(pTAS2557, true); + if (!hrtimer_active(&pTAS2557->mtimer)) { + pTAS2557->mnDieTvReadCounter = 0; + hrtimer_start(&pTAS2557->mtimer, + ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL); + } + } + pTAS2557->mbPowerUp = true; + } + } else { + if (pTAS2557->mbPowerUp) { + if (hrtimer_active(&pTAS2557->mtimer)) + hrtimer_cancel(&pTAS2557->mtimer); + + dev_dbg(pTAS2557->dev, "Enable: load shutdown sequence\n"); + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + /* turn off IRQ */ + pTAS2557->enableIRQ(pTAS2557, false); + } + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + if (nResult < 0) + goto end; + + pTAS2557->mbPowerUp = false; + } + } + + nResult = 0; + +end: + if (nResult < 0) { + if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK)) + failsafe(pTAS2557); + } + + return nResult; +} + +int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate) +{ + int nResult = 0; + struct TConfiguration *pConfiguration; + unsigned int nConfiguration; + + dev_dbg(pTAS2557->dev, "tas2557_setup_clocks: nSamplingRate = %d [Hz]\n", + nSamplingRate); + + if ((!pTAS2557->mpFirmware->mpPrograms) || + (!pTAS2557->mpFirmware->mpConfigurations)) { + dev_err(pTAS2557->dev, "Firmware not loaded\n"); + nResult = -EINVAL; + goto end; + } + + pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]); + if (pConfiguration->mnSamplingRate == nSamplingRate) { + dev_info(pTAS2557->dev, "Sampling rate for current configuration matches: %d\n", + nSamplingRate); + nResult = 0; + goto end; + } + + for (nConfiguration = 0; + nConfiguration < pTAS2557->mpFirmware->mnConfigurations; + nConfiguration++) { + pConfiguration = + &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]); + if ((pConfiguration->mnSamplingRate == nSamplingRate) + && (pConfiguration->mnProgram == pTAS2557->mnCurrentProgram)) { + dev_info(pTAS2557->dev, + "Found configuration: %s, with compatible sampling rate %d\n", + pConfiguration->mpName, nSamplingRate); + nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false); + goto end; + } + } + + dev_err(pTAS2557->dev, "Cannot find a configuration that supports sampling rate: %d\n", + nSamplingRate); + +end: + + return nResult; +} + +static void fw_print_header(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware) +{ + dev_info(pTAS2557->dev, "FW Size = %d", pFirmware->mnFWSize); + dev_info(pTAS2557->dev, "Checksum = 0x%04X", pFirmware->mnChecksum); + dev_info(pTAS2557->dev, "PPC Version = 0x%04X", pFirmware->mnPPCVersion); + dev_info(pTAS2557->dev, "FW Version = 0x%04X", pFirmware->mnFWVersion); + dev_info(pTAS2557->dev, "Driver Version= 0x%04X", pFirmware->mnDriverVersion); + dev_info(pTAS2557->dev, "Timestamp = %d", pFirmware->mnTimeStamp); + dev_info(pTAS2557->dev, "DDC Name = %s", pFirmware->mpDDCName); + dev_info(pTAS2557->dev, "Description = %s", pFirmware->mpDescription); +} + +inline unsigned int fw_convert_number(unsigned char *pData) +{ + return pData[3] + (pData[2] << 8) + (pData[1] << 16) + (pData[0] << 24); +} + +static int fw_parse_header(struct tas2557_priv *pTAS2557, + struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize) +{ + unsigned char *pDataStart = pData; + unsigned int n; + unsigned char pMagicNumber[] = { 0x35, 0x35, 0x35, 0x32 }; + + if (nSize < 104) { + dev_err(pTAS2557->dev, "Firmware: Header too short"); + return -EINVAL; + } + + if (memcmp(pData, pMagicNumber, 4)) { + dev_err(pTAS2557->dev, "Firmware: Magic number doesn't match"); + return -EINVAL; + } + pData += 4; + + pFirmware->mnFWSize = fw_convert_number(pData); + pData += 4; + + pFirmware->mnChecksum = fw_convert_number(pData); + pData += 4; + + pFirmware->mnPPCVersion = fw_convert_number(pData); + pData += 4; + + pFirmware->mnFWVersion = fw_convert_number(pData); + pData += 4; + + pFirmware->mnDriverVersion = fw_convert_number(pData); + pData += 4; + + pFirmware->mnTimeStamp = fw_convert_number(pData); + pData += 4; + + memcpy(pFirmware->mpDDCName, pData, 64); + pData += 64; + + n = strlen(pData); + pFirmware->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL); + pData += n + 1; + if ((pData - pDataStart) >= nSize) { + dev_err(pTAS2557->dev, "Firmware: Header too short after DDC description"); + return -EINVAL; + } + + pFirmware->mnDeviceFamily = fw_convert_number(pData); + pData += 4; + if (pFirmware->mnDeviceFamily != 0) { + dev_err(pTAS2557->dev, + "deviceFamily %d, not TAS device", pFirmware->mnDeviceFamily); + return -EINVAL; + } + + pFirmware->mnDevice = fw_convert_number(pData); + pData += 4; + + if (pFirmware->mnDevice != 2) { + dev_err(pTAS2557->dev, + "device %d, not TAS2557 Dual Mono", pFirmware->mnDevice); + return -EINVAL; + } + + fw_print_header(pTAS2557, pFirmware); + return pData - pDataStart; +} + +static int fw_parse_block_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware, + struct TBlock *pBlock, unsigned char *pData) +{ + unsigned char *pDataStart = pData; + unsigned int n; + + pBlock->mnType = fw_convert_number(pData); + pData += 4; + + if (pFirmware->mnDriverVersion >= PPC_DRIVER_CRCCHK) { + pBlock->mbPChkSumPresent = pData[0]; + pData++; + + pBlock->mnPChkSum = pData[0]; + pData++; + + pBlock->mbYChkSumPresent = pData[0]; + pData++; + + pBlock->mnYChkSum = pData[0]; + pData++; + } else { + pBlock->mbPChkSumPresent = 0; + pBlock->mbYChkSumPresent = 0; + } + + pBlock->mnCommands = fw_convert_number(pData); + pData += 4; + + n = pBlock->mnCommands * 4; + pBlock->mpData = kmemdup(pData, n, GFP_KERNEL); + pData += n; + return pData - pDataStart; +} + +static int fw_parse_data(struct tas2557_priv *pTAS2557, struct TFirmware *pFirmware, + struct TData *pImageData, unsigned char *pData) +{ + unsigned char *pDataStart = pData; + unsigned int nBlock; + unsigned int n; + + memcpy(pImageData->mpName, pData, 64); + pData += 64; + + n = strlen(pData); + pImageData->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL); + pData += n + 1; + + pImageData->mnBlocks = (pData[0] << 8) + pData[1]; + pData += 2; + + pImageData->mpBlocks = + kmalloc(sizeof(struct TBlock) * pImageData->mnBlocks, GFP_KERNEL); + + for (nBlock = 0; nBlock < pImageData->mnBlocks; nBlock++) { + n = fw_parse_block_data(pTAS2557, pFirmware, + &(pImageData->mpBlocks[nBlock]), pData); + pData += n; + } + return pData - pDataStart; +} + +static int fw_parse_pll_data(struct tas2557_priv *pTAS2557, + struct TFirmware *pFirmware, unsigned char *pData) +{ + unsigned char *pDataStart = pData; + unsigned int n; + unsigned int nPLL; + struct TPLL *pPLL; + + pFirmware->mnPLLs = (pData[0] << 8) + pData[1]; + pData += 2; + + if (pFirmware->mnPLLs == 0) + goto end; + + pFirmware->mpPLLs = kmalloc_array(pFirmware->mnPLLs, sizeof(struct TPLL), GFP_KERNEL); + for (nPLL = 0; nPLL < pFirmware->mnPLLs; nPLL++) { + pPLL = &(pFirmware->mpPLLs[nPLL]); + + memcpy(pPLL->mpName, pData, 64); + pData += 64; + + n = strlen(pData); + pPLL->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL); + pData += n + 1; + + n = fw_parse_block_data(pTAS2557, pFirmware, &(pPLL->mBlock), pData); + pData += n; + } + +end: + return pData - pDataStart; +} + +static int fw_parse_program_data(struct tas2557_priv *pTAS2557, + struct TFirmware *pFirmware, unsigned char *pData) +{ + unsigned char *pDataStart = pData; + unsigned int n; + unsigned int nProgram; + struct TProgram *pProgram; + + pFirmware->mnPrograms = (pData[0] << 8) + pData[1]; + pData += 2; + + if (pFirmware->mnPrograms == 0) + goto end; + + pFirmware->mpPrograms = + kmalloc(sizeof(struct TProgram) * pFirmware->mnPrograms, GFP_KERNEL); + for (nProgram = 0; nProgram < pFirmware->mnPrograms; nProgram++) { + pProgram = &(pFirmware->mpPrograms[nProgram]); + memcpy(pProgram->mpName, pData, 64); + pData += 64; + + n = strlen(pData); + pProgram->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL); + pData += n + 1; + + pProgram->mnAppMode = pData[0]; + pData++; + + pProgram->mnBoost = (pData[0] << 8) + pData[1]; + pData += 2; + + n = fw_parse_data(pTAS2557, pFirmware, &(pProgram->mData), pData); + pData += n; + } + +end: + + return pData - pDataStart; +} + +static int fw_parse_configuration_data(struct tas2557_priv *pTAS2557, + struct TFirmware *pFirmware, unsigned char *pData) +{ + unsigned char *pDataStart = pData; + unsigned int n; + unsigned int nConfiguration; + struct TConfiguration *pConfiguration; + + pFirmware->mnConfigurations = (pData[0] << 8) + pData[1]; + pData += 2; + + if (pFirmware->mnConfigurations == 0) + goto end; + + pFirmware->mpConfigurations = + kmalloc(sizeof(struct TConfiguration) * pFirmware->mnConfigurations, + GFP_KERNEL); + for (nConfiguration = 0; nConfiguration < pFirmware->mnConfigurations; + nConfiguration++) { + pConfiguration = &(pFirmware->mpConfigurations[nConfiguration]); + memcpy(pConfiguration->mpName, pData, 64); + pData += 64; + + n = strlen(pData); + pConfiguration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL); + pData += n + 1; + + if ((pFirmware->mnDriverVersion >= PPC_DRIVER_CONFDEV) + || ((pFirmware->mnDriverVersion >= PPC_DRIVER_CFGDEV_NONCRC) + && (pFirmware->mnDriverVersion < PPC_DRIVER_CRCCHK))) { + pConfiguration->mnDevices = (pData[0] << 8) + pData[1]; + pData += 2; + } else + pConfiguration->mnDevices = 1; + + pConfiguration->mnProgram = pData[0]; + pData++; + + pConfiguration->mnPLL = pData[0]; + pData++; + + pConfiguration->mnSamplingRate = fw_convert_number(pData); + pData += 4; + + n = fw_parse_data(pTAS2557, pFirmware, &(pConfiguration->mData), pData); + pData += n; + } + +end: + + return pData - pDataStart; +} + +int fw_parse_calibration_data(struct tas2557_priv *pTAS2557, + struct TFirmware *pFirmware, unsigned char *pData) +{ + unsigned char *pDataStart = pData; + unsigned int n; + unsigned int nCalibration; + struct TCalibration *pCalibration; + + pFirmware->mnCalibrations = (pData[0] << 8) + pData[1]; + pData += 2; + + if (pFirmware->mnCalibrations == 0) + goto end; + + pFirmware->mpCalibrations = + kmalloc(sizeof(struct TCalibration) * pFirmware->mnCalibrations, GFP_KERNEL); + for (nCalibration = 0; + nCalibration < pFirmware->mnCalibrations; + nCalibration++) { + pCalibration = &(pFirmware->mpCalibrations[nCalibration]); + memcpy(pCalibration->mpName, pData, 64); + pData += 64; + + n = strlen(pData); + pCalibration->mpDescription = kmemdup(pData, n + 1, GFP_KERNEL); + pData += n + 1; + + pCalibration->mnProgram = pData[0]; + pData++; + + pCalibration->mnConfiguration = pData[0]; + pData++; + + n = fw_parse_data(pTAS2557, pFirmware, &(pCalibration->mData), pData); + pData += n; + } + +end: + + return pData - pDataStart; +} + +static int fw_parse(struct tas2557_priv *pTAS2557, + struct TFirmware *pFirmware, unsigned char *pData, unsigned int nSize) +{ + int nPosition = 0; + + nPosition = fw_parse_header(pTAS2557, pFirmware, pData, nSize); + if (nPosition < 0) { + dev_err(pTAS2557->dev, "Firmware: Wrong Header"); + return -EINVAL; + } + + if (nPosition >= nSize) { + dev_err(pTAS2557->dev, "Firmware: Too short"); + return -EINVAL; + } + + pData += nPosition; + nSize -= nPosition; + nPosition = 0; + + nPosition = fw_parse_pll_data(pTAS2557, pFirmware, pData); + + pData += nPosition; + nSize -= nPosition; + nPosition = 0; + + nPosition = fw_parse_program_data(pTAS2557, pFirmware, pData); + + pData += nPosition; + nSize -= nPosition; + nPosition = 0; + + nPosition = fw_parse_configuration_data(pTAS2557, pFirmware, pData); + + pData += nPosition; + nSize -= nPosition; + nPosition = 0; + + if (nSize > 64) + nPosition = fw_parse_calibration_data(pTAS2557, pFirmware, pData); + return 0; +} + + +static const unsigned char crc8_lookup_table[CRC8_TABLE_SIZE] = { +0x00, 0x4D, 0x9A, 0xD7, 0x79, 0x34, 0xE3, 0xAE, 0xF2, 0xBF, 0x68, 0x25, 0x8B, 0xC6, 0x11, 0x5C, +0xA9, 0xE4, 0x33, 0x7E, 0xD0, 0x9D, 0x4A, 0x07, 0x5B, 0x16, 0xC1, 0x8C, 0x22, 0x6F, 0xB8, 0xF5, +0x1F, 0x52, 0x85, 0xC8, 0x66, 0x2B, 0xFC, 0xB1, 0xED, 0xA0, 0x77, 0x3A, 0x94, 0xD9, 0x0E, 0x43, +0xB6, 0xFB, 0x2C, 0x61, 0xCF, 0x82, 0x55, 0x18, 0x44, 0x09, 0xDE, 0x93, 0x3D, 0x70, 0xA7, 0xEA, +0x3E, 0x73, 0xA4, 0xE9, 0x47, 0x0A, 0xDD, 0x90, 0xCC, 0x81, 0x56, 0x1B, 0xB5, 0xF8, 0x2F, 0x62, +0x97, 0xDA, 0x0D, 0x40, 0xEE, 0xA3, 0x74, 0x39, 0x65, 0x28, 0xFF, 0xB2, 0x1C, 0x51, 0x86, 0xCB, +0x21, 0x6C, 0xBB, 0xF6, 0x58, 0x15, 0xC2, 0x8F, 0xD3, 0x9E, 0x49, 0x04, 0xAA, 0xE7, 0x30, 0x7D, +0x88, 0xC5, 0x12, 0x5F, 0xF1, 0xBC, 0x6B, 0x26, 0x7A, 0x37, 0xE0, 0xAD, 0x03, 0x4E, 0x99, 0xD4, +0x7C, 0x31, 0xE6, 0xAB, 0x05, 0x48, 0x9F, 0xD2, 0x8E, 0xC3, 0x14, 0x59, 0xF7, 0xBA, 0x6D, 0x20, +0xD5, 0x98, 0x4F, 0x02, 0xAC, 0xE1, 0x36, 0x7B, 0x27, 0x6A, 0xBD, 0xF0, 0x5E, 0x13, 0xC4, 0x89, +0x63, 0x2E, 0xF9, 0xB4, 0x1A, 0x57, 0x80, 0xCD, 0x91, 0xDC, 0x0B, 0x46, 0xE8, 0xA5, 0x72, 0x3F, +0xCA, 0x87, 0x50, 0x1D, 0xB3, 0xFE, 0x29, 0x64, 0x38, 0x75, 0xA2, 0xEF, 0x41, 0x0C, 0xDB, 0x96, +0x42, 0x0F, 0xD8, 0x95, 0x3B, 0x76, 0xA1, 0xEC, 0xB0, 0xFD, 0x2A, 0x67, 0xC9, 0x84, 0x53, 0x1E, +0xEB, 0xA6, 0x71, 0x3C, 0x92, 0xDF, 0x08, 0x45, 0x19, 0x54, 0x83, 0xCE, 0x60, 0x2D, 0xFA, 0xB7, +0x5D, 0x10, 0xC7, 0x8A, 0x24, 0x69, 0xBE, 0xF3, 0xAF, 0xE2, 0x35, 0x78, 0xD6, 0x9B, 0x4C, 0x01, +0xF4, 0xB9, 0x6E, 0x23, 0x8D, 0xC0, 0x17, 0x5A, 0x06, 0x4B, 0x9C, 0xD1, 0x7F, 0x32, 0xE5, 0xA8 +}; + +static int isInPageYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData, + unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len) +{ + int nResult = 0; + + if (nBook == TAS2557_YRAM_BOOK1) { + if (nPage == TAS2557_YRAM1_PAGE) { + if (nReg >= TAS2557_YRAM1_START_REG) { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = len; + nResult = 1; + } else if ((nReg + len) > TAS2557_YRAM1_START_REG) { + pCRCData->mnOffset = TAS2557_YRAM1_START_REG; + pCRCData->mnLen = len - (TAS2557_YRAM1_START_REG - nReg); + nResult = 1; + } else + nResult = 0; + } else if (nPage == TAS2557_YRAM3_PAGE) { + if (nReg > TAS2557_YRAM3_END_REG) { + nResult = 0; + } else if (nReg >= TAS2557_YRAM3_START_REG) { + if ((nReg + len) > TAS2557_YRAM3_END_REG) { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = TAS2557_YRAM3_END_REG - nReg + 1; + nResult = 1; + } else { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = len; + nResult = 1; + } + } else { + if ((nReg + (len - 1)) < TAS2557_YRAM3_START_REG) + nResult = 0; + else { + pCRCData->mnOffset = TAS2557_YRAM3_START_REG; + pCRCData->mnLen = len - (TAS2557_YRAM3_START_REG - nReg); + nResult = 1; + } + } + } + } else if (nBook == TAS2557_YRAM_BOOK2) { + if (nPage == TAS2557_YRAM5_PAGE) { + if (nReg > TAS2557_YRAM5_END_REG) { + nResult = 0; + } else if (nReg >= TAS2557_YRAM5_START_REG) { + if ((nReg + len) > TAS2557_YRAM5_END_REG) { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = TAS2557_YRAM5_END_REG - nReg + 1; + nResult = 1; + } else { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = len; + nResult = 1; + } + } else { + if ((nReg + (len - 1)) < TAS2557_YRAM5_START_REG) + nResult = 0; + else { + pCRCData->mnOffset = TAS2557_YRAM5_START_REG; + pCRCData->mnLen = len - (TAS2557_YRAM5_START_REG - nReg); + nResult = 1; + } + } + } + } else + nResult = 0; + + return nResult; +} + +static int isInBlockYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData, + unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len) +{ + int nResult; + + if (nBook == TAS2557_YRAM_BOOK1) { + if (nPage < TAS2557_YRAM2_START_PAGE) + nResult = 0; + else if (nPage <= TAS2557_YRAM2_END_PAGE) { + if (nReg > TAS2557_YRAM2_END_REG) + nResult = 0; + else if (nReg >= TAS2557_YRAM2_START_REG) { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = len; + nResult = 1; + } else { + if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG) + nResult = 0; + else { + pCRCData->mnOffset = TAS2557_YRAM2_START_REG; + pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG; + nResult = 1; + } + } + } else + nResult = 0; + } else if (nBook == TAS2557_YRAM_BOOK2) { + if (nPage < TAS2557_YRAM4_START_PAGE) + nResult = 0; + else if (nPage <= TAS2557_YRAM4_END_PAGE) { + if (nReg > TAS2557_YRAM2_END_REG) + nResult = 0; + else if (nReg >= TAS2557_YRAM2_START_REG) { + pCRCData->mnOffset = nReg; + pCRCData->mnLen = len; + nResult = 1; + } else { + if ((nReg + (len - 1)) < TAS2557_YRAM2_START_REG) + nResult = 0; + else { + pCRCData->mnOffset = TAS2557_YRAM2_START_REG; + pCRCData->mnLen = nReg + len - TAS2557_YRAM2_START_REG; + nResult = 1; + } + } + } else + nResult = 0; + } else + nResult = 0; + + return nResult; +} + + +static int isYRAM(struct tas2557_priv *pTAS2557, struct TYCRC *pCRCData, + unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char len) +{ + int nResult; + + nResult = isInPageYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len); + + if (nResult == 0) + nResult = isInBlockYRAM(pTAS2557, pCRCData, nBook, nPage, nReg, len); + + return nResult; +} + +/* + * crc8 - calculate a crc8 over the given input data. + * + * table: crc table used for calculation. + * pdata: pointer to data buffer. + * nbytes: number of bytes in data buffer. + * crc: previous returned crc8 value. + */ +static u8 ti_crc8(const u8 table[CRC8_TABLE_SIZE], u8 *pdata, size_t nbytes, u8 crc) +{ + /* loop over the buffer data */ + while (nbytes-- > 0) + crc = table[(crc ^ *pdata++) & 0xff]; + + return crc; +} + +static int doSingleRegCheckSum(struct tas2557_priv *pTAS2557, + unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned char nValue) +{ + int nResult = 0; + struct TYCRC sCRCData; + unsigned int nData1 = 0; + + if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG)) + && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG)) + && (nReg >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG)) + && (nReg <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) { + /* DSP swap command, pass */ + nResult = 0; + goto end; + } + + nResult = isYRAM(pTAS2557, &sCRCData, nBook, nPage, nReg, 1); + if (nResult == 1) { + nResult = pTAS2557->read(pTAS2557, TAS2557_REG(nBook, nPage, nReg), &nData1); + if (nResult < 0) + goto end; + + if (nData1 != nValue) { + dev_err(pTAS2557->dev, "error2 (line %d),B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n", + __LINE__, nBook, nPage, nReg, nValue, nData1); + nResult = -EAGAIN; + goto end; + } + + nResult = ti_crc8(crc8_lookup_table, &nValue, 1, 0); + } + +end: + + return nResult; +} + +static int doMultiRegCheckSum(struct tas2557_priv *pTAS2557, + unsigned char nBook, unsigned char nPage, unsigned char nReg, unsigned int len) +{ + int nResult = 0, i; + unsigned char nCRCChkSum = 0; + unsigned char nBuf1[128]; + struct TYCRC TCRCData; + + if ((nReg + len-1) > 127) { + nResult = -EINVAL; + dev_err(pTAS2557->dev, "firmware error\n"); + goto end; + } + + if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG)) + && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG)) + && (nReg == TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG)) + && (len == 4)) { + /* DSP swap command, pass */ + nResult = 0; + goto end; + } + + nResult = isYRAM(pTAS2557, &TCRCData, nBook, nPage, nReg, len); + if (nResult == 1) { + if (len == 1) { + dev_err(pTAS2557->dev, "firmware error\n"); + nResult = -EINVAL; + goto end; + } else { + nResult = pTAS2557->bulk_read(pTAS2557, TAS2557_REG(nBook, nPage, TCRCData.mnOffset), nBuf1, TCRCData.mnLen); + if (nResult < 0) + goto end; + + for (i = 0; i < TCRCData.mnLen; i++) { + if ((nBook == TAS2557_BOOK_ID(TAS2557_SA_COEFF_SWAP_REG)) + && (nPage == TAS2557_PAGE_ID(TAS2557_SA_COEFF_SWAP_REG)) + && ((i + TCRCData.mnOffset) + >= TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG)) + && ((i + TCRCData.mnOffset) + <= (TAS2557_PAGE_REG(TAS2557_SA_COEFF_SWAP_REG) + 4))) { + /* DSP swap command, bypass */ + continue; + } else + nCRCChkSum += ti_crc8(crc8_lookup_table, &nBuf1[i], 1, 0); + } + + nResult = nCRCChkSum; + } + } + +end: + + return nResult; +} + +static int tas2557_load_block(struct tas2557_priv *pTAS2557, struct TBlock *pBlock) +{ + int nResult = 0; + unsigned int nCommand = 0; + unsigned char nBook; + unsigned char nPage; + unsigned char nOffset; + unsigned char nData; + unsigned int nLength; + unsigned int nSleep; + unsigned char nCRCChkSum = 0; + unsigned int nValue1; + int nRetry = 6; + unsigned char *pData = pBlock->mpData; + + dev_dbg(pTAS2557->dev, "TAS2557 load block: Type = %d, commands = %d\n", + pBlock->mnType, pBlock->mnCommands); +start: + if (pBlock->mbPChkSumPresent) { + nResult = pTAS2557->write(pTAS2557, TAS2557_CRC_RESET_REG, 1); + if (nResult < 0) + goto end; + } + + if (pBlock->mbYChkSumPresent) + nCRCChkSum = 0; + + nCommand = 0; + + while (nCommand < pBlock->mnCommands) { + pData = pBlock->mpData + nCommand * 4; + + nBook = pData[0]; + nPage = pData[1]; + nOffset = pData[2]; + nData = pData[3]; + + nCommand++; + + if (nOffset <= 0x7F) { + nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), nData); + if (nResult < 0) + goto end; + if (pBlock->mbYChkSumPresent) { + nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, nData); + if (nResult < 0) + goto check; + nCRCChkSum += (unsigned char)nResult; + } + } else if (nOffset == 0x81) { + nSleep = (nBook << 8) + nPage; + msleep(nSleep); + } else if (nOffset == 0x85) { + pData += 4; + nLength = (nBook << 8) + nPage; + nBook = pData[0]; + nPage = pData[1]; + nOffset = pData[2]; + if (nLength > 1) { + nResult = pTAS2557->bulk_write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData + 3, nLength); + if (nResult < 0) + goto end; + if (pBlock->mbYChkSumPresent) { + nResult = doMultiRegCheckSum(pTAS2557, nBook, nPage, nOffset, nLength); + if (nResult < 0) + goto check; + nCRCChkSum += (unsigned char)nResult; + } + } else { + nResult = pTAS2557->write(pTAS2557, TAS2557_REG(nBook, nPage, nOffset), pData[3]); + if (nResult < 0) + goto end; + if (pBlock->mbYChkSumPresent) { + nResult = doSingleRegCheckSum(pTAS2557, nBook, nPage, nOffset, pData[3]); + if (nResult < 0) + goto check; + nCRCChkSum += (unsigned char)nResult; + } + } + + nCommand++; + + if (nLength >= 2) + nCommand += ((nLength - 2) / 4) + 1; + } + } + if (pBlock->mbPChkSumPresent) { + nResult = pTAS2557->read(pTAS2557, TAS2557_CRC_CHECKSUM_REG, &nValue1); + if (nResult < 0) + goto end; + if ((nValue1&0xff) != pBlock->mnPChkSum) { + dev_err(pTAS2557->dev, "Block PChkSum Error: FW = 0x%x, Reg = 0x%x\n", + pBlock->mnPChkSum, (nValue1&0xff)); + nResult = -EAGAIN; + pTAS2557->mnErrCode |= ERROR_PRAM_CRCCHK; + goto check; + } + + nResult = 0; + pTAS2557->mnErrCode &= ~ERROR_PRAM_CRCCHK; + dev_dbg(pTAS2557->dev, "Block[0x%x] PChkSum match\n", pBlock->mnType); + } + + if (pBlock->mbYChkSumPresent) { + if (nCRCChkSum != pBlock->mnYChkSum) { + dev_err(pTAS2557->dev, "Block YChkSum Error: FW = 0x%x, YCRC = 0x%x\n", + pBlock->mnYChkSum, nCRCChkSum); + nResult = -EAGAIN; + pTAS2557->mnErrCode |= ERROR_YRAM_CRCCHK; + goto check; + } + pTAS2557->mnErrCode &= ~ERROR_YRAM_CRCCHK; + nResult = 0; + dev_dbg(pTAS2557->dev, "Block[0x%x] YChkSum match\n", pBlock->mnType); + } + +check: + if (nResult == -EAGAIN) { + nRetry--; + if (nRetry > 0) + goto start; + } + +end: + if (nResult < 0) { + dev_err(pTAS2557->dev, "Block (%d) load error\n", + pBlock->mnType); + } + return nResult; +} + +static int tas2557_load_data(struct tas2557_priv *pTAS2557, struct TData *pData, unsigned int nType) +{ + int nResult = 0; + unsigned int nBlock; + struct TBlock *pBlock; + + dev_dbg(pTAS2557->dev, + "TAS2557 load data: %s, Blocks = %d, Block Type = %d\n", pData->mpName, pData->mnBlocks, nType); + + for (nBlock = 0; nBlock < pData->mnBlocks; nBlock++) { + pBlock = &(pData->mpBlocks[nBlock]); + if (pBlock->mnType == nType) { + nResult = tas2557_load_block(pTAS2557, pBlock); + if (nResult < 0) + break; + } + } + + return nResult; +} + +static int tas2557_load_configuration(struct tas2557_priv *pTAS2557, + unsigned int nConfiguration, bool bLoadSame) +{ + int nResult = 0; + struct TConfiguration *pCurrentConfiguration = NULL; + struct TConfiguration *pNewConfiguration = NULL; + + dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, nConfiguration); + + if ((!pTAS2557->mpFirmware->mpPrograms) || + (!pTAS2557->mpFirmware->mpConfigurations)) { + dev_err(pTAS2557->dev, "Firmware not loaded\n"); + nResult = 0; + goto end; + } + + if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) { + dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n", + nConfiguration); + nResult = 0; + goto end; + } + + if ((!pTAS2557->mbLoadConfigurationPrePowerUp) + && (nConfiguration == pTAS2557->mnCurrentConfiguration) + && (!bLoadSame)) { + dev_info(pTAS2557->dev, "Configuration %d is already loaded\n", + nConfiguration); + nResult = 0; + goto end; + } + + pCurrentConfiguration = + &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]); + pNewConfiguration = + &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]); + if (pNewConfiguration->mnProgram != pCurrentConfiguration->mnProgram) { + dev_err(pTAS2557->dev, "Configuration %d, %s doesn't share the same program as current %d\n", + nConfiguration, pNewConfiguration->mpName, pCurrentConfiguration->mnProgram); + nResult = 0; + goto end; + } + + if (pNewConfiguration->mnPLL >= pTAS2557->mpFirmware->mnPLLs) { + dev_err(pTAS2557->dev, "Configuration %d, %s doesn't have a valid PLL index %d\n", + nConfiguration, pNewConfiguration->mpName, pNewConfiguration->mnPLL); + nResult = 0; + goto end; + } + + if (pTAS2557->mbPowerUp) { + pTAS2557->mbLoadConfigurationPrePowerUp = false; + nResult = tas2557_load_coefficient(pTAS2557, pTAS2557->mnCurrentConfiguration, nConfiguration, true); + } else { + dev_dbg(pTAS2557->dev, + "TAS2557 was powered down, will load coefficient when power up\n"); + pTAS2557->mbLoadConfigurationPrePowerUp = true; + pTAS2557->mnNewConfiguration = nConfiguration; + } + +end: + + if (nResult < 0) { + if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK)) + failsafe(pTAS2557); + } + + return nResult; +} + +int tas2557_set_config(struct tas2557_priv *pTAS2557, int config) +{ + struct TConfiguration *pConfiguration; + struct TProgram *pProgram; + unsigned int nProgram = pTAS2557->mnCurrentProgram; + unsigned int nConfiguration = config; + int nResult = 0; + + if ((!pTAS2557->mpFirmware->mpPrograms) || + (!pTAS2557->mpFirmware->mpConfigurations)) { + dev_err(pTAS2557->dev, "Firmware not loaded\n"); + nResult = -EINVAL; + goto end; + } + + if (nConfiguration >= pTAS2557->mpFirmware->mnConfigurations) { + dev_err(pTAS2557->dev, "Configuration %d doesn't exist\n", + nConfiguration); + nResult = -EINVAL; + goto end; + } + + pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[nConfiguration]); + pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]); + + if (nProgram != pConfiguration->mnProgram) { + dev_err(pTAS2557->dev, + "Configuration %d, %s with Program %d isn't compatible with existing Program %d, %s\n", + nConfiguration, pConfiguration->mpName, pConfiguration->mnProgram, + nProgram, pProgram->mpName); + nResult = -EINVAL; + goto end; + } + + nResult = tas2557_load_configuration(pTAS2557, nConfiguration, false); + +end: + + return nResult; +} + +void tas2557_clear_firmware(struct TFirmware *pFirmware) +{ + unsigned int n, nn; + + if (!pFirmware) + return; + + kfree(pFirmware->mpDescription); + + if (pFirmware->mpPLLs != NULL) { + for (n = 0; n < pFirmware->mnPLLs; n++) { + kfree(pFirmware->mpPLLs[n].mpDescription); + kfree(pFirmware->mpPLLs[n].mBlock.mpData); + } + kfree(pFirmware->mpPLLs); + } + + if (pFirmware->mpPrograms != NULL) { + for (n = 0; n < pFirmware->mnPrograms; n++) { + kfree(pFirmware->mpPrograms[n].mpDescription); + kfree(pFirmware->mpPrograms[n].mData.mpDescription); + for (nn = 0; nn < pFirmware->mpPrograms[n].mData.mnBlocks; nn++) + kfree(pFirmware->mpPrograms[n].mData.mpBlocks[nn].mpData); + kfree(pFirmware->mpPrograms[n].mData.mpBlocks); + } + kfree(pFirmware->mpPrograms); + } + + if (pFirmware->mpConfigurations != NULL) { + for (n = 0; n < pFirmware->mnConfigurations; n++) { + kfree(pFirmware->mpConfigurations[n].mpDescription); + kfree(pFirmware->mpConfigurations[n].mData.mpDescription); + for (nn = 0; nn < pFirmware->mpConfigurations[n].mData.mnBlocks; nn++) + kfree(pFirmware->mpConfigurations[n].mData.mpBlocks[nn].mpData); + kfree(pFirmware->mpConfigurations[n].mData.mpBlocks); + } + kfree(pFirmware->mpConfigurations); + } + + if (pFirmware->mpCalibrations != NULL) { + for (n = 0; n < pFirmware->mnCalibrations; n++) { + kfree(pFirmware->mpCalibrations[n].mpDescription); + kfree(pFirmware->mpCalibrations[n].mData.mpDescription); + for (nn = 0; nn < pFirmware->mpCalibrations[n].mData.mnBlocks; nn++) + kfree(pFirmware->mpCalibrations[n].mData.mpBlocks[nn].mpData); + kfree(pFirmware->mpCalibrations[n].mData.mpBlocks); + } + kfree(pFirmware->mpCalibrations); + } + + memset(pFirmware, 0x00, sizeof(struct TFirmware)); +} + +static int tas2557_load_calibration(struct tas2557_priv *pTAS2557, char *pFileName) +{ + int nResult = 0; + + int nFile; + mm_segment_t fs; + unsigned char pBuffer[1000]; + int nSize = 0; + + dev_dbg(pTAS2557->dev, "%s:\n", __func__); + + fs = get_fs(); + set_fs(KERNEL_DS); + nFile = sys_open(pFileName, O_RDONLY, 0); + + dev_info(pTAS2557->dev, "TAS2557 calibration file = %s, handle = %d\n", + pFileName, nFile); + + if (nFile >= 0) { + nSize = sys_read(nFile, pBuffer, 1000); + sys_close(nFile); + } else { + dev_err(pTAS2557->dev, "TAS2557 cannot open calibration file: %s\n", + pFileName); + } + + set_fs(fs); + + if (!nSize) + goto end; + + tas2557_clear_firmware(pTAS2557->mpCalFirmware); + dev_info(pTAS2557->dev, "TAS2557 calibration file size = %d\n", nSize); + nResult = fw_parse(pTAS2557, pTAS2557->mpCalFirmware, pBuffer, nSize); + + if (nResult) + dev_err(pTAS2557->dev, "TAS2557 calibration file is corrupt\n"); + else + dev_info(pTAS2557->dev, "TAS2557 calibration: %d calibrations\n", + pTAS2557->mpCalFirmware->mnCalibrations); + +end: + + return nResult; +} + +static bool tas2557_get_coefficient_in_block(struct tas2557_priv *pTAS2557, + struct TBlock *pBlock, int nReg, int *pnValue) +{ + int nCoefficient = 0; + bool bFound = false; + unsigned char *pCommands; + int nBook, nPage, nOffset, len; + int i, n; + + pCommands = pBlock->mpData; + for (i = 0 ; i < pBlock->mnCommands;) { + nBook = pCommands[4 * i + 0]; + nPage = pCommands[4 * i + 1]; + nOffset = pCommands[4 * i + 2]; + if ((nOffset < 0x7f) || (nOffset == 0x81)) + i++; + else if (nOffset == 0x85) { + len = ((int)nBook << 8) | nPage; + nBook = pCommands[4 * i + 4]; + nPage = pCommands[4 * i + 5]; + nOffset = pCommands[4 * i + 6]; + n = 4 * i + 7; + i += 2; + i += ((len - 1) / 4); + if ((len - 1) % 4) + i++; + if ((nBook != TAS2557_BOOK_ID(nReg)) + || (nPage != TAS2557_PAGE_ID(nReg))) + continue; + if (nOffset > TAS2557_PAGE_REG(nReg)) + continue; + if ((len + nOffset) >= (TAS2557_PAGE_REG(nReg) + 4)) { + n += (TAS2557_PAGE_REG(nReg) - nOffset); + nCoefficient = ((int)pCommands[n] << 24) + | ((int)pCommands[n + 1] << 16) + | ((int)pCommands[n + 2] << 8) + | (int)pCommands[n + 3]; + bFound = true; + break; + } + } else { + dev_err(pTAS2557->dev, "%s, format error %d\n", __func__, nOffset); + break; + } + } + + if (bFound) { + *pnValue = nCoefficient; + dev_dbg(pTAS2557->dev, "%s, B[0x%x]P[0x%x]R[0x%x]=0x%x\n", __func__, + TAS2557_BOOK_ID(nReg), TAS2557_PAGE_ID(nReg), TAS2557_PAGE_REG(nReg), + nCoefficient); + } + + return bFound; +} + +static bool tas2557_get_coefficient_in_data(struct tas2557_priv *pTAS2557, + struct TData *pData, int blockType, int nReg, int *pnValue) +{ + bool bFound = false; + struct TBlock *pBlock; + int i; + + for (i = 0; i < pData->mnBlocks; i++) { + pBlock = &(pData->mpBlocks[i]); + if (pBlock->mnType == blockType) { + bFound = tas2557_get_coefficient_in_block(pTAS2557, + pBlock, nReg, pnValue); + if (bFound) + break; + } + } + + return bFound; +} + +static bool tas2557_find_Tmax_in_configuration(struct tas2557_priv *pTAS2557, + struct TConfiguration *pConfiguration, int *pnTMax) +{ + struct TData *pData; + bool bFound = false; + int nBlockType, nReg, nCoefficient; + + if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1) + nReg = TAS2557_PG2P1_CALI_T_REG; + else + nReg = TAS2557_PG1P0_CALI_T_REG; + + nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A; + + pData = &(pConfiguration->mData); + bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCoefficient); + if (bFound) + *pnTMax = nCoefficient; + + return bFound; +} + +void tas2557_fw_ready(const struct firmware *pFW, void *pContext) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *) pContext; + int nResult; + unsigned int nProgram = 0; + unsigned int nSampleRate = 0; + +#ifdef CONFIG_TAS2557_CODEC + mutex_lock(&pTAS2557->codec_lock); +#endif + +#ifdef CONFIG_TAS2557_MISC + mutex_lock(&pTAS2557->file_lock); +#endif + + dev_info(pTAS2557->dev, "%s:\n", __func__); + + if (unlikely(!pFW) || unlikely(!pFW->data)) { + dev_err(pTAS2557->dev, "%s firmware is not loaded.\n", + TAS2557_FW_NAME); + goto end; + } + + if (pTAS2557->mpFirmware->mpConfigurations) { + nProgram = pTAS2557->mnCurrentProgram; + nSampleRate = pTAS2557->mnCurrentSampleRate; + dev_dbg(pTAS2557->dev, "clear current firmware\n"); + tas2557_clear_firmware(pTAS2557->mpFirmware); + } + + nResult = fw_parse(pTAS2557, pTAS2557->mpFirmware, (unsigned char *)(pFW->data), pFW->size); + release_firmware(pFW); + if (nResult < 0) { + dev_err(pTAS2557->dev, "firmware is corrupt\n"); + goto end; + } + + if (!pTAS2557->mpFirmware->mnPrograms) { + dev_err(pTAS2557->dev, "firmware contains no programs\n"); + nResult = -EINVAL; + goto end; + } + + if (!pTAS2557->mpFirmware->mnConfigurations) { + dev_err(pTAS2557->dev, "firmware contains no configurations\n"); + nResult = -EINVAL; + goto end; + } + + if (nProgram >= pTAS2557->mpFirmware->mnPrograms) { + dev_info(pTAS2557->dev, + "no previous program, set to default\n"); + nProgram = 0; + } + + pTAS2557->mnCurrentSampleRate = nSampleRate; + nResult = tas2557_set_program(pTAS2557, nProgram, -1); + +end: + + printk("ready end !"); +#ifdef CONFIG_TAS2557_CODEC + mutex_unlock(&pTAS2557->codec_lock); +#endif + +#ifdef CONFIG_TAS2557_MISC + mutex_unlock(&pTAS2557->file_lock); +#endif +} + +int tas2557_set_program(struct tas2557_priv *pTAS2557, + unsigned int nProgram, int nConfig) +{ + struct TProgram *pProgram; + unsigned int nConfiguration = 0; + unsigned int nSampleRate = 0; + unsigned char nGain; + bool bFound = false; + int nResult = 0; + + if ((!pTAS2557->mpFirmware->mpPrograms) || + (!pTAS2557->mpFirmware->mpConfigurations)) { + dev_err(pTAS2557->dev, "Firmware not loaded\n"); + nResult = 0; + goto end; + } + + if (nProgram >= pTAS2557->mpFirmware->mnPrograms) { + dev_err(pTAS2557->dev, "TAS2557: Program %d doesn't exist\n", + nProgram); + nResult = 0; + goto end; + } + + if (nConfig < 0) { + nConfiguration = 0; + nSampleRate = pTAS2557->mnCurrentSampleRate; + while (!bFound && (nConfiguration < pTAS2557->mpFirmware->mnConfigurations)) { + if (pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnProgram == nProgram) { + if (nSampleRate == 0) { + bFound = true; + dev_info(pTAS2557->dev, "find default configuration %d\n", nConfiguration); + } else if (nSampleRate == pTAS2557->mpFirmware->mpConfigurations[nConfiguration].mnSamplingRate) { + bFound = true; + dev_info(pTAS2557->dev, "find matching configuration %d\n", nConfiguration); + } else { + nConfiguration++; + } + } else { + nConfiguration++; + } + } + if (!bFound) { + dev_err(pTAS2557->dev, + "Program %d, no valid configuration found for sample rate %d, ignore\n", + nProgram, nSampleRate); + nResult = 0; + goto end; + } + } else { + if (pTAS2557->mpFirmware->mpConfigurations[nConfig].mnProgram != nProgram) { + dev_err(pTAS2557->dev, "%s, configuration program doesn't match\n", __func__); + nResult = 0; + goto end; + } + nConfiguration = nConfig; + } + + pProgram = &(pTAS2557->mpFirmware->mpPrograms[nProgram]); + if (pTAS2557->mbPowerUp) { + dev_info(pTAS2557->dev, + "device powered up, power down to load program %d (%s)\n", + nProgram, pProgram->mpName); + if (hrtimer_active(&pTAS2557->mtimer)) + hrtimer_cancel(&pTAS2557->mtimer); + + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) + pTAS2557->enableIRQ(pTAS2557, false); + + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + if (nResult < 0) + goto end; + } + + pTAS2557->hw_reset(pTAS2557); + nResult = pTAS2557->write(pTAS2557, TAS2557_SW_RESET_REG, 0x01); + if (nResult < 0) + goto end; + msleep(1); + nResult = tas2557_load_default(pTAS2557); + if (nResult < 0) + goto end; + + dev_info(pTAS2557->dev, "load program %d (%s)\n", nProgram, pProgram->mpName); + nResult = tas2557_load_data(pTAS2557, &(pProgram->mData), TAS2557_BLOCK_PGM_DEV_A); + if (nResult < 0) + goto end; + pTAS2557->mnCurrentProgram = nProgram; + + nResult = tas2557_get_DAC_gain(pTAS2557, &nGain); + if (nResult < 0) + goto end; + pTAS2557->mnDevGain = nGain; + pTAS2557->mnDevCurrentGain = nGain; + + nResult = tas2557_load_coefficient(pTAS2557, -1, nConfiguration, false); + if (nResult < 0) + goto end; + + if (pTAS2557->mbPowerUp) { + pTAS2557->clearIRQ(pTAS2557); + dev_dbg(pTAS2557->dev, "device powered up, load startup\n"); + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_startup_data); + if (nResult < 0) + goto end; + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + nResult = tas2557_checkPLL(pTAS2557); + if (nResult < 0) { + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_shutdown_data); + pTAS2557->mbPowerUp = false; + goto end; + } + } + dev_dbg(pTAS2557->dev, "device powered up, load unmute\n"); + nResult = tas2557_dev_load_data(pTAS2557, p_tas2557_unmute_data); + if (nResult < 0) + goto end; + + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + pTAS2557->enableIRQ(pTAS2557, true); + if (!hrtimer_active(&pTAS2557->mtimer)) { + pTAS2557->mnDieTvReadCounter = 0; + hrtimer_start(&pTAS2557->mtimer, + ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL); + } + } + } + +end: + + if (nResult < 0) { + if (pTAS2557->mnErrCode & (ERROR_DEVA_I2C_COMM | ERROR_PRAM_CRCCHK | ERROR_YRAM_CRCCHK)) + failsafe(pTAS2557); + } + return nResult; +} + +int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration) +{ + struct TCalibration *pCalibration = NULL; + struct TConfiguration *pConfiguration; + struct TProgram *pProgram; + int nTmax = 0; + bool bFound = false; + int nResult = 0; + + if ((!pTAS2557->mpFirmware->mpPrograms) + || (!pTAS2557->mpFirmware->mpConfigurations)) { + dev_err(pTAS2557->dev, "Firmware not loaded\n\r"); + nResult = 0; + goto end; + } + if (nCalibration == 0x00FF) { + nResult = tas2557_load_calibration(pTAS2557, TAS2557_CAL_NAME); + if (nResult < 0) { + dev_info(pTAS2557->dev, "load new calibration file %s fail %d\n", + TAS2557_CAL_NAME, nResult); + goto end; + } + nCalibration = 0; + } + + if (nCalibration >= pTAS2557->mpCalFirmware->mnCalibrations) { + dev_err(pTAS2557->dev, + "Calibration %d doesn't exist\n", nCalibration); + nResult = 0; + goto end; + } + + pTAS2557->mnCurrentCalibration = nCalibration; + if (pTAS2557->mbLoadConfigurationPrePowerUp) + goto end; + + pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[nCalibration]); + pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]); + pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]); + if (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE) { + if (pTAS2557->mbBypassTMax) { + bFound = tas2557_find_Tmax_in_configuration(pTAS2557, pConfiguration, &nTmax); + if (bFound && (nTmax == TAS2557_COEFFICIENT_TMAX)) { + dev_dbg(pTAS2557->dev, "%s, config[%s] bypass load calibration\n", + __func__, pConfiguration->mpName); + goto end; + } + } + + dev_dbg(pTAS2557->dev, "%s, load calibration\n", __func__); + nResult = tas2557_load_data(pTAS2557, &(pCalibration->mData), TAS2557_BLOCK_CFG_COEFF_DEV_A); + if (nResult < 0) + goto end; + } + +end: + if (nResult < 0) { + tas2557_clear_firmware(pTAS2557->mpCalFirmware); + nResult = tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration); + } + + return nResult; +} + +bool tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0) +{ + struct TCalibration *pCalibration; + struct TData *pData; + int nReg; + int nCali_Re; + bool bFound = false; + int nBlockType; + + if (!pTAS2557->mpCalFirmware->mnCalibrations) { + dev_err(pTAS2557->dev, "%s, no calibration data\n", __func__); + goto end; + } + + if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1) + nReg = TAS2557_PG2P1_CALI_R0_REG; + else + nReg = TAS2557_PG1P0_CALI_R0_REG; + + nBlockType = TAS2557_BLOCK_CFG_COEFF_DEV_A; + + pCalibration = &(pTAS2557->mpCalFirmware->mpCalibrations[pTAS2557->mnCurrentCalibration]); + pData = &(pCalibration->mData); + + bFound = tas2557_get_coefficient_in_data(pTAS2557, pData, nBlockType, nReg, &nCali_Re); + +end: + + if (bFound) + *prm_r0 = nCali_Re; + + return bFound; +} + +int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557) +{ + struct device_node *np = dev->of_node; + int rc = 0, ret = 0; + unsigned int value; + + pTAS2557->mnResetGPIO = of_get_named_gpio(np, "ti,cdc-reset-gpio", 0); + if (!gpio_is_valid(pTAS2557->mnResetGPIO)) { + dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n", + "ti,cdc-reset-gpio", np->full_name, + pTAS2557->mnResetGPIO); + ret = -EINVAL; + goto end; + } else + dev_dbg(pTAS2557->dev, "ti,cdc-reset-gpio=%d\n", pTAS2557->mnResetGPIO); + + pTAS2557->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0); + if (!gpio_is_valid(pTAS2557->mnGpioINT)) + dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n", + "ti,irq-gpio", np->full_name, + pTAS2557->mnGpioINT); + + + rc = of_property_read_u32(np, "ti,i2s-bits", &value); + if (rc) + dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n", + "ti,i2s-bits", np->full_name, rc); + else + pTAS2557->mnI2SBits = value; + + rc = of_property_read_u32(np, "ti,bypass-tmax", &value); + if (rc) + dev_err(pTAS2557->dev, "Looking up %s property in node %s failed %d\n", + "ti,bypass-tmax", np->full_name, rc); + else + pTAS2557->mbBypassTMax = (value > 0); + +end: + + return ret; +} + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS2557 common functions for Android Linux"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/tas2557-core.h b/sound/soc/codecs/tas2557-core.h new file mode 100644 index 0000000000000..a94ad23405cc0 --- /dev/null +++ b/sound/soc/codecs/tas2557-core.h @@ -0,0 +1,79 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-core.h +** +** Description: +** header file for tas2557-core.c +** +** ============================================================================= +*/ + +#ifndef _TAS2557_CORE_H +#define _TAS2557_CORE_H + +#include "tas2557.h" + +#define TAS2557_YRAM_BOOK1 140 + +#define TAS2557_YRAM1_PAGE 42 +#define TAS2557_YRAM1_START_REG 88 +#define TAS2557_YRAM1_END_REG 127 + +#define TAS2557_YRAM2_START_PAGE 43 +#define TAS2557_YRAM2_END_PAGE 49 +#define TAS2557_YRAM2_START_REG 8 +#define TAS2557_YRAM2_END_REG 127 + +#define TAS2557_YRAM3_PAGE 50 +#define TAS2557_YRAM3_START_REG 8 +#define TAS2557_YRAM3_END_REG 27 + +/* should not include B0_P53_R44-R47 */ +#define TAS2557_YRAM_BOOK2 0 +#define TAS2557_YRAM4_START_PAGE 50 +#define TAS2557_YRAM4_END_PAGE 60 +#define TAS2557_YRAM4_START_REG 8 +#define TAS2557_YRAM4_END_REG 127 + +#define TAS2557_YRAM5_PAGE 61 +#define TAS2557_YRAM5_START_REG 8 +#define TAS2557_YRAM5_END_REG 27 + +#define TAS2557_COEFFICIENT_TMAX 0x7fffffff +#define TAS2557_SAFE_GUARD_PATTERN 0x5a +#define LOW_TEMPERATURE_CHECK_PERIOD 5000 /* 5 second */ + +struct TYCRC { + unsigned char mnOffset; + unsigned char mnLen; +}; + +int tas2557_enable(struct tas2557_priv *pTAS2557, bool bEnable); +int tas2557_SA_DevChnSetup(struct tas2557_priv *pTAS2557, unsigned int mode); +int tas2557_get_die_temperature(struct tas2557_priv *pTAS2557, int *pTemperature); +int tas2557_set_sampling_rate(struct tas2557_priv *pTAS2557, unsigned int nSamplingRate); +int tas2557_set_bit_rate(struct tas2557_priv *pTAS2557, unsigned int nBitRate); +int tas2557_get_bit_rate(struct tas2557_priv *pTAS2557, unsigned char *pBitRate); +int tas2557_set_config(struct tas2557_priv *pTAS2557, int config); +void tas2557_fw_ready(const struct firmware *pFW, void *pContext); +bool tas2557_get_Cali_prm_r0(struct tas2557_priv *pTAS2557, int *prm_r0); +int tas2557_set_program(struct tas2557_priv *pTAS2557, unsigned int nProgram, int nConfig); +int tas2557_set_calibration(struct tas2557_priv *pTAS2557, int nCalibration); +int tas2557_load_default(struct tas2557_priv *pTAS2557); +int tas2557_parse_dt(struct device *dev, struct tas2557_priv *pTAS2557); +int tas2557_get_DAC_gain(struct tas2557_priv *pTAS2557, unsigned char *pnGain); +int tas2557_set_DAC_gain(struct tas2557_priv *pTAS2557, unsigned int nGain); +int tas2557_configIRQ(struct tas2557_priv *pTAS2557); +#endif /* _TAS2557_CORE_H */ diff --git a/sound/soc/codecs/tas2557-misc.c b/sound/soc/codecs/tas2557-misc.c new file mode 100644 index 0000000000000..a442c048321d4 --- /dev/null +++ b/sound/soc/codecs/tas2557-misc.c @@ -0,0 +1,594 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-misc.c +** +** Description: +** misc driver for Texas Instruments TAS2557 High Performance 4W Smart Amplifier +** +** ============================================================================= +*/ + +#ifdef CONFIG_TAS2557_MISC + +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas2557.h" +#include "tas2557-core.h" +#include "tas2557-misc.h" +#include + +static int g_logEnable = 1; +static struct tas2557_priv *g_tas2557; + +static int tas2557_file_open(struct inode *inode, struct file *file) +{ + struct tas2557_priv *pTAS2557 = g_tas2557; + + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + file->private_data = (void *)pTAS2557; + if (g_logEnable) + dev_info(pTAS2557->dev, "%s\n", __func__); + return 0; +} + +static int tas2557_file_release(struct inode *inode, struct file *file) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)file->private_data; + + if (g_logEnable) + dev_info(pTAS2557->dev, "%s\n", __func__); + file->private_data = (void *)NULL; + module_put(THIS_MODULE); + + return 0; +} + +static ssize_t tas2557_file_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)file->private_data; + int ret = 0; + unsigned int nValue = 0; + unsigned char value = 0; + unsigned char *p_kBuf = NULL; + + mutex_lock(&pTAS2557->file_lock); + + switch (pTAS2557->mnDBGCmd) { + case TIAUDIO_CMD_REG_READ: { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_READ: current_reg = 0x%x, count=%d\n", + pTAS2557->mnCurrentReg, (int)count); + if (count == 1) { + ret = pTAS2557->read(pTAS2557, pTAS2557->mnCurrentReg, &nValue); + if (ret < 0) + break; + + value = (u8)nValue; + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_READ: nValue=0x%x, value=0x%x\n", nValue, value); + ret = copy_to_user(buf, &value, 1); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + } else if (count > 1) { + p_kBuf = kzalloc(count, GFP_KERNEL); + if (p_kBuf != NULL) { + ret = pTAS2557->bulk_read(pTAS2557, pTAS2557->mnCurrentReg, p_kBuf, count); + if (ret < 0) + break; + ret = copy_to_user(buf, p_kBuf, count); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + kfree(p_kBuf); + } else + dev_err(pTAS2557->dev, "read no mem\n"); + } + } + break; + + case TIAUDIO_CMD_PROGRAM: { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM: count = %d\n", (int)count); + + if (count == PROGRAM_BUF_SIZE) { + p_kBuf = kzalloc(count, GFP_KERNEL); + if (p_kBuf != NULL) { + struct TProgram *pProgram = + &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]); + p_kBuf[0] = pTAS2557->mpFirmware->mnPrograms; + p_kBuf[1] = pTAS2557->mnCurrentProgram; + p_kBuf[2] = pProgram->mnAppMode; + p_kBuf[3] = (pProgram->mnBoost&0xff00)>>8; + p_kBuf[4] = (pProgram->mnBoost&0x00ff); + memcpy(&p_kBuf[5], pProgram->mpName, FW_NAME_SIZE); + strlcpy(&p_kBuf[5+FW_NAME_SIZE], pProgram->mpDescription, strlen(pProgram->mpDescription) + 1); + ret = copy_to_user(buf, p_kBuf, count); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + kfree(p_kBuf); + } else + dev_err(pTAS2557->dev, "read no mem\n"); + } else + dev_err(pTAS2557->dev, "read buffer not sufficient\n"); + } else + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + } + break; + + case TIAUDIO_CMD_CONFIGURATION: { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION: count = %d\n", (int)count); + if (count == CONFIGURATION_BUF_SIZE) { + p_kBuf = kzalloc(count, GFP_KERNEL); + if (p_kBuf != NULL) { + struct TConfiguration *pConfiguration = &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]); + + p_kBuf[0] = pTAS2557->mpFirmware->mnConfigurations; + p_kBuf[1] = pTAS2557->mnCurrentConfiguration; + memcpy(&p_kBuf[2], pConfiguration->mpName, FW_NAME_SIZE); + p_kBuf[2+FW_NAME_SIZE] = pConfiguration->mnProgram; + p_kBuf[3+FW_NAME_SIZE] = pConfiguration->mnPLL; + p_kBuf[4+FW_NAME_SIZE] = (pConfiguration->mnSamplingRate&0x000000ff); + p_kBuf[5+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8); + p_kBuf[6+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16); + p_kBuf[7+FW_NAME_SIZE] = ((pConfiguration->mnSamplingRate&0xff000000)>>24); + strlcpy(&p_kBuf[8+FW_NAME_SIZE], pConfiguration->mpDescription, strlen(pConfiguration->mpDescription)+1); + ret = copy_to_user(buf, p_kBuf, count); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + kfree(p_kBuf); + } else + dev_err(pTAS2557->dev, "read no mem\n"); + } else + dev_err(pTAS2557->dev, "read buffer not sufficient\n"); + } else + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + } + break; + + case TIAUDIO_CMD_FW_TIMESTAMP: { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_FW_TIMESTAMP: count = %d\n", (int)count); + + if (count == 4) { + p_kBuf = kzalloc(count, GFP_KERNEL); + if (p_kBuf != NULL) { + p_kBuf[0] = (pTAS2557->mpFirmware->mnTimeStamp&0x000000ff); + p_kBuf[1] = ((pTAS2557->mpFirmware->mnTimeStamp&0x0000ff00)>>8); + p_kBuf[2] = ((pTAS2557->mpFirmware->mnTimeStamp&0x00ff0000)>>16); + p_kBuf[3] = ((pTAS2557->mpFirmware->mnTimeStamp&0xff000000)>>24); + ret = copy_to_user(buf, p_kBuf, count); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + kfree(p_kBuf); + } else + dev_err(pTAS2557->dev, "read no mem\n"); + } + } + break; + + case TIAUDIO_CMD_CALIBRATION: { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_CALIBRATION: count = %d\n", (int)count); + + if (count == 1) { + unsigned char curCal = pTAS2557->mnCurrentCalibration; + + ret = copy_to_user(buf, &curCal, 1); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + } + } + break; + + case TIAUDIO_CMD_SAMPLERATE: { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_SAMPLERATE: count = %d\n", (int)count); + if (count == 4) { + p_kBuf = kzalloc(count, GFP_KERNEL); + if (p_kBuf != NULL) { + struct TConfiguration *pConfiguration = + &(pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration]); + + p_kBuf[0] = (pConfiguration->mnSamplingRate&0x000000ff); + p_kBuf[1] = ((pConfiguration->mnSamplingRate&0x0000ff00)>>8); + p_kBuf[2] = ((pConfiguration->mnSamplingRate&0x00ff0000)>>16); + p_kBuf[3] = ((pConfiguration->mnSamplingRate&0xff000000)>>24); + + ret = copy_to_user(buf, p_kBuf, count); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + + kfree(p_kBuf); + } else + dev_err(pTAS2557->dev, "read no mem\n"); + } + } + break; + + case TIAUDIO_CMD_BITRATE: { + if (g_logEnable) + dev_info(pTAS2557->dev, + "TIAUDIO_CMD_BITRATE: count = %d\n", (int)count); + + if (count == 1) { + unsigned char bitRate = 0; + ret = tas2557_get_bit_rate(pTAS2557, &bitRate); + if (ret >= 0) { + ret = copy_to_user(buf, &bitRate, 1); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + } + } + } + break; + + case TIAUDIO_CMD_DACVOLUME: { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_DACVOLUME: count = %d\n", (int)count); + + if (count == 1) { + unsigned char volume = 0; + + ret = tas2557_get_DAC_gain(pTAS2557, &volume); + if (ret >= 0) { + ret = copy_to_user(buf, &volume, 1); + if (ret != 0) { + /* Failed to copy all the data, exit */ + dev_err(pTAS2557->dev, "copy to user fail %d\n", ret); + } + } + } + } + break; + } + pTAS2557->mnDBGCmd = 0; + + mutex_unlock(&pTAS2557->file_lock); + return count; +} + +static ssize_t tas2557_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)file->private_data; + int ret = 0; + unsigned char *p_kBuf = NULL; + unsigned int reg = 0; + unsigned int len = 0; + + mutex_lock(&pTAS2557->file_lock); + + p_kBuf = kzalloc(count, GFP_KERNEL); + if (p_kBuf == NULL) { + dev_err(pTAS2557->dev, "write no mem\n"); + goto err; + } + + ret = copy_from_user(p_kBuf, buf, count); + if (ret != 0) { + dev_err(pTAS2557->dev, "copy_from_user failed.\n"); + goto err; + } + + pTAS2557->mnDBGCmd = p_kBuf[0]; + switch (pTAS2557->mnDBGCmd) { + case TIAUDIO_CMD_REG_WITE: + if (count > 5) { + reg = ((unsigned int)p_kBuf[1] << 24) + + ((unsigned int)p_kBuf[2] << 16) + + ((unsigned int)p_kBuf[3] << 8) + + (unsigned int)p_kBuf[4]; + len = count - 5; + if (len == 1) { + ret = pTAS2557->write(pTAS2557, reg, p_kBuf[5]); + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_WITE, Reg=0x%x, Val=0x%x\n", reg, p_kBuf[5]); + } else + ret = pTAS2557->bulk_write(pTAS2557, reg, &p_kBuf[5], len); + } else + dev_err(pTAS2557->dev, "%s, write len fail, count=%d.\n", __func__, (int)count); + pTAS2557->mnDBGCmd = 0; + break; + + case TIAUDIO_CMD_REG_READ: + if (count == 5) { + pTAS2557->mnCurrentReg = ((unsigned int)p_kBuf[1] << 24) + + ((unsigned int)p_kBuf[2] << 16) + + ((unsigned int)p_kBuf[3] << 8) + + (unsigned int)p_kBuf[4]; + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_REG_READ whole=0x%x\n", pTAS2557->mnCurrentReg); + } else + dev_err(pTAS2557->dev, "read len fail.\n"); + break; + + case TIAUDIO_CMD_DEBUG_ON: + if (count == 2) + g_logEnable = p_kBuf[1]; + + pTAS2557->mnDBGCmd = 0; + break; + + case TIAUDIO_CMD_PROGRAM: + { + if (count == 2) { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) { + int config = -1; + + if (p_kBuf[1] == pTAS2557->mnCurrentProgram) + config = pTAS2557->mnCurrentConfiguration; + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_PROGRAM, set to %d, cfg=%d\n", p_kBuf[1], config); + tas2557_set_program(pTAS2557, p_kBuf[1], config); + pTAS2557->mnDBGCmd = 0; + } else + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + } + } + break; + + case TIAUDIO_CMD_CONFIGURATION: + { + if (count == 2) { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_CONFIGURATION, set to %d\n", p_kBuf[1]); + tas2557_set_config(pTAS2557, p_kBuf[1]); + pTAS2557->mnDBGCmd = 0; + } else + dev_err(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + } + } + break; + + case TIAUDIO_CMD_FW_TIMESTAMP: + /*let go*/ + break; + + case TIAUDIO_CMD_CALIBRATION: + { + if (count == 2) { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_CALIBRATION, set to %d\n", p_kBuf[1]); + tas2557_set_calibration(pTAS2557, p_kBuf[1]); + pTAS2557->mnDBGCmd = 0; + } + } + } + break; + + case TIAUDIO_CMD_SAMPLERATE: + if (count == 5) { + unsigned int nSampleRate = ((unsigned int)p_kBuf[1] << 24) + + ((unsigned int)p_kBuf[2] << 16) + + ((unsigned int)p_kBuf[3] << 8) + + (unsigned int)p_kBuf[4]; + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_SAMPLERATE, set to %d\n", nSampleRate); + + tas2557_set_sampling_rate(pTAS2557, nSampleRate); + } + break; + + case TIAUDIO_CMD_BITRATE: + if (count == 2) { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_BITRATE, set to %d\n", p_kBuf[1]); + + tas2557_set_bit_rate(pTAS2557, p_kBuf[1]); + } + break; + + case TIAUDIO_CMD_DACVOLUME: + if (count == 2) { + unsigned char volume; + + volume = (p_kBuf[1] & 0x0f); + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_DACVOLUME, set to %d\n", volume); + + tas2557_set_DAC_gain(pTAS2557, volume); + } + break; + + case TIAUDIO_CMD_SPEAKER: + if (count == 2) { + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_SPEAKER, set to %d\n", p_kBuf[1]); + tas2557_enable(pTAS2557, (p_kBuf[1] > 0)); + } + break; + + case TIAUDIO_CMD_FW_RELOAD: + if (count == 1) { + const char *pFWName; + if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1) + pFWName = TAS2557_FW_NAME; + else if (pTAS2557->mnPGID == TAS2557_PG_VERSION_1P0) + pFWName = TAS2557_PG1P0_FW_NAME; + else + break; + + ret = request_firmware_nowait(THIS_MODULE, 1, pFWName, + pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready); + + if (g_logEnable) + dev_info(pTAS2557->dev, "TIAUDIO_CMD_FW_RELOAD: ret = %d\n", ret); + } + break; + + default: + pTAS2557->mnDBGCmd = 0; + break; + } + +err: + if (p_kBuf != NULL) + kfree(p_kBuf); + + mutex_unlock(&pTAS2557->file_lock); + + return count; +} + +static long tas2557_file_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct tas2557_priv *pTAS2557 = file->private_data; + int ret = 0; + + mutex_lock(&pTAS2557->file_lock); + + switch (cmd) { + case SMARTPA_SPK_DAC_VOLUME: + { + } + break; + + case SMARTPA_SPK_POWER_ON: + { + tas2557_enable(pTAS2557, true); + } + break; + + case SMARTPA_SPK_POWER_OFF: + { + tas2557_enable(pTAS2557, false); + } + break; + + case SMARTPA_SPK_SWITCH_PROGRAM: + { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) + tas2557_set_program(pTAS2557, arg, -1); + } + break; + + case SMARTPA_SPK_SWITCH_CONFIGURATION: + { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) + tas2557_set_config(pTAS2557, arg); + } + break; + + case SMARTPA_SPK_SWITCH_CALIBRATION: + { + if ((pTAS2557->mpFirmware->mnConfigurations > 0) + && (pTAS2557->mpFirmware->mnPrograms > 0)) + tas2557_set_calibration(pTAS2557, arg); + } + break; + + case SMARTPA_SPK_SET_SAMPLERATE: + { + tas2557_set_sampling_rate(pTAS2557, arg); + } + break; + + case SMARTPA_SPK_SET_BITRATE: + { + tas2557_set_bit_rate(pTAS2557, arg); + } + break; + } + + mutex_unlock(&pTAS2557->file_lock); + return ret; +} + +static const struct file_operations fops = { + .owner = THIS_MODULE, + .read = tas2557_file_read, + .write = tas2557_file_write, + .unlocked_ioctl = tas2557_file_unlocked_ioctl, + .open = tas2557_file_open, + .release = tas2557_file_release, +}; + +#define MODULE_NAME "tas2557" +static struct miscdevice tas2557_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = MODULE_NAME, + .fops = &fops, +}; + +int tas2557_register_misc(struct tas2557_priv *pTAS2557) +{ + int ret = 0; + + g_tas2557 = pTAS2557; + + ret = misc_register(&tas2557_misc); + if (ret) + dev_err(pTAS2557->dev, "TAS2557 misc fail: %d\n", ret); + + dev_info(pTAS2557->dev, "%s, leave\n", __func__); + + return ret; +} + +int tas2557_deregister_misc(struct tas2557_priv *pTAS2557) +{ + misc_deregister(&tas2557_misc); + return 0; +} + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS2557 Misc Smart Amplifier driver"); +MODULE_LICENSE("GPL v2"); +#endif diff --git a/sound/soc/codecs/tas2557-misc.h b/sound/soc/codecs/tas2557-misc.h new file mode 100644 index 0000000000000..99a240c168ed1 --- /dev/null +++ b/sound/soc/codecs/tas2557-misc.h @@ -0,0 +1,58 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-misc.h +** +** Description: +** header file for tas2557-misc.c +** +** ============================================================================= +*/ + +#ifndef _TAS2557_MISC_H +#define _TAS2557_MISC_H + +#define FW_NAME_SIZE 64 +#define FW_DESCRIPTION_SIZE 256 +#define PROGRAM_BUF_SIZE (5 + FW_NAME_SIZE + FW_DESCRIPTION_SIZE) +#define CONFIGURATION_BUF_SIZE (8 + FW_NAME_SIZE + FW_DESCRIPTION_SIZE) + +#define TIAUDIO_CMD_REG_WITE 1 +#define TIAUDIO_CMD_REG_READ 2 +#define TIAUDIO_CMD_DEBUG_ON 3 +#define TIAUDIO_CMD_PROGRAM 4 +#define TIAUDIO_CMD_CONFIGURATION 5 +#define TIAUDIO_CMD_FW_TIMESTAMP 6 +#define TIAUDIO_CMD_CALIBRATION 7 +#define TIAUDIO_CMD_SAMPLERATE 8 +#define TIAUDIO_CMD_BITRATE 9 +#define TIAUDIO_CMD_DACVOLUME 10 +#define TIAUDIO_CMD_SPEAKER 11 +#define TIAUDIO_CMD_FW_RELOAD 12 + +#define TAS2557_MAGIC_NUMBER 0x32353537 /* '2557' */ + +#define SMARTPA_SPK_DAC_VOLUME _IOWR(TAS2557_MAGIC_NUMBER, 1, unsigned long) +#define SMARTPA_SPK_POWER_ON _IOWR(TAS2557_MAGIC_NUMBER, 2, unsigned long) +#define SMARTPA_SPK_POWER_OFF _IOWR(TAS2557_MAGIC_NUMBER, 3, unsigned long) +#define SMARTPA_SPK_SWITCH_PROGRAM _IOWR(TAS2557_MAGIC_NUMBER, 4, unsigned long) +#define SMARTPA_SPK_SWITCH_CONFIGURATION _IOWR(TAS2557_MAGIC_NUMBER, 5, unsigned long) +#define SMARTPA_SPK_SWITCH_CALIBRATION _IOWR(TAS2557_MAGIC_NUMBER, 6, unsigned long) +#define SMARTPA_SPK_SET_SAMPLERATE _IOWR(TAS2557_MAGIC_NUMBER, 7, unsigned long) +#define SMARTPA_SPK_SET_BITRATE _IOWR(TAS2557_MAGIC_NUMBER, 8, unsigned long) + +int tas2557_register_misc(struct tas2557_priv *pTAS2557); +int tas2557_deregister_misc(struct tas2557_priv *pTAS2557); + +#endif /* _TAS2557_MISC_H */ diff --git a/sound/soc/codecs/tas2557-regmap.c b/sound/soc/codecs/tas2557-regmap.c new file mode 100644 index 0000000000000..ea74971d4176a --- /dev/null +++ b/sound/soc/codecs/tas2557-regmap.c @@ -0,0 +1,905 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557-regmap.c +** +** Description: +** I2C driver with regmap for Texas Instruments TAS2557 High Performance 4W Smart Amplifier +** +** ============================================================================= +*/ + +#ifdef CONFIG_TAS2557_REGMAP + +#define DEBUG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tas2557.h" +#include "tas2557-core.h" + +#ifdef CONFIG_TAS2557_CODEC +#include "tas2557-codec.h" +#endif + +#ifdef CONFIG_TAS2557_MISC +#include "tas2557-misc.h" +#endif + +#define ENABLE_TILOAD +#ifdef ENABLE_TILOAD +#include "tiload.h" +#endif + +#define LOW_TEMPERATURE_GAIN 6 +#define LOW_TEMPERATURE_COUNTER 12 + +static int tas2557_change_book_page( + struct tas2557_priv *pTAS2557, + unsigned char nBook, + unsigned char nPage) +{ + int nResult = 0; + + if ((pTAS2557->mnCurrentBook == nBook) + && pTAS2557->mnCurrentPage == nPage) + goto end; + + if (pTAS2557->mnCurrentBook != nBook) { + nResult = regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_PAGE, 0); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + goto end; + } + pTAS2557->mnCurrentPage = 0; + nResult = regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_REG, nBook); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + goto end; + } + pTAS2557->mnCurrentBook = nBook; + if (nPage != 0) { + nResult = regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_PAGE, nPage); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + goto end; + } + pTAS2557->mnCurrentPage = nPage; + } + } else if (pTAS2557->mnCurrentPage != nPage) { + nResult = regmap_write(pTAS2557->mpRegmap, TAS2557_BOOKCTL_PAGE, nPage); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + goto end; + } + pTAS2557->mnCurrentPage = nPage; + } + +end: + if (nResult < 0) + pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM; + else + pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM; + + return nResult; +} + +static int tas2557_dev_read( + struct tas2557_priv *pTAS2557, + unsigned int nRegister, + unsigned int *pValue) +{ + int nResult = 0; + unsigned int Value = 0; + + mutex_lock(&pTAS2557->dev_lock); + + if (pTAS2557->mbTILoadActive) { + if (!(nRegister & 0x80000000)) + goto end; /* let only reads from TILoad pass. */ + nRegister &= ~0x80000000; + + dev_dbg(pTAS2557->dev, "TiLoad R REG B[%d]P[%d]R[%d]\n", + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister), + TAS2557_PAGE_REG(nRegister)); + } + + nResult = tas2557_change_book_page(pTAS2557, + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister)); + if (nResult >= 0) { + nResult = regmap_read(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), &Value); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM; + goto end; + } else + pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM; + *pValue = Value; + } + +end: + + mutex_unlock(&pTAS2557->dev_lock); + return nResult; +} + +static int tas2557_dev_write( + struct tas2557_priv *pTAS2557, + unsigned int nRegister, + unsigned int nValue) +{ + int nResult = 0; + + mutex_lock(&pTAS2557->dev_lock); + if ((nRegister == 0xAFFEAFFE) && (nValue == 0xBABEBABE)) { + pTAS2557->mbTILoadActive = true; + goto end; + } + + if ((nRegister == 0xBABEBABE) && (nValue == 0xAFFEAFFE)) { + pTAS2557->mbTILoadActive = false; + goto end; + } + + if (pTAS2557->mbTILoadActive) { + if (!(nRegister & 0x80000000)) + goto end;/* let only writes from TILoad pass. */ + nRegister &= ~0x80000000; + + dev_dbg(pTAS2557->dev, "TiLoad W REG B[%d]P[%d]R[%d] =0x%x\n", + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister), + TAS2557_PAGE_REG(nRegister), + nValue); + } + + nResult = tas2557_change_book_page(pTAS2557, + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister)); + if (nResult >= 0) { + nResult = regmap_write(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), nValue); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM; + } else + pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM; + } + +end: + + mutex_unlock(&pTAS2557->dev_lock); + + return nResult; +} + +static int tas2557_dev_bulk_read( + struct tas2557_priv *pTAS2557, + unsigned int nRegister, + u8 *pData, + unsigned int nLength) +{ + int nResult = 0; + + mutex_lock(&pTAS2557->dev_lock); + if (pTAS2557->mbTILoadActive) { + if (!(nRegister & 0x80000000)) + goto end; /* let only writes from TILoad pass. */ + + nRegister &= ~0x80000000; + dev_dbg(pTAS2557->dev, "TiLoad BR REG B[%d]P[%d]R[%d], count=%d\n", + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister), + TAS2557_PAGE_REG(nRegister), + nLength); + } + + nResult = tas2557_change_book_page(pTAS2557, + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister)); + if (nResult >= 0) { + nResult = regmap_bulk_read(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), pData, nLength); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM; + } else + pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM; + } + +end: + + mutex_unlock(&pTAS2557->dev_lock); + return nResult; +} + +static int tas2557_dev_bulk_write( + struct tas2557_priv *pTAS2557, + unsigned int nRegister, + u8 *pData, + unsigned int nLength) +{ + int nResult = 0; + + mutex_lock(&pTAS2557->dev_lock); + if (pTAS2557->mbTILoadActive) { + if (!(nRegister & 0x80000000)) + goto end; /* let only writes from TILoad pass. */ + + nRegister &= ~0x80000000; + + dev_dbg(pTAS2557->dev, "TiLoad BW REG B[%d]P[%d]R[%d], count=%d\n", + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister), + TAS2557_PAGE_REG(nRegister), + nLength); + } + + nResult = tas2557_change_book_page(pTAS2557, + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister)); + if (nResult >= 0) { + nResult = regmap_bulk_write(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), pData, nLength); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM; + } else + pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM; + } + +end: + + mutex_unlock(&pTAS2557->dev_lock); + return nResult; +} + +static int tas2557_dev_update_bits( + struct tas2557_priv *pTAS2557, + unsigned int nRegister, + unsigned int nMask, + unsigned int nValue) +{ + int nResult = 0; + + mutex_lock(&pTAS2557->dev_lock); + + if (pTAS2557->mbTILoadActive) { + if (!(nRegister & 0x80000000)) + goto end; /* let only writes from TILoad pass. */ + + nRegister &= ~0x80000000; + dev_dbg(pTAS2557->dev, "TiLoad SB REG B[%d]P[%d]R[%d], mask=0x%x, value=0x%x\n", + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister), + TAS2557_PAGE_REG(nRegister), + nMask, nValue); + } + + nResult = tas2557_change_book_page(pTAS2557, + TAS2557_BOOK_ID(nRegister), + TAS2557_PAGE_ID(nRegister)); + if (nResult >= 0) { + nResult = regmap_update_bits(pTAS2557->mpRegmap, TAS2557_PAGE_REG(nRegister), nMask, nValue); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s, %d, I2C error %d\n", + __func__, __LINE__, nResult); + pTAS2557->mnErrCode |= ERROR_DEVA_I2C_COMM; + } else + pTAS2557->mnErrCode &= ~ERROR_DEVA_I2C_COMM; + } + +end: + mutex_unlock(&pTAS2557->dev_lock); + return nResult; +} + +void tas2557_clearIRQ(struct tas2557_priv *pTAS2557) +{ + unsigned int nValue; + int nResult = 0; + + nResult = pTAS2557->read(pTAS2557, TAS2557_FLAGS_1, &nValue); + if (nResult >= 0) + pTAS2557->read(pTAS2557, TAS2557_FLAGS_2, &nValue); + +} + + +void tas2557_enableIRQ(struct tas2557_priv *pTAS2557, bool enable) +{ + if (enable) { + if (!pTAS2557->mbIRQEnable) { + if (gpio_is_valid(pTAS2557->mnGpioINT)) { + enable_irq(pTAS2557->mnIRQ); + /* check after 10 ms */ + schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(10)); + pTAS2557->mbIRQEnable = true; + } + } + } else { + if (gpio_is_valid(pTAS2557->mnGpioINT)) + disable_irq_nosync(pTAS2557->mnIRQ); + pTAS2557->mbIRQEnable = false; + } +} + +static void tas2557_hw_reset(struct tas2557_priv *pTAS2557) +{ + if (gpio_is_valid(pTAS2557->mnResetGPIO)) { + gpio_direction_output(pTAS2557->mnResetGPIO, 0); + msleep(5); + gpio_direction_output(pTAS2557->mnResetGPIO, 1); + msleep(2); + } + + pTAS2557->mnCurrentBook = -1; + pTAS2557->mnCurrentPage = -1; + if (pTAS2557->mnErrCode) + dev_info(pTAS2557->dev, "before reset, ErrCode=0x%x\n", pTAS2557->mnErrCode); + pTAS2557->mnErrCode = 0; +} + +static void irq_work_routine(struct work_struct *work) +{ + int nResult = 0; + unsigned int nDevInt1Status = 0, nDevInt2Status = 0; + unsigned int nDevPowerUpFlag = 0; + int nCounter = 2; + struct tas2557_priv *pTAS2557 = + container_of(work, struct tas2557_priv, irq_work.work); + +#ifdef CONFIG_TAS2557_CODEC + mutex_lock(&pTAS2557->codec_lock); +#endif + +#ifdef CONFIG_TAS2557_MISC + mutex_lock(&pTAS2557->file_lock); +#endif + +#ifdef I2C_RESTART + if (pTAS2557->mnErrCode == ERROR_FAILSAFE) + goto program; +#endif + if (pTAS2557->mbRuntimeSuspend) { + dev_info(pTAS2557->dev, "%s, Runtime Suspended\n", __func__); + goto end; + } + + if (!pTAS2557->mbPowerUp) { + dev_info(pTAS2557->dev, "%s, device not powered\n", __func__); + goto end; + } + + if ((!pTAS2557->mpFirmware->mnConfigurations) + || (!pTAS2557->mpFirmware->mnPrograms)) { + dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + goto end; + } + + nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_1, &nDevInt1Status); + if (nResult >= 0) + nResult = tas2557_dev_read(pTAS2557, TAS2557_FLAGS_2, &nDevInt2Status); + + if (nResult < 0) + goto program; + + if (((nDevInt1Status & 0xfc) != 0) || ((nDevInt2Status & 0x0c) != 0)) { + /* in case of INT_OC, INT_UV, INT_OT, INT_BO, INT_CL, INT_CLK1, INT_CLK2 */ + dev_err(pTAS2557->dev, "critical error: 0x%x, 0x%x\n", nDevInt1Status, nDevInt2Status); + if (nDevInt1Status & 0x80) { + pTAS2557->mnErrCode |= ERROR_OVER_CURRENT; + dev_err(pTAS2557->dev, "DEVA SPK over current!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_OVER_CURRENT; + + if (nDevInt1Status & 0x40) { + pTAS2557->mnErrCode |= ERROR_UNDER_VOLTAGE; + dev_err(pTAS2557->dev, "DEVA SPK under voltage!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_UNDER_VOLTAGE; + + if (nDevInt1Status & 0x20) { + pTAS2557->mnErrCode |= ERROR_CLK_HALT; + dev_err(pTAS2557->dev, "DEVA clk halted!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_CLK_HALT; + + if (nDevInt1Status & 0x10) { + pTAS2557->mnErrCode |= ERROR_DIE_OVERTEMP; + dev_err(pTAS2557->dev, "DEVA die over temperature!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_DIE_OVERTEMP; + + if (nDevInt1Status & 0x08) { + pTAS2557->mnErrCode |= ERROR_BROWNOUT; + dev_err(pTAS2557->dev, "DEVA brownout!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_BROWNOUT; + + if (nDevInt1Status & 0x04) { + pTAS2557->mnErrCode |= ERROR_CLK_LOST; + dev_err(pTAS2557->dev, "DEVA clock lost!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_CLK_LOST; + + if (nDevInt2Status & 0x08) { + pTAS2557->mnErrCode |= ERROR_CLK_DET1; + dev_err(pTAS2557->dev, "DEVA clk detection 1!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_CLK_DET1; + + if (nDevInt2Status & 0x04) { + pTAS2557->mnErrCode |= ERROR_CLK_DET2; + dev_err(pTAS2557->dev, "DEVA clk detection 2!\n"); + } else + pTAS2557->mnErrCode &= ~ERROR_CLK_DET2; + + goto program; + } else { + dev_dbg(pTAS2557->dev, "IRQ Status: 0x%x, 0x%x\n", nDevInt1Status, nDevInt2Status); + nCounter = 2; + while (nCounter > 0) { + nResult = tas2557_dev_read(pTAS2557, TAS2557_POWER_UP_FLAG_REG, &nDevPowerUpFlag); + if (nResult < 0) + goto program; + if ((nDevPowerUpFlag & 0xc0) == 0xc0) + break; + nCounter--; + if (nCounter > 0) { + /* in case check pow status just after power on TAS2557 */ + dev_dbg(pTAS2557->dev, "PowSts: 0x%x, check again after 10ms\n", + nDevPowerUpFlag); + msleep(10); + } + } + if ((nDevPowerUpFlag & 0xc0) != 0xc0) { + dev_err(pTAS2557->dev, "%s, Critical ERROR B[%d]_P[%d]_R[%d]= 0x%x\n", + __func__, + TAS2557_BOOK_ID(TAS2557_POWER_UP_FLAG_REG), + TAS2557_PAGE_ID(TAS2557_POWER_UP_FLAG_REG), + TAS2557_PAGE_REG(TAS2557_POWER_UP_FLAG_REG), + nDevPowerUpFlag); + pTAS2557->mnErrCode |= ERROR_CLASSD_PWR; + goto program; + } + pTAS2557->mnErrCode &= ~ERROR_CLASSD_PWR; + + dev_dbg(pTAS2557->dev, "%s: INT1=0x%x, INT2=0x%x; PowerUpFlag=0x%x\n", + __func__, nDevInt1Status, nDevInt2Status, nDevPowerUpFlag); + goto end; + } + +program: + /* hardware reset and reload */ + tas2557_set_program(pTAS2557, pTAS2557->mnCurrentProgram, pTAS2557->mnCurrentConfiguration); + +end: + +#ifdef CONFIG_TAS2557_MISC + mutex_unlock(&pTAS2557->file_lock); +#endif + +#ifdef CONFIG_TAS2557_CODEC + mutex_unlock(&pTAS2557->codec_lock); +#endif +} + +static irqreturn_t tas2557_irq_handler(int irq, void *dev_id) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)dev_id; + + tas2557_enableIRQ(pTAS2557, false); + /* get IRQ status after 100 ms */ + schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(100)); + return IRQ_HANDLED; +} + +static enum hrtimer_restart temperature_timer_func(struct hrtimer *timer) +{ + struct tas2557_priv *pTAS2557 = container_of(timer, struct tas2557_priv, mtimer); + + if (pTAS2557->mbPowerUp) { + schedule_work(&pTAS2557->mtimerwork); + schedule_delayed_work(&pTAS2557->irq_work, msecs_to_jiffies(1)); + } + return HRTIMER_NORESTART; +} + +static void timer_work_routine(struct work_struct *work) +{ + struct tas2557_priv *pTAS2557 = container_of(work, struct tas2557_priv, mtimerwork); + int nResult, nTemp, nActTemp; + struct TProgram *pProgram; + static int nAvg; + +#ifdef CONFIG_TAS2557_CODEC + mutex_lock(&pTAS2557->codec_lock); +#endif + +#ifdef CONFIG_TAS2557_MISC + mutex_lock(&pTAS2557->file_lock); +#endif + + if (pTAS2557->mbRuntimeSuspend) { + dev_info(pTAS2557->dev, "%s, Runtime Suspended\n", __func__); + goto end; + } + + if (!pTAS2557->mpFirmware->mnConfigurations) { + dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + goto end; + } + + pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]); + if (!pTAS2557->mbPowerUp + || (pProgram->mnAppMode != TAS2557_APP_TUNINGMODE)) { + dev_info(pTAS2557->dev, "%s, pass, Pow=%d, program=%s\n", + __func__, pTAS2557->mbPowerUp, pProgram->mpName); + goto end; + } + + nResult = tas2557_get_die_temperature(pTAS2557, &nTemp); + if (nResult >= 0) { + nActTemp = (int)(nTemp >> 23); + dev_dbg(pTAS2557->dev, "Die=0x%x, degree=%d\n", nTemp, nActTemp); + if (!pTAS2557->mnDieTvReadCounter) + nAvg = 0; + pTAS2557->mnDieTvReadCounter++; + nAvg += nActTemp; + if (!(pTAS2557->mnDieTvReadCounter % LOW_TEMPERATURE_COUNTER)) { + nAvg /= LOW_TEMPERATURE_COUNTER; + dev_dbg(pTAS2557->dev, "check : avg=%d\n", nAvg); + if ((nAvg & 0x80000000) != 0) { + /* if Die temperature is below ZERO */ + if (pTAS2557->mnDevCurrentGain != LOW_TEMPERATURE_GAIN) { + nResult = tas2557_set_DAC_gain(pTAS2557, LOW_TEMPERATURE_GAIN); + if (nResult < 0) + goto end; + pTAS2557->mnDevCurrentGain = LOW_TEMPERATURE_GAIN; + dev_dbg(pTAS2557->dev, "LOW Temp: set gain to %d\n", LOW_TEMPERATURE_GAIN); + } + } else if (nAvg > 5) { + /* if Die temperature is above 5 degree C */ + if (pTAS2557->mnDevCurrentGain != pTAS2557->mnDevGain) { + nResult = tas2557_set_DAC_gain(pTAS2557, pTAS2557->mnDevGain); + if (nResult < 0) + goto end; + pTAS2557->mnDevCurrentGain = pTAS2557->mnDevGain; + dev_dbg(pTAS2557->dev, "LOW Temp: set gain to original\n"); + } + } + nAvg = 0; + } + + if (pTAS2557->mbPowerUp) + hrtimer_start(&pTAS2557->mtimer, + ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL); + } + +end: + +#ifdef CONFIG_TAS2557_MISC + mutex_unlock(&pTAS2557->file_lock); +#endif + +#ifdef CONFIG_TAS2557_CODEC + mutex_unlock(&pTAS2557->codec_lock); +#endif +} + +static int tas2557_runtime_suspend(struct tas2557_priv *pTAS2557) +{ + dev_dbg(pTAS2557->dev, "%s\n", __func__); + + pTAS2557->mbRuntimeSuspend = true; + + if (hrtimer_active(&pTAS2557->mtimer)) { + dev_dbg(pTAS2557->dev, "cancel die temp timer\n"); + hrtimer_cancel(&pTAS2557->mtimer); + } + if (work_pending(&pTAS2557->mtimerwork)) { + dev_dbg(pTAS2557->dev, "cancel timer work\n"); + cancel_work_sync(&pTAS2557->mtimerwork); + } + if (delayed_work_pending(&pTAS2557->irq_work)) { + dev_dbg(pTAS2557->dev, "cancel IRQ work\n"); + cancel_delayed_work_sync(&pTAS2557->irq_work); + } + + return 0; +} + +static int tas2557_runtime_resume(struct tas2557_priv *pTAS2557) +{ + struct TProgram *pProgram; + + dev_dbg(pTAS2557->dev, "%s\n", __func__); + if (!pTAS2557->mpFirmware->mpPrograms) { + dev_dbg(pTAS2557->dev, "%s, firmware not loaded\n", __func__); + goto end; + } + + if (pTAS2557->mnCurrentProgram >= pTAS2557->mpFirmware->mnPrograms) { + dev_err(pTAS2557->dev, "%s, firmware corrupted\n", __func__); + goto end; + } + + pProgram = &(pTAS2557->mpFirmware->mpPrograms[pTAS2557->mnCurrentProgram]); + if (pTAS2557->mbPowerUp && (pProgram->mnAppMode == TAS2557_APP_TUNINGMODE)) { + if (!hrtimer_active(&pTAS2557->mtimer)) { + dev_dbg(pTAS2557->dev, "%s, start Die Temp check timer\n", __func__); + pTAS2557->mnDieTvReadCounter = 0; + hrtimer_start(&pTAS2557->mtimer, + ns_to_ktime((u64)LOW_TEMPERATURE_CHECK_PERIOD * NSEC_PER_MSEC), HRTIMER_MODE_REL); + } + } + + pTAS2557->mbRuntimeSuspend = false; +end: + + return 0; +} + +static bool tas2557_volatile(struct device *pDev, unsigned int nRegister) +{ + return true; +} + +static bool tas2557_writeable(struct device *pDev, unsigned int nRegister) +{ + return true; +} + +static const struct regmap_config tas2557_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .writeable_reg = tas2557_writeable, + .volatile_reg = tas2557_volatile, + .cache_type = REGCACHE_NONE, + .max_register = 128, +}; + +/* tas2557_i2c_probe : +* platform dependent +* should implement hardware reset functionality +*/ +static int tas2557_i2c_probe(struct i2c_client *pClient, + const struct i2c_device_id *pID) +{ + struct tas2557_priv *pTAS2557; + int nResult = 0; + unsigned int nValue = 0; + const char *pFWName; + struct pinctrl_state *set_state; + + dev_info(&pClient->dev, "%s enter\n", __func__); + + pTAS2557 = devm_kzalloc(&pClient->dev, sizeof(struct tas2557_priv), GFP_KERNEL); + if (!pTAS2557) { + nResult = -ENOMEM; + goto err; + } + + pTAS2557->dev = &pClient->dev; + i2c_set_clientdata(pClient, pTAS2557); + dev_set_drvdata(&pClient->dev, pTAS2557); + + pTAS2557->mpRegmap = devm_regmap_init_i2c(pClient, &tas2557_i2c_regmap); + if (IS_ERR(pTAS2557->mpRegmap)) { + nResult = PTR_ERR(pTAS2557->mpRegmap); + dev_err(&pClient->dev, "Failed to allocate register map: %d\n", + nResult); + goto err; + } + + if (pClient->dev.of_node) + tas2557_parse_dt(&pClient->dev, pTAS2557); + + if (gpio_is_valid(pTAS2557->mnResetGPIO)) { + nResult = gpio_request(pTAS2557->mnResetGPIO, "TAS2557-RESET"); + if (nResult < 0) { + dev_err(pTAS2557->dev, "%s: GPIO %d request error\n", + __func__, pTAS2557->mnResetGPIO); + goto err; + } + tas2557_hw_reset(pTAS2557); + } + + set_state = pinctrl_lookup_state(devm_pinctrl_get(pTAS2557->dev), "smartpa_irq_active"); + if (IS_ERR(set_state)) + printk(" \n cannot get smartpa pinctrl state\n"); + else + pinctrl_select_state(devm_pinctrl_get(pTAS2557->dev), set_state); + + + pTAS2557->read = tas2557_dev_read; + pTAS2557->write = tas2557_dev_write; + pTAS2557->bulk_read = tas2557_dev_bulk_read; + pTAS2557->bulk_write = tas2557_dev_bulk_write; + pTAS2557->update_bits = tas2557_dev_update_bits; + pTAS2557->enableIRQ = tas2557_enableIRQ; + pTAS2557->clearIRQ = tas2557_clearIRQ; + pTAS2557->set_config = tas2557_set_config; + pTAS2557->set_calibration = tas2557_set_calibration; + pTAS2557->hw_reset = tas2557_hw_reset; + pTAS2557->runtime_suspend = tas2557_runtime_suspend; + pTAS2557->runtime_resume = tas2557_runtime_resume; + +#ifdef I2C_RESTART + pTAS2557->mnRestart = 0; +#endif + mutex_init(&pTAS2557->dev_lock); + + /* Reset the chip */ + nResult = tas2557_dev_write(pTAS2557, TAS2557_SW_RESET_REG, 0x01); + if (nResult < 0) { + dev_err(&pClient->dev, "I2c fail, %d\n", nResult); + goto err; + } + + msleep(1); + tas2557_dev_read(pTAS2557, TAS2557_REV_PGID_REG, &nValue); + pTAS2557->mnPGID = nValue; + if (pTAS2557->mnPGID == TAS2557_PG_VERSION_2P1) { + dev_info(pTAS2557->dev, "PG2.1 Silicon found\n"); + pFWName = TAS2557_FW_NAME; + } else if (pTAS2557->mnPGID == TAS2557_PG_VERSION_1P0) { + dev_info(pTAS2557->dev, "PG1.0 Silicon found\n"); + pFWName = TAS2557_PG1P0_FW_NAME; + } else { + nResult = -ENOTSUPP; + dev_info(pTAS2557->dev, "unsupport Silicon 0x%x\n", pTAS2557->mnPGID); + goto err; + } + + if (gpio_is_valid(pTAS2557->mnGpioINT)) { + nResult = gpio_request(pTAS2557->mnGpioINT, "TAS2557-IRQ"); + if (nResult < 0) { + dev_err(pTAS2557->dev, + "%s: GPIO %d request INT error\n", + __func__, pTAS2557->mnGpioINT); + goto err; + } + + gpio_direction_input(pTAS2557->mnGpioINT); + pTAS2557->mnIRQ = gpio_to_irq(pTAS2557->mnGpioINT); + dev_dbg(pTAS2557->dev, "irq = %d\n", pTAS2557->mnIRQ); + INIT_DELAYED_WORK(&pTAS2557->irq_work, irq_work_routine); + nResult = request_threaded_irq(pTAS2557->mnIRQ, tas2557_irq_handler, + NULL, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + pClient->name, pTAS2557); + if (nResult < 0) { + dev_err(pTAS2557->dev, + "request_irq failed, %d\n", nResult); + goto err; + } + disable_irq_nosync(pTAS2557->mnIRQ); + } + + pTAS2557->mpFirmware = devm_kzalloc(&pClient->dev, sizeof(struct TFirmware), GFP_KERNEL); + if (!pTAS2557->mpFirmware) { + nResult = -ENOMEM; + goto err; + } + + pTAS2557->mpCalFirmware = devm_kzalloc(&pClient->dev, sizeof(struct TFirmware), GFP_KERNEL); + if (!pTAS2557->mpCalFirmware) { + nResult = -ENOMEM; + goto err; + } + +#ifdef CONFIG_TAS2557_CODEC + mutex_init(&pTAS2557->codec_lock); + tas2557_register_codec(pTAS2557); +#endif + +#ifdef CONFIG_TAS2557_MISC + mutex_init(&pTAS2557->file_lock); + tas2557_register_misc(pTAS2557); +#endif + +#ifdef ENABLE_TILOAD + tiload_driver_init(pTAS2557); +#endif + + hrtimer_init(&pTAS2557->mtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + pTAS2557->mtimer.function = temperature_timer_func; + INIT_WORK(&pTAS2557->mtimerwork, timer_work_routine); + + nResult = request_firmware_nowait(THIS_MODULE, 1, pFWName, + pTAS2557->dev, GFP_KERNEL, pTAS2557, tas2557_fw_ready); + +err: + + return nResult; +} + +static int tas2557_i2c_remove(struct i2c_client *pClient) +{ + struct tas2557_priv *pTAS2557 = i2c_get_clientdata(pClient); + + dev_info(pTAS2557->dev, "%s\n", __func__); + +#ifdef CONFIG_TAS2557_CODEC + tas2557_deregister_codec(pTAS2557); + mutex_destroy(&pTAS2557->codec_lock); +#endif + +#ifdef CONFIG_TAS2557_MISC + tas2557_deregister_misc(pTAS2557); + mutex_destroy(&pTAS2557->file_lock); +#endif + + mutex_destroy(&pTAS2557->dev_lock); + return 0; +} + +static const struct i2c_device_id tas2557_i2c_id[] = { + {"tas2557", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tas2557_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id tas2557_of_match[] = { + {.compatible = "ti,tas2557"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, tas2557_of_match); +#endif + +static struct i2c_driver tas2557_i2c_driver = { + .driver = { + .name = "tas2557", + .owner = THIS_MODULE, +#if defined(CONFIG_OF) + .of_match_table = of_match_ptr(tas2557_of_match), +#endif + }, + .probe = tas2557_i2c_probe, + .remove = tas2557_i2c_remove, + .id_table = tas2557_i2c_id, +}; + +module_i2c_driver(tas2557_i2c_driver); + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TAS2557 I2C Smart Amplifier driver"); +MODULE_LICENSE("GPL v2"); + +#endif diff --git a/sound/soc/codecs/tas2557.h b/sound/soc/codecs/tas2557.h new file mode 100644 index 0000000000000..d20d0727be044 --- /dev/null +++ b/sound/soc/codecs/tas2557.h @@ -0,0 +1,489 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tas2557.h +** +** Description: +** definitions and data structures for TAS2557 Android Linux driver +** +** ============================================================================= +*/ + +#ifndef _TAS2557_H +#define _TAS2557_H + +#include +#include +#include + +#define I2C_RESTART + +/* Page Control Register */ +#define TAS2557_PAGECTL_REG 0 + +/* Book Control Register (available in page0 of each book) */ +#define TAS2557_BOOKCTL_PAGE 0 +#define TAS2557_BOOKCTL_REG 127 + +/* 0000 0000 0BBB BBBB BPPP PPPP PRRR RRRR */ + +#define TAS2557_REG(book, page, reg) ((((unsigned int)book * 256 * 128) + \ + ((unsigned int)page * 128)) + reg) + +#define TAS2557_BOOK_ID(reg) ((unsigned char)(reg / (256 * 128))) +#define TAS2557_PAGE_ID(reg) ((unsigned char)((reg % (256 * 128)) / 128)) +#define TAS2557_BOOK_REG(reg) ((unsigned char)(reg % (256 * 128))) +#define TAS2557_PAGE_REG(reg) ((unsigned char)((reg % (256 * 128)) % 128)) + +/* Book0, Page0 registers */ +#define TAS2557_SW_RESET_REG TAS2557_REG(0, 0, 1) + +#define TAS2557_REV_PGID_REG TAS2557_REG(0, 0, 3) +#define TAS2557_PG_VERSION_1P0 0x80 +#define TAS2557_PG_VERSION_2P0 0x90 +#define TAS2557_PG_VERSION_2P1 0xa0 + +#define TAS2557_POWER_CTRL1_REG TAS2557_REG(0, 0, 4) +#define TAS2557_POWER_CTRL2_REG TAS2557_REG(0, 0, 5) + +#define TAS2557_SPK_CTRL_REG TAS2557_REG(0, 0, 6) +/* B0P0R6 - TAS2557_SPK_CTRL_REG */ +#define TAS2557_DAC_GAIN_MASK (0xf << 3) +#define TAS2557_DAC_GAIN_SHIFT 0x03 + +#define TAS2557_MUTE_REG TAS2557_REG(0, 0, 7) +#define TAS2557_SNS_CTRL_REG TAS2557_REG(0, 0, 8) +#define TAS2557_ADC_INPUT_SEL_REG TAS2557_REG(0, 0, 9) +#define TAS2557_DBOOST_CTL_REG TAS2557_REG(0, 0, 10) +#define TAS2557_NONAME11_REG TAS2557_REG(0, 0, 11) +#define TAS2557_NONAME12_REG TAS2557_REG(0, 0, 12) +#define TAS2557_NONAME13_REG TAS2557_REG(0, 0, 13) +#define TAS2557_NONAME14_REG TAS2557_REG(0, 0, 14) +#define TAS2557_NONAME15_REG TAS2557_REG(0, 0, 15) +#define TAS2557_NONAME16_REG TAS2557_REG(0, 0, 16) +#define TAS2557_NONAME17_REG TAS2557_REG(0, 0, 17) +#define TAS2557_NONAME18_REG TAS2557_REG(0, 0, 18) +#define TAS2557_SAR_SAMPLING_TIME_REG TAS2557_REG(0, 0, 19) +#define TAS2557_SAR_ADC1_REG TAS2557_REG(0, 0, 20) +#define TAS2557_SAR_ADC2_REG TAS2557_REG(0, 0, 21) /* B0_P0_R0x15*/ +#define TAS2557_CRC_CHECKSUM_REG TAS2557_REG(0, 0, 32) +#define TAS2557_CRC_RESET_REG TAS2557_REG(0, 0, 33) +#define TAS2557_DSP_MODE_SELECT_REG TAS2557_REG(0, 0, 34) +#define TAS2557_SAFE_GUARD_REG TAS2557_REG(0, 0, 37) +#define TAS2557_ASI_CTL1_REG TAS2557_REG(0, 0, 42) +#define TAS2557_CLK_ERR_CTRL TAS2557_REG(0, 0, 44) /* B0_P0_R0x2c*/ +#define TAS2557_CLK_ERR_CTRL2 TAS2557_REG(0, 0, 45) /* B0_P0_R0x2d*/ +#define TAS2557_CLK_ERR_CTRL3 TAS2557_REG(0, 0, 46) /* B0_P0_R0x2e*/ +#define TAS2557_DBOOST_CFG_REG TAS2557_REG(0, 0, 52) +#define TAS2557_POWER_UP_FLAG_REG TAS2557_REG(0, 0, 100) +#define TAS2557_FLAGS_1 TAS2557_REG(0, 0, 104) /* B0_P0_R0x68*/ +#define TAS2557_FLAGS_2 TAS2557_REG(0, 0, 108) /* B0_P0_R0x6c*/ + +/* Book0, Page1 registers */ +#define TAS2557_ASI1_DAC_FORMAT_REG TAS2557_REG(0, 1, 1) +#define TAS2557_ASI1_ADC_FORMAT_REG TAS2557_REG(0, 1, 2) +#define TAS2557_ASI1_OFFSET1_REG TAS2557_REG(0, 1, 3) +#define TAS2557_ASI1_ADC_PATH_REG TAS2557_REG(0, 1, 7) +#define TAS2557_ASI1_DAC_BCLK_REG TAS2557_REG(0, 1, 8) +#define TAS2557_ASI1_DAC_WCLK_REG TAS2557_REG(0, 1, 9) +#define TAS2557_ASI1_ADC_BCLK_REG TAS2557_REG(0, 1, 10) +#define TAS2557_ASI1_ADC_WCLK_REG TAS2557_REG(0, 1, 11) +#define TAS2557_ASI1_DIN_DOUT_MUX_REG TAS2557_REG(0, 1, 12) +#define TAS2557_ASI1_BDIV_CLK_SEL_REG TAS2557_REG(0, 1, 13) +#define TAS2557_ASI1_BDIV_CLK_RATIO_REG TAS2557_REG(0, 1, 14) +#define TAS2557_ASI1_WDIV_CLK_RATIO_REG TAS2557_REG(0, 1, 15) +#define TAS2557_ASI1_DAC_CLKOUT_REG TAS2557_REG(0, 1, 16) +#define TAS2557_ASI1_ADC_CLKOUT_REG TAS2557_REG(0, 1, 17) +#define TAS2557_ASI2_DAC_FORMAT_REG TAS2557_REG(0, 1, 21) +#define TAS2557_ASI2_ADC_FORMAT_REG TAS2557_REG(0, 1, 22) +#define TAS2557_ASI2_OFFSET1_REG TAS2557_REG(0, 1, 23) +#define TAS2557_ASI2_ADC_PATH_REG TAS2557_REG(0, 1, 27) +#define TAS2557_ASI2_DAC_BCLK_REG TAS2557_REG(0, 1, 28) +#define TAS2557_ASI2_DAC_WCLK_REG TAS2557_REG(0, 1, 29) +#define TAS2557_ASI2_ADC_BCLK_REG TAS2557_REG(0, 1, 30) +#define TAS2557_ASI2_ADC_WCLK_REG TAS2557_REG(0, 1, 31) +#define TAS2557_ASI2_DIN_DOUT_MUX_REG TAS2557_REG(0, 1, 32) +#define TAS2557_ASI2_BDIV_CLK_SEL_REG TAS2557_REG(0, 1, 33) +#define TAS2557_ASI2_BDIV_CLK_RATIO_REG TAS2557_REG(0, 1, 34) +#define TAS2557_ASI2_WDIV_CLK_RATIO_REG TAS2557_REG(0, 1, 35) +#define TAS2557_ASI2_DAC_CLKOUT_REG TAS2557_REG(0, 1, 36) +#define TAS2557_ASI2_ADC_CLKOUT_REG TAS2557_REG(0, 1, 37) +#define TAS2557_GPIO1_PIN_REG TAS2557_REG(0, 1, 61) /*B0_P1_R0x3d */ +#define TAS2557_GPIO2_PIN_REG TAS2557_REG(0, 1, 62) /*B0_P1_R0x3e */ +#define TAS2557_GPIO3_PIN_REG TAS2557_REG(0, 1, 63) /*B0_P1_R0x3f */ +#define TAS2557_GPIO4_PIN_REG TAS2557_REG(0, 1, 64) /*B0_P1_R0x40 */ +#define TAS2557_GPIO5_PIN_REG TAS2557_REG(0, 1, 65) +#define TAS2557_GPIO6_PIN_REG TAS2557_REG(0, 1, 66) +#define TAS2557_GPIO7_PIN_REG TAS2557_REG(0, 1, 67) +#define TAS2557_GPIO8_PIN_REG TAS2557_REG(0, 1, 68) +#define TAS2557_GPIO9_PIN_REG TAS2557_REG(0, 1, 69) +#define TAS2557_GPIO10_PIN_REG TAS2557_REG(0, 1, 70) +#define TAS2557_GPI_PIN_REG TAS2557_REG(0, 1, 77) /*B0_P1_R0x4d */ +#define TAS2557_GPIO_HIZ_CTRL1_REG TAS2557_REG(0, 1, 79) +#define TAS2557_GPIO_HIZ_CTRL2_REG TAS2557_REG(0, 1, 80) +#define TAS2557_GPIO_HIZ_CTRL3_REG TAS2557_REG(0, 1, 81) +#define TAS2557_GPIO_HIZ_CTRL4_REG TAS2557_REG(0, 1, 82) +#define TAS2557_GPIO_HIZ_CTRL5_REG TAS2557_REG(0, 1, 83) +#define TAS2557_BIT_BANG_CTRL_REG TAS2557_REG(0, 1, 87) +#define TAS2557_BIT_BANG_OUT1_REG TAS2557_REG(0, 1, 88) +#define TAS2557_BIT_BANG_OUT2_REG TAS2557_REG(0, 1, 89) +#define TAS2557_BIT_BANG_IN1_REG TAS2557_REG(0, 1, 90) +#define TAS2557_BIT_BANG_IN2_REG TAS2557_REG(0, 1, 91) +#define TAS2557_BIT_BANG_IN3_REG TAS2557_REG(0, 1, 92) +#define TAS2557_PDM_IN_CLK_REG TAS2557_REG(0, 1, 94) +#define TAS2557_PDM_IN_PIN_REG TAS2557_REG(0, 1, 95) +#define TAS2557_ASIM_IFACE1_REG TAS2557_REG(0, 1, 98) +#define TAS2557_ASIM_FORMAT_REG TAS2557_REG(0, 1, 99) +#define TAS2557_ASIM_IFACE3_REG TAS2557_REG(0, 1, 100) +#define TAS2557_ASIM_IFACE4_REG TAS2557_REG(0, 1, 101) +#define TAS2557_ASIM_IFACE5_REG TAS2557_REG(0, 1, 102) +#define TAS2557_ASIM_IFACE6_REG TAS2557_REG(0, 1, 103) +#define TAS2557_ASIM_IFACE7_REG TAS2557_REG(0, 1, 104) +#define TAS2557_ASIM_IFACE8_REG TAS2557_REG(0, 1, 105) +#define TAS2557_CLK_HALT_REG TAS2557_REG(0, 1, 106) /* B0_P1_R0x6a */ +#define TAS2557_INT_GEN1_REG TAS2557_REG(0, 1, 108) /* B0_P1_R0x6c */ +#define TAS2557_INT_GEN2_REG TAS2557_REG(0, 1, 109) /* B0_P1_R0x6d */ +#define TAS2557_INT_GEN3_REG TAS2557_REG(0, 1, 110) /* B0_P1_R0x6e */ +#define TAS2557_INT_GEN4_REG TAS2557_REG(0, 1, 111) /* B0_P1_R0x6f */ +#define TAS2557_INT_MODE_REG TAS2557_REG(0, 1, 114) /* B0_P1_R0x72 */ +#define TAS2557_MAIN_CLKIN_REG TAS2557_REG(0, 1, 115) +#define TAS2557_PLL_CLKIN_REG TAS2557_REG(0, 1, 116) +#define TAS2557_CLKOUT_MUX_REG TAS2557_REG(0, 1, 117) +#define TAS2557_CLKOUT_CDIV_REG TAS2557_REG(0, 1, 118) +#define TAS2557_HACK_GP01_REG TAS2557_REG(0, 1, 122) + +#define TAS2557_HACK01_REG TAS2557_REG(0, 2, 10) + +#define TAS2557_ISENSE_THRESHOLD TAS2557_REG(0, 50, 104) +#define TAS2557_BOOSTON_EFFICIENCY TAS2557_REG(0, 51, 16) +#define TAS2557_BOOSTOFF_EFFICIENCY TAS2557_REG(0, 51, 20) +#define TAS2557_BOOST_HEADROOM TAS2557_REG(0, 51, 24) +#define TAS2557_THERMAL_FOLDBACK_REG TAS2557_REG(0, 51, 100) + +#define TAS2557_SA_PG2P1_CHL_CTRL_REG TAS2557_REG(0, 53, 20) /* B0_P0x35_R0x14 */ +#define TAS2557_SA_COEFF_SWAP_REG TAS2557_REG(0, 53, 44) /* B0_P0x35_R0x2c */ + +#define TAS2557_SA_PG1P0_CHL_CTRL_REG TAS2557_REG(0, 58, 120) /* B0_P0x3a_R0x78 */ + +#define TAS2557_TEST_MODE_REG TAS2557_REG(0, 253, 13) +#define TAS2557_BROADCAST_REG TAS2557_REG(0, 253, 54) +#define TAS2557_CRYPTIC_REG TAS2557_REG(0, 253, 71) +#define TAS2557_PG2P1_CALI_R0_REG TAS2557_REG(0x8c, 0x2f, 0x40) +#define TAS2557_PG1P0_CALI_R0_REG TAS2557_REG(0x8c, 0x2f, 0x28) +#define TAS2557_PG2P1_CALI_T_REG TAS2557_REG(0x8c, 0x30, 0x20) +#define TAS2557_PG1P0_CALI_T_REG TAS2557_REG(0x8c, 0x30, 0x08) + +#define TAS2557_DAC_INTERPOL_REG TAS2557_REG(100, 0, 1) +#define TAS2557_SOFT_MUTE_REG TAS2557_REG(100, 0, 7) +#define TAS2557_PLL_P_VAL_REG TAS2557_REG(100, 0, 27) +#define TAS2557_PLL_J_VAL_REG TAS2557_REG(100, 0, 28) +#define TAS2557_PLL_D_VAL_MSB_REG TAS2557_REG(100, 0, 29) +#define TAS2557_PLL_D_VAL_LSB_REG TAS2557_REG(100, 0, 30) +#define TAS2557_CLK_MISC_REG TAS2557_REG(100, 0, 31) +#define TAS2557_PLL_N_VAL_REG TAS2557_REG(100, 0, 32) +#define TAS2557_DAC_MADC_VAL_REG TAS2557_REG(100, 0, 33) +#define TAS2557_ISENSE_DIV_REG TAS2557_REG(100, 0, 42) +#define TAS2557_RAMP_CLK_DIV_MSB_REG TAS2557_REG(100, 0, 43) +#define TAS2557_RAMP_CLK_DIV_LSB_REG TAS2557_REG(100, 0, 44) + +#define TAS2557_DIE_TEMP_REG TAS2557_REG(130, 2, 124) /* B0x82_P0x02_R0x7C */ + +/* Bits */ +/* B0P0R4 - TAS2557_POWER_CTRL1_REG */ +#define TAS2557_SW_SHUTDOWN (0x1 << 0) +#define TAS2557_MADC_POWER_UP (0x1 << 3) +#define TAS2557_MDAC_POWER_UP (0x1 << 4) +#define TAS2557_NDIV_POWER_UP (0x1 << 5) +#define TAS2557_PLL_POWER_UP (0x1 << 6) +#define TAS2557_DSP_POWER_UP (0x1 << 7) + +/* B0P0R5 - TAS2557_POWER_CTRL2_REG */ +#define TAS2557_VSENSE_ENABLE (0x1 << 0) +#define TAS2557_ISENSE_ENABLE (0x1 << 1) +#define TAS2557_BOOST_ENABLE (0x1 << 5) +#define TAS2557_CLASSD_ENABLE (0x1 << 7) + +/* B0P0R7 - TAS2557_MUTE_REG */ +#define TAS2557_CLASSD_MUTE (0x1 << 0) +#define TAS2557_ISENSE_MUTE (0x1 << 1) + +/* B0P253R13 - TAS2557_TEST_MODE_REG */ +#define TAS2557_TEST_MODE_ENABLE (13) +#define TAS2557_TEST_MODE_MASK (0xf << 0) + +/* B0P253R71 - TAS2557_CRYPTIC_REG */ +#define TAS2557_OSC_TRIM_CAP(x) ((x & 0x3f) << 0) +#define TAS2557_DISABLE_ENCRYPTION (0x1 << 6) +#define TAS2557_SL_COMP (0x1 << 7) + +/* B0P1R115/6 - TAS2557_MAIN/PLL_CLKIN_REG */ +#define TAS2557_XXX_CLKIN_GPIO1 (0) +#define TAS2557_XXX_CLKIN_GPIO2 (1) +#define TAS2557_XXX_CLKIN_GPIO3 (2) +#define TAS2557_XXX_CLKIN_GPIO4 (3) +#define TAS2557_XXX_CLKIN_GPIO5 (4) +#define TAS2557_XXX_CLKIN_GPIO6 (5) +#define TAS2557_XXX_CLKIN_GPIO7 (6) +#define TAS2557_XXX_CLKIN_GPIO8 (7) +#define TAS2557_XXX_CLKIN_GPIO9 (8) +#define TAS2557_XXX_CLKIN_GPIO10 (9) +#define TAS2557_XXX_CLKIN_GPI1 (12) +#define TAS2557_XXX_CLKIN_GPI2 (13) +#define TAS2557_XXX_CLKIN_GPI3 (14) +#define TAS2557_NDIV_CLKIN_PLL (15) +#define TAS2557_PLL_CLKIN_INT_OSC (15) + +#define TAS2557_MCLK_CLKIN_SRC_GPIO1 (0) +#define TAS2557_MCLK_CLKIN_SRC_GPIO2 (1) +#define TAS2557_MCLK_CLKIN_SRC_GPIO3 (2) +#define TAS2557_MCLK_CLKIN_SRC_GPIO4 (3) +#define TAS2557_MCLK_CLKIN_SRC_GPIO5 (4) +#define TAS2557_MCLK_CLKIN_SRC_GPIO6 (5) +#define TAS2557_MCLK_CLKIN_SRC_GPIO7 (6) +#define TAS2557_MCLK_CLKIN_SRC_GPIO8 (7) +#define TAS2557_MCLK_CLKIN_SRC_GPIO9 (8) +#define TAS2557_MCLK_CLKIN_SRC_GPIO10 (9) +#define TAS2557_MCLK_CLKIN_SRC_GPI1 (12) +#define TAS2557_MCLK_CLKIN_SRC_GPI2 (13) +#define TAS2557_MCLK_CLKIN_SRC_GPI3 (14) + +#define TAS2557_FORMAT_I2S (0x0 << 5) +#define TAS2557_FORMAT_DSP (0x1 << 5) +#define TAS2557_FORMAT_RIGHT_J (0x2 << 5) +#define TAS2557_FORMAT_LEFT_J (0x3 << 5) +#define TAS2557_FORMAT_MONO_PCM (0x4 << 5) +#define TAS2557_FORMAT_MASK (0x7 << 5) + +#define TAS2557_WORDLENGTH_16BIT (0x0 << 3) +#define TAS2557_WORDLENGTH_20BIT (0x1 << 3) +#define TAS2557_WORDLENGTH_24BIT (0x2 << 3) +#define TAS2557_WORDLENGTH_32BIT (0x3 << 3) +#define TAS2557_WORDLENGTH_MASK TAS2557_WORDLENGTH_32BIT + +/* B100P0R7 - TAS2557_SOFT_MUTE_REG */ +#define TAS2557_PDM_SOFT_MUTE (0x1 << 0) +#define TAS2557_VSENSE_SOFT_MUTE (0x1 << 1) +#define TAS2557_ISENSE_SOFT_MUTE (0x1 << 2) +#define TAS2557_CLASSD_SOFT_MUTE (0x1 << 3) + +/* B100P0R27 - TAS2557_PLL_P_VAL_REG */ +#define TAS2557_PLL_P_VAL_MASK (0x3f << 0) + +/* B100P0R28 - TAS2557_PLL_J_VAL_REG */ +#define TAS2557_PLL_J_VAL_MASK ((unsigned int) (0x7f << 0)) +#define TAS2557_PLL_J_VAL_MASKX 0x00 + +/* B100P0R29-30 - TAS2557_PLL_D_VAL_MSB/LSB_REG */ +#define TAS2557_PLL_D_MSB_VAL(x) ((x >> 8) & 0x3f) +#define TAS2557_PLL_D_LSB_VAL(x) (x & 0xff) + +/* B100P0R31 - TAS2557_CLK_MISC_REG */ +#define TAS2557_DSP_CLK_FROM_PLL (0x1 << 5) + +#define TAS2557_FW_NAME "tas2557_uCDSP.bin" +#define TAS2557_PG1P0_FW_NAME "tas2557_pg1p0_uCDSP.bin" + +#define TAS2557_APP_ROM1MODE 0 +#define TAS2557_APP_ROM2MODE 1 +#define TAS2557_APP_TUNINGMODE 2 +#define TAS2557_APP_ROM1_96KHZ 3 +#define TAS2557_APP_ROM2_96KHZ 4 +#define TAS2557_APP_RAMMODE 5 + +#define TAS2557_BOOST_OFF 0 +#define TAS2557_BOOST_DEVA 1 +#define TAS2557_BOOST_DEVB 2 +#define TAS2557_BOOST_BOTH 3 + +#define ERROR_NONE 0x00000000 +#define ERROR_PLL_ABSENT 0x00000001 +#define ERROR_DEVA_I2C_COMM 0x00000002 +#define ERROR_PRAM_CRCCHK 0x00000008 +#define ERROR_YRAM_CRCCHK 0x00000010 +#define ERROR_CLK_DET2 0x00000020 +#define ERROR_CLK_DET1 0x00000040 +#define ERROR_CLK_LOST 0x00000080 +#define ERROR_BROWNOUT 0x00000100 +#define ERROR_DIE_OVERTEMP 0x00000200 +#define ERROR_CLK_HALT 0x00000400 +#define ERROR_UNDER_VOLTAGE 0x00000800 +#define ERROR_OVER_CURRENT 0x00001000 +#define ERROR_CLASSD_PWR 0x00002000 +#define ERROR_FAILSAFE 0x40000000 + +struct TBlock { + unsigned int mnType; + unsigned char mbPChkSumPresent; + unsigned char mnPChkSum; + unsigned char mbYChkSumPresent; + unsigned char mnYChkSum; + unsigned int mnCommands; + unsigned char *mpData; +}; + +struct TData { + char mpName[64]; + char *mpDescription; + unsigned int mnBlocks; + struct TBlock *mpBlocks; +}; + +struct TProgram { + char mpName[64]; + char *mpDescription; + unsigned char mnAppMode; + unsigned short mnBoost; + struct TData mData; +}; + +struct TPLL { + char mpName[64]; + char *mpDescription; + struct TBlock mBlock; +}; + +struct TConfiguration { + char mpName[64]; + char *mpDescription; + unsigned int mnDevices; + unsigned int mnProgram; + unsigned int mnPLL; + unsigned int mnSamplingRate; + struct TData mData; +}; + +struct TCalibration { + char mpName[64]; + char *mpDescription; + unsigned int mnProgram; + unsigned int mnConfiguration; + struct TData mData; +}; + +struct TFirmware { + unsigned int mnFWSize; + unsigned int mnChecksum; + unsigned int mnPPCVersion; + unsigned int mnFWVersion; + unsigned int mnDriverVersion; + unsigned int mnTimeStamp; + char mpDDCName[64]; + char *mpDescription; + unsigned int mnDeviceFamily; + unsigned int mnDevice; + unsigned int mnPLLs; + struct TPLL *mpPLLs; + unsigned int mnPrograms; + struct TProgram *mpPrograms; + unsigned int mnConfigurations; + struct TConfiguration *mpConfigurations; + unsigned int mnCalibrations; + struct TCalibration *mpCalibrations; +}; + +struct tas2557_register { + int book; + int page; + int reg; +}; + +struct tas2557_priv { + struct device *dev; + struct regmap *mpRegmap; + int mnPGID; + int mnResetGPIO; + struct mutex dev_lock; + struct TFirmware *mpFirmware; + struct TFirmware *mpCalFirmware; + unsigned int mnCurrentProgram; + unsigned int mnCurrentSampleRate; + unsigned int mnNewConfiguration; + unsigned int mnCurrentConfiguration; + unsigned int mnCurrentCalibration; + unsigned char mnCurrentBook; + unsigned char mnCurrentPage; + bool mbTILoadActive; + bool mbPowerUp; + bool mbLoadConfigurationPrePowerUp; + bool mbLoadCalibrationPostPowerUp; + bool mbCalibrationLoaded; + int (*read)(struct tas2557_priv *pTAS2557, + unsigned int reg, + unsigned int *pValue); + int (*write)(struct tas2557_priv *pTAS2557, + unsigned int reg, + unsigned int Value); + int (*bulk_read)(struct tas2557_priv *pTAS2557, + unsigned int reg, + unsigned char *pData, + unsigned int len); + int (*bulk_write)(struct tas2557_priv *pTAS2557, + unsigned int reg, + unsigned char *pData, + unsigned int len); + int (*update_bits)(struct tas2557_priv *pTAS2557, + unsigned int reg, + unsigned int mask, + unsigned int value); + int (*set_config)(struct tas2557_priv *pTAS2557, + int config); + int (*set_calibration)(struct tas2557_priv *pTAS2557, + int calibration); + void (*clearIRQ)(struct tas2557_priv *pTAS2557); + void (*enableIRQ)(struct tas2557_priv *pTAS2557, bool enable); + void (*hw_reset)(struct tas2557_priv *pTAS2557); + /* device is working, but system is suspended */ + int (*runtime_suspend)(struct tas2557_priv *pTAS2557); + int (*runtime_resume)(struct tas2557_priv *pTAS2557); + + int mnGpioINT; + struct delayed_work irq_work; + unsigned int mnIRQ; + bool mbIRQEnable; + unsigned char mnI2SBits; + + + /* for low temperature check */ + unsigned int mnDevGain; + unsigned int mnDevCurrentGain; + unsigned int mnDieTvReadCounter; + struct hrtimer mtimer; + struct work_struct mtimerwork; + + /* device is working, but system is suspended */ + bool mbRuntimeSuspend; + + unsigned int mnErrCode; + + /* for configurations with maximum TLimit 0x7fffffff, + * bypass calibration update, usually used in factory test + */ + bool mbBypassTMax; + +#ifdef CONFIG_TAS2557_CODEC + struct mutex codec_lock; +#endif + +#ifdef CONFIG_TAS2557_MISC + int mnDBGCmd; + int mnCurrentReg; + struct mutex file_lock; +#endif + +#ifdef I2C_RESTART + int mnRestart; +#endif +}; + +#endif /* _TAS2557_H */ diff --git a/sound/soc/codecs/tiload.c b/sound/soc/codecs/tiload.c new file mode 100644 index 0000000000000..3509fe45ca8ec --- /dev/null +++ b/sound/soc/codecs/tiload.c @@ -0,0 +1,410 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tiload.c +** +** Description: +** utility for TAS2557 Android in-system tuning +** +** ============================================================================= +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tiload.h" + +/* enable debug prints in the driver */ +#define DEBUG + +static struct cdev *tiload_cdev; +static int tiload_major; /* Dynamic allocation of Mjr No. */ +static int tiload_opened; /* Dynamic allocation of Mjr No. */ +static struct tas2557_priv *g_TAS2557; +struct class *tiload_class; +static unsigned int magic_num; + +static char gPage; +static char gBook; +/******************************** Debug section *****************************/ + + +/*---------------------------------------------------------------------------- + * Function : tiload_open + * + * Purpose : open method for tiload programming interface + *---------------------------------------------------------------------------- + */ +static int tiload_open(struct inode *in, struct file *filp) +{ + struct tas2557_priv *pTAS2557 = g_TAS2557; + + dev_info(pTAS2557->dev, "%s\n", __func__); + + if (tiload_opened) { + dev_info(pTAS2557->dev, "%s device is already opened\n", "tiload"); + return -EINVAL; + } + filp->private_data = (void *)pTAS2557; + tiload_opened++; + return 0; +} + +/*---------------------------------------------------------------------------- + * Function : tiload_release + * + * Purpose : close method for tiload programming interface + *---------------------------------------------------------------------------- + */ +static int tiload_release(struct inode *in, struct file *filp) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)filp->private_data; + + dev_info(pTAS2557->dev, "%s\n", __func__); + filp->private_data = NULL; + tiload_opened--; + return 0; +} + +#define MAX_LENGTH 128 +/*---------------------------------------------------------------------------- + * Function : tiload_read + * + * Purpose : read from codec + *---------------------------------------------------------------------------- + */ +static ssize_t tiload_read(struct file *filp, char __user *buf, + size_t count, loff_t *offset) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)filp->private_data; + static char rd_data[MAX_LENGTH + 1]; + unsigned int nCompositeRegister = 0, Value = 0; + char reg_addr; + size_t size; + int ret = 0; +#ifdef DEBUG + /* int i; */ +#endif + + dev_info(pTAS2557->dev, "%s\n", __func__); + if (count > MAX_LENGTH) { + dev_err(pTAS2557->dev, "Max %d bytes can be read\n", MAX_LENGTH); + return -EINVAL; + } + + /* copy register address from user space */ + size = copy_from_user(®_addr, buf, 1); + if (size != 0) { + dev_err(pTAS2557->dev, "read: copy_from_user failure\n"); + return -EINVAL; + } + + size = count; + + nCompositeRegister = BPR_REG(gBook, gPage, reg_addr); + if (count == 1) { + ret = + pTAS2557->read(pTAS2557, 0x80000000 | nCompositeRegister, &Value); + if (ret >= 0) + rd_data[0] = (char) Value; + } else if (count > 1) { + ret = + pTAS2557->bulk_read(pTAS2557, 0x80000000 | nCompositeRegister, + rd_data, size); + } + if (ret < 0) + dev_err(pTAS2557->dev, "%s, %d, ret=%d, count=%zu error happen!\n", + __func__, __LINE__, ret, count); + +#ifdef DEBUG + dev_info(pTAS2557->dev, "read size = %d, reg_addr= %x , count = %d\n", + (int) size, reg_addr, (int) count); +/* for (i = 0; i < (int) size; i++) { +* dev_dbg(pTAS2557->dev, "rd_data[%d]=%x\n", i, rd_data[i]); +* } +*/ +#endif + if (size != count) + dev_err(pTAS2557->dev, "read %d registers from the codec\n", (int) size); + + if (copy_to_user(buf, rd_data, size) != 0) { + dev_err(pTAS2557->dev, "copy_to_user failed\n"); + return -EINVAL; + } + + return size; +} + +/* + *---------------------------------------------------------------------------- + * Function : tiload_write + * + * Purpose : write to codec + *---------------------------------------------------------------------------- + */ +static ssize_t tiload_write(struct file *filp, const char __user *buf, + size_t count, loff_t *offset) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)filp->private_data; + static char wr_data[MAX_LENGTH + 1]; + char *pData = wr_data; + size_t size; + unsigned int nCompositeRegister = 0; + unsigned int nRegister; + int ret = 0; +#ifdef DEBUG + /* int i; */ +#endif + dev_info(pTAS2557->dev, "%s\n", __func__); + + if (count > MAX_LENGTH) { + dev_err(pTAS2557->dev, "Max %d bytes can be read\n", MAX_LENGTH); + return -EINVAL; + } + + /* copy buffer from user space */ + size = copy_from_user(wr_data, buf, count); + if (size != 0) { + dev_err(pTAS2557->dev, "copy_from_user failure %d\n", (int) size); + return -EINVAL; + } +#ifdef DEBUG + dev_info(pTAS2557->dev, "write size = %zu\n", count); +/* for (i = 0; i < (int) count; i++) { +* dev_info(pTAS2557->dev, "wr_data[%d]=%x\n", i, wr_data[i]); +* } +*/ +#endif + nRegister = wr_data[0]; + size = count; + if ((nRegister == 127) && (gPage == 0)) { + gBook = wr_data[1]; + return size; + } + + if (nRegister == 0) { + gPage = wr_data[1]; + pData++; + count--; + } + + nCompositeRegister = BPR_REG(gBook, gPage, nRegister); + if (count == 2) { + ret = + pTAS2557->write(pTAS2557, 0x80000000 | nCompositeRegister, + pData[1]); + } else if (count > 2) { + ret = + pTAS2557->bulk_write(pTAS2557, 0x80000000 | nCompositeRegister, + &pData[1], count - 1); + } + + if (ret < 0) + dev_err(pTAS2557->dev, "%s, %d, ret=%d, count=%zu, ERROR Happen\n", __func__, + __LINE__, ret, count); + + return size; +} + +static void tiload_route_IO(struct tas2557_priv *pTAS2557, unsigned int bLock) +{ + if (bLock) + pTAS2557->write(pTAS2557, 0xAFFEAFFE, 0xBABEBABE); + else + pTAS2557->write(pTAS2557, 0xBABEBABE, 0xAFFEAFFE); +} + +static long tiload_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)filp->private_data; + long num = 0; + void __user *argp = (void __user *) arg; + int val; + struct BPR bpr; + + dev_info(pTAS2557->dev, "%s, cmd=0x%x\n", __func__, cmd); +/* if (_IOC_TYPE(cmd) != TILOAD_IOC_MAGIC) + * return -ENOTTY; + */ + + switch (cmd) { + case TILOAD_IOMAGICNUM_GET: + num = copy_to_user(argp, &magic_num, sizeof(int)); + break; + case TILOAD_IOMAGICNUM_SET: + num = copy_from_user(&magic_num, argp, sizeof(int)); + dev_info(pTAS2557->dev, "TILOAD_IOMAGICNUM_SET\n"); + tiload_route_IO(pTAS2557, magic_num); + break; + case TILOAD_BPR_READ: + break; + case TILOAD_BPR_WRITE: + num = copy_from_user(&bpr, argp, sizeof(struct BPR)); + dev_info(pTAS2557->dev, "TILOAD_BPR_WRITE: 0x%02X, 0x%02X, 0x%02X\n\r", bpr.nBook, + bpr.nPage, bpr.nRegister); + break; + case TILOAD_IOCTL_SET_CHL: + break; + case TILOAD_IOCTL_SET_CONFIG: + num = copy_from_user(&val, argp, sizeof(val)); + pTAS2557->set_config(pTAS2557, val); + break; + case TILOAD_IOCTL_SET_CALIBRATION: + num = copy_from_user(&val, argp, sizeof(val)); + pTAS2557->set_calibration(pTAS2557, val); + break; + default: + break; + } + return num; +} + +#ifdef CONFIG_COMPAT +static long tiload_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct tas2557_priv *pTAS2557 = (struct tas2557_priv *)filp->private_data; + long nResult = 0; + + switch (cmd) { + case TILOAD_COMPAT_IOMAGICNUM_GET: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOMAGICNUM_GET=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_IOMAGICNUM_GET, + (unsigned long) compat_ptr(arg)); + break; + + case TILOAD_COMPAT_IOMAGICNUM_SET: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOMAGICNUM_SET=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_IOMAGICNUM_SET, + (unsigned long) compat_ptr(arg)); + break; + + case TILOAD_COMPAT_BPR_READ: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_BPR_READ=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_BPR_READ, + (unsigned long) compat_ptr(arg)); + break; + + case TILOAD_COMPAT_BPR_WRITE: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_BPR_WRITE=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_BPR_WRITE, + (unsigned long) compat_ptr(arg)); + break; + + case TILOAD_COMPAT_IOCTL_SET_CHL: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CHL=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CHL, + (unsigned long) compat_ptr(arg)); + break; + + case TILOAD_COMPAT_IOCTL_SET_CONFIG: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CONFIG=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CONFIG, + (unsigned long) compat_ptr(arg)); + break; + + case TILOAD_COMPAT_IOCTL_SET_CALIBRATION: + dev_info(pTAS2557->dev, "%s, TILOAD_COMPAT_IOCTL_SET_CALIBRATION=0x%x\n", + __func__, cmd); + nResult = tiload_ioctl(filp, TILOAD_IOCTL_SET_CALIBRATION, + (unsigned long) compat_ptr(arg)); + break; + + default: + dev_err(pTAS2557->dev, "%s, unsupport compat ioctl=0x%x\n", + __func__, cmd); + break; + } + + return nResult; +} +#endif + +/*********** File operations structure for tiload *************/ +static const struct file_operations tiload_fops = { + .owner = THIS_MODULE, + .open = tiload_open, + .release = tiload_release, + .read = tiload_read, + .write = tiload_write, + .unlocked_ioctl = tiload_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tiload_compat_ioctl, +#endif +}; + +/*---------------------------------------------------------------------------- + * Function : tiload_driver_init + * + * Purpose : Register a char driver for dynamic tiload programming + *---------------------------------------------------------------------------- + */ +int tiload_driver_init(struct tas2557_priv *pTAS2557) +{ + int result; + dev_t dev = MKDEV(tiload_major, 0); + + g_TAS2557 = pTAS2557; + + dev_info(pTAS2557->dev, "%s\n", __func__); + + result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); + if (result < 0) { + dev_err(pTAS2557->dev, "cannot allocate major number %d\n", tiload_major); + return result; + } + tiload_class = class_create(THIS_MODULE, DEVICE_NAME); + tiload_major = MAJOR(dev); + dev_info(pTAS2557->dev, "allocated Major Number: %d\n", tiload_major); + + tiload_cdev = cdev_alloc(); + cdev_init(tiload_cdev, &tiload_fops); + tiload_cdev->owner = THIS_MODULE; + tiload_cdev->ops = &tiload_fops; + + if (device_create(tiload_class, NULL, dev, NULL, "tiload_node") == NULL) + dev_err(pTAS2557->dev, "Device creation failed\n"); + + if (cdev_add(tiload_cdev, dev, 1) < 0) { + dev_err(pTAS2557->dev, "tiload_driver: cdev_add failed\n"); + unregister_chrdev_region(dev, 1); + tiload_cdev = NULL; + return 1; + } + dev_info(pTAS2557->dev, "Registered TiLoad driver, Major number: %d\n", tiload_major); + /* class_device_create(tiload_class, NULL, dev, NULL, DEVICE_NAME, 0); */ + return 0; +} + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("Utility for TAS2557 Android in-system tuning"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/tiload.h b/sound/soc/codecs/tiload.h new file mode 100644 index 0000000000000..d97fc8fb29f5c --- /dev/null +++ b/sound/soc/codecs/tiload.h @@ -0,0 +1,66 @@ +/* +** ============================================================================= +** Copyright (c) 2016 Texas Instruments Inc. +** Copyright (C) 2019 XiaoMi, Inc. +** +** This program is free software; you can redistribute it and/or modify it under +** the terms of the GNU General Public License as published by the Free Software +** Foundation; version 2. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +** +** File: +** tiload.h +** +** Description: +** header file for tiload.c +** +** ============================================================================= +*/ + +#ifndef _TILOAD_H +#define _TILOAD_H + +#ifdef CONFIG_COMPAT +#include +#endif + +#include "tas2557.h" + +#define BPR_REG(book, page, reg) (((book * 256 * 128) + \ + (page * 128)) + reg) + +/* typedefs required for the included header files */ +struct BPR { + unsigned char nBook; + unsigned char nPage; + unsigned char nRegister; +}; + +/* defines */ +#define DEVICE_NAME "tiload_node" + +#define TILOAD_IOC_MAGIC 0xE0 +#define TILOAD_IOMAGICNUM_GET _IOR(TILOAD_IOC_MAGIC, 1, int) +#define TILOAD_IOMAGICNUM_SET _IOW(TILOAD_IOC_MAGIC, 2, int) +#define TILOAD_BPR_READ _IOR(TILOAD_IOC_MAGIC, 3, struct BPR) +#define TILOAD_BPR_WRITE _IOW(TILOAD_IOC_MAGIC, 4, struct BPR) +#define TILOAD_IOCTL_SET_CHL _IOW(TILOAD_IOC_MAGIC, 5, int) +#define TILOAD_IOCTL_SET_CONFIG _IOW(TILOAD_IOC_MAGIC, 6, int) +#define TILOAD_IOCTL_SET_CALIBRATION _IOW(TILOAD_IOC_MAGIC, 7, int) + +#ifdef CONFIG_COMPAT +#define TILOAD_COMPAT_IOMAGICNUM_GET _IOR(TILOAD_IOC_MAGIC, 1, compat_int_t) +#define TILOAD_COMPAT_IOMAGICNUM_SET _IOW(TILOAD_IOC_MAGIC, 2, compat_int_t) +#define TILOAD_COMPAT_BPR_READ _IOR(TILOAD_IOC_MAGIC, 3, struct BPR) +#define TILOAD_COMPAT_BPR_WRITE _IOW(TILOAD_IOC_MAGIC, 4, struct BPR) +#define TILOAD_COMPAT_IOCTL_SET_CHL _IOW(TILOAD_IOC_MAGIC, 5, compat_int_t) +#define TILOAD_COMPAT_IOCTL_SET_CONFIG _IOW(TILOAD_IOC_MAGIC, 6, compat_int_t) +#define TILOAD_COMPAT_IOCTL_SET_CALIBRATION _IOW(TILOAD_IOC_MAGIC, 7, compat_int_t) +#endif + +int tiload_driver_init(struct tas2557_priv *pTAS2557); + +#endif diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 42ea423662d68..a3869dd5e7267 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1,4 +1,5 @@ /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,6 +26,7 @@ #include #include #include +#include #include #include #include "wcd-mbhc-v2.h" @@ -42,7 +44,7 @@ #define OCP_ATTEMPT 1 #define HS_DETECT_PLUG_TIME_MS (3 * 1000) #define SPECIAL_HS_DETECT_TIME_MS (2 * 1000) -#define MBHC_BUTTON_PRESS_THRESHOLD_MIN 250 +#define MBHC_BUTTON_PRESS_THRESHOLD_MIN 750 #define GND_MIC_SWAP_THRESHOLD 4 #define WCD_FAKE_REMOVAL_MIN_PERIOD_MS 100 #define HS_VREF_MIN_VAL 1400 @@ -50,8 +52,9 @@ #define FW_READ_TIMEOUT 4000000 #define FAKE_REM_RETRY_ATTEMPTS 3 #define MAX_IMPED 60000 +#define CAM_HS_IMPED 45000 -#define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50 +#define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 200 #define ANC_DETECT_RETRY_CNT 7 #define WCD_MBHC_SPL_HS_CNT 2 @@ -60,6 +63,8 @@ module_param(det_extn_cable_en, int, S_IRUGO | S_IWUSR | S_IWGRP); MODULE_PARM_DESC(det_extn_cable_en, "enable/disable extn cable detect"); +bool is_jack_insert = false; + enum wcd_mbhc_cs_mb_en_flag { WCD_MBHC_EN_CS = 0, WCD_MBHC_EN_MB, @@ -67,9 +72,19 @@ enum wcd_mbhc_cs_mb_en_flag { WCD_MBHC_EN_NONE, }; +static struct switch_dev accdet_data; + static void wcd_mbhc_jack_report(struct wcd_mbhc *mbhc, struct snd_soc_jack *jack, int status, int mask) { + printk("[%s]=====status[%d]type[%d]\n", __FUNCTION__, status, jack->jack->type); + if (!status && (jack->jack->type&WCD_MBHC_JACK_MASK)){ + switch_set_state(&accdet_data, 0); + is_jack_insert = false; + }else if (jack->jack->type&WCD_MBHC_JACK_MASK){ + switch_set_state(&accdet_data, status); + is_jack_insert = true; + } snd_soc_jack_report(jack, status, mask); } @@ -162,11 +177,13 @@ static void wcd_enable_curr_micbias(const struct wcd_mbhc *mbhc, switch (cs_mb_en) { case WCD_MBHC_EN_CS: + #if 0 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 3); /* Program Button threshold registers as per CS */ wcd_program_btn_threshold(mbhc, false); break; + #endif case WCD_MBHC_EN_MB: WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1); @@ -333,13 +350,17 @@ static int wcd_event_notify(struct notifier_block *self, unsigned long val, &mbhc->event_state))) /* enable pullup and cs, disable mb */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_PULLUP); - else + else{ /* enable current source and disable mb, pullup*/ - wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); + if (is_jack_insert) + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); + else + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); + } /* configure cap settings properly when micbias is disabled */ if (mbhc->mbhc_cb->set_cap_mode) - mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false); + mbhc->mbhc_cb->set_cap_mode(codec, micbias1, is_jack_insert); break; case WCD_EVENT_PRE_HPHL_PA_OFF: mutex_lock(&mbhc->hphl_pa_lock); @@ -350,12 +371,12 @@ static int wcd_event_notify(struct notifier_block *self, unsigned long val, hphlocp_off_report(mbhc, SND_JACK_OC_HPHL); clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); /* check if micbias is enabled */ - if (micbias2) + if (true == is_jack_insert) /* Disable cs, pullup & enable micbias */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); else /* Disable micbias, pullup & enable cs */ - wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); mutex_unlock(&mbhc->hphl_pa_lock); break; case WCD_EVENT_PRE_HPHR_PA_OFF: @@ -367,12 +388,12 @@ static int wcd_event_notify(struct notifier_block *self, unsigned long val, hphrocp_off_report(mbhc, SND_JACK_OC_HPHR); clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state); /* check if micbias is enabled */ - if (micbias2) + if (true == is_jack_insert) /* Disable cs, pullup & enable micbias */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); else /* Disable micbias, pullup & enable cs */ - wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); mutex_unlock(&mbhc->hphr_pa_lock); break; case WCD_EVENT_PRE_HPHL_PA_ON: @@ -562,7 +583,10 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, __func__, insertion, mbhc->hph_status); if (!insertion) { /* Report removal */ - mbhc->hph_status &= ~jack_type; + mbhc->hph_status &= ~(SND_JACK_HEADSET | + SND_JACK_LINEOUT | + SND_JACK_ANC_HEADPHONE | + SND_JACK_UNSUPPORTED); /* * cancel possibly scheduled btn work and * report release if we reported button press @@ -678,7 +702,12 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, } else if (jack_type == SND_JACK_ANC_HEADPHONE) mbhc->current_plug = MBHC_PLUG_TYPE_ANC_HEADPHONE; - if (mbhc->mbhc_cb->hph_pa_on_status) + if (jack_type == SND_JACK_UNSUPPORTED){ + printk("%s:jack_type is 0x100, off pa to compute imp\n", __func__); + wcd_mbhc_set_and_turnoff_hph_padac(mbhc); + } + + if (mbhc->mbhc_cb->hph_pa_on_status) is_pa_on = mbhc->mbhc_cb->hph_pa_on_status(codec); if (mbhc->impedance_detect && @@ -691,7 +720,7 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, mbhc->zl < MAX_IMPED) && (mbhc->zr > mbhc->mbhc_cfg->linein_th && mbhc->zr < MAX_IMPED) && - (jack_type == SND_JACK_HEADPHONE)) { + (jack_type == SND_JACK_HEADPHONE) && (mbhc->mbhc_cfg->detect_extn_cable)) { jack_type = SND_JACK_LINEOUT; mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; if (mbhc->hph_status) { @@ -706,6 +735,26 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, pr_debug("%s: Marking jack type as SND_JACK_LINEOUT\n", __func__); } + if ((mbhc->zl > CAM_HS_IMPED && + mbhc->zl < MAX_IMPED) && + (mbhc->zr > CAM_HS_IMPED && + mbhc->zr < MAX_IMPED) && + (jack_type == SND_JACK_UNSUPPORTED)) { + jack_type = SND_JACK_HEADSET; + mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET; + mbhc->jiffies_atreport = jiffies; + if (mbhc->hph_status) { + mbhc->hph_status &= ~(SND_JACK_HEADSET | + SND_JACK_LINEOUT | + SND_JACK_UNSUPPORTED); + wcd_mbhc_jack_report(mbhc, + &mbhc->headset_jack, + mbhc->hph_status, + WCD_MBHC_JACK_MASK); + } + } + printk("%s: [%d,%d] jack type changed by IMPED\n", + __func__, mbhc->zl, mbhc->zr); } mbhc->hph_status |= jack_type; @@ -834,7 +883,7 @@ static void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc, SND_JACK_HEADPHONE); if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET); - wcd_mbhc_report_plug(mbhc, 1, SND_JACK_UNSUPPORTED); + wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET); } else if (plug_type == MBHC_PLUG_TYPE_HEADSET) { if (mbhc->mbhc_cfg->enable_anc_mic_detect) anc_mic_found = wcd_mbhc_detect_anc_plug_type(mbhc); @@ -1094,6 +1143,9 @@ static void wcd_enable_mbhc_supply(struct wcd_mbhc *mbhc, WCD_MBHC_EN_CS); } else if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) { wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); + } else if (is_jack_insert) + { + wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB); } else { wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE); } @@ -1193,6 +1245,7 @@ static void wcd_correct_swch_plug(struct work_struct *work) WCD_MBHC_REG_READ(WCD_MBHC_BTN_RESULT, btn_result); WCD_MBHC_REG_READ(WCD_MBHC_HS_COMP_RESULT, hs_comp_res); + printk("[%s]=====rc=%d, btn_result=%d, hs_comp_res=%d\n", __FUNCTION__, rc, btn_result, hs_comp_res); if (!rc) { pr_debug("%s No btn press interrupt\n", __func__); if (!btn_result && !hs_comp_res) @@ -1453,7 +1506,7 @@ static void wcd_correct_swch_plug(struct work_struct *work) WCD_MBHC_RSC_UNLOCK(mbhc); } if (mbhc->mbhc_cb->set_cap_mode) - mbhc->mbhc_cb->set_cap_mode(codec, micbias1, micbias2); + mbhc->mbhc_cb->set_cap_mode(codec, micbias1, is_jack_insert); if (mbhc->mbhc_cb->hph_pull_down_ctrl) mbhc->mbhc_cb->hph_pull_down_ctrl(codec, true); @@ -2003,6 +2056,10 @@ static irqreturn_t wcd_mbhc_release_handler(int irq, void *data) */ if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) { wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET); + wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack, + 0, WCD_MBHC_JACK_MASK); + msleep(100); + wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET); goto exit; } @@ -2378,6 +2435,16 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, pr_debug("%s: enter\n", __func__); + accdet_data.name = "h2w"; + accdet_data.index = 0; + accdet_data.state = 0; + ret = switch_dev_register(&accdet_data); + if (ret) { + dev_err(card->dev, "[Accdet]switch_dev_register returned:%d!\n", ret); + return -EPERM; + + } + ret = of_property_read_u32(card->dev->of_node, hph_switch, &hph_swh); if (ret) { dev_err(card->dev, @@ -2397,7 +2464,7 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, mbhc->is_btn_press = false; mbhc->codec = codec; mbhc->intr_ids = mbhc_cdc_intr_ids; - mbhc->impedance_detect = impedance_det_en; + mbhc->impedance_detect = true; mbhc->hphl_swh = hph_swh; mbhc->gnd_swh = gnd_swh; mbhc->micbias_enable = false; @@ -2574,6 +2641,7 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec, mbhc->mbhc_cb->register_notifier(codec, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); err: + switch_dev_unregister(&accdet_data); pr_debug("%s: leave ret %d\n", __func__, ret); return ret; } @@ -2595,6 +2663,7 @@ void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) if (mbhc->mbhc_cb && mbhc->mbhc_cb->register_notifier) mbhc->mbhc_cb->register_notifier(codec, &mbhc->nblock, false); mutex_destroy(&mbhc->codec_resource_lock); + switch_dev_unregister(&accdet_data); } EXPORT_SYMBOL(wcd_mbhc_deinit); diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index 06166959067fa..422202a1aa634 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -122,13 +122,6 @@ module_param(wsa881x_ocp_poll_timer_sec, int, S_IRUGO | S_IWUSR | S_IWGRP); MODULE_PARM_DESC(wsa881x_ocp_poll_timer_sec, "timer for ocp ctl polling"); -static struct wsa881x_priv *dbgwsa881x; -static struct dentry *debugfs_wsa881x_dent; -static struct dentry *debugfs_peek; -static struct dentry *debugfs_poke; -static struct dentry *debugfs_reg_dump; -static unsigned int read_data; -static unsigned int devnum; static int32_t wsa881x_resource_acquire(struct snd_soc_codec *codec, bool enable); @@ -176,30 +169,6 @@ static const struct snd_kcontrol_new wsa_analog_gain_controls[] = { static int codec_debug_open(struct inode *inode, struct file *file) { - file->private_data = inode->i_private; - return 0; -} - -static int get_parameters(char *buf, u32 *param1, int num_of_par) -{ - char *token; - int base, cnt; - - token = strsep(&buf, " "); - for (cnt = 0; cnt < num_of_par; cnt++) { - if (token) { - if ((token[1] == 'x') || (token[1] == 'X')) - base = 16; - else - base = 10; - - if (kstrtou32(token, base, ¶m1[cnt]) != 0) - return -EINVAL; - - token = strsep(&buf, " "); - } else - return -EINVAL; - } return 0; } @@ -285,142 +254,19 @@ int wsa881x_codec_info_create_codec_entry(struct snd_info_entry *codec_root, } EXPORT_SYMBOL(wsa881x_codec_info_create_codec_entry); -static bool is_swr_slv_reg_readable(int reg) -{ - bool ret = true; - - if (((reg > 0x46) && (reg < 0x4A)) || - ((reg > 0x4A) && (reg < 0x50)) || - ((reg > 0x55) && (reg < 0xE0)) || - ((reg > 0xE0) && (reg < 0xF0)) || - ((reg > 0xF0) && (reg < 0x100)) || - ((reg > 0x105) && (reg < 0x120)) || - ((reg > 0x128) && (reg < 0x130)) || - ((reg > 0x138) && (reg < 0x200)) || - ((reg > 0x205) && (reg < 0x220)) || - ((reg > 0x228) && (reg < 0x230)) || - ((reg > 0x238) && (reg < 0x300)) || - ((reg > 0x305) && (reg < 0x320)) || - ((reg > 0x328) && (reg < 0x330)) || - ((reg > 0x338) && (reg < 0x400)) || - ((reg > 0x405) && (reg < 0x420))) - ret = false; - - return ret; -} - -static ssize_t wsa881x_swrslave_reg_show(char __user *ubuf, size_t count, - loff_t *ppos) -{ - int i, reg_val, len; - ssize_t total = 0; - char tmp_buf[SWR_SLV_MAX_BUF_LEN]; - - if (!ubuf || !ppos || (devnum == 0)) - return 0; - - for (i = (((int) *ppos / BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR); - i <= SWR_SLV_MAX_REG_ADDR; i++) { - if (!is_swr_slv_reg_readable(i)) - continue; - swr_read(dbgwsa881x->swr_slave, devnum, - i, ®_val, 1); - len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i, - (reg_val & 0xFF)); - if ((total + len) >= count - 1) - break; - if (copy_to_user((ubuf + total), tmp_buf, len)) { - pr_err("%s: fail to copy reg dump\n", __func__); - total = -EFAULT; - goto copy_err; - } - *ppos += len; - total += len; - } - -copy_err: - return total; -} - static ssize_t codec_debug_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { - char lbuf[SWR_SLV_RD_BUF_LEN]; - char *access_str; - ssize_t ret_cnt; - if (!count || !file || !ppos || !ubuf) return -EINVAL; - - access_str = file->private_data; - if (*ppos < 0) - return -EINVAL; - - if (!strcmp(access_str, "swrslave_peek")) { - snprintf(lbuf, sizeof(lbuf), "0x%x\n", (read_data & 0xFF)); - ret_cnt = simple_read_from_buffer(ubuf, count, ppos, lbuf, - strnlen(lbuf, 7)); - } else if (!strcmp(access_str, "swrslave_reg_dump")) { - ret_cnt = wsa881x_swrslave_reg_show(ubuf, count, ppos); - } else { - pr_err("%s: %s not permitted to read\n", __func__, access_str); - ret_cnt = -EPERM; - } - return ret_cnt; } static ssize_t codec_debug_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - char lbuf[SWR_SLV_WR_BUF_LEN]; - int rc; - u32 param[5]; - char *access_str; if (!filp || !ppos || !ubuf) return -EINVAL; - - access_str = filp->private_data; - if (cnt > sizeof(lbuf) - 1) - return -EINVAL; - - rc = copy_from_user(lbuf, ubuf, cnt); - if (rc) - return -EFAULT; - - lbuf[cnt] = '\0'; - if (!strcmp(access_str, "swrslave_poke")) { - /* write */ - rc = get_parameters(lbuf, param, 3); - if ((param[0] <= SWR_SLV_MAX_REG_ADDR) && (param[1] <= 0xFF) && - (rc == 0)) - swr_write(dbgwsa881x->swr_slave, param[2], - param[0], ¶m[1]); - else - rc = -EINVAL; - } else if (!strcmp(access_str, "swrslave_peek")) { - /* read */ - rc = get_parameters(lbuf, param, 2); - if ((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0)) - swr_read(dbgwsa881x->swr_slave, param[1], - param[0], &read_data, 1); - else - rc = -EINVAL; - } else if (!strcmp(access_str, "swrslave_reg_dump")) { - /* reg dump */ - rc = get_parameters(lbuf, param, 1); - if ((rc == 0) && (param[0] > 0) && - (param[0] <= SWR_SLV_MAX_DEVICES)) - devnum = param[0]; - else - rc = -EINVAL; - } - if (rc == 0) - rc = cnt; - else - pr_err("%s: rc = %d\n", __func__, rc); - - return rc; } static const struct file_operations codec_debug_ops = { @@ -1211,29 +1057,6 @@ static int wsa881x_swr_probe(struct swr_device *pdev) wsa881x_gpio_ctrl(wsa881x, true); wsa881x->state = WSA881X_DEV_UP; - if (!debugfs_wsa881x_dent) { - dbgwsa881x = wsa881x; - debugfs_wsa881x_dent = debugfs_create_dir( - "wsa881x_swr_slave", 0); - if (!IS_ERR(debugfs_wsa881x_dent)) { - debugfs_peek = debugfs_create_file("swrslave_peek", - S_IFREG | S_IRUGO, debugfs_wsa881x_dent, - (void *) "swrslave_peek", - &codec_debug_ops); - - debugfs_poke = debugfs_create_file("swrslave_poke", - S_IFREG | S_IRUGO, debugfs_wsa881x_dent, - (void *) "swrslave_poke", - &codec_debug_ops); - - debugfs_reg_dump = debugfs_create_file( - "swrslave_reg_dump", - S_IFREG | S_IRUGO, - debugfs_wsa881x_dent, - (void *) "swrslave_reg_dump", - &codec_debug_ops); - } - } return 0; err: @@ -1249,7 +1072,6 @@ static int wsa881x_swr_remove(struct swr_device *pdev) dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__); return -EINVAL; } - debugfs_remove_recursive(debugfs_wsa881x_dent); snd_soc_unregister_codec(&pdev->dev); if (wsa881x->pd_gpio) gpio_free(wsa881x->pd_gpio); diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index cefd3865037ba..88b4637def3bf 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2707,6 +2708,40 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "MultiMedia29", .probe = fe_dai_probe, }, +#if (defined CONFIG_SND_SOC_MAX98927) || (defined CONFIG_SND_SOC_TAS2557) + { + .capture = { + .stream_name = "Quinary MI2S_TX Hostless Capture", + .aif_name = "QUIN_MI2S_UL_HL", + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .channels_min = 1, + .channels_max = 2, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &msm_fe_dai_ops, + .name = "QUIN_MI2S_TX_HOSTLESS", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "Quinary MI2S_RX Hostless Playback", + .aif_name = "QUIN_MI2S_DL_HL", + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE, + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_fe_dai_ops, + .name = "QUIN_MI2S_RX_HOSTLESS", + .probe = fe_dai_probe, + }, +#endif }; static int msm_fe_dai_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/msm/msm8952.c b/sound/soc/msm/msm8952.c index 24fc90036b513..f5371332455ac 100644 --- a/sound/soc/msm/msm8952.c +++ b/sound/soc/msm/msm8952.c @@ -1,4 +1,5 @@ /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -9,7 +10,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - #include #include #include @@ -92,14 +92,22 @@ static int msm8952_wsa_switch_event(struct snd_soc_dapm_widget *w, static struct wcd_mbhc_config mbhc_cfg = { .read_fw_bin = false, .calibration = NULL, - .detect_extn_cable = true, + + .detect_extn_cable = false, + .mono_stero_detection = false, .swap_gnd_mic = NULL, .hs_ext_micbias = false, + /* .key_code[0] = KEY_MEDIA, .key_code[1] = KEY_VOICECOMMAND, .key_code[2] = KEY_VOLUMEUP, .key_code[3] = KEY_VOLUMEDOWN, + */ + .key_code[0] = KEY_MEDIA, + .key_code[1] = BTN_1, + .key_code[2] = BTN_2, + .key_code[3] = 0, .key_code[4] = 0, .key_code[5] = 0, .key_code[6] = 0, @@ -1608,7 +1616,7 @@ static void *def_msm8952_wcd_mbhc_cal(void) return NULL; #define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(msm8952_wcd_cal)->X) = (Y)) - S(v_hs_max, 1500); + S(v_hs_max, 1600); #undef S #define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(msm8952_wcd_cal)->X) = (Y)) S(num_btn, WCD_MBHC_DEF_BUTTONS); @@ -1631,16 +1639,29 @@ static void *def_msm8952_wcd_mbhc_cal(void) * 210-290 == Button 2 * 360-680 == Button 3 */ - btn_low[0] = 75; - btn_high[0] = 75; - btn_low[1] = 150; - btn_high[1] = 150; - btn_low[2] = 225; - btn_high[2] = 225; - btn_low[3] = 450; - btn_high[3] = 450; - btn_low[4] = 500; - btn_high[4] = 500; + #if defined(CONFIG_MBHC_UART) + btn_low[0] = 177; + btn_high[0] = 277; + btn_low[1] = 206; + btn_high[1] = 437; + btn_low[2] = 243; + btn_high[2] = 612; + btn_low[3] = 243; + btn_high[3] = 612; + btn_low[4] = 243; + btn_high[4] = 612; + #else + btn_low[0] = 91; + btn_high[0] = 91; + btn_low[1] = 259; + btn_high[1] = 259; + btn_low[2] = 488; + btn_high[2] = 488; + btn_low[3] = 488; + btn_high[3] = 488; + btn_low[4] = 488; + btn_high[4] = 488; + #endif return msm8952_wcd_cal; } @@ -2426,6 +2447,40 @@ static struct snd_soc_dai_link msm8952_dai[] = { .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA29, }, +#if (defined CONFIG_SND_SOC_MAX98927) || (defined CONFIG_SND_SOC_TAS2557) + {/* hw:x,43 */ + .name = "Quinary MI2S TX_Hostless", + .stream_name = "Quinary MI2S_TX Hostless Capture", + .cpu_dai_name = "QUIN_MI2S_TX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + { /* hw:x,44 */ + .name = "Quinary MI2S_RX Hostless", + .stream_name = "Quinary MI2S_RX Hostless", + .cpu_dai_name = "QUIN_MI2S_RX_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + /* this dailink has playback support */ + .ignore_pmdown_time = 1, + /* This dainlink has MI2S support */ + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, +#endif /* Backend I2S DAI Links */ { .name = LPASS_BE_PRI_MI2S_RX, @@ -2673,7 +2728,38 @@ static struct snd_soc_dai_link msm8952_dai[] = { .be_hw_params_fixup = msm_be_hw_params_fixup, .ignore_suspend = 1, }, +#if defined(CONFIG_SND_SOC_MAX98927) + { + .name = LPASS_BE_QUIN_MI2S_TX, + .stream_name = "Quinary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.5", + .platform_name = "msm-pcm-routing", + .codec_dai_name = "max98927-aif1", + .codec_name = "max98927", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUINARY_MI2S_TX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ops = &msm8952_quin_mi2s_be_ops, + .ignore_suspend = 1, + }, +#elif defined (CONFIG_SND_SOC_TAS2557) + { + .name = LPASS_BE_QUIN_MI2S_TX, + .stream_name = "Quinary MI2S Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.5", + .platform_name = "msm-pcm-routing", + .codec_dai_name = "tas2557 ASI1", + .codec_name = "tas2557.2-004c", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUINARY_MI2S_TX, + .be_hw_params_fixup = msm_be_hw_params_fixup, + .ops = &msm8952_quin_mi2s_be_ops, + .ignore_suspend = 1, + }, +#else { .name = LPASS_BE_QUIN_MI2S_TX, .stream_name = "Quinary MI2S Capture", @@ -2688,6 +2774,7 @@ static struct snd_soc_dai_link msm8952_dai[] = { .ops = &msm8952_quin_mi2s_be_ops, .ignore_suspend = 1, }, +#endif }; static struct snd_soc_dai_link msm8952_hdmi_dba_dai_link[] = { { @@ -2706,7 +2793,43 @@ static struct snd_soc_dai_link msm8952_hdmi_dba_dai_link[] = { .ignore_suspend = 1, }, }; - +#if defined(CONFIG_SND_SOC_MAX98927) +static struct snd_soc_dai_link msm8952_quin_dai_link[] = { + { + .name = LPASS_BE_QUIN_MI2S_RX, + .stream_name = "Quinary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.5", + .platform_name = "msm-pcm-routing", + .codec_dai_name = "max98927-aif1", + .codec_name = "max98927", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUINARY_MI2S_RX, + .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup, + .ops = &msm8952_quin_mi2s_be_ops, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .ignore_suspend = 1, + }, +}; +#elif defined (CONFIG_SND_SOC_TAS2557) +static struct snd_soc_dai_link msm8952_quin_dai_link[] = { + { + .name = LPASS_BE_QUIN_MI2S_RX, + .stream_name = "Quinary MI2S Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.5", + .platform_name = "msm-pcm-routing", + .codec_dai_name = "tas2557 ASI1", + .codec_name = "tas2557.2-004c", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUINARY_MI2S_RX, + .be_hw_params_fixup = msm_mi2s_rx_be_hw_params_fixup, + .ops = &msm8952_quin_mi2s_be_ops, + .ignore_pmdown_time = 1, /* dai link has playback support */ + .ignore_suspend = 1, + }, +}; +#else static struct snd_soc_dai_link msm8952_quin_dai_link[] = { { .name = LPASS_BE_QUIN_MI2S_RX, @@ -2724,6 +2847,7 @@ static struct snd_soc_dai_link msm8952_quin_dai_link[] = { .ignore_suspend = 1, }, }; +#endif static struct snd_soc_dai_link msm8952_split_a2dp_dai_link[] = { { diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index b341adda77226..c37004166a114 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1299,8 +1300,13 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) pr_debug("%s: stream_id %d bits_per_sample %d\n", __func__, ac->stream_id, bits_per_sample); - ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, - bits_per_sample); + if (prtd->codec_param.codec.flags & COMPRESSED_TIMESTAMP_FLAG) { + ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, + bits_per_sample, true); + } else { + ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, + bits_per_sample, false); + } if (ret < 0) { pr_err("%s: q6asm_open_read failed:%d\n", __func__, ret); return ret; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 51ef01c3b9344..23f8013e7c4ab 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -466,7 +466,8 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) case (Q6_SUBSYS_AVS2_8): ret = q6asm_open_read_v4(prtd->audio_client, FORMAT_LINEAR_PCM, - bits_per_sample); + bits_per_sample, + false); break; case (Q6_SUBSYS_INVALID): diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index ed7d4edaa40a4..4af2140fc6a42 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -57,6 +58,7 @@ static int pri_mi2s_switch_enable; static int sec_mi2s_switch_enable; static int tert_mi2s_switch_enable; static int quat_mi2s_switch_enable; +static int quin_mi2s_switch_enable; static int fm_pcmrx_switch_enable; static int lsm_port_index; static int slim0_rx_aanc_fb_port; @@ -2051,6 +2053,38 @@ static int msm_routing_put_quat_mi2s_switch_mixer( return 1; } +static int msm_routing_get_quin_mi2s_switch_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = quin_mi2s_switch_enable; + pr_debug("%s: QUIN MI2S Switch enable %ld\n", __func__, + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_routing_put_quin_mi2s_switch_mixer( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget_list *wlist = + dapm_kcontrol_get_wlist(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct snd_soc_dapm_update *update = NULL; + + pr_debug("%s: QUIN MI2S Switch enable %ld\n", __func__, + ucontrol->value.integer.value[0]); + if (ucontrol->value.integer.value[0]) + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 1, + update); + else + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 0, + update); + quin_mi2s_switch_enable = ucontrol->value.integer.value[0]; + return 1; +} + + static int msm_routing_get_fm_pcmrx_switch_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -3194,6 +3228,14 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol, msm_route_ec_ref_rx = 18; ec_ref_port_id = AFE_PORT_ID_TERTIARY_TDM_TX; break; + case 19: + msm_route_ec_ref_rx = 19; + ec_ref_port_id = AFE_PORT_ID_QUINARY_MI2S_TX; + break; + case 20: + msm_route_ec_ref_rx = 20; + ec_ref_port_id = AFE_PORT_ID_QUINARY_MI2S_RX; + break; default: msm_route_ec_ref_rx = 0; /* NONE */ pr_err("%s EC ref rx %ld not valid\n", @@ -3216,7 +3258,7 @@ static const char *const ec_ref_rx[] = { "None", "SLIM_RX", "I2S_RX", "TERT_MI2S_TX", "QUAT_MI2S_TX", "SEC_I2S_RX", "PROXY_RX", "SLIM_5_RX", "SLIM_1_TX", "QUAT_TDM_TX_1", "QUAT_TDM_RX_0", "QUAT_TDM_RX_1", "QUAT_TDM_RX_2", "SLIM_6_RX", - "TERT_MI2S_RX", "QUAT_MI2S_RX", "TERT_TDM_TX_0"}; + "TERT_MI2S_RX", "QUAT_MI2S_RX", "TERT_TDM_TX_0", "QUIN_MI2S_TX", "QUIN_MI2S_RX"}; static const struct soc_enum msm_route_ec_ref_rx_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ec_ref_rx), ec_ref_rx), @@ -7752,6 +7794,9 @@ static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_BACKEND_DAI_QUINARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), @@ -7767,6 +7812,9 @@ static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_RX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_TERTIARY_MI2S_RX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUIN_MI2S_RX", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_BACKEND_DAI_QUINARY_MI2S_RX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("QUAT_MI2S_RX", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_BACKEND_DAI_QUATERNARY_MI2S_RX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), @@ -7968,6 +8016,30 @@ static const struct snd_kcontrol_new quat_mi2s_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +static const struct snd_kcontrol_new quin_mi2s_rx_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_RX, + MSM_BACKEND_DAI_QUINARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + static const struct snd_kcontrol_new pri_tdm_rx_0_port_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, @@ -9373,6 +9445,13 @@ static const struct snd_kcontrol_new quat_mi2s_rx_switch_mixer_controls = 0, 1, 0, msm_routing_get_quat_mi2s_switch_mixer, msm_routing_put_quat_mi2s_switch_mixer); + +static const struct snd_kcontrol_new quin_mi2s_rx_switch_mixer_controls = + SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, + 0, 1, 0, msm_routing_get_quin_mi2s_switch_mixer, + msm_routing_put_quin_mi2s_switch_mixer); + + static const struct snd_kcontrol_new hfp_pri_aux_switch_mixer_controls = SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, 0, 1, 0, msm_routing_get_hfp_switch_mixer, @@ -10371,6 +10450,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("QUAT_MI2S_DL_HL", "Quaternary MI2S_RX Hostless Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("QUIN_MI2S_DL_HL", + "Quinary MI2S_RX Hostless Playback", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("AUXPCM_DL_HL", "AUXPCM_HOSTLESS Playback", 0, 0, 0, 0), @@ -10398,6 +10480,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_UL_HL", "Quaternary MI2S_TX Hostless Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_UL_HL", + "Quinary MI2S_TX Hostless Capture", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("PRI_TDM_RX_0_DL_HL", "Primary TDM0 Hostless Playback", @@ -10858,6 +10943,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { &tert_mi2s_rx_switch_mixer_controls), SND_SOC_DAPM_SWITCH("QUAT_MI2S_RX_DL_HL", SND_SOC_NOPM, 0, 0, &quat_mi2s_rx_switch_mixer_controls), + SND_SOC_DAPM_SWITCH("QUIN_MI2S_RX_DL_HL", SND_SOC_NOPM, 0, 0, + &quin_mi2s_rx_switch_mixer_controls), SND_SOC_DAPM_SWITCH("HFP_PRI_AUX_UL_HL", SND_SOC_NOPM, 0, 0, &hfp_pri_aux_switch_mixer_controls), SND_SOC_DAPM_SWITCH("HFP_AUX_UL_HL", SND_SOC_NOPM, 0, 0, @@ -11164,6 +11251,9 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, quat_mi2s_rx_port_mixer_controls, ARRAY_SIZE(quat_mi2s_rx_port_mixer_controls)), + SND_SOC_DAPM_MIXER("QUIN_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, + quin_mi2s_rx_port_mixer_controls, + ARRAY_SIZE(quin_mi2s_rx_port_mixer_controls)), SND_SOC_DAPM_MIXER("PRI_TDM_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0, pri_tdm_rx_0_port_mixer_controls, ARRAY_SIZE(pri_tdm_rx_0_port_mixer_controls)), @@ -12553,6 +12643,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"VOC_EXT_EC MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"VOC_EXT_EC MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"VOC_EXT_EC MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"VOC_EXT_EC MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, {"VOC_EXT_EC MUX", "SLIM_1_TX" , "SLIMBUS_1_TX"}, {"CS-VOICE_UL1", NULL, "VOC_EXT_EC MUX"}, {"VOIP_UL", NULL, "VOC_EXT_EC MUX"}, @@ -12566,6 +12657,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"AUDIO_REF_EC_UL1 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL1 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL1 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL1 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL1 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL1 MUX", "SLIM_1_TX" , "SLIMBUS_1_TX"}, {"AUDIO_REF_EC_UL1 MUX", "QUAT_TDM_TX_1" , "QUAT_TDM_TX_1"}, {"AUDIO_REF_EC_UL1 MUX", "QUAT_TDM_RX_0" , "QUAT_TDM_RX_0"}, @@ -12577,61 +12670,85 @@ static const struct snd_soc_dapm_route intercon[] = { {"AUDIO_REF_EC_UL2 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL2 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL2 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL2 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL2 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL3 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL3 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL3 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL3 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL3 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL3 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL4 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL4 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL4 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL4 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL4 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL4 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL5 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL5 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL5 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL5 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL5 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL5 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL6 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL6 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL6 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL6 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL6 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL6 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL8 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL8 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL8 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL8 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL8 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL8 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL9 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL9 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL9 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL9 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL9 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL9 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL17 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL17 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL17 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL17 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL17 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL17 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL18 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL18 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL18 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL18 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL18 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL18 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL19 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL19 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL19 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL19 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL19 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL19 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL28 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL28 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL28 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL28 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL28 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL28 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"AUDIO_REF_EC_UL29 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"AUDIO_REF_EC_UL29 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"}, {"AUDIO_REF_EC_UL29 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"AUDIO_REF_EC_UL29 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"AUDIO_REF_EC_UL29 MUX", "QUIN_MI2S_TX" , "QUIN_MI2S_TX"}, + {"AUDIO_REF_EC_UL29 MUX", "QUIN_MI2S_RX" , "QUIN_MI2S_RX"}, {"MM_UL1", NULL, "AUDIO_REF_EC_UL1 MUX"}, {"MM_UL2", NULL, "AUDIO_REF_EC_UL2 MUX"}, @@ -12882,6 +12999,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_MI2S_RX_DL_HL", "Switch", "QUAT_MI2S_DL_HL"}, {"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX_DL_HL"}, + + {"QUIN_MI2S_RX_DL_HL", "Switch", "PRI_MI2S_DL_HL"}, + {"QUIN_MI2S_RX", NULL, "QUIN_MI2S_RX_DL_HL"}, + {"MI2S_UL_HL", NULL, "TERT_MI2S_TX"}, {"TERT_MI2S_UL_HL", NULL, "TERT_MI2S_TX"}, {"SEC_I2S_RX", NULL, "SEC_I2S_DL_HL"}, @@ -12890,7 +13011,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_MI2S_RX", NULL, "SEC_MI2S_DL_HL"}, {"PRI_MI2S_RX", NULL, "PRI_MI2S_DL_HL"}, {"TERT_MI2S_RX", NULL, "TERT_MI2S_DL_HL"}, + {"QUIN_MI2S_RX", NULL, "QUIN_MI2S_DL_HL"}, {"QUAT_MI2S_UL_HL", NULL, "QUAT_MI2S_TX"}, + {"QUIN_MI2S_UL_HL", NULL, "QUIN_MI2S_TX"}, {"PRI_TDM_TX_0_UL_HL", NULL, "PRI_TDM_TX_0"}, {"PRI_TDM_TX_1_UL_HL", NULL, "PRI_TDM_TX_1"}, @@ -13366,7 +13489,16 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"QUAT_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"QUAT_MI2S_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"QUAT_MI2S_RX Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Port Mixer"}, + {"QUIN_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"QUIN_MI2S_RX Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"QUIN_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"QUIN_MI2S_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_UL_TX"}, + {"QUIN_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIM_0_TX"}, + {"QUIN_MI2S_RX Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"QUIN_MI2S_RX Port Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX"}, + {"QUIN_MI2S_RX", NULL, "QUIN_MI2S_RX Port Mixer"}, /* Backend Enablement */ diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 3d4f60ed04519..2f709b6c4bc18 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -119,6 +120,9 @@ struct afe_ctl { struct aanc_data aanc_info; struct mutex afe_cmd_lock; int set_custom_topology; +#ifdef CONFIG_SND_SOC_MAX98927 + uint8_t *dsm_payload; +#endif }; #define MAD_SLIMBUS_PORT_COUNT ((SLIMBUS_PORT_LAST - SLIMBUS_0_RX) + 1) @@ -256,6 +260,33 @@ static int32_t sp_make_afe_callback(uint32_t *payload, uint32_t payload_size) } } +#ifdef CONFIG_SND_SOC_MAX98927 + if ( + param_id == AFE_PARAM_ID_DSM_CFG || + param_id == AFE_PARAM_ID_DSM_INFO || + param_id == AFE_PARAM_ID_CALIB){ + struct afe_dsm_get_resp *dsm_resp = + (struct afe_dsm_get_resp *) payload; + + if (payload_size < sizeof(*dsm_resp)) { + pr_err("%s: Error: received size %d, afe_dsm_get_resp size %zu\n", + __func__, payload_size, sizeof(*dsm_resp)); + return -EINVAL; + } + + if (this_afe.dsm_payload) + memcpy(this_afe.dsm_payload, dsm_resp->payload, + payload_size - sizeof(*dsm_resp)); + + if (!dsm_resp->status) { + atomic_set(&this_afe.state, 0); + } else { + pr_debug("%s: dsm resp status: %d", __func__, dsm_resp->status); + atomic_set(&this_afe.state, -1); + } + } +#endif + return 0; } @@ -890,6 +921,198 @@ static int afe_spk_ramp_dn_cfg(int port) return ret; } +#ifdef CONFIG_SND_SOC_MAX98927 +int afe_dsm_setget_params(uint8_t *payload, int size, int dir, uint32_t dst_port, uint32_t mod_id, uint32_t param_id) +{ + struct afe_dsm_set_command *set = NULL; + struct afe_dsm_get_command *get = NULL; + uint32_t *config = NULL; + int index = 0, ret = -EINVAL; + + if (!payload || size <= 0) { + pr_err("%s: Invalid params\n", __func__); + goto fail_cmd; + } + ret = q6audio_validate_port(dst_port); + if (ret < 0) { + pr_err("%s: Invalid src port 0x%x ret %d", + __func__, dst_port, ret); + ret = -EINVAL; + goto fail_cmd; + } + + index = q6audio_get_port_index(dst_port); + if (index < 0 || index > AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, index); + ret = -EINVAL; + goto fail_cmd; + } + + if (dir){ + get = (struct afe_dsm_get_command *) (payload - sizeof(*get)); + + memset(get, 0 , sizeof(*get)); + + get->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + get->hdr.pkt_size = size + sizeof(*get); + get->hdr.token = index; + get->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; + get->param.port_id = q6audio_get_port_id(dst_port); + get->param.payload_size = size + sizeof(struct afe_port_param_data_v2); + get->param.module_id = mod_id; + get->param.param_id = param_id; + get->pdata.module_id = mod_id; + get->pdata.param_id = param_id; + get->pdata.param_size = size; + + this_afe.dsm_payload = payload; + + config = (uint32_t *)get; + } + else{ + set = (struct afe_dsm_set_command *) (payload - sizeof(*set)); + + memset(set, 0 , sizeof(*set)); + + set->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + set->hdr.pkt_size = size + sizeof(*set); + set->hdr.token = index; + set->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2; + set->param.port_id = q6audio_get_port_id(dst_port); + set->param.payload_size = size + sizeof(struct afe_port_param_data_v2); + set->pdata.module_id = mod_id; + set->pdata.param_id = param_id; + set->pdata.param_size = size; + + config = (uint32_t *)set; + } + + atomic_set(&this_afe.state, 1); + atomic_set(&this_afe.status, 0); + ret = apr_send_pkt(this_afe.apr, config); + if (ret < 0) { + pr_err("%s: port = 0x%x failed %d\n", __func__, dst_port, ret); + goto fail_cmd; + } + ret = wait_event_timeout(this_afe.wait[index], + (atomic_read(&this_afe.state) == 0), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + pr_err("%s: wait_event timeout\n", __func__); + ret = -EINVAL; + goto fail_cmd; + } + if (atomic_read(&this_afe.status) > 0) { + pr_err("%s: config cmd failed [%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&this_afe.status))); + ret = adsp_err_get_lnx_err_code( + atomic_read(&this_afe.status)); + goto fail_cmd; + } + + ret = 0; + +fail_cmd: + pr_debug("%s: status %d 0x%x\n", __func__, ret, dst_port); + + this_afe.dsm_payload = NULL; + + return ret; +} + +int afe_dsm_ramp_dn_cfg(uint8_t *payload, int delay_in_ms) +{ + uint32_t *params = (uint32_t *)payload; + *(params) = 0; + *(params + 1) = 3; + *(params + 2) = 0x03000063; + *(params + 3) = 5; + *(params + 4) = 0x03000064; + *(params + 5) = 300; + *(params + 6) = 0x03000066; + *(params + 7) = 1; + + afe_dsm_setget_params(payload, 8*sizeof(uint32_t), 0, DSM_RX_PORT_ID, AFE_MODULE_DSM_RX, AFE_PARAM_ID_DSM_CFG); + + usleep_range(delay_in_ms*1000, delay_in_ms*1000 + 10); + return 0; +} + +int afe_dsm_rx_set_params(uint8_t *payload, int size) +{ + return afe_dsm_setget_params(payload, size, 0, DSM_RX_PORT_ID, AFE_MODULE_DSM_RX, AFE_PARAM_ID_DSM_CFG); +} + +int afe_dsm_rx_get_params(uint8_t *payload, int size) +{ + return afe_dsm_setget_params(payload, size, 1, DSM_RX_PORT_ID, AFE_MODULE_DSM_RX, AFE_PARAM_ID_DSM_CFG); +} + +int afe_dsm_set_calib(uint8_t *payload) +{ + return afe_dsm_setget_params(payload, sizeof(uint32_t)*3, 0, DSM_TX_PORT_ID, AFE_MODULE_DSM_TX, AFE_PARAM_ID_CALIB); +} + +int afe_dsm_pre_calib(uint8_t *payload) +{ + uint32_t *params = (uint32_t *)payload; + *(params) = 0; + *(params + 1) = 1; + *(params + 2) = 0x03000001; + *(params + 3) = 4; + afe_dsm_setget_params(payload, 4*sizeof(uint32_t), 0, DSM_RX_PORT_ID, AFE_MODULE_DSM_RX, AFE_PARAM_ID_DSM_CFG); + usleep_range(1000*1000, 1000*1000 + 10); + return 0; +} + +int afe_dsm_post_calib(uint8_t *payload) +{ + uint32_t *params = (uint32_t *)payload; + *(params) = 0; + *(params + 1) = 1; + *(params + 2) = 0x03000001; + *(params + 3) = 1; + return afe_dsm_setget_params(payload, 4*sizeof(uint32_t), 0, DSM_RX_PORT_ID, AFE_MODULE_DSM_RX, AFE_PARAM_ID_DSM_CFG); +} + +int afe_dsm_get_calib(uint8_t *payload){ + return afe_dsm_setget_params(payload, sizeof(uint32_t)*14, 1, DSM_TX_PORT_ID, AFE_MODULE_DSM_TX, AFE_PARAM_ID_CALIB); +} + +int afe_dsm_get_average_calib(uint8_t *payload) +{ + uint32_t *params = (uint32_t *)payload; + uint64_t sum_rdc[2] = {0, 0}; + int i, rc = 0; + for (i = 0; i < 4; i++){ + rc = afe_dsm_setget_params(payload, sizeof(uint32_t)*14, 1, DSM_TX_PORT_ID, AFE_MODULE_DSM_TX, AFE_PARAM_ID_CALIB); + if (rc != 0){ + sum_rdc[0] = 0; + sum_rdc[1] = 0; + goto failed; + } + sum_rdc[0] += params[0]; + sum_rdc[1] += params[1]; + usleep_range(50*1000, 50*1000 + 10); + } + +failed: + params[0] = (sum_rdc[0] >> 2); + params[1] = (sum_rdc[1] >> 2); + return rc; +} + +int afe_dsm_get_libary_info(uint32_t *payload, int size) +{ + return afe_dsm_setget_params((int8_t*)payload, 4*100, 1, DSM_TX_PORT_ID, AFE_MODULE_DSM_TX, AFE_PARAM_ID_DSM_INFO); +} + +#endif + static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id, union afe_spkr_prot_config *prot_config) { diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 035c6bc500532..472866bde9ada 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * Author: Brian Swetland * * This software is licensed under the terms of the GNU General Public @@ -2512,13 +2513,14 @@ EXPORT_SYMBOL(q6asm_open_read_v3); * @ac: Client session handle * @format: encoder format * @bits_per_sample: bit width of capture session + * @ts_mode: timestamp mode */ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, - uint16_t bits_per_sample) + uint16_t bits_per_sample, bool ts_mode) { return __q6asm_open_read(ac, format, bits_per_sample, PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/, - true/*ts_mode*/); + ts_mode); } EXPORT_SYMBOL(q6asm_open_read_v4); diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index 8292f474a3574..f3657916cd913 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (C) 2019 XiaoMi, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -48,6 +49,7 @@ struct cvd_version_table cvd_version_table_mapping[CVD_INT_VERSION_MAX] = { {CVD_VERSION_0_0, CVD_INT_VERSION_0_0}, {CVD_VERSION_2_1, CVD_INT_VERSION_2_1}, {CVD_VERSION_2_2, CVD_INT_VERSION_2_2}, + {CVD_VERSION_2_3, CVD_INT_VERSION_2_3}, }; static struct common_data common; @@ -5713,7 +5715,7 @@ int voc_set_rx_vol_step(uint32_t session_id, uint32_t dir, uint32_t vol_step, int ret = 0; struct voice_session_itr itr; - pr_debug("%s session id = %#x vol = %u", __func__, session_id, + printk("%s session id = %#x vol = %u", __func__, session_id, vol_step); voice_itr_init(&itr, session_id); @@ -5726,7 +5728,7 @@ int voc_set_rx_vol_step(uint32_t session_id, uint32_t dir, uint32_t vol_step, ret = voice_send_vol_step_cmd(v); mutex_unlock(&v->lock); } else { - pr_err("%s: invalid session_id 0x%x\n", __func__, + printk("%s: invalid session_id 0x%x\n", __func__, session_id); ret = -EINVAL; diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index a4c3a4be19ee5..71c0e80464ef0 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -42,12 +42,14 @@ #define CVD_VERSION_0_0 "0.0" #define CVD_VERSION_2_1 "2.1" #define CVD_VERSION_2_2 "2.2" +#define CVD_VERSION_2_3 "2.3" #define CVD_INT_VERSION_DEFAULT 0 #define CVD_INT_VERSION_0_0 1 #define CVD_INT_VERSION_2_1 2 #define CVD_INT_VERSION_2_2 3 -#define CVD_INT_VERSION_LAST CVD_INT_VERSION_2_2 +#define CVD_INT_VERSION_2_3 4 +#define CVD_INT_VERSION_LAST CVD_INT_VERSION_2_3 #define CVD_INT_VERSION_MAX (CVD_INT_VERSION_LAST + 1) struct cvd_version_table { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 60275bf339208..73f2f98a27dd0 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2990,17 +2990,23 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, struct snd_soc_dpcm *dpcm; int state; - list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) { - - if (dpcm->fe == fe) - continue; - - state = dpcm->fe->dpcm[stream].state; - if (state == SND_SOC_DPCM_STATE_START || - state == SND_SOC_DPCM_STATE_PAUSED || - state == SND_SOC_DPCM_STATE_SUSPEND) - return 0; - } + list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) { + + if (dpcm->fe == fe) + continue; + + state = dpcm->fe->dpcm[stream].state; + if (state == SND_SOC_DPCM_STATE_START || + state == SND_SOC_DPCM_STATE_PAUSED || + state == SND_SOC_DPCM_STATE_SUSPEND) + return 0; + + if (dpcm->fe->cpu_dai->playback_active){ + dev_info(dpcm->fe->dev, "ASoc: playback_active %d, cpu_dai->name %s\n", + dpcm->fe->cpu_dai->playback_active, dpcm->fe->cpu_dai->name); + return 0; + } + } /* it's safe to free/stop this BE DAI */ return 1;